I am looking for a way to simplify this code using for loops. Any help is appreciated.
I am setting up a system of opening modal frames full of images when somebody clicks on a link with a date on it (e.g. a photo archive). I have a lot of different dates and each time I make a new one I have to insert it a million times into the code as shown below. Maybe I could make an array of some sort that holds the dates and loop through the array and generate the code below. There is probably a simple fix to this, but I am new to web development. Thanks!!!!
// Get the modal gallery
var gallery161207 = document.getElementById('gallery161207');
var gallery161130 = document.getElementById('gallery161130');
...
var gallery150916 = document.getElementById('gallery150916');
// Get the close button
var closeButton161207 = document.getElementById('closeModal161207');
var closeButton161130 = document.getElementById('closeModal161130');
...
var closeButton150916 = document.getElementById('closeModal150916');
// Get the buttons
var btn161207 = document.getElementById('161207');
var btn161130 = document.getElementById('161130');
...
var btn150916 = document.getElementById('150916');
// When the user clicks on the button, open the modal gallery
function openGallery(source) {
// Open the modal gallery depending on what was clicked
if (source == '161207')
gallery161207.style.display = "block";
if (source == '161130')
gallery161130.style.display = "block";
...
if (source == '150916')
gallery150916.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
closeButton161207.onclick = function() {
gallery161207.style.display = "none";
}
closeButton161130.onclick = function() {
gallery161130.style.display = "none";
}
...
closeButton150916.onclick = function() {
gallery150916.style.display = "none";
}
btn161207.onclick = function() { openGallery('161207'); }
btn161130.onclick = function() { openGallery('161130'); }
...
btn150916.onclick = function() { openGallery('150916'); }
window.onclick = function(event) {
if (event.target == gallery161207) {
closeButton161207.onclick();
}
if (event.target == gallery161130) {
closeButton161130.onclick();
}
...
if (event.target == gallery150916) {
closeButton150916.onclick();
}
}
You could do this fairly easily using jQuery, but I assume, since you're new to web development, you'll want to start out from scratch.
First, let's deal with setting up the buttons to show the galleries. I'd say you give each button a class="gallery-button" attribute and an id="<id of gallery>". The galleries also should have IDs id="gallery-<id of gallery>". Then:
var buttons = document.getElementsByClassName("gallery-button");
for(var i =0; i < buttons.length; i++){
var elem = buttons[i];
elem.onclick = function() {
document.getElementById('gallery' + elem.id).style.display="block";
};
}
}
We can do a similar thing for the close buttons (assuming they have IDs of id="close-<id of gallery>" and their class="close-button":
var closeButtons = document.getElementsByClassName("close-button");
for(var i =0; i < buttons.length; i++){
var elem = closeButtons[i];
elem.onclick = function() {
document.getElementById('gallery-' + elem.id.replace("close-", "")).style.display="none";
};
}
}
And then:
window.onclick = function(event) {
var id = event.target.id;
if (id.startsWith("gallery-") {
var closeButton = document.getElementById("close-" + id.replace("gallery-", ""));
closeButton.onclick();
}
}
You can try making an object saving all the dom references and using those. This answer makes use of jQuery for its document ready function.
var sourceList = [];
var sources = {};
var wrappers = document.getElementsByClassName('gallery-wrapper');
for(var i = 0; i < wrappers.length; i++){
sourceList.push(wrappers[i].id);
}
$( document ).ready(function() {
for(var i = 0; i < sourceList.length; i++){
var source = {};
source.gallery = document.getElementById("gallery"+sourceList[i]);
source.button = document.getElementById("button"+sourceList[i]);
source.closeButton = document.getElementById('closeButton'+sourceList[i]);
source.button.onclick = function() {
if(source.gallery)source.gallery.style.display = "block";
}
source.closeButton.onclick = function() {
if(source.gallery)source.gallery.style.display = "none";
}
sources[sourceList[i]] = source;
}
window.onclick = function(event) {
for (var source in sources)
if (event.target == sources[source].gallery)
sources[source].closeButton.onclick();
}
});
Related
This is a Sudoko generator I'm programming in vanilla javascript:
Fiddle with code
Nicer looking full screen fiddle
If you click on one of the fields, a popup will be shown with 3x3 fields from 1 to 9. The problem is this popup can't be closed anymore, although I'm applying the close dialog.
The code how I'm generating the Sudoku board:
// create sudoku
function tableCreate() {
var body = document.getElementsByClassName("frame")[0];
var containerDiv = body.appendChild(document.createElement('div'))
containerDiv.className = 'container';
// create single cells with numbers
function createInnnerCells(parent, xx, yy) {
for (var x = 1; x <= 3; x++) {
for (var y = 1; y <= 3; y++) {
var abc = function () {
var div = parent.appendChild(document.createElement('div'))
var X = y+yy;
var Y = x+xx;
var id = 'x' + [X] + 'y' + [Y];
var cellValue = sudoku[X][Y]['value'] || '';
div.style.background = sudoku[X][Y]['background'] || 'white'
div.className = 'cell';
div.id = id;
var popover = createDialog(id);
popover.onclick = function() {
popover.close();
};
div.onclick = function() {
popover.show();
};
div.appendChild(popover);
div.appendChild(document.createTextNode(cellValue));
};
abc();
}
}
}
// create big cells for 3x3 single cells
for (var i = 0; i <= 6; i+=3) {
for (var j = 0; j <= 6; j+=3) {
var div = containerDiv.appendChild(document.createElement('div'))
div.className = 'block';
createInnnerCells(div, i, j);
}
}
}
Note that I apply the close() function to each cell:
popover.onclick = function() {
popover.close();
};
The code how I create the popup:
// create dialog
function createDialog(position){
var dialog = document.createElement('dialog');
dialog.id ='window_'+ position;
var dialogblock = dialog.appendChild(document.createElement('div'));
dialogblock.className = 'dialogblock';
for (var z = 1; z <= 9; z++) {
var div = dialogblock.appendChild(document.createElement('div'));
div.className = 'dialogcell';
div.id = position + 'z'+ z;
div.appendChild(document.createTextNode(position));
}
dialog.onclick = function() {
dialog.close();
};
return dialog;
}
I applied the close() dialog here as well
dialog.onclick = function() {
dialog.close();
};
I don't know why show() is working, but close() not?
DOM events bubble up the DOM through its parents. In your code, the dialog is a child of div. Therefore, a click event happens on dialog and then again on div which means you're closing and then opening the dialog.
You can stop the propagation of the event by using event.stopPropagation.
You can change your code like this:
popover.onclick = function(e) {
e.stopPropagation();
popover.close();
};
and
dialog.onclick = function(e) {
e.stopPropagation();
dialog.close();
};
modified your fiddle: http://jsfiddle.net/p40oahkd/9/
There's no method close() on the element you are trying to hide. You should either do element.style.display = "none" if you need to hide. Or do the following:
dialog.addEventListener('click', function() {
this.remove();
});
Check out this edit to your fiddle.
i'm currently developing an application that relies on webservice calls in order to create a tree-like "menu", everything works as intended but i realized not all the target audience has a fast internet connection like i have right now on the development environment. my goal is to show a loading "screen" while the javascript function creates and then adds the elements to the DOM, the flowchart is as follows:
user click on the "expand" image of a node
user sees a div loading gif
user is presented with the childnodes
i'm not sure where i should put the timeout
my code:
...
elemento_tema_imagem_esconde_mostra.addEventListener("click", Get_Feat);
...
function Get_Feat(event) {
Tema_Expandido = event.target.parentNode;
if (typeof (Tema_Expandido.getElementsByTagName("ul")[0]) === "undefined") {
sMNID = event.target.parentNode.getElementsByTagName("a")[0].getAttribute("mnid");
var service = new WebJSON;
service.GetFeat(sMNID, SuccessCallback_Get_Feat, OnfailureCallback_Get_Feat);
} else {
//debugger;
var elemento = Tema_Expandido.getElementsByTagName("ul")[0];
var imagem_esconder_mostar = elemento.parentNode.childNodes[0];
var style = window.getComputedStyle(elemento, null);
if (style.display == "block") {
elemento.style.display = "none";
imagem_esconder_mostar.src = "Content/Images/img_abrir_22_22.png";
} else if (style.display == "none") {
elemento.style.display = "block";
imagem_esconder_mostar.src = "Content/Images/img_fechar_22_22.png";
}
}
};
function SuccessCallback_Get_Feat(Resultado_Get_Feat) {
var colleccao_Feat = JSON.parse(Resultado_Get_Feat);
var lista_feat = document.createElement("ul");
lista_feat.setAttribute("class", "lista-sem-bullets");
for (var i = 0; i < colleccao_Feat.length; i++) {
var elemento_feat = document.createElement("li");
var elemento_feat_imagem_esconde_mostra = document.createElement("img");
var elemento_feat_imagem_no = document.createElement("img");
var elemento_feat_link = document.createElement("a");
if (colleccao_Feat[i].FILHOS > 0) {
elemento_feat_imagem_esconde_mostra.src = "Content/Images/img_abrir_22_22.png";
elemento_feat_imagem_esconde_mostra.addEventListener("click", Get_Compo);
} else if (colleccao_Feat[i].FILHOS = 0) {
elemento_feat_imagem_esconde_mostra.src = "Content/Images/seta_dir_26_20.png";
}
//elemento_feat_imagem_esconde_mostra.addEventListener("click", Get_Feat);
//elemento_feat_imagem_no.src = "Content/Images/feat.png"
elemento_feat_link.setAttribute("FNID", colleccao_Feat[i].FNID);
elemento_feat_link.innerText = colleccao_Feat[i].NAMEDESC;
elemento_feat.appendChild(elemento_feat_imagem_esconde_mostra);
elemento_feat.appendChild(elemento_feat_imagem_no);
elemento_feat.appendChild(elemento_feat_link);
lista_feat.appendChild(elemento_feat);
};
document.getElementById("myModal_Loading").style.display = "none";
Tema_Expandido.appendChild(lista_feat);
Tema_Expandido.childNodes[0].src = "Content/Images/img_fechar_22_22.png";
};
function OnfailureCallback_Get_Feat(error) {
//displaying error on alert box
alert(error);
};
any help will be much appreciated
Hello fellow stackoverflow members,
I've been trying to make a Slideshow. I've referenced from many other sites including this one but the pictures aren't showing up in the container element nor are the "prev" and "next" buttons functioning properly. I'd appreciate it if I got help! :)
my code:
var photos = newArray ();
photos[0] = "img/image(2).jpg";
photos[1] = "img/image(4).jpg";
photos[2] = "img/image(6).jpg";
photos[3] = "img/image(8).jpg";
photos[4] = "img/image(10).jpg";
photos[5] = "img/image(12).jpg";
photos[6] = "img/image(14).jpg";
photos[7] = "img/image(16).jpg";
photos[8] = "img/image(18).jpg";
photos[9] = "img/image(20).jpg";
photos[10] = "img/image(22).jpg";
photos[11] = "img/image(24).jpg"
//END OF PHOTOS ARRAY//
var i = 0;
var k = photos.length-1;
function next.onclick() {
var img= document.getElementById("image-container");
img.src = photos[i];
if (i < k ) {
i++;
}else {
i = 0; }
}
function prev.onclick() {
var img= document.getElementById("image-container");
img.src=photos[i];
if)i > 0) {i--;}
else {i = k; }
}
getImageArray = function(containerId) {
var containerElement = document.getElementById(container);
if (containerElement) {
var imageArray = containerElement.getElementById("container");
return photos[i];
} else {
return null;
}
}
this is what my slideshow looks like (it's broken)
http://prntscr.com/5dcfzq
The share button isn't important, I can make that work at least.
The main problem is that the pictures aren't showing and the back and foward buttons are messed up :'(
p.s ( I'm not sure if part of the reason is how I'm linking to the "next" or "back" functions with the div tag, because i'm this is how i'm doing it :
<div id = "back" onclick = "prev()"></div>
OK ... to summarize ...
1. var photos = newArray ();
There needs to be a space between new and Array, so ...
var photos = new Array();
2. function prev.onclick() { needs to be just function prev() {
3. Same with next.onclick() based on usage in HTML.
4. In prev() ... if)i > 0) {i--;} should be ...
if (i > 0) { i--; }
5. WRONG: Also in prev()' ... else should bei = k-1;`
6. DO NOT NEED Not sure why you have the getImageArray function at all.
7. This assumes there is an '' tag in the HTML.
UPDATE:
Here's the code that works ... this all goes in the body:
These are my assumptions in the body ...
<img id="image-container" />
<div id="back" onclick="prev()">Previous</div>
<div id="next" onclick="mext()">Next</div>
The script code MUST be at the end of the body ...
<script>
var photos = new Array ();
photos[0] = "img/image(2).jpg";
photos[1] = "img/image(4).jpg";
photos[2] = "img/image(6).jpg";
photos[3] = "img/image(8).jpg";
photos[4] = "img/image(10).jpg";
photos[5] = "img/image(12).jpg";
photos[6] = "img/image(14).jpg";
photos[7] = "img/image(16).jpg";
photos[8] = "img/image(18).jpg";
photos[9] = "img/image(20).jpg";
photos[10] = "img/image(22).jpg";
photos[11] = "img/image(24).jpg"
//END OF PHOTOS ARRAY//
// Here, I set the img variable so that it can be re-used.
// I also loaded the first image ...
var i = 0;
var k = photos.length-1;
var img = document.getElementById("image-container");
img.src = photos[i];
function next() {
img.src = photos[i];
if (i<k) {
i++;
} else {
i = 0;
}
}
function prev() {
img.src=photos[i];
if (i>0) {
i--;
} else {
i = k;
}
}
</script>
I am trying to write a click event for an anchor tag in my tampermonkey script.
var contentTag = document.getElementsByTagName("pre")[0];
var fileContents = contentTag.innerHTML;
contentTag.innerHTML = "";
var lines = fileContents.split("\n");
window.alert("Number of lines:"+lines.length);
for(var i=0; i<20; i++) {
if(i!==15)
contentTag.innerHTML+=(lines[i]+"<br>");
else {
contentTag.innerHTML+=("<a id=link1>Click me</a>");
var link = document.getElementById('link1');
link.addEventListener("click", function() {
window.alert('I am clicked');
}, false);
}
}
The alert message never gets triggered when I click on the link in the page dispalyed, even though I have a a click event listener defined. What am I doing wrong here?
It's the way you're adding HTML, you're reappending the link when you do this in the next iteration.
link.innerHTML += something
So the event handler is lost, and you can actually prove that by adding the event handler to the last element instead.
If you do it the proper way, creating elements and appending them, it works fine
var contentTag = document.getElementsByTagName("pre")[0];
var fileContents = contentTag.innerHTML;
contentTag.innerHTML = "";
var lines = fileContents.split("\n");
for (var i = 0; i < 20; i++) {
if (i !== 15) {
var txt = document.createTextNode(lines[i] || ''),
br = document.createElement('br');
contentTag.appendChild(txt);
contentTag.appendChild(br);
} else {
var link = document.createElement('a');
link.id = 'link1';
link.innerHTML = 'Click me';
link.addEventListener("click", function () {
alert('clicked')
}, false);
contentTag.appendChild(link)
}
}
FIDDLE
Shoud be contentTag.innerHTML+=("<a id='link1'>Click me</a>");
Try this:
<script>
var contentTag = document.getElementsByTagName("pre")[0];
var fileContents = contentTag.innerHTML;
contentTag.innerHTML = "";
var lines = fileContents.split("\n");
window.alert("Number of lines:"+lines.length);
for(var i=0; i<20; i++) {
if(i!==15)
contentTag.innerHTML+=(lines[i]+"<br>");
else {
contentTag.innerHTML+=("<a id=link"+i+">Click me</a>");
var link = document.getElementById('link'+i);
var att=document.createAttribute('onclick');
att.value="alert('Clicked !')";
link.setAttributeNode(att);
}
}
</script>
Demo: http://jsfiddle.net/TmJ38/
I want this code to check if the user has clicked inside the open box and if so then it will keep it open, also if the user clicks outside the box it will close.
http://jsfiddle.net/MTJa5/26/
var boxes = function(){
var divClicks = document.getElementsByClassName("clickToShow");
for(i=0; i < divClicks.length; i++){
var click = divClicks[i];
var clickEvent = function(){
click.addEventListener("click", function(e){
var currentClass= this.getElementsByTagName('div')[0].className;
var divs = document.getElementsByClassName('openedBox');
for(var i = 0; i < divs.length; i++){
divs[i].setAttribute("class", "closedBox");
}
if(currentClass === "openedBox"){
this.childNodes[3].setAttribute("class", "closedBox");
} else {
this.childNodes[3].setAttribute("class", "openedBox");
}
},false);
}();
}
}();
Instead of binding several event listeners, you can also bind just one click event, and use the event.target property to check where you've clicked.
The updated code is less comples, and easier to maintain.
Demo: http://jsfiddle.net/MTJa5/28/
var hellos = function() {
function closeAllButThisBox(targ) {
var allBoxes = document.getElementsByClassName('openedBox');
for (var i=allBoxes.length-1; i>=0; i--) {
if (allBoxes[i] !== targ) {
allBoxes[i].className = 'closedBox';
}
}
}
window.addEventListener('click', function(ev) {
var targ = ev.target;
// Traverse the tree, until you hit the desired / root element
while (targ && targ !== document.documentElement) {
if (targ.className.indexOf('openedBox') !== -1) {
closeAllButThisBox(targ);
// Do nothing when clicking inside an opened box
return;
}
// This will open boxes, if closed, when clicking at the <p>
if (targ.tagName.toLowerCase() === 'p' && targ.parentNode.className.indexOf('clickToShow') !== -1) {
closeAllButThisBox(targ.parentNode);
targ.parentNode.getElementsByTagName('div')[0].className = 'openedBox';
return;
}
targ = targ.parentNode;
}
// At this point, the click is not at the right place.
// Close all boxes by removing the closedBox class names
var boxes = document.getElementsByClassName('openedBox');
for (var i=boxes.length-1; i>=0; i--) {
boxes[i].className = 'closedBox';
}
}, false);
}();