Is "remove" a reserved keyword in Google Chrome? - javascript

I have an interesting problem, and I think I got to the root of it, but I wanted to be sure. I have a link that calls a function called remove(). All browsers except Chrome had no issues with the function. However, the link that is clicked disappeared in Chrome, even when I simplified the function as in the example below. I have seen this question: Can't use "download" as a function name in javascript. In the links, however, I did not see anything about "remove" as a reserved keyword. My question is this, I am correct about this being a keyword? If so, is there anywhere I can find a list of Google keywords? I have searched and have not found this to be a problem anywhere else.
Remove
Javascript:
function remove(){
alert("Hi");
}

Elements in Chrome have a .remove() method which allows for self-removal of an element instead of having to do it from the parent.
The trouble is that when using attribute handlers, you get a different scope chain. That scope chain includes the element itself, as well as the document. This means that all properties of the element and document show up as variables.
Because you named your function remove(), and because it's a global function/variable, it is being shadowed by the .remove property (now variable) on the element itself. This can be seen with an alert. If you change your handler to:
onclick="alert(remove)"
...you'll get something like:
function remove() { [native code] }
So it's not that it's reserved, but rather that it's used as a property which ends up shadowing the global.
To fix it, either use the global directly:
onclick="window.remove()"
Or change the function name.

I can't find any documentation on it, but DOM elements in Chrome have a native method remove that apparently removes them. In onclick, this actually refers to the element itself so it ends up calling this.remove() which removes the element. To get around this, you can just call window.remove() instead.
http://jsfiddle.net/3YkZH/1/
It would also be better to use standard event binding via addEventListener which does not have this problem when simply calling remove:
http://jsfiddle.net/3YkZH/2/

