Fade In Document Fragment - javascript

I'm using a technique from this answer for fading in an appended element with jQuery:
$(html).hide().appendTo("#mycontent").fadeIn(1000);
And trying to apply it to a document fragment:
var docfrag = document.createDocumentFragment(),
div = document.createElement('div');
div.textContent = 'Fade This In';
docfrag.appendChild(div);
But when I try to fade in the fragment:
$(docfrag).hide().appendTo('#container').fadeIn();
I get this error from jQuery:
Uncaught TypeError: Cannot set property 'cur' of undefined
Does anyone know how to fade in the document fragment?
--
Trying to fade in appended list items? See answer below.

$('docfrag') is a DocumentFragment, which has no hide().
Here is the revised code in jsFiddle: link
Reason:
DocumentFragments are DOM Nodes. They are in memory when created and never part of the main DOM tree. Which means jQuery selector will not return as expected a DOM element.

I didn't specify this in my question, but the document fragment I'm appending is a series of list items.
Since the list is already rendered with other items, I didn't have the option of fading in a container div the way Blaise and adeneo do in their fiddles.
Fading in the container <ul> would mean fading in the entire list, including the items already there. And I couldn't add another container for just the new list items without breaking the markup or making it really messy.
My solution is a bit hack-ish but gets the job done. This is for a Backbone.js application, so the code here is simplified (and ugly) to get the basic point across without all the Backbone stuff.
var docfrag = document.createDocumentFragment(),
item1 = document.createElement('li'),
item2 = document.createElement('li');
item1.textContent = 'New List Item 1';
item2.textContent = 'New List Item 2';
docfrag.appendChild(item1);
docfrag.appendChild(item2);
$item1 = $(item1);
$item2 = $(item2);
$item1.addClass('hidden').hide();
$item2.addClass('hidden').hide();
$('#button').on('click', function() {
$(docfrag).appendTo('#list');
$('#list').find('.hidden').fadeIn();
});
Once the new list items are accessible to jQuery (in my case, after running render() on their Backbone views), I hide them and add a class hook for fading them in later.

Related

Parent cannot .append() .prepend() the same created element

Interested to know if anyone can help describe the internals for the behaviour I am seeing.
Essentially, when creating a new dom element (then storing in a const) this element cannot be appened and prepended to the same parent element.
Example:
const ul = document.querySelector('ul');
const button = document.querySelector('button');
button.addEventListener('click', () => {
const li = document.createElement('li');
li.textContent = 'new li';
ul.prepend(li);
ul.append(li);
});
It seems the last call to either append or prepend, note if you call prepend last the new element is only added to start of the ul.
Digging into this it seems the cloning the node works prior to the subsequent append/prepend call.
const li = document.createElement('li');
li.textContent = 'something new to do';
ul.prepend(li);
const newLi = li.cloneNode(true);
ul.append(newLi);
However I'm interested to know the inner workings of this and why you can't seem to call against the same element? Can anyone shed any light on this as the mozilla docs don't seem to shed any light on this.
Fiddle: https://jsfiddle.net/gf7b0pom
Thanks everyone!
I think the confusion here is perhaps your understanding of what is stored created and stored in the line const li = document.createElement('li');. In this case, li doesn't contain a template that can be used over and over- when you use document.createElement() you are creating a single instance of an element of your choice. That single instance can only be in one place at a time.
As an analogy, I believe you are imagining li to be something like a rubber stamp, that can be used anywhere on a sheet of paper to make a list item. In reality, li is more like a sticker -- it can only be in one place on the paper at a time. When you run:
ul.prepend(li);
ul.append(li);
...it is like you stick your list item sticker to the front of the list, then you peel it off and stick it to the back of the list. This is why you need to call .cloneNode(true)-- it is essentially giving you a duplicate sticker to use elsewhere.
The reason is actually simple. When you create a new element, you create only one element. In your event listener, you first prepend that element then you append the same element.
ul.prepend(li);
ul.append(li);
So code is doing what you ask. It is moving the element but it is using the same element because you don't have a 2nd element.
On the other hand you want to append and prepend total of 2 elements which contains the same shape/data.
So you need 2 DOM elements for that.
If you also clone an element, you can also use it once. So if you want to append that element to multiple places, then every-time you need to clone then append.

.appendChild() an HTML element on click

