dynamic link making and pure javascript - javascript

I have a link like:
test
and a javascript variable:
var t='this';
How can I make the click on the link go to http://www.example.com/'+this using pure javascript?
(so clicking makes a dynamic url that has the variable t at the end)

You could provide your anchor an id:
test
and then:
var t = 'this';
document.getElementById('mylink').onclick = function() {
window.location.href = this.href + t;
return false;
};
obviously if you are putting this script in the <head> section you might need to wait for the DOM to be ready before attempting to attach click handlers:
window.onload = function() {
document.getElementById('mylink').onclick = function() {
window.location.href = this.href + t;
return false;
};
};
If you cannot modify your DOM to provide an unique id to your anchor you could use the document.getElementsByTagName method which will return you an array of all elements with the given tag in your DOM and then you will have to loop through them and attach the onclick handler to your anchor. In order to identify it between all the links that you might have, you will have to use either its innerHTML text or the current href property.

Based on Darin solition, this opens into a new window and does not modify original;
window.onload = function() {
document.getElementById('mylink').onclick = function() {
window.open(this.href + t);
return false;
};
};

Related

Load script on event and trigger the same event

I am trying to add certain javascript files on an event, say click. I am trying to use the Javascript to be used on same event, only if it is triggered. This is because the scripts are slowing down the page load and there is no need for the scripts otherwise.
Can I just move the scripts to the footer and be all set, or do this pro grammatically via loading them only when needed - via event triggering instead? Below is what I have so far:
HTML:
<a id="customId" href="#myLink"></a>
Javascript:
$(document).ready(function() {
//The async addition
var myJS = {
lazyload : function(scriptSrc) {
if(!this.isPresent(scriptSrc)){
var scriptTag = document.createElement('script');
scriptTag.src = scriptSrc;
scriptTag.async = true;
document.getElementsByTagName('head')[0].appendChild(scriptTag);
}
return false;
}
};
//The event trigger needs to do something using the said script
if($('#customId')){
//Approach 1:
var mapEl = document.getElementById("customId");
mapEl.addEventListener("click", customEventHandler, false);
//mapEl.dispatchEvent(event);
//*where
customEventHandler : function(e){
e.preventDefault;
myJS.lazyload('/jsfile.js');
// Update or use link relative #href (not complete path) and use the javascript without navigating out of page.
//e.currentTarget.dispatchEvent(?);
}
//2nd attempt: Adds the script, but not able to trigger event to use JS
$('#customId').click(function(event) {
event.preventDefault();
myJS.lazyload('/jsfile.js');
//Either approach:
//Trigger the custom event to do an actual click after doing the lazy load, using the JS file
(click); $('#customId').trigger('click'); //Is this correct on same element ID
});
}
}
Try using onload event of script element, defining a custom event to prevent recursively calling native click event handler on element
$(document).ready(function() {
//The async addition
var myJS = {
lazyload: function(scriptSrc, id, type) {
// use `.is()` to check if `script` element has `src`
// equal to `scriptSrc`
if (!$("script[src='"+ scriptSrc +"']").is("*")) {
var scriptTag = document.createElement("script");
scriptTag.src = scriptSrc;
scriptTag.async = true;
// use `script` `onload` to trigger custom event `customClick`
scriptTag.onload = function() {
$(id).trigger(type)
};
document.getElementsByTagName("head")[0].appendChild(scriptTag);
}
return false;
}
};
$("#customId").on("click", function() {
myJS.lazyload("jsfile.js", "#" + this.id, "customClick");
})
// do stuff at `customClick` event
.one("customClick", function(e) {
customClick(e.type)
});
});
plnkr http://plnkr.co/edit/Rw4BRAfSYlXXe5c6IUml?p=preview

How to show the result of this jQuery function without the need of clicking the button?

I have this function below, however I want to make it work on windows load and show the result without clicking the button.
This is the code I use https://raw.githubusercontent.com/SuyashMShepHertz/indexedDB_sample/master/index.html
How to do this?
$("#getBtn").click(function(){
var type = 'permanent';
var request = db.transaction(["hashes"],"readwrite").objectStore("hashes").get(type);
request.onsuccess = function(event){
$("#result").html("Name : "+request.result.name);
};
});
just put your code in
$( window ).load(function() {
//Code Here
});
If you need it both on click and initially when the page loads, make it a reusable function:
function doTheThing() {
var type = 'permanent';
var request = db.transaction(["hashes"], "readwrite").objectStore("hashes").get(type);
request.onsuccess = function(event) {
$("#result").html("Name : " + request.result.name);
};
}
Then call it from both places you need it:
On page load
On click
To call it on page load, just make sure your script is at the end of the HTML (just before the closing </body> tag; this is best practice unless you have a good reason for doing something else) and call it:
doTheThing();
If you can't put the script at the end of the HTML, you can use jQuery's ready callback instead:
// Concise, but easy to misunderstand:
$(doTheThing);
// Or more verbose but also more clear:
$(document).ready(doTheThing);
(See note below about doing it directly or indirectly.)
To call it on click, hook it up, either directly or indirectly:
// Directly
$("#getBtn").click(doTheThing);
// Or indirectly
$("#getBtn").click(function() {
doTheThing();
});
The only reason for hooking it up indirectly would be to avoid having it receive the event object jQuery will pass it automatically, and to avoid having its return value examined by jQuery to see if it should stop propagation and prevent the default event action.
To avoid creating globals, I'd make sure the entire thing is in a scoping function:
(function() {
function doTheThing() {
var type = 'permanent';
var request = db.transaction(["hashes"], "readwrite").objectStore("hashes").get(type);
request.onsuccess = function(event) {
$("#result").html("Name : " + request.result.name);
};
}
doTheThing();
$("#getBtn").click(doTheThing);
})();
just put it in $(document).ready, like this
$(document).ready(function(){
var type = 'permanent';
var request = db.transaction(["hashes"],"readwrite").objectStore("hashes").get(type);
request.onsuccess = function(event){
$("#result").html("Name : "+request.result.name);
};
});

addEventListener only firing once

I'm adding a click event to all links that match a particular selector as part of a JS module I'm creating. It looks something like this.
var Lightbox = (function () {
var showLightbox = function () {
// this does stuff
};
var init = function () {
var links = document.querySelectorAll(options.selector);
for(var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function() {
showLightbox();
}, false);
}
};
return {
init: init
};
})();
Lightbox.init();
On first load the any links on the page that match the selector work. There is also a closeLightbox() method that works fine. However when clicking the links for a second time nothing happens. I get no console errors – nuffin.
Is there something I'm doing wrong when adding the event listener?
EDIT: I've updated the code to remove some redundant methods and have pasted the full code here: http://pastebin.com/mC8pSAV2
You are reassigning innerHTML of the whole document:
document.body.innerHTML += response;
on the link click. That wipes out all existing DOM elements with their events and creates new DOM structure with no clicks assigned.

