How to I undo .detach()? - javascript

I'm using JQuery 1.5 and the following code to detach li elements w/ a certain class when a button is clicked. What I want to know is, when that button is clicked again, how do I add the element back onto the page?
<script>
$("#remove").click(function () {
$('li.type').fadeOut(300, function() { $(this).detach(); });
});</script>

The question is: where on the page do you want to put the element back? If, for example, all the li elements go back inside <ul id="foo"></ul> you might use something like this:
var items = [];
$('li.type').fadeOut(300, function() {
items.push( $(this).detach() );
});
$('#replace').click(function() {
for(var i = 0; i < items.length; i++) {
$("ul#foo").append(items[i]);
}
items = [];
});

here u can't for loop.
var demo;
$('li.type').fadeOut(300, function() {
demo = $(this).detach();
});
$('#replace').click(function() {
$("ul#foo").append(demo);
});

Related

How do invoke an already existing jquery function on an html anchor?

I created expandable content using jquery on several divs with unique ids. The code is working but now I also want to trigger this function from a top navigation using an anchor. I have tried several things but nothing works. I am very new to jquery so any help would be greatly appreciated.
I am specifically trying to invoke the click() function on each anchor.
Here is my jquery:
(function($) {
$(document).ready(function () {
var panelspeed = 500;
var totalpanels = 6;
var defaultopenpanel = 0;
var accordian = true;
var panelheight = new Array();
var currentpanel = defaultopenpanel;
var iconheight = parseInt($('.icon-close-open').css('height'));
var highlightopen = true;
//Initialise collapsible panels
function panelinit() {
for (var i=1; i<=totalpanels; i++) {
panelheight[i] = parseInt($('#cp-'+i).find('.expandable-panel-content').css('height'));
$('#cp-'+i).find('.expandable-panel-content').css('margin-top', -panelheight[i]);
if (defaultopenpanel == i) {
$('#cp-'+i).find('.icon-close-open').css('background-position', '0px -'+iconheight+'px');
$('#cp-'+i).find('.expandable-panel-content').css('margin-top', 0);
}
}
}
$('.expandable-panel-heading').click(function() {
var obj = $(this).next();
var objid = parseInt($(this).parent().attr('ID').substr(3,2));
currentpanel = objid;
if (accordian == true) {
resetpanels();
}
if (parseInt(obj.css('margin-top')) <= (panelheight[objid]*-1)) {
obj.clearQueue();
obj.stop();
obj.prev().find('.icon-close-open').css('background-position', '0px -'+iconheight+'px');
obj.animate({'margin-top':0}, panelspeed);
if (highlightopen == true) {
$('#cp-'+currentpanel + ' .expandable-panel-heading').addClass('header-active');
}
} else {
obj.clearQueue();
obj.stop();
obj.prev().find('.icon-close-open').css('background-position', '0px 0px');
obj.animate({'margin-top':(panelheight[objid]*-1)}, panelspeed);
if (highlightopen == true) {
$('#cp-'+currentpanel + ' .expandable-panel-heading').removeClass('header-active');
}
}
});
function resetpanels() {
for (var i=1; i<=totalpanels; i++) {
if (currentpanel != i) {
$('#cp-'+i).find('.icon-close-open').css('background-position', '0px 0px');
$('#cp-'+i).find('.expandable-panel-content').animate({'margin-top':-panelheight[i]}, panelspeed);
if (highlightopen == true) {
$('#cp-'+i + ' .expandable-panel-heading').removeClass('header-active');
}
}
}
}
//Uncomment these lines if the expandable panels are not a fixed width and need to resize
$( window ).resize(function() {
panelinit();
});
$(window).load(function() {
panelinit();
}); //END LOAD
}); //END READY
})(jQuery);
The html for the expandable jquery content is:
<div class="expandable-panel" id="cp-3">
<div class="expandable-panel-heading">
<h2>Testimonials<span class="icon-close-open"></span></h2>
</div>
<div class="expandable-panel-content">
<p>Panel HTML...</p>
</div>
</div>
The html anchors that I want to trigger the click() function are:
<ul class="nav">
<li class="nav">What is Justice Court Judge?</li>
<li class="nav">About Reeves Jones</li>
<li class="nav">Testimonials</li>
<li class="nav">Polling Locations</li>
<li class="nav">Map</li>
<li class="nav">Contact</li>
</ul>
Thank you in advance for your help!
If I understand correctly, you don't want to trigger the click event for the anchors, but instead you want to trigger the click event of the corresponding navigation element when an anchor is clicked.
You can do that by adding the following code inside your document-ready function:
$('.nav a').click(function() {
$($(this).attr('href')).find('.expandable-panel-heading').click();
});
This code registers a click handler on all the <a> elements inside the .nav element. It uses the href value of the clicked <a> element to get a jQuery object representing the navigation element.
In this case, you should not place the "onclick" attribute on the <a> elements.
BTW: For valid HTML, you should nest the <a> elements inside the <li> elements, not the other way around.
I recommend not to use inline event handlers.
You can add the following to your jquery code:
$(".nav").find('a').trigger("click");
$(".nav").find('a').click(function(){
//your code
})

