Javascript - Need an Underscore in Function Name? - javascript

I don't have any trouble with this code but I am very curious as to why the function below seems to need an underscore in its name.
function _clear()
{
document.getElementById("test").innerHTML = "";
}
The function _clear() only executes after clicking the button if the function name contains an underscore.
<button type="submit" onClick="_clear()">Clear</button>

According to the MDN, clear() is a method of the Document object, which one might call by writing document.clear(). But, since this method is deprecated one ought not to call it at all. In fact, in HTML5, the method does nothing (see HTML5 spec).
So, until this method is actually removed from the Document object, one might conclude that a potential conflict exists in having a user-defined function with the same name as that of the Document's method. That said, the following code runs just fine using Google Chrome (Version 49.0.2623.112 m):
var d = document;
d.g = d.getElementById;
function clear()
{
d.g("test").innerHTML = "";
}
var test = d.g("test");
test.onmouseover=clear;
See demo
It's unlikely that there is a conflict between clear() and document.clear(). I wrote a user-defined function that uses the same name as another document method and the code ran flawlessly; see here.
Apparently, when the onclick event attribute is given the user-defined function "clear()" there is some kind of confusion with clear() being associated with document.clear(); see here and read the excellent explanation in the official answer. In brief, the issue boils down to "...the Document object is in the scope chain before the Window object (...)" (see JavaScript: The Definitive Guide).
If for some reason you were determined for the code to work, here's how to specify the correct context:
HTML:
<div id="test">a test to see if this will clear</div>
<button id="but" onclick="window.clear()">Clear</button>
So, the user-defined function actually becomes a method of the Window object, along side the built-in ones like window.open(), allowing the code to execute; see here.
Note, the best way to have an action occur when a click event occurs is to put this line in your JavaScript code given a button with an id of "but":
but.addEventListener('click',clear);
See demo.

That's because clear() is a function that already exists in JavaScript. You could also add the underscore to the end or add another c or do anything so that the function has a different name.

Related

Using "this" as an argument

