I have a problem with selecting dynamically-added elements, each with dynamically-defined ID; script always returns null when using getElemendById.
I want the script to first check, if element with certain ID already exists within the DOM, and if not - create one, if it does - do something else.
My code looks like this:
document.addEventListener('DOMContentLoaded', function () {
//define variables
var playersOnField = document.querySelector('.players');
//using timeBar as indicator of current time frame
var timeBar = document.querySelector('#time');
//its maximum value needs to be adjusted to the number of the frames we have
timeBar.setAttribute("max", data.player_positions.length);
//display the players position for current frame
positionPlayers = function() {
time = timeBar.value;
currentFrame = data.player_positions[time];
//check if DOM element representing each player of current frame already exists, if not - create it
for (var i = 0; i < currentFrame.length; i++) {
var playerId = currentFrame[i][0];
//ID's start with number, so they require special unicode notation
if (!!document.getElementById(`#\\3${playerId} `) == false) {
console.log('no element, let\'s create one');
var newPlayer = document.createElement('div');
newPlayer.id = `${playerId}`;
playersOnField.appendChild(newPlayer);
} else {
console.log('element already exists!');
}
}
}
//every time the bar changes its postion (and therefore its value) it should trigger the action to set up the players in the current position on the field
timeBar.addEventListener('change', positionPlayers);
timeBar.addEventListener('input', positionPlayers);
})
But the function is always returning false, and creating dozens od div's of the same ID, as getElementById never finds any of those newly-appended elements. How can I avoid this happening, preferably using vanilla JS?
You seem to have an extra space in the id string you are testing for. Since #{...} is an evaluated value, it shouldn't be in quotes in the first place.
Also, why use the back-tick string syntax here?
if (!!document.getElementById(`#\\3${playerId} `) == false) {
And, getElementById() already knows to look for id's so adding the # is going to search for elements that actually start with #.
Finally, if the element with that id does exist, it will return a "truthy" value that when converted to a Boolean, will convert to true, so there is no need to force a Boolean conversion (with !!) and then check to see if that is false.
That line can be rewritten to:
if (!document.getElementById(${playerId})) {
Related
Important: Even though this could probably be done with php (I'm using WooCommerce on Wordpress), I want this script to run only on my browser. That's why I want to do it in Javascript. Hence, I'm using Custom Javascript for Websites to load my script from my browser.
What my script should do: Check if the data of a specific element has been changed.
Logic: Step 1) Get and locally remember specific string (order number) of a specific class. Step 2) Refresh the page. Step 3) Again get the specific string (order number) of a specific class. Step 4) If strings do not match, run a function (play an audio).
Problem: After page reloads, the script starts to run again from the beginning. Hence, it results in overriding the stored string. As a result, stored and newly fetched string are always equal.
Question: How do I make the script to run the 3rd step only after refresh so that the stored data doesn't override itself?
Current code:
var OrderIdOld = document.getElementsByClassName("row-title"); // Select every single element with ClassName "row-title"
var x = (OrderIdOld[0].innerText); // Get the string of the first element of the class "row-title"
var compareOld = x.slice(-1); // Get the last element of the string (since it will be a number, we can change the string into a number easily later)
localStorage.setItem("compareOld", compareOld); // Store this element in local storage, so that it can be used after page reloads.
setInterval ("window.location.reload()", 30000); // Reload page every 30 secs.
var remembered = localStorage.getItem("compareOld"); // Assign stored element to a new var.
var n = compareOld.valueOf(); // Turn stored element into a number (for easy comparison later).
var OrderIdNew = document.getElementsByClassName("row-title"); // Select every single element with ClassName "row-title"
var y = (OrderIdNew[0].innerText); // Get the string of the first element of the class "row-title"
var compareNew = y.slice(-1); // Get the last element of the string (since it will be a number, we can change the string into a number easily later)
var m = compareNew.valueOf(); // Turn fetched element into a number (for easy comparison later).
function beep() {
var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
snd.play();
} // Function that will play the sound.
if (n!=m) {
beep();
} // Run function if two numbers are not equal.
Additional: I have gathered the parts of the code from various Questions on stackoverflow. Meaning, I have been searching about this topic for the past week. This is my first questions ever. Hopefully I formatted the question so that it easy to understand.
EDIT: The issue has been solved. I used the idea of only running the first step of function on the first load of page. This post helped me to get functionality working https://stackoverflow.com/a/22334768/7929506
The working code looks like this:
function beep() {
window.open('https://www.youtube.com/watch?v=EQ3zPIj2O5k','_blank');
}
if (sessionStorage.getItem("visit") == null) {
var OrderIdOld = document.getElementsByClassName("row-title")[0].innerText.slice(-1).valueOf();
sessionStorage.setItem("OrderIdOld", OrderIdOld);
sessionStorage.setItem("visit", new Date());
setTimeout("window.location.reload()", 10000);
}
else {
var OrderIdNew = document.getElementsByClassName("row-title")[0].innerText.slice(-1).valueOf();
var x = sessionStorage.getItem("OrderIdOld");
if (x==OrderIdNew) {
setTimeout("window.location.reload()", 10000);
}
else {
beep();
var x = sessionStorage.getItem("OrderIdOld");
sessionStorage.removeItem("OrderIdOld");
sessionStorage.removeItem("visit");
setTimeout("window.location.reload()", 10000);
}
}
When you refresh the page first time, you can simply append a flag variable to URL to identify weather its a refresh or a first time load. Based on that, you can pass a localized variable to script and if that is set then you need to refresh else not.
Long after a page has loaded (e.g. a minute or more), we can receive push messages which would cause us to append new content. After doing this when we query using Jquery hash selector it never returns the newly added content. In all cases, the length is always zero. We can see the content, but the selector returns nothing.
var section = '<section id="NewSection">Hello</section>';
$('.container').append(section);
if ($('#NewSection').length == 0)
{
alert('This should not be zero at this point... Why is it?');
}
Is there something we need to do in order to enable JQuery to find the appended content after it is appended?
Thou shall not cast when not necesairly.
You're casting to boolean using !, See this cold run:
len = $('#NewSection').length
CASE len = 0
then !len = true
if(1){
// code excecutes
}
CASE len = 1
then !len = false
if(0){
// no code executes
}
In order work, you should rework your condition.
// #updated!
var section = '<section id="NewSection">Hello</section>';
$('.container').append(section);
if ($('#NewSection').length > 0) // meaning one or MORE than one element got selected
{
alert('I should have found this!');
}
Here is a jsfiddle
Is it possible to use Javascript in Safari/Firefox/Chrome to search a particular div container for a given text string. I know you can use window.find(str) to search the entire page but is it possible to limit the search area to the div only?
Thanks!
Once you look up your div (which you might do via document.getElementById or any of the other DOM functions, various specs here), you can use either textContent or innerText to find the text of that div. Then you can use indexOf to find the string in that.
Alternately, at a lower level, you can use a recursive function to search through all text nodes in the window, which sounds a lot more complicated than it is. Basically, starting from your target div (which is an Element), you can loop through its childNodes and search their nodeValue string (if they're Texts) or recurse into them (if they're Elements).
The trick is that a naive version would fail to find "foo" in this markup:
<p><span>fo</span>o</p>
...since neither of the two Text nodes there has a nodeValue with "foo" in it (one of them has "fo", the other "o").
Depending on what you are trying to do, there is an interesting way of doing this that does work (does require some work).
First, searching starts at the location where the user last clicked. So to get to the correct context, you can force a click on the div. This will place the internal pointer at the beginning of the div.
Then, you can use window.find as usual to find the element. It will highlight and move toward the next item found. You could create your own dialog and handle the true or false returned by find, as well as check the position. So for example, you could save the current scroll position, and if the next returned result is outside of the div, you restore the scroll. Also, if it returns false, then you can say there were no results found.
You could also show the default search box. In that case, you would be able to specify the starting position, but not the ending position because you lose control.
Some example code to help you get started. I could also try putting up a jsfiddle if there is enough interest.
Syntax:
window.find(aStringToFind, bCaseSensitive, bBackwards, bWrapAround, bWholeWord, bSearchInFrames, bShowDialog);
For example, to start searching inside of myDiv, try
document.getElementById("myDiv").click(); //Place cursor at the beginning
window.find("t", 0, 0, 0, 0, 0, 0); //Go to the next location, no wrap around
You could set a blur (lose focus) event handler to let you know when you leave the div so you can stop the search.
To save the current scroll position, use document.body.scrollTop. You can then set it back if it trys to jump outside of the div.
Hope this helps!
~techdude
As per the other answer you won't be able to use the window.find functionality for this. The good news is, you won't have to program this entirely yourself, as there nowadays is a library called rangy which helps a lot with this. So, as the code itself is a bit too much to copy paste into this answer I will just refer to a code example of the rangy library that can be found here. Looking in the code you will find
searchScopeRange.selectNodeContents(document.body);
which you can replace with
searchScopeRange.selectNodeContents(document.getElementById("content"));
To search only specifically in the content div.
If you are still looking for someting I think I found a pretty nice solution;
Here it is : https://www.aspforums.net/Threads/211834/How-to-search-text-on-web-page-similar-to-CTRL-F-using-jQuery/
And I'm working on removing jQuery (wip) : codepen.io/eloiletagant/pen/MBgOPB
Hope it's not too late :)
You can make use of Window.find() to search for all occurrences in a page and Node.contains() to filter out unsuitable search results.
Here is an example of how to find and highlight all occurrences of a string in a particular element:
var searchText = "something"
var container = document.getElementById("specificContainer");
// selection object
var sel = window.getSelection()
sel.collapse(document.body, 0)
// array to store ranges found
var ranges = []
// find all occurrences in a page
while (window.find(searchText)) {
// filter out search results outside of a specific element
if (container.contains(sel.anchorNode)){
ranges.push(sel.getRangeAt(sel.rangeCount - 1))
}
}
// remove selection
sel.collapseToEnd()
// Handle ranges outside of the while loop above.
// Otherwise Safari freezes for some reason (Chrome doesn't).
if (ranges.length == 0){
alert("No results for '" + searchText + "'")
} else {
for (var i = 0; i < ranges.length; i++){
var range = ranges[i]
if (range.startContainer == range.endContainer){
// Range includes just one node
highlight(i, range)
} else {
// More complex case: range includes multiple nodes
// Get all the text nodes in the range
var textNodes = getTextNodesInRange(
range.commonAncestorContainer,
range.startContainer,
range.endContainer)
var startOffset = range.startOffset
var endOffset = range.endOffset
for (var j = 0; j < textNodes.length; j++){
var node = textNodes[j]
range.setStart(node, j==0? startOffset : 0)
range.setEnd(node, j==textNodes.length-1?
endOffset : node.nodeValue.length)
highlight(i, range)
}
}
}
}
function highlight(index, range){
var newNode = document.createElement("span")
// TODO: define CSS class "highlight"
// or use <code>newNode.style.backgroundColor = "yellow"</code> instead
newNode.className = "highlight"
range.surroundContents(newNode)
// scroll to the first match found
if (index == 0){
newNode.scrollIntoView()
}
}
function getTextNodesInRange(rootNode, firstNode, lastNode){
var nodes = []
var startNode = null, endNode = lastNode
var walker = document.createTreeWalker(
rootNode,
// search for text nodes
NodeFilter.SHOW_TEXT,
// Logic to determine whether to accept, reject or skip node.
// In this case, only accept nodes that are between
// <code>firstNode</code> and <code>lastNode</code>
{
acceptNode: function(node) {
if (!startNode) {
if (firstNode == node){
startNode = node
return NodeFilter.FILTER_ACCEPT
}
return NodeFilter.FILTER_REJECT
}
if (endNode) {
if (lastNode == node){
endNode = null
}
return NodeFilter.FILTER_ACCEPT
}
return NodeFilter.FILTER_REJECT
}
},
false
)
while(walker.nextNode()){
nodes.push(walker.currentNode);
}
return nodes;
}
For the Range object, see https://developer.mozilla.org/en-US/docs/Web/API/Range.
For the TreeWalker object, see https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
var elements = [];
$(document).find("*").filter(function () {
if($(this).text().contains(yourText))
elements.push($(this));
});
console.log(elements);
I didn't try it, but according the jQuery documentation it should work.
Here is how I am doing with jquery:
var result = $('#elementid').text().indexOf('yourtext') > -1
it will return true or false
Maybe you are trying to not use jquery...but if not, you can use this $('div:contains(whatyouarelookingfor)') the only gotcha is that it could return parent elements that also contain the child div that matches.
The Problem
I am trying to figure out the offset of a selection from a particular node with javascript.
Say I have the following HTML
<p>Hi there. This <strong>is blowing my mind</strong> with difficulty.</p>
If I select from blowing to difficulty, it gives me the offset from the #text node inside of the <strong>. I need the string offset from the <p>'s innerHTML and the length of the selection. In this case, the offset would be 26 and the length would be 40.
My first thought was to do something with string offsets, etc. but you could easily have something like
<p> Hi there. This <strong>is awesome</strong>. For real. It <strong>is awesome</strong>.</p>
which would break that method because there are identical nodes. I also need the option to throw out nodes. Say I have something like this
<p>Hi there. This <strong>is blowing my mind</strong> with difficulty.</p>
I want to throw out an elements with rel="inserted" when I do the calculation. I still want 26 and 40 as the result.
What I'm looking for
The solution needs to be recursive. If there was a <span> with a <strong> in it, it would still need to traverse to the <p>.
The solution needs to remove the length of any element with rel="inserted". The contents are important, but the tags themselves are not. All other tags are important. I'd strongly prefer not to remove any elements from the DOM when I do all of this.
I am using document.getSelection() to get the selection object. This solution only has to work in WebKit. jQuery is an option, but I'd prefer to it without it if possible.
Any ideas would be greatly appreciated.
I have no control over the HTML I doing all of this on.
I think I solved my issue. I ended not calculating the offset like I originally planned. I am storing the "path" from the chunk (aka <p>). Here is the code:
function isChunk(node) {
if (node == undefined || node == null) {
return false;
}
return node.nodeName == "P";
}
function pathToChunk(node) {
var components = new Array();
// While the last component isn't a chunk
var found = false;
while (found == false) {
var childNodes = node.parentNode.childNodes;
var children = new Array(childNodes.length);
for (var i = 0; i < childNodes.length; i++) {
children[i] = childNodes[i];
}
components.unshift(children.indexOf(node));
if (isChunk(node.parentNode) == true) {
found = true
} else {
node = node.parentNode;
}
}
return components.join("/");
}
function nodeAtPathFromChunk(chunk, path) {
var components = path.split("/");
var node = chunk;
for (i in components) {
var component = components[i];
node = node.childNodes[component];
}
return node;
}
With all of that, you can do something like this:
var p = document.getElementsByTagName('p')[0];
var piece = nodeAtPathFromChunk(p, "1/0"); // returns desired node
var path = pathToChunk(piece); // returns "1/0"
Now I just need to expand all of that to support the beginning and the end of a selection. This is a great building block though.
What does this offset actually mean? An offset within the innerHTML of an element is going to be extremely fragile: any insertion of a new node or change to an attribute of an element preceding the point in the document the offset represents is going to make that offset invalid.
I strongly recommend using the browser's built-in support for this in the form of DOM Range. You can get hold of a range representing the current selection as follows:
var range = window.getSelection().getRangeAt(0);
If you're going to be manipulating the DOM based on this offset that you want, you're best off doing so using nodes instead of string representations of those nodes.
you can use the following java script code:
var text = window.getSelection();
var start = text.anchorOffset;
alert(start);
var end = text.focusOffset - text.anchorOffset;
alert(end);
Just check if your selected element is a paragraph, and if not use something like Prototype's Element.up() method to select the first paragraph parent.
For example:
if(selected_element.nodeName != 'P') {
parent_paragraph = $(selected_element).up('p');
}
Then just find the difference between the parent_paragraph's text offset and your selected_element's text offset.
Maybe you could use the jQuery selectors to ignore the rel="inserted"?
$('a[rel!=inserted]').doSomething();
http://api.jquery.com/attribute-not-equal-selector/
What code are you using now to select from blowing to difficulty?
I am trying to create a function that given a divid, and a list of classes, will then do some text replacing inside them.
Having learned of how Firefox Dom is handling text nodes differently, I read that I had to use javascript to loop through the elements, sibling to nextSibling.
The last obstacle I had in my script, of which you see a small portion of, is getting the classname. I need the class name so that I can filter down what content get's text replaced.
Having looked all the answers, and with the help of a co-worker named Ryan at work, we have redone this in jquery.
$(divid).find(".status_bar").each( function() {
var value = $.trim($(this).text());
// if value is not defined thru browser bugs do not replace
if (typeof(value) != 'undefined') {
// it is a text node. do magic.
for (var x = en_count; x > 0; x--) {
// get current english phrase
var from = en_lang[x];
// get current other language phrase
var to = other_lang[x];
if (value == from) {
console.log('Current Value ['+value+'] English ['+from+'] Translation ['+to+']');
value = to;
$(this).attr('value', to);
}
}
}
});
This currently works in all areas, except in the replacing of text.
The reason I had originally with doing this in jQuery, had to be not sure I could loop thru elements, and avoid the problem with firefox and text nodes.
I am doing a loop of all elements inside a div, and I now need to get the classname of the element that I am looping by.
Then i can check if the current element's class is one, I need to do something with...
// var children = parent.childNodes, child;
var parentNode = divid;
// start loop thru child nodes
for(var node=parentNode.firstChild;node!=null;node=node.nextSibling){
var myclass = (node.className ? node.className.baseVal : node.getAttribute('class'));
}
But this code for getting the classname only get's null values.
Any suggestions?
For those of you who are trying to figure out what the whole point is, read this JavaScript NextSibling Firefox Bug Fix I have code that does my language translation that works in Google Chrome and IE. But when I use it in Firefox, and try to translate div content after ajax has loaded it, it fails because of the whitespace issue.
I really don't have a preference of jQuery or Pure Javascript, I just want a working solution.
Thank you all for being patient. I personally thought I was extremely clear in my description, I apologize if it wasn't. I wasn't trying to be obscure or make it difficult to get help. But please don't insult me, by implying I am trying to make it unclear.
Thanks.
Hm... You have jQuery but don't use it?
$(divid).children(".yourSpecialClassName").each( function() {
doSomethingWith(this);
});
To get the CSS class attribute value, this will do:
$(divid).children().each( function() {
alert(this.className);
});
Based on the function you posted now, you want this:
$(divid).find(".status_bar").each( function() {
$(this).text( function(i, text) {
var x = $.inArray(en_lang, $.trim(text));
if (x > -1) {
console.log('Current Value ['+text+'] English ['+en_lang[x]+'] Translation ['+other_lang[x]+']');
return other_lang[x];
}
return text;
});
});
And please, don't ever use "do magic" as a comment again. This is incredibly lame.
EDIT. This can be made much more efficient (superfluous console.log() removed):
$(divid).find(".status_bar").each( function() {
// prepare dictionary en_lang => other_lang
var dict = {};
$.each(en_lang, function(x, word) { dict[word] = other_lang[x]; });
$(this).text( function(i, text) {
var t = $.trim(text);
return (t in dict) ? dict[t] : text;
});
});
if you are using jquery you can do this:
$("#myDiv").find("*").each(
function(){
var myclass = $(this).attr("class");
}
);
Your sample code doesn't make sense.
$(this).attr('value', to);
'value' is an attribute of the tag, not the text content.
Did you really mean to do this instead?
$(this).text(to);
Also, you've re-edited your question, but you're still trying to loop through the child nodes using non-jQuery methods. You said "The last obstacle I had in my script, of which you see a small portion of, is getting the classname. I need the class name so that I can filter down what content get's text replaced."
If you are using jQuery it is completely unnecessary to loop through anything to get a class name. You simply have to use a proper selector in the first place.
$(divid).find(".status_bar.replaceme").each( function() {
// .replaceme is whatever class you're using for the stuff you want to change
// .status_bar.replaceme matches all elements with BOTH status_bar and replaceme classes
var value = $.trim($(this).text());
// if value is not defined thru browser bugs do not replace
if (typeof(value) != 'undefined') {
// it is a text node. do magic.
// NOTE: The following is inefficient but I won't fix it.
// You're better off using an associative array
for (var x = en_count; x > 0; x--) {
// get current english phrase
var from = en_lang[x];
// get current other language phrase
var to = other_lang[x];
if (value == from) {
console.log('Current Value ['+value+'] English ['+from+'] Translation ['+to+']');
// value = to; <-- useless, get rid of it.
$(this).text(to);
// or $(this).html(to);
}
}
}
});