I'm inexperienced with javascript/jquery. I was reading the docs for http://api.jquery.com/mouseover/ where it states:
The mouseover event is sent to an element when the mouse pointer enters the element. Any HTML element can receive this event.
1) What sends the event to the element ?
2) Is the event 'stored' in the element? I'm imagining that each HTML element in the DOM is treated as an object and the presence or absence of the event is a property of the object.
The browser itself generates the event, which is a special object implementing the Event interface and it is passed to the handler function as an argument. The event is not stored in the element, it is created by the engine.
You are on the right rack, this link should help you better understand Javascript and how browsers operate. It is the documentation for the DOM Level 2. This is when functionality to allow scripts and other programs to dynamically access and update various sections of content and structure of the DOM was added. It includes a list of the various interfaces that were introduced.
HTML elements on their own implement an interface called the HTMLElement, which is the base interface for HTML elements, either directly or indirectly through an interface that inherits it.
Elements themselves are interfaces that represent an object within the document. The Element interface lays out various properties that are common for numerous kinds of elements.
There are a couple of different interfaces within the web platform.
It's always a plus to look up these various interfaces and learn how they interact. The Document is a great starting place.
Related
I'm new to web components, and I've noticed some examples set the dom in the custom-element's constructor, while others do it in the connectedCallback.
As both seem to work fine(although I tried only Chrome), I assume the main difference is the case in which a user creates the element in js and not attaching it to the page?
I guess the main question here is whether I'm missing some other reason to prefer one method over the other.
Thanks.
Best practices and rules for custom element constructors
What's safe to do in the constructor
In the constructor, it's safe to
create the shadow root;
create and append elements *;
attach event listeners to those elements (scoped to your own ShadowDOM);
create attributes * (which might still be a bad idea because in the dynamic creation case this might come unexpected).
What you cannot do in the constructor
In the constructor, you are not allowed (amongst other things)
to read any attributes you haven't created beforehand...
to access child elements...
...because those might not be present in the non-upgrade case, and definitely won't be present when you dynamically create your custom element using either document.createElement('my-custom-element') or new MyCustomElement.
What's unwise to do in the constructor
In the constructor, you probably don't want to
attach event listeners to elements outside of the component's shadow DOM (like e.g. document, window), because these are the kind of listeners you should clean up in your component's disconnectedCallback (which will be called when e.g. your component is moved in the DOM).
Attaching these listeners in the constructor and properly cleaning them up in the disconnectedCallback results in missing listeners once your component gets removed from (and later re-added) or moved in the DOM.
*Pitfalls and things to be aware of
You need to be aware of the custom element lifecycle to not fall into otherwise obvious pitfalls, which include:
If you add attributes in the constructor and have included those in your component's observedAttributes, remember this will immediately trigger the attributeChangedCallback for those attributes, even if you element is not yet connected (a.k.a. in the DOM).
If you create and append other custom elements into your component's shadow DOM, remember this will trigger those components' connectedCallback.
In part, these best practices and rules follow https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance, in other parts they deviate from recommendations done there in the spec.
Specifically I disagree on the following (given the scope for the listeners is outside the component), for the reasons I gave above.
In general, the constructor should be used to set up initial state and default values, and to set up event listeners and possibly a shadow root.
I have a question on how we can possibly figure out which elements, among existing ones on the DOM, have an attached function through 'EventListener'. I know that it is not easy at all and I know that I can check it using Visual Event.
But, I would like to know how Browsers or even more interesting, how Visual Event can detect that?
Let's say we are going to load a webpage and extract all the clickable elements from the DOM. How possibly we can determine that some of the existing elements won't change the status of the DOM?
For example, if we don't know anything about the elements, we would need to try to click even on P tags since there might be some functions attached to those. But, if we can determine whether or not this particular element will do anything after clicking on that, then we would be able to ignore it if it is not going to do anything.
Is there any straight way by which we can do something which Visual Event is doing?
There are no built-in functions that support this.
The neatest way I know of is to overwrite the addEventListener method on Element.prototype with your own method that records the additions/removals of event listeners on DOM nodes. You can then expose a function to enumerate them.
This modification will of course need to be run before the relevant event listener activity in your application.
See How to find event listeners on a DOM node when debugging or from the JavaScript code?
Note that Chrome has built in support for this functionality via getEventListeners and a dedicated UI in the dev tools.
Hi I really could do with a point in the right direction with this question.
I'm trying to fathom object orientated javascript, but am having trouble getting my head around binding dom elements to objects.
I would like to make a little animated widget type thing for my web page. the widget will be just simple drop down tabs , (like tabs from an actual folder) I want the tab to drop down a bit with a mouseover event then raise up with mouseout.
here is my current implementation, it doesnt work well at the moment it's just a mock up
http://bombinglish.com/
I want to make a class for the tabs , which will include the open and close animation methods, methos to add events, and other necessary fields. then instanciate a new object for each tab. but how do I do I tell each object that it must must respond to the corresponding mouse events, or to put it another way how do I bind the DOM element to the object?
If you are using Javascript just for presentation logic, then I don't think it's worth anything to try and get wild with OO.
If you have that at the top of every page, you could simply label the tabs with a unique class name. Then in your Javascript file you bind a mouseover event on every DOM element with that class name.
Perhaps, others have differing opinions on this however.
I am in the process of creating a huge web application, with a JavaScript based UI, and many events generated continuously.
To avoid bad performance due to the huge amount of the event listeners needed, I of course opted to use a single event listener which will catch all the events generated from the children elements (event bubbling).
The problem is, this application is designed in such a way that one or more modules can be loaded into the main JavaScript library I'm coding (which is responsible for controlling the UI and every other aspect of the program). Of course every module should be completely independent from each other, so you can choose which methods to load, without affecting the general functionality of the library, only adding or removing features.
Since every module can operate in different DOM elements, I need to have at least a single event listener for each module, since two modules can listen for events generated by html elements placed in different DOM branches.
http://jsfiddle.net/YRejF/2/
In this fiddle for example, the first button will let the first paragraph trigger an event, and its parent will catch it. The second button will let the second paragraph fire the event, but the div listening for the same event won't catch it, because it's not fired from one of its sons.
So my question is: is it possible to have a single event listener, able to listen also to events triggered from elements that are not its sons (elements placed everywhere on the page)?
I was thinking about having a js object, or a dom node, which store the data of the element which triggered the event, and the event itself, then a general event will be fired on the global event listener (no matter where it's placed in the dom), and it will then read the data to discover which element generated which event, and act accordingly.
Any help or suggestion about better ways of achieving this?
jQuery has a special binder for this kind of cases: live(). It let's all events bubble to the document and then handles them accordingly. However, if you use div or other containers for different panels etc, maybe using delegate() makes more sense. Don't worry too much about the number of bound elements. Believe me, it will run as well with 50 binds or 10 delegates as it will with 1 live.
It seems like there should be, but I've looked over the API and nada. I don't see how it's done in 2.x. Currently, I store references with the elements to the tab and tabview objects via jQuery's data method.
The why: When I interact with the tabs via mouseovers and clicks, I need to be able to reference the YUI tab/tabview objects' properties & methods. Since I'm using event delegation b/c I have so many tabs (tabs within tabs), I'm not directly attaching (potentially hundreds of) event listeners, and thus I don't have access to the tabs and tabviews via the this symbol.
There's a corresponding method for buttons (YAHOO.widget.Button.getButton) but not one for tabs unless I'm missing something obvious.
Additionally, it seems that if I have a tab object, there's not a reference to the tabview. Once again, I create my own reference, but I assume there should be a reference or an accessor method already.
Can anyone shed any light on this? Anyone else approaching this differently?
The best place for YUI questions are the forums on yuilibrary.com.
The YUI TabView component has event delegation built-in. Every Tab event is actually handled by the TabView that it belongs to. Each events is routed to the appropriate Tab, and the context of the handler is set to the Tab.
This allows you to assign your listeners as you normally would:
tabview.getTab(1).on('mouseover', function(e) {
console.log(e.target.innerHTML); // e.target === Tab Label Element
console.log(this.get('label')); // this === Tab instance
});
This works for nested TabViews as well.
There is currently no binding between Tab and TabView except for the TabView's "tabs" attribute. You can iterate this collection and compare your element to each Tab's "element" attribute if there is a use-case for knowing which TabView it belongs to.
have you tried using Firebug, using the DOM tab/DOM subpanel, and actually looking through the attributes/properties/methods on the document and/or related elements? It's usually the fastest way to see what you can access.
also worthwhile to do a for..in loop to enumerate all of the properties/methods of a returned object if you are unsure what is available and unable to get that info via firebug.
e.g.
var properties = "";
for (prop in obj) {
properties += prop+"\n";
}
alert(properties);
This is true in most cases, not just your particular question.
EDIT
Having just checked the YUI examples for tabview, I see there is no property on the DOM elements for the tabs that refer to JS objects. I suppose this has been done to avoid DOM pollution, but it looks like you may have to make those reference yourself when creating the tabs/tabviews
e.g.
var tabView = new YAHOO.widget.TabView('demo');
document.getElementById("demo").tabView = tabView;