JavaScript get the right zero-based index of clicked link - javascript

An alert should display anchor's zero-based index within a document instead of following the link.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test page</title>
</head>
<body>
In my life, I used the following web search engines:<br/>
Yahoo!<br/>
AltaVista<br/>
Google<br/>
<script type="text/javascript" src="js/js8.js"></script>
</body>
</html>
JavaScript:
function registerHandlers() {
var as = document.getElementsByTagName('a');
for (i = as.length; i-- >= 0;) {
as[i].onclick = function() {
alert(i);
return false;
}
}
}
I tried to use jQuery:
$('a').click(function(event) {
var as = document.getElementsByTagName('a');
alert($(this).index());
});
but I got the index like 1,3,5 not 0,1,2

Try this (http://jsfiddle.net/bcjv6suf/):
alert($('a').index(this));
P.S. https://api.jquery.com/index/#index-selector
Update: same without jquery (you need use closure for pass argument)
function registerHandlers() {
var as = document.getElementsByTagName('a');
for (i = as.length; i-- > 0;) {
as[i].onclick = (function(index) {
return function() {
console.log(index);
return false;
}}(i));
}
}
http://jsfiddle.net/u9f64y0c/

Here is my solution by adding a data-index attribute to the <a>.
function registerHandlers() {
var as = document.getElementsByTagName('a');
for (var i = 0; i < as.length; i++) {
as[i].setAttribute('data-index', i);
as[i].onclick = function () {
alert(this.getAttribute('data-index'));
}
}
}

Depends what collection you are trying to find the index of for that element.
Using jQuery
Index of instance of <a> within all <a> in page:
var $links = $('a').click(function(event) {
alert($links.index(this));
});
Index within siblings group
<div id="div">
<a/>
<a/>
<a/>
</div>
$('#div a').click(function(event) {
alert($(this)index());
});
Index of element within all elements in page
$('a').click(function(event) {
alert($('*')index(this));
});

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test page</title>
</head>
<body>
In my life, I used the following web search engines:<br />
Yahoo!<br />
AltaVista<br />
Google<br />
<script type="text/javascript">
function registerHandlers() {
var as = document.getElementsByTagName("a");
for (var i = 0; i < as.length; i++) {
as[i].onclick = (function() {
var n = i;
return function() {
alert(n);
return false;
};
})();
}
}
registerHandlers();
</script>
</body>
</html>

function registerHandlers() {
var as = document.getElementsByTagName('a');
for (var i = 0; i < as.length; i++) {
as[i].addEventListener('click', (function(i) {
return function(e) {
e.preventDefault();
alert(i);
}
})(i));
}
}
registerHandlers();

jQuery or exotic properties like setAttribute are not necessary. This question is about closures. Also don't forget to prevent the default behaviour, which was part of this practice question at present.
function registerHandlers() {
var as = document.getElementsByTagName('a');
for (var i = 0; i < as.length; i++) {
const index = i; // the following anon function closes over this variable
as[i].onclick = function(event) {
event.preventDefault(); // prevent default behaviour
alert(index);
return false;
}
}
}

The simplest way to debug this is to change the var i to let i = 0. let creates its own block scope within the onclick function. So, when the value of i is returned from within the onclick function scope, the value of i is preserved and gives zero-based index value. Without this, for loop has already run and the value of i it returns is the last value, which is 3, even if you click on any link.
function registerHandlers() {
var as = document.getElementsByTagName('a');
for (let i =0; i< as.length; i++) {
as[i].onclick = function() {
alert(i);
return false;
}
}
}

function registerHandlers() {
var as = document.getElementsByTagName("a");
for (var i = 0; i < as.length; i++) {
as[i].onclick = (function() {
var n = i;
return function() {
alert(n);
return false;
};
})();
}
}
registerHandlers();
In my life, I used the following web search engines:<br />
Yahoo!<br />
AltaVista<br />
Google<br />

Related

HtmlService: google.script.run not recognizing gs function

I'm currently trying to pass an array of values from a Google Sheet to the HtmlService where I will have the user choose an option and eventually pass it back to the .gs script. I have been using these two links as references:
1. Google Documentation
2. Stack Overflow example
When running the code, I looked at my console and noticed this error:
VM3051:4 Uncaught TypeError: google.script.run.withSuccessHandler(...).getVersionArray is not a function
It appears that getVersionArray() is not being passed correctly. When removing this function from the rest of that google.script.run call, the error goes away.
Also, per link two, I tried that code with the template and never even got a window to pop up, so I have been using the HtmlOutput example from the Google documentation link as a starting point. I have also tried the code with and without the SandboxMode declaration.
gs code:
function bugPieChart() {
getVersionArray();
openDialog();
function getVersionArray() {
var ss = SpreadsheetApp.getActive();
var valuesR = ss.getSheetByName("report").getRange('R1:R').getValues();
var valuesS = ss.getSheetByName("report").getRange('S1:S').getValues();
var versionRSArray = [];
for (var i = 0; i < valuesR.length; i++) {
versionRSArray.push(valuesR[i][0]);
}
for (var i = 0; i < valuesS.length; i++) {
versionRSArray.push(valuesS[i][0]);
}
versionRSArray.sort();
var uniqueArray = [];
uniqueArray.push(versionRSArray[0]);
for (var i in versionRSArray ) {
if((uniqueArray[uniqueArray.length-1]!=versionRSArray[i]) && (versionRSArray[i] !== "")) {
uniqueArray.push(versionRSArray[i]);
}
}
return uniqueArray;
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('index');
SpreadsheetApp.getUi().showModalDialog(html, 'Dialog title');
var htmlOutput = html.setSandboxMode(HtmlService.SandboxMode.NATIVE);
return htmlOutput;
}
}
index.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
$(function() {
google.script.run.withSuccessHandler(buildOptionsList)
.getVersionArray();
});
function buildOptionsList(uniqueArray) {
var list = $('#optionList');
list.empty();
for (var i = 0; i < uniqueArray.length; i++) {
list.append('<option value="' + uniqueArray[i].toLowerCase() + '">' + uniqueArray[i] + '</option>');
}
}
</script>
</head>
<body>
<select id="optionList">
<option>Loading...</option>
</select>
<input type="button" value="Close" onclick="google.script.host.close()" />
</body>
</html>
I think your just missing a closing bracket on the function above it.
function bugPieChart() {
getVersionArray();
openDialog();
}
function getVersionArray() {
var ss = SpreadsheetApp.getActive();
var valuesR = ss.getSheetByName("report").getRange('R1:R').getValues();
var valuesS = ss.getSheetByName("report").getRange('S1:S').getValues();
var versionRSArray = [];
for (var i = 0; i < valuesR.length; i++) {
versionRSArray.push(valuesR[i][0]);
}
for (var i = 0; i < valuesS.length; i++) {
versionRSArray.push(valuesS[i][0]);
}
versionRSArray.sort();
var uniqueArray = [];
uniqueArray.push(versionRSArray[0]);
for (var i in versionRSArray ) {
if((uniqueArray[uniqueArray.length-1]!=versionRSArray[i]) && (versionRSArray[i] !== "")) {
uniqueArray.push(versionRSArray[i]);
}
}
return uniqueArray;
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('index');
SpreadsheetApp.getUi().showModalDialog(html, 'Dialog title');
var htmlOutput = html.setSandboxMode(HtmlService.SandboxMode.NATIVE);
return htmlOutput;
}

Unexpected hidden div appears in html file

I have been trying to search this, but haven't even found anyone with the same problem.
For my assignment, I had to write a javascript code that would read all the text from the external page (from the same directory though), but that's not the problem. The problem appeared when I have created a test html file with some random text.
HTML Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<p> Just a random text.</p>
<h1> More of a random text</h1>
<p> And again, just testing the program.</p>
</body>
</html>
And this code is taken from the debugger:
Image of html file as from Inspector
The problem is my javascript code does read the text from this div element and append the array of words that i have.
Does anyone know why is this div generated and how to get rid of it ?
P.S I have tried creating other html files, but div appears there too.
Thanks in advance!
EDIT:
That's my JS code:
var externalPage;
var words = [];
var j = 0;
function indexOf(array, item) {
for (var i = 0; i < array.length; i++) {
if (array[i][0].toString() === item.toString()) return i;
}
return -1;
}
function clearNode(node) {
while (node.firstChild) {
node.removeChild(node.firstChild);
}
}
function sortNumerically(words) {
return words.sort(function(a,b){
return b[1] - a[1];
});
}
function sortAlphabetically(words) {
return words.sort();
}
function openFile(url) {
externalPage = window.open();
externalPage.location = url;
}
function extractWords(node) {
if (node.nodeType==Node.ELEMENT_NODE) {
for (var m = node.firstChild; m!=null; m = m.nextSibling)
extractWords(m);
}
else {
var value = node.nodeValue.trim();
value = value.split(/\s/);
for(var i = 0; i < value.length; i++) {
if(indexOf(words, value[i]) != -1) {
words[indexOf(words, value[i])][1] =
words[indexOf(words, value[i])][1] + 1;
} else if(value[i] != '') {
words.push([]);
words[j][0] = value[i];
words[j][1] = 1;
j++;
}
}
}
}
function populateTable(arr) {
var tbody = document.createElement('tbody');
clearNode(tbody);
for(var i = 0; i< words.length; i++) {
var tr = document.createElement('tr');
var tdW = document.createElement('td');
var tdF = document.createElement('td');
tdW.appendChild(document.createTextNode(arr[i][0]));
tdF.appendChild(document.createTextNode(arr[i][1]));
tr.appendChild(tdW);
tr.appendChild(tdF);
tbody.appendChild(tr);
}
document.getElementById('tableCounter').appendChild(tbody);
}
function generateArray(node) {
words = [];
j = 0;
extractWords(node, words);
alert(sortNumerically(words));
populateTable(words);
}
This hidden box is an effect of a virus. The page dataloading.net is know as a virus page. You can search for it with your favourite search-module (google, bing, ...).
As attached code snap that DIV definitely come from JS or any JS plugin which simply append to body with generated code.

for loop an argument in function

I was doing this code but it will take time because it will be h1 up until h24 so i decided to use a for loop but i don't know how..
this is my original code
function hover(h1,h2,h3,h4){
document.getElementById(h1).style.backgroundColor="orange";
document.getElementById(h2).style.backgroundColor="orange";
document.getElementById(h3).style.backgroundColor="orange";
document.getElementById(h4).style.backgroundColor="orange";
}
and i want to replace it something like this
function hover(
for(i = 1; i<=24; i++) {
document.write("h"+i+",");
}
)
but there is an error.. Please help me out.. Thank you
function hover() {
for(var i = 1; i < 25; i++) {
document.getElementById("h" + i).style.backgroundColor="orange";
}
}
If you could need more control, you could set the upper limit as a parameter, e.g.
function hover(limit) {
for(var i = 1; i <= limit; i++) {
document.getElementById("h" + i).style.backgroundColor="orange";
}
}
A call to hover(10); would change the background colour of h1 through h10.
There are several things wrong with the code you posted. I think I understand the problem you are trying to solve though. Try something like this:
function hover(eleId){
document.getElementById(eleId).style.backgroundColor="orange";
}
for(i=1; i<=24; i++){
hover("h"+i.toString());
}
Also note h1, h2, h3 all look like HTML tags. Check out getElementsByTagName.
You need to use Javascript's arguments object
function hover() {
var args = Array.prototype.slice.call(arguments);
var length = args.length;
for (var i = 0; i < length; i++) {
document.getElementById(args[i]).onmouseover =
function () { this.style.backgroundColor = "orange"; }
document.getElementById(args[i]).onmouseout =
function () { this.style.backgroundColor = "transparent"; }
}
}
jsFiddle Demo
HTML:
<div id="h1">A</div>
<div id="Hello">B</div>
<div id="box">C</div>
<div id="World">D</div>
JS Call:
hover("h1", "Hello", "box", "World");
Here is my suggestion :
<div id="h1">test</div>
<div id="h2">test</div>
<div id="h3">test</div>
<div id="h4">test</div>
script, notice the dummy variable
<script>
function hover(dummy){
for (var i=0; i<arguments.length; i++) {
var element = document.getElementById(arguments[i]);
element.onmouseover = function() {
this.style.backgroundColor="orange";
}
element.onmouseout = function() {
this.style.backgroundColor="white";
}
}
}
//hover('h1','h2','h3','h4');
for (var i=1;i<=24;i++) {
hover('h'+i);
}
</script>

Select all links and forms without jQuery

How can I select all a and form tags without needing to include jQuery?
I ultimately am trying to do the following:
$("a").click(function {
window.onbeforeunload = null;
});
$("form").submit(function {
window.onbeforeunload = null;
});
But I really would rather not include jQuery (or even Sizzle.js), if there's a more compact way to do that.
You can use document.querySelectorAll() like this:
var els = document.querySelectorAll( 'a' );
for( var i=els.length; i--; ) {
els[i].addEventListener( 'click', function(){ window.onbeforeunload = null; } );
}
Similar for the <form> tags.
It is available in most modern browsers (caniuse.com).
This should do it:
var links = document.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
links[i].addEventListener("click", function() { console.log("Clicked"); window.onbeforeunload = null; });
}
To get the form submit, you can do something like this:
<script>
do_function() { window.onbeforeunload = null; }
</script>
<form action="" onsubmit="do_function()" method="">
EDIT:
To combine the two:
var links = document.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
links[i].addEventListener("click", function() { console.log("Clicked"); window.onbeforeunload = null; });
}
var forms = document.getElementsByTagName("form");
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener("submit", function() { console.log("Submitted"); window.onbeforeunload = null; });
}
Fiddle

