Reputation: 48963
Using JavaScript and jQuery I am trying to cache a Selector to an Objects property.
I save $("#dnsTitle")
to zPanelDNS.cache.dnsTitleId
however down in my zPanelDNS.events
function you can see where I try using the Selector and the Cached version.
For some reason the cached version does not work as I thought it would. I write both selectors to console log and they both find the target element but for some reason the cached version does not work.
Here is the output in console of the 2, you can see they are slightly different...
$("#dnsTitle")
WORKS =
[div#dnsTitle.account accountTitle, context: document, selector: "#dnsTitle", jquery: "1.9.1", constructor: function, init: function…]
zPanelDNS.cache.dnsTitleId
DOES NOT WORK =
[context: document, selector: "#dnsTitle", jquery: "1.9.1", constructor: function, init: function…]
The JavaScript...
var panelDNS = {
unsavedChanges: false,
init: function () {
panelDNS.events();
},
cache: {
dnsTitleId: $("#dnsTitle"),
translation: {
absolute: 0,
relative: 0,
sinceDirectionChange: 0,
percentage: 0
}
},
events: function() {
// Activate SAVE and UNDO Buttons when Record Row EDITED
$(document).on("keydown", "#dnsRecords input" ,function() {
// Using Selector
// DOES WORK
$("#dnsTitle").find(".save, .undo").removeClass("disabled");
console.log($("#dnsTitle"));
// Using Cached Selector panelDNS.cache.dnsTitleId
// DOES NOT WORK
//panelDNS.cache.dnsTitleId.find(".save, .undo").removeClass("disabled");
console.log(panelDNS.cache.dnsTitleId);
});
}
}
$(function(){
panelDNS.init();
});
Upvotes: 0
Views: 846
Reputation: 1074595
$("#dnsTitle")
looks up the element with that ID immediately when you call it, and returns a jQuery object wrapping the element (if found) or an empty one (if not). It doesn't re-query or something when you try to use it later. Apparently, the element with that ID doesn't exist when the code creating the panelDNS
object is created, but does exist later when a key is pressed.
There could be any number of reasons for that. For instance, if the script
element for your code is higher up in your HTML document than the dnsTitle
element, that would be why; the element doesn't exist until that part of the document is parsed.
For example, this will not turn the text of the myElement
element blue:
<script>
$("#myElement").css("color", "blue");
</script>
<!-- ... -->
<div id="myElement">This text will not turn blue</div>
but this will:
<div id="myElement">This text WILL turn blue</div>
<!-- ... -->
<script>
$("#myElement").css("color", "blue");
</script>
This is one of many reasons that, unless you have a good reason not to, you should put your script
elements at the bottom of your document, just before your closing </body>
tag. That's the recommendation from the YUI Best Practices and the Google Closure Library teams.
There were a couple of other problems with that code, not least that it had a syntax error where you were defining events
, and you were using PanelDNS
and panelDNS
interchangeably, but JavaScript is case-sensitive and so they're not the same thing.
Here's that code with the changes described above and fixes for the other problems I noticed, see inline comments with ****
:
var panelDNS = {
unsavedChanges: false,
init: function () {
// **** Removed unnecessary second `ready` call
// **** Get the element here
panelDNS.cache.dnsTitleId = $("#dnsTitle");
// **** Call the `events` function to hook events
panelDNS.events();
// (Instead of `panelDNS` above, you could use `this`, but since you
// only have one `panelDNS` object, it's simpler to use that)
},
cache: {
// **** Removed dnsTitleId here
translation: {
absolute: 0,
relative: 0,
sinceDirectionChange: 0,
percentage: 0
}
},
events: function() { // **** Made this a function
// Activate SAVE and UNDO Buttons when Record Row EDITED
$(document).on("keydown", "#dnsRecords input" ,function() {
panelDNS.cache.dnsTitleId.find(".save, .undo").removeClass("disabled");
});
}
}
$(function(){
panelDNS.init();
});
Upvotes: 2