How to affect an Li with a certain class in jQuery? - javascript

I am using a jQuery gallery plugin, the thumbs are all in an unordered list and the main image is to the right in a div.
The plugin adds the class "selected" to the li whose main image is currently being shown. As soon as the plugin moves on to the next image, the selected class is removed from the li and added to the next li.
I want to affect the li that currently has the class "selected" applied to it. I can't just do this:
$('li.selected').whateverRules();
because jQuery is applying the class dynamically, the class isn't there from the document ready state hence it doesn't work.
I also can't use .live() because I have no event to attach. So how can I work with this?
How can I affect the li which currently has a class of "selected" if this class was added dynamically?

There is no way to bind to an event when a CSS class has been changed. Perhaps you could modify the jquery plugin to trigger an event when the selected class has been added and bind to that?
Here is a link for trigger() if you feel adventurous. trigger()

Depending on how intensive your calls are you could always use an interval. It's not ideal, necessarily, but may do what you need:
var selectedInterval = setInterval(function () {
$('li.selected').whateverRules();
}, 100); // adjust timing to fit based on function complexity / timing.
I try to remember to store setInterval's return values into a variable in case they need to be cleared later. It's worth a shot, though not as clean as I'd like. If I were you I'd look into some event that fires when the gallery changes it's selection (there ought to be one, I'd imagine).

I guess you can attach the event to the controls of the gallery:
jQuery(function($){
$('a.next-image').mouseup(function(){
$('img.selected') ... // what you want.
});
});
I guess this a bit ugly but with no source is dificult solve in a clean way.

Related

Attaching multiple click events without having to repeat myself

