What does dojo.empty() / domConstruct.empty() do exactly - javascript

Let's say I register some widgets with some ids(let's say id1, id2) in someNode. Now if I do, domConstruct.empty(someNode), this will remove the widgets from someNode by doing someNode.innerHTML= "". But are the widgets still in memory?
What I mean to say is, after domConstruct.empty(someNode), will I be able to register a widget with id1 or id2?
If not, then how can I achieve the same? I do not want to check for widget with same id during its creation and destroy it if it exists.
P.S: I am assuming that dojo.empty() and domConstruct.empty() work in the same way.

dojo/dom-construct's APIs do not know anything about Dijit widgets, so when you run domConstruct.empty(node) or domConstruct.destroy(node), it does nothing to look for and destroy widgets. (I've explained how to do that in a largely-related question.)
When Dijit widgets are created, they are populated in a hash maintained by the dijit/registry module, which allows them to be accessed by ID (or node) in the future. dijit/registry.findWidgets is also used by dijit/_WidgetBase#getChildren (which is in turn used by container and layout widgets) to retrieve child widgets according to the DOM tree.
Since dojo/dom-construct knows nothing of Dijit, it simply destroys all DOM nodes underneath the given node, and doesn't update Dijit's registry. Thus, you end up with an inconsistent state, where Dijit thinks these widgets still exist, but their DOM has actually been destroyed. As answered in the other question, you should use findWidgets to properly destroy the widgets first, or consider using a layout widget or ContentPane to manage the child widgets for you.

Related

Polymer: access properties of parent or other elements

How do I access properties of parent or other elements in Polymer?
For example my top-most element is "my-app".
Now I am in an element called "my-element-1", how would I access/reference any properties from "my-app" using Javascript?
Further, if I am in "my-element-2", would I be able to access/reference properties of "my-element-1"?
EDIT: There are many reasons why I want to do this, and I certainly believe there are better ways than having to do this. But, I do not know the ways.
1: The first use case that comes to mind is that I use "iron-pages", which is located in a parent element. Each "page" is therefore a child of that parent.
The parent definitely knows which "page" is "selected" because the "iron-pages" is a property of the parent.
However, each "page" does not know if it is selected or no longer selected because the "selected" attribute is only known to the parent.
In this use case, I just want to be able to know from within the "page" whether it is still selected or not.
2: The second use case is probably a general design pattern. I want to maintain a set of GLOBAL properties, which can then be accessed anywhere from within the Polymer app. My assumption is that it should be store within "my-app" as the root element.
1 In a closed parent-child pair like with the iron-pages you can take advantage of the selectedAttribute and selectedClass properties. By setting one of them you can let the child "know" that it's selected.
2 The other example isn't so simple. For keeping shared state you can use the oxygen-state element which was mentioned on Polymer's Slack recently. Similar solution is possible with iron-meta which lets you access global variables.
The more robust solution to connecting elements app-wide is the Flux pattern. It appeared as a solution to a similar problem - communication between elements on a page. If elements are to communicate freely, it quickly can become unwieldy. You can read a number of related questions on SO: Flux architecture with polymer elements, Binding to global variables in Polymer, Polymer 1.0: How to pass an event to a child-node element without using <iron-signals>?
A simplification of this is to use events to notify any interested element of changes elsewhere in your application. A naive way is to listen for events on the document. Then there is also the iron-signals element.

Can the DOM be differentially updated?

