Getting value of <a> link? - javascript

I am having troubles pulling the value from a link. It's a CSS formatted page and I would really prefer to use a <a> than a <button>.
<button value="1" onclick="showDetails(this.value)">This works</button>
<a value="2" onclick="showDetails(this.value)">This doesn't work</a>
};
xmlhttp.open("GET","getdetails.php?q="+str,true);
xmlhttp.send();
How can I get the value of <a> when it is clicked and not having it go somewhere?

Only a select few elements, like <input>s, <textarea>s, and <button>s can have value properties:
console.log(
document.querySelector('a').value
);
<a value="val">a</a>
If you have to use the value attribute, use the getAttribute method instead of dot notation:
console.log(
document.querySelector('a').getAttribute('value')
);
<a value="val">a</a>
Another option would be to use data attributes instead, which would be more appropriate than value="s when working with an <a>:
console.log(
document.querySelector('a').dataset.value
);
<a data-value="val">a</a>
(also make sure to attach your event handlers properly using Javascript if at all possible - inline handlers are generally considered to be pretty poor practice - try using addEventListener)
To use addEventListener, select your a, and call addEventListener on it. For example, if your <a> has an id of details:
const details = document.querySelector('#details');
details.addEventListener('click', () => {
showDetails(details.dataset.value);
});
function showDetails(str) {
console.log('showing details for ' + str);
}
<a id="details" data-value="thevalue">click for details</a>

You can write a Javascript function to get the value from the link as follows:
function showDetails(a){
let value = a.getAttribute("value");
// view value
console.log(value)
}
<!--<button value="1" onclick="showDetails(this)">Button link</button>-->
<a value="2" onclick="showDetails(this)">Anchor link</a>

Your issues has 2 parts:
#1: Use of correct attribute
You should not use the value attribute in <a> tag, as it's not a valid attribute for HTML standard; try to use data-val instead. Attributes starting with data- allow us to store extra information on standard, semantic HTML elements without other hacks.
Example:
<a data-val="2" onclick="showDetails(this)">Test</a>
For the JS function, it can be written as:
function showDetails(obj) {
console.log(obj.dataset.val); // 2
}
References: https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes
#2: Prevent the <a> gets redirected
The initial choice of using <a> is incorrect, as <a> is designed to: (1) redirect to other page via hyperlink specified; or (2) go to certain section in the page using anchor name.
However, you can still stop the redirection using JavaScript (though not suggested). Edit your onclick function as below:
<a data-val="2" onclick="showDetails(this); return false;">Test</a>
Note the return false is added.
p.s. for better coding standard, you should separate JS from HTML structure.

Anchor tag does not have a value attribute, you can read about it in mdn. If you need to assign a value to an anchor tag you can use custom data attribute data-*. In order to get values from data-* in your javascript function can try something like this
const anchor = document.querySelector('a');
const str = anchor.data.value;
And then use it in your ajax logic.
const url = 'getdetails.php';
const params = `q=${str}`;
const http = new XMLHttpRequest();
http.open('GET', `${url}?${params}`, true);
// ... other logic

Related

passing values to a function does not work when inside for loop

