jQuery .add method seemingly not working? - javascript

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...

Related

Create variables from Html elements

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).

jQuery: Using .after() or .before() adds element to last item in selection only

I've been using jQuery for a while but this is a new one. A simplified example:
HTML
<div class='custom'></div>
<div class='custom'></div>
<div class='custom'></div>
jQuery:
var $customElems = $('.custom'),
$spanOuter = $('<span class="outer"/>'),
$spanInner = $('<span class="inner"/>');
$customElems.each( function() {
$(this).wrap($spanOuter).after($spanInner);
});
JSFiddle:
http://jsfiddle.net/a3ZK8/
I would have expected the 'inner' span to be added to all three elements in the selection but it gets always inserted into the last one only (no matter how many). I tried it with .before(), with and without the chaining, same result. What am I missing??
The problem is you are using a reference to a jQuery object.
Hence you keep moving the object reference around within each iteration.
If you have no events attached or no need for the span to be a jQuery object then just pass the parameter as a HTML string literal instead of an object reference
Cloning a jQuery object that doesn't need to be a jQuery object in the first place is just redundant processing and unnecessary overhead.
Change your jQuery object to a string similar to this:
spanInnerString = '<span class="inner"/>';
and your method like this:
$(this).wrap($spanOuter).after(spanInner);
The result is:
<span class="outer"><div class="custom"></div><span class="inner"></span></span>
<span class="outer"><div class="custom"></div><span class="inner"></span></span>
<span class="outer"><div class="custom"></div><span class="inner"></span></span>
DEMO - Passing parameter as HTML string
Off course, the same goes for the outer span. Don't create jQuery objects unless you have to.
If you must use a jQuery object because you want to attach events to the span or similar, than cloning is the way to go, though make sure you use clone(true, true) then to also clone the attached events.
You need to clone the element. Otherwise, after() will relocate the same element 3 times, which results in it being attached to only the last looped element.
$customElems.each(function () {
$(this).wrap($spanOuter).after($spanInner.clone());
});
Demo: Fiddle
You might ask, "Why would wrap() work?" That's because 'wrap()' internally clones the element.
You're moving the same span from place to place. If you acted on all three divs at once, jquery will instead clone the span.
http://jsfiddle.net/a3ZK8/1/
var $customElems = $('.custom'),
$spanOuter = $('<span class="outer"/>'),
$spanInner = $('<span class="inner"/>');
$customElems.wrap($spanOuter).after($spanInner);
From the documentation for .after:
Important: If there is more than one target element, cloned
copies of the inserted element will be created for each target except
for the last one.
which means the last element will always get the original, while all other selected elements will get a clone. That's why when you acted on one element at a time, it simply moved the same span around.

How to add text to a DIV from array of DIVs

Var divs = $(".txt"); this will return a list of divs with a class txt .
I want to add text to a selected div for example :
divs[4].html("Hello World"); this with return error saying divs[4].html is not a function. why ?
When you access a jQuery object by its DOM array index, you get the HTML element, not a jQuery object, which doesn't have the html() function. Use the eq(n) selector instead:
$(".txt:eq(4)").html("Hello World");
The divs[0] is giving you a DOM reference, not a jQuery object. So, pass that to the jQuery function ($() is shorthand for jQuery()):
$(document).ready(function(){
var divs = $('.txt');
$(divs[4]).html('this one');
});
http://jsfiddle.net/userdude/unu8g/
Note as well the use of $(document).ready(), which will wait until the DOM is accessible. $(window).load() will suffice for this as well, although it may fire after onDOMReady.
The non jQuery way:
document.getElementsByClassName("txt")[4].innerHTML = "banananana!";
Just a side note: I'd suggest learning basic browser javascript before moving to libraries.
It will give you an understanding of how such libraries work and will keep you from being 'locked in' to a specific few

Adding and finding classes that is dynamically added to body - jquery

Is there any way to add classes or alter objects that is dynamically added to the body?
I am adding a range of objects to the body by javascript.
Fot instance Im adding some links that is dynamically generated and added to the body. When they are loaded I need to elect the first of the divs and add a new class to it.
I can't seem to find any way to do this... Update the DOM or how should I go around this? There must be a way to alter dynamically added objects.
Any clues?
Thanks for any help!
if you added them dynamically, then you can just use the objects you already have. Otherwise you'll need to find them with sizzle.
//create the elements
var $link1 = $('<a>click me</a>').attr('href','page1.html');
var $link2 = $('<a>click me</a>').attr('href','page2.html');
//append the elements
$('#some-links').append($link1).append($link2);
//use the element we created
$link1.addClass('my-class');
//find the second link element using sizzle
$('#some-links>a').eq(1).addClass('my-other-class');
demo: http://jsfiddle.net/PtebM/2/
Well of course you caN:
var a = $('<a>');
a.html('new link').appendTo('#menu');
a.addClass('border');
or
var a = $('<a>');
a.html('new link').appendTo('#menu');
$('#menu a').addClass('border');
fiddle http://jsfiddle.net/4NPqH/
Why not just add a class name to your generated elements?.
I.e.:
$('span').html('Hello world').addClass("fancyText").appendTo('body');

jQuery - How to link together a DOM element and a Javascript object?

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.

Categories

Resources