Backbone, javascript mvc - view styles using javascript

Some of my views need their text fields to be converted to text editors.

I am using jwysiwyg as an editor. This requires that the element to which it is attached is on the page when the editor is initialized, that is, when I call $ (this.el) .wysiwyg (), this.el is already in the document.

Most of my views are not actually attached to dom - their visualization methods simply set their html content elements using application template templates, for example. $ (this.el) .html (this.template (content)

Views / Controllers continue to follow the chain, actually inserting these child views on the page. At the same time, looks re-display themselves when their models change.

How to ensure that the editor is attached to the element each time it is rendered and still makes sure that the editor is not attached until the element is on the page?

Obviously, I could hack something together that would work in this particular case, but I would like an elegant solution to work for all cases.

Any help would be greatly appreciated.

Edit: The main thing is that the solution must be gracefully scaled to cover several elements that should be styled after rendering and should not be written until they are in the DOM

Edit: this is not a problem if I am doing top-down rendering, but it is slow, I would like it to be able to render from bottom to top and then paste the full view in one pass at the top

Edit:

Using a combination of some of the methods below, I'm going to do something like the following. Any comments / criticism would be appreciated.

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 } 
+6
source share
4 answers

What if you used the jQuery LiveQuery Plugin to attach the editor? Such code may be part of your template code, but not as HTML, but as Javascript associated with the template. Or you can add it globally. The code may look like this (provided that you included the plugin itself):

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

I have not tested this code, but theoretically it should correspond to an instance of the textarea element with the class "wysiwyg" when it appears in the DOM, and calls the wysiwyg function to use the editor.

+1
source

To adhere to the DRY principle and get an elegant solution, you will need a function designed to determine if textarea has wysiwyg, say wysiwygAdder and add it if necessary. You can then use the wrap underscore function to add your wysiwyg adder to the end of the render function.

 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 } 

When a view is initialized, it overwrites your render function with the render function, and then wysiwygAdder. Make sure return this; from render to provide context.

+1
source

One solution would be to use event delegation and bind a focus event to check if a text editor has been loaded or not. Thus, the user will receive a text editor when he needs it (through lazy loading, a slight performance improvement), and you will not have to download it otherwise. It would also eliminate the need to worry about when to join the rich text editor and be dependent on the rendering chain.

If you are worried about FOUC (flash uneven content), you can simply style the unedited text areas to contain an element with a background image that looked just like wysiwyg controls, and snap focus to the class to hide the facade after the editor extended text text occupied.

Here is an example of what I had in mind:

 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(); } }); } }); 
0
source

Great problem to solve! Not too sure that I have the whole jist, but ... You can get away with "construction_yard" (I just made this term) this way to the left, build and place objects there, and then just move when they are ready for placement. Sort of:

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

This solution may solve several problems that may arise. For example, the jquery height and width attributes for something that is hidden are 0, so if you fit along these lines, you have to wait until it is placed, which is more complicated and something gets in the way.

your views would then have to do something in accordance with (pseudo-code):

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

Similarly, for children, you would do a similar thing:

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

... and, since the trunk expands quite easily, it can be wrapped in a more generalized class using:

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

and then

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

hope this helps!

I almost forgot to note my source: 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
source

Source: https://habr.com/ru/post/890558/


All Articles