I've encountered an issue with ember's (app is on 2.6.0, but seems to happen in latest as well) rendering process and its compatibility with the MathJax.js library. I have an ember twiddle (linked below) that isolates the problem, but essentially it seems like MathJax's rendering of inline equations that occur in the middle of a single text node breaks ember's re-rendering, in that the single text node becomes multiple text nodes after MathJax transforms the inline equation text into its Math elements, and the 2nd text node becomes orphaned, and remains in the DOM across re-renders.
https://ember-twiddle.com/cadfb80d7c90df98353cc3d9900f2b73/1ab7f66c3c6ca4aad15bf443bbe02fbb1f79a0d4?openFiles=controllers.application.js%2C
It may just be that my integration of mathjax with ember is just not correct, so I'd love some pointers if thats the case.
I was able to fix this with a somewhat hacky workaround:
https://ember-twiddle.com/cadfb80d7c90df98353cc3d9900f2b73
The issue (as confirmed on slack by some ember core team members) is with how MathJax modifies the DOM, in that ember is not able to keep track of the extra nodes it creates, and as a result can not properly clean up after it on re-renders.
To solve this, the component which contains the mathjax content manually sets its element's innerHTML to whatever the content attribute is set to when didRender() is fired, effectively wiping out all the DOM created/modified by MathJax. MathJax's rendering process is then invoked to render any formulas in the newly rendered content.
Note that if your content does not contain any HTML, it is recommended to set element.innerText instead of element.innerHTML.
Related
I want to reuse the html of a complex UI that I created using underscore template. The issue is that the template constructor takes the data and generates the plain html with data.
Now, I want to cache the generated html for future to use it as a template and would change the data of specific html nodes by selecting each of them using jQuery selectors.
My goal is to reduce the memory consumption by keep re-using the JS and DOM objects once created.
Has anybody done something like this before?
Okay. I myself have found a way. I am caching the DOM fragment (without removing from body) prepared by underscore template. When next time same fragment is needed, I re-use the cached fragment by updating the values using jQuery selectors.
It is still WIP but looks promising.
I am using coffeescript with react-rails gem. In the measure.js.coffee, there is no span present in the coffee code, but when the HTML is getting painted a mysterious ghost span is appearing. Below is a screenshot of code and HTML generated by it.
In my code, there is no span in between carousel-mImages and mtag-images. Is it because of the reactCSSTransitionGroup = React.createFactory(React.addons.CSSTransitionGroup)
Yes, ReactCSSTransitionGroup is a wrapper around ReactTransitionGroup.
And from the official docs here:
By default ReactTransitionGroup renders as a span.
You can change this behavior, and render as another type of component, but this would mean you have to manually configure and render the ReactTransitionGroup.
This may save you one wrapper element in the DOM, but this depends on your component tree structure.
This question relates specifically to the new Ember angle bracket component syntax, but also in general to Web Components.
I am working on upgrading an Ember application that is not on the later versions of Ember, and I decided that I would use the Ember 1.13 beta so that I can take advantage of the angle brackets components already.
I have a lot of components that built html hierarchies with other elements than div, such as a table where every tbody/tr/td is a component (for let's say having a form inside a table for manipulating rows) or a list where every li is a component. I was surprised to see that <my-component> is actually generated as <my-component> in the final html, even with tagName property set. Maybe this was unsurprising to every one else, but for me it will be a much bigger change than anything else announced for Ember 2.0. I read a bunch of articles about Web Components and couldn't see any mention of this issue, so maybe it is just a fundamental misunderstanding on my part.
How do you create components (Web/Ember) that are not block level? By restructuring your html to only have block elements as components? By writing a bunch of css to change them to non-block (such as using display: table-row) elements?
The answer is that there is no answer currently. The behaviour of angle bracket components is being worked out and there is an RFC suggesting how they should behave:
https://github.com/emberjs/rfcs/blob/angle-bracket-components/active/0000-component-unification.md
Quite often we deal with lists of things on our site. These initially get loaded with the rest of the page from the server. However, any updates received we would like to update these lists using Ember.
All of the examples I have seen so far with Ember views deal with controlling content on a page that has always been created purely by Ember. What options are there for dealing with DOM elements that already exist on the page with Ember views?
There has been some discussion around this idea here: https://github.com/emberjs/ember.js/issues/563
In the current situation two approaches come to my mind:
Replace the static rendered list with an Ember.CollectionView as soon as all list items are available to ember as data objects (e.g through ember-data)
Use plain old jQuery to append the latest updates at the beginning / end of the list
I guess it depends on how complex your list items and the updating logic is. If updates need reordering of items and your list needs complex interaction, the first approach using ember might be better suited, although there could be a "flickering" of content while the lists are replaced. The second approach is much simpler but also limited. I would only use jQuery for appending / prepending content. Still, if the lists are simple it would be overkill to even use ember in this case.
I am listing products as table rows, each row contains input fields for specifying the quantity of products.
I made a Fiddle for it here, http://jsfiddle.net/kroofy/4jTa8/19/
As you can see, after the input in the Qty field have been made, the whole row render again. And because of that the focus of the input field will be lost, which is not good if you want to input more than just one digit, or tab between input fields.
What would be the most elegant way to solve this?
I would handle this by setting model.set({qty: _qty}, {silent: true}) and then updating the non-input fields with this.$.
As an alternative to the silent treatment: rather than listening for change events, listen for change:qty and change:sellPrice and have a method that updates just the HTML that needs updating within this.$, rather than re-rendering the DOM object and breaking your focus.
Either way, your comment about "selective updating" on the fiddle is certainly the right way to go.
(this.$ is a backbone hack to jQuery that restricts all selectors to search only within the DOM of the View's element. The element doesn't even need an ID or class; it just needs to exist and the View maintains a handle to it. It's incredibly useful.)
i built a plugin for backbone called Backbone.ModelBinding that may be able to help in this situation. my plugin allows you to update portions of a view with data from a model, when the model changes.
i've forked / updated your fiddle to show it in action: http://jsfiddle.net/derickbailey/FEcyF/6/
i removed the binding to the model change. i've also added id attributes to the inputs of the form to facilitate the plugin (the attribute that the plugin uses is configurable, though). and lastly, i've added a data-bind attribute to the sell price total td.
you can get the plugin here: http://github.com/derickbailey/backbone.modelbinding/
hope that helps
FWIW: my plugin is an automated version of what Elf is suggesting. I've written code exactly like he is describing, numerous times, which is where the plugin came from. I just got tired of writing that code by hand :)