backbone, javascript mvc - стилизация видов с помощью javascript - PullRequest
6 голосов
/ 15 июня 2011

Некоторые из моих представлений нуждаются в преобразовании текстовых полей в редакторы форматированного текста.

Я использую jwysiwyg в качестве редактора.Требуется, чтобы элемент, к которому он присоединяется, находился на странице при инициализации редактора, т.е. когда я вызываю $ (this.el) .wysiwyg (), this.el уже находится в документе.

Большинствоиз моих представлений на самом деле не привязываются к dom - их методы рендеринга просто устанавливают html-контент своих элементов с помощью механизма шаблонов приложений, например, $ (this.el) .html (this.template (content)

Views /Контроллеры дальше по цепочке выглядят после фактической вставки этих дочерних представлений на страницу. В то же время представления изменяют свои представления при изменении их моделей.

Как убедиться, что редактор присоединен к элементукаждый раз, когда он визуализируется и все еще гарантирует, что редактор не присоединен, пока элемент уже не находится на странице?

Очевидно, я мог бы взломать что-то вместе, что сработало бы в этом конкретном случае, но я хотел бы элегантное решение, которое будетработа для всех случаев.

Любая помощь будет высоко ценится.

Редактировать: Сутьв данном случае решение должно изящно масштабироваться, чтобы охватить несколько элементов, которые должны быть стилизованы после рендеринга, и не должны быть стилизованы до тех пор, пока они не будут в 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 ]

1 голос
/ 16 июня 2011

Чтобы придерживаться принципа СУХОЙ и получить элегантное решение, вам понадобится функция, предназначенная для определения, имеет ли текстовая область 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; от рендера, чтобы обеспечить контекст.

1 голос
/ 19 июня 2011

Что если бы вы использовали JQuery LiveQuery Plugin , чтобы прикрепить редактор?Такой код может быть частью кода вашего шаблона, но не как HTML, а как Javascript, связанный с шаблоном.Или вы можете добавить это глобально.Код может выглядеть следующим образом (при условии, что вы включили сам плагин):

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

Я не тестировал этот код, но теоретически он должен соответствовать экземпляру элемента textarea с классом 'wysiwyg ', когда он появляется в DOM и вызывает функцию wysiwyg для применения редактора.

0 голосов
/ 21 июня 2011

Отличная проблема для решения!Не слишком уверен, что у меня есть весь джист, но ... Возможно, вам удастся уйти с 'construction_yard' (я только что придумал этот термин), который далеко налево, строить и размещать там предметы, а затем просто двигатьсяих, когда они будут готовы к размещению.Что-то вроде:

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

Это решение может решить несколько проблем, которые могут возникнуть.Например, атрибуты jquery height и width для чего-то, что «скрыто», равны 0, поэтому, если вы стилизуете по этим линиям, вам придется подождать, пока оно не будет размещено, что является более сложным и перемешивает.1005 * тогда ваши представления должны будут что-то делать в соответствии с (псевдокодом):

//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

0 голосов
/ 15 июня 2011

Одним из решений будет использование делегирования события и привязка события фокуса, чтобы проверить, был ли загружен текстовый редактор или нет.Таким образом, пользователь получит текстовый редактор, когда он ему понадобится (из-за отложенной загрузки, незначительного улучшения производительности), и вам не придется загружать его в противном случае.Это также избавило бы от необходимости беспокоиться о том, когда присоединять редактор форматированного текста, и о том, что это зависит от цепочки рендеринга.

Если вы беспокоитесь о 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();
      }
    });

  }
});
...