I wrote an own document method and it works. Consider the use of it like this:
document.myMethod();
How can I dynamically find out what dot notations were used before myMethod?
document.getElementsByTagName('div')[0].myMethod();
I tried this but it does not work. Any ideas?
Update: I'm making my own getElementsByClass('class'). So I have to know what elements should be checked. document.myMethod() should check all of the elements but document.getElementById('id').myMethod() only the childs of #id. How do I do that?
First of all, myMethod does not exist on 'all' DOM Elements unless you put it on Element.prototype etc, and you really don't want to go down this path.
But if you do, then this will refer to the Element on which the method is invoked on.
Chaining dot notation functions is (I think) just syntactic sugar - you're basically calling the last function on the output of the previous function. As far as I'm aware myMethod() would have no way to know what the function was that provided it's input was, unless you provided it as some kind of parameter on the function, for instance:
document.getElementsByTagName('div')[0].myMethod('getElementsByTagName');
Why do you want this information?
Related
I was poking around the source code of a website when I came across some code like this:
$($('#newForm_step1')).hide("slide", { direction: "left" }, 0);
and this:
$($($('.breadcrumbs')[0]).children().last()).html("...");
I've never seen the $ (jQuery) function used this way, and I was wondering if there'd be any practical reason to do something like this? To the best of my knowledge, wrapping a jQuery object with a call to $ simply returns a jQuery object for the same selector, and methods on jQuery objects return this, so I don't see why one would need nested calls to $.
No, there is no reason to do this.
In the first example, $($(...)) is redundant. There is absolutely no effect in immediately wrapping a jQuery object in another jQuery object.
The line should read
$('#newForm_step1').hide("slide", { direction: "left" }, 0);
In the second example, $(...)[0] returns a raw DOM element, so it's wrapped again before having jQuery's .children().last() invoked on it. The result of that is already a jQuery object, so there is no need to re-wrap it, and the "unwrapping" could have been avoided by calling .first() instead of [0].
The line should read
$('.breadcrumbs').first().children().last().html("...");
There's no necessary to wrap jQuery object with jQuery. That will just result the same but over-coding and redundant.
But when you have DOM Object then you need to wrap with jQuery so that it will be jQuery object.
Taking your example:
$('.breadcrumbs')[0];//[0] converts to JavaScript Object
Now, if you want to work with jQuery again, you may then wrap with jQuery:
$($('.breadcrumbs')[0]);//is now a jQuery Object
But with this example is unnecessary because you can do just like this:
$('.breadcrumbs:eq(0)');//selects first .breadcrumbs element
However, if you have some DOM Object rather than jQuery object then you need jQuery wrapper to work with jQuery methods.
You must remember this:
JavaScript Object needs JavaScript methods to be chained:
javascriptObject.javascriptMethods
Ex-
$('.breadcrumbs')[0].addEventListener();//javascript addEventListener method
jQuery Object needs jQuery methods to be chained:
jQueryObject.jQueryMethods
Ex-
$('.breadcrumbs').on();//jQuery on method
I am creating a few DOM elements dynamically like,
var anchorElement = jQuery('<a />',{text:property.text});
var liElement = jQuery('<li />',{"class":"navlink_"+i,id:"navlink_"+i});
anchorElement.on('click',property.fnctn);
liElement.append(anchorElement);
parentID.append(liElement);
Where property is a JSON object.
property.text is the text that I want to put into anchor element. (Works fine)
I want to attach a click event handler to that anchor element.
The function that needs to be bound to that element is specified in JSON and we can access it like
property.fnctn
The following line should bind the event handler to the anchor element.
anchorElement.on('click',property.fnctn);
This was not working so I tried converting it into string like,
anchorElement.on('click',property.fnctn.toString());
No Success...
When I click on this link, the error is logged in the console
The object has no method 'apply'.
What is the reason...???
I am able to get it working with a slight work around like
anchorElement.attr('onclick',property.fnctn+"()");
Above statement works, but I want to know why .on() API is not working.
Thanks :)
AÐitya.
Update:
Youve said that property.actfn is a string, "paySomeoneClick". It's best not to use strings for event handlers, use functions instead. If you want the function paySomeoneClick, defined in the string, to be called, and if that function is global, you can do this:
anchorElement.on('click',function(event) {
return window[property.fnctn](event);
});
That works because global functions are properties of the global object, which is available via window on browsers, and because of the bracketed notation described below.
If the function is on an object you have a reference to, then:
anchorElement.on('click',function(event) {
return theObject[property.fnctn](event);
});
That works because in JavaScript, you can access properties of objects in two ways: Dotted notation with a literal property name (foo.bar accesses the bar propety on foo) and bracketed notation with a string property name (foo["bar"]). They're equivalent, except of course in the bracketed notation, the string can be the result of an expression, including coming from a property value like property.fnctn.
But I would recommend stepping back and refactoring a bit so you're not passing function names around in strings. Sometimes it's the right answer, but in my experience, not often. :-)
Original answer:
(This assumed that property.fnctn was a function, not a string. But may be of some use to someone...)
The code
anchorElement.on('click',property.fnctn);
will attach the function to the event, but during the call to the function, this will refer to the DOM element, not to your property object.
To get around that, use jQuery's $.proxy:
anchorElement.on('click',$.proxy(property.fnctn, property));
...or ES5's Function#bind:
anchorElement.on('click',property.fnctn.bind(property));
...or a closure:
anchorElement.on('click',function(event) {
return property.fnctn(event);
});
More reading (on my blog):
Mythical methods
You must remember this
Closures are not complicated
Does anyone know why this would not work in IE7/8?
drop_area = $('div#drop_area');
It works perfectly in IE9, FF2/3, and Chrome. Internet Explorer 7/8 gives the following error:
SCRIPT438: Object doesn't support this property or method
Edit: This is the HTML that goes with my javascript:
http://pastebin.com/nwxx8RzW
IE has a weird behaviour to register some properties in global scope. Elements with an given ID may be accessed simply by using the ID.
So you have a element with the ID "drop_area", it's accessible in IE by using this ID, try:
alert(drop_area.tagName)
..to check it.(should give "DIV")
So what happens: You try to assign something else to this element when using drop_area = $('div#drop_area'); , but this is an invalid operation on an DOMElement.
So use the var-keyword to clarify that you want to create a variable
var drop_area = $('div#drop_area');
or in the case that you have to create a global variable inside a function, assign the variable to the global context:
window['drop_area'] = $('div#drop_area');
The code you've shown on pastebin has numerous global variable issues. In other words, you are coding assuming that variables you are declaring are local in scope, whereas in reality they turn out to be global. Examples include set, box_handle, elements, i, id, drop_area, element, row, image_id, etc. All of your functions are global in scope as well, when they can easily be encapsulated in an other function.
Now I don't know if there's some subtle interactions going on, whether some code has hammering (global) data set by other code, but it certainly seems as if something is getting overwritten and hence methods and properties are disappearing. I would start by going through the code and adding var to local variables. Next I'd be encapsulating most of this code in an anonymous autoexecuting function.
Usually that error shows, that you use jQuery on a website that also uses Prototype. That's why get an error (which is actually throw by Prototype). The other possibility is, that you try to call the code, before the jQuery lib was included into the HTML.
To make sure it's not my first guess, add this code to your JS code:
$.noConflict();
Therefore it is important that Prototype is included into the HTML, before jQuery is included: http://api.jquery.com/jQuery.noConflict/
If you than replace all occurrences of $() with jQuery() and it works, it was the first issue with using jQuery and Prototype at the same time.
Have you got an element with an id of 'drop_area'? ie 6/7/8 auto assigns a global var to the dom element using the element id. Some more code would be helpful.
I have a gallery that I am trying to integrate in my site. I am replacing a and then I want to call the galleries function "function loadGal($)" so the gallery will be rebuilt. But I don't know what kind of parameter to send to it.
Before I changed it, it was called inside "jQuery(document).ready(function($) {"
I just tried to do something like this:
jQuery(document).ready(function($) {
loadGal($);
});
it works fine but I don't know what is the dollar...
The $ is just the name of the parameter. It is nothing special. $ is a valid character of variable names in JavaScript.
However it is often used by libraries such as jQuery or Prototype as it is probably the most characteristic one-letter variable (j or p don't stand out that much) (meaning it is easy to spot and easy to use as you only have to type one character).
The value passed to the ready handler, is the jQuery object (emphasis is mine):
When using another JavaScript library, we may wish to call $.noConflict() to avoid namespace difficulties. When this function is called, the $ shortcut is no longer available, forcing us to write jQuery each time we would normally write $. However, the handler passed to the .ready() method can take an argument, which is passed the global jQuery object. This means we can rename the object within the context of our .ready() handler without affecting other code
but you can name the parameter however you want. You could also write:
jQuery(document).ready(function(foobar) {
loadGal(foobar);
});
Update: And now that I understood the real question ;)
$ is the jQuery object, so you can write:
loadGal(jQuery);
But note that loadGal might not work if it has to work on the DOM elements and you call it outside the ready handler.
Pouring over the release notes regarding jQuery 1.4, I came acrosss $.noop() which is:
Description: An empty function. (added in 1.4)
You can use this empty function when you wish to pass around a function that will do nothing.
Perhaps I'm missing something profound here, but what exactly is a practical use of passing around an empty function?
Code examples appreciated.
This function was proposed due to performance issues on embedded systems when using $.ajax, reported on the jQuery-Dev mailing list. You can see the thread.
Basically, they preferred to introduce and use this single empty function, rather than declaring empty anonymous functions all around.
Now this function is internally used in the ajax, event and offset modules.
You can give a look to the commit when it was introduced also.
If you have a function that accepts a function as a parameter, and you don't have any code to give it, you can pass $.noop.
I can't think of any such cases in jQuery where the parameter isn't optional in the first place, though.
Unlike writing function(){}, passing $.noop will not create a new function instance, saving a bit of memory. However, if whatever you're passing it to modifies the function object (eg, funcParam.id = 2), passing $.noop will mess things up.
Real World Example (well almost):
jQuery.fn.myAwesomeAjax = function(url, complete) {
return jQuery.ajax(url || this.url)
.complete(complete || jQuery.noop);
};
Use it instead of function (){}
Probably if some bad API requires a function as a parameter, and you don't want to do anything in it, this would be a framework-supported way of making that obvious.
I use a couple of plugins which require callbacks, but for some parts I don't actually want to use a certain callback. So, I put in function() {}.
noop is defined in the jQuery source as
noop: function() {}
so it will fit anywhere you'd use a blank function, such as the above example.
The only logical reason is if you're calling a function that does something AND calls another function, and you want the higher-level function to do its thing without calling a parameter function.
Most of the jQuery functions optionally take a parameter function, so you don't have to pass one in. Maybe there's one or two where that's not the case -- or maybe it's to assist developers with their custom code that behaves like this.
If a function requires you pass a function as an argument maybe? It's shorter to say do_something($.noop) than do_something(function(){}).
Although not by much...
...6 characters...
...yeah, that feature looks quite useless actually.
It can be useful if you have a function that supplies functions to other functions.
Example: You have a List of data. Each item has a Button that does something. The "something" can be different for every item. You have a "FunctionFactory" that takes in the item and returns a function. If you don't want the button to do something for whatever reason, then the cleanest way could be to return an empty function, as that way you know that your Factory ALWAYS returns a function.
I don't have a concrete example for jQuery, but I guess this could come in handy when used in an .each or .map block.
It's purely a convenience/replacement for function(){} in the context of where callbacks are required - I don't think I'll be using it anytime soon.
I bet the jQuery team had quite a laugh when they dropped it in though, also serves a comedic purpose.