First and foremost, I've done extensive research about this, under different names that I think could apply such as "Javascript differential templating", "Javascript update DOM without reparsing", "Javascript render UI using deltas" and other variations. Pardon me if I missed an existing thread that covers my question.
Essentially, I would first like to know if most DOM parsers in browsers do the following already, even though I'm fairly sure the answer is no: do they update the DOM differentially (i.e. only the nodes that have changed in the same tree since the last update) when a node is modified? Like I said, I figure the answer is no and they actually reparse and rerender the updated node and everything in its tree.
Which brings me to my question: is there any Javascript library that allows to manage differential updates to a data model and to the DOM?
I realize I might not be really clear about this, so I will provide some code to explain what I mean: http://jsfiddle.net/btZ3e/6/
In that example, I have an "event queue" (which is really a timeline) with events in it. UserEvents all have a unique ID. The way it works now is that UserEvents can execute() and undo(), in the former they modify data in memory (myAppManager.dataModel) and append a <p> in the DOM while in the latter they undo these changes. (Each UserEvent's undo() is defined within the execute() of the same UserEvent as to allow more flexibility, one could consider moving events around independently)
Then, there is myAppManager.render() :
var myAppManager = new function () {
this.dataModel = {
someValue: 0,
disableButton: false
};
this.render = function () {
$('#displaysomevalue').text(this.dataModel.someValue);
$('#go').prop('disabled', this.dataModel.disableButton)
}
}
How would it be possible (is it at all?) that myAppManager.render() only updates what has changed since the last update? I reckon this would mean that I would have to have some sort of differentiation system in my data model too. Ultimately I'm wondering about this because I'm gonna be receiving multiple new UserEvents per second (let's say 20-30 per second at worst?) via websockets and I was wondering if I would need to rerender my whole UI for every new piece of data I get. I investigated into Javascript templates to see how they do it, and it seems they all just go this route:
document.getElementById('someTemplateContainer').innerHTML = someTemplateEngine.getHtmlOutput();
I doubt however they need to refresh as often as I need to in some instances. Is there prior work on this? Did I miss anything? Thank you very much!
The way Backbone.js, as an example, does this is that models (name:value pairs basically) are backed by a view/template, and that models have events associated with them like change. Let's say you have a <ul> where each <li> is one Backbone view, backed by a model.
You could bind every model's change event to re-render its own view (and ONLY its own view). So when the 5th <li> gets its name changed, it will re-render just the contents of that <li>, and the rest of the <ul> is undisturbed.
That lets only new or updated models have their DOM nodes touched and updated.
The difference is that you don't need to know 'what parts of the whole <ul> have changed and just render those', because you've actually decomposed the problem to a series of smaller ones, each of which are responsible for their own rendering and updating logic. (I'm sure other frameworks have similar patterns, and you can do them in vanilla JS too no doubt)

How to get information from a view to a model in Backbone.js without a DOM event

I'm new to Backbone.js and am having trouble figuring out the proper architecture for a model-view relationship.
I have a view that holds an input box and a model that is supposed to take the contents of that input box and send it to the server.
My issue is that I don't always have a discreet DOM event that triggers a request for the view to update the model data, such as input.change. Sometimes the code itself needs to ask the model to send updates to the server.
I've thought of three solutions to this problem so far, I'm not sure if any if them are any good though:
Update the model on the input element's keypress event
Once the view is initialized with the model, have the view update/add a function to the model called 'get_input_value()' that returns the value of the input box
Whenever the application needs to request the model to update the server, first call a function in the view that updates all of the information that the user has typed into the view to the model.
Please bear in mind that this is a simplified example. The view contains child views as well, all of which hold a number of elements that the user can manipulate, the model needs to be updated with all of this information so that it can update the server.
Any help and input is appreciated! Thanks so much!
Edit :::
Base on machineghost's response, I now see that I did not articulate this problem correctly:
There is a DOM event, but the problem is that it doesn't necessarily originate from inside the view that uses the model. It may originate from the Router or another view and be triggered by a global event handler. Additionally, there is not a 1:1 View-Model relationship. This model is used by multiple views who express the model in different ways. So in this case, it seems like the command to update the server should not go through a View, but to the model itself. If that is the case, the model must be able to say "Sync me with my views!".
But I don't know how to do this without breaking the rules and thus creating other problems with architecture...
Ok this is kind of a subjective question, so forgive me if this just seems like me spouting off my two cents. And before I even answer your question, I have to admit I'm a bit skeptical that you:
don't always have a discreet DOM event
because pretty much anything the user can do triggers an event that you can watch for. For instance, if you want to wait until a user changes a text input there's change, but also (as you noted) the various key* events, plus there's blur (which is commonly used for this sort of thing). Between the 3(+) you should always be able to respond appropriately to the user's actions. It would only be if (say) you had to save the text input's contents every 3 seconds that it would truly be independent of DOM events.
So, without knowing your particulars, I just have to point out that something smells fishy there. But anyhow, as for your actual question, here's my take on your ideas:
Update the model on the input element's keypress event
This certainly would work, but just be sure to use the view to do the actual event handling/model setting; hooking up the onKeyPress handler in the model would be a bad idea
Overall this approach seems pretty standard, and fits the Backbone paradigm.
Once the view is initialized with the model, have the view update/add a function to the model called 'get_input_value()' that returns the value of the input box
I don't quite get how this helps your problem, plus it seems to put the concerns in the wrong place: the model should (ideally) have nothing to do with the DOM.
Whenever the application needs to request the model to update the server, first call a function in the view that updates all of the information that the user has typed into the view to the model.
Is the save happening every 5 minutes or something? If not, then it's presumably happening in response to the user's actions, and you should use an event handler to respond.
However, if you truly do need to make the sync independent of user actions, I'd recommend using a custom event to manage things. In other words, in your model's sync method put something like this.trigger('preSync'). Then, every view which uses that model can bind some sort of updateMyModelValue method, ie. this.model.on('preSync', this.updateMyModelValue, this);.
This way, your model code is never directly interacting with the DOM at all; instead, it just worries about the stuff it's supposed to worry about (the data) and the views pay attention for when they need to update that data from the DOM.
Hope that helps.
* EDIT (in response to your editing of your question) *
If that is the case, the model must be able to say "Sync me with my views!".
The general Backbone way for a model to say ... well, pretty much anything to its views is through events.
(Technically you could maintain a list of a model's views in the model itself, and then iterate through that list to tell the views to do things. Backbone is even un-opinionated enough to let you do that. However, from a maintainability standpoint that seems like a terrible approach to me.)
My example of a "presync" event (above) demonstrates how you'd use this technique; comment back if any of it is unclear.
Similarly, if you have an issue of:
View A catches an event
View B needs to do something in response to that event
You basically have two options:
1) You can tightly couple the two views. Let's say have a table view that creates row views, but needs to respond to events that happen in those rows. You can pass the table itself as an option to the row when you create it (new Row({table:this})), and then when those rows need to tell their table "an event happened" they can just do this.options.table.informThatAnEventHappened(). This is a great approach if the two views are inherently related, like a table and its rows. If not, a better approach is:
2) You can use events to communicate between the views. Let's say you have a title div at the top of the page, which needs to be updated whenever a "title" text input changes ... but that text input is way down the page and doesn't conceptually have much to do with the page's title (apart from setting it). The common point between these two elements (and their views) is the data, the text of the title itself.
Now imagine that titleDivView and titleSettingInputView both share a pageTitle model. When titleSettingInputView calls this.model.set('titleText', 'newTitle'), the titleDivView can listen for this.model.on('change:titleText', ...), and re-render itself appropriately in response. In this way two totally un-connected, de-coupled views can interact with each other, without creating a tangled web of inter-related code.
And of course, if there isn't a nice convenient "change:title" event to bind to, you can always make your own, as with the custom "presync" event I described above.

Extjs databinding model properties to ui elements (textbox)

I need binding the model properties to view elements directly bidirectional way automatically stay sync. If I make a change in a textbox I need run bussiness logic in the related model, and model properties changes automatically refresh the related ui elements.
Im new in Extjs, but I guess it doesnt support it, JQXB seem to be the right way, does anyone could point me a sample using JQXB with Extjs?
With jQXB it's very simple to stay in sync.
jQXB is striclty related to jQuery so I assume your needs can be satisfied only with jQXB and jQuery.(Extjs is no more required);
In your case you need only to use jQuery to catch textbox changes and then, supposing your datamodel already binded to controls via jQXB datasource, invoke doBind method to refresh controls after changing data model.
At http://www.jqxb.altervista.org you can see in demos pages that already do something like that.
At http://jqxb.codeplex.com ( Download Section) you can examples and in Documentation Section you can find other examples.
Alternatively you can post an example of what you want to obtain or write directly a post or an email on jQXB site.
regards

dojo tree event on root nodes

**I'm building dojo tree using the following code:
The tree is displayed as expected. The problem that I have is that the onClick event is only fired on leaf nodes. When I click on the root level node(I have several root level) it is just open showing child nodes.
How can I add "extra" onClick functionality to the root nodes?
You've got openOnClick set to true for your tree. I think the API docs answer this as well as I possibly could.
http://dojotoolkit.org/api/dijit/Tree/openOnClick
That said, it looks like you'd be able to connect to _onClick instead and do whatever you want (that's the method responsible for calling onClick only when openOnClick is false, anyway). Or, if you wanted to feel a little less guilty about accessing private members, dojo.declare yourself a subclass of dijit.Tree, extending _onClick to also fire another function you define as public.

Categories

Resources