Javascript for loop and alert

I am looping through a list of links. I can correctly get the title attribute, and want it displayed onclick. When the page is loaded and when I click on a link, all of the link titles are alerted one by one. What am I doing wrong?
function prepareShowElement () {
var nav = document.getElementById('nav');
var links = nav.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
links[i].onclick = alert(links[i].title);
}
}
What you were doing was actually running the alert function.
enclosing the whole thing in an anonymous function will only run it when it is clicked
for (var i = 0; i < links.length; i++) {
links[i].onclick = function () {
alert(this.title);
}
}
You are assigning the onclick to the return value of alert(links[i].title); which doesn't make any sense, since onclick is supposed to be a function.
What you want instead is somethig like onclick = function(){ alert('Hi'); };
But
Since you are using a variable i in that loop you need to create a local copy of it
onclick = function(){ alert(links[i].title); }; would just use the outer scope i and all your links would alert the same message.
To fix this you need to write a function that localizes i and returns a new function specific to each link's own onclick:
onclick = (function(i){ return function(e){ alert(links[i].title); }; })(i);
Final result:
function prepareShowElement () {
var nav = document.getElementById('nav');
var links = nav.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
links[i].onclick = (function(i){ return function(e){ alert(links[i].title); }; })(i);
}
}
You can use jquery. To display title of the link on click.
$("#nav a").click(function() {
var title = $(this).attr('title');
alert(title);
});
links.forEach(function(link) {
link.onclick = function(event) {
alert(link.title);
};
}
Also note that your original solution suffered from this problem:
JavaScript closure inside loops – simple practical example
By passing in our iteration variable into a closure, we get to keep it. If we wrote the above using a for-loop, it would look like this:
// machinery needed to get the same effect as above
for (var i = 0; i < links.length; i++) {
(function(link){
link.onclick = function(event) {
alert(link.title);
}
})(links[i])
}
or
// machinery needed to get the same effect as above (version 2)
for (var i = 0; i < links.length; i++) {
(function(i){
links[i].onclick = function(event) {
alert(links[i].title);
}
})(i)
}
You need change .onclick for a eventlistener same:
function prepareShowElement () {
var nav = document.getElementById('nav');
var links = nav.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click',function() {
alert(links[i].title);
},false);
}
}

Categories

Resources