I am working on a personal project involving some jQuery / native Javascript programming. I am hoping somebody can clarify an issue I'm seeing with my code. I'm confused about the relationship among objects created in Javascript and objects that are part of the DOM.
When using JQuery UI (the tabs feature), my program behaves differently depending on whether I manipulate my object from Javascript directory, or if I first access it from the DOM API, which leads me to believe that the two references are not equal.
For Example:
myObject = $(document.createElement("div")).attr("id", "tabs");
$("body").append(myObject);
Now, I have found that the following example works correctly:
$("#tabs").tabs();
But the following does not:
$(myObject).tabs();
Am I correct in assuming that the object I am retrieving via $("#tabs") is different or works different than the object I have created manually in Javascript (myObject)?
Is there some mechanism that is invoked once you insert an object into the DOM? Should I not be tinkering with it after I insert it into the DOM, and instead re-retrieve it via its id field?
Creating elements with the raw JS methods is no different to any element referenced with jQuery except that those found by expressions like $(...) are wrapped in a jquery object.
Since you're doing this:
myObject = $(document.createElement("div")).attr("id", "tabs");
you already have a jquery object so you should be able to do this:
myObject.tabs();
By doing:
$(myObject).tags();
you're effectively doing this:
$($(document.createElement(...)...);
and I'm not sure what the expected behaviour of that is.
Also bear in mind you can do this (and should favour this way):
var myObject = $("<div></div>").attr("id", "tabs");
The var makes it local in scope (which is what you want 95% of the time) and you can create arbitrary markup with jquery without using the raw JS methods.
Related
This is something I cannot find an official answer about. For some, DOM objects are JS objects, for others they differ. What is the right answer?
By searching in stackoverflow, you may see controversial opinions.
For example, does the object document.body belongs to DOM API only or may it be considered as part of javascript engine too?
Does Javascript create an internal representation of it or does it just communicates with DOM to access it?
The DOM API is a collection of standards which have implementations in a variety of programming languages.
The DOM available to JavaScript in a browser provides things in the form of JavaScript objects. Large portions of it are written in native code (so are handled by libraries not written in JavaScript but made available through a JavaScript API).
Where JavaScript leaves off and native code begins doesn't really matter, it is an implementation detail and probably varies from browser to browser. The point of having a standard API is that developers using it interact with that API and don't need to worry about how it is implemented under the hood.
Strictly speaking, no. The JavaScript runtime has access to them, and in that capacity they can function as JavaScript objects. But they are defined in a way that is not bound to any particular language, and in most DOM implementations, they're native code. Most DOM implementations take care to make the objects function the same way you'd expect other objects in the chosen language to work, but that's not always the same way that JavaScript objects do: for example, you can't go around adding dynamic properties to objects when you're working in Java.
For most practical purposes, when you're working in the browser or in some other JavaScript runtime, yes. As I stated above, most DOM implementations try to make the DOM objects work the same way as other objects in the language, and for JavaScript, that means making them work like "real" JavaScript objects. Although IE took a while to really get this right (you need IE9+ to take full advantage), these days you can pretty much use DOM objects the same way you'd use any other JavaScript object.
If you inspect deeply the __proto__ of document.body for instance, you would find this :
HTMLBodyElement > HTMLElement > Element > Node > EventTarget > Object
So yes : in the browser's context, DOM objects are JS objects, this is not reciprocal of course.
But DOM API is not exclusive to Javascript, it defines interfaces which can be implemented in any languages, for instance Python has a DOM API too and in this case, DOM objects are Python objects.
The DOM objects are not part of the JavaScript language, they are part of the environment that is provided when JavaScript runs in a browser.
When JavaScript runs in another environment, for example in Node.js, then there is no DOM. Instead there are other objects that make up the environment that the script works with.
The DOM objects are there just for JavaScript so the script works directly with the objects, there is no extra wrapper to make them available to JavaScript.
Dojo for instance adds a member to a JS object called "declared_class". I would like to find those and replace some stuff. And, can this be done also outside of Dojo ? I know, JS is not type oriented but you never know whats out to bypass this lack of introspection facilities.
Update : This is NOT about DOM objects. I am writing a sort of real-time Javascript editor. After I reloaded the script, I need to locate related (Dojo modules) objects and mixin altered functions only.
Update 2 : It doesn't seem to be possible without a prototype or a similar patch. Since all the code is running 1:1 in a node instance as well, I am wondering whether I can determine those objecys in a node.js instance ?
I am writing an HTML5 application that involves a lot of XML manipulation, part of this manipulation involves comparing the versions of two different XML Elements.
What I need is for every Element, Attr, and TextNode (all of which inherit from Node, AFAIK) object that gets created to have associated version information, but still be able to behave like a normal Element, Attr, or TextNode. The current working solution I am using to store the version information, is the following:
Node.prototype.MyAppAnnotation = {
Version : null
};
Now, I understand that augmenting built-in types is considered bad form, but beyond this technique, I'm at a loss for how to get the desired functionality. I don't think I can encapsulate the Node in a wrapper because I need the Node related properties and functions exposed on the wrapper. I might be able to write some sort of pass-through functions for the wrapper, but that seems really clunky.
I feel that because the app I'm writing is an HTML5 app, and as such only has to run on the most modern browsers (all of which support the augmentation of built-ins), makes this technique appropriate. Also, by providing a sufficiently obscure name to my augmentation object, I can avoid all naming collisions (except for intentional collisions). I've also explored inheritance-based solution using Google's Closure library. However, it appears that because Element, Node and TextNode don't have direct constructors (i.e. they're created off of a Document object), this technique will not work either.
I was wondering if someone could either a) recommend an elegant way of achieving this effect without augmenting Element, or b) provide a compelling reason for why I shouldn't break the "don't augment built-ins" rule in this case.
Many Thanks,
Jarabek
Your idea is theoretically valid, but there's a weird feeling I get when reading about it.
First of all - you don't have to augment any prototypes. If you just do somedomnode.myweirdname='foo' it will become a field of that object. That's what javascript does ;)
So when there is no version you'll get undefined instead of null.
But, if you want to add more functionality or wrap dom node in anything - there's a bit of history of doing that. Most of that history is dominated by stuff like jQuery :)
Just create an object that has a field containing the node. And then you can access it really simply:
myobject.node
And create the object with some constructor or just factory function:
var myobject = createDomNodeWrapper(domnode)
My current style of programming is OO javascript using the Class.extend function by John Resig: http://ejohn.org/blog/simple-javascript-inheritance/
This has been fine but I find myself writing numerous setters and getters that only get used on init. Also, it seems to lead to memory leaks in IE when storing instances of these objects in an array for later use.
I am starting to favor smaller, cleaner, and more readable code over the seemingly overkill OO approach. My idea is to now just base everything off the dom using jquery and storing data properties using the .data method. For example, instead of creating an instance of a new Tweet object, you would simply add a div to the dom with class tweet and simply add the properties like author, timestamp, reply to, sent from, etc. in the .data cache for that dom element.
What do you think of this less structured approach when creating instances of things such as items in a stream like twitter? Is OO and prototypal inheritance the best approach or is strict dom manipulation better?
I am doing something similar. I took the OO javascript approach. But instead of using arrays i use a key value object. The key is a unique dom element id, the value is the object itself. it looks something like this.
for example:
var collection = {};
var $domEl = jQuery; // jquery dom element
var myClass= new MyClass($domEl); // class instance
// add to collection
collection[$domEl.attr('id')] = myClass;
// remove
delete collection[$domEl.attr('id')];
Really it depends on the complexity of your objects. A strictly .data approach would need to rely on plugins for all of the related methods, and then store data in the elements data. I have many methods that are not related to strictly element interaction, so i keep the methods and data in the class.
My brain tells me that the very structured Javascript that doesn't rely on the DOM manipulation and calling in and out of it with jQuery would be ideal.
However, I just wrote an HTML5 web app that runs offline using the built in SQLlite and did it using primarily .data and storing information in divs and getting them out of there. It was simple, clean, and easy but for some reason didn't feel right.
But it worked well.
This is a rephrase of a post I made last week. I was surprised I didn't get more of a response, thinking maybe I didn't describe/title it very well.
Simplest possible way to describe it:
Is there something like spring:bind for javascript/dhtml?
The high level view of what I want:
In my app, I have a list of "subscriber" objects which I've loaded via ajax. I'd like to dynamically draw UI elements representing these objects, and register event handlers so that the backing objects are updated when the user edits the view.
The more low level thoughts
Dynamically displaying js data in the browser is trivial. It's also not a big problem to write event handlers for every type of data, but it's a bit tedious. I feel like there should be some library out there which will behave as a template system, creating HTML form elements dynamically, populating placeholders with data from my js objects, but go to the additional step of updating the backing objects when the user makes edits to the form elements. The closest example I'm aware of is a back-end technology, the Spring (java framework) binding functionality, where form elements in templates are coded according to a system where they're automatically linked to the model objects on the server.
So, does what I've described exist in the front-end world?
I do not know about libraries of the kind you described, but jQuery offers the very useful data() function which allows you to associate an arbitrary piece of data with a DOM element, using a key. Adding a new element and associating data with it might look like this:
var elem = $('<div class="subscriber">...</div>').appendTo(someContainer);
elem.data('yourKey', backingObject);
Using event delegation (e.g., the live() function), you can add one event handler that is valid for all graphical representations of your subscriber objects, no matter if they already exist or not.
$('.subscriber').live('click', function(e) {
var backingObject = $(this).data('yourKey');
// Now call some methods on the backing object
});
Hope this helps you somehow.
This is not an answer, but a larger comment. It might help to write the API you want to use, such as:
var jsObj = {};
jsObj.bind(document.getElementById("firstName"), "onchange");
//binds the data from the firstName element to the jsObject in property "firstName" during the onchange event.
Is this what you are trying to do?
A quick google search turns up:
http://api.jquery.com/bind/
It might be interesting to make a delegate to jQuery's bind, which doesn't see to hard to do.
Knockout looks like it does the job you are looking for.