javascript - insert div after elements with a certain class on mouseover - javascript

I know that there is a really simple jQuery way to to this, but now I would like to understand why my code is not working properly:
function insertAfter(referenceNode, newNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
var menuHelp = document.querySelector(".menu_help");
for (var i = 0;i<menuHelp.length;i++){
menuHelp[i].onmouseenter = function(){
menuHelpPopup = document.createElement("div");
menuHelpPopup.setAttribute('class','menu_help_popup');
menuHelpPopup.innerHTML = "test";
insertAfter(menuHelp[i], menuHelpPopup);
}
menuHelp[i].onmouseleave = function(){
menuHelpPopup.remove();
}
}
What I'm trying to do is to create a popup and insert it after elements with a certain class when mouseover on them..
DEMO http://jsfiddle.net/r5e8rvkg/

Please make sure menuHelp is a nodeList, so you should use document.querySelectorAll;
When the mouse enter, the value of i is menuHelp.length. so you should use this, like insertAfter(this, menuHelpPopup)

I used getElementsByClassName and it seemed to have worked.
var menuHelp = document.getElementsByClassName('menu_help');

Please checkout here: http://jsfiddle.net/r5e8rvkg/1/
First, use querySelectorAll instead of querySelector.
More importantly, you need to take care that in your code:
menuHelp[i].onmouseenter = function(){
menuHelpPopup = document.createElement("div");
menuHelpPopup.setAttribute('class','menu_help_popup');
menuHelpPopup.innerHTML = "test";
insertAfter(menuHelp[i], menuHelpPopup);
}
The value i would not be passed in correctly because the event onmouseenter is Async. When the function is called, the value of i is actually i === menuHelp.length, which results in menuHelp[i] === undefined.
You need to use Closure, as shown in my JSFiddle code.

The document.querySelector() method returns only the first element with the specified selector. To get each element with class 'menu_help', you need to use the document.querySelectorAll() method.
In other words, replace:
var menuHelp = document.querySelector(".menu_help");
With
var menuHelp = document.querySelectorAll(".menu_help");

Related

jQuery appendTo does not work under $.post

// plays a card into table.
// this code works. rendered card is appending into the table.
var playCard = function(card){
var renderedCard = renderCard(card);
$('#'+renderedCard.id).appendTo('#flop');
// but this one does not work.
var playCom = function(){
$.post('/api/comPlay', function(data){
var renderedCard = renderCard(data.card);
$('#'+renderedCard.id).appendTo('#flop');
});
};
I check the returned value from $.post. data.card gives the correct value. I create a div html with my renderCard function. That function works correctly as you see. But under $.post not.
I am stuck. Is there something special that i must know about $.post?
Thank you.
update :
var renderCard = function(card){
var create = document.createElement('div');
create.className = 'cardBig';
create.id = card;
return create;
};
You don't need to "find" your newly-created DOM element.
$(renderedCard).appendTo('#flop');
should do it.
Also, since you're using jQuery anyway:
$('#flop').append($('<div/>', {
className: 'cardBig',
id: data.card
}));
will save you the extra function.
In renderCard() method you are just creating a new html element but it is not rendered to the dom.
So your element lookup $('#'+renderedCard.id) will not work
$(renderedCard).appendTo('#flop');
have you tried selecting the id element first, like so:
$(renderedCard).appendTo( $('#flop')[0] )

Jquery, ajax, javascript - getting an element by id

I have some ajax onclick stuff that updates this line when the value is selected from the menu:
<li id="li_273" data-pricefield="special" data-pricevalue="0" >
The intention is to take the that value (data-pricevalue) and then multiple it by the amount that is entered from another input box. Here's my function to try to make that happen:
$('#main_body').delegate('#element_240','keyup', function(e){
var temp = $(this).attr("id").split('_');
var element_id = temp[1];
var price = $('#li_273').data("pricevalue");
var ordered = $(this).val();
var price_value = price * ordered;
price_value = parseFloat(price_value);
if(isNaN(price_value)){
price_value = 0;
}
$("#li_273").data("pricevalue",price_value);
calculate_total_payment();
});
Except I get the following error:
Uncaught TypeError: Cannot call method 'data' of null
It appears as tho my attempt to get the price value out of getElementById isn't correct. Any suggestions?
UPDATE: The code above has been edited from your suggestions and thanks to all. It appears to be working just fine now.
This part is wrong:
var price = document.getElementById('#li_273').data("pricevalue").val();
Instead, you should use jQuery all the way here:
var price = $('#li_273').data("pricevalue");
Btw, you shouldn't use .val() because .data() already returns a string. .val() is used exclusively for input elements such as <input> and <select> to name a few.
Update
Also, the rest of your code should be something like this:
var price_value = parseFloat(price);
if(isNaN(price_value)){
price_value = 0;
}
getElementById doesn't return a jQuery object it returns just a normal DOM object.
You can wrap any DOM object in a jQuery call to get it as a jQuery object:
$(document.getElementById("li_273")).data("pricevalue").val();
Or better yet just use jQuery
$("#li_273").data("pricevalue").val()
Your call should be document.getElementById('li_273') it's a normal method and doesn't require the hash as jQuery does.
EDIT As #kennypu points out you're then using jQuery on a non jQuery object. #Craig has the best solution.
document.getElementById('#li_273').data("pricevalue").val(); should be jQuery('#li_273').data("pricevalue").val();
Again the variable price_value is not present, I think you mean price.
Ex:
$('#main_body').delegate('#element_240','keyup mouseout change', function(e){
var temp = $(this).attr("id").split('_');
var element_id = temp[1];
var price = $('#li_273').data("pricevalue").val();
var ordered = $(this).val();
var price_value = parseFloat(price);
if(isNaN(price_value)){
price_value = 0;
}
$("#li_273").data("pricevalue",price_value);
calculate_total_payment();
});
The document.getElementById('#li_273') is the problem. The method won't recognize the hash. If you want to get the element ID using that method try document.getElementById('li_273') and it will work.
Otherwise use all jQuery.
Since you're using jQuery, why are you using document.getElementById instead of $(...)? It should be:
$('#li_273').data("pricevalue")
Note also that the data() method is only defined on jQuery objects, not DOM elements. And you don't need to call val() after it -- that's for getting the value of form elements.
Your getElementById is wrong with javascript you do not need the #, if your using jQuery do it like this instead (Also I removed the .val() because its not needed):
$('#main_body').delegate('#element_240','keyup mouseout change', function(e){
var temp = $(this).attr("id").split('_');
var element_id = temp[1];
var price = $('#li_273').data("pricevalue");
var ordered = $(this).val();
price_value = parseFloat(price_value);
if(isNaN(price_value)){
price_value = 0;
}
$("#li_273").data("pricevalue",price_value);
calculate_total_payment();
});

Remove multiple elements with same name using removeChild?

I have an element with multiple elements inside. All of the elements inside have the same name. Is there any way to remove them using one function?
(refer to this question for example Remove multiple children from parent?
Here's a solution that removes the first level children with the specified name for the parent with the specified id. If you want to go deeper, you can recursively call it on the child elements you get inside (you'll have to add a parent parameter as well).
function removeChildren (params){
var parentId = params.parentId;
var childName = params.childName;
var childNodes = document.getElementById(parentId).childNodes;
for(var i=childNodes.length-1;i >= 0;i--){
var childNode = childNodes[i];
if(childNode.name == 'foo'){
childNode.parentNode.removeChild(childNode);
}
}
}
And to call it:
removeChildren({parentId:'div1',childName:'foo'});
And a fiddle for testing:
Notes: You can only access the name element dependably in JavaScript when it supported on your element (e.g. NOT on DIVs!). See here for why.
UPDATE:
Here's a solution using className based on our conversation:
function removeChildren (params){
var parentId = params.parentId;
var childName = params.childName;
var childNodesToRemove = document.getElementById(parentId).getElementsByClassName('foo');
for(var i=childNodesToRemove.length-1;i >= 0;i--){
var childNode = childNodesToRemove[i];
childNode.parentNode.removeChild(childNode);
}
}
2021 Answer:
Perhaps there are lots of way to do it, such as Element.replaceChildren().
I would like to show you an effective solution with only one redraw & reflow supporting all ES6+ browsers.
function removeChildren(cssSelector, parentNode){
var elements = parentNode.querySelectorAll(cssSelector);
let fragment = document.createDocumentFragment();
fragment.textContent=' ';
fragment.firstChild.replaceWith(...elements);
}
Usage: removeChildren('.foo',document.body);: remove all elements with className foo in <body>
ok this should be easy. First get the parent element:
var theParent = document.getElementById("notSoHappyFather");
then get an array of the nodes that you want to remove:
var theChildren = theParent.getElementsByName("unluckyChild");
Lastly, remove them with a loop:
for (var i = 0; i < theChildren.length; i++)
{
theParent.removeChild(theChildren[i]);
}
A sample of your HTML would get you a more complete answer, but one can fairly easy call DOM functions to get the list of children and just remove them. In jQuery, remove all children would be something like this:
$("#target > *").remove();
or
$("#target").html("");
And, you can see a demo here: http://jsfiddle.net/jfriend00/ZBYCh/
Or, not using jQuery you could also do:
document.getElementById("target").innerHTML = "";
If you're trying to only remove a subset of the children (and leave others intact), then you need to be more specific how one would determine which children to leave and which to remove. In jQuery, you could use a .find() select or a filter() selector to narrow the list of children to just the children you wanted to target for removal.

JQuery on dynamically creating element and attaching data does not return value when calling data() again using selector?

I create a div element dynamically and associate data() to it. When accessing it again via selector it does not return the data. As result of below snippet I see first alert with data '1' and another with 'null' value. Can someone please help.
var dc = 0;
$("#attachData").click(function () {
dc++;
var newDiv = jQuery('#oldid').clone();
newDiv.attr('id', 'dt'+dc);
jQuery.data(newDiv, "dd", '1')
alert(jQuery.data(newDiv, "dd"));
var divFromSelector = $('#dt'+dc);
alert(jQuery.data(divFromSelector, "dd"));
});
Sorry, I did not add it in the snippet but its attached to the tree:
newDiv.attr('id', 'dt'+dc).
appendTo('#workspace-container');
Also when I try to access it using selector the element is returned correctly - but no data found.
Try:
var dc = 0;
$("#attachData").click(function () {
dc++;
var newDiv = jQuery('#oldid').clone();
newDiv.attr('id', 'dt'+dc).appendTo('#workspace-container');
jQuery.data(newDiv[0], "dd", '1')
alert(jQuery.data(newDiv[0], "dd"));
var divFromSelector = $('#dt'+dc);
alert(jQuery.data(divFromSelector[0], "dd"));
});
From the docs it seems that the JQuery.data method expects a DOM element, not a JQuery object. Appending [0] to a JQuery object gives the DOM element it is wrapping.
It'd probably be better if you used newDiv.data(...) and divFromSelector.data(...).
Demo here.
It looks like you haven't attached the new node in the DOM your accessing. http://api.jquery.com/clone/

My javascript to jQuery translation has a bug

My guess is that this javascript just finds the div called divid and then uses it with the sendit function.
var somevalue = 19;
if (navigator.appName.indexOf("Microsoft") != -1) {
thediv = window["divid"];
} else {
thediv = document["divid"];
}
thediv.sendit(somevalue);
I would imagine in jQuery it would look something as simple as this:
var somevalue = 19;
$('divid').sendit(somevalue);
But it's not working!! What could I be missing?
I should say that it's in the middle of other javascript code, could that be a problem?
You would need to get the actual DOM object (not the JQuery collection) to access the function that you set on it.
$('divid').get(0).sendit(somevalue);
Assuming there is an element with ID 'divid' you need to use the ID selector #
var somevalue = 19;
$('#divid').sendit(somevalue);
That may not be the whole answer as it's unclear where sendit is defined.

Categories