I have a couple of objects which I use to make and remove elements, that is working just fine. But I can't get it to work with existing elements in the DOm tree. I think there is some error with how the event listeners are set up, but I can't spot it.., when I use the buttons I create with js, they remove the elements added dynamically instead of the elements itselfs. Basically I'm adding a event to body onLoad which is calling a method "initBody" to iterate through every child of a wrapping element, and adds a span element and event to each which belongs to a certain classname. Any clue on what I'm doing wrong here would be of great help as I'm rather new with javascript. I cant link to this yet, but there is an example at http://gjenklang.no/js/ Code is as following /* * Copying and moving elements * syntax: Move.element('e', target', 'move/copy'); */ var Move = { // todo: fix elementname recursivly fixName: function(node, number){ var amt = node.childNodes.length - 1; for (var i = 0; amt >= i; i++) { if (node.childNodes[i].name) { node.childNodes[i].name = node.childNodes[i].name + number; } if (node.childNodes[i].childNodes.length > 0) { Move.fixName(node.childNodes[i], number); } } }, //copying elements copy: function(e, target, name){ var eId = document.getElementById(e); var copyE = eId.cloneNode(true); var cLength = copyE.childNodes.length - 1; copyE.id = name; if (copyE.childNodes.length > 0) { Move.fixName(copyE, name); } document.getElementById(target).appendChild(copyE); return copyE; }, element: function(e, target, type, name){ var eId = document.getElementById(e); if (type == 'move') { document.getElementById(target).appendChild(eId); } else if (type == 'copy') { this.copy(e, target, name); } } }; /* * ******** DOM, get/add/remove *** */ var Dom = { get: function(el){ if (typeof el === 'string') { return document.getElementById(el); } else { return el; } }, add: function(el, dest){ var el2 = this.get(el); var dest2 = this.get(dest); dest2.appendChild(el2); }, remove: function(el){ var el2 = this.get(el); el2.parentNode.removeChild(el2); } }; var Event = { add: function(){ if (window.addEventListener) { return function(el, type, fn){ Dom.get(el).addEventListener(type, fn, false); }; } else if (window.attachEvent) { return function(el, type, fn){ var f = function(){ fn.call(Dom.get(el), window.event); }; Dom.get(el).attachEvent('on' + type, f); }; } }() }; function initBody(){ var td = Dom.get("verv-wrap"); var num = 0; for (var i = 0; td.childNodes.length > i; i++) { if (td.childNodes[i].className == "dotted") { var txt = document.createElement("span"); txt.innerHTML = "remove " + num; txt.className = "pointer"; Dom.add(txt,td.childNodes[i]); Event.add(txt, 'click', function(ex){ Dom.remove(td.childNodes[i]); }); num++; } } } /* *** Run at start */ Event.add(window, 'load', function(){ initBody(); var inc = 0; Event.add('add', 'click', function(){ inc++; var copy = Move.copy('verv-template', 'verv-wrap', 'verv-div-'+inc); var txt = document.createElement("span"); txt.innerHTML = "remove " + inc; txt.className = "pointer"; Dom.add(txt, copy); Event.add(txt, 'click', function(ex){ Dom.remove(copy); }); }); }); Code (markup):
What is not working, is the buttons to remove the elements allready there, called "posted elements". I'm trying to get those to behave similar as to the ones you create by the "add element" button.
for (var i = 0; td.childNodes.length > i; i++) { if (td.childNodes[i].className == "dotted") { var txt = document.createElement("span"); txt.innerHTML = "remove " + num; txt.className = "pointer"; Dom.add(txt,td.childNodes[i]); Event.add(txt, 'click', function(e) { if (e.target) var targ = e.target; else if (e.srcElement) var targ = e.srcElement; if (targ.nodeType == 3) // defeat Safari bug targ = targ.parentNode; Dom.remove(targ.parentNode); }); num++; } } Code (markup): You were using Dom.remove(td.childNodes); Which didn't work because when the function was invoked it took the value of i, which was whatever i was in that scope, which was whatever it was in the last iteration. You could have solved that by using a closure, but you still had the problem that if you remove items that come before the last item, then the indexes get screwed up. So it's best just to pass the parent of the event target.
Thanks a lot LogicFlux , you made my day Rather new to javascript, but interface scripting seems to become a unavoidable "evil", mostly doing php. Now, this solution by loading the buttons with the onload event for the body might be a ugly way of doing it, incase the user's browser doesnt support js, I suppose. But it's meant for a limited userbase. I was about to give up this as a whole and rather add checkboxes to which to remove, but this way is so much more elegant I'd say.