I am using jQuery and semantic UI for a project, and I got stuck with what the second this is referring to. what would the second this be referring to? I am new with jQuery by the way. I want the second this to refer to #sideBar a but every time I try to add classes it doesn't work,
I want to remove all classes, then add item to all of them, then get the text content of the anchor tag and set that anchor tag's attribute with a class with the textContent as it's name.
$('#sideBar a').on('click', function(){
$('#sideBar a').removeClass().addClass("item");
var addC = ($(this).text());
$(this).addClass(addC);
});
Could anyone tell me how to do this, I have some knowledge of apply call and bind in javascript by the way
this inside and event listener with a non-arrow function will be your event target:
$('#sideBar a').on('click', function (event) {
// next line removes all classes from all anchor elements that are children of #sideBar then adds the class item to each of them
$('#sideBar a').removeClass().addClass("item");
// sets addC to whatever the event target's text is
var addC = ($(this).text());
// adds the text stored in addC as a class to the event target
$(this).addClass(addC);
console.log(this === event.target); // logs true
});
edit: I just realized I didn't answer your question:
$(this).parents('#sideBar').first().addClass(addC); instead of $(this).addClass(addC); should do the trick.
Related
I am trying to target a class called 'horizontal-video' in a div within an AEM component and if the author has clicked a checkbox that has an ID of 'coral-id-540' I want to add a second class called 'flipped' to the div. Here is the code I wrote that isn't working. Could someone help me figure out why it's not working? The console does not show errors.
var x = document.getElementsByClassName("horizontal-video");
$('#coral-id-540').change(function(){
if($(this).is(":checked")) {
$(this).addClass("flipped");
} else {
$(this).removeClass("flipped");
}
});
It's quite possible you're not waiting for the DOM to completely load, (or at least have this bit of code below the element in question on the page during page load)
Is your code wrapped in $(document).ready(function(){ //your code });?
Also, be aware that any element that is dynamically added to the page by JavaScript/jQuery after page load will not have a listener attached using the method you're using.
To allow dynamically added elements to be included in your listener, you should target an ancestor node and add the listener to that node. In plain English: attach the listener to a "higher up" element. The safest (although slowest) node being document itself, but it's better to target something closer:
$(document).ready(function () {
var $horizontalVideo = $(".horizontal-video"); //You're using jQuery - why not use it here? Also, I always name jQuery objects with a `$` in front as a shorthand to know it's wrapped in a jQuery object. Plus, a more descriptive name will help you immensely.
//replace parent-of-coral with the ID of a parent element that you know exists on DOM ready:
$("#parent-of-coral").on("change", "#coral-id-540", function (e) { //get used to using "e" as the event variable for preventing default / stopping propagation / etc
$this = $(this); //cache $(this) reference rather than creating another jQuery object each time you use it
if ($this.is(":checked")) {
$this.addClass("flipped");
} else {
$this.removeClass("flipped");
}
});
});
I'm trying to disable a li click event after it has clicked the first time. Essentially to stop the array data being doubled. The click is working fine for each time. My current method doesn't appear to be working. I also need to disable the other li's from being clicked once the first one has :)
Thanks
JS code is:
$('#eventType ul li').click(function(e) {
e.preventDefault();
var value = $(this).attr('value');
answers.push(value);
// Below isn't working
$(this).click(function() {
return false;
});
console.log(answers);
});
you need to use one:
$('#eventType ul li').one('click',function(){
//your code here
});
this event will be fired only once
UPDATE
you can do that using $.off()
$('#eventType ul li').one('click',function(){
//your code here
$('#eventType ul li').off('click');
});
jQuery is just JavaScript so you can easily add behaviors that you want
// basic jQuery plugin boilerplate
$.fn.once = function once(eventType, f) {
// this = the selected elements
return this.each(idx, elem) {
// create reference to jQuery-wrapped elem
var $elem = $(elem);
// add event listener for eventType
$elem.on(eventType, function(event) {
// call the event handler
return f(event);
// remove the event handler
$elem.off(eventType, f);
});
});
};
Usage would look like this
$('#eventType ul li').once('click', function(event) {
console.log("you will only see this once");
});
However, this is obviously a common need so it exists in jQuery already. It's called $.one. As APIs grow, you may not know about the existence of such procedures. This answer exists to show you that you can use your brain to program the things that you want or that might be missing from a particular library. This lessens your dependence on the creator's of the lib to introduce the functionality you need.
EDIT
In a comment, you ask if the event handler can be disabled for all other LI elements after the first LI is clicked. The trouble here is that jQuery uses implicit iteration, which means that when you call $('li').on('click', ...), jQuery will bind an onclick event handler for each LI.
A better solution to this problem would be to use jQuery's event delegation
// only fire event handler for the first LI clicked
$('ul').one('click', 'li', function(event) {
console.log($(this).text());
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
This will delegate the event listener to the children LI, but once one of the LI is clicked, the event handler will be removed (because we delegated using the $.one procedure).
Try clicking one LI, you will see a message in the console. When you click the second LI, nothing will happen because the event handler was removed.
var used = false;
$('#eventType ul li').click(function(e) {
if (used == false) {
used = true;
e.preventDefault();
var value = $(this).attr('value');
answers.push(value);
console.log(answers);
}
});
the way you did it was just adding another on click handler, not removing or overriding the old ond.
You can use CSS classes; add the class 'disabled' to elements you don't need, and avoid adding elements that have the classe 'disabled'.
https://plnkr.co/edit/6aloNPETHGxfiP5oYZ9f?p=preview
$('ul li').click(function(e) {
if(!$(this).hasClass('disabled')) {
var value = $(this).text();
answers.push(value);
$('li').addClass('disabled');
}
console.log(answers);
});
I have a click function which is given below
$('.page-nav li').click(function(event){
console.log("clickedTab-page-nav-first-before set ="+Session.get('clickedTab'));
Session.set('clickedTab',event.target.id);
//var sel = event.prevUntil("[class*=active]").andSelf();
var sel = $(this).prevUntil("[class*=active]").andSelf(); //find all previous li
//of li which have
//class=active
sel = sel.add(sel.eq(0).prev()); // include the that li also(Now all li elements).
sel.removeClass('active'); //Remove the active.
//sel = event.nextUntil("[class*=active]").andSelf(); //Also for top to bottom
//(Viceversa)
sel = $(this).nextUntil("[class*=active]").andSelf();
sel = sel.add(sel.eq(-1).next());
sel.removeClass('active');
//event.addClass('active');
$(this).addClass('active'); //Now add class active for the clicked li
var rightcontent="";
console.log("clickedTab-page-nav-second-after set = "+Session.get('clickedTab'));
switch($(this).attr('id')){
case 'rfq':
.......
.....
}
});
Then next is I want to call this click function from another place
$(document).ready(function() {
console.log("clickedTab-page load = "+Session.get('clickedTab'));
if(Session.get('clickedTab')!=null||Session.get('clickedTab')!= undefined){
alert("Got It");
//$('.page-nav li').click(event);
$('.page-nav li').click(); //this is not working
}
});
Now the problem is page click function in if condition is not working. However I got the alert. Any help is highly appreciated. Thanks in advance...
you are not really using the event parameter in your function and you state you wish to call it outside of an event chain so you could change it to be a regular function
var setupClicktab = function(id){
console.log("clickedTab-page-nav-first-before set ="+Session.get('clickedTab'));
Session.set('clickedTab',id);
...
}
the you'd use it like:
$('.page-nav li').click(function(event){return setupClicktab(event.target.id);});
and in document ready
setupClicktab.Call($('.page-nav li'),Session.get('clickedTab'));
The latter call class it in the context of the selection (that is this inside the function will refer to the selection(1). It also passes the value stored in the session variable in as the id.
a side note. Your test
if(Session.get('clickedTab')!=null||Session.get('clickedTab')!= undefined)
could simply be
if(Session.get('clickedTab'))
Unless you might store either an empty string, zero or the boolean value false in that variable. But seeing how it's used that's unlikely since they are all invalid values for the id attribute
(1)This is slightly different than in the click event where it refers to the DOM element)
You need to put $('.page-nav li').click(function(event){ inside document.ready and before your $('.page-nav li').click();. Because if you call .click when the DOM is not ready, there are chances that there is no event handler attached
If you don't put $('.page-nav li').click(function(event){ inside document.ready OR you're dealing with dynamically created elements. You need delegated event $(document).on("click",".page-nav li",function(event){
From $.on
I want to obtain the exact details for the item on a web page that has been clicked on, using jquery.
That item can be a form item (like a checkbox, text box, text area etc) or section of text (in a paragraph or div or other) or list or image ...
What I figured out is the following--
$(function(){
$('*')
.bind('click', function(event) {
//now obtain details of item that has been clicked on...
});
});
Now, I want the exact details- viz the div id/form id/paragraph #, ie all details for that particular item. How do i get this data? I understand that this data is available in the DOM but I just dont know how to get it in this particular case...
Probably the best way to do to use the target property of the event. By default, this returns a non-jQuery object, which isn't particularly useful, however wrapping it in $() solves this issue:
$(function() {
$(document).bind('click', function(event) {
var element = $(event.target);
alert(element.height()); // Get height
alert(element.attr('id')); // Get ID attribute
// ...
});
});
If you want to fix your current method, inside your click() handler, you can access the properties of that element using .attr(), and friends:
$(function() {
$('*').bind('click', function(event) {
alert($(this).height()); // Get height
alert($(this).attr('id')); // Get ID attribute
// ...
});
});
$(this) in the scope of the function references the element that was clicked. There is a list of functions that will return attributes here and here in the jQuery docs. $.attr('id') will return the element's ID, among other things, and $.data() will return data-* attributes.
To get attributes of parent elements, simply use $(this).parent(). For example, to get the ID of the form that contains the clicked element, use $(this).closest('form').attr('id');. Everything is relative to the clicked element ($(this)), so you can just use the DOM traversal functions.
However, using $('*').bind() is incredibly inefficient; you're binding an event handler to every element on the page, when really you should delegate events with .on() (jQuery 1.7+):
$(function() {
$('body').on('click', '*', function(event) {
alert($(this).height()); // Get height
alert($(this).attr('id')); // Get ID attribute
// ...
});
});
This approach only binds one event to <body> instead of an event to every element on the page.
Use the target of click event on page
$(document).click(function(event){
/* store native dom node*/
var tgt=event.target;
/* store jQuery object of dom node*/
var $tgt=$(tgt);
/* example element details*/
var details={ id : tgt.id, height: $tgt.height(), tag : tgt.tagName}
console.log( details)
})
Look at the event.target, and then you can use jQuery's .parents() method to look at every ancestor:
$(document).on('click', function(event) {
var $t = $(event.target); // the element that was actually clicked
var $p = $t.parents(); // the target's parents
var $form = $p.filter('form').first(); // the enclosing form, if it exists
});
I have a ul list :
<ul id="menubar">
<li onclick="ajx=new Ajax.Updater('container','schedule.php',{evalScripts:true,onComplete:oncom(this)})">one</li>
<li onclick="ajx=new Ajax.Updater('container','schedule.php',{evalScripts:true,onComplete:oncom(this)})">two</li>
</ul>
Here is the function callback:
function oncom(element){
//$(element).addClassName('current');
$$('#menubar li').invoke('observe', 'click', (function(element) {
//removes classname from all the li elements
//
var list_item = Event.element(element);
//Gets the li you clicked on
//adds the classname
if(!(list_item.hasClassName('current'))){
list_item.addClassName('current');
}else{
$$('#menubar li').invoke('removeClassName', 'current');
}
}).bindAsEventListener(this));
}
But its not making the current link having affect of that class, but when I click on next link its takes affect. How to solve this?
The options you are passing to the updater are {evalScripts:true,onComplete:oncom(this)}. You are not assigning the function oncom to onComplete but calling oncom(this) straight away then assigning it's result to onComplete - and the result is null.
If container contains the menubar list then it will also be replaced (probably why you are recreating click handlers). Consider using Event.on once so that newly inserted elements behave correctly.
Event.on('container', 'click', '#menubar li', function(event, element) {
// manipulate class names here
});
Also consider that if all you're doing is manipulating class names you can do that on the server when AJAX is used, that will avoid race problems.
The reason its not working until you click the first item is because the oncom function contains the observe for the li elements, and you're not running that code until you click on one. You need to get rid of the onClick stuff in the html if possible. Just run this code when the page load, and it will observe the li's straight away:
$$('#menubar li').invoke('observe', 'click', (function(e) {
//Removes current class from all the li's
$$('#menubar li').invoke('removeClassName', 'current');
//Add current class to the li clicked on
Event.element(e).addClassName('current');
//Does whatever this does, without being in the onClick
new Ajax.Updater('container','schedule.php',{
evalScripts:true
});
}).bindAsEventListener(this));