6

我的一些观点需要将它们的文本区域转换为富文本编辑器。

我使用 jwysiwyg 作为编辑器。它要求它所附加的元素在编辑器初始化时位于页面中,即当我调用 $(this.el).wysiwyg() 时,this.el 已经在文档中。

我的大多数视图实际上并没有附加到 dom - 他们的渲染方法只是使用应用程序模板引擎设置他们的元素 html 内容,例如 $(this.el).html(this.template(content)

在将这些子视图实际插入页面后,视图/控制器会进一步向上查看。同时,视图会在模型更改时重新渲染自己。

如何确保每次渲染时都将编辑器附加到元素,并且仍然确保在元素已经在页面中之前不附加编辑器?

显然,我可以一起破解一些适用于这种特殊情况的东西,但我想要一个适用于所有情况的优雅解决方案。

任何帮助将非常感激。

编辑:这里的要点是解决方案必须优雅地扩展以覆盖渲染后必须设置样式的多个元素,并且在它们位于 DOM 中之前不得设置样式

编辑:如果我进行自上而下渲染,这不是问题,但这很慢,我想要一个解决方案,我可以从下向上渲染,然后在顶部一次性插入完整视图

编辑:

结合使用下面建议的一些技术,我正在考虑执行以下操作。任何评论/批评将不胜感激。

app/views/base_view.js:

initialize: function() {
  // wrap the render function to trigger 'render' events
  this.render = _.wrap(this.render, function() {
    this.trigger('render')
  });

  // bind this view to 'attach' events. 
  // 'attach' events must be triggered manually on any view being inserted into the dom
  this.bind('attach', function() {
    this.attached();
    // the refreshed event is only attached to the render event after the view has been attached
    this.bind('render', this.refreshed())
    // each view must keep a record of its child views and propagate the 'attach' events
    _.each(this.childViews, function(view) {
      view.trigger('attach')
    })
  })
}

// called when the view is first inserted to the dom
attached: function() {
  this.style();
}

// called if the view renders after it has been inserted
refreshed: function() {
  this.style();
}

style: function() {
  // default styling here, override or extend for custom
}
4

4 回答 4

1

如果您使用JQuery LiveQuery 插件来附加编辑器会怎样?此类代码可能是您模板代码的一部分,但不是 HTML,而是与模板关联的 Javascript。或者您可以全局添加它。代码可能如下所示(假设您已包含插件本身):

$('textarea.wysiwyg').livequery(function() {
   $(this).wysiwyg();
});

我没有测试过这段代码,但理论上它应该匹配一个 textarea 元素的实例,当它出现在 DOM 中时,它应该具有一个“所见即所得”的类,并调用所见即所得函数来应用编辑器。

于 2011-06-19T19:03:08.053 回答
1

为了遵守 DRY 原则并获得一个优雅的解决方案,您需要一个专用于确定 textarea 是否具有所见即所得的功能,假设wysiwygAdder并在必要时添加它。然后你可以使用下划线的wrap函数将你所见即所得的加法器附加到渲染函数的末尾。

var View = Backbone.View.extend({
    el: '#somewhere',

    initialize: function(){
        _.bind(this, "render");
        this.render = _.wrap(this.render, wysiwygAdder);
    },

    render: function(){
        //Do your regular templating
        return this;//allows wysiwygAdder to pick up context
    }
});

function wysiwygAdder(context){
    $('textarea', context).doYourStuff();
    //check for presence of WYSIWYG, add here
}

初始化视图时,它会用您的渲染函数覆盖您的渲染函数,然后是所见即所得的Adder。确保return this;从渲染中提供上下文。

于 2011-06-16T02:42:16.110 回答
0

大问题要解决!不太确定我已经掌握了整个 jist,但是......你可能能够逃脱左侧的“construction_yard”(我刚刚提出这个术语),在那里建造和放置物品,然后移动当它们准备好放置时。类似于以下内容:

.construction_yard {
    position: absolute;
    left: -10000000000px;
}

此解决方案可能会解决可能出现的几个问题。例如,“隐藏”的东西的 jquery 高度和宽度属性为 0,所以如果你按照这些线进行样式设置,你必须等到它被放置,这更复杂,并且混乱起来。

然后,您的视图将需要按照(伪代码)的方式做一些事情:

//parent
//do all your view-y stuff...
foreach (child = this.my_kids) {
  if child.is_ready() {
    put_that_child_in_its_place();
  }
}

同样,对于孩子,你会做类似的事情:

//child
foreach(parent = this.my_parents) {
  if parent.isnt_ready() {
    this.go_play_in_construction_yard();
  } else {
    this.go_to_parents_house();
  }
}

...而且,由于骨干很容易扩展,您可以使用以下方法将其包装在更通用的类中:

var ParentsAndChildrenView = Backbone.View.extend({blah: blah});

接着

var Wsywig = ParentsAndChildrenView.extend({blah: blah});

希望有帮助!

差点忘了我的来源:http: //jqueryui.com/demos/tabs/#...my_slider.2C_Google_Map.2C_sIFR_etc._not_work_when_placed_in_a_hidden_​​.28inactive.29_tab.3F

于 2011-06-20T21:05:16.443 回答
0

一种解决方案是使用事件委托并绑定焦点事件来检查富文本编辑器是否已加载。这样,用户将在需要时获得文本编辑器(通过延迟加载,性能稍有改进),否则您不必加载它。它还无需担心何时附加富文本编辑器以及依赖于渲染链。

如果您担心 FOUC(无样式内容的闪烁),您可以简单地设置未修改文本区域的样式以包含一个带有背景图像的元素,看起来就像所见即所得的控件,并让您的焦点绑定切换一个类以隐藏富文本编辑器接管后的外观。

这是我想到的一个示例:

var View = Backbone.View.extend({
  el: '#thing',
  template: _.template($("#template").html()),

  render: function() {
    // render me
    $(this.el).html(this.template(context));

    // setup my textareas to launch a rich text area and hide the facade
    $(this.el).delegate('focus', 'textarea', function() {
      if(!$(this).hasRichTextEditor()) { // pseudocode
        $(this).wysiwyg();
        $(this).find('.facade').toggle();
      }
    });

  }
});
于 2011-06-15T05:07:47.667 回答