Javascript 如何在Summernote中插入占位符元素?

Javascript 如何在Summernote中插入占位符元素?,javascript,jquery,iframe,summernote,Javascript,Jquery,Iframe,Summernote,我正在为Summernote WYSIWYG编辑器(版本0.8.1)开发一个插件,将iframe元素插入到代码中 使用提供的示例,我成功地获得了菜单中的插件按钮,它打开了一个对话框,我可以在其中输入URL和标题。向源代码添加iframe标记没有问题,但这不是我想要的 我想在代码中插入一个占位符,其标记如下(或类似): iframe URL:http://www.test.example 现在,summernote允许我编辑跨度的内容,但我希望有一个占位符,它不能在编辑器中修改 如何在编辑器中插

我正在为Summernote WYSIWYG编辑器(版本0.8.1)开发一个插件,将iframe元素插入到代码中

使用提供的示例,我成功地获得了菜单中的插件按钮,它打开了一个对话框,我可以在其中输入URL和标题。向源代码添加iframe标记没有问题,但这不是我想要的

我想在代码中插入一个占位符,其标记如下(或类似):

iframe URL:http://www.test.example
现在,summernote允许我编辑跨度的内容,但我希望有一个占位符,它不能在编辑器中修改

如何在编辑器中插入具有以下属性的占位符:

  • 可作为单个块进行编辑(可通过单个删除进行删除)
  • 点击后,我可以打开一个类似链接或图像的弹出框,以调整大小f.I
  • 内部内容不可修改
这就是我到目前为止所做的:

// Extends plugins for adding iframes.
//  - plugin is external module for customizing.
$.extend($.summernote.plugins, {
  /**
   * @param {Object} context - context object has status of editor.
   */
  'iframe': function (context) {
    var self = this;

    // ui has renders to build ui elements.
    //  - you can create a button with `ui.button`
    var ui = $.summernote.ui;

    var $editor = context.layoutInfo.editor;
    var options = context.options;
    var lang = options.langInfo;

    // add context menu button
    context.memo('button.iframe', function () {
      return ui.button({
        contents: '<i class="fa fa-newspaper-o"/>',
        tooltip: lang.iframe.iframe,
        click: context.createInvokeHandler('iframe.show')
      }).render();
    });


    // This events will be attached when editor is initialized.
    this.events = {
      // This will be called after modules are initialized.
      'summernote.init': function (we, e) {
        console.log('IFRAME initialized', we, e);
      },
      // This will be called when user releases a key on editable.
      'summernote.keyup': function (we, e) {
        console.log('IFRAME keyup', we, e);
      }
    };

    // This method will be called when editor is initialized by $('..').summernote();
    // You can create elements for plugin
    this.initialize = function () {
      var $container = options.dialogsInBody ? $(document.body) : $editor;

      var body = '<div class="form-group row-fluid">' +
          '<label>' + lang.iframe.url + '</label>' +
          '<input class="ext-iframe-url form-control" type="text" />' +
          '<label>' + lang.iframe.title + '</label>' +
          '<input class="ext-iframe-title form-control" type="text" />' +
          '<label>' + lang.iframe.alt + '</label>' +
          '<textarea class="ext-iframe-alt form-control" placeholder="' + lang.iframe.alttext + '" rows=""10""></textarea>' +
          '</div>';
      var footer = '<button href="#" class="btn btn-primary ext-iframe-btn disabled" disabled>' + lang.iframe.insert + '</button>';

      this.$dialog = ui.dialog({
        title: lang.iframe.insert,
        fade: options.dialogsFade,
        body: body,
        footer: footer
      }).render().appendTo($container);
    };

    // This methods will be called when editor is destroyed by $('..').summernote('destroy');
    // You should remove elements on `initialize`.
    this.destroy = function () {
      this.$dialog.remove();
      this.$dialog = null;
    };


    this.bindEnterKey = function ($input, $btn) {
      $input.on('keypress', function (event) {
        if (event.keyCode === 13) { //key.code.ENTER) {
          $btn.trigger('click');
        }
      });
    };



    this.createIframeNode = function (data) {
      var $iframeSubst = $('<div class="ext-iframe-subst"><span>' + lang.iframe.iframe + '</span></div>');

      $iframeSubst.attr("data-src", data.url).attr("data-title", data.title);

      return $iframeSubst[0];
    };


    this.show = function () {
      var text = context.invoke('editor.getSelectedText');
      context.invoke('editor.saveRange');

      console.log("iframe.getInfo: " + text);

      this
        .showIframeDialog(text)
        .then(function (data) {
          // [workaround] hide dialog before restore range for IE range focus
          ui.hideDialog(self.$dialog);
          context.invoke('editor.restoreRange');

          // build node
          var $node = self.createIframeNode(data);

          if ($node) {
            // insert iframe node
            context.invoke('editor.insertNode', $node);
          }
        })
        .fail(function () {
          context.invoke('editor.restoreRange');
        });

    };

    this.showIframeDialog = function (text) {
      return $.Deferred(function (deferred) {
        var $iframeUrl = self.$dialog.find('.ext-iframe-url');
        var $iframeTitle = self.$dialog.find('.ext-iframe-title');
        var $iframeBtn = self.$dialog.find('.ext-iframe-btn');

        ui.onDialogShown(self.$dialog, function () {
          context.triggerEvent('dialog.shown');

          $iframeUrl.val(text).on('input', function () {
            ui.toggleBtn($iframeBtn, $iframeUrl.val());
          }).trigger('focus');

          $iframeBtn.click(function (event) {
            event.preventDefault();

            deferred.resolve({ url: $iframeUrl.val(), title: $iframeTitle.val() });
          });

          self.bindEnterKey($iframeUrl, $iframeBtn);
        });

        ui.onDialogHidden(self.$dialog, function () {
          $iframeUrl.off('input');
          $iframeBtn.off('click');

          if (deferred.state() === 'pending') {
            deferred.reject();
          }
        });

        ui.showDialog(self.$dialog);
      });
    };


  }
});

