jQuery selector does not work in IE7/8 - javascript

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.

Related

Use passed variable name as part of another variable name

blah('A');
function blah(letter){
arrayA.push('something');
}
I want to push something to an array where the name of the array is 'array' plus a letter being passed to it.
I can console out 'arrayA' fine:
console.log('array'+${letter})
But if I try to build the array name, the same logic doesn't work:
array${letter}.push('something')
In the browser (where the global objects, functions, and variables become members of the window object) you can create and access dynamically named objects using the bracket notation.
Were you looking for something like this?
function blah(letter){
window['array' + letter] = [];
window['array' + letter].push('something');
}
blah('A');
After this you can access and use the newly created array (arrayA) as usual.
arrayA.push('something else');
In node you can probably achieve this using global instead of window.
Try it and forget it (or replace the 3 occurrences of window with global for testing with node.js):
function test(name,value){
if(!window["array"+name])
window["array"+name]=[];
window["array"+name].push(value);
}
try{console.log(arrayA);}catch(e){console.log("arrayA missing: "+e);}
test("A",10);
try{console.log(arrayA);}catch(e){console.log("arrayA missing: "+e);}
test("A",20);
try{console.log(arrayA);}catch(e){console.log("arrayA missing: "+e);}
window is the global scope in a browser, and generally you should not rely on global variables without a good reason. They lack context (that is why they are 'global'), making it hard to tell where they belong, what they are and where they come from. That is something what most programming paradigms advise against.
The thing also works with node.js, just it has global as global context, you can paste this snippet into https://www.tutorialspoint.com/execute_nodejs_online.php as a test, replace the 3 window-s, and it will work (you can of course wrap it into a proper module too, just that is more work). What is written above against the usage of global variables stays true for node.js too. Do not use the global context especially if you are developing modules.
However, instead of window, the syntax works with any object too, and that would be considered okay:
var obj={};
console.log(obj.something);
obj['some'+'thing']=10;
console.log(obj.something);
So you can freely have your own 'context' object (if you write the var obj={}; line in the top-level of a module, it will be available everywhere in that module, and it will not interfere with the outside world), and create/access its members using this array-like syntax (obj['something']), constructing the names on the fly when necessary.

Javascript can't pass parameters between functions

I have a page where users can choose to book a ticket for a concert. First, they click on a artist which launches them into the booking process (and passes "artist" to the starting function).
The program then loads the venues for the artists. When the user changes the venue (and the value isn't blank) it tried to load the dates available in another select drop down menu by calling another function.
The original code was like:
<select onchange="loadDates(artist)">...</select>
However for some reason this wasn't passing the parameter from the starting function to the next function.
So I changed it too:
<select onchange="loadDates.call(this, artist)">..</select>
However the next function still gives me the error "artist is not defined" when I try to run it. Can anyone see what I'm doing wrong here as I read online that this works perfectly. I can give more information if need be. Thanks
Code in onXyz attributes is run at global scope, so both of your examples require that there be a global variable called artist. If there isn't one, then you'll get a ReferenceError because you're trying to take the value of a symbol that isn't defined.
If you meant to pass a string, put quotes around it. If you meant to pass something else, you'll need to say what that was. But the fundamental issue is that artist is not a defined symbol at global scope, which is where you're trying to use it.
If you have artist defined in some non-global location (good! globals are a bad thing), then you'll want to hook up your event handler via modern techniques rather than using the onXyz attributes.
The simplest way if you're not using a DOM library (like jQuery or similar) is to assign to the onXyz property of the select box element:
(function() { // Something to keep the stuff inside from being globals
var artist = "Joe Cocker";
var selectBox = document.querySelector("selector for the select box");
selectBox.onchange = function() {
loadDates(artist); // `artist` is in scope now
};
})();
In general, though, I avoid the onXyz properties because they only allow a single handler per event per element, preferring the DOM method addEventListener (and its Microsoft-specific predecessor, attachEvent). I didn't use them above for simplicity. If you don't use a DOM library, you might want this hookEvent function given in another answer which uses addEventListener if it's there, or attachEvent if it isn't, and supplies some missing bits for the attachEvent browsers.

Object has no method 'apply'

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

JavaScript - my own document method

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?

What object does the $ sign in "function loadGal($) "?

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.

Categories

Resources