Javascript: Eventhandler not functioning, works in JSFiddle - javascript

So this is an answer to another question I posted and I think it is the correct solution. However, while it works wonderfully in jsfiddle it does not function whatsoever outside of that environment. I have tried multiple combinations and I cannot get this thing to work right.
I've tried onLoad in the body, Window.onload both in the header wrapping around the function and separately calling it at the base of the page after all the elements have loaded. Nothing works.
I always get this issue:
Uncaught TypeError: Cannot call method 'addEventListener' of null
Which is frustrating, because all other solutions to this error I have seen revolve around ensuring you do in fact have the specified ID the handler triggers off of in your HTML. Which I do.
I know its probably overkill to make a post here on this but I'm yanking my hair out.
Here's the JSfiddle: http://jsfiddle.net/fFW5r/1/
Here's a mockup page I made to test the concept (which never works):
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript">
var link_container = document.getElementById('links');
function myFunction(){ link_container.addEventListener('click', function(e){
if(e.target.nodeName === "A"){
var href = e.target.getAttribute('href'),
selfhost = window.location.hostname;
if(href.indexOf(selfhost) !== -1){
alert('Inbound link clicked');
} else {
alert('Outbound link clicked');
}
}
}, false);
}
</script>
</head>
<body onload="myFunction()">
<div id="links">
Inbound Link
Outbout Link
</div>
<script>window.onload=myFunction()</script>
</body>
</html>
This particular iteration I was trying to test it with the onload call at the bottom of the page after everything had loaded.

var link_container = document.getElementById('links'); need to be executed on document.onload so it has to be inside myFunction
In jsfiddle, the code is executed on load by default. in the fiddle at the left side panel > second select box if you select no wrap - in head you can recreate the problem.
Demo: Fiddle
<script type="text/javascript">
function myFunction(){
var link_container = document.getElementById('links'); // <<-- Move it inside `myFunction()`
link_container.addEventListener('click', function(e){
if(e.target.nodeName === "A"){
var href = e.target.getAttribute('href'),
selfhost = window.location.hostname;
if(href.indexOf(selfhost) !== -1){
alert('Inbound link clicked');
} else {
alert('Outbound link clicked');
}
}
}, false);
}
</script>

The reason it doesn't work is that you are initializing link_container before the DOM is ready. Then when myFunction() runs, link_container has been initialized to undefined. Which causes it to fail. Initializing it in the function (after the DOM has loaded) should fix the issue
Put declare link_container inside the function.
var link_container = document.getElementById('links');
function myFunction(){
link_container.addEventListener('click', function(e){
if(e.target.nodeName === "A"){
var href = e.target.getAttribute('href'),
selfhost = window.location.hostname;
if(href.indexOf(selfhost) !== -1){
alert('Inbound link clicked');
} else {
alert('Outbound link clicked');
}
}
}, false);
}

Related

How do i use javascript to manipulate empty divs?

So this is what i want to do. if my div doesn't contain anything a js file will write "no links check in the future."
my html file:
<div id="games" load="checknull(this)"></div>
my js file:
function checknull(id) {
gamelist = document.getElementById(id);
if (gamelist.innerHTML == null) {
gamelist.innerHTML = "No links check in the future"
}
}
But it doesn't work! I've linked the external js file correctly its name and the tag!
There is no load event on a div.
You can achieve the result you're looking for with the onload event of either body or window depending on the rest of your code:
<body onload="checknull(this)">
</body>
I tried this and works for me:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>empty div</title>
</head>
<body>
<div id="games"></div>
<script>
gameList = document.getElementById("games");
window.onload = function () {
if (!gameList.innerHTML) {
return (gameList.innerText = "No links check in the future");
}
};
</script>
</body>
</html>
There is two things that will not work. load handle doesn't exist on div so you could use window.onload and your condition "gamelist.innerHTML == null" will always be false you should use gamelist.innerHTML == "".
First of all, divs don't have event "load", so if you want to wait until the DOM is loaded use document.addEventListener("DOMContentLoaded", callback) instead.
Also, innerHTML and innerText either are strings, not null.
document.addEventListener("DOMContentLoaded", () => {
gamelist = document.getElementById("games");
if (!gamelist.innerHTML) {
gamelist.innerHTML = "No links check in the future"
}
});
<div id="games" load="checknull(this)"></div>

