JavaScript: trouble assigning event handlers - javascript

I'm not sure what I'm doing wrong here:
index.html
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "XHTML1-s.dtd" >
<html xmlns="http://www.w3.org/TR/1999/REC-html-in-xml" xml:lang="en" lang="en" >
<head>
<script type="text/javascript" src="scripts/eventInit.js"></script>
</head>
<body>
<p id="javascriptWarning">This page will not work with JavaScript disabled.</p>
</body>
</html>
eventInit.js
window.onload = function () {
alert("check"); // works
var jsWarning = document.getElementById("javascriptWarning");
jsWarning.onclick = function () {
alert("hi"); // works
};
jsWarning.onload = function () {
alert("loaded"); // fails
};
}
And yet, nothing happens. What am I doing wrong? I've tried other events, like onmouseover and onload.
I'm doing this in Visual Studio, and intellisense isn't giving me options for setting any event handlers. Is that because I'm doing this wrong?
I have confirmed that JS is working on my setup; just putting alert("hi") in a script and including it does work.
It might be important to note that I'm doing this in JScript, since I'm using Visual Studio 2010, so perhaps event handling is different?
Updated to remove '-' from the ID name, but it still doesn't work.
Updated added the window.onload block. Now onclick works, but onload doesn't.

You are trying to set a load event on a paragraph. Only objects which load external data (window, frame, iframe, img, script, etc) have a load event.
Some JS libraries implement an available event (such as YUI) — but you know the paragraph is available, since you're setting an event on it, and you couldn't do that if it was unavailable.

maybe you forgot to have the code block inside a
window.onload = function() {
// btn click code here
}

You have to wait for the document to be parsed before you can go looking for elements by "id" value. Put your event handling setup into an "onload" function on the window object.
The browser won't fire an "onload" event on your <p> tag. You won't need that anyway if you do your work in the "onload" handler for the window as a whole.
[soapbox] Use a framework.

The script is executed before the desired element exists. Additionally, I don't think, p has an onload-Event. Windows, frames and images, yes, but paragraphs?
You should use <body onload="init();"> or window.onload=function(){ … } or a library function, if you use a library. Example:
index.html
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "XHTML1-s.dtd" >
<html xmlns="http://www.w3.org/TR/1999/REC-html-in-xml" xml:lang="en" lang="en" >
<head>
<script type="text/javascript" src="scripts/eventInit.js"></script>
</head>
<body>
<p id="javascriptWarning">This page will not work with JavaScript disabled.</p>
</body>
</html>
scripts/eventInit.js
window.onload=function(){
alert('JS is working!');}
Edit: Okay, I am very sure, p makes no use of an onload event handler. And it's no wonder, you don't need it. If you want to execute JS code just after the paragraph is finished, do this:
<p>
<!-- stuff -->
</p>
<script type="text/javascript">
/* stuff */
</script>

Instead of this:
jsWarning.onload = function () {
alert("loaded"); // fails
};
try this
if(jsWarning) alert("loaded");
I think someone above mentioned checking for the existence of the element. At this stage the element should be present but it does no harms to check for it.

I think you have to make sure your JavaScript is binding.
Is your javascript before or after your paragraph element, for some reason my brain is aiming towards that.
I would look into using something like jQuery, it will help.
using jQuery your code would be (with the relevant jQuery files included of course):
$(document).ready(function()
{
$("#javascript-warning").click(function(){
alert("HELLO");
});
});

I don't think hyphens are valid in class names when used in conjunction with JavaScript. Try an underscore instead.

onload is a window event.

Related

Javascript Function Not Being Called after dynamic loading

I have a weird issue that i am hoping someone can help resolve.
Problem
When i load html dynamically via .load() function, if any aspect of html in the loaded fragment tries to access the javascript query functions in original HTML page, it doesn't work. Example code below:
Main HTML page (main.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<!--javascript load functions etc... standard header stuff -->
</head>
<body>
<div id="dynamic_section_fragment"></div>
Load Fragment
<script type="text/javascript">
// <![CDATA[
function loadFragment() {
$("#dynamic_section_fragment").load("/api/fragment/");
};
$(".checkvalue").click(function () {
$.getJSON("/api/checkvalue", {term: $(this).attr('value')}, function () {
console.info("submitted for checking");
})
});
// ]]>
</script>
</body>
</html>
FRAGMENT File (fragment.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
</head>
<body>
<div th:fragment="check_value">
<br/>
Check the value in the attribute field
<br/>
<a href="javascript:" th:attr="value='123'" class="checkvalue">Check This<a/>
</div>
</body>
</html>
SPRING MVC Controller Method
#RequestMapping("/api/checkvalue")
public String getFragment(Model model) {
return "fragment :: check_value";
}
So a run down of actions:
-Main.html page loads
-User clicks on Load Fragment hyperlink
-Javascript dynamically loads the relevant fragment into the div
-User clicks on Check This hyperlink, nothing happens
Is there something i am missing or something i need to be aware?
It is as if Thymeleaf has preregistered all the possible scenarios of events and doesn't allow any others.
Only way i have been able to get it to work is by injecting the "checkvalue" javascript within the fragment, which as you can agree is a bad way of doing things.
Help is appreciated.
You are applying the click event listener to all existing objects with the checkvalue class.
$(".checkvalue").click(function ()
What you rather wish to do (to make the click event apply to all the existing and any new added, dynamically) is to set a event on a parent in the dom tree (parent both to the existing and to all that will be added).
In your case, the body tag would probably be the safe bet.
The following should suffice:
$('body').on('click', '.checkvalue', function() { ...
Simplified, the code will apply a listener on the body element instead of the .checkvalue objects, and whenever a object with the .checkvalue class is clicked (wether dynamically or statically loaded), the event will fire.
edit
I would also suggest that you, in your javascript, don't use jquery before you know for certain that it is loaded.
The jquery lib have a way of fixing this for you, by using the $( document ).ready() function:
$( document ).ready(function() {
// All jquery dependant code here.
});

Cannot access getElementsByTagName from external js

This thing is driving me mad... I have a simple js script wich checks for all the links tag () in a page and check if two of those links at least correspond to a given href attribute.
If I put the script in the main page as an inline script it works great. If I put it inside an external .js script on the same page, it doesn't find any element. Just like if it's only scanning its internal ones but not the parent document ones.
the script is this
var as,i,islink,l1,l2;
l1 = false
l2 = false
as=document.getElementsByTagName('a');
for(i=0;i<as.length;i++)
{
islink=as[i].href;
alert(islink);
if(islink == 'http://www.linktocheck.com/')
{
if(!as[i].getAttribute('rel')) {l1 = true;}
}
if(islink == 'http://www.linktocheck.com/somedir/somepage.asp')
{
if(!as[i].getAttribute('rel')) {l2 = true;}
}
}
if(!l1 || !l2) {alert('links not found in the page');}
I put alert(islink); for debug purposes to see if some link element has been found in the page or not.
The HTML of the calling page is this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1"><title>page a</title>
<meta name="robots" content="noarchive" />
<meta content="text/html; charset=iso-8859-1" http-equiv="content-type" /></head>
<body>
<script src="externaljstochecklinks.js?PARAMETER=somevalue" id="uniqueid" type="text/javascript"></script><div style="margin-top: 6px;margin-bottom: 4px;text-align: center;">[...] <img src="http://www.linktocheck.com/skins/some/images/some.gif" alt="" style="border: none;vertical-align: middle;" /></div>
Why if I put the link check script inline it finds the elements if I put it as external it doesn't?
You have to wait for the DOM to finish loading before you can query it to find DOM elements.
Your script appears to be at the beginning of the <body> section which means it will execute BEFORE the DOM has been parsed and loaded. Thus, there is nothing yet loaded to find.
The simplest fix would be to move your <script> tag to the end of the body right before the </body> tag. You could also use an event listener and execute your code only when the event fires indicating that the DOM is ready.
Assuming the url to the external.js file is correct, the problem might be with the synchronous loading of the js files.
As soon as the js file is downloaded, it starts running. If this happens before the DOM finished loading, it can't find any <a> tag because they don't exist yet.
To test the hypothesis, include your external js file at the end of the <BODY> tag and see if it works.
To fix this issue permanently (and you don't want to include a JS file at the end of the body, you can defer the loading by either:
using an external library (such as jquery) and place the code inside $(document).ready()
placing your code inside window.onload event
trigger your own "ready" event

What's wrong with this simple Safari Extension code?

I'm creating a Safari extension that will stay in Safari's menubar, and upon being clicked, it will open all links containing a certain string. However, it's not working.
This is what my extension builder screen looks like: http://i.imgur.com/xRXB1.png
I don't have any external scripts set as I have the script in my HTML file, because I only want it to run when clicked.
And I have a global.html page with the following code in it:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<script>
safari.application.addEventListener("comnand", performCommand, false);
Function performCommand(event) {
if (event.command == "open-designs") {
$(document).ready(function() {
$('a[href*="/Create/DesignProduct.aspx?"]').each(function() {
window.open($(this).attr('href'),'_blank');
});
});
}
}
</script>
</body>
</html>
Should this not work? I'm allowed to mix jQuery and JS write, as jQuery is JS? And isn't that how I'd target the links?
The problem is that your extensions Global page does not have direct access to the currently loaded page's DOM. To be able to achieve what you need, you'll have to use an Injected Script and use the messaging proxy to talk to the page.
For instance, your global would look like:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<script>
$(document).ready(function() {
safari.application.addEventListener("command", performCommand, false);
});
function performCommand(event) {
if (event.command == "open-designs") {
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("open-designs", "all");
}
}
</script>
</body>
</html>
And then, in Extension Builder, you'd need to add two "Start Scripts", one is jquery, the other, a new file that gets loaded into the page and looks similar to this:
function extensionname_openAll(event)
{
if (event.name == 'open-designs')
{
$('a[href*="/Create/DesignProduct.aspx?"]').each(function(index,elem) {
window.open($(elem).attr('href'),'_blank');
});
}
}
safari.self.addEventListener("message", extensionname_openAll, true);
One clear thing I'm seeing is that your $(document).ready() function is located within another function. This essentially alleviates the need for a $(document).ready() provided you only call that function once the DOM and jQuery are fully loaded.
Rearrange your code to only add the event listener once the DOM and jQuery are loaded. That is what you use the $(document).ready() callback for.
In addition there is one more issue I see with the callback function for .each(). That function needs to handle two parameters the index and the element that it references. A call to each() iterates over a collection of elements. For each element entering the callback function, its index is passed as a parameter and also the element itself that is located at that index. Check out the documentation for more info.
$(document).ready(function() {
safari.application.addEventListener("command", performCommand, false);
console.log("Document is ready to go!");
});
function performCommand(event) {
console.log("event recieved");
if (event.command == "open-designs") {
console.log("got 'open-designs' event");
$('a[href*="/Create/DesignProduct.aspx?"]').each(function(index,elem) {
console.log("opening window", index, elem);
window.open($(elem).attr('href'),'_blank');
});
}
}
You use the $(document).ready() callback as an indication that your DOM is ready and jQuery has been initialized. Once you know everything is ready, you can setup your event listener.
The function performCommand() can not be called before the listener is added (unless there is some other reference to it).

jQuery not working in Chrome 18

Nothing in jQuery appears to be working in Chrome for me. My version is 18.0.1025.151 m. The javascript is in the file test.js:
$('#paragraph').click(function() {
$('#paragraph').hide();
});
And the html is this:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery Example</title>
<script src="jquery-1.7.1.min.js"></script>
<script src="test.js"></script>
</head>
<body>
<p id="paragraph">This is my paragragh 401!</p>
</body>
</html>
I have triple-checked that the jQuery file is where it's supposed to be. Essentially, the code is supposed to make the paragraph disappear when clicked on. Seems simple enough and syntactically correct. I chose such a simple code because while regular javascript statements and code work fine (such as alert() and whatnot), absolutely nothing in jQuery has worked so far at all.
Here's the strange part though. When using the console in Chrome's developer tools, if I input the exact same jQuery stuff and hit enter, it actually works and functions how it's supposed to.
Does this have anything to do with Chrome's security structure or something?
Edit: Also, I should note that I have not yet uploaded these files on my server yet. This is on localhost (I'm using xammp for what it's worth), so perhaps that may help shed some light on the issue.
Wrap the code in a document ready, or put test.js before the end body tag.
It's executing before the DOM is ready. It should look like this:
$(function(){
$('#paragraph').click(function() {
$('#paragraph').hide();
});
});
To address the comment below:
http://api.jquery.com/ready/
The .ready() method is typically used with an anonymous function:
$(document).ready(function() {
// Handler for .ready() called.
});
Which is equivalent to calling:
$(function() {
// Handler for .ready() called.
});
You have to wrap it in document ready. That's probably your problem. Also you can use $(this) or cache the selector.
$(function () {
$('#paragraph').click(function () {
$(this).hide();
});
});

Why won't this JS code work?

Can anyone tell me why when I use the following code, clicking on "Click Here" doesn't cause an alert? Is there any way to do this without adding an onClick attribute to the div tag?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html>
<head>
<script type="text/javascript">
var clicker = document.getElementById("test");
clicker.onclick = test;
function test() {
alert('Test');
}
</script>
</head>
<body>
<div id="test">Click Here</div>
</body>
</html>
Because the element doesn't exist when you try to select it.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head></head>
<body>
<div id="test">Click Here</div>
<!-- moved the script to the end of the body element -->
<script type="text/javascript">
var clicker = document.getElementById("test");
clicker.onclick = test;
function test() {
alert('Test');
}
</script>
</body>
</html>
Looks like the JavaScript is running before the DOM loads. Try this:
window.onload = function(){
var clicker = document.getElementById("test");
clicker.onclick = test;
}
This JavaScript code gets executed before the document has loaded. This could be fixed by adding "onclick" as an attribute of the html tag (instead of dynamically registering it), or registering it in a function set as the "onload" attribute of the body tag. Also, on a somewhat separate note, why use that incredibly ancient doctype instead of the HTML5 doctype <!DOCTYPE html>?
The element 'test' has not been created when your JS is invoked. I suggest that you use jQuery and put your code inside it's document.Ready() method.
hold on the answers suggested here although they are pointing out the mistake correctly they are incorrect in some ways..
First of all you shouldnt have your Script tag within the body tag. It should always be in the head. you can jsut move the head tag to the end of the file.
Secondly as a web programmer you should always separate your concerns. Just an intro here: http://www.livestoryboard.com/Benefits/CMS-separation-of-concerns.html
Now with that in mind with respect to your program the concerns are the markup, css and script you should be having all your scripts in a separate js file and in the script tag you call document onload event and call the required function.
Hope all this makes sense

Categories