Appending an element to a cloned element

I have a form with an HTML table that has a button (#addRows) that when clicked will clone the first table row and append it to the bottom of the table.
This table resides in a section of HTML with some other input fields that can also be cloned and appended onto the bottom of my form. When I am cloning the section I am changing all child element ID's to include a number that can be iterated dependent on how many times the user clones the section.
Example
<div id="someID"> ... </div>
<div id="someID2"> ... </div>
<div id="someID3"> ... </div>
I am doing this with JQuery like this
$(function() {
var $section = $("#facility_section_info").clone();
var $cloneID = 1;
$( ".addSection" ).click(function() {
var $sectionClone = $section.clone(true).find("*[id]").andSelf().each(function() { $(this).attr("id", $(this).attr("id") + $cloneID); });
$('#facility_section_info').append($sectionClone);
$cloneID++;
});
});
When I clone the section that holds the table I am also cloning the #addRows button which when clicked should append a table row to the table it is being clicked on. However if I clone my section and I click on my second `#addRows button it will clone my table row but it is appending to my first table and not the second.
Here is my addRows button and event handler
<input type="button" value="+" id="addRows" class="addRows"/>
$(function() {
var $componentTB = $("#component_tb"),
$firstTRCopy = $("#row0").clone();
$idVal = 1;
$(document).on('click', '.addRows', function(){
var copy = $firstTRCopy.clone(true);
var newId = 'row' +$idVal;
copy.attr('id', newId);
$idVal += 1;
copy.children('td').last().append("Remove");
$componentTB.append(copy);
});
});
My question is, when I clone my section of HTML that holds my table and #addButton how can I ensure that when the user clicks on the original button it will clone and append to that table or if I click the cloned button it will clone and append to the cloned table only?
If anything is unclear please let me know so I can try to better explain what I am trying to do, thanks.
Here is a JSFiddle demonstrating the problem I am having.
Because I truly love you BigRabbit, here is where I got to. You will see at least one useful fix here:
var $sectionClone = $section.clone(true);
$sectionClone.find("*[id]").andSelf().each(function () {
$(this).attr("id", $(this).attr("id") + $cloneID);
});
and a fix for an issue you did not report yet
$copy.children('td').last().append(' Remove');
using
$("#facility_section_info").on('click', '.remove', function (e) {
e.preventDefault();
$("#"+$(this).data("removeid")).remove();
});
FIDDLE
$(function () {
var $componentTB = $("#component_tb"),
$firstTRCopy = $("#row0").clone(),
$section = $("#facility_section_info>fieldset").clone(),
$cloneID = 0,
$idVal = 0;
$("#facility_section_info").on('click', '.remove', function (e) {
e.preventDefault();
$("#"+$(this).data("removeid")).remove();
});
$("#facility_section_info").on('click', '.addRows', function () {
$idVal++;
var $copy = $firstTRCopy.clone(true);
var newId = 'row' + $idVal;
$copy.attr('id', newId);
$copy.children('td').last().append(' Remove');
$(this).closest("fieldset").find("tbody").append($copy);
});
$("#facility_section_info").on("click", ".addSection", function () {
$cloneID++;
var $sectionClone = $section.clone(true);
$sectionClone.find("*[id]").andSelf().each(function () {
$(this).attr("id", $(this).attr("id") + $cloneID);
});
$('#facility_section_info').append($sectionClone);
});
});

jQuery animation skipped when clicking quickly

Please take a look at this jsfiddle
If you click on the divs on the top quickly enough, you'll find that eventually two divs end up appearing. I've had this problem with jQuery before as well. I just ended up disabling the buttons (or animation triggers) in that case, but I'm wondering if there is a more elegant solution to this.
Here is my jQuery code -
$(function () {
var _animDuration = 400;
$("#tabLists a").click(function () {
var attrHref = $(this).attr('href');
// Get shown anchor and remove that class -
$('.shownAnchor').removeClass('shownAnchor');
$(this).addClass('shownAnchor');
// first hide currently shown div,
$('.shownDiv').fadeOut(_animDuration, function () {
debugger;
// then remove the shownDiv class, show the clicked div.
$(this).removeClass('shownDiv');
$('#' + attrHref).fadeIn(_animDuration, function () {
// then add that shownDiv class to the div currently being shown.
$(this).addClass('shownDiv');
})
});
return false;
});
});
I'm using callbacks everywhere. I would like a solution that would queue up the animation rather than, not allow me to click
try this code with a check var:
$(function(){
var check = 1;
var _animDuration = 400;
$("#tabLists a").click(function(){
if(check == 1){
check = 0;
var attrHref = $(this).attr('href');
// Get shown anchor and remove that class -
$('.shownAnchor').removeClass('shownAnchor');
$(this).addClass('shownAnchor');
// first hide currently shown div,
$('.shownDiv').fadeOut(_animDuration, function(){
debugger;
// then remove the shownDiv class, show the clicked div.
$(this).removeClass('shownDiv');
$('#' + attrHref).fadeIn(_animDuration, function(){
// then add that shownDiv class to the div currently being shown.
$(this).addClass('shownDiv');
check = 1;
})
});
}
return false;
});
});
DEMO

Loop through list using Jquery

Total js newb here.
Here is the HTML
Size 8.5
<div class="product1">
<ul class="sizeAvail" style="display:none;">
<li>8</li>
<li>8.5</li>
<li>9</li>
<li>9.5</li>
<li>10</li>
</ul>
</div>
<div class="product2">
<ul class="sizeAvail" style="display:none;">
<li>8</li>
<li>8.5</li>
<li>9</li>
<li>9.5</li>
</ul>
</div>
Here's the 'logic' of what I need...
When the user clicks the Link
Capture the id of that element
Set that as a variable
Loop through li for all ul that have class 'sizeAvail'
If li element matches variable
stop looping and move onto next ul
If ul does not have li that matches variable
set class of container div to 'hide'
This is where I'm at so far...any help would be greatly appreciated.
<script type = "text/javascript" > $(document).ready(
$(".dur").click(function () {
var clickedSize = $(this).attr("id");
$(".sizeAvail").each(function (li,+) {
alert($(this).text());
});
});
</script>
Here is a working fiddle:
http://jsfiddle.net/Hive7/uZTYf/
Here is the jquery I used:
$(".dur").click(function () {
var clickedSize = this.id;
$(".sizeAvail li").each(function () {
if($(this).text() == clickedSize) {
$(this).parent().show();
} else {
$(this).hide();
}
});
});
What you are currently doing is not right as you aren't looping through the children of .sizeAvail because you didn't directly state though what you did state wasn't in quotes like most aspects of jquery need to be.
If this still does not work make sure you have a jquery library
Or you can use the pure js option:
var $items = document.getElementsByClassName('sizeAvail');
var $dur = document.getElementsByClassName('dur');
for (i = 0; i < $dur.length; i++) {
$dur[i].addEventListener('click', durClick);
}
function durClick() {
var clickedSize = this.id;
for (i = 0; i < $items.length; i++) {
var $liElems = $items[i].getElementsByTagName('li');
for (i = 0; i < $liElems.length; i++) {
if ($liElems[i].innerHTML == clickedSize) {
$liElems[i].parentNode.style.display = 'block';
$liElems[i].style.display = 'block';
} else {
$liElems[i].style.display = 'none';
}
}
}
}
http://jsfiddle.net/Hive7/uZTYf/2/
everything you are trying to do is pretty simple syntax-wise. you can find documentation on methods to use in a number of places. you could simply use javascript for this but i am assuming you want to use jQuery
on a high level you'll want to use the jQuery selector to get all UL objects and then for each UL loop over all LI children, e.g.:
$('ul').each(function() {
$(this).find('li').each(function(){
});
});
to get the data you are looking for, you can use jQuery methods like addClass(), attr(), etc.
You may use this. Set a flag when checking all li's of a div. If none li has same value as the id, at the end hide the div.
$(document).ready(function(){
$(".dur").click(function () {
var clickedSize = this.id;
$(".sizeAvail").each(function(){
var hide = 1;
$(this).children('li').each(function(){
if(clickedSize == $(this).text()) hide=0;
});
if(hide){
$(this).closest('div').hide(); //Or $(this).parent().hide();
}
});
});
});
JSFIDDLE
You may try this too
$('a.dur').on('click', function(e){
e.preventDefault();
var id = this.id;
$('ul.sizeAvail li').each(function(){
if($(this).text() == id) $(this).closest('ul').addClass('hide');
});
});
EXAMPLE.
Demo: http://jsfiddle.net/QyKsb/
This is one way to do it, as you were doing. However, i don't, personally like cluttering html with data as that. But it maybe good choice in some situations but i dont like it.
also you cant give id a value that starts with numbers.
var products= $("div[class^='product']"),
dur =$('.dur');
dur.click(change);
function change(){
var size= $(this).data('size');
products.each(function(){
var d = $(this);
d.find('.sizeAvail>li').each(function(){
d.hide();
if($(this).text()==size) { d.show(); return false;}
});
});
}
You can use a combination of not, has and contains selectors to get the matched elements and set a class on them using addClass.
Ref:
http://api.jquery.com/not-selector/
http://api.jquery.com/has-selector/
http://api.jquery.com/contains-selector/
http://api.jquery.com/addClass/
Code:
$(".dur").click(function () {
$(".sizeAvail:not(:has(li:contains('"+$(this).prop("id")+"')))").addClass('hide')
});
Demo: http://jsfiddle.net/IrvinDominin/t8eMD/

multiple functions in the document.ready function

here's my code:
$(document).ready(function () {
$('.flip1').click(function () {
$('.panel1').slideToggle("slow");
});
$('.flip2').click(function () {
$('.panel2').slideToggle("slow");
});
$('.flip3').click(function () {
$('.panel3').slideToggle("slow");
});
$('.flip4').click(function () {
$('.panel4').slideToggle("slow");
});
});
I want to make a loop with .flip as the variable (flipVar) and .panel as (panelVar)
Well if it were my page I'd make sure that those elements all shared a class so that I wouldn't need to loop. However, you could do this:
for (var i = 1; i <= 4; ++i) $('.flip' + i).click((function(i) {
return function() { $('.panel' + i).slideToggle('slow'); };
})(i));
The loop variable has to be trapped in a closure so that each "click" handler references the proper value. Again, I really wouldn't do it this way. I'd make the "flip" elements share a class, and then keep that index (the implicit reference to a corresponding "panel") in a separate class element or in a "data-" attribute. Then the handler could find the panel using that value.
edit — as a hack, you could leverage the fact that the class names of the related elements are both of the form "somethingNN", where "NN" is the numeric part. You could strip off the number and then append it to "panel":
for (var i = 1; i <= 4; ++i) $('.flip' + i).click(function() {
var panelClass = this.className.replace(/.*\bflip(\d+).*/, "panel$1");
$(panelClass).slideToggle('slow');
});
Even though you want to run the selector in a loop, I wouldn't do it like that because you're doing multiple DOM selections. You can get it done with one DOM selection:
$(document).ready(function () {
$('div[class^=flip]').each(function ( idx ) {
$(this).click(function() {
$('.panel' + (idx + 1)).slideToggle("slow");
});
});
});
This will work assuming that the flip elements occur on the page in their numerical order.
This uses the attribute starts with selector to get all <div> elements that have a class name starting with "flip". Change the tag name if it is different, or remove it if they don't all have the same tag.
It uses the index that .each() makes available to you in order to toggle the correct .panel.
$(document).ready(function () {
for (var i=1; i<=4; i++) {
(function(i) {
$('.flip'+i).click(function () {
$('.panel'+i).slideToggle("slow");
});
})(i);
}
});
try this:
$(function(){
for(var i=1;i<5;i++){
$('.flip'+i).click(function () {
$('.panel'+i).slideToggle("slow");
});
}
});
PS:- don't use this it will not work as pointed out by #patrick

Categories

Resources