Unclear behavior of a global variable

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="/jquery-2.1.0.min.js"></script>
<title>Title!</title>
<script type="text/javascript">
var x = false;
function foo() {
alert (x);
return true;
}
window.onload = function() {
$('#my_form').attr('onsubmit', foo);
$('a').click(function(e) {
x = true;
$('#my_form').submit();
return false;
});
}
</script>
</head>
<body>
<form id="my_form" action="">
<input type="submit">
</form>
Click here!
</body>
</html>
The 'a' click function sets the variable x to be true, why it is false when foo() is run?
Raw JS events do not work the same way as jQuery events. Don't mix the two.
attr allows you to supply a function as the second parameter. That is why your code fires immediately. It is simply assigning the return value to the attribute, e.g. onsubmit="true"
Your current fiddle fires the foo handler as soon as you run this line:
$('#my_form').attr('onsubmit', foo)
You probably meant something like this (or equivalent), but it does not work either:
$('#my_form').attr('onsubmit', "javascript:foo()");
Here is the jQuery equivalent:
var x = false;
function foo() {
alert (x);
return true;
}
$(function() {
$('#my_form').submit(foo);
$('a').click(function(e) {
x = true;
$('#my_form').submit();
return false;
});
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/Lf8hhwvq/
The shortcut DOM ready handler I use above, $(function(){...});, also acts as an IIFE, so you can move the related code inside it:
$(function () {
var x = false;
function foo() {
alert(x);
return true;
}
$('#my_form').submit(foo);
$('a').click(function (e) {
x = true;
$('#my_form').submit();
return false;
});
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/Lf8hhwvq/1/
There are quite a few problems with this code. First of all, you are mixing old parts of the DOM API with jQuery. In your case I would recommend just to stick to jQuery. Amongst other things:
You should put all render-blocking code (that includes code that changes the DOM) before the </body> Tag, not in the <head>. Depending on the size of your JavaScript dependencies, your page will load very slowly.
Don't use window.load =, especially if jQuery has its very own $(document).ready() function, that probably meets your needs even better.
If you want to set an event handler, don't try to set it with the attr function. That's a very old way of doing it and also the source of your problem. Use the jQuery .on() function instead (the jQuery equivalent of .addEventListener).
If you can avoid it, don't use global variables. Wrap all your code in an IIFE instead.
Thus, your code becomes:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title!</title>
</head>
<body>
<form id="my_form" action="">
<input type="submit">
</form>
Click here!
<script src="/jquery-2.1.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var x = false;
function foo() {
alert (x);
return true;
}
$('#my_form').on('submit', foo);
$('a').on('click', function(e) {
x = true;
$('#my_form').submit();
return false;
});
});
</script>
</body>
</html>
Codepen: http://codepen.io/anon/pen/zvaOLR

Javascript: onclick function to get elements

I'm trying to get the elements of the clicked source, but I don't know why it isn't working.
JSFIDDLE
HTML:
<span class="populate" onclick="populate();" href="?id=1">Hello</span>
CSS:
.populate {
cursor: pointer;
}
JS:
function populate(event) {
var event = event || window.event;
var src = event.srcElement;
var href = src.getAttribute('href');
alert(href);
}
The error I see in console is that the function populate is not defined.
Any help or suggestions will be appreciated!
The problem is with the order of the javascript and the span tag.
put the javascript function before the tag
JS
function populate(event) {
var event = event || window.event;
var src = event.srcElement;
var href = src.getAttribute('href');
alert(href);
}
html
<span class="populate" onclick="populate();" href="?id=1">Hello</span>
We need to define functions before calling them. Fiddle here
http://jsfiddle.net/HdvGD/7/
You code works fine in fiddle. The reason you didn't get it because you wrapped in onload() instead do it in No wrap in Head (fiddle at left top)
your fiddle1
Incase you want in onload() assign like variable
populate = function (event) {
var event = event || window.event;
var src = event.srcElement;
var href = src.getAttribute('href');
alert(href);
}
Check is fiddle2
Check this [answer to find the difference]
Update:
Sorry for pointing depreciated one(I'hv removed it). Event object "event" is not passed from the parameter. Actually here is a simple one
passing the event from onclick like
onclick="populate(event);"
then simple pass it and access like below
function populate(event) {
var src = event.target || event.srcElement;
var href = src.getAttribute('href');
alert(href);
}
Final Fiddle
Anchor tags contain href attribute
<a class="populate" id="link" onclick="populate(this.id);" href="......">Hello
</a>
function populate(id)
{
var someimage = document.getElementById(id);
var mysrc = someimage .src;
}
Use jquery to get it work as simple
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#populate").click(function(event) {
alert("As you can see, the link no longer took you to jquery.com");
var href = $('#populate').attr('href');
alert(href);
event.preventDefault();
});
});
</script>
</head>
<body>
<span class="populate" id="populate" onclick="populate();" href="?id=1" >Hello</span>
</body>
</html>
Your fiddle works fine, on the left-hand side, second drop-down, change to No Wrap - In <head>, now your content is there and script is loaded. Try it again: http://jsfiddle.net/HdvGD/4/