Here is the fiddle.
Ignore the styling, that's not important.
Basically I needed to open the Fancybox with two links present, but I only want one gallery image. I figured that out easily enough. When the thumbnail is clicked it triggers the li anchor.
To keep the galleries separate I did unique classes for each ol.
The problem I have run into is I will be repeating myself.
I attempted to do a loop (commented out), but the logic is beyond my grasp.
What is the best way to attach a new click handler (I need to add 8 more) without repeating myself in my current fashion? I've also tried a function with a couple parameters, but I had trouble with the e.preventDefault().
I greatly appreciate any guidance, thanks!
This looks like a great use case to use jQuery's on() method. on() is a method that will allow you to establish a handler on an outer container that can listen to its children for click events. So, for example: if you specified a class of .js-listen on your lists, you could call on() like this:
$('.js-listen').on('click', 'other-selector', function(e){
// function logic with either $(this) or e.target goes here
}
This block would essentially look for all elements with .js-listen and then when something inside the element with the .js-listen class is clicked, the event will bubble up through the DOM and the event will be handled according to the element that was clicked. The second parameter I have 'other-selector' can be a class name, element, or ID. so you could essentially put something like img there and it would fire the event if the child element clicked was an <img> tag.
This prevents you from attaching a handler a million times, and one of the benefits of on() is that if elements are dynamically added to the container with the handler, you don't have to worry about attaching handlers to those elements, because again, they bubble up!
Hope this helps!

Force a function to overwrite other actions

I am trying to get some contenteditable elements working. Obviously this is incredibly easy with just a simple HTML5 attribute, but I want to be able to toggle the amount of elements with the attribute and also toggle the attribute itself. For example, my starting element is this <article class="column contentEditable"> and then the class of contentEditable is used to toggle the contenteditable attribute. But because I am duplicating this element an amount of times based on what the user selects - I need to run the .focus() action as a function which is then called when some more articles are added. With me so far? Hope so.
Here is the jQuery I have so far (bearing in mind another function sets the class contentEditable to have the attribute contenteditable)
// content edittable
function makeEditable(action){
$('.contentEditable').focus(function(){
$(this).addClass('active');
$(this).prepend('<div class="toolbar" contenteditable="false">TEST</div>');
});
$('.contentEditable').blur(function(){
$(this).removeClass('active');
$(this).remove('.toolbar');
alert('test');
});
}
To a certain extent this works perfectly, however because an article may have already been there when this DOM call was issued before, it means that it's running twice or more (depending on how many times I've changed the option in the select. How on earth can I get the function to only run once per item, i.e. not stack.
Hope this all makes sense, pretty difficult to explain.
I think what's happening here is that you are calling the makeEditable function everytime the user is selecting an element to edit (if I understand your workflow right). If that's happening you're adding a new focus and blur event every time they do and that will cause the event to fire multiple times.
What I recommend is something like this:
function addElement(containerElement) {
// containerElement is a string with the jQuery selector of the parent element
var el = $('<article class="column contentEditable"></article>').appendTo(containerElement);
el.focus(function(){
$(this).addClass('active');
$(this).prepend('<div class="toolbar" contenteditable="false">TEST</div>');
});
el.blur(function(){
$(this).removeClass('active');
$(this).remove('.toolbar');
alert('test');
});
}
function toggleEditable(el) {
// here el is a string with the jQuery selector of the element
$(el).toggleClass('contentEditable');
}
It was a simple case of having a process class on it to only run it once, each time the .focus is run it removes the process class. Pretty simple really, fresh eyes helped after a break. Thanks.

using jQuery to change, only the elements that were loaded via ajax

For each checkbox on the web page, I replace it with a slider that I borrowed from jsfiddle.net/gnQUe/170/
This is done by going through the elements when the document is loaded.
Now the problem is that when more content is loaded via ajax, the new checkboxes are not transformed.
To solve the problem, I used AjaxComplete event to go through all the elements again and replace the checkboxes with sliders.
Now the problem happens that elements that were already replaced, get two sliders. To avoid that I check if the checkbox is hidden and next element is div of class "slider-frame", then don't process the re-process the element.
But I have a lot of other such controls as well, and I am presume I am not the only one that has this problem. Is there another easy way around it?
There exists jQuery live/on( http://api.jquery.com/on/ ) event but it requires an event as an argument? whereas I would like to change the look of my controls when they are rendered.
Another example of the same problem is to extend some controls that are loaded via ajax with jQuerys autocomplete plugin.
Is there a better way to accomplish this other than changing some attributes on the element.
To summarize, on document load I would like to process every element in DOM, but when more elements are loaded via ajax then I want to change only the new elements.
I would assume that when the element's are transformed into a slider, a class is added to them. So just add a not clause.
$(".MySelector").not(".SomeClassThatSliderAddsToElement").slider({});
So in the case of your code do something like this
$('.slider-button').not(".sliderloaded").addClass("sliderloaded").toggle(function(){
$(this).addClass('on').html('YES');
$('#slider').val(true);
},function(){
$(this).removeClass('on').html('NO');
$('#slider').val(false);
});
Since you said you do not want to add anything else, how about you change the toggle function to click.
$(document).on("click", ".slider-button", function(){
var elem = $(this);
elem.toggleClass("on");
var state = elem.hasClass("on");
elem.text(state?"YES":"NO");
elem.parent().next().val(state);
});
Running fiddle: http://jsfiddle.net/d9uFs/

Recursive jQuery function to amend select option values

I have a form that I am trying to alter with jQuery. Basically, my form has two elements and I need to change the value of the first option in each of them. However, there is an "add more" option that uses AJAX to dynamically generate another element that also needs changed. This add more button can be clicked an unlimited amount of times.
Right now I have this:
$(document).ready(function(){
$("#myname-0-field option:first").val("None");
$("#myname-1-field option:first").val("None");
});
This works fine, but once the "add more" button is clicked, I have more elements called "#myname-2-field", "#myname-3-field", "#myname-4-field" etc. These obviously aren't affected by adding another line into my jQuery as the document has already loaded when they are added.
So the real question is, can someone point me in the right direction of writing a function that can react when the new element is added and change it. If possible, I'm also looking for the function to be aware and look for "#myname-X-field option:first" for tidyness.
use live() function
Then using each function set value
From the jQuery API look live function
Maybe you could add class to your element, so that finding particular element would be easier and it would not add event to other similar elements.
In the example I have a Li with class
$('li.myClass').live('click', function() {
$(this).val(); // this is the getter for clicked value
$(this).val("some_value_here"); // this is the setter for clicked value
});
Now you can add more elements (that has myClass class) and it will have a click event.
Btw. if you know that all elements are inside some container (div for example) then you can write more efficient jQuery using delegate.
$('#container_id').delegate('li.myClass', 'click', function () {
});
This is more efficient because it looks your new elements only under "containter" not from the whole DOM structure.

Hover Item with JQuery

Is there a way to hover an element using javascript?
I don't want to create another class, I just want to cause element to hover with javascript when my mouse pointer is not over that element.
For example I have 5 elements with the same class and I want to call hover on all of them when one of them is actually hovered.
I assume you mean the pseudo class :hover that you've associated with a link (for example). As you hover over that link, you want to invoke all other link's :hover styles.
Unfortunately, you can not invoke the :hover styles from jQuery, that requires that you actually move your mouse pointer over that element. You have to use classes and utilize jQuery's hover event.
You can achieve this by addressing all of the items in your collection at the same time in your hover event handlers
var items = $(".some-class-applied-to-many-different-items");
items.hover(function() {
// Mouseover state
items.addClass("blah"); // <- for example
},
function() {
// Mouseout state
items.removeClass("blah");
});
If I understand your question correctly, you've added a hover event using jQuery, and you'd like to trigger that event manually regardless of the mouse.
If I understood correctly, you want to call the mouseenter to trigger the mouseenter event.
If I've understood incorrectly, and you actually have a :hover CSS rule which you'd like to trigger using Javascript, that's not possible.
Instead, you should add a class name to the rule (eg, something:hover, something.FakeHover { ... }), and add that class name using jQuery. (eg, $(...).addClass('FakeHover')).
In jQuery, the trigger function allows you to trigger events (includingmouseover, I believe) on elements.
In straight JavaScript, if you’ve assigned a function to an element’s event handler, you can of course call that whenever you want. E.g.
function mouseoverHandler() {
// Do something
}
// Assign function to element’s event handler
document.getElementById('link1').onmouseover = mouseoverHandler
// Call that function
document.getElementById('link1').onmouseover();

Categories