function JGallery() {
this.elements = this._init();
this.overlay = this.elements.overlay;
this.media_hld = this.elements.media_hld;
}
JGallery.prototype._init = function(){
var overlay = document.createElement('div');
var media_hld = document.createElement('div');
return{
'overlay': overlay,
'media_hld': media_hld
}
};
This is where I create a document fragment and using it so I can add several div to same element:
JGallery.prototype.getReference = function(holder) {
var overlay = this.overlay;
var media_hld = this.media_hld;
var that = this;
var holderChildren = holder.querySelectorAll('img');
var docfrag = document.createDocumentFragment();
holderChildren.forEach(function (e) {
e.addEventListener('click', JGallery.prototype.showMe.bind(that), false);
var media_holder = that.media_hld;
media_holder.textContent = "<img src="+e.getAttribute('src')+">";
docfrag.appendChild(media_holder);
//it only appends the last child of my array...
});
overlay.appendChild(docfrag);
};
my goal is to have something like this:
<div class="JGallery_BG">
<div class="JGallery_mediaContainer"><img src="images/thumb_video.jpg"></div>
<div class="JGallery_mediaContainer"><img src="images/thumb_video.jpg"></div>
</div>
by the way the forEach function works well, 8 or 9 times. But I'm not sure whether it adds node to docFrag on every run or not.
Another thing, I'm not insisting to use a document fragment, if there is a better way to add multiple elements to one element, I like to know about it and use it.
One of the problems is that you are constantly re-using the same media holder <div> element in every iterations.
In the code below that.media_hld is always referencing the same element.
var media_holder = that.media_hld;
media_holder.textContent = "<img src="+e.getAttribute('src')+">";
docfrag.appendChild(media_holder);
If you clone the node it should work and you also need to set the innerHTML property, not the textContent.
var media_holder = that.media_hld.cloneNode();
One other thing I did spot is that what's returned from querySelectorAll is not an array and thus doesn't have a forEach method.
You could borrow forEach from an array instance though:
[].forEach.call(holderChildren, forEachBodyFunction);
The entire thing could read:
JGallery.prototype.getReference = function(holder) {
var docfrag = document.createDocumentFragment(),
images = holder.querySelectorAll('img');
[].forEach.call(images, function (img) {
img.addEventListener('click', JGallery.prototype.showMe.bind(this), false);
var media_holder = this.media_hld.cloneNode();
media_holder.appendChild(img.cloneNode());
docfrag.appendChild(media_holder);
}.bind(this));
this.overlay.appendChild(docfrag);
};
Related
So, I am trying to make an element and then assign an onclick to it through JS.
Here is my code so far:
HTML
<div id = "Programs" onclick = "Cpb()">Programs</div>
JS
function Cpb() {
document.getElementById("AllBody").innerHTML = "";
var rh = document.createElement("h2");
var rht = document.createTextNode("Recent Programs");
rh.id = "Recentt";
var rh1 = document.createElement("h4");
var rh1t = document.createTextNode("test");
rh1t.onclick = window.open('website');
rh1.appendChild(rh1t);
rh.appendChild(rht);
}
So does anybody know how I can do this?
This javascript worked for me:
let h4Node = document.createElement("H4");
h4Node.innerHTML = "4th Header";
h4Node.onclick = function (){
alert('Oi!');
};
document.getElementById("demo").appendChild(h4Node);
Html:
<div class="demo"></div>
It will put an h4 element with an onclick event listener inside the demo div.
I think you want addEventListener.
Example:
rh1t.addEventListener('click', myHandlerFunction);
function myHandlerFunction () {
// ...
}
You can continue using onclick as you have in your code. But you'll need to do as I've done above and assign a function reference to it. Like this:
rh1t.onclick = myHandlerFunction;
function myHandlerFunction () {
window.open('website');
}
I am retrieving some information from an xml file ( movie information ) and I am creating dynamically some DOM elements according to each movie. I want, when I click on the test element, to get the value of the title of the movie. Right now, no matter which movie I click, it gets the title of the last movie that was introduced.
How can I get the title of each individual movie when I click on that div and not the last one introduced by the for-loop?
xmlDoc=xmlhttp.responseXML;
var x=xmlDoc.getElementsByTagName("movie");
for (i=0;i<x.length;i++)
{
var titlu = x[i].getElementsByTagName("title")[0].childNodes[0].nodeValue;
var description = x[i].getElementsByTagName("description")[0].childNodes[0].nodeValue;
var descriere = document.createElement('div');
descriere.className='expandedDescriere';
descriere.innerHTML = description;
var titlediv = document.createElement('div');
titlediv.className = 'title';
titlediv.id='title';
titlediv.innerHTML = title;
var test=document.createElement('div');
test.className='test';
test.onclick= function(){
var filmName= test.previousSibling.innerHTML;
alert(filmName);
}
placeholder.appendChild(titlediv);
placeholder.appendChild(test);
placeholder.appendChild(descriere);
}
I think your problem might be in the function you assigned to onclick:
test.onclick= function(){
var filmName= test.previousSibling.innerHTML; // <===
alert(filmName);
}
the marked line should be var filmName= this.previousSibling.innerHTML;
My guess is that the var test is hoisted out of the for loop, meaning that when the loop finished, all the onclick function are referencing the same test variable which is the last element you created.
Use this to reference the clicked element:
test.onclick = function() {
var filmName = this.previousSibling.innerHTML;
alert(filmName);
};
I am trying to clone the contents of a modal before it disappears.
basically when the ok button is clicked it passes a clone of object to function like so
$ok.onclick = function(e){
if(params.ok)
var $cont = $content.cloneNode(true);
params.ok($cont);
closeSlert($slert);
}
however later I am trying to use getElementById() but it returns that this is not a function
I thought that Element.clone clones the prototype as well.
just incase someone thinks to suggest $content.cloneNode(true) that doesnt seem to pass prototype methods either. is there a way to reapply the prototype methods or better yet clone them with the element
here is the entire slert function
function genSlert(params) {
var slerts = getSlerts(),
$slert = document.createElement('div'),
$buttons = document.createElement('div'),
$ok = document.createElement('button'),
$cancel = document.createElement('button'),
$content = document.createElement('div');
for(var i = 0; i < slerts.length; i++){
slideUp(slerts[i]);
}
$buttons.className = 'buttons';
$content.innerHTML = params.content;
$content.className = 'content';
$slert.className = 'slert';
$slert.appendChild($content);
$slert.appendChild($buttons);
$buttons.appendChild($cancel);
$buttons.appendChild($ok);
$ok.innerHTML = 'OK';
$cancel.innerHTML = 'CANCEL';
wrapper.appendChild($slert);
wrapper.classList.remove('hidden');
document.body.classList.add('no-scroll');
$cancel.onclick = function (e) {
if (params.cancel) {
params.cancel(e);
}
//close modal
closeSlert($slert);
}
$ok.onclick = function(e){
if(params.ok){
var $cont = $content.cloneNode(true);
params.ok($cont);
}
closeSlert($slert);
}
}
I have a link that is attached with an "onclick" function. When pressed it attaches an img element into a separate div called "mediaBox". The problem I'm having is that if it's pressed multiple times then it attaches more instances of the img. How can I control this. I'm still new to JavaScript and I prefer to receive this answer in pure Javascript not jQuery, as I will cross that bridge after I have a full understanding of Javascript.
var rkf = document.getElementById("submenulinks").getElementsByTagName("li")[0];
rkf.onclick = function(){
var client = document.getElementById('client');
var description2 = document.getElementById('description2');
var role = document.getElementById('role');
var mediaBox = document.getElementById('mediaBox');
var thumb = document.getElementById("thumb");
var client2 = document.getElementById("client2");
var newImage = document.createElement("img");
client2.innerHTML = "Role - Applications";
client.innerHTML = "RKF Real Estate";
client2.innerHTML = "Role - Applications";
description2.innerHTML = "Quarterly Catalog of Exclusive Listings managed by RKF";
role.innerHTML = "Custom designed Cover and listings content. Tables were also utilized within Indesign. <br><br><b><i> Photoshop and Indesign</i></b>";
newImage.setAttribute("src", "../images/rkf_cover.jpg");
newImage.setAttribute("height", "500px");
newImage.setAttribute("width", "387px");
newImage.setAttribute("alt", "rkf");
newImage.setAttribute("href", "#");
mediaBox.style.backgroundImage = "none";
document.getElementById("mediaBox").appendChild(newImage);
newImage.style.display = "block";
newImage.style.marginLeft = "auto";
newImage.style.marginRight = "auto";
newImage.style.marginTop = "25px";
}
rkf.onclick = function(){
var client = document.getElementById('client');
...
...
...
// Remove the handler after it ran once.
this.onclick = null; // <<<<<========================
}
Since you do want to use jQuery in the future, it's equal to:
$('#submenulinks li:first').one('click', handler);
These two javascript functions work perfectly on unaltered dom elements. However the delete_route function fails when asked to delete elements appended to the dom via the second function. For clarity, I am only looking at elements where parts[0] is always option - it is created by spliting the a > id on the "_".
Why is Javascript apparently seeing this difference between "native" dom objects and inserted objects?
//handle delete events
function delete_route (parts) {
if (parts[0] == "field") {
var select_container = "container_"+parts[2];
var getContainer = document.getElementById(select_container);
getContainer.parentNode.removeChild(getContainer);
} else if (parts[0] == "option") {
var optionId = parts[0]+"_"+parts[2]+"_"+parts[3];
var getOption = document.getElementById(optionId);
getOption.parentNode.removeChild(getOption);
}
}
//handle new events
function new_route (parts) {
var highest_number = -1;
if (parts[0] == "field") {
} else if (parts[0] == "option") {
var selectContainer = "container_"+parts[2];
var thisContainer = document.getElementById(selectContainer);
//get last option id (for new object tagging)
var optionList = thisContainer.getElementsByTagName("input");
var optionListLength = optionList.length -2;
//more accurate new node placement than last option which didn't work correctly anyway
lastChild = "options_wrapper_"+parts[2];
var lastChildNode = document.getElementById(lastChild);
//generate option
var labelNode = document.createElement ("label");
var inputNode = document.createElement ("input");
var linkNode = document.createElement ("a");
var breakNode = document.createElement ("br");
inputNode.setAttribute("type", "text");
var inputNodeId = parts[0]+"_"+parts[2]+"_"+optionListLength;
inputNode.setAttribute("id", inputNodeId);
inputNode.setAttribute("name", inputNodeId);
inputNode.setAttribute("value", "Undefined");
labelNode.setAttribute ("for", inputNodeId);
var labelNodeText = document.createTextNode ("Option Value");
linkNode.setAttribute("href", "#");
var linkId = parts[0]+"_delete_"+parts[2]+"_"+optionListLength;
linkNode.setAttribute("id", linkId);
var linkNodeText = document.createTextNode ("Delete option");
lastChildNode.appendChild (labelNode);
labelNode.appendChild (labelNodeText);
lastChildNode.appendChild (inputNode);
lastChildNode.appendChild (linkNode);
linkNode.appendChild (linkNodeText);
lastChildNode.appendChild (breakNode);
}
}
HTML this applies to (I have gone though some effort with the creating part - options that were inserted by javascript are exactly indentical to "native" page elements):
<div id="options_wrapper_7">
<label for="option_7_0">Option Value</label><input type=text id="option_7_0" name="option_7_0" value="Red"> <a id="option_delete_7_0" href="#">Delete option</a><br>
<label for="option_7_1">Option Value</label><input type=text id="option_7_1" name="option_7_1" value="Green"><a id="option_delete_7_1" href="#">Delete option</a><br>
<label for="option_7_2">Option Value</label><input type=text id="option_7_2" name="option_7_2" value="Blue"><a id="option_delete_7_2" href="#">Delete option</a><br>
</div>
Based on the code from your previous questions, you're assigning event handlers at window.onload by calling the clickDetection() function.
I assume when you've created new elements, you haven't bothered to give those new elements the same event handlers that your initial clickDetection() does.
If that's the case, you'll need to be sure that those new elements get handlers that can respond to clicks.
// make a separate reference to the handler so we can use it
// for elements that are created later.
function clickHandler() {
clickRoute(this);
return false
};
function clickDetection() {
var canvas = document.getElementById("content");
var dumbLinks = canvas.getElementsByTagName("a");
for (var i = 0; i < dumbLinks.length; i++) {
// Assign the "clickHandler" when the page loads
dumbLinks[i].onclick = clickHandler;
}
}
Then in your new_route function, manually assign clickHandler to the new <a> element.
function new_route (parts) {
var highest_number = -1;
if (parts[0] == "field") {
} else if (parts[0] == "option") {
var selectContainer = "container_"+parts[2];
var thisContainer = document.getElementById(selectContainer);
//get last option id (for new object tagging)
var optionList = thisContainer.getElementsByTagName("input");
var optionListLength = optionList.length -2;
//more accurate new node placement than last option which didn't work correctly anyway
lastChild = "options_wrapper_"+parts[2];
var lastChildNode = document.getElementById(lastChild);
//generate option
var labelNode = document.createElement ("label");
var inputNode = document.createElement ("input");
var linkNode = document.createElement ("a");
var breakNode = document.createElement ("br");
// ********RIGHT HERE*********
// Assign the handler to the new "linkNode" element
linkNode.onclick = clickHandler;
// ...and so on with the rest of the code...
}