I wanted to copy an entire row including its' siblings and contents on button click. When I click the button the element, it appears in the console but doesn't append to the page. This is my code:
It doesn't show any error messages. I've tried innerHTML/outerHTML or append() it doesn't work.
$(document).ready(function() {
$('#addSubFBtn').on('click', function() {
var itm = document.getElementById("trFb");
var wrapper = document.createElement('div');
var el = wrapper.appendChild(itm);
document.getElementById("tbFb").append(el);
console.log(el);
});
});
Seems like what you're trying to do is clone the item after you get it from your document. W3schools website explains how to accomplish this. Check out the link: https://www.w3schools.com/jsref/met_node_clonenode.asp
Once you clone the node, [appendchild] should work as intended
Not sure (as said without seeing related HTML) but i see flaw in your logic:
var itm = document.getElementById("trFb");
still exist on the document(so in the page) so you've to retrieve it before you want to add/move it to another place.
using .removeElement will return you removed element(or null if no element matche the selector) so correct script should be:
var itm=document.getElementById("trFb").parentNode.removeChild(document.getElementById("trFb"));
as shown here to remove element you've to use method on to parent element.
So you can add it to any other element existing.
For more specific use or element created in global JS variable (such an createElement not yet appended) you can see :document.createDocumentFragment(); as explained here https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment

Trying to find out one of my overflowed div's heights thanks to .scrollHeight

I'm trying to figure out my content div's height when overflowed with content thanks to the nifty .scrollHeight javascript function. However, when I alert this height I'm getting an "undefined" result. I'm fairly new to javascript so I might have made some really dumb mistake:
http://codepen.io/anon/pen/GJOVvd
basically looks like this in my html (because Stack Overflow doesn't let me just post codepen links):
<script>var intElemScrollHeight = document.getElementsByClassName("content").scrollHeight;
alert(intElemScrollHeight + " px");
</script>
I made a quick codepen which really resembles my problem, except that the height of my content container in my actual project depends on the height of the header, but that changes naught I believe, as I'm still getting that "undefined".
document.getElementsByClassName returns an array of elements matching the given class name. This might be only one, or multiple. The change you have to do is to get the first element of the results array:
var intElemScrollHeight = document.getElementsByClassName("content")[0].scrollHeight;
alert(intElemScrollHeight + " px");
For more information on getElementsByClassName see MDN: Document.getElementsByClassName
If you have multiple elements with a class content what you have to do is to iterate over the result. See this stackoverflow thread: Iterating over Results of getElementsByClassName.
Essentially, the solution is the following:
var els = document.getElementsByClassName("myclass");
Array.prototype.forEach.call(els, function(el) {
// Do stuff with the element
console.log(el.tagName);
});
You should use
var intElemScrollHeight = document.getElementsByClassName("content")[0].scrollHeight;
because if you try to getElementByClassName, it will return the array that includes all html elements that have "content" class. So you have to give index 0 as in your case it has only div or html element that has "content" class. It is advised to use document.GetElementById if there are more that one element assigned same class.

How to duplicate a div in JavaScript

I was wondering how I can duplicate a DIV element a few times through JavaScript without duplicating the DIV in my html code?
Let's assume the you selected the div doing something like:
var myDiv = document.getElementById("myDivId");
The DOM API contains a cloneNode method which you can use
var divClone = myDiv.cloneNode(true); // the true is for deep cloning
Now you can add it to the document
document.body.appendChild(divClone);
Here is a short self contained code example illustrating this

Javascript Sections

I have a website I want to take that always has the same section with the same id with all the content I want to display. I'm not very amazing at javascript and I'm wondering how I could remove everything but a specific section.
Would the best approach be to just do a loop that goes through all the elements in the DOM and remove everything but the section with the id I want to keep? If I go that approach how do I keep it from removing all the elements inside that section?
Perhaps another way to do this more efficiently would be:
document.body.innerHTML = document.getElementById( 'saveContentId' ).innerHTML
Removing one node includes all its children, so you won't need to loop over all elements in the whole document. I see two possibilities:
get the section, remove all its siblings in the current parent, and then walk up the DOM tree until document.body, while removing all siblings.
get the section and detach it from the document. Then clear document.body and re-attach the section there
The first solution seems cleaner to me, so here some sample code:
function removeEverythingBut(el) {
while (el != document.body) {
var par = el.parentNode;
for (var i=par.childNodes.length-1; i>=0; i--)
if (par.childNodes[i] != el)
par.removeChild(par.childNodes[i]);
el = par;
}
}
// usage:
removeEverythingBut(document.getElementById("my-section"));
you can save only the element you want and delete all other elements. Also I recommend using Jquery

Categories