I have an onclick function to navigate from one "page" to another (it's not actually navigating, just imitates it):
$('.button').on('click', function(){
$('.home').css('display','none');
var newPage = $('.'+this.id);
goTo(newPage);
});
goTo simplified for reference:
function goTo(page){
$(page).css('display', 'block');
}
This works perfectly fine. All of the navigation buttons have the class of button, and also an ID that matches the class name of the different "pages". Click #page1, display .page1, etc.
My problem is now I'm having to rewrite my code to do the same thing for other elements - trying to rewrite this with arguments doesn't work for this in particular.
Here's what I'm trying:
function goToPage(link, destination){
link.click(function(){
$('.home').css('display','none');
goTo(destination);
}
}
and calling it as:
goToPage($('#page1'), $('.page1'));
works fine, however:
goToPage($('.button'), $('.'+this.id));
doesn't.
I suppose I'm misunderstanding how "this" is working in this context. I thought it would only determine what "this" is when the argument is called.
So my question is: can "this" be used as an argument in this way, am I slightly off with the logic or am I a complete idiot?
Fiddle: https://jsfiddle.net/hek0ptca/13/
To explicitly answer your question, no, this cannot be used as an argument in this case because it points to nothing.
goToPage($('.button'), $('.'+this.id));
In this context, this points to "undefined". Try running console.log(this.id);at the same scope of the code mentioned above and check your browser's console. It returns "undefined".
A good way to think about this is that you need something for it to reference. Scope matters. If there is nothing for this to reference, you will always get "undefined" as a value. Typically this is used inside a function where an object has already been referenced, for example, inside your event handler:
$('.button').click(function(){
$('#home').css('display', 'none');
goTo($('.'+this.id));
});
This will work in this case because this will refer back to the object that is being operated on, the .button class.

Is attaching an onchange object a closure?

I have searched prior SO posts here, here and here, and couldn't an answer that made sense to me. This should be a basic question, but I'm not understanding the posts I find. They don't seem to address using a this parameter.
I want to programatically add an input with an onchange event, such that the final result is this:
<input type="button" onchange="handleButtonOnChange(this)">ClickMe</input>
I am working on a project that is using an embedded IE6 browser inside a old Delphi application, so I have to have a solution that is IE6 compatible (yes, IE6 is horrible, but there are reasons I am stuck with it for now).
My initial attempt was this:
var DaySelect = document.createElement("select");
DaySelect.id = ParentID+"-day";
DaySelect.disabled = true;
MonthSelect.onchange="handleDayChange(this);" //<--- not correct
Parent.appendChild(DaySelect);
I then read that the .onchange should be assigned an object, not a string, and one should use this instead:
MonthSelect.onchange=handleDayChange; //<--- '(this)' removed
But it seem to me that this will result in this element (notice the missing this parameter)
<input type="button" onchange="handleButtonOnChange">ClickMe</input>
If I use the line below, instead, won't this make a closure, and the 'this' will refer to the event at the time the object is assigned to the .onchange property, instead of being the event at the time of the change event?
//Does the line below make a closure?
MonthSelect.onchange=handleDayChange(this); //<-- What does 'this' refer to?
I'm a relatively new web programmer, but long time Delphi programmer. Closures still make my head hurt. I appreciate any help in this.
Also, I read here about using addEventListener and the problems with older versions of IE, and the last post on the page provides a work around. But I don't understand how it works.
EDIT -- And what about passing other parameters? It seems that many event handlers will need to have parameters specific for the attached element. It seems that it is just not possible to add a listener with any parameters.
A simple closure if you are creating the elements in JS as you show:
var DaySelect = document.createElement("select");
DaySelect.id = ParentID+"-day";
DaySelect.disabled = true;
MonthSelect.onchange=function(){handleDayChange(DaySelect);};
Parent.appendChild(DaySelect);
Since the function is created inside the scope that you create the element in, the same variables will be available to it.
EDIT:
Additional parameters can be passed with this method, for example, the anonymous function we create and attach as the handler will still have the event object sent to it:
function(e){handleDayChange(DaySelect, e);};
In the event object you will have access to the event target, but in your example the event target and "this" are not the same element, so there would be no way for the handler to know about the DaySelect element.
jQuery makes a lot of event handling much simpler which is one of the reasons many people use it, it also normalizes it's methods between various browsers so you don't have to write multiple versions of the same code (in most cases)

VBA IE call a javascript containing 'this' keyword

I am attempting to call a javascript function on a webpage that contains the 'this' keyword which is referring to the <input> textbox on the webpage. The function looks like this:
functiondostuff('hdnAttribute',this,'Key')
Using
js = "functiondostuff('hdnAttribute',this,'Key')"
Call IE.Document.parentWindow.execScript(js)
doesn't throw an error but does not produce the results of the function since this cannot be identified.
Stepping through the website this = [object DispHTMLInputElement] instead of the element name while the function is running. Anyone have any ideas?
Good Morning,
Adding more to this issue. There seems to be two problems, 1st is setting the window.event, functiondostuff begins with: if (window.event && window.event.keyCode == 13), when the function is called it exits out immediately due to the event being null. Is there a way to pass the event as 13 to the website? The second issue is submitting the "this" HTMLInputObject.
Does anyone know a method to fire the 'onkeypress' event? I am at the point of trying sendkeys to avoid calling the function but have not been able to get them to work with IE. Thanks for any suggestions!
Key point is context. If you have this HTML
<input onclick="functiondostuff('hdnAttribute',this,'Key')">
then the browser can infer context from the user interaction and set this for you correctly.
From within VBA that's a slightly different matter and you have to define context manually.
How about this:
Dim js As Variant
js = Array( _
"var input = document.getElementById('yourElementsId');", _
"functiondostuff('hdnAttribute',input,'Key');" _
)
Call IE.Document.parentWindow.execScript(Join(js, vbNewLine))
This way you get to define context yourself.
document.getElementById was just for the sake of the example. If your element has no ID, use any other method (like DOM traversal, document.querySelectorAll, document.getElementsByTagName + a loop, ...) to get a reference to the desired element.

Howto: generic test to see if widgets call this.inherited succesfully?

I maintain a custom library consisting of many dijit widgets at the company I work at.
Many of the defects/bugs I have had to deal with were the result of this.inherited(arguments) calls missing from overriden methods such as destroy startup and postCreate.
Some of these go unnoticed easily and are not always discovered until much later.
I suspect I can use dojo\aspect.after to hook onto the 'base' implementation, but I am not sure how to acquire a handle to the _widgetBase method itself.
Merely using .after on the method of my own widget would be pointless, since that wouldn't check whether this.inherited(..) was inded called.
How can I write a generic test function that can be passed any dijit/_WidgetBase instance and checks whether the _widgetBase's methods mentioned above are called from the widget when the same method is called on the subclassing widget itself?
Bottom-line is how do I acquire a reference to the base-implementation of the functions mentioned above?
After reading through dojo's documentation, declare.js code, debugging, googling, debugging and hacking I end up with this piece of code to acquire a handle to a base method of the last inherited class/mix-in, but I am not entirely happy with the hackiness involved in calling getInherited:
Edit 2 I substituted the second param of getInherited with an empty array. While I actually get a reference to the method of the baseclass using aspect doesn't work. It appears this approach is a bust.
require(['dijit/registry','dojo/_base/declare','mycompany/widgets/widgetToTest'],
function(registry,declare,widgetToTest)
{
var widget = registry.byId('widgetToTestId');
var baseStartup = getBaseMethod(widget,'startup');
function getBaseMethod(widget,methodName){
return widget.getInherited(methodName,[]);
}
//This is the method body I want to use .after on to see if it was called, it returns the last overriden class in the array of inherited classes. (a mixin in this case, good enough for me!)
alert(baseStartup);
});
I have given up trying to use dojo/aspect.
I have instead opted to modify the code of our custom base widget to incorporate snippets such as the one below. They are automatically removed when creating a release-build in which console-calls and their content are removed:
console.log(
function(){
(this._debugInfo = this._debugInfo|| {}).postCreate=true;
}.call(this)
);
A simple method in boilerplate code I added near the unittests is available so that I can call it on all mycompany.widgets.basewidget instances in their respective unittests.

Javascript creating references to native functions

I have written this code (this is a snippet) that doesn't seem to be working. I have isolated it to here.
grab = window.document.getElementById;
grab("blueBox") // i.e. grab("blueBox").onclick [...]
Is it possible to create references to native function in javascript. I am doing something with the grabbed element, I just left it out for example. The grab function doesn't seem to work.
I am using FireFox's most recent version
The way you're doing it will mess up the assignment of the this value for the function.
grab = window.document.getElementById;
grab("blueBox") // i.e. grab("blueBox").onclick [...]
here this will be the global object. Try:
grab.apply(window.document, ["blueBox"])
or in newer browsers:
grab = window.document.getElementById.bind(window.document);
to get directly define what this will be.
The first step here is always the JavaScript console. Firebug is your friend. Tell us the error message if it doesn't mean anything to you.
In the mean time, here is a workaround:
var grab = function(id) { return window.document.getElementById(id); }
function grab(id) {
return window.document.getElementById(id);
}
grab("blueBox");
The reason is because the function getElementById is not being called as a method of document, so its this keyword doesn't reference the right object. Using call as suggested in other answers shows that when this references the document, getElementById works.

Categories