Getting a dom element before its displayed? - javascript

I currently am trying to use a library that requires a dom element to be passed to it.
However I am dynamically creating a layout like this so the dom element doesnt exist at that time.
I wanted to know how i can pass the current dom element which will eventually be rendered ?
function addControl(domeElement)
{
jsonTree.create(data, domeElement);
}
function () {
$(container).append(
"<div class='myfancydiv'>" + addControl(this Div) + "</div>"
);

You should use appendTo so that you can easily retrieve the element after it is appended, then pass that element to your function:
let domElement = $("<div class='myfancydiv'></div>").appendTo(container)[0];
addControl(domElement);
Note: [0] is simply a way to grab the actual DOM element from the JQuery Object, instead of a reference to the JQuery Object itself.
Example:
function demo(domEle) {
$(domEle).css({color: "blue"});
}
let el = $( "<p>Test</p>" ).appendTo( ".inner" )[0];
demo(el);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<h2>Greetings</h2>
<div class="container">
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>

Related

Jquery - if element contains a class, add HTML after element

I've got a booking form.booking-wrap with 2 elements in it, div#booking and then div.quantity
<form class="booking-wrap">
<div id="booking"></div>
/* insert div#message IF div.quantity is present inside div.booking-wrap */
<div class="quantity"></div>
</form>
The div.quantity is only present dynamically for some bookings.
What I am trying to achieve is that if the div.quantity is present, then I would like to insert an additional html div#message, but this new div should appear after div#booking and before div.quantity
I am trying the following jQuery:
if($('.booking-wrap:has(div.quantity)')){
$('#booking' ) .after( '<div id="message">Message</div>');
}
But that doesn't seem to work.
I then tried this:
$('.booking-wrap:has(div.quantity)').append($('<div id="message">Message</div>'));
This works and the new div appears, however it is just next to the quantity div.
How can I get it to show after the #booking , but before .quantity?
Any selector returns an object, you should check the length property of the returned object. Like $('.booking-wrap:has(div.quantity)').length
Though, I prefer $('.booking-wrap > div.quantity').length
if($('.booking-wrap > div.quantity').length){
$('#booking').after('<div id="message">Message</div>');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="booking-wrap">
<div id="booking">booking</div>
<div class="quantity">quantity</div>
</form>
Try using prepend instead of append, since the selector $('.booking-wrap:has(div.quantity) will return the (div.quantity) element.
Example:
$('.booking-wrap:has(div.quantity)').prepend($('<div id="message">Message</div>'));
You can use "hasClass()" jQuery function to check class is exist or not:
Try This
if($( ".booking-wrap" ).children('div').hasClass( "quantity" )){
jQuery('<div id="message">Message</div>').insertAfter('.booking');
}
Try This jQuery.
if($(".quantity").length ){
$('#booking' ).after( '<div id="message">Message</div>');
}
You need to put the div you are adding within a function.
if($('.booking-wrap:has(div.quantity)')){
$( "#booking" ).after(function() {
return '<div id="message">Message</div>';
});
}

jQuery append seems to ghost append in an _.each statement

As strange as it sounds my code is simply this :
$element = "<div>Testing</div>";
_.each($('.chat-messages'), function(el) {
el.append($element);
debugger;
});
If I inspect from the debugger, when I type el in console, I can clearly see that $element.el was successfully appended. However, when I go and click continue, the element was never added.
The $('.chat-messages') selector returns two objects. The second was has $element.el added just fine to it. The first one doesn't. Even though the first one definitely returns the same kind of object as the second one. And in the debugger, I can clearly see that the object was appended to el. It just is never added to the actual HTML. Just the representational object within the debugger.
Am I just not selecting el correctly? How could the first and second one be different?
This works fine although I had to use timeout because the div wasn't rendering until then
Do you think you have a similar problem like the UI isn't rendered yet?
This code works if the $element as the OP originally asked is a string value "<div>Testing</div>"
var f = function() {
$element = "<div>Testing</div>";
_.each($('.chat-messages'), function(el) {
el.append($element);
//debugger;
});
};
setTimeout(f, 100);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='chat-messages'>
<div class='chat-messages'>
<div class='chat-messages'>
<div class='chat-messages'>
EDIT:
After going through the comments, I did a quick research of how the append works and what happens if we swap the $element with an actual $("<div>Testing</div>") only to find out that the comments were true
Note 1:
- The $.each is not required as you can choose all the elements matching the result and append at once
var f = function() {
$element = $("<div>Testing</div>");
$('.chat-messages').append($element);
};
setTimeout(f, 100);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='chat-messages'></div>
<div class='chat-messages'></div>
<div class='chat-messages'></div>
<div class='chat-messages'></div>
Now lets use $.each
var f = function() {
$element = $("<div>Testing</div>");
$('.chat-messages').each(function(ix, el) {
$(el).append($element);
});
};
setTimeout(f, 100);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='chat-messages'></div>
<div class='chat-messages'></div>
<div class='chat-messages'></div>
<div class='chat-messages'></div>
Note 2:
Use of each to iterate through the elements and appending will not yield the desired result as explained in the comments and also append documentation (pasting it below)
You can also select an element on the page and insert it into
another:
$( ".container" ).append( $( "h2" ) );
If an element selected this way is inserted into a single location
elsewhere in the DOM, it will be moved into the target (not cloned):

How to save data using jQuery?

I have some dynamic data in my <div> element. Look at the sample below:
<div>345</div>
<div>3245</div>
When I click on the div element, the nested value will change.
var someVar = $(this).find(div);
someVar.empty();
someVar.append("<div>Number has changed</div>");
Sample:
<div>345</div>
<div>Number has changed</div>
And when I click again on the div, I need to return the previous value:
<div>345</div>
<div>3245</div>
Here's the question: How do I keep this value for returning the number every time I click on the div with changed text inside of it?
you need create some data attribute store the previous value.The each time click get the data from attribute and restore the current text to attr like this data-prev.No need to append .html() is enought to toggle
updated
$('div').click(function(){
var prev=$(this).html();
$(this).html($(this).data('prev'));
$(this).data('prev',prev)
console.log($(this).data('prev'))
})
.nested{
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>345</div>
<div data-prev="<div class='nested'>Number has changed</div>">3245</div>
You can use jQuery 'data' method.
$( "div" ).data( "number", 1 )
Then read it with:
( $( "div" ).data( "number" ) )
Documentation:
https://api.jquery.com/data/

Append additional html to cloned object in jquery

I want to add additional html in the cloned object.
var item = $("#clone")
.clone(true, true)
.attr({"id": "citem", "class": "row cartItem_" + item_id})
.css('display', 'block')
.appendTo("#all-items");
I know about wrap method but that is something else. I want to append html after this cloned object. Or somehow i can manipulate the HTML of the cloned object element.
This approach is to explain how the .clone() works, and covers all the states you ever mentioned in the question, such as..
Creating a clone of a DOM
Appending additional raw HTML to a clone
Manipulating the clone
Manipulating the content in the clone
Clone in another clone
Appending another clone to a clone
Appending HTML after this cloned object
$(function() {
//! Cloning the HTML
var $clonedContent = $('.content').clone();
// Manipulate the cloned element
// -- Update the existing content
$clonedContent.find('h5').text("My content just got manipulated");
// -- Adding raw HTML content
$clonedContent.append("<small> It's a raw HTML </small>");
// -- Adding property to an existing content
$clonedContent.find('small').addClass('make-me-day');
//! Getting another cloned content
var $anotherClonedContent = $('.content').clone();
// -- Another manipulation of another cloned content
$anotherClonedContent.find('h5').text("This is another cloned content");
// -- Manipulate the another cloned content's content
$anotherClonedContent.find('h5').addClass('make-me-day');
// -- Add another cloned content to the already manipulated & cloned content.
$clonedContent.append($anotherClonedContent);
//! Finally, add the clonedContent to the DOM, aaaand.. add more HTML afterwards.
$('#main').append($clonedContent, "<em> I added this HTML after the cloned object </em>");
});
.make-me-day {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<div class="content">
<h5> Just a simple content </h5>
</div>
</div>
Assuming you are trying to add html after the clone:
$("#toclone")
.clone()
.attr({"id":"cloned"})
.appendTo("#all-items")
.after("<div>some more content <em>after</em> the clone</div>");
The .appendTo() returns the element that was appended, so you can then manipulate it as required, eg using .after()
I think that's more easy than you imagine:
$(function(){
var item_id=0;
// function to clone your element
var newItem=function(){
item_id++;
return $('#clone')
.clone(true, true)
.attr({'id':'citem_'+item_id, 'class':'row cartItem_'+item_id})
.css('display','block')
.appendTo('#all-items');
};
// Clone element and edit what you want
newItem().html('hobby').css('color','blue');
// Clone element and append what you want
newItem().append(' - <i>spaghetti</i>');
// You can also find element by id
$('#citem_2').css('color','red');
//You can add buttons to do it
$('button:eq(0)').on('click',function(){
newItem().html('Your <b>html</b> here.');
});
$('button:eq(1)').on('click',function(){
newItem().append(' - Your <b>html</b> here.');
});
});
<button>New clone</button>
<button>New clone + append</button>
<div id="all-items">
<div id="clone">pizza</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
I took a close look to all answers and comments to this bounty question...
I can see that the bidder is kind of demanding, which is okay since 100 rep. points is valuable.
I think that the question contains two, in fact.
How to clone
How to «manipulate the HTML of the cloned object» - Wasif Iqbal on Sep 22th.
I think the question is intended to get explanations on how to manipulate the clone, not only on creation and appending to somewhere, but also afterward.
I really think my very cool example below could be a «valid answer» - Vixed on Sep 29th.
The other answers were good too, anyway... So a made a supplemental effort. ;)
First explanation of all:
Cloning an element is done by jQuery .clone(). So have a nice reading.
Then:
jQuery chaining is nice to append some other stuff «inside» or «before/after» the clone in a concise way, as demonstrated in other answers.
But to manipulate it afterward, like in another click event handler...
This is the trick to know, which is not explained in the previous reference:
You have to make sure to set a unique id attribute to it, instead of the same id as the original.
Because you know that an id shall be unique!
«One ring to rule them all.
One ring to find them, one ring to bring them all and in the darkness bind them.»
- A well known deamon said this while forging a curse...
Then... What more explanation could I give if it ain't clear?
Alert reader should have understood everything already.
I made a funny «clone-and-kill-it-game» to demontrate cloning and further manipulations.
For the «inspiration», I have to admit that I saw a japaneese zombie movie yesterday night...
lol!
Have fun with this code snippet:
(also on CodePen)
// Constants
var number = 1;
var revealed = false;
// The cloning function
$("#cloneIt").click(function(){
var cloning = $("#Human")
.clone()
.attr({"id": "Clone_number_"+number, "class":"clone"})
.appendTo("#CloneBucket");
$(this).val("Clone him again! It's fun!");
number++;
if(number==4){
$(".reveal").show();
}
if(number==9){
$(this).val("Enought! This is now illegal.").prop("disabled",true);
}
// Add them to select
var options="<option disabled selected class='deceased'>KILL THEM!</option>";
for (i=1;i<number;i++){
if( $("#CloneBucket").children().eq(i-1).hasClass("dead") ){
options += "<option value='"+i+"' class='deceased'>Clone #"+i+"</option>";
}else{
options += "<option value='"+i+"'>Clone #"+i+"</option>";
}
}
$("#cloneSelect").html(options);
if(revealed){
reveal(); // Sub function to add clones to a select element.
}
});
// Reveal clone numbers
$(".reveal").click(function(){
reveal();
setTimeout(function(){
$(".reveal").val("Kill a clone! (While it's not illegal!)").removeClass("reveal").addClass("shoot");
},50);
});
// Kill button
$("#page").on("click",".shoot",function(){
$(this).prop("disabled",true).val("Select one");
$("#cloneSelect").show();
});
// Select kill target
$("#cloneSelect").change(function(){
var thisCloneIs = parseInt($(this).val());
var niceShot = "#Clone_number_"+thisCloneIs;
$(niceShot).css({"opacity":0.3,"color":"red"});
$(niceShot+" .definition").html("I was the number"+thisCloneIs).parent().addClass("dead");
// Redish the option
$(this).find("option").eq(thisCloneIs).prop("disabled",true).addClass("deceased");
$(this).find("option").eq(0).prop("selected",true);
// Bravo!
var allDead = [];
setTimeout(function(){
$("#cloneSelect").find("option").each(function(index){
if( $("#cloneSelect").find("option").eq(index).hasClass("deceased") ){
allDead.push(true);
}else{
allDead.push(false);
}
});
if( allDead.indexOf(false)==-1 ){
// Reset this super gaming experience for a new.
$("#CloneBucket").html("");
$(".shoot").addClass("reveal").removeClass("shoot").val("Reveal clone numbers!").prop("disabled",false).hide();
$("#cloneIt").val("Clone again?").prop("disabled",false);
$("#cloneSelect").html("").hide();
revealed = false;
number = 1;
}
},50);
});
function reveal(){
$(".clone .definition").each(function(index){
var cloneIndex = index+1; // zero-based
$(this).html("I'm the number "+cloneIndex);
revealed = true;
});
}
img{
width:60px;
}
div{
text-align:center;
}
.reveal{
display:none;
}
#CloneBucket div{
display:inline-block;
padding:10px;
}
#CloneBucket{
margin:0 auto;
text-align:center;
}
select{
display:none;
margin:0 auto;
}
.deceased{
color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div id="page">
<input type="button" id="cloneIt" value="Want to clone him?"><br>
<br>
<div id="Human">
<img src="http://image.flaticon.com/icons/svg/10/10522.svg"><br>
<span class="definition">I'm a real human!</span>
</div>
<br>
<input type="button" class="reveal" value="Reveal clone numbers!">
<select id="cloneSelect"></select>
<div id="CloneBucket"></div>
<br>
</div>
Still waiting for clarification in the comments, but I think this solution is what you are looking for:
$('button').click(function() {
$('#clone').clone()
.append('<span style="color:red;">some other elements</span>')
.removeAttr('id')
.appendTo('#all-items');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button>Click to clone</button>
<div id="all-items">
<div id="clone">pizza</div>
</div>
Since the appendTo returns the original element that was appended, you can use after on the returned value to add some new element after the cloned element that you just appended:
$('button').click(function() {
$('#clone').clone()
.append('<span style="color:red;">some other elements</span>')
.removeAttr('id')
.addClass('cloned')
.appendTo('#all-items')
.after('<div>this element was added after the cloned element (no blue border here)</div>');
});
.cloned {
border: 1px solid blue;
margin: 5px;
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button>Click to clone</button>
<div id="all-items">
<div id="clone">pizza</div>
</div>
One can add to a collection at any time using jQuery's add() function.
This effectively adds to the collection, placing whatever is passed to add() after the clone itself, as opposed to append which places the content inside the clone, answering the question
"I want to append html after this cloned object"
var more1 = $('<span />', {html : '<em> and will</em>'}); // element(s) to add
var more2 = '<span> happen again....</span>'; // or strings of HTML for that matter
var item = $("#clone").clone(true, true)
.attr({"id": "citem"})
.show()
.add(more1) // add whatever after the clone
.add(more2) // before appending everything
.appendTo("#all-items");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="clone">
<span>All of this has happened before</span>
</span>
<br /><br /><br />
<div id="all-items"><!-- clone goes here --></div>
From the documentation
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.
The argument to .add()
can be pretty much anything that $() accepts, including a jQuery
selector expression, references to DOM elements, or an HTML snippet.
example : $("p").clone().add("<span>Again</span>").appendTo(document.body);
add() does not change the original collection, but returns a new collection, so if not chaining directly on the modified collection, one has to store that collection
var clone = $('#elem').clone(true, true);
var changed = clone.add('<div>new content</div>'); // clone is not changed
Manipulating the content inside a clone is done in the exact same way as manipulating any other collection with jQuery
Post something link this
var clone = parent.find('.divclone').clone();
clone.removeClass('identifier');
clone.removeClass('hide');
//.. code changes for the new clone
clone.find(".link-slug").attr('href',invstr_val.slug_url);
// append it again to the original
clone.insertAfter(parent.find(".divclone"));

Loading content in a target div using jquery

So the first part of the code works fine as it should be, the two grid and list view loads in the views-div when clicked, however, I want a default view shown in the views-div using jquery, I tried loading using clone and prependto but it doesn't work. any suggestion on how to do this?
note: the content I'm loading from the backend has tags and ID's so if I use the html markup to show a default content in the views-div the content repeats. So I'm hoping if use jquery to load content, the repeating will not occur.
here's a demo http://jsfiddle.net/soulsurfer/eta0uyye/
$(document).ready(function() {
$('.iw-grid-select, .iw-list-select').on('click', function() {
var aID = $(this).attr('href');
var elem = $('' + aID).html();
$('#iw-grid-view').fadeOut("slow", 1000);
$('#iw-listview').fadeOut("slow", 1000);
$('#iw-views-div').html(elem);
});
$( "#iw-grid-view" ).contents().find( ".iw-grid-list-col" ).clone().prependTo("#iw-views-div");
});
The simplest solution could be is to trigger a click event
$(document).ready(function() {
$('.iw-grid-select, .iw-list-select').on('click.view', function() {
var aID = $(this).attr('href');
var elem = $('' + aID).html();
$('#iw-grid-view').fadeOut("slow", 1000);
$('#iw-listview').fadeOut("slow", 1000);
$('#iw-views-div').html(elem);
}).first().trigger('click.view');
});
.iw-listview,
.iw-grid-view {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="iw-filter-col ">
grid view link
list view link
</div>
<div class="row iw-listing-view-row">
<div class="iw-grid-view" id="iw-grid-view">Grid view content</div>
<div id="iw-listview" class="iw-listview">list view content</div>
<div class="iw-views-div" id="iw-views-div">Content loading column</div>
<div id="loading"></div>
</div>
I know that this has been resolved, but just in case anyone was wondering where OP went wrong, I have a theory.
This:
$( "#iw-grid-view" ).contents().find( ".iw-grid-list-col" ).clone().prependTo("#iw-views-div");
Should be changed to this:
$( "#iw-grid-view" ).find( ".iw-grid-list-col" ).clone().prependTo("#iw-views-div");
If the .iw-grid-list-col element was an immediate child of #iw-grid-view, then find() wouldn't have found it when called on the return value of contents(). This is because find() searches through descendants of elements. The return value of contents(), in this case, would have included the .iw-grid-list-col element and find() would not have found it since it was a member of the array that find() was called on, rather than a descendant of a member of the array.
Removing contents() from that chain of function calls allows find() to search all of the descendants of #iw-grid-view instead of just the descendants of its immediate children.

Categories