Click all anchor tags on page with given class, but cancel prior to navigation

Trying to automate some testing for some analytics tracking code, and I'm running into issues when I try passing links into the each() method.
I copied a lot of this from stackoverflow - how to follow all links in casperjs, but I don't need return the href of the link; I need to return the link itself (so I can click it). I keep getting this error: each() only works with arrays. Am I not returning an array?
UPDATE:
For each anchor tag that has .myClass, click it, then return requested parameters from casper.options.onResourceReceived e.g. event category, event action, etc. I may or may not have to cancel the navigation the happens after the click; I simply only need to review the request, and do not need the follow page to load.
Testing steps:
click link that has .myClass
look at request parameters
cancel the click to prevent it from going to the next page.
I'm new to javascript and casper.js, so I apologize if I'm misinterpreting.
ANOTHER UPDATE:
I've updated the code to instead return an array of classes. There are a few sketchy bits of code in this though (see comments inline).
However, I'm now having issues canceling the navigation after the click. .Clear() canceled all js. Anyway to prevent default action happening after click? Like e.preventDefault();?
var casper = require('casper').create({
verbose: true,
logLevel: 'debug'
});
casper.options.onResourceReceived = function(arg1, response) {
if (response.url.indexOf('t=event') > -1) {
var query = decodeURI(response.url);
var data = query.split('&');
var result = {};
for (var i = 0; i < data.length; i++) {
var item = data[i].split('=');
result[item[0]] = item[1];
}
console.log('EVENT CATEGORY = ' + result.ec + '\n' +
'EVENT ACTION = ' + result.ea + '\n' +
'EVENT LABEL = ' + decodeURIComponent(result.el) + '\n' +
'REQUEST STATUS = ' + response.status
);
}
};
var links;
//var myClass = '.myClass';
casper.start('http://www.leupold.com', function getLinks() {
links = this.evaluate(function() {
var links = document.querySelectorAll('.myClass');
// having issues when I attempted to pass in myClass var.
links = Array.prototype.map.call(links, function(link) {
// seems like a sketchy way to get a class. what happens if there are multiple classes?
return link.getAttribute('class');
});
return links;
});
});
casper.waitForSelector('.myClass', function() {
this.echo('selector is here');
//this.echo(this.getCurrentUrl());
//this.echo(JSON.stringify(links));
this.each(links, function(self, link) {
self.echo('this is a class : ' + link);
// again this is horrible
self.click('.' + link);
});
});
casper.run(function() {
this.exit();
});
There are two problems that you're dealing with.
1. Select elements based on class
Usually a class is used multiple times. So when you first select elements based on this class, you will get elements that have that class, but it is not guaranteed that this will be unique. See for example this selection of element that you may select by .myClass:
myClass
myClass myClass2
myClass myClass3
myClass
myClass myClass3
When you later iterate over those class names, you've got a problem, because 4 and 5 can never be clicked using casper.click("." + links[i].replace(" ", ".")) (you need to additionally replace spaces with dots). casper.click only clicks the first occurrence of the specific selector. That is why I used createXPathFromElement taken from stijn de ryck to find the unique XPath expression for every element inside the page context.
You can then click the correct element via the unique XPath like this
casper.click(x(xpathFromPageContext[i]));
2. Cancelling navigation
This may depend on what your page actually is.
Note: I use the casper.test property which is the Tester module. You get access to it by invoking casper like this: casperjs test script.js.
Note: There is also the casper.waitForResource function. Have a look at it.
2.1 Web 1.0
When a click means a new page will be loaded, you may add an event handler to the page.resource.requested event. You can then abort() the request without resetting the page back to the startURL.
var resourceAborted = false;
casper.on('page.resource.requested', function(requestData, request){
if (requestData.url.match(/someURLMatching/)) {
// you can also check requestData.headers which is an array of objects:
// [{name: "header name", value: "some value"}]
casper.test.pass("resource passed");
} else {
casper.test.fail("resource failed");
}
if (requestData.url != startURL) {
request.abort();
}
resourceAborted = true;
});
and in the test flow:
casper.each(links, function(self, link){
self.thenClick(x(link));
self.waitFor(function check(){
return resourceAborted;
});
self.then(function(){
resourceAborted = false; // reset state
});
});
2.2 Single page application
There may be so many event handlers attached, that it is quite hard to prevent them all. An easier way (at least for me) is to
get all the unique element paths,
iterate over the list and do every time the following:
Open the original page again (basically a reset for every link)
do the click on the current XPath
This is basically what I do in this answer.
Since single page apps don't load pages. The navigation.requested and page.resource.requested will not be triggered. You need the resource.requested event if you want to check some API call:
var clickPassed = -1;
casper.on('resource.requested', function(requestData, request){
if (requestData.url.match(/someURLMatching/)) {
// you can also check requestData.headers which is an array of objects:
// [{name: "header name", value: "some value"}]
clickPassed = true;
} else {
clickPassed = false;
}
});
and in the test flow:
casper.each(links, function(self, link){
self.thenOpen(startURL);
self.thenClick(x(link));
self.waitFor(function check(){
return clickPassed !== -1;
}, function then(){
casper.test.assert(clickPassed);
clickPassed = -1;
}, function onTimeout(){
casper.test.fail("Resource timeout");
});
});

