I'm attempting to add target="_blank" to links on a page depending on a checkbox click.
On the javascript side I have:
function newTab(v) {
if(v.tab.checked == true) {
document.getElementsByTagName('a').setAttribute('target', '_blank');
} else {
document.getElementsByTagName('a').setAttribute('target', '_self');
}
} //end function
And on the HTML side I have:
<form>
<input type="checkbox" name="tab" onclick="newTab(this.form)" />
<label>Open Links In New Tab?</label>
</form>
Gmail
Naturally it isn't as simple as I thought it would be, so it doesn't work.
The page contains over a dozen links so I need the checkbox to apply to all links on the page - why I used getElementsByTagName(). Any help appreciated!
EDIT:
Code that works is as follows:
function newTab(f) {
var els = document.getElementsByTagName('a'); //read anchor elements into variable
if(f.tab.checked == true) { //If the box is checked.
for (var i in els) {
els[i].setAttribute('target', '_blank'); //Add 'target="blank"' to the HTML
}
} else { // not checked...
for (var i in els) {
els[i].setAttribute('target', '_self'); //Add 'target="self" to HTML
}
}
} //end function.
getElementsByTagName() returns a nodeset. You need to iterate over it and apply the change to each one in turn. What you currently have is more like jQuery syntax, which handles this internally for you.
This would have shown up in the console. With JS issues, always check the console before wondering what's wrong.
var els = document.getElementsByTagName('p');
for (var i=0, len = els.length; i<len; i++)
els[i].setAttribute('name', 'value');
Also, with checkboxes use change, not click events, as someone might toggle them via the keyboard, not mouse. Lastly, you should look into handling your events centrally, not inline DOM-zero events specified in the HTML. Numerous reasons for this that are beyond the scope of this question.
Related
Might be a strange setup, but I have a number of hyperlinks on the page with the same id (yeah, I know, but it was not my choice and I cannot change that at this time plus those hyperlinks are generated dynamically).
Example:
<div id="Links">
<div class="myItem">Some text</div>
<div class="myItem">More text</div>
<div class="myItem">Even more text</div>
</div>
Now I need to attach javascript to those links dynamically (the hyperlinks are also dynamically generated). The easiest way I see is by getting all hyperlinks on the page and then check the hyperlink id to ensure I only take care of those that have id of "myLink" (I have many other hyperlinks on the page).
I thought of using getElementById but that would only grab the first element with the specified id.
am attaching javascript to those links using the following:
window.onload = function() {
var anchors = document.getElementsByTagName('a');
for(var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
if (anchor.id='myLink')
{
if (anchor.getAttribute("LinkID") != null)
{
anchor.onclick = function() {
MyFunction(this.getAttribute("LinkID"), false);
return false;
}
}
}
}
}
The above function works fine, but it creates another issue - affects the styling of other hyperlinks on the page. So I was wondering if there is a way to accomplish the same thing but without affecting other elements on the page?
This is more modern and corrects your equality test:
window.onload = function() {
var anchors = document.getElementsByTagName('a');
for(var i = 0; i < anchors.length; i++) {
if (anchor[i].id==='myLink' && anchor[i].getAttribute("LinkID") !== null)
{
anchor[i].addEventListener("click", function() {
MyFunction(this.getAttribute("LinkID"), false);
}
}
}
}
Even with your original code, I don't see anything that would interfere with styling in the code. Can you elaborate as what styling changes you were getting?
You can use an attribute selector and document.querySelector([id=<id>]) pretty reliably depending on your browser support situation: http://codepen.io/anon/pen/YwLdKj
Then, of course, loop through that result and make subsequent changes or event bindings.
If not, you could use jQuery (referenced in above code pen).
You might also use JavaScript event delegation and listen for all click events, check if the user is clicking a link with the correct id.
If a combination of tag == 'a', class == "myItem" and presence of a LinkID attribute is sufficient to identify nodes requiring a click handler they could be identified using multiple CSS selectors. If this is not possible however, a query selector not using id can create a list of nodes to be checked for id, as for example:
function callMyFunction()
{ MyFunction(this.getAttribute("LinkID"), false);
}
function addClickHandlers()
{ var list = document.querySelectorAll("a[LinkID]")
var i, node;
for( i = 0; i < list.length; ++i)
{ node = list[i];
if(node.id == "myLink")
{ node.onclick=callMyFunction;
}
}
}
See also running a selector query on descendant elements of given node if of interest.
I have this in my html, which works:
<input id="File1" type="file" runat="server" onchange="fileUpload(value)" />
But for IE8 and below I have a button to create a new input: type=file
It is working and uploads the file.
But I need to send the value to a function first.
newUploadBox.setAttribute("onchange", "fileUpload(value)");
Now when I go into inspect element, everything looks right.
It renders out like the original input.
Unfortunately, it does not go to the function like the first one does.
I fond some post on here:
Dynamically added SELECT element does not fire onchange event in Internet Explorer
&& onchange with alert not working in ie
But none are able to help me.
https://jsfiddle.net/satjzr6z/
Try this code
newUploadBox.onchange = fileUpload.bind(this, value);
function.prototype.bind - creates a bound function that has the same body as the original function
Method description
I added a onClientClick event handler to check the validation for me instead of doing an onchange event listener.
I used the following function:
function FileUploadValidate() {
var input;
var thisId;
var fileInput;
input = document.getElementsByTagName("input");
for(i = 0;i < input.length; i++)
{
if(input[i].getAttribute("type") === "file"){
thisId = input[i].getAttribute("id");
fileInput = document.getElementById(thisId);
fileUpload(fileInput.value, thisId)
}
}
for(i = 0;i < input.length; i++)
{
if(input[i].getAttribute("type") === "file"){
thisId = input[i].getAttribute("id");
if(document.getElementById(thisId).style.backgroundColor === "#ff0000"){
alert("true")
document.getElementById("decoyBtn").innerText = "Check"
return
}else{
document.getElementById("decoyBtn").style.display = "none"
document.getElementById("btnSubmit").style.display = "inline"
}
}
}
}
This will parse through all my file upload input fields.
If one doesnt meet my requirements it will not allow them to upload.
It is the best work around I could come up with that would work in IE8.
I also used a decoy button that would basically be my "onClientClick" because I didnt want an accidental upload.
The second for each loop checks the condition of all of them validating and if they do it will take the decoy button off the DOM and bring in the ASP.NET button for upload.
I have a javascript file that sets an EventListener of 'click' on every element with the <article> tag. I want to get the id of the article clicked when the event fires. For some reason, my code produces nothing!
My javascript:
articles = document.getElementsByTagName('article');
articles.addEventListener('click',redirect(e),false);
function redirect(e){
alert(e.target.id);
}
Why isn't this working? BTW my article setup is in a function called when the window is loaded, and i know that works for sure because that function has other stuff that work.
EDIT
So i fixed my code so it will loop and add the listener to every article element, and now i get an alert box with nothing in it. When trying to output the e.target without the ID, i get the following message for every element:
[object HTMLHeadingElement]
Any suggestions?
ANOTHER EDIT
My current javascript code:
function doFirst(){
articles = document.getElementsByTagName('article');
for (var i = 0; i < articles.length; i++) {
articles[i].addEventListener('click',redirect(articles[i]),false);
}
}
function redirect(e){
alert(e.id);
}
window.addEventListener('load',doFirst,false);
This is showing my alert boxes when the page finished loading, without considering that i haven't clicked a damn thing :O
You are not passing an article object to redirect as a parameter.
Try this (EDIT):
articles = document.getElementsByTagName('article');
for (var i = 0; i < articles.length; i++) {
articles[i].addEventListener('click',redirect,false);
}
function redirect(ev){
alert(ev.target.id);
}
Hope, it will solve the bug.
Why is nobody mentioning a single event which checks for the clicked element?
document.body.addEventListener('click', function(e) {
var target = e.target;
if (target.nodeName === 'article') {
// do whatever you like ;-)
}
e.stopPropagation()
});
it's more performant to have less events..
if you don't need to check for click events on the whole body you could attach the event to some closer parent element
You are executing the redirect function instead of passing the reference, try this:
articles = document.getElementsByTagName('article');
articles.addEventListener('click',redirect,false);
function redirect(e){
alert(e.target.id);
}
Edit:
Also, getElementsByTagName returns an array with articles, so you have to loop through them and call addEventListener on each one of them.
articles = document.getElementsByTagName('article');
for (var i = 0; i < articles.length; i++) {
articles[i].addEventListener('click',redirect,false);
}
function redirect(e){
alert(e.target.id);
}
getElementsByTagName returns a nodelist. You can then add an eventlistener to each one of those elements with a for loop.
<div id="test">
hey
</div>
<div id="test2">
yo
</div>
<script>
var nl = document.getElementsByTagName('div');
for(var i=0; i<nl.length; i++){
nl[i].addEventListener('click', function(e){
alert(e.target.id);
},false);
}
</script>
This mini javascript libary (1.3 KB) can do all these things
https://github.com/Norair1997/norjs/
nor.event(["#first"], ["touchstart", "click"], [doSomething, doSomething]);
This plugin can handle such stuff and more
Sry for bumping this old post, but I would do something like this
const myElements = document.querySelectorAll("article")
myElements.forEach(x => x.setAttribute("onclick", "alertFunction(this.id)"))
function alertFunction(theId){
alert(theId)
}
That would be if JavaScript is what you need. But today you can use JQuery instead, and that would be less code.
articles.addEventListener('click',redirect,false); // omit redirect(e) inside event listener // and then try with the alert as you did.
if does not work then try by e.id instead of e.target.id inside alert as below:
alert(this.id);
Thanks.
I'm wondering if it's possible for a script to enable/disable all input elements on the page with some sort of toggle button.
I googled it but didn't find anything too useful except for this:
http://www.codetoad.com/javascript/enable_disable_form_element.asp
but I'm not sure how to edit it for the toggle.
Something like this would work:
var inputs=document.getElementsByTagName('input');
for(i=0;i<inputs.length;i++){
inputs[i].disabled=true;
}
A working example:
$().ready(function() {
$('#clicker').click(function() {
$('input').each(function() {
if ($(this).attr('disabled')) {
$(this).removeAttr('disabled');
}
else {
$(this).attr({
'disabled': 'disabled'
});
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<input type='text'></input>
<input type='text'></input>
<input type='text'></input>
<div id='clicker' style='background-color:#FF0000; height:40px; width:100px;'></div>
Here is a function to toggle all inputs on the page:
function toggle_inputs() {
var inputs = document.getElementsByTagName('input');
for (var i = inputs.length, n = 0; n < i; n++) {
inputs[n].disabled = !inputs[n].disabled;
}
}
It works by using the logical NOT operator (the exclamation point), which returns the opposite of the operand. For example, !true will return false. So by using !inputs[n].disabled, it will return the opposite of what it's currently set to, thereby toggling it.
If you need code to bind the click event to the button:
document.getElementById('your_button_id').onclick = toggle_inputs;
You can also use addEventListener, but see the linked page for more information, including compatibility with Internet Explorer. The code I gave above should work across all browsers with no trouble.
for (var i = 0; i < document.getElementyByTagName('input').length; i++) {
document.getElementsByTagName('input')[i].disabled = 'disabled';
}
http://code.google.com/p/getelementsbyclassname/
^^Robert Nyman has a "get elements by class" script. Basically you'd just assign all those input elements to the same class, and then do something like:
//Collapse all the nodes
function collapseNodesByClass(theClass){
var nodes = getElementsByClassName(theClass);
for(i = 0; i < nodes.length; i++){
nodes[i].style.display='none';
}
}
This is a piece of code I'm actually currently using to collapse everything with a given class name (it uses the script I mentioned above). But in any case I think the key to your problem is being able to refer to multiple elements at once, which that script will help you with.
Also the link in your question didn't work for me :(.
and thanks for looking.
Currently I am implementing code from this example. In my aspx file, I have Label1 and Textbox1 defined. In my aspx.cs file, I am setting the Label1.Text property to a random string in the Page_Load method.
In the .js file I have included, I have:
var Label1, TextBox1;
Sys.Application.add_init(AppInit);
function AppInit(sender) {
Label1 = $get('Label1');
TextBox1 = $get('TextBox1');
$addHandler(Label1, "click", Label1_Click);
$addHandler(TextBox1, "blur", TextBox1_Blur);
$addHandler(TextBox1, "keydown", TextBox1_KeyDown);
}
Now, I want to add more labels (and corresponding textboxes), but I do not want the overhead of defining separate handlers for each of the additional events, i.e. I want to avoid this:
$addHandler(Label1, "click", Label1_Click);
$addHandler(TextBox1, "blur", TextBox1_Blur);
$addHandler(TextBox1, "keydown", TextBox1_KeyDown);
$addHandler(Label2, "click", Label2_Click);
$addHandler(TextBox2, "blur", TextBox2_Blur);
$addHandler(TextBox2, "keydown", TextBox2_KeyDown);
...
How can I pass a parameter to the handler that will identify the sender accurately, and have the handler use 'this' or something. Also of note, I want to be able to identify the index of the Label (1,2,3...) because I have to edit the corresponding textbox as well. FOr instance, the current implementation of Label1_Click looks like this:
function Label1_Click() {
TextBox1.value = Label1.innerHTML;
Label1.style.display = 'none';
TextBox1.style.display = '';
TextBox1.focus();
TextBox1.select();
}
Thanks, you guys.
Well, $addHandlers can help speed up the process of adding handlers... also, in JS you can attach miscellaneous data to objects by doing: Label1["somenewproperty"] = value; and so you can attach certain attributes and check in the event handlers... that does take up resources though, so be careful how much you do this...
On some level, how is JS supposed to know the objects you want to listen to and what order the objects are in, to reduce the amount of code? Maybe storing an array of textboxes and labels, and referring to those objects by index, but on some level, you can't get away from certain plumbing code.
HTH.
You can try creating a delegate. For example with your labels:
function AppInit(sender) {
$addHandler(Label1, "click", Function.createDelegate(this, LabelClick());
$addHandler(Label2, "click", Function.createDelegate(this, LabelClick());
}
function LabelClick(sender)
{
/..
}
I know this is an old question but yesterday I faced this very same problem and here is the solution I came of with.
I don't like it a lot but haven't found an easier way: I use a custom CssClass for every label I want to be linked with a textbox by this method (and the same for the textbox).
Then I iterate them and attach the corresponding handler depending on if it is a label or a button.
var labels;
var texts;
Sys.Application.add_init(AppInit);
function AppInit(sender) {
labels = document.getElementsByClassName('lblDynamic');
texts = document.getElementsByClassName('txtDynamic');
for (i = 0; i < labels.length; i++)
{
$addHandler(labels[i], "click", Label1_Click);
}
for (i = 0; i < texts.length; i++) {
$addHandler(texts[i], "blur", TextBox1_Blur);
$addHandler(texts[i], "keydown", TextBox1_KeyDown);
}
}
The next step is to access the generic control inside the method handler. This is quite easy with the this reference. Example:
function TextBox1_KeyDown(event) {
if (event.keyCode == 13) {
event.preventDefault();
this.blur();
}
}
But there is a problem here: How do I know that a certain label pairs with a certain textbox? I use a very similar id for both controls. ASP will add it's viewstate weird nomenclature after rendering the page so I need to use very dirty tricks to get rid of the extra text. Then I iterate the textbox controls and if one matches the label on the handled event then I can work with them like in the example you posted:
function Label1_Click()
{
var offset = this.id.indexOf('lbl') + 3;
for (j = 0; j < texts.length; j++)
{
if (texts[j].id.substring(offset) == this.id.substring(offset))
{
texts[j].value = this.innerHTML;
this.style.display = 'none';
texts[j].style.display = '';
texts[j].focus();
}
}
}
In this case my label and textbox are declared this way. Note the very similar nomenclature:
<asp:Label runat="server" CssClass="lblDynamic" ID="lblExerciseName">My Text</asp:Label>
<asp:TextBox runat="server" CssClass="txtDynamic" ID="txtExerciseName" Style="display: none;" />
Hope it helps :)
there are many ways, but this one works perfectly in any browser and you don't need a library.
I append an onclick handler to every input on this page and give it 2 parameters, that I get from a 2-dimensional array. I used a closure to make sure the handler still has access to the given parameters. I also made me a global object (p from page), so I don't clutter the global namespace with variables.
<!DOCTYPE html>
<html>
<head>
<script>
var p = {
onload: function() {
var btns = document.getElementsByTagName("input");
var parameters = [["btn1 p1", "btn1 p2"], ["btn2 p1", "btn2 p2"]];
for(var i = 0, ceiling = btns.length; i < ceiling; i++) {
btns[i].onclick = function(par1, par2) {
return function() {
p.btnOnclick(par1, par2);
};
}(parameters[i][0], parameters[i][1]);
}
},
btnOnclick: function(par1, par2) {
alert("par1: " + par1 + " | par2: " + par2);
}
};
</script>
</head>
<body onload="p.onload()">
<input type="button" value="button1"/>
<input type="button" value="button2"/>
</body>
</html>