// add localization texts
$.extend($.summernote.lang['en-US'], {
    iframe: {
      iframe: 'iframe',
      url: 'iframe URL',
      title: 'title',
      insert: 'insert iframe',
      alt: 'Text alternative',
      alttext: 'you should provide a text alternative for the content in this iframe.',
      test: 'Test'
    }
});
//扩展插件以添加iframe。
//-插件是用于定制的外部模块。
$.extend($.summernote.plugins{
/**
*@param{Object}context-context对象的状态为编辑器。
*/
“iframe”:函数(上下文){
var self=这个;
//ui具有用于构建ui元素的呈现。
//-您可以使用“ui.button”创建按钮`
var ui=$.summernote.ui;
var$editor=context.layoutInfo.editor;
var options=context.options;
var lang=options.langInfo;
//添加上下文菜单按钮
context.memo('button.iframe',function(){
返回用户界面按钮({
内容:'',
工具提示:lang.iframe.iframe,
单击:context.createInvokeHandler('iframe.show')
}).render();
});
//此事件将在编辑器初始化时附加。
此项。事件={
//这将在模块初始化后调用。
'summernote.init':函数(we,e){
log('IFRAME initialized',we,e);
},
//当用户在“可编辑”按钮上释放键时,将调用此选项。
“summernote.keyup”:函数(we,e){
log('IFRAME keyup',we,e);
}
};
//当编辑器由$('..').summernote()初始化时,将调用此方法;
//您可以为插件创建元素
this.initialize=函数(){
var$container=options.dialogsInBody?$(document.body):$editor;
变量体=“”+
“+lang.iframe.url+”+
'' +
“+lang.iframe.title+”+
'' +
“+lang.iframe.alt+”+
'' +
'';
var footer=''+lang.iframe.insert+'';
这个.$dialog=ui.dialog({
标题:lang.iframe.insert,
淡入淡出:options.dialogsFade,
身体:身体,,
页脚:页脚
}).render().appendTo($container);
};
//当编辑器被$('..')销毁时,将调用此方法;
//您应该删除“initialize”上的元素。
this.destroy=函数(){
这是.dialog.remove();
此参数为.$dialog=null;
};
this.bindEnterKey=函数($input,$btn){
$input.on('keypress',函数(事件){
if(event.keyCode==13){//key.code.ENTER){
$btn.trigger('click');
}
});
};
this.createIframeNode=函数(数据){
变量$iframeSubst=$(''+lang.iframe.iframe+'');
$iframeSubst.attr(“数据src”,data.url).attr(“数据标题”,data.title);
返回$iframeSubst[0];
};
this.show=函数(){
var text=context.invoke('editor.getSelectedText');
invoke('editor.saverage');
log(“iframe.getInfo:+text”);
这
.showiframe对话框(文本)
.then(功能(数据){
//[解决方法]在恢复IE范围焦点的范围之前隐藏对话框
ui.hideDialog(self.$dialog);
invoke('editor.restorerage');
//构建节点
var$node=self.createIframeNode(数据);
如果($node){
//插入iframe节点
invoke('editor.insertNode',$node);
}
})
.fail(函数(){
invoke('editor.restorerage');
});
};
this.showIframeDialog=函数(文本){
return$.Deferred(函数(Deferred)){
var$iframeUrl=self.$dialog.find('.ext-iframeUrl');
变量$iframetTitle=self.$dialog.find('.ext-iframetTitle');
var$iframeBtn=self.$dialog.find('.ext-iframeBtn');
显示ui.ondialog(self.$对话框,函数(){
triggerEvent('dialog.show');
$iframeUrl.val(text).on('input',function(){
toggleBtn($iframeBtn,$iframeUrl.val());
}).触发(“焦点”);
$iframeBtn.单击(函数(事件){
event.preventDefault();
resolve({url:$iframeUrl.val(),title:$iframetTitle.val()});
});
bindEnterKey($iframeUrl,$iframeBtn);
});
ui.onDialogHidden(self.$dialog,函数(){
$iframeUrl.off('input');
$iframeBtn.off('click');
if(deferred.state()=='pending'){
拒绝();
}
});
ui.showDialog(self.$dialog);
});
};
}
});
//添加本地化文本
$.extend($.summernote.lang['en-US']{
iframe:{
iframe:“iframe”,
url:“iframe url”,
标题:“标题”,
插入:“插入iframe”,
alt:'文本替换',
alttext:“您应该为此iframe中的内容提供一个文本备选方案。”,
测试:“测试”
}
});