I had no issue in chromium using it, well not in this manner
Remove
function remove() {
alert("Hi");
}
document.getElementById("remove").addEventListener("click", remove, false);
on jsfiddle
Inline javascript is considered bad practice.
If you have more elements using the same function, just add more lines, like this
document.getElementById("remove1").addEventListener("click", remove, false);
document.getElementById("remove2").addEventListener("click", remove, false);
document.getElementById("remove3").addEventListener("click", remove, false);
document.getElementById("remove4").addEventListener("click", remove, false);
or you could get a nodelist and loop through that
var nodelist = document.querySelectorAll("[id^=remove]");
Array.prototype.forEach.call(nodelist, function (element) {
element.addEventListener("click", remove, false);
}
You can take a look at another answer here on SO to find out more about the differences between event binding methods, also do a little G searching on the subject will give you further information. And of course, you would have avoided the issue that you were experiencing by doing it in this manner.

Related

removing onClick from dynamic elements

Should I be removing dynamic clickHandlers to the dynamically created html tags or is it taken care of automatically by the garbage collector.
My primary browser is Safari (embedded in iOS app), but I think i read that IE has memory leak problem around this.
var li = document.createElement('li');
li.addEventListener('click', function(){});
so if this element was removed from DOM later on, should I delete the clickHandler, just in case please let me know how to property delete a clickHandler?
li.removeEventListener("click", function_name);
This will remove the event listener
Source: http://www.w3schools.com/jsref/met_element_removeeventlistener.asp
For anonymous functions, the point of them is really to have no reference and lacks a name, so for removeEventListener() you will need a named function.
If there are no references remaining to the element after you remove it, the GC should clean up handler functions that it references. So you shouldn't need to do anything.
But if IE has a bug along this way, you can use removeEventListener to remove the handler, but this requires that you use a named function, since you have to give the same function to removeEventListener as you did when you called addEventListener, and anonymous functions will never be the same as each other.
function myClickHandler {
...
}
var li = document.createElement('li');
li.addEventListener('click', myClickHandler);
...
li.removeEventListener('click', myClickHandler);
myClickHandler = null;
li.parentNode.removeChild(li);
myClickHandler = null; is needed because otherwise the function name will hold a reference to the handler function, so it won't be GCed.
If you have multiple LIs, and they're all using the same handler function, it shouldn't be necessary to do this. No matter how many LIs you have, they're all just referring to the same function, so it doesn't take up lots of memory.

Why not passing "this" instead of using document.getElementById() in JavaScript

I started learn JavaScript and in some tutorials I saw that was used document.getElementById() and in some tutorials in same case was used "this" that was passed from control that fired the event.
Maybe someone can explain why should I prefer one way over an other?
Thank's a lot
Are you referring to the documentation from this MDN page on addEventListener? Make sure you look at the section on the value of this within the handler. The earlier examples use document.getElementById to look up an arbitrary element. For example, you could attach a click handler to a button (or any other element), that modifies some other element when it is clicked. In this case, you don't really do anything with the object that generated the click event. So in the handler, you will use document.getElementById to modify the element you want.
However, in some other cases you would like to modify the element itself. For example, you might want to change the color of an element the user clicks on, to let them know that its state has changed (a toggle basically). In this case, you want access to the element that actually generated the event, and you can do that by using this. Here this means "I am the HTML element who generated this event".
In a more general context, this can have different meanings, and it depends on the use case. In the context of event handlers, this means the element that generated the event. In other cases, such as in object-oriented JavaScript, this in a function can refer to the parent object of that function. JavaScript is flexible enough that a function can have whatever this value the author decides. In well-written code, this has a meaning that generally makes sense, and usually refers to some sort of "owning" context or object.
Functions assigned as Events have their this context as the Object to which the Event belongs. In other words, the Element itself.
// you can get Element a number of ways including document.getElementById('idHere')
function someFunc(){
this.style.color = 'blue';
}
Element.onclick = someFunc;
or
Element.addEventListener('click', someFunc);
or
Element.onclick = function(){
this.style.color = 'blue';
}
or
function someFunc(context){
context.style.color = 'blue';
}
Element.onclick = function(){
someFunc(this);
// more code here
// could use document.getElementById('whatever') to get HTML Element with id='whatever'
}

using this rather than $(this) in an .each() call

I've done quite a lot of reading this past day to get a deeper understanding of this vs. $(this) and how JS determines this as it interprets, but I still can't figure out one detail of a plugIn I'm analyzing to deepen my knowledge:
$.fn.plugInName = function(options) {
return this.each(function() {
new $.plugInName(this,options);
});
};
Everything I've read indicates that although this.each() is used to call JQuery.prototype.each(), each object should be referred to as $(this) within the each() function, but the above uses regular ol' this, and I can't figure why. The $.plugInName declaration looks like this:
$.plugInName = function(el,options) {
...
}
Any insights anyone may have will be a big help.
EDIT: Here's the full source on GitHub
From MDN:
When a function is called as a method of an object, its this is set to
the object the method is called on.
When you call something like
$('#myDiv').plugInName()
the function is called as a method of the jQuery object $('#myDiv'). So, in this case, this already refers to a jQuery object, thus we don't need the extra $() wrapper.
A common case when we do need $() is when binding events.
$('#myDiv').on('click', function(){
alert('You clicked my div!');
});
The difference here is that the function is called not on $('#myDiv'), but the DOM element that it belongs to. So, here this is a DOM object, not a jQuery object.
Inside the callback function passed to each, this refers to the DOM element, it is not a jQuery object.. which is just what $.plugInName wants. It expects a DOM element.

How does the onmouseover attribute know to accept an event object?

I was looking at this basic example below (which makes all images in the DOM semi-transparent on mouseover), and was confused as to how an arbitrary function, such as handleMouseOver, receives an event object if you give it an argument.
How is it that the act of assigning such a function to the onmouseover attribute tells it to modify this function in this way, as there's nothing inherent in the function definition itself that says: "please pass me an event"? Is the assignment operator being overloaded somehow? Or is the browser doing some extra work here? I would really appreciate a link to a detailed explanation of this phenomenon because it doesn't seem to make any sense looking at it as pure JavaScript (to me at least!)
function handleMouseOver(e) {
e.target.style.opacity = 0.5;
}
function handleMouseOut(e) {
e.target.style.opacity = 1;
}
var elements = document.getElementsByTagName("img");
for (var i = 0; i < elements.length; i++) {
elements[i].onmouseover = handleMouseOver;
elements[i].onmouseout = handleMouseOut;
}
Lets break it down by taking one browser's example. IE'S OnMouseOver Event for instance.
In the remarks section it says it passes IHTMLEventObj for ALL events even for the events that don't require it such as Body.OnLoad.
When we go into IHTMLEventObj's detail, we read the following remarks
Although all event properties are available to all event objects, some properties might not have meaningful values during some events
So, Event object is passed regardless; you have to access the object in some specific events and get event-specific properties to get event-related data.
onmouseover, for example, is an event handler. When the event handler needs to be called (in this case when the browser javascript engine decides it) then it will call it be passing it some pre-determined arguments (all good documentation will explain what those arguments are). Your use of those arguments is optional however.
This can be demonstrated with a manual function call like so:
function myFunction(e){
alert(e.myProperty);
}
//assign the handler
var handler = myFunction;
//when required, create event parameter data and call the function assigned to the handler
var myE = { myProperty: "some data" };
handler(myE);
It is not "exactly" how it works (because I don't know how browsers have chosen to implement their code), but it shows the concept.
Here is an example in action
Not only the event object is passed, but also the this value within the function is set to the event target. This is done by the browser, and dictated by the DOM specification.
EDIT:
I was hoping to find something more detailed in the DOM specification (I'm sure I've seen that before), but so far I found this:
In JavaScript, user-defined functions are considered to implement the EventListener interface. Thus the Event object will be provided as the first parameter to the user-defined function when it is invoked. Additionally, JavaScript objects can also implement the EventListener interface when they define a handleEvent method.
https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#glossary-event-handler
By the way, the last sentence is talking about an interesting way to bind event listeners, in an OO context.
You can pass whatever arguments you like to any JavaScript function.
Defining them in the function definition just means you have a named, local variable to access them with.
That is to say:
function foo() {
}
foo("hello");
… won't throw an error.
When a function is treated as an event handler (which is what code provided by the browser will do if you assign a function to the onmouseover property of a DOM node) then the event object will be passed as an argument.

First parameter to event handler

If I have some event handlers registered inline with my markup (deprecated, I know) like
span id="..." onclick="foo(p1,p2,p3)"
how can I access the "event" object in the event handler function foo? Changing the above to
span id="..." onclick="foo(event,p1,p2,p3)"
and then using it in foo like:
function foo(e,p1,p2,p3)
{
if (!e) e = window.event;
}
seems to work but I don't see it documented anywhere so I am wary of using it. In other words, is the first parameter to a inline event handler always the event object if it is named as such in the onclick=... markup? Is this cross-browser so it can be safely used? And if it is not named as such (as in my first example), the parameters are treated like regular parameters and the event object is not passed?
Thoughts?
You're misunderstanding your code.
The string that you put in the inline handler is a normal piece of Javascript code. It does not need to be a single function call; it can even contain multiple statements (separated by semicolons, as usual)
The code in the inline handler will be given a variable called event which refers to the event object.
When you write onclick="foo(event,p1,p2,p3)", you're making a regular function call, and passing the values of four variables named event, p1, p2, and p3 as parameters to the function.
Take a look here. This seems to line up with your example. However, there is some mention of this not working the same way in IE, so you have to check whether the first argument (event object) is defined and if not use window.event.
Another reference here. I frequently find MDC to be helpful.
Ok, so I ran a few tests in Firefox (3.5.8/linux) and here's what I've come up with. I was unaware of 'event' being used like in example 2, but it seems to work correctly in Firefox. However, it is NOT the case that the first variable passed to a function is always the event. 'event' seems to be registered in some global object, but I can't seem to determine which one. (It's not document, or window :P)
The line of code that you have in the foo function
if (!e) e = window.event;
is basically how you have to catch events in Internet Explorer anyway, so it will work in IE and Firefox for sure. And yes, therefore, if you are not passing a variable called 'event', as in your second example, the parameters will be treated as normal parameters, and the event object will not be passed.

Categories

Resources