6

私のビューのいくつかは、テキストエリアをリッチテキストエディタに変換する必要があります。

私はエディターとしてjwysiwygを使用しています。アタッチされている要素は、エディターが初期化されるときにページにある必要があります。つまり、$(this.el).wysiwyg()を呼び出すと、this.elは既にドキュメントにあります。

私のビューのほとんどは実際にはdomにアタッチされていません-それらのrenderメソッドは、アプリテンプレートエンジンを使用して要素の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();
});

このコードはテストしていませんが、理論的には、テキストエリア要素のインスタンスがDOMに表示されたときに、クラス「wysiwyg」と一致し、wysiwyg関数を呼び出してエディターを適用する必要があります。

于 2011-06-19T19:03:08.053 に答える
1

DRYの原則に準拠し、洗練されたソリューションを得るには、テキストエリアにwysiwygがあるかどうかを判断するための専用の関数が必要です。たとえばwysiwygAdder、必要に応じて追加します。次に、アンダースコアのwrap関数を使用して、レンダリング関数の最後にwysiwyg加算器を追加できます。

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
}

ビューが初期化されると、レンダリング関数がレンダリング関数で上書きされ、その後にwysiwygAdderが続きます。return this;コンテキストを提供するために、レンダリングから確認してください。

于 2011-06-16T02:42:16.110 に答える
0

1つの解決策は、イベント委任を使用し、フォーカスイベントをバインドして、リッチテキストエディターがロードされているかどうかを確認することです。そうすれば、ユーザーは必要なときにテキストエディターを取得し(遅延読み込み、パフォーマンスのわずかな改善を介して)、それ以外の方法でテキストエディターを読み込む必要はありません。また、リッチテキストエディタをいつ接続するか、レンダリングチェーンに依存するかどうかを心配する必要がなくなります。

FOUC(スタイル設定されていないコンテンツのフラッシュ)が心配な場合は、変更されていないテキスト領域のスタイルを設定して、wysiwygコントロールと同じように見える背景画像の要素を含め、フォーカスバインディングでクラスを切り替えて非表示にすることができます。リッチテキストエディタが引き継いだ後のファサード。

これが私が考えていたもののサンプルです:

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 に答える
0

解決すべき大きな問題!私が全体のジストを持っているかどうかはわかりませんが...あなたは左に離れた「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 に答える