What's the best way to re-initialize javascript without a page refresh
I'm currently trying to append an MDBootstrap <select> tag, which is not as simple as adding a child element. Instead I'm removing the element and reconstructing it with the updated data via AJAX request.
At the moment, the only possibility I see is just executing the code again after the element is recreated.
Apologies if this isn't clear enough.
What I'm attempting to try, which works, however it's not very clean:
$("#function-btn").click(function(){
$.get("api/endpoint/getprofiles", function(){}).done(function(data){
$(".select-wrapper.mdb-select.md-form").remove()
$("#charcontainer").html(data);
$('.mdb-select').materialSelect();
})
// Reinitialize other JQuery functions around the '.mdb-select' element (alot)
})
Consider the following html
<div id='wrapper'>
<div id='container'>
<span>Content</span>
</div>
</div>
If you're deleting and replacing #container you will not want to hook your selector on #container but rather your jQuery should hook onto the parent (#wrapper) first and then drill down.
Therefore it will look something like this.
$('#wrapper>#container').on('click',function(){
//do the thing
});
That way you're technically not hooking onto the element that's removed from the DOM but rather the parent (#wrapper) element even though the selector has the child.
Related
I want to have a button which toggles element in the document.
I don't want to use class display: none if/else statement. Instead, I want to appendChild if it doesn't exist and if it exists, then I want to removeChild.
There is an idea of what I want to achieve, but I have some problem there. The element is shown, but on next click, it is not removed, instead, I get multiple copies of it. (I think so). Please, no jQuery. Vanilla JavaScript only. Don't know is it important, but my-element is HTML <template>.
<body>
<button id="my-button">Toggle</button>
<template id="my-element">
<div>
Some content
</div>
</template>
<script>
let element = document.getElementById('my-element');
let content = element.content;
function toggle () {
if (document.body.contains(content)) {
document.body.removeChild(content);
} else {
document.body.appendChild(content);
}
}
let button = document.getElementById('my-button');
button.addEventListener('click', toggle, false);
</script>
</body>
You should understand that template exists outside of the loaded DOM, so no matter where you physically locate it in the code really won't make any difference later. Also, understand that when you want to access content of a template, you use .content, but after that content is injected into the DOM, it's not template.content anymore, it's part of the DOM.
So, you can't search the document for template .content because, after it gets inserted, it won't be template content in your document, it will be actual DOM content. You'll need some way of identifying it and a class is the simplest way.
Also, the documentation on templates says that you bring template content into the document with document.importNode, which you aren't using.
Next, always remember that .removeChild does what its name implies, it removes child elements. document.body.removeChild() can therefore only remove children of the body element, so you need to remember this. Your code may be OK for finding the imported node as a child of body, but that may not always be the case depending on where you inserted it. The code below dynamically locates the imported content's parent node and will always remove it, regardless of where it winds up being located in the DOM.
Lastly, and this is very important, although you have indicated that you don't want to hide/show the element and would rather append it and remove it, doing so is very expensive in terms of performance. Every time you add or remove an element from the DOM, the entire DOM has to be rebuilt and the node(s) you remove don't necessarily get removed from memory even though they are not present in the DOM anymore. So, do this at your own risk. It's actually much better (from a performance standpoint) to simply hide/show content.
let element = document.getElementById('my-element');
function toggle () {
// Attempt to reference the element in the document, not the template content
var imported = document.querySelector(".imported");
// Check for the element, not the template content
if (document.body.contains(imported)) {
// Element exists, call removeChild on its parent
imported.parentNode.removeChild(imported);
} else {
// Use .importNode to bring template content in:
document.body.appendChild(document.importNode(element.content, true));
}
}
document.getElementById('my-button').addEventListener('click', toggle);
<button id="my-button">Toggle</button>
<template id="my-element">
<div class="imported">Some content</div>
</template>
I am trying to toggle a div by clicking on a different div. The only relation that two divs share is that they are inside the same div. I have a DIV class comment which holds DIV class button that is supposed to toggle DIV class box when clicked. The box DIV is also inside the comment DIV. I am trying to use jQuery(this).find(".box").toggle();, but it is not working. I am triggering it with $( ".button" ).click(function(). The script is currently at the bottom of my body.
Could anyone please tell me what am I doing wrong here? I've been playing around with the function for a while now, but with no luck at all. Thank you in advance for your replies.
JSFIDDLE here
HTML
<div class="comment">
<div class="button">
show/hide .box with text1
</div>
<div class="box">
text 1
</div>
</div>
<div class="comment">
<div class="button">
show/hide .box with text2
</div>
<div class="box">
text 2
</div>
<div>
jQuery
$( ".button" ).click(function() {
jQuery(this).find(".box").toggle();
});
You can use the jQuery selector .siblings() to re-write your function like this:
$( ".button" ).click(function() {
$(this).siblings().toggle();
});
Here's a working fiddle to demonstrate.
All you really need to do is this:
$(this).parent().find(".box").toggle();
In short, change:
jQuery(this).find(".box").toggle();
To ONE of the following lines:
$(this).parent('.comment').find(".box").toggle();
$(this).closest('.comment').find(".box").toggle();
$(this).siblings(".box").toggle();
Full Explanation:
The reason it's not working is due to the call. Let's break down your call and see what exactly it's doing.
First we see a simple jQuery selector. This tells jQuery to look for a div containing the class button. Keep in mind, jQuery makes use of any CSS selector. So selecting an item in jQuery is as simple as using it's CSS selector!
$( ".button" )
Next you are assigning an event. In this case, that event is click, meaning you're telling a div having the class button to do something every time it is clicked. Keep in mind, however, not including a callback function is an easy way to trigger this event as well.
$( ".button" ).click(function() {
Now this next line is where your mistake takes place.
jQuery(this).find(".box").toggle();
The first mistake is the use of jQuery. after you're already making use of it's short sign, $. You only need use the elongated name if you are using jQuery's noconflict because another JS library you include might use $. In other words, if $('.button') works and is a jQuery object when used, then you don't need to use jQuery.. See more about this here.
Now, that aside, we can look at jQuery(this) as $(this). Whenever you use $(this) in an Event's callback method, you're referring to the element that the event was tied too. That means that $(this) in your function refers to $('.button'). The problem here is that you then want it to find an inner element containing the class box. Well according to your HTML, that can't happen since .box is a sibling, it is not within the inner HTML of .button. Thus you need to make a different call before you can find .box.
There are actually several solutions here. No solution is more "correct" than another, just simply different and possibly causes a different amount of "time" to run. Now I went with what I saw as being the most simple in that it gives you control over the parent element which contains ALL relevant elements to this function. I'll talk about possible alternatives in a minute.
$(this).closest('.comment')
The above line simply tells .button:clicked to look for the first parent element that contains the class .comment. In other words, this won't find any children or siblings, it will only go up from the current element. This allows us to grab the block that contains all relevant elements and information and thus make maneuvers as needed. So, in the future, you might even use this as a variable in the function, such as:
$('.button').click(function(e) {
var container = $(this).closest('.comment');
Now you can find anything within this element block. In this case you want to find box and toggle it. Thus:
$(this).closest('.comment').find(".box").toggle();
// Or with our variable I showed you
container.find(".box").toggle();
Now, there are plenty of alternatives based on your HTML layout. This example I've given would be good even if .box was buried inside more elements inside .comment, however, given your exact HTML, we see that .button and .box are siblings. This means that you could make this call different entirely and get the same result using something like:
$(this).siblings(".box").toggle();
This will allow our currently clicked and selected button element to look for ANY and ALL siblings having class box. This is a great solution and simple if your HTML is that simple.
However, many times, for "comment" type setups, our HTML is not so simple, nor is it static. It's usually something loaded after the page load. This means our general assignment of .click will not work. Given your exact HTML and not knowing a static Parent ID, I would probably write your code as:
$(document).on('click', '.button', function(e) {
$(this).siblings('.box').toggle();
});
What this does is allow for this click event to be assigned to ANY element containing .button for a class, whether loaded with page or even ten minutes after the page is up. However, the caveat often seen here is the assignment is placed on document. Should we assign a lot of events to document it could become quite convoluted and possibly slow down the client's browser. Not to mention the arguments held over all the other headaches this could cause. So here's my recommendation, make a static (loads with page, is a part of page's main HTML) loading area and do our dynamic assignment to that. For instance:
<div id"Comments"><!-- load comments --></div>
Then you can do the assignment as such:
$('#Comments').on('click', '.button', function(e) {
$(this).siblings('.box').toggle();
});
If you have any more questions, just comment!
Side Note .on is for jQuery versions 1.7+. If using older jQuery, use .live or .bind
I see all sorts of jQuery options such as append, prepend, appedTo etc. but I just want to take out the content of a div and append it to the inside of the body. The whole contents, so not by using .html() but being loads of other divs. These divs may have events attached as well so I don't want to mess them all up.
<div id="main">
<div id="anything" class="anything">
<p>hello etc.</p>
</div>
</div>
So I need to take out everything inside id="main"
So, something like $('#main').get-its-contents-and-append-to('body') would do it.
I guess I could write a lengthy script, but there must be a simple one-line jQuery option?
Something like this:
$('#main').detach().children().appendTo('body');
Omit the .detach() part if you want to leave the #main div in place but empty.
This will retain any event handlers or data associated with the elements being moved, as you can see here: http://jsbin.com/iguqew/1/edit
You should be able to use append:
$("body").append($("#main").html());
$("#main").empty();
You could also do this which should keep the event handlers in place:
$('body').append($("#main").children());
I have a div that has this elements:
<div id = "menu">
<a>Elemento1</a><br/>
<a>Elemento2</a><br/>
<a>Elemento3</a><br/>
</div>
Each time one of the elements gets clicked I want a new div with different content to be added beside this list, depending on which element is clicked, it should add a diferent list. I'm new to web development, and I found that using the jQuery function .replaceWith() may do it, but is there any way I can use this function, adding divs I got in other .html files?
Thanks!
To get a certain part of another HTML file, use jQuery load function. A basic usage in your case, would be:
$('#result').load('ajax/test.html #container_you_want_to_load');
To add an element after or before the link, you have a few choices. The question is if you really need it. Perhaps it's enough to define one target div into which you'll load your content. In that case, the above example would suit perfectly.
If you however want to add element next to <a> tag, consider using after or before jQuery functions.
To catch a click even on one of your links, check click
Why not just have <div id="content"></div> after the menu, then use
$("#content").load("your_file.html");?
replaceWith is used to replace some DOM elements with different ones. I don't think this function can solve this.
You can use .load function to get html files content and insert it wherever you want. Just bind a click event to every link and use their href atributtes to get the respective file. Don't forget to return false in the end of the event.
something like this:
<div id="menu">
Elemento1
Elemento2
Elemento3
</div>
<div id="content"></div>
$("#menu a").click(function(){
$("#content").load(this.href);
return false;
});
I am really wondering if jQuery remove function really remove elements from DOM.
First, I looked here but the answers are not convincing.
I encountered this problem when I noticed I am still able to manipulate elements on which I have called remove function.
My code:
<div id="container">
<div id="div">
This is a div
</div>
</div>
var div = $('#div');
$('#div').remove();
$('#container').append(div);
Note: My question is not how to solve this? but I want to understand what's going on here!
Actually, this code doesn't remove the #div from the dom, but if I have any data set to the #div, it will be lost. I am pretty confused now about the behaviour of remove function. Can anyone explain this please?
DEMO
I am convinced that div variable is not just a clone of the dom element, is a reference to it, because when I manipulate the div variable, (like div.html('something')) the div within the DOM get updated.
Or am I wrong?
remove() does indeed remove the element from the DOM.
However in your example, the element has been cached in memory because you assigned it to the div variable. Therefore you can still use it, and append it again, and it will still contain all the events the original did.
If what you say is right, why I loose the data bound to the div so?
If you check the source for remove() you'll see that it calls the internal cleanData function which removes the events and clears the data cache for the element. This is why you lose the information.
If you want to remove the element from the DOM, but keep the elements, use detach() instead.
Here's a fiddle to show the difference: http://jsfiddle.net/2VbmX/
had to delete the assigned variable:
delete div;