How can i use javascript (i assume) to clone a table row like ive beautifully illustrated in the picture below?
You can hookup a live event to all the buttons. If you give them a class of clone for instance the following will work.
$('input.clone').live('click', function(){
//put jquery this context into a var
var $btn = $(this);
//use .closest() to navigate from the buttno to the closest row and clone it
var $clonedRow = $btn.closest('tr').clone();
//append the cloned row to end of the table
//clean ids if you need to
$clonedRow.find('*').andSelf().filter('[id]').each( function(){
//clear id or change to something else
this.id += '_clone';
});
//finally append new row to end of table
$btn.closest('tbody').append( $clonedRow );
});
Please Note:
If you have elements in the table row with id's you will need to do a .each through them and set them to a new value otherwise you will end up with duplicate id's in the dom which is not valid and can play havoc with jQuery selectors
You can do this like so
If you want a really simple solution, just use innerHTML:
var html = document.getElementById("the row").innerHTML;
var row = document.createElement('p');
row.innerHTML= html;
document.getElementById("table id").appendChild(row);
For what purpose do you want to use the data? I've done similar things previously on data input forms and generally I've found it to be beneficial to the users not to manipulate everything in Javascript but to hook to store the data on the server and interface with AJAX.
The issue is that as soon as you start letting users do this sort of complex table manipulation and they accidentally hit the back button you end up with a lot of disgruntled punters. Coding up transient storage on a database isn't that much harder than manipulating Javascript and in fact can be easier as you can break the operations down more easily. Debugging is simpler for that reason too (you always have inspect access to the current state of your table).
Lots of option for handling via AJAX - the simplest being to just use a place-holder division and feed the whole table structure in as needed.
A jQuery example:
$(document).ready(function(){
$('TABLE.recs').delegate('INPUT.clone','click',function(e){
e.preventDefault();
var s = $(this).parent().parent().clone().wrap('<div>').parent().html();
$('TABLE.recs TBODY TR:last').after(s);
});
});
Related
I am currently making a website for a class that I am in. It is supposed to be a store, made in Pure HTML, CSS, and JavaScript (no libraries including jQuery). I am currently attempting at making a functional cart right now. My idea is to take the element that has the information about that item (image and name, but price I kept to be constant throughout to make it simpler). From here, I thought about serialising that element and saving it to localStorage so that I can load it from the cart page. When I try JSON.serialize(product) where product is the element of the item, it only ends up with "{}" and nothing else. XMLS.serialiseToString() only gives the element without the event handler. How am I supposed to make this work?
I also tried loading the event handler in the cart page too, but I cannot figure out a way to get the HTML element from a string. Could someone tell me how to make this work? I looked at a few other questions on here but it does not make much sense to me.
Edit: I got the serialisation and deserialisation working using XMLSerializer. However, I want to change the click event handler after deserialising the element. How am I supposed to make this work?
XMLSerializer should work.
You will need to provide more code for what you're doing with local storage and your event handler but based on the info you provided, I included some code with comments below.
//this is a test click handler function to see if it still works after being added to page
function testClickHandler() {
console.log('I still work after being added to document again.')
}
//initialize XML serializer
var serializer = new XMLSerializer();
//get html element from document
var html = document.querySelector('#serializemecapt');
//convert element to string
var htmlString = serializer.serializeToString(html);
//once element is converted to string you can save in local storage
//after you retrieve the element again from local storage, use the code below to insert it into your document again
//insert element back onto page
document.body.insertAdjacentHTML('afterbegin', htmlString);
<div id="serializemecapt" onclick="testClickHandler()">Click me to see if the click event still works after I'm pushed back into the document.<br/><br/></div>
Edit: If you want to change the click handler after serialization, you can do something like this (run the snippet below and see comments):
//this function will be removed before serialization
function originalFunction() {
console.log('I am the original function before serialization.')
}
//this function will be added after serialization
function newFunction() {
console.log('I am the new function after serialization.')
}
//get html element from document
var html = document.querySelector('#serializeme');
//apply originalFunction to div using addEventListener
html.addEventListener('click', originalFunction)
//new function to demonstrate serialization
function serializeHtml() {
//initialize XML serializer
var serializer = new XMLSerializer();
//remove event listener for originalFunction before serialization
html.removeEventListener('click', originalFunction)
//serialize html
var htmlString = serializer.serializeToString(html);
//insert element back onto page
document.body.insertAdjacentHTML('afterbegin', htmlString);
//change innerText on element for example purposes
html.innerText = 'I am the same div as above after serialization. I have new text and a new function. Click me now and I will run the new function.'
//add newFunction to div using addEventListener
html.addEventListener('click', newFunction)
}
//get button element from document
var serialButton = document.querySelector('#serialButton');
//apply serializeHtml function to button using addEventListener
serialButton.addEventListener('click', serializeHtml)
<div id="serializeme"><b>Click me</b> before serializing to run the original function.<br/><br/></div>
<p><b>Click button below to serialize the div above and apply a new function to the div after serialization.</b></p>
<button id="serialButton">Serialize</button>
I have a firebase database with some information in it, that I just constructed a table:
rootRef.on("child_added", snap => {
var name = snap.child("leagueName").val();
var code = snap.key;
$("#table_body").append("<tr><td> <button id="+code+" class='mdl-button mdl-js-button'>"+ name +" </button></td></tr>");});
So now I have arbitrary number of rows at my table, each has a button with it's unique ID.
next step is that I want each of them to be a link to some other page.
Is there a way to retrieve these ID's to create a js click function with them?
I mean I don't know what these ID's are and how many of them will be, since this is something the user will enter.
Maybe there's another more efficient way?
I think you may be looking for:
$('#table_body').on('click', 'btn', function() {
alert($(this).attr('id'));
document.location = 'https:/your.new.url/leagues/' + $(this).attr('id');
});
Of course if you want the elements to just be a link to another page, you should really consider making them <a href='...'> elements, as those are the idiomatic way to model links to pages. And in that case, you could also simply inject the keys when you generate the row in the table:
$("#table_body").append("<tr><td> <a id="+code+" href='https:/your.new.url/leagues/"+code+"' class='mdl-button mdl-js-button'>"+ name +" </button></td></tr>");});
I have a standard HTML formatted table, that dynamically generates the content, via Zend Framework. From which I have an issue altering the form internally PHP side. So I need to alter the tables appearance somehow. With that on the occasion I have an element show up in one of the rows and when this element shows up I want to break out of the table and then do something after it then start the table again.
Basically I want to inject the equivlant of
</tbody></table>/*other stuff*/<table><tbody> after the row containing the one element I seek which in this case is a label.
I tried $("label[for='theLable']").parents('tr').after('</tbody></table><br><table><tbody>') which appears to ignore the ending table parts add the br, and then does a complete open/close tag for table and tbody within the same table I am trying to break out of so inbetween tr tags basically it adds this new table
Whats the best way to approach this concept?
update with jsfiddle link
http://jsfiddle.net/cPWDh/
You can't really modify the HTML of the document the way you're thinking, since it's not a legitimate way to alter the DOM.
Instead, I would create a new table and .append the rows you want to move to it, which will automatically move them from their current location (instead of copying them):
$(document).ready(function() {
var $trow = $('label[for="specialLabel"]').closest('tr'),
$table = $trow.closest('table');
$('<table>').append( $trow.nextAll().andSelf() ).insertAfter($table);
});
http://jsfiddle.net/cPWDh/1/
this approach won't work in js. What you could do if the table has not too many rows is this:
var nextTable = $("table").after("/*other stuff*/<table id="nextTable"></table>");
//now you loop over the lines of your original table that you want to have after the "break", and move them to the nextTable:
var before = true;
$("table tr").each(function(){
if ($(this).has("[for='theLable']")) {
before = false;
}
if (!before) {
nextTable.append($(this));
}
});
I have used firebug and IE profilers and can see what function in my code is causing the slowness. Being new to jquery, the recommendations that I have read online are not clear to me. I have made an example page that shows the slow behavior when you check or uncheck a check box. No surprise that this is fast using Chrome.
The function that is slow can be found on line 139.
$('.filters input').click( function()
JSFiddle can be found here
The code is 122 KB and can be found here
UPDATE: if you know of any examples online that are similar in function and faster, please share.
i had a brief look through your code, but it was very hard to follow. it seemed as if you were looping through things many many times. i used a much simpler approach to get the list of all states.
your approach was
* make a massive string which contained every class (possibly repeated multiple times)
* chop it up into an array
* loop through the array and remove duplicates
i simply took advantage of the fact that when you select something in jQuery you get a set rather than a single item. you can therefore apply changes to groups of object
$(document).ready(function () {
//this will hold all our states
var allStates = [];
//cache filterable items for future use
var $itemsToFilter = $(".filterThis");
//loop through all items. children() is fast because it searches ONLY immediate children
$itemsToFilter.children("li").each(function() {
//use plain ol' JS, no need for jQuery to get attribute
var cssClass = this.getAttribute("class");
//if we haven't already added the class
//then add to the array
if(!allStates[cssClass]) {
allStates[cssClass] = true;
}
});
//create the container for our filter
$('<ul class="filters"><\/ul>').insertBefore('.filterThis');
//cache the filter container for use in the loop
//otherwise we have to select it every time!
var $filters = $(".filters");
// then build the filter checkboxes based on all the class names
for(var key in allStates) {
//make sure it's a key we added
if(allStates.hasOwnProperty(key)) {
//add our filter
$filters.append('<li><input class="dynamicFilterInput" type="checkbox" checked="checked" value="'+key+'" id="filterID'+key+'" /><label for="filterID'+key+'">'+key+'<\/label><\/li>');
}
}
// now lets give those filters something to do
$filters.find('input').click( function() {
//cache the current checkbox
var $this = $(this);
//select our items to filter
var $targets = $itemsToFilter.children("li." + $this.val());
//if the filter is checked, show them all items, otherwise hide
$this.is(":checked") ? $targets.show() : $targets.hide();
});
});
FIDDLE: http://jsfiddle.net/bSr2X/6/
hope that's helpful :)
i noticed it ran quite a bit slower if you tried to slideup all the targets, this is because so many items are being animated at once. you may as well just hide them, since people will only see the ones at the top of the list slide in and out of view, so it's a waste of processor time :)
EDIT: i didn't add logic for show all, but that should be quite a trivial addition for you to make if you follow how i've done it above
You could use context with your selector:
$('.filters input', '#filters_container').click(function()...
this limits the element that jQuery has to look in when selecting elements. Instead of looking at every element in the page, it only looks inside your $('#filters_container') element.
I'm building a multi-feed RSS reader for school.
aList is the div that encompasses each individual feed (the amount of feeds will fluctuate).
theTitle is the div that will be filled with the attribute of the current feed. Additionally, if clicked, it will load a list of attributes from the current feed into theContent.
I'm wondering how I can dynamically load the attributes into theContent when theTitle is clicked, since theContent and theTitle are going to be non-unique divs (I can't give them IDs).
Thanks for your help in advance,
-Andrew
document.getElementsByClassName('aList').getElementsByTagName('div')
You should look into jQuery selectors for that and other DOM Manipulation. Something like
$("div.theContent").attr("name", "value");
by using jquery, you may use code like the following:
$(".theTitle").bind("click", function(){
$el = $(this);
$el.parent().$(".theContent").load('ajax/content.php?news=' . $el.text());
});
this will make all your links clickable, an on click, update their corresponding content divs with the value of ajax/content.php?news=theTitle-value
Use a nice Javascript library such as Prototype or jQuery. Seems petty now, but these frameworks save you tons of time in the long run.
In both frameworks, you can select that div with:
$('div.theTitle')
With jQuery, you can do:
$('div.theTitle').click( function() {
var title = $(this).text();
var contentDiv = $(this).siblings('div.theContent');
// Do something with contentDiv and the title
} );
This will make every theTitle div have an onClick event that does something with its associated theContent div.
<div class="aList">
<div class="theTitle" onclick="fillContentBox(this)"></div>
<div class="theContent"></div>
</div>
And in your script ...
function fillContentBox(div) {
var theContentDiv = div.parentNode.getElementsByTagName("div")[1];
// statements that do things with theContentDiv
}
You have to be able to determine which element you want to update if you don't want to update more than one. If the elements are grouped inside something else that does have an "id" value, you can take advantage of that.