I'm mapping currencies from a json file and i render the mapped currencies to a component. I have a .php file like this
<div class="currency-switch-container" id="currency_container">
<span style="font-size:12px;font-weight:bold">All currencies</span>
<div id="currency-map" style="margin-top:15px"></div>
</div>
I refer the div in the above component in my js file as follows
let currencyMap = jQuery("#currency-map");
And when my jQuery document is ready i'm doing the following
jQuery(document).ready(function($) {
$.getJSON('wp-content/themes/mundana/currency/currency.json', function(data) {
for(let c in data){
currencyMap.append(`<span onclick="onCurrencyClick(${data[c].abbreviation})"
class="currency-item">
<span>
${data[c].symbol}
</span>
<span>
${data[c].currency}
</span>
</span>`)
}
});
}
and my function is like this
function onCurrencyClick(val){
console.log("val",val);
setCookie("booking_currency", val, 14);
}
Here the function does not work. But if i do not pass anything to the function it seems to work as i can see the log in the terminal.
Hi your expression ${data[c].abbreviation} will put the value into function string without string quotes i.e. the resultant would be onCurrencyClick(abbreviation) while it should be onCurrencyClick('abbreviation').
please use onclick="onCurrencyClick('${data[c].abbreviation}')" instead.
Instead of using the inline onclick, use event delegation. This means that you have a single event listener that handles all the events from the children and grandchildren. The modification is a very minor one seeing the example here below.
A reason for doing this is that you keep your JavaScript inside your JS file. Like now, you encounter a JS error and have to look for it in your HTML. That can get very confusing. Also however inline onclick listeners are valid, they are outdated and should be avoided unless there is absolutely no other way. Compare it with using !important in CSS, same goes for that.
function onCurrencyClick(event){
var val = $(this).val();
setCookie("booking_currency", val, 14);
}
currencyMap.on('click', '.currency-item', onCurrencyClick);
This example takes the val that you try to insert from the value attribute from the clicked .current-item. <span> elements don't have such an attribute, but a <button> does and is a much more suitable element for it expects to be interacted with. It is generally a good practice to use clickable elements for purposes such as clicking.
In the example below you see the button being used and the abbreviation value being output in the value attribute of the <button> element and can be read from the onCurrencyClick function.
jQuery(document).ready(function($) {
$.getJSON('wp-content/themes/mundana/currency/currency.json', function(data) {
for(let c in data){
currencyMap.append(`
<button value="${data[c].abbreviation}" class="currency-item">
<span>
${data[c].symbol}
</span>
<span>
${data[c].currency}
</span>
</button>
`)
}
});
onclick will not work for a dynamically added div tag
Yo should follow jQuery on event
Refer: jQuery on
Stackoverflow Refer: Dynamic HTML Elements

How to move onclick code to one place using something like class. Repeated code at various html tags

onclick="triggersTracking($(this).attr('a'),$(this).attr('b'),$(this).attr('c'),Enum.BtnSellerView)"
I have this line at various HTML tags/buttons. I want to move this code to one place for better maintainability. The problem is with third/last attribute i am passing since its Enum, it has different values being passed from different tag elements.
How can i move it to one common place where it would get invoke. For example I could have made a class if i have had just these (this).attr since its common for every tag.
You can do like
Give all the elements a common class name
Then add a data attribute, "data-enum" to each tag with corresponding value.
Then you can write the code like this,
$(".className").click(function () {
var a = $(this).attr('a');
var b = $(this).attr('b');
var c = $(this).attr('c');
var enum = $(this).data('enum');
});
You can use jquery to get this:
$("body").on("click", "someClass", function() {
//code here
});
you don't need to write $(this).attr('a'),$(this).attr('b'),$(this).attr('c')
again and agin on every onclick just paas this object and get them all in function like :
onclick="triggersTracking(this,Enum.BtnSellerView)"
function triggersTracking(obj,enumVal){
// get these values here by obj (no repetitive code needed in every onclick )
$(obj).attr('a')
$(obj).attr('c')
$(obj).attr('b')
}
Do some thing like this
.click()
.on()
.data()
if you use attributes like data-enum , data-e....
so use $(this).data() it will return all attributes in JSON which is starting
from data-
$('.click').click(function(e) {
console.log($(this).data())
$('body').append($(this).attr('a'))
})
// if you have dynamic html tag then go for .on
$('body').on('click','.click',function(){
//callback
console.log($(this).data())
$('body').append($(this).attr('a'))
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="click" a="i am a attr of p" b="i am b" data-a="i am data a">i am p</p>
<h2 class="click" a="i am a attr of h2">i am h2</h2>

why does selenium change the element's href?

I'm using selenium to inspect a web element and then get its "href"
driver.findElement(getSelectorForButton(name)).getAttribute("href")
why the result I get is ...current url...# instead of jut # as I see in the browser console?
<a class="action-btn big-button btn-phone take-button v3" data-model="{"analytics_url":"/coupons/use?action_source=popup&cookie=..uot;],"redirect_url":null}" href="#">
<div class="btn-text">
<span>Call Now</span>
</div>
</a>
I may be wrong but I think it is because
driver.findElement(getSelectorForButton(name));
does not return the DOM element, but a selenium wrapper which getAttribute property (method) invoked with the ('href') argument does not return the href attribute content, but the href property content.
The href property is 'filled' by the browser automatically with the matching prefix for every relative/absolute path in href.
Examples below:
HTML:
Test
Test
Test
JavaScript:
var a = document.getElementById('link1');
console.log(a.href); // '...Whatever_your_url_is...#'
console.log(a.getAttribute('href')); // '#'
var b = document.getElementById('link2');
console.log(b.href); // '...Whatever_your_url_is.../uri'
console.log(b.getAttribute('href')); // '/uri'
var c = document.getElementById('link3');
console.log(c.href); // '...Whatever_your_domain_and_port_is.../uri'
console.log(c.getAttribute('href')); // './uri'
DEMO here: http://jsfiddle.net/j8t470uk/
The reason is (as per docs)
this method will return the value of the given attribute, unless that attribute is not present, in which case the value of the property with the same name is returned (for example for the "value" property of a textarea element). If neither value is set, null is returned.
getAttribute first of all looks for the attribute in the DOM, where if you can see href contains the complete web url.
For example: in the answers you are getting on this question if you inspect the active tab you could see href="/questions/28339297/why-does-selenium-change-the-elements-href?answertab=active#tab-top", but if you have a look at the DOM there you can find this href is appended to http://stackoerflow.com.

How to submit a form by clicking a link javascript

currently I'm trying to make it so that when the user clicks a link it submits the corresponding form via javascript. I used document.getElementById("id").submit() as a basis on how to send the form so my code should act similar to it in my understanding.
Here's the code:
function run(clickedLink){
clickedLink.id.submit(); //I did it like this since document.getElementById just gets the form id and since link and form have similar id's I thought it would send
}
<form id = 'formId'>
<a href = '#' id = 'formId' onclick = run(this)>Link</a>
</form>
I tried going with name = 'formId' too but it still doesn't run as I wanted it too.
Note: doing this since this code iterates dynamically and the id gets updated i.e. formID1, formID2...
Better ways to implement this are welcome too
Modify your function as follows
function run(clickedLink){
clickedLink.parentNode.submit(); // parentNode refers to the form element
}
You cannot use same id on the same page for more than one element. This is against HTML and DOM specifications https://softwareengineering.stackexchange.com/questions/127178/two-html-elements-with-same-id-attribute-how-bad-is-it-really .
You can change it to class if you want to reuse or you can change the id itself of other element. Also links are not recommended to submit the form. Their job is to navigate
Try this:
<a href="#" onclick="document.forms[0].v.value='Link1';
document.forms[0].submit();">Link 1</a>
One Basic thing:
-ID's are used to Uniquely Describe The Element in DOM Hierarchy. Please Don't Repeat it. (it is really bad)
Now to the answer:
function run(x){
var y=findParentForm(x); /* if Id's aren't Unique */
// If iD's are Unique :- var y=document.getElementById("formId");
y.submit();
}
function findParentForm(elem){
/*
This function will find exact parent form
even if link or elem is inside <div> or other complex DOM structure
This will Only return the parent <form> of that elemnt
*/
var parent = elem.parentNode;
if(parent && parent.tagName != 'FORM'){
parent = findParentForm(parent);
}
return parent;
}
<form id='formId' action="Server Side Script" method="GET/POST">
Link <!-- change id of link -->
</form>

How to relate data (id's) to links for JavaScript?

I'm trying to write a fairly complex dynamic web page, using JQuery AJAX, and I am struggling with how to relate my links (<a ...>) with the the data their tied to, such as action names, and data element ids. I have pondered several different schemes, but I'm not sure I like any of them.
Building it into onclick, which means I have to configure it in the link generation.
<a onlick="func('abc', 123)">...</a>
Inserting it into the id of the link, which means parsing it out in JavaScript.
<a id="link_abc_123">...</a>
Putting the link in a div with hidden input elements...
<div>
<a>...</a>
<input type="hidden" name="action" value="abc"/>
<input type="hidden" name="id" value="123"/>
</div>
Is there a best practice or a commonly accepted way of structuring this data?
Best practice should always be, to strictly separate Code.
That means, you shouldn't include any Javascript into your backend-source code. So personally I'm a big fan of either putting the necesarry data into the elements (your last example) when using a template-engine, or sending just the necesarry data on a separate request (JSON for instance) to the client.
Using jQuery, it's a very convinient way to create data- attributes, where you can store any information, while jQuery will translate the values from those attributes into the data expandos. For instance:
<div id="test" data-foo='bar' data-test='{"cool": "stuff"}'>Just a div</div>
When selecting that element with jQuery var $test = $('#test'), you can access:
$test.data('foo') // === 'bar'
$test.data('test').cool // === 'stuff'
Read more: http://api.jquery.com/data/
With HTML5, you have the luxury of using data-* attributes - for example:
...
Which jQuery actually has support for - calls to $('a').data() will include the data-* values in it.
For simple things, I use a function like:
function getIdStr(i, sDelim) {
if (typeof i != "string") {
var i = $(i).attr("id");
}
var arr = i.split(sDelim || /_|-/);
if (arr.length > 1) {
return arr[arr.length-1];
} else {
return "";
}
}
// usage
$(function(){
$(".data .action").click(function(){
doSomething(getIdStr(this)); // -> 123
});
});
For something heavier, you might try to attach a data to the topmost container.
i would go with the new Custom Data Attributes HTML5 brings along.
Just use this <a data-action="foo" data-id="bar">...</a>
Also, jQuery already has support to get these data-attributes
You can add a custom property to the input and access it in javascript.
eg
<input type="hidden" name="action" value="abc" yourproperty='<%= Eval("YourDataID") %>'/>

Categories

Resources