I have the following function below that is supposed to rotate/loop through a list of 4 items, which does work through an onclick. However, the user has to click twice for the loop to perform.
function rotateList(){
var list = document.getElementById("arrange");
var first = list.removeChild(list.firstChild);
list.appendChild(first);
}
Does anyone know how to make the above work with one click?
Many thanks in advance.
function rotateList() {
var list = document.getElementById("arrange");
list.appendChild(list.firstElementChild);
}
Note that any DOM node can only ever exist once in the document. If you append it in one place, it gets removed in its original location.
This way appending the first child node has the desired effect.
firstElementChild gives you the "real" first child, whereas firstChild also gives you the (blank) text node that can occur between elements, which is what's making you click twice. However, firstElementChild is not supported before IE9. Other browsers are no problem.
http://jsfiddle.net/Vb8dY/1/
Related
The API docs for appendTo list the method being able to select an HTML string for a target.
However, there seems to be no use to this since the set still includes the original elements, and the HTML string seems not to have been added anywhere in the DOM nor do I see a circumstance where it could be available.
var b = button.appendTo('<div>').appendTo('body');
b is a button, and yet it is not wrapped in a div or anything.
You can see this at http://jsfiddle.net/0dgLe5sj/
Where would it be useful to append to a HTML string (which doesn't yet exist on the page)?
appendTo() returns the item being appended.
So your code is:
var btn = button.appendTo('<div>');
btn.appendTo('body');
As you can see, you move it inside a div, then immediately move it inside the body. So you when you look at it at the end, it's inside the body.
Perhaps you meant:
var b = button.appendTo($('<div>').appendTo('body'));
which will append a div to the body and then append the btn to that div.
Updated fiddle: http://jsfiddle.net/0dgLe5sj/8/
or, if you wanted to add to the div first:
var b = button.appendTo("<div>");
b.parent().appendTo("body")
but if you combine it into a single line, you can't get the button back into the variable using .appendTo as you're adding the div to the body so you're going to get the div or the body back.
To address the 'where would this be useful part':
Being able to create detached DOM elements is extremely useful for parsing HTML strings and can also be used to 'batch' up some changes without forcing page redraws between.
Moving one button to a detached div and the back to the body doesn't have a lot of point, but it proves the principles.
I'm trying to detect if an element with a specific tag name has been inserted into the document. I am aware of DOMSubtreeModified and MutationObserver and I know that they can detect changes in the elements, but if the document is big and many changes are applied to the document, these two methods can become quite heavy.
One of the ideas I had was to collect all elements using getElementsByTagName and then detect a change of HTMLCollection's length property but I didn't find any method that could watch this property and trigger an event.
Another idea I had was to set an interval, but the problem with this is that an item can be deleted and inserted in between the timer and this wouldn't be detected in the interval's function.
Is there any efficient way of detecting new element insertion in the whole document? Alternatively, how can I detect change of HTMLCollection's length property?
Thanks for any answer.
Here is a thought:
var cnt=0;
var f = Element.prototype.appendChild;
Element.prototype.appendChild = function(){
f.apply(this, arguments);
console.log("added",++cnt)
};
However you will need to see if it is the same element that is added and I have not figured out how to check the remove since that is parentNode.removeChild
If you want events on all selects in jQuery all you have to do is delegate
$(document).on("change","select",function() {
// all current and future selects will have this event
});
I'm attempting to create a system that, when one element is selected, shows an element of the same ID whilst hiding the previous without hiding all instances of that ID (i.e. it is only hidden if a certain class is present).
The first part (making an element 'active' and setting the ID variable) works fine, but I can't seem to get the secondary element to stop being set using the '.hidden' class.
The code I'm using for this part is
function showSelect() {
select = $(".active").attr('id');
$(".items").addClass("hidden");
$("#"+select).removeClass("hidden");
}
I've tried using $(select).remove... on the fourth line, as well as what is currently present, but to no avail.
The rest of the code can be found on http://jsfiddle.net/ActualRealJamz/2JZA6/
I'm not sure what I'm doing wrong here, and JSHint reports no syntax error of any kind - so in that there must be an error to my method.
If this happens to be of any use, Chrome reports an 'Unexpected identifier' on the line $(".items").addClass("hidden");.
Any help in this matter is most appreciated.
As Barmar pointed out in the comments, that fundamentally cannot work because you cannot have the same id on more than one element. If you do, the document is invalid and the browser is free to ignore the id values. (In practice, they typically act as though only the first element in the document with a given id value has that id, ignoring subsequent ones.)
You seem to be using the class items on the relevant elements, so it's straight-forward to do what you're looking to do. Assuming showSelect is attached to the relevant elements as a click handler, within showSelect, this will be the specific element that was clicked. So:
// Hooking it up
$(".items").click(showSelect);
// The function
function showSelect() {
$(".items").not(this).addClass("hidden");
$(this).removeClass("hidden");
}
No ids required at all.
I've noticed that, on some platforms, it can be very difficult to click text that is being continually modified. The click event doesn't always trigger when the user clicks elements that are being modified resulting in an unresponsive interface.
For example, see this http://jsfiddle.net/hq9Rh/2/
In that example, there are four elements:
Replaces its text value every 100th millisecond and is almost impossible to click.
Replaces its text with an identical text. Is equally difficult to click.
Only writes to the element if the text is different. It's much more responsive to clicks.
Static, and perfectly clickable.
Here's the code to update the four elements:
setInterval(updateList, 100);
var iteration = 0;
function updateList(){
iteration++;
$(".updating").text(iteration);
$(".replaceSameText").text("SameText");
var oldText = $(".replaceDifferentText").text();
var newText = "SameText";
if(oldText != newText)
$(".replaceDifferentText").text(newText);
}
What is going on? Is there any way to fix this?
I'm running Chrome 32 on Windows.
It's because the text node within the element you're updating keeps getting destroyed and recreated, so the click may miss the text node.
You can avoid it by updating the value of the text node, rather than destroying and recreating it:
$(".replaceSameText")[0].firstChild.nodeValue = "SameText";
Updated Fiddle
I have the following javascript working to insert AJAX responses into a div with id results:
document.getElementById("results").innerHTML=xmlhttp.responseText;
However, this adds all new elements after those already present. I need for the new elements to be inserted before everything else.
I know this is probably very trivial but I can't seem to find anyway to do it myself.
Thanks for any help!
With modern js you can utilize the prepend method. Currently caniuse.com says only of IE, Edge, and OperaMini are not supported.
ParentNode.prepend(nodesToPrepend);
e.g.,
ParentNode.prepend(newDiv);
Also, it automatically converts text into a text node so you could do the following for your use case:
document.getElementById("results").prepend(xmlhttp.responseText);
You want either this
results.insertAdjacentHTML( 'beforebegin', xmlhttp.responseText );
or this
results.insertAdjacentHTML( 'afterbegin', xmlhttp.responseText );
(the variable results of course being a reference to the DOM element)
So, the first one will insert the new content before the element itself (as a previous sibling), and the second one will insert it inside the element before any other children).
I don't remember the exact syntax, but it something like:
var newDiv = document.createElement("div");
newDiv.innerHTML=xmlhttp.responseText;
document.getElementById("results").childNodes.addAt(0,newDiv);
if you can use jQuery, it's just simple as:
$("#results").prepend(xmlhttp.responseText);