Is it possible to make <a href=""> to do 2 things? One to javascript: and the other to jump to a section in a documents using <a id=""> and a # mark.
In short I am looking for something like this:
Link
Yes, use onclick property:
Link
Of course, you can do this:
Link
I'd suggest using unobtrusive JavaScript, moving the event-handling away from your HTML:
function doSomething(){
console.log("You clicked on the " + this.tagName.toLowerCase() + " element.");
}
var link = document.getElementById('aElementID');
link.onclick = doSomething;
JS Fiddle demo.
This does, though, require an id on the a element:
Go to the paragraph
You could, though, use a class-name instead, though this involves binding the functionality to multiple elements, with a for loop (or similar); given the a elements having the form:
Go to the paragraph
Go to the other paragraph
The JavaScript would become:
function doSomething(){
console.log("You clicked on the " + this.tagName.toLowerCase() + " element.");
}
var links = document.getElementsByClassName('linkClassName');
for (var i = 0, len = links.length; i < len; i++){
links[i].onclick = doSomething;
}
JS Fiddle demo.
You could even bind the event-handling to an ancestor element, and basing the response on which element received the event; this would allow HTML of the form:
<div id="arbitraryAncestorElement">
Go to One
<ul>
<li>Go to Two</li>
<li>Go to Three</li>
</ul>
</div>
With the JavaScript:
function doSomething(event){
if (event.target.tagName.toLowerCase() === 'a') {
console.log("You clicked on an 'a' element.");
}
}
var ancestor = document.getElementById('arbitraryAncestorElement');
ancestor.onclick = doSomething;
JS Fiddle demo.
Related
I have to loop through <article> tag in the Html file and add its classname when clicked and then remove the class name in all other <article> tags
for eg:
<article onclick="javascript:selectthis(this)">
1
</article>
<article onclick="javascript:selectthis(this)">
11
</article>
<article onclick="javascript:selectthis(this)">
111
</article>
<article onclick="javascript:selectthis(this)">
1111
</article>
<article onclick="javascript:selectthis(this)">
11111
</article>
<script>
function selectthis(THIS) {
THIS.className = "countrySelected";
}
</script>
is there a way to loop through the tags and remove the classnames except for the recent one that is clicked? What is the best possible way to do ? Should I really have to add a onclick event attached to every <article> tag? because there could be many <article> tag in the html file. I really donot want to add this onclick event to every article tag.
any help would be appreciated.
You didn't tag jQuery , but I'd recommend using that in this particular case, where event bubling and filtering plays nice. Instead of register multiple click-handlers (as you point out) you can register one soley, and have that one in common for all elements. jQuery is good at filtering out events to a specific selector as well. I'd give it a shot.
Here's an example of how to solve your issue using jQuery:
// Register an event-handler on document, that listens for a 'click' event.
// Only pick up the event from the selector 'article' though, which corresponds
// to only article elements on the page.
$(document).on('click', 'article', function(){
this.className = "countrySelected"; // this in this context, is the actual DOM-element
});
Then for your issue of removing the className for all articles, not having the class countrySelected. This also is nice with jQuery as such:
// Find all article-elements, that DON'T have the class countrySelected
// Then remove _all_ the classes it has
// To remove a specific class, use .removeClass('classToRemove')
$('article').not('.countrySelected').removeClass();
So in the end, you can combine the two and make this:
$(document).on('click', 'article', function(){
$('article').removeClass(); // Remove class from all other first
this.className = "countrySelected"; // this in this context, is the actual DOM-element
});
Assuming you do place an onclick on each article .. inside of your function, you could do this:
function selectthis(THIS) {
//remove the css classes from all articles
var articles=document.getElementsByTagName('article');
for(var a=0;a<articles.length;a++){
articles[a].setAttribute('class','');
}
//add class back on for this article
THIS.className = "countrySelected";
}
Add this jquery:
$("article").click(function() {
$("article").toggleClass("countrySelected");
});
Example code snippet:
$("article").click(function() {
$(".countrySelected").removeClass("countrySelected");
$(this).addClass("countrySelected");
});
article.countrySelected {
background-color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<article>This is article 1</article>
<article>This is article 2</article>
<article>This is article 3</article>
<article>This is article 4</article>
<article>This is article 5</article>
<article>This is article 6</article>
Since you didn't tag this jquery, here is a pure javascript solution:
window.onload = function() {
// This is a list of all the articles on the page
var articles = document.querySelectorAll("article");
for (var i = 0; i < articles.length; ++i) {
// Loop through each article
var article = articles[i];
// Add an event listener for each one
article.addEventListener("click", function() {
// Get the previously selected one and deselect it
var prevSelected = document.querySelector(".countrySelected");
if (prevSelected != null) prevSelected.classList.remove("countrySelected");
this.classList.add("countrySelected"); // or for older browsers: this.className = "countrySelected";
}, false);
}
}
window.onload = function() {
var articles = document.querySelectorAll("article");
for (var i = 0; i < articles.length; ++i) {
var article = articles[i];
article.addEventListener("click", function() {
var prevSelected = document.querySelector(".countrySelected");
if (prevSelected != null) prevSelected.classList.remove("countrySelected");
this.classList.add("countrySelected"); // or for older browsers: this.className = "countrySelected";
}, false);
}
}
.countrySelected {
background-color: orange;
}
<article>Article 1</article>
<article>Article 2</article>
<article>Article 3</article>
<article>Article 4</article>
<article>Article 5</article>
I'll treat it this way without using jQuery. The reason why is this way in the future it is far more easier to understand why certain stuff happens. And sometimes basic JS is far more fitting for using a small adjustment instead of a bloated library.
The best way is to start, is at the moment nothing still happened and the page just loaded. Instead of using the javascript inline with an onclick. First assign an event-listener.
Page Loaded
With Element.getElementsByTagName() you can get all the needed elements and go for a loop. documentation;
So you get
var articleTags = document.getElementsByTagName('ARTICLE');
In this case we can use a simple loop
var articleDOM = null;
for(var i = 0; i < articlesTags.length; i++){
articleDOM = articlesTags[i];
articleDOM.addEventListener("click", addClassToArticleFunction);
)
Each article now has an event binded with a function. Let's define that function.
Add Class Function
I'll use 'addClassToArticleFunction', but you can of course make it even more generic in name. Could be you want also use this function for other tags or DOM-elements.
function addClassToArticleFunction(){
this.className = "countrySelected";
}
Each time this will be called the class will be defined. Only you off course get a problem by all of them will get that classname.
So lets just call a function that will do all the deleting.
function addClassToArticleFunction(){
deleteClassNameFromArticles();
this.className = "countrySelected";
}
function deleteClassNameFromArticles(){
//deletion here
}
Since we know all the articles already, and know how to calls the classname it is an easy copy paste
for(i = 0; i < articleTags.length; i++){
articleDOM = articleTags[i];
articleDOM.className = "";
}
At this point it is done.
Recap
load window
assign event listeners to articles
when clicked on article a function will be called
this function will delete all classnames from articles
this function will assign on the clicked article a classname
JS fiddle to see it work
I have a list of texts and I want to change their innerHTML. how can I do that by javascript if I have thousands of li tag (whose data come from database)?
<div>
<ul>
<li>a</li>
<li>as</li>
<li>asd</li>
<li>asds</li>
<li>asdsa</li>
<li>asdsad</li>
<li>asdsadz</li>
<li>asdsadzc</li>
....
.....
</ul>
</div>
-Thanks.
Update
JS code being used:
function a(){
var parent = document.getElementById("z");
var i = 0;
for(i = 0; i <= parent.children.length; i++){
if(parent.children[i].tagName == "LI"){
if(i%2!=0){
parent.children[i].innerHTML="ok";
}
}
}
}
document.onload=a(); // this didn't work. so I called the function in body tag instead of that.
<body onload="a();">
Have you tried using getElementsByTagName ? Sonds like it would help you find the elements you're trying to work with.
Edit
If you can give an Id to the UL element that holds the li's you're trying to process, you could do something like this:
var parent = document.getElementById("yourID");
var i = 0;
for(i = 0; i < parent.children.length; i++){
if(parent.children[i].tagName == "LI") {
//do what you want...
}
}
EDit 2
You have to change the last line on your script:
document.onload=a();
With this one: window.onload=a;
That'll get your function to execute on the onLoad event. Note that there might be some crossbrowser incompatibility, I would suggest researching a bit on how to execute functions on the onload event on a crossbrowser manner, or just adding this to your body tag:
<body onload="a();">
Given the - not so far fetched - precondition you wish to use jQuery, you can select them and iterate over them with "each".
$("li").each(
function() { $(this).html("changed content"); }
);
If you are not using jQuery, using a js-library that helps you out with the quircky dom is probably not a bad idea...
The general idea
Select nodes
Iterate and change html
is always the same.
In this scenario, I have a series of list items each of which has a corresponding content area. When clicking a list item, a corresponding content area is manipulated (i.e., if the first list item is clicked, then the first content section would be manipulated).
<ul>
<li>List item</li>
<li>List item</li>
<li>List item</li>
</ul>
<div>
<section>Content section</section>
<section>Content section</section>
<section>Content section</section>
</div>
My old-school way of doing this was giving each list item and section an id, such as "li1", "li2", etc. and "section1", "section2", etc. I would then parse the integer off the id of the element that was clicked and manipulate the corresponding section.
Is there a way to determine this without needing extra id attributes? E.g., if I click the 3rd list item and know that is the 3rd, I can use document.querySelector('div:nth-child(3)') to manipulate the third content section. My question is how to know it was the 3rd element in a series that was clicked to begin with.
My first-thought solution was something like this:
var target = e.target;
var parent = e.target.parentNode;
for (var i in parent.childNodes) {
if (parent.childNodes[i].nodeType == 1 && parent.childNodes[i] == target) {
// found it... i+1
}
}
This seems like a rather expensive operation compared to just using IDs, especially if there were many more list items and content sections. I'm hoping there is some node attribute that will give me the correct DOM position that I haven't yet found.
Modern browser-only solutions welcomed.
So i have no ide what you are doing here but there must be a more data oriented approach to this.
Like both the li and the section is referring to the same Product or Person or something so you can find it by that reference.
otherwise you can use the previousElementSibling method to count your location like this
var position = function(el) {
var count = 1;
for(var cur = el.previousElementSibling;
cur !== null; cur = cur.previousElementSibling) {
count++;
}
return count;
};
gl
I’d use something like:
var target = e.target,
i = 0;
while(target = target.previousSibling) {
i += target.nodeType == 1;
}
alert('you clicked on '+i);
Fiddle: http://jsfiddle.net/K5Qg9/1/
You can also try using a data lib or assign stuff to the element expano onload:
var elems = document.getElementsByTagName('li'),
i=0;
for(; elems[i]; i++) {
elems[i].rel = i;
}
Then just fetch e.target.rel onclick. Fiddle: http://jsfiddle.net/UnrCt/
If you can use jQuery: $(elem).index()
Update 2016
Well I've run into this issue again nearly 5 years later only this time I used a much simpler solution using a built-in Array method:
var index = Array.prototype.indexOf.call(event.target.parent.children, event.target);
I have the following HTML page:
<html>
<head>
<script type="text/javascript" src="JavaScript/Menu.js"></script>
</head>
<body>
<ul>
<li><a onclick="GetIndex(this)">One</a></li>
<li><a onclick="GetIndex(this)">Two</a></li>
<li><a onclick="GetIndex(this)">Three</a></li>
<li><a onclick="GetIndex(this)">Four</a></li>
</ul>
</body>
</html>
And the Menu.js javascript:
function GetIndex(sender)
{
var aElements = sender.parentNode.parentNode.getElementsByTagName("a");
var aElementsLength = aElements.length;
var index;
for (var i = 0; i < aElementsLength; i++)
{
if (aElements[i] == sender) //this condition is never true
{
index = i;
return index;
}
}
}
Why is the commented condition never met? How do I compare if the two HTML elements are equal in Javascript? Thanks for all the help.
"Your code is correct"
Old Post, but here is a quick function to do this:
function nodeIndex(el) {
var i=0;
while(el.previousElementSibling ) {
el=el.previousElementSibling;
i++;
}
return i;
}
This should work with an element reference as the parameter. It basically just returns the number of previous siblings.
try to use:
if (aElements[i] === sender)
instead of
if (aElements[i] == sender)
Are you sure GetIndex function gets executed on click event on anchor tag?
Try by giving href attribute to anchor tag. You can write either
One
or
One
here is the working example http://jsfiddle.net/QfRSb/
Jquery can help using prevAll()
$(document).on("click","li",function(){
var index=$(this).prevAll();
alert(index);
});
The modern way to find index of element
[...el.parentNode.children].indexOf(el)
i have a list of items containig names.
then i have a eventlistener, which ckecks for keypress event.
if the user types i.g. an A all names starting with an A should be viewed with the A bold. so all starting As should be bold.
what is the best way using jquery to highlite only a part of a string?
thanks for your help
Here's a function you can call during your keypress event to highlight a search string:
function Highlight(search)
{
$('ul > li').each(function() {
if (this.innerHTML.indexOf(search) > -1)
{
var text = $(this).text();
text = text.replace(search, "<span id='highlight' style='font-weight: bold'>" + search + "</span>");
$(this).html(text);
}
else
{
this.innerHTML = $(this).text();
}
});
}
Test html:
<ul id='list'>
<li>Bob Jones</li>
<li>Red Smith</li>
<li>Chris Edwards</li>
</ul>
It's not quite as elegant as Pointy's answer, but it handles the matching strings requirement.
There are jQuery plugins to do text highlighting, but I've not seen one that highlights parts of words.
One possible solution would be to put all your names on the page with the first letter surrounded by a <span> tag, with a class:
<span class='A FL'>A</span>ugustine
<span class='C FL'>C</span>arlos
You can then use jQuery to fiddle with those by class name.
$('whatever').keypress(function(ev) {
var k = e.which.toUpperCase();
$('#textContainer span.FL').css('font-weight', 'normal');
$('#textContainer span.' + k).css('font-weight', 'bold');
});
Note that bold characters are fatter than normal characters, so this is going to have a "wiggly" effect that your users might not like. You might consider changing color instead.
thanks for your help...
i figured it out and the detailed resolution comes here:
var communities = $('#mylist').find('.name');
var temp_exp = new RegExp("^("+match_string+")","i");
communities.each(function(i){
var current = $(this);
var name = current.text();
name = name.replace(temp_exp, '<b>$1</b>');
current.html(name);
});
while all items have to have the class "name".