Redesign plugin interface and extract video plugin from base code.

Redesign plugin interface base on #662.

ex) video plugin...

```javascript
(function ($) {
  // template, editor, range, dom
  var tmpl = $.summernote.renderer.getTemplate();
  var editor = $.summernote.eventHandler.getEditor();
  var range = $.summernote.core.range;
  var dom = $.summernote.core.dom;

  var createVideoNode = function (url) {
      // ...
      return $video[0];
  };

  var getTextOnRange = function ($editable) {
    //..
    return rng.toString();
  };

  /**
   * Show video dialog and set event handlers on dialog controls.
   *
   * @param {jQuery} $dialog 
   * @param {jQuery} $dialog
   * @param {Object} text
   * @return {Promise}
   */
  var showVideoDialog = function ($editable, $dialog, text) {
    return $.Deferred(function (deferred) {
      var $videoDialog = $dialog.find('.note-video-dialog');
    
      var $videoUrl = $videoDialog.find('.note-video-url'),
          $videoBtn = $videoDialog.find('.note-video-btn');
    
      $videoDialog.one('shown.bs.modal', function () {
        $videoUrl.val(text).keyup(function () {
          toggleBtn($videoBtn, $videoUrl.val());
        }).trigger('keyup').trigger('focus');

        $videoBtn.click(function (event) {
          event.preventDefault();

          deferred.resolve($videoUrl.val());
          $videoDialog.modal('hide');
        });
      }).one('hidden.bs.modal', function () {
        $videoUrl.off('keyup');
        $videoBtn.off('click');

        if (deferred.state() === 'pending') {
          deferred.reject();
        }
      }).modal('show');
    });
  };

  // add video plugin
  $.summernote.addPlugin({
    name: 'video',

    // define buttons
    buttons: {
      /**
       * @param {Object} lang
       * @param {Object} options
       * @return {String}
       */
      video: function (lang, options) {
        return tmpl.iconButton('fa fa-youtube-play', {
          event: 'showVideoDialog',
          title: lang.video.video,
          hide: true
        });
      }
    },

    // define dialogs
    dialogs: {
      /**
       * @param {Object} lang
       * @param {Object} options
       * @return {String}
       */
      video: function (lang, options) {
        var body = '<div class="form-group row-fluid">' +
                     '<label>' + lang.video.url + ' <small class="text-muted">' + lang.video.providers + '</small></label>' +
                     '<input class="note-video-url form-control span12" type="text" />' +
                   '</div>';
        var footer = '<button href="#" class="btn btn-primary note-video-btn disabled" disabled>' + lang.video.insert + '</button>';
        return tmpl.dialog('note-video-dialog', lang.video.insert, body, footer);
      }
    },

    // define events
    events: {
      /**
       * @param {Object} layoutInfo
       */
      showVideoDialog: function (layoutInfo) {
        var $dialog = layoutInfo.dialog(),
            $editable = layoutInfo.editable(),
            text = getTextOnRange($editable);

        // save current range
        editor.saveRange($editable)

        showVideoDialog($editable, $dialog, text).then(function (url) {
          // when ok button clicked

          // restore range
          editor.restoreRange($editable);

          // insert video node
          editor.insertNode($editable, createVideoNode(url));
        }).fail(function () {
          // when cancel button clicked
          editor.restoreRange($editable);
        });
      }
    },

    // define language
    langs: {
      'en-US': {
        video: {
          video: 'Video',
          videoLink: 'Video Link',
          insert: 'Insert Video',
          url: 'Video URL?',
          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)'
        }
      }
    }
  });
})(jQuery);
```
하나의 플러그인에 자신만의 버튼이 여러개 들어갈 수 있겠네요. 사용은 각자 알아서 하겠죠?  전 플러그인 하나에 버튼 하나로만 생각했는데. 여러개 들어가도 좋겠네요. ^^