Track onclick events

My goal is to store the total amount of clicks on links in a certain page into a variable and recall that variable when the user exits the page. Would this be a correct way of doing it?
window.onunload = function(){
alert("Total Links Clicked:" + clicks(););
}
var clicks = function(){
var clickArray = [];
var getLinks = document.getElementsByTagName(A);
var clickValue = getLinks.onclick = function() {
clickArray.push("1");
}
var totalClicks = clickArray.length;
return totalClicks;
}
Your code won't work for several reasons:
You bind the click handler in clicks() function and don't call clicks() until the page is unloaded, at which point it is too late to handle any clicks. You need to bind the click handler when the page loads.
You can't set .onclick on a list of elements, which is what your getLinks variable is given it was set to the result of getElementsByTagName() (get elements not get element).
You pass an undeclared variable A to getElementsByTagName(); you should pass the string "a".
You have a semicolon inside the alert()'s closing ), which is a syntax error.
You could try something like this:
window.onload = function() {
var clicks = 0;
window.onunload = function(){
alert("Total Links Clicked:" + clicks);
}
function clicked() {
clicks++;
}
var getLinks = document.getElementsByTagName("a");
for (var i = 0; i < getLinks.length; i++)
getLinks[i].onclick = clicked;
};
Note that the browser may block an alert() during an unload event, but if you use console.log() instead you can see that clicks had the right value.
Note also that of course a click on a link to another page will cause an unload, so the click count will only be more than 1 if you have links within the current page.
Demo: http://jsfiddle.net/A3bkT/1/
You can use sessionStorage or localStorage for that.
if(typeof(Storage)!=="undefined")
{
// store the clicks here
sessionStorage.numClicks = value;
}
and read more on these two here : http://www.w3schools.com/html/html5_webstorage.asp
Bind a global event listener and just store the count with sessionStorage:
var clicks = 0;
document.addEventListener('click', function(event) {
if (event.target.nodeName == 'A') {
window.sessionStorage.setItem('clicks', ++clicks);
}
}, false);

Categories