Javascript Objects and the DOM - javascript

So we all know you can create JavaScript objects quite simply as:
var myObject = new Object() ;
myObject.attribute = someValue ;
myObject.doSomething = someFunction ;
We can then use that object within JavaScript to manipulate the DOM using the standard techniques one would except eg:
document.getEmelemntByID("some ID").someAttribute = myObject.attribute;
Now this is simply using the facilities of JavaScript to query the DOM to find some element and then set an attribute, all well and good. You can do the same thing with jQuery and other tools, all of which are based on JavaScript.
One can call a JavaScript function with any of the various methods the DOM provides such as onClick, onChange, etc. etc.
So my question is how does one actually have a JavaScript object IN the dom, with say a draw method a click method, etc. etc. This would allow DOM to execute the draw method to render something on the DOM canvas and then call a method particular to that object on say click or double click?

The DOM tree is made up of Javascript objects, specifically different kinds of element objects. You can't put other objects in the DOM tree.
The DOM elements uses events for customisable actions, not methods. The click event for example is activated when someone clicks on the element. You hook up a method as event handler for an event, and that method will be called when the event is activated.

You can't make your own types of objects in the DOM and create new browser level events with javascript. You must create one of the types of objects that the browser DOM already supports and use the events that those objects support. It is possible to use native code to create browser plug-ins (like Adobe Flash) that will do some of what you're asking, but I don't think that's what you wanted as those aren't implemented in javascript and require downloads.
You can however use a generic object like a <div> and respond to click events on it in any way you want. Since a div has no default behavior for clicks and drawing, it's just a placeholder in the DOM. You can then embed your own objects inside of it or set properties on it to create whatever visual look you want. And, you can handle the various events on it (clicks, keys, etc...) to give it the desired behavior. So, you can think of a generic object like a <div> as scaffolding which you can build your own object look and behavior on.
There are even ways to put a javascript wrapper around the DOM object so most of your interaction with that object appears to be with your javascript object instead of with the actual DOM object (that's what both jQuery and YUI do). But, underneath, it's still a real DOM object with your own javascript wrapper around it.

Related

How to know what JavaScript functions are bound to an HTML element?

I want to know what JavaScript function is allocated to the events of an HTML element, an input, for example. I would like to check if it has any function bound to the onmouseover, or onclick, or any other event.
In plain JavaScript, that information is not accessible.
So, your options:
Some frameworks like you track event listeners provided you used their syntax to bind them (like jQuery).
Some libraries will "rewrite" how event tracking works (like VisualEvent)
Lastly, you can write your own wrapper around the add/removeEventListener functions, so that it tracks that information in addition to calling the native add/removeEventListener functions. Making sure it wraps all the possible ones, though, can be a challenge.
Inspect your input box in Google Chrome browser, you can check the Event Listeners tab. You can also make use of timeline to track the firing events and effectively use DOM break points.

Javascript properties to jquery variables

I'm making a little script right now and one of the inputs for an arg of the main function is an element. In order to make sure that raw JS works for this stuff I'm doing theelement.value to get the variable's value. Unfortunately, that doesn't work if thelement is a jquery function, like $('#foo'). Some other reasons I need this kind of compatibility is that I need access to theelement.style, once again something jquery doesn't support. I know there are jquery workarounds for these (.css(), .val() etc.) but if I use those, then regular js inputs (document.getElementbyId('foo')) won't work. Is there any way to use one "property" and make it universal against all inputs of elements (including stuff from libraries like prototype and Dojo)?
No it is not possible to make everything universal.
If you want to work on DOM elements, the input needs to be DOM elements and the framworks all have ways of getting the DOM elements out. You can not magically make a script that works with any library out there, that is why generic plugins normally have library specific extensions to add support.
It sounds to me like you have a function that takes an argument and you have issues when you pass different types as that argument:
function doSomething(element) {
// do something with element
}
You've mentioned that you want element to sometimes be a jQuery object and sometimes just a DOM object and then you also mentioned other libraries too (prototype, Dojo).
First off, your problem will go away entirely if you just call your function with a consistent type. The simplest type here that is available in all libraries is a DOM element. So, if you just enforce that element is passed as a DOM object reference and not a jQuery object or any other library object, then your problem will go away entirely. If the caller is using some other library and then wants to call your function, they can always get the DOM object from that library and pass the actual DOM object. For example, in jQuery, you can get a DOM object like this `$("#foo").get(0)
If you want to make it more universal and accept multiple types, then you have to write code to detect each type that might be passed and get the DOM object out of each type so you can then process them all identically. For example, if you wanted to detect either a jQuery object of a DOM object, you could do so like this:
function doSomething(element) {
// normalize element to be just a DOM object
// if it's a jQuery object, then reach in to get the first DOM object
if (element.jquery) {
element = element.get(0);
}
// do something with element here which is a DOM object
}
If you wanted to detect objects from other libraries too, then you'd have to write similar detection code for each other library and get the actual DOM object out of that other library's object.

Why is jquery's .data() method needed

In the following getElementsByTagName("p")[0] and getElementById("demo") access the same element.
Both of the following work, so I can't figure out why the jquery data function is even needed. Is the second not portable to all browsers.
$(document.getElementsByTagName("p")[0]).data("funcZ", function() {console.log("ZZZZZ")})
$(document.getElementById("demo")).data("funcZ")()
document.getElementsByTagName("p")[0].funcX = function() {console.log("XXXXX")}
document.getElementById("demo").funcX()
According the the jQuery website:
The jQuery.data() method allows us to attach data of any type to DOM elements in a way that is safe from circular references and therefore free from memory leaks. jQuery ensures that the data is removed when DOM elements are removed via jQuery methods, and when the user leaves the page.
It's possible that by attaching random fields to a DOM element, when the DOM element disappears, the fields remain in memory. It looks like jQuery handles that for you.
The $.data() method is perfect for hiding data as opposed to attaching it to a data-attribute. It's easily accessed by key/value, great for storing state information when creating plugins, or really anything.

Is there a good way to attach JavaScript objects to HTML elements?

I want to associate a JavaScript object with an HTML element. Is there a simple way to do this?
I noticed HTML DOM defines a setAttribute method and it looks like this is defined for arbitrary attribute name. However this can only set string values. (You can of course use this to store keys into a dictionary.)
Specifics (though I'm mostly interested in the general question):
Specifically, I have HTML elements representing nodes in a tree and I'm trying to enable drag-and-drop, but the jQuery drop event will only give me the elements being dragged and dropped.
The normal pattern for getting information to event handlers seems to be to create the HTML elements at the same time as you are creating JavaScript objects and then to define event handlers by closing over these JavaScript objects - however this doesn't work too well in this case (I could have a global object that gets populated when a drag begins... but this feels slightly nasty).
JavaScript objects can have arbitrary properties assigned to them, there's nothing special you have to do to allow it. This includes DOM elements; although this behaviour is not part of the DOM standard, it has been the case going back to the very first versions of JavaScript and is totally reliable.
var div= document.getElementById('nav');
div.potato= ['lemons', 3];
If you're already using jQuery, you can use its data() method for this. This allows you to assign complex objects to the element if you want or you can leverage that method to hold a reference to an object (or some other data) at the very least.
It's worth noting that, under the hood, jQuery implements data() in precisely the way that bobince described in his answer, so you always use that directly, whether or not you're using jQuery.

Trying to wrap my head around custom events

I'm trying to get my head around custom events. I understand how to register and trigger custom events. However, it seems like its not possible to register truly custom events. Everything has to trace back to a DOM event like click, onload, blur, etc. Or am I wrong?
For example, suppose I have an array. I want to register an event that fires when the length of the array changes. To my understanding, I would have to register the event and then create a setInterval timer that checks the current array length against the previously stored length. If the length has changed, I would then need to trigger my custom event from inside the setInterval.
Is there a way to register an event for my array and have it fire automatically when the length changes?
Custom events are in the W3C spec, but none of the major browsers support them. This is why several other users have suggested 3rd party libraries. Prototype, YUI, JQuery, and most others have these capabilities. You can also roll your own.
If you'd like to see what some custom event syntax might look like, you can take a look at this tutorial for Prototype custom events. Some important points:
Prototype custom events must be attached to DOM elements, so that they can bubble like native events.
They must be in a prefix:event syntax in order to fire
They can contain a highly-useful memo parameter that allows any arbitrary context or set of objects to bubble with the event.
why don't you write a method addElement for your array that you'll use whenever you want to insert elements,that way you will be able to write code in the event of array.length change.
same thing with removeElement.
Events are not meant to be used for this kind of thing.

Categories