I want to be able to link a javascript object with a dom element but cant find a way for this to be done properly. An example: say when opening a page with an inventory it loads all the items contained in it and when I hover over the images inside it creates a small tooltip with some information. Well there will be much of these items on the page and i want to be able to link the DOM element with an object so i can access its properties easily. I hope im explaining my self properly.
say I had this inside an inventory:
<div id="slot1"><img id="item1"></div>
<div id="slot2"><img id="item2"></div>
and say i have a javascript object called slot1 and slot2:
the object slot1 has all the properties that need to be shown in the tooltip so i would like to do something like this in the mouseover event:
this.showTooltip()
any help would be great ty if i need to explain it better just say!
-Thaiscorpion
Use jQuery data:
$("div.hasToolTip").hover(
function() {
//Get the associated data with the DOM element
//with $(this).data(someKey)
showToolTip($(this).data('toolTipInformation'));
},
function() {
//Here you can hide all tooltips
}
);
Obviously, before you can register this event, you have to assign the object to every DOM element with $(selector).data(key, value).
These example expects that every DOM element which should have a tooltip has a class named .hasToolTip.
Look at the jQuery documentation for more information about the .data() function.
Just have the javascript object know the ID of the object it's watching.
function Tooltipper(divID) {
this.id = divID;
}
Tooltipper.prototype.showTooltip = function () {
// do tooltip stuff
$('#' + this.id).tooltip(); // assuming that it has a tooltip thing
};
var slot1 = new Tooltipper('slot1'),
slot2 = new Tooltipper('slot2');
And then:
slot1.showTooltip();
Or better yet, instead of passing in the ID, pass in the object:
var slot1 = new Tooltipper($('#slot1'));
This way you don't have to do a DOM lookup each time.
Related
Is it possible to get all the elements from a webpage, and make a variable for each one? can you make variables within an each function and name them the same as their element name?
Yes, but be careful.
It is useful to store an element reference in a variable if it's present at load time and not changed later, but removing the div after load would cause your variable to return undefined. If the div is added after the variable is declared, you will also encounter an error.
Have a read here.
As you said, it's just for fun.. so I think that this should do the trick:
$("*").each(function() {
const elmnt = $(this);
const id = elmnt.attr("id");
if(id) {
window[id] = elmnt;
}
});
This will only create variables for the DOMs that have the id defined. But you can change the rule the way you want.
Use:
var div = $('div');
div.click();
If you wanted to bind the click event to all div elements you could easily just do:
var div = $('div');
div.click(function(){
//do something
});
A good way to shorten the jQuery selector and overhead and page performance is to use VanillaJS: http://vanilla-js.com/
Selecting object is one of the easiest thing to do with vanilla JS. I don't know what is your use case but a lot of what jQuery does is never used. If you are looking for optimization, try to live without it for a while and you might be surprised. Here are some out of the box ways to get elements in short variables.
Get all divs in your document:
var divs = document.querySelectorAll('div');
Get the first div only:
var div = document.querySelector('div');
Get a specific div:
var div = document.getElementById('somediv');
This way you can control everything (a la carte variables, rather than trying to solve all problems you might not need to solve).
I'm looking for a more succint and possibly more jQuery-e way of doing the following.
I have an object lbl which is a div. Contained within the div is a span tag that is the firstName and lastName property of the lbl object. So, so far we have the following HTML:
<div class="label">
<span class="firstName">John</span>
<span class="lastName">Doe</span>
</div>
Now consider the following fiddle http://jsfiddle.net/VfErV/
$('#btnSubmit').click(function ()
{
var lbl = $('<div>').addClass('label');
//I need to be able to access the child elements of the parent div
//via the dot operator
firstName = $('<span>').text('test1').addClass('firstName');
lastName = $('<span>').text('test2').addClass('lastName');
lbl.append(firstName);
lbl.append(lastName);
lbl.firstName = firstName;
lbl.lastName = lastName;
$('#page').append(lbl);
console.log(lbl.firstName.text());
//span tag is never added to the div
var lbl2 = $('<div>').addClass('label');
lbl2.firstName = $('<span>').text('test2').addClass('firstName');
$('#page').append(lbl2);
});
Please refer to the fiddle for behavior. I need to be able to control font-sizes, borders, etc. on the child objects of the parent div container, lbl, and have the appear on the page as normal DOM elements. All of the JS up until the first lbl control is appended to the page works. This looks clunky to me, though. Is there a better way to have child elements of a DOM element be properties of the parent object more easily/succintly?
You asked for a more jQuery-way to do this. Here's how you could create your structure:
$('#btnSubmit').click(function () {
var lbl = $('<div>').addClass('label');
lbl.html('<span class="firstName">test1</span><span class="lastName">test2</span>');
$('#page').append(lbl);
// Then, to retrieve that data, you can just do something like this
console.log(lbl.find(".firstName").text());
});
Then, anytime you want to get the firstName from a given label div, you just use .find("firstName") to get that object and then get its text.
Best practices generally just use the structure of the DOM and find things as needed in the DOM rather than make new duplicate ways to access everything. For 99% of what we do, accessing things through the DOM is plenty fast and doesn't require creation and duplication of another way to get to the data. And, jQuery makes it pretty easy to find things in the DOM as long as you have enough id or class markers to identify what you're looking for (which you do).
The following chain works:
$("</p>").html('message').hide().appendTo("#chat").fadeIn()
.parent().scrollTop($('#chat')[0].scrollHeight);
But this doesn't:
$("</p>").html('message').hide().appendTo("#chat").fadeIn()
.parent().scrollTop($(this)[0].scrollHeight);
this.scrollHeight doesn't work too.
How can i get current object reference in jquery chain?
You only get access to the current object inside of a callback. There's no way you can get access to the current object in your chain.
Try this:
var $parent = $("</p>").html('message').hide().appendTo("#chat").fadeIn().parent();
$parent.scrollTop($parent[0].scrollHeight);
If you really don't want to break out of you chain, you can re-select:
$("</p>").html('message').hide().appendTo("#chat").fadeIn()
.parent().scrollTop($("#chat")[0].scrollHeight);
But I'd strongly advise you against it. There's no need to select the same DOM element twice.
In your second code snippet this doesn't point to #chat that's why it doesn't work. this mostly points to the calling function instance or the object which triggered any event.
You can try something like this
var $p = $("</p>").html('message').hide().appendTo("#chat");
$p.fadeIn().parent().scrollTop($p[0].scrollHeight);
Well, it's obvious. The #chat element is a static element and you are dynamically appending paragraphs to it. Therefore, you want to get a reference to that element beforehand (for instance, on page initialization):
var chat = $( '#chat' )[0];
Now, you do this:
$( '<p />' ).html( 'message' ).hide().appendTo( chat ).fadeIn();
$( chat ).scrollTop( chat.scrollHeight );
So, the idea is to retrieve references to the main static elements (chat-box, toolbar, panel, navigation, etc.) on page initialization, and then use those references all over your application code.
Update: Everyone that contributed, it's well appreciated, you all are very kind and generous and all of you deserve my dear respect. Cheers.
Note: I'm making a simple jQuery tooltip plugin, the tooltip will fire on mouseover. The mouseover will create an instance of the div tool-tip that will be specific to each anchor that launched the div tool-tip. So each anchor with the class .c_tool will have its own created div that will erase after mouseout. Anyway all those details are irrelevant. What is important is how to create a div with .append() or .add() on and then find a way to call it and apply actions to that div without setting an identifier (id), class, or any means to identify it.
I know theres a way you could find the div by counting, so if you gave every created div the same class and then counted them to find that one, however I don't know if this is the most efficient method that is why I'm asking for help.
I'm not going to post the whole plugin script thats unnecessary, so I'll paste a simplified version.
hover me
hover me
$(document).ready(function() {
obj = $('a.c_tool');
obj.mouseover(function() {
/// append div to body it will be specific to each item with class c_tool, however I don't want to set an ID, or CLASS to the appended div
}).mouseout(function() {
/// remove added div without setting ID or class to it.
});
});
Working example:
http://jsfiddle.net/xzL6F/
$(document).ready(function() {
var tooltip;
obj = $('a.c_tool');
obj.mouseover(function() {
var element = $('<div>', {
html: "I'm a tooltip"
});
tooltip = element.appendTo($("body"));
/// append div to body it will be specific to each item with class c_tool, however I don't want to set an ID, or CLASS to the appended div
}).mouseout(function() {
tooltip.remove();
/// remove added div without setting ID or class to it.
});
});
To create a new DOM node you can use the jQuery constructor, like
$(document).ready(function() {
obj = $('a.c_tool');
obj.mouseover(function() {
if(!$.data(this, 'ref')) {
$.data(this, 'ref', $ref = $('<div>', {
html: 'Hello World!'
}).appendTo(document.body));
}
}).mouseout(function() {
$.data(this, 'ref').remove();
});
});
.appendTo() returns the DOM node of invocation (in this case, the newly created DIV) as jQuery object. That way you can store the reference in a variable for instance and access it later.
Referring your comment:
To remove all stored references, you should do this:
$('a.c_tool').each(function(index, node) {
$.removeData(node, 'ref');
});
you can use $.append(
);
http://api.jquery.com/append/
and to find the DOM created dynamically u can use
$("#dynamicallyCreatedDOMid").live("yourCustomTrigger",function(){
});
http://api.jquery.com/live/
I wonder if anyone can explain this:
$(document).ready(function() {
var popup = $('<div id="popup"><div class="popup-content"></div></div>');
var popupContent = popup.children('div');
var overlay = $('<div id="overlay"></div>');
console.log(popup);
console.log(popupContent);
console.log(overlay);
console.log(overlay.add(popup).appendTo('body'));
});
I've added some debugging in there in case you want to test it.
I don't understand why only the overlay gets appended when appendTo() is being called on a jQuery object containing two elements?
Any help would be much appreciated.
.add() doesn't modify the existing object, it returns a new object with the values in it. So you aren't appending the object you think you are.
This portion of code does NOT modify the overlay object: overlay.add(popup) Rather, it creates a new object, but since there is no reference to that new object, it is immediately lost--there is no way you can use it. The overlay object itself is unchanged.
You should do something like this instead:
overlay = overlay.add(popup);
overlay.appendTo('body');
My guess is it has something to do with the overlay jQuery object having not been added to the DOM yet. The jquery doc on .add says:
"Given a jQuery object that represents
a set of DOM elements, the .add()
method constructs a new jQuery object
from the union of those elements and
the ones passed into the method." - http://api.jquery.com/add/
Your overlay is not a set of DOM elements yet. Can you just use append?:
overlay.append(popup).appendTo('body')
But I've just found that removeing the id from the overlay fixes the issue:
$(document).ready(function() {
var popup = $('<div id="popup"><div class="popup-content"></div></div>');
var popupContent = popup.children('div');
var overlay = $('<div></div>');
console.log(popup);
console.log(popupContent);
console.log(overlay);
console.log(overlay.add(popup).appendTo('body'));
});
I don't think it should be relevant whether the nodes are on the DOM or not yet as .add() is just combining two jQuery objects.
This is making no sense...