Cloned content editable div not retaining keydown event

I'm very new to Jquery and looking to solve the reason a keydown event on a content editable div isn't cloning. I thought I had solved things when I discovered clone(true), but no my code still isn't working. The code below is a simplified version of what I'm trying to achieve.
Basically I'm attaching a keydown event to a content editable div then cloning it. However the cloned div isn't working like the original div.
I've been searching for a solution for a good while now and was hope someone could give me an answer so I can move on - many thanks.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>untitled</title>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var mymax1 = 10;
$('#List_1').keydown(function(e){ check_charcount(mymax1, e); });
function check_charcount(mymax1, e)
{
<!--prevent line breaks, that is the enter key from working-->
if(e.keyCode==13){
e.preventDefault();
}
if(e.which != 8 && $('#List_1').text().length > mymax1{
$("#List_1").css("background-color","yellow");
e.preventDefault();
}
}
<!---->
var $cloned = $('#hope').clone(true);
$('#placeHere').append($cloned.html());
});
</script>
</head>
<body>
<div id="hope">
<div id="List_1" contentEditable="true">TEXT</div>
</div>
</br>
<div id="placeHere"></div>
</body>
</html>
Some things were not correct in your code as pointed Ian.
In your keydown function you are using $('list_1'), you should use reference to element.
BTW, clone keep id attr which mean that your cloned element get same id as original, which is not valid. See working code:
$(document).ready(function () {
var mymax1 = 10;
$('#List_1').keydown(function (e) {
check_charcount(mymax1, e);
});
function check_charcount(mymax, e) {
if (e.keyCode == 13) {
e.preventDefault();
}
if (e.which != 8 && $(e.target).text().length > mymax) {
$(e.target).css("background-color", "yellow");
e.preventDefault();
}
}
var $cloned = $('#hope').clone(true);
$('#placeHere').append($cloned.contents().removeAttr('id'));
});
SEE DEMO

iOS automatic hover fix?