尝试使用

$(文档).ready(函数(){
$('#summernote')。summernote({
占位符:“你好,独立用户界面”,
tabsize:2,
身高:120
});
});

您可以在
span
元素和i上使用属性
// Extends plugins for adding iframes.
//  - plugin is external module for customizing.
$.extend($.summernote.plugins, {
  /**
   * @param {Object} context - context object has status of editor.
   */
  'iframe': function (context) {
    var self = this;

    // ui has renders to build ui elements.
    //  - you can create a button with `ui.button`
    var ui = $.summernote.ui;

    var $editor = context.layoutInfo.editor;
    var options = context.options;
    var lang = options.langInfo;

    // add context menu button
    context.memo('button.iframe', function () {
      return ui.button({
        contents: '<i class="fa fa-newspaper-o"/>',
        tooltip: lang.iframe.iframe,
        click: context.createInvokeHandler('iframe.show')
      }).render();
    });


    // This events will be attached when editor is initialized.
    this.events = {
      // This will be called after modules are initialized.
      'summernote.init': function (we, e) {
        console.log('IFRAME initialized', we, e);
      },
      // This will be called when user releases a key on editable.
      'summernote.keyup': function (we, e) {
        console.log('IFRAME keyup', we, e);
      }
    };

    // This method will be called when editor is initialized by $('..').summernote();
    // You can create elements for plugin
    this.initialize = function () {
      var $container = options.dialogsInBody ? $(document.body) : $editor;

      var body = '<div class="form-group row-fluid">' +
          '<label>' + lang.iframe.url + '</label>' +
          '<input class="ext-iframe-url form-control" type="text" />' +
          '<label>' + lang.iframe.title + '</label>' +
          '<input class="ext-iframe-title form-control" type="text" />' +
          '<label>' + lang.iframe.alt + '</label>' +
          '<textarea class="ext-iframe-alt form-control" placeholder="' + lang.iframe.alttext + '" rows=""10""></textarea>' +
          '</div>';
      var footer = '<button href="#" class="btn btn-primary ext-iframe-btn disabled" disabled>' + lang.iframe.insert + '</button>';

      this.$dialog = ui.dialog({
        title: lang.iframe.insert,
        fade: options.dialogsFade,
        body: body,
        footer: footer
      }).render().appendTo($container);
    };

    // This methods will be called when editor is destroyed by $('..').summernote('destroy');
    // You should remove elements on `initialize`.
    this.destroy = function () {
      this.$dialog.remove();
      this.$dialog = null;
    };


    this.bindEnterKey = function ($input, $btn) {
      $input.on('keypress', function (event) {
        if (event.keyCode === 13) { //key.code.ENTER) {
          $btn.trigger('click');
        }
      });
    };



    this.createIframeNode = function (data) {
      var $iframeSubst = $('<div class="ext-iframe-subst"><span>' + lang.iframe.iframe + '</span></div>');

      $iframeSubst.attr("data-src", data.url).attr("data-title", data.title);

      return $iframeSubst[0];
    };


    this.show = function () {
      var text = context.invoke('editor.getSelectedText');
      context.invoke('editor.saveRange');

      console.log("iframe.getInfo: " + text);

      this
        .showIframeDialog(text)
        .then(function (data) {
          // [workaround] hide dialog before restore range for IE range focus
          ui.hideDialog(self.$dialog);
          context.invoke('editor.restoreRange');

          // build node
          var $node = self.createIframeNode(data);

          if ($node) {
            // insert iframe node
            context.invoke('editor.insertNode', $node);
          }
        })
        .fail(function () {
          context.invoke('editor.restoreRange');
        });

    };

    this.showIframeDialog = function (text) {
      return $.Deferred(function (deferred) {
        var $iframeUrl = self.$dialog.find('.ext-iframe-url');
        var $iframeTitle = self.$dialog.find('.ext-iframe-title');
        var $iframeBtn = self.$dialog.find('.ext-iframe-btn');

        ui.onDialogShown(self.$dialog, function () {
          context.triggerEvent('dialog.shown');

          $iframeUrl.val(text).on('input', function () {
            ui.toggleBtn($iframeBtn, $iframeUrl.val());
          }).trigger('focus');

          $iframeBtn.click(function (event) {
            event.preventDefault();

            deferred.resolve({ url: $iframeUrl.val(), title: $iframeTitle.val() });
          });

          self.bindEnterKey($iframeUrl, $iframeBtn);
        });

        ui.onDialogHidden(self.$dialog, function () {
          $iframeUrl.off('input');
          $iframeBtn.off('click');

          if (deferred.state() === 'pending') {
            deferred.reject();
          }
        });

        ui.showDialog(self.$dialog);
      });
    };


  }
});

// add localization texts
$.extend($.summernote.lang['en-US'], {
    iframe: {
      iframe: 'iframe',
      url: 'iframe URL',
      title: 'title',
      insert: 'insert iframe',
      alt: 'Text alternative',
      alttext: 'you should provide a text alternative for the content in this iframe.',
      test: 'Test'
    }
});