Javascript - Function works once, but never again - javascript

I'm building a very simple lightbox script; when you click a button, the lightbox is created. When you click on the lightbox background, it is removed.
The first time you call the function it works just fine. Click button, lightbox shows, click lightbox, it disappears. However, if you try to click the button AGAIN, nothing happens - the div isn't called. No console errors or anything, don't know what the problem is.
JSFIDDLE http://jsfiddle.net/3fgTC/
CODE
function closeLightBox(){
document.body.removeChild(lightBox);
}
function createElem(){
var elem = "<div id='lightBox'></div>";
var bodyElem = document.body;
bodyElem.innerHTML = elem + bodyElem.innerHTML;
var lightBox = document.getElementById("lightBox");
lightBox.style.width = "100%";
lightBox.style.height = "800px";
lightBox.style.backgroundColor = "rgba(0,0,0,.5)";
lightBox.onclick = function(){
closeLightBox();
}
}
var button = document.getElementsByClassName("btn");
for (var i = 0; i<button.length; i++){
button[i].onclick = function(){
createElem();
}
}
Any ideas?

Don't prepend to innerHTML; that makes the browser re-parse the HTML and re-create every DOM element, losing event handlers in the process. Instead, use document.createElement:
var lightBox = document.createElement('div');
document.body.insertBefore(lightBox, document.body.firstChild);
Furthermore, inline closeLightBox:
lightBox.onclick = function() {
document.body.removeChild(lightBox);
}
Try it.

Related

Javascript hiding and showing dynamic content of a div

Currently I hide and show the content of a div like this:
var header = null;
var content = null;
var mainHolder = null;
var expandCollapseBtn = null;
var heightValue = 0;
header = document.getElementById("header");
content = document.getElementById("content");
mainHolder = document.getElementById("mainHolder");
expandCollapseBtn = header.getElementsByTagName('img')[0];
heightValue = mainHolder.offsetHeight;
header.addEventListener('click', handleClick, false);
mainHolder.addEventListener('webkitTransitionEnd',transitionEndHandler,false);
function handleClick() {
if(expandCollapseBtn.src.search('collapse') !=-1)
{
mainHolder.style.height = "26px";
content.style.display = "none";
}
else
{
mainHolder.style.height = heightValue + "px";
}
}
function transitionEndHandler() {
if(expandCollapseBtn.src.search('collapse') !=-1)
{
expandCollapseBtn.src = "expand1.png";
}
else{
expandCollapseBtn.src = "collapse1.png";
content.style.display = "block";
}
}
This is fine if the content is static, but I'm trying to populate my div dynamically like so.
This is called from an iphone application and populates the div with a string.
var method;
function myFunc(str)
{
method = str;
alert(method);
document.getElementById('method').innerHTML = method;
}
I store the string globally in the variable method. The problem I am having is now when I try expand the div I have just collapsed there is nothing there. Is there some way that I could use the information stored in var to repopulate the div before expanding it again? I've tried inserting it like I do in the function but it doesn't work.
Does anyone have any ideas?
to replicate:
Here is the jsfiddle. jsfiddle.net/6a9B3 If you type in text between
here it will work fine. I'm not sure
how I can call myfunc with a string only once in this jsfiddle, but if
you can work out how to do that you will see it loads ok the first
time, but when you collapse the section and attempt to re open it, it
wont work.
If the only way to fix this is using jquery I dont mind going down that route.
is it working in other browsers?
can you jsfiddle.net for present functionality because it is hard to understand context of problem in such code-shoot...
there are tonns of suggestions :) but I have strong feeling that
document.getElementById('method')
returns wrong element or this element not placed inside mainHolder
update: after review sample in jsfiddle
feeling about wrong element was correct :) change 'method' to 'info'
document.getElementById('method') -> document.getElementById('info')
I think you want to use document.getElementById('content') instead of document.getElementById('method') in myFunc.
I really see nothing wrong with this code. However, a guess you could explore is altering the line
content.style.display = "none";
It might be the case that whatever is displaying your html ( a webview or the browser itself) might be wiping the content of the elemtns, as the display is set to none

Greasemonkey popup loop not waiting for load-event listener

I'm writing a Greasemonkey script to automatically delete my notifications from a site, based on words I enter into a search box.
The delete "button" is basically a link, so I'm trying to open the first link in a new tab. Then, after it loads enough, open the rest of the links, one by one, in that same tab.
I figured out how to get the links I needed and how to loop and manipulate them. I was able to grab the first delete-link and open it in a new tab. I added an event listener to make sure the page was loaded before going to the next link.
I finally made that work so added my search box and button. Then I had to figure out how to wrap the whole thing in the event listener again.
So, I now have the whole thing working, except only the last link loads.
All links are going to my waitFor function so they should open, so it seems the event listener isn't working so it goes through the loop too fast and only the last link loads.
How do I make this script not continue the loop until the previous loaded page is fully loaded?
Complete code except for box and button creation:
var mytable = document.getElementById ('content').getElementsByTagName ('table')[0]
var myrows = mytable.rows
//function openLinkInTab () {
//mywin2.close ();
//}
var mywin2;
mywin2 = window.open ("http://www.aywas.com/message/notices/test/", "my_win2");
var links;
var waitFor = function (i) {
links = myrows[i].cells[1].getElementsByTagName ("a");
mywin2 = window.open (links[0].href, "my_win2");
}
var delnotifs = function () {
var matching;
var toRemove;
toRemove = document.getElementById ('find').value;
alert (toRemove)
for (i = 0; i < 10; i++) {
matching = myrows[i].cells[0].innerHTML;
if (matching.indexOf (toRemove) > 0) {
mywin2.addEventListener ('load', waitFor (i), false);
}
}
}
searchButton.addEventListener ('click', delnotifs, true);
So, why isn't it waiting for `mywin2.addEventListener('load', waitFor(i), false);`? I have a feeling it's something extremely simple that I'm missing here, but I just can't see it.
I also tried mywin2.addEventListener('load', function(){waitFor(i)}, false); and it still does the same thing, so it's not a problem of being a call instead of a pointer.
Swapping mywin2.addEventListener('load', waitFor(i), false); for
if (mywin2.document.readyState === "complete") { waitFor(i)} doesn't work either.
And while I'm at it... every time I see code looping through a list like this it uses
for(i=1;i < myrows.length;i++)
Which was skipping the first link in the list since arrays start at zero. So my question is, if I switch 'i' to zero, and the loop only goes while 'i' is < length, doesn't that mean it won't go through the whole list? Shouldn't it be
for(i=0;i != myrows.length;i++)
When you open a popup (or tab) with window.open, the load event only fires once -- even if you "open" a new URL with the same window handle.
To get the load listener to fire every time, you must close the window after each URL, and open a new one for the next URL.
Because popups are asynchronous and you want to load these links sequentially, don't use a for() loop for that. Use the popup load status to "chain" the links.
Here is the code to do that. It pushes the links onto an array, and then uses the load event to grab and open the next link. You can see the code in action at jsFiddle. :
var searchButton = document.getElementById ('gmPopUpBtn');
var mytable = document.getElementById ('content').getElementsByTagName ('table')[0];
var myrows = mytable.rows;
var linksToOpen = [];
var mywin2 = null;
function delnotifs () {
var toRemove = document.getElementById ('find').value;
for (var J = 0, L = myrows.length; J < L; J++) {
var matching = myrows[J].cells[0].innerHTML;
if (matching.indexOf (toRemove) > 0) {
var links = myrows[J].cells[1].getElementsByTagName ("a");
linksToOpen.push (links[0].href); //-- Add URL to list
}
}
openLinksInSequence ();
};
function openLinksInSequence () {
if (mywin2) {
mywin2.close ();
mywin2 = null;
}
if (linksToOpen.length) {
var link = linksToOpen.shift ();
mywin2 = window.open (link, "my_win2");
mywin2.addEventListener ('load', openLinksInSequence, false);
}
}
searchButton.addEventListener ('click', delnotifs, true);
See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener.
The second argument of the addEventLister function must be a pointer to a function and not a call.

Why is my image not loading?

At http://blajeny.com I have:
jQuery('body').click(function(event_object)
{
spark(event_object.pageX, event_object.pageY);
});
function spark(x, y)
{
console.log('Spark called.');
var image_object = new Image();
image_object.onLoad = function()
{
image_object.style.position = 'absolute';
image_object.style.zIndex = 1;
image_object.style.top = y;
image_object.style.left = x;
}
image_object.src = '/img/spark.png';
}
The intended effect, at this stage, is to load an image at the X and Y where the user clicked. (I want to do other things as well, like animate it, but right now I'm trying to get the image to show up where the user clicked.)
The javaScript console shows that the handler is being called, however I am not seeing what I expect, a hazy blue circle immediately below and to the right of the point where the mouse was clicked.
What can/should I do differently so it loads a fresh image below and to the right of the clicked coordinates?
Thanks,
As far as I know, the onLoad should be onload
var image_object = document.createElement('img');
image_object.onload = function() { // Note the small onload
// your code
}
// Also, append the image_object to DOM
document.body.appendChild(image_object);
I don't see you appending the image to DOM that's probably why you're not seeing it
$('body').append($(image_object));
I agree, first create an element with the "img" tag, assign the src value to it, and append it to the current div (in this case its the body), like so
var imgTag = document.createElement("img");
imgTag.src = '/img/spark.png';
document.body.appendChild(imgTag);
Hope this helps.
You never append the image to the DOM, that's why you can't see it.
You can do
document.body.appendChild(image_object);
You must also replace onLoad by onload and specify the top and left position with an unit :
image_object.onload = function() {
image_object.style.position = 'absolute';
image_object.style.zIndex = 1;
image_object.style.top = '100px';
image_object.style.left = '100px';
}
Demonstration

javascript crashing iPad browser

I have some javascript inside a function that creates and populates an image carousel. It works fine after activating it in a pop up window the first 5 or 6 times, but then it eventually crashes the browser. I think there's some kind of leak, like something inside of it needs to be deleted before it gets created again. I know it's the carousel because if I get rid of that part of the script, it no longer crashes.
Here's the carousel script:
/* carousel */
var carousel,
el,
i,
page,
slides;
carousel = new SwipeView('#wrapper', {
numberOfPages: slides.length,
hastyPageFlip: true
});
// Load initial data
for (i=0; i<3; i++) {
page = i==0 ? slides.length-1 : i-1;
el = document.createElement('span');
el.innerHTML = slides[page];
carousel.masterPages[i].appendChild(el)
}
carousel.onFlip(function () {
var el,
upcoming,
i;
for (i=0; i<3; i++) {
upcoming = carousel.masterPages[i].dataset.upcomingPageIndex;
if (upcoming != carousel.masterPages[i].dataset.pageIndex) {
el = carousel.masterPages[i].querySelector('span');
el.innerHTML = slides[upcoming];
}
}
});
This script runs every time I click a link that launches a floating window.
I found out that I needed to clear my wrapper div. In the beginning of my function call:
document.getElementById('wrapper').innerHTML = "";
Seems to work.

Greasemonkey script seems to ignore setInterval?

I'm trying to make a toy script in GreaseMonkey that will cause my screen to repeatedly jump to the top of my screen when I click a button, and stop jumping when I click the button again.
This is my code:
var perpetualScroll = function () {
var scrolling = false;
var scroll = function () {
if (scrolling) {
window.scrollTo(0, 0);
}
};
var scrollDiv = document.createElement("div");
scrollDiv.id = "topScroll0x2a";
scrollDiv.innerHTML = '<a class="topScroll" onclick="scrolling = !scrolling;" style="display:block; position:fixed; bottom: 1em; right: 1em; color:#fff; background-color:#000; padding:.5em;" href="#">Start scroll</a>';
document.body.appendChild(scrollDiv);
var intervalId = window.setInterval(scroll, 50);
};
perpetualScroll();
When I click the button in the lower corner the script creates, it does jump to the top of the screen, but doesn't continue to perpetually do so.
I'm really new to Javascript and GreaseMonkey, so I'm not quite sure what the problem is. I suspect it might be due to issues in the onclick part of the link, but if it is, I can't seem to figure it out.
Doing onclick like that will not work like you expect. Your innerHTML is just a string, so JS has no idea that it is scoped within your perpetualScroll function.
onclick handlers that are strings are evaluated in the global scope, so what you have is equivalent to this:
window.scrolling = !window.scrolling;
The scrolling variable you want is different.
You should create an actual function like this:
var a = document.createElement('a');
a.className = (a.className || "") + ' topScroll';
a.style.display = 'block';
a.style.position = 'fixed';
a.style.bottom = '1em';
a.style.right = '1em';
a.style.color = '#FFF';
a.style.backgroundColor = '#000';
a.style.padding = '0.5em';
a.href = '#';
a.onclick = function(e){
scrolling = !scrolling;
return false;
};
scrollDiv.appendChild(a);
Obviously setting that CSS is terrible, so you should really put that in a separate stylesheet anyway.

Categories