(function (factory) {  /* global define */  if (typeof define === 'function' && define.amd) {    // AMD. Register as an anonymous module.    define(['jquery'], factory);  } else {    // Browser globals: jQuery    factory(window.jQuery);  }}(function ($) {  // template  var tmpl = $.summernote.renderer.getTemplate();  // core functions: range, dom  var range = $.summernote.core.range;  var dom = $.summernote.core.dom;  /**   * createVideoNode   *     * @member plugin.video   * @private   * @param {String} url   * @return {Node}   */  var createVideoNode = function (url) {    // video url patterns(youtube, instagram, vimeo, dailymotion, youku, mp4, ogg, webm)    // BUG: CWE-89 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')    // var ytRegExp = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;    // FIXED:     var ytRegExp = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-) {11})(?:\S+)?$/;    var ytMatch = url.match(ytRegExp);    var igRegExp = /\/\/instagram.com\/p\/(.[a-zA-Z0-9]*)/;    var igMatch = url.match(igRegExp);    var vRegExp = /\/\/vine.co\/v\/(.[a-zA-Z0-9]*)/;    var vMatch = url.match(vRegExp);    var vimRegExp = /\/\/(player.)?vimeo.com\/([a-z]*\/)*([0-9]{6,11})[?]?.*/;    var vimMatch = url.match(vimRegExp);    var dmRegExp = /.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/;    var dmMatch = url.match(dmRegExp);    var youkuRegExp = /\/\/v\.youku\.com\/v_show\/id_(\w+)=*\.html/;    var youkuMatch = url.match(youkuRegExp);    var mp4RegExp = /^.+.(mp4|m4v)$/;    var mp4Match = url.match(mp4RegExp);    var oggRegExp = /^.+.(ogg|ogv)$/;    var oggMatch = url.match(oggRegExp);    var webmRegExp = /^.+.(webm)$/;    var webmMatch = url.match(webmRegExp);    var $video;    if (ytMatch && ytMatch[1].length === 11) {      var youtubeId = ytMatch[1];      $video = $('<iframe>')        .attr('frameborder', 0)        .attr('src', '//www.youtube.com/embed/' + youtubeId)        .attr('width', '640').attr('height', '360');    } else if (igMatch && igMatch[0].length) {      $video = $('<iframe>')        .attr('frameborder', 0)        .attr('src', igMatch[0] + '/embed/')        .attr('width', '612').attr('height', '710')        .attr('scrolling', 'no')        .attr('allowtransparency', 'true');    } else if (vMatch && vMatch[0].length) {      $video = $('<iframe>')        .attr('frameborder', 0)        .attr('src', vMatch[0] + '/embed/simple')        .attr('width', '600').attr('height', '600')        .attr('class', 'vine-embed');    } else if (vimMatch && vimMatch[3].length) {      $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')        .attr('frameborder', 0)        .attr('src', '//player.vimeo.com/video/' + vimMatch[3])        .attr('width', '640').attr('height', '360');    } else if (dmMatch && dmMatch[2].length) {      $video = $('<iframe>')        .attr('frameborder', 0)        .attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2])        .attr('width', '640').attr('height', '360');    } else if (youkuMatch && youkuMatch[1].length) {      $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')        .attr('frameborder', 0)        .attr('height', '498')        .attr('width', '510')        .attr('src', '//player.youku.com/embed/' + youkuMatch[1]);    } else if (mp4Match || oggMatch || webmMatch) {      $video = $('<video controls>')        .attr('src', url)        .attr('width', '640').attr('height', '360');    } else {      // this is not a known video link. Now what, Cat? Now what?      return false;    }    return $video[0];  };  /**   * @member plugin.video   * @private   * @param {jQuery} $editable   * @return {String}   */  var getTextOnRange = function ($editable) {    $editable.focus();    var rng = range.create();    // if range on anchor, expand range with anchor    if (rng.isOnAnchor()) {      var anchor = dom.ancestor(rng.sc, dom.isAnchor);      rng = range.createFromNode(anchor);    }    return rng.toString();  };  /**   * toggle button status   *     * @member plugin.video   * @private   * @param {jQuery} $btn   * @param {Boolean} isEnable   */  var toggleBtn = function ($btn, isEnable) {    $btn.toggleClass('disabled', !isEnable);    $btn.attr('disabled', !isEnable);  };  /**   * Show video dialog and set event handlers on dialog controls.   *   * @member plugin.video   * @private   * @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).on('input', function () {          toggleBtn($videoBtn, $videoUrl.val());        }).trigger('focus');        $videoBtn.click(function (event) {          event.preventDefault();          deferred.resolve($videoUrl.val());          $videoDialog.modal('hide');        });      }).one('hidden.bs.modal', function () {        $videoUrl.off('input');        $videoBtn.off('click');        if (deferred.state() === 'pending') {          deferred.reject();        }      }).modal('show');    });  };  /**   * @class plugin.video   *   * Video Plugin   *   * video plugin is to make embeded video tag.   *   * ### load script   *   * ```   * < script src="plugin/summernote-ext-video.js"></script >   * ```   *   * ### use a plugin in toolbar   * ```   *    $("#editor").summernote({   *    ...   *    toolbar : [   *        ['group', [ 'video' ]]   *    ]   *    ...       *    });   * ```   */  $.summernote.addPlugin({    /** @property {String} name name of plugin */    name: 'video',    /**     * @property {Object} buttons     * @property {function(object): string} buttons.video     */    buttons: {      video: function (lang, options) {        return tmpl.iconButton(options.iconPrefix + 'youtube-play', {          event: 'showVideoDialog',          title: lang.video.video,          hide: true        });      }    },    /**     * @property {Object} dialogs     * @property {function(object, object): string} dialogs.video    */    dialogs: {      video: function (lang) {        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);      }    },    /**     * @property {Object} events     * @property {Function} events.showVideoDialog     */    events: {      showVideoDialog: function (event, editor, 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);                    // build node          var $node = createVideoNode(url);                    if ($node) {            // insert video node            editor.insertNode($editable, $node);          }        }).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)'        }      },      'ar-AR': {        video: {          video: 'فيديو',          videoLink: 'رابط الفيديو',          insert: 'إدراج الفيديو',          url: 'رابط الفيديو',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion ou Youku)'        }      },      'ca-ES': {        video: {          video: 'Video',          videoLink: 'Enllaç del video',          insert: 'Inserir video',          url: 'URL del video?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, o Youku)'        }      },      'cs-CZ': {        video: {          video: 'Video',          videoLink: 'Odkaz videa',          insert: 'Vložit video',          url: 'URL videa?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion nebo Youku)'        }      },      'da-DK': {        video: {          video: 'Video',          videoLink: 'Video Link',          insert: 'Indsæt Video',          url: 'Video URL?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion eller Youku)'        }      },      'de-DE': {        video: {          video: 'Video',          videoLink: 'Video Link',          insert: 'Video einfügen',          url: 'Video URL?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, oder Youku)'        }      },      'es-ES': {        video: {          video: 'Video',          videoLink: 'Link del video',          insert: 'Insertar video',          url: '¿URL del video?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, o Youku)'        }      },      'es-EU': {        video: {          video: 'Bideoa',          videoLink: 'Bideorako esteka',          insert: 'Bideo berri bat txertatu',          url: 'Bideoaren URL helbidea',          providers: '(YouTube, Vimeo, Vine, Instagram, edo DailyMotion)'        }      },      'fa-IR': {        video: {          video: 'ویدیو',          videoLink: 'لینک ویدیو',          insert: 'افزودن ویدیو',          url: 'آدرس ویدیو ؟',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, یا Youku)'        }      },      'fi-FI': {        video: {          video: 'Video',          videoLink: 'Linkki videoon',          insert: 'Lisää video',          url: 'Videon URL-osoite?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion tai Youku)'        }      },      'fr-FR': {        video: {          video: 'Vidéo',          videoLink: 'Lien vidéo',          insert: 'Insérer une vidéo',          url: 'URL de la vidéo',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion ou Youku)'        }      },      'he-IL': {        video: {          video: 'סרטון',          videoLink: 'קישור לסרטון',          insert: 'הוסף סרטון',          url: 'קישור לסרטון',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion או Youku)'        }      },      'hu-HU': {        video: {          video: 'Videó',          videoLink: 'Videó hivatkozás',          insert: 'Videó beszúrása',          url: 'Videó URL címe',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, vagy Youku)'        }      },      'id-ID': {        video: {          video: 'Video',          videoLink: 'Link video',          insert: 'Sisipkan video',          url: 'Tautan video',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, atau Youku)'        }      },      'it-IT': {        video: {          video: 'Video',          videoLink: 'Collegamento ad un Video',          insert: 'Inserisci Video',          url: 'URL del Video',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion o Youku)'        }      },      'ja-JP': {        video: {          video: '動画',          videoLink: '動画リンク',          insert: '動画挿入',          url: '動画のURL',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, Youku)'        }      },      'ko-KR': {        video: {          video: '동영상',          videoLink: '동영상 링크',          insert: '동영상 추가',          url: '동영상 URL',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, Youku 사용 가능)'        }      },      'nb-NO': {        video: {          video: 'Video',          videoLink: 'Videolenke',          insert: 'Sett inn video',          url: 'Video-URL',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion eller Youku)'        }      },      'nl-NL': {        video: {          video: 'Video',          videoLink: 'Video link',          insert: 'Video invoegen',          url: 'URL van de video',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion of Youku)'        }      },      'pl-PL': {        video: {          video: 'Wideo',          videoLink: 'Adres wideo',          insert: 'Wstaw wideo',          url: 'Adres wideo',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, lub Youku)'        }      },      'pt-BR': {        video: {          video: 'Vídeo',          videoLink: 'Link para vídeo',          insert: 'Inserir vídeo',          url: 'URL do vídeo?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, ou Youku)'        }      },      'ro-RO': {        video: {          video: 'Video',          videoLink: 'Link video',          insert: 'Inserează video',          url: 'URL video?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, sau Youku)'        }      },      'ru-RU': {        video: {          video: 'Видео',          videoLink: 'Ссылка на видео',          insert: 'Вставить видео',          url: 'URL видео',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion или Youku)'        }      },      'sk-SK': {        video: {          video: 'Video',          videoLink: 'Odkaz videa',          insert: 'Vložiť video',          url: 'URL videa?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion nebo Youku)'        }      },      'sl-SI': {        video: {          video: 'Video',          videoLink: 'Video povezava',          insert: 'Vstavi video',          url: 'Povezava do videa',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion ali Youku)'        }      },      'sr-RS': {        video: {          video: 'Видео',          videoLink: 'Веза ка видеу',          insert: 'Уметни видео',          url: 'URL видео',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion или Youku)'        }      },      'sr-RS-Latin': {        video: {          video: 'Video',          videoLink: 'Veza ka videu',          insert: 'Umetni video',          url: 'URL video',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion ili Youku)'        }      },      'sv-SE': {        video: {          video: 'Filmklipp',          videoLink: 'Länk till filmklipp',          insert: 'Infoga filmklipp',          url: 'Länk till filmklipp',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion eller Youku)'        }      },      'th-TH': {        video: {          video: 'วีดีโอ',          videoLink: 'ลิงก์ของวีดีโอ',          insert: 'แทรกวีดีโอ',          url: 'ที่อยู่ URL ของวีดีโอ?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion หรือ Youku)'        }      },      'tr-TR': {        video: {          video: 'Video',          videoLink: 'Video bağlantısı',          insert: 'Video ekle',          url: 'Video bağlantısı?',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion veya Youku)'        }      },      'uk-UA': {        video: {          video: 'Відео',          videoLink: 'Посилання на відео',          insert: 'Вставити відео',          url: 'URL відео',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion чи Youku)'        }      },      'vi-VN': {        video: {          video: 'Video',          videoLink: 'Đường Dẫn đến Video',          insert: 'Chèn Video',          url: 'URL',          providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion và Youku)'        }      },      'zh-CN': {        video: {          video: '视频',          videoLink: '视频链接',          insert: '插入视频',          url: '视频地址',          providers: '(优酷, Instagram, DailyMotion, Youtube等)'        }      },      'zh-TW': {        video: {          video: '影片',          videoLink: '影片連結',          insert: '插入影片',          url: '影片網址',          providers: '(優酷, Instagram, DailyMotion, Youtube等)'        }      }    }  });}));