Is there a jQuery plugin or JavaScript script that automagically loops through each CSS hover (found in an external stylesheet) and binds it with a double touchdown event?
Touchdown 1 - CSS :hover is triggered
Touchdown 2 - Click (link following or form action)
If there isn't something like this yet, can it be made and how (guidelines)?
EDIT:
To be clear, I am not in search of a double tap. Touchdown 1 is a single tab just like Touchdown 2 is. There can be as less as 0 seconds between both or as much as 3 minutes, that's the user's choice.
No touch:
:hover -> element becomes visible
click -> following link or other action
Touch (iOS):
touchdown 1 -> element becomes visible
touchdown 2 -> following link or other action
Try 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" xml:lang="en" lang="en">
<head>
<title>iPad Experiment</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
if(navigator.platform == "iPad") {
$("a").each(function() { // have to use an `each` here - either a jQuery `each` or a `for(...)` loop
var onClick; // this will be a function
var firstClick = function() {
onClick = secondClick;
return false;
};
var secondClick = function() {
onClick = firstClick;
return true;
};
onClick = firstClick;
$(this).click(function() {
return onClick();
});
});
}
});
</script>
<style type="text/css">
a:hover {
color:white;
background:#FF00FF;
}
</style>
<body>
Google
stackoverflow.com
</body>
</html>
... or check out the demo on my web site. Note that it's set up to only work its magic on the iPad - detecting all versions of the iOS is another question in my books ;)
It works on the basis of the fact that...
After you click a link on the iphone or ipad, it leaves a simulated mouse hover that triggers the a:hover css styling on that link. If the link has a javascript handler that keeps you on same page, the hover state will not change until you click on another link.
Citation: Safari iphone/ipad “mouse hover” on new link after prior one is replaced with javascript
I've used this:
$(document).ready(function() {
$('.hover').bind('touchstart touchend', function(e) {
e.preventDefault();
$(this).toggleClass('hover_effect');
});
});
Before, to allow hover on certain elements. Obviously you'll need to tweak it for your own use, but it's a nice way to allow a touch and hold hover effect.
Here is a further optimized version that also handles closing the :hover
You'll have to encapsulate your site with a
<div id="container"></div>
for it to work. Just putting the closing event on the body did nothing
var bodyBound = false;
var container;
if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/iPad/i))
{
container = $("#container");
// Provoke iOS :hover event
$("a.someLink").on("mouseover", handleHoverClick);
}
function handleClose(event)
{
container.off("click", handleClose);
bodyBound = false;
}
function handleHoverClick(event)
{
if (!bodyBound)
{
bodyBound = true;
// Somehow, just calling this function—even if empty—closes the :hover
container.on("click", handleClose);
}
}
I created this update apon Richard JP Le Guens solution. It works GREAT, but my version fixes the issue recognized by DADU.
Also I fixed his workaround to detect iPads. My solution detects any other touch devices too (except IE10 on MS surface, I didn't remember the MS special treatment).
My fix is not a 100% perfect solution, but it resets the hover fix at least when hovering another link.
<!DOCTYPE html>
<html>
<head>
<title>TouchDevice Experiment</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
if(document.createEvent("TouchEvent")) { // using document.createEvent is more reliable than navigator (Modernizr uses this practice)
$("a").each(function() { // have to use an `each` here - either a jQuery `each` or a `for(...)` loop
var onClick; // this will be a function
var firstClick = function() {
$("a").trigger("JWUnhover"); // triggering hoverfix reset if any link gets touched
onClick = secondClick;
return false;
};
secondClick = function() {
onClick = firstClick;
return true;
};
onClick = firstClick;
$(this).click(function() {
return onClick();
});
$(this).bind('JWUnhover', function(){ onClick = firstClick; });
});
}
});
</script>
<style type="text/css">
a:hover {
color:white;
background:#FF00FF;
}
</style>
</head>
<body>
Google
stackoverflow.com
</body>
</html>
There is no jQuery plugin that I know of to do such a thing.
You cannot trigger a css psuedo class such as ":hover". You can however loop through the anchor elements and add a css class ".hover" on touchstart and touchend events as follows:
var pageLinks = document.getElementsByTagName('a');
for(var i = 0; i < pageLinks.length; i++){
pageLinks[i].addEventListener('touchstart', function(){this.className = "hover";}, false);
pageLinks[i].addEventListener('touchend', function(){this.className = "";}, false);
}
To add a double finger tap gesture recognizer, you can use a plugin such as:
http://plugins.jquery.com/project/multiswipe
This worked for me!
// Ipad Navigation Hover Support
$('#header .nav li a').bind('touchstart touchend', function(e) {
if( $(this).attr("href") != "" ){
window.location = $(this).attr("href");
}
});
Here's an optimized version of the jQuery code provided by Richard JP Le Guen:
$(document).ready(function() {
$('a').each(function() {
var clicked = false;
$(this).bind('click', function() {
if(!clicked) return !(clicked = true);
});
});
});
There is a more simpler way to fix the issue with iOS and hover states, using CSS. For the link you have an issue with set the cursor property to pointer and the hover state will be ignored on iOS. For all links to function as expected, see below:
a
{cursor: pointer;}

Categories