Storing jquery selector arrays? - javascript

Below you can see that I store the results of the jquery selector in an array. I then use this array to perform other functions. This example here doesn't seem to work, it's behaving as if the var/array is a live selector, not the results when they were instantiated.
function flipIt(elementId){
if (window.jQuery){
var thisVisibleArray = $('#' + elementId + ' div:visible');
var thisInvisibleArray = $('#' + elementId + ' > div:visible');
$(thisInvisibleArray).slideDown("fast");
$(thisVisibleArray).slideUp("fast");
/*
if ($('#flip1').is(":visible")){
$('#flip1').slideUp("fast", function(){
$('#flip2').slideDown();
});
} else {
$('#flip2').slideUp("fast", function(){
$('#flip1').slideDown();
});
}*/
}
}

In order to select the invisible div elements you have to use not and not ">". And also the 2 variables you defined are already jquery element array so you dont have to use $(). Try this
function flipIt(elementId){
if (window.jQuery){
var thisVisibleArray = $('#' + elementId + ' div:visible');
var thisInvisibleArray = $('#' + elementId + ' div:not(:visible)');
thisInvisibleArray.slideDown("fast");
thisVisibleArray.slideUp("fast");
/*if ($('#flip1').is(":visible")){
$('#flip1').slideUp("fast", function(){
$('#flip2').slideDown();
});
} else {
$('#flip2').slideUp("fast", function(){
$('#flip1').slideDown();
});
}*/
}
}

You are storing the selected elements in a variable, and then you are trying to get a jQuery object out of another jQuery object. Just do:
thisInvisibleArray.slideDown("fast");
thisVisibleArray.slideUp("fast");
Also, they are not arrays, but jQuery objects.

Related

Changing CSS based on button state

in my application i post data to the server via ajax, while data is being posted to the server i want to be able to show the user that something is indeed happening, now a simple way to do this will be to display a loading gif. What i actually want to do is change the state of the button that was clicked. I have 4 classes in my css:
btn-ready-state
btn-working-state
btn-completed-state
btn-failed-state
Now each button has a class of btn-ready-state when you click the button the class changes to btn-working-state where the text of the button changes to "working" and a small loading icon appears inside the button. When the operation is done successfully it switches to btn-completed-state if it fails then btn-failed-state. Now i have been able to do this in my code with jquery but the code is so messy and untidy and doesn't work properly with angular. I have been told i can use directives to achieve this but since i am new to angular i am confused as to how to implement this with directives, i do know what a directive is and how to make one, my issue here is the implementation of this particular feature. This is how i did it with jquery:
<script type="text/javascript">
$(document).ready(function() {
var $loading = $('#loading');
$loading.on("change", function(){ //bind() for older jquery version
var index = parseInt($('#loading').val());
var done = parseInt($('#done').val());
if (done === 0) {
$('.btn.ticket:eq(' + [index] + ')').removeClass('btn-ready-state');
$('.btn.ticket:eq(' + [index] + ')').addClass('btn-working-state');
$('.btn.ticket:eq(' + [index] + ')').find('.text').text('Working..');
$('.btn.ticket:eq(' + [index] + ')').find('.state').addClass('loading');
$('.btn.ticket:eq(' + [index] + ')').find('i').replaceWith('<img src="/images/loading.gif">' + '</img>');
} else {
$('.btn.ticket:eq(' + [index] + ')').removeClass('btn-ready-state');
$('.btn.ticket:eq(' + [index] + ')').removeClass('btn-working-state');
$('.btn.ticket:eq(' + [index] + ')').addClass('btn-completed-state');
$('.btn.ticket:eq(' + [index] + ')').find('.text').text('Added');
$('.btn.ticket:eq(' + [index] + ')').find('.state').addClass('done');
$('.btn.ticket:eq(' + [index] + ')').find('i').replaceWith('<i class="glyphicon glyphicon-ok state"></i>');
$('.btn.ticket:eq(' + [index] + ')').find('img').replaceWith('<i class="glyphicon glyphicon-ok state"></i>');
}
}).change(); //could be change() or trigger('change')
});
$(document).on("click", ".btn.ticket", function() {
var index = $(".btn.ticket").index(this);
$('#loading').val(index).change();
});
$(document).on("click", ".btn.next", function() {
$(this).removeClass('btn-ready-state');
$(this).addClass('btn-working-state');
$(this).find('.text').text('Working..');
$(this).find('.state').addClass('loading');
$(this).find('i').replaceWith('<img src="/images/loading.gif">' + '</img>');
});
</script>
This is a sample html of the button:
<button class="btn-ready-state"><span class="img"></span><span class="text"></span></button>
90% of the script changes the style. You said you like to indicate ajax? Look at this:
<script>
jQuery.ajaxSetup({
ajaxStart:function(){
jQuery('body').toggleClass('ajaxing', true);
},
ajaxStop:function(){
jQuery('body').toggleClass('ajaxing', false);
}
})
</script>
This is better because you dont need to repeat yourself (DRY-Principle).
So instead of doing this in javascript:
$(this).find('i').replaceWith('<img src="/images/loading.gif">' + '</img>');
You can now do all the graphical stuff you did in javascript in CSS:
.ajaxing i {
background-image: url(/images/loading.gif);
}
// for text you can use this:
.ajaxing .btn.ticket:active:before{
position:relative;
content:'Working...';
}
Or in anguarjs:
angular.module('app', []).value('loadManager', {
c: 0,
requested: function() { c++; document.body.class="ajaxing";},
responded: function() { c--; if(!c)document.body.class="";}
}).factory('loadingInterceptor', function(loadManager) {
return {
request: function(e) {
loadManager.requested();
return e;
},
response: function(e) {
loadManager.responded();
return e;
},
}
});
$httpProvider.interceptors.push('loadManager');
All of this is only an example. I do not know the complete HTML you are using.

How to Show Dynamically Added Element

I'm trying to create tooltips with title attribute and jQuery but can't find method to show dynamically added element.
HTML
some page
CSS
.tooltip {
    …
display: none; /* I's needed for hard coded tooltips */
…
}
jQuery
$(function () {
if (window.matchMedia('(min-width: 980px)').matches) {
$('.dfn').hover(
function () {
var el = $(this);
var txtTitle = el.prop('title');
el.append('<p class="tooltip">' + txtTitle + '</p>');
                //That's it. My tooltip has been created, but it has not been shown
$(el + ' .tooltip').show('fast');
el.data('title', el.prop('title'));
el.removeAttr('title');
}, function () {
$(el + ' .tooltip').hide('fast').remove();
el.prop('title', el.data('title'));
}
);
}
});
As mentioned by others, $(el + ' .tooltip').show('fast'); is probably wrong.
The el is an object, not a string to concat', one way is to use el.find('.tooltip').show().
The other way is to use the context option: $('.tooltip', el).show();
You need to have correct code to find new element:
$('.tooltip', el).show('fast');
Your current one probably endup searching for something like [object] .tooltip or similar string depending on how JavaScript decides to convert HTML element to string.
As others have mentioned el.find('.tooltip').show() and el.find('.tooltip').hide().remove(); solve the problem.
Also, in HandlerOut function, you el was not declared. Fiddle here
$(function () {
//if (window.matchMedia('(min-width: 980px)').matches) {
$('.dfn').hover(
function () {
var el = $(this);
var txtTitle = el.prop('title');
el.append('<p class="tooltip">' + txtTitle + '</p>');
//That's it. My tooltip has been created, but it has not been shown
el.find('.tooltip').show()
el.data('title', el.prop('title'));
el.removeAttr('title');
}, function () {
var el = $(this);
el.find('.tooltip').hide().remove();
el.prop('title', el.data('title'));
}
);
//}
});

simplify jQuery selector highlight

I have over 100 videos and I use a function to highlight the links clicked. The code thought is very long and I feel like there must be a way to simplify it into a for loop or something. Any idea?
var vid_all0 = $('#vid_link0, #vidtop_link0, .vidtop_link0, #vidmob_link0, #link0'); //cache selector
vid_all0.click(function () {
$('[id^=vid_link],[id^=vidtop_link],[id^=vidmob_link], .vidtop_link0').css('background-color', 'inherit');
vid_all0.css('background-color', '#A9CDEB'); //change color of all elements
$('.vidtop_link0').css('background-color', 'inherit');
});
var vid_all1 = $('#vid_link1, #vidtop_link1, #vidmob_link1,#link10'); //cache selector
vid_all1.click(function () {
$('[id^=vid_link],[id^=vidtop_link],[id^=vidmob_link]').css('background-color', 'inherit');
vid_all1.css('background-color', '#A9CDEB'); //change color of all elements
});
var vid_all2 = $('#vid_link2, #vidtop_link2, #vidmob_link2,#link19'); //cache selector
vid_all2.click(function () {
$('[id^=vid_link],[id^=vidtop_link],[id^=vidmob_link]').css('background-color', 'inherit');
vid_all2.css('background-color', '#A9CDEB'); //change color of all elements
});
...
it goes up to 15
Give all those elements the same class, then use all elements with that class like
$(".vidtop").on("click", function()
{
// Do something with their CSS
});
If you can't modify your HTML with a class, something like this should work:
for (var i=1; i=99; i==;) {
$(vid_all + i).click(function () {
$(this).find('[id^=vid_link],[id^=vidtop_link],[id^=vidmob_link]').css('background-color', 'inherit');
});
}
I'm not sure if I understood your code correctly, but this would seem to be a simpler version:
function doStuff(links, additional) {
links.click(function() {
$('[id^=vid_link],[id^=vidtop_link],[id^=vidmob_link]' + (additional ? "," + additional : "")).css('background-color', 'inherit');
links.css('background-color', '#A9CDEB');
if (additional) {
additional.css('background-color', 'inherit');
}
});
}
// vid_all0
doStuff($('#vid_link0, #vidtop_link0, .vidtop_link0, #vidmob_link0, #link0'), $('.vidtop_link0'));
// vid_all1
doStuff($('#vid_link1, #vidtop_link1, #vidmob_link1,#link10'));
// vid_all2
doStuff($('#vid_link2, #vidtop_link2, #vidmob_link2,#link19'));
// etc.

Apply a jQuery function live() in 1 object

I have a Facebook-Like Chat. (You can see it # http://www.live-pin.com/). It gets the last messages from a JSON file and inserts into an individual UL for each user, it before checks if the ul exists and if it doesnt, it creates. Now the problem is that when I click on 1 chat bar, the 3 open at the same time, and only close if I click on the last one, what can I do? I want that this bars only open/close when clicked on chat bar but doesnt if click on not_clickable. Thanks for your help
$(document).ready(function(){
getOnJSON();
setInterval("getOnJSON()", 60000);
var Id;
var target;
});
function showChat(obj){
$(obj).animate({marginBottom : "0"}).removeClass("hidden_box").addClass("active_box").unbind('click')/*.click(function(){
hideChat(this);
})*/;
}
function hideChat(obj){
$(obj).animate({marginBottom : "-270px"}).removeClass("active_box").addClass("hidden_box").unbind('click')/*.click(function(){
showChat(this);
})*/;
}
function getOnJSON(){
var self = this; // Added this line, as this changes scope in each()
var from;var to;var msg_id;var msg_txt;var new_chat_string;
//Getting the data from the json file
$.getJSON("/ajax/chat.json.php",function(data){
$.each(data.notif, function(i,data){
from = data.from;to = data.to;msg_id = data.id;msg_txt = data.text;
if ($("#chat_"+from+"_lp").length === 0){
$("#boxes").append('<div id="chat_'+from+'_lp" class="chat_box hidden_box clickable_box"><div id="chat_'+from+'_nick" class="chat_name">'+from+'</div><div class="not_clickable"><ul id="chat_'+from+'_txt" class="chat_txt"><li id="' + msg_id + '">'+ msg_txt+'</li></ul><form class="chat_new_message" name="new_msg"><input type="text" placeholder="Enter your message..." class="chat_new_input"/></form></div></div>');
$('.hidden_box #chat_'+from+'_nick').live("click", function(){ showChat('#chat_'+from+'_lp'); });
$('.active_box #chat_'+from+'_nick').live("click", function(){ hideChat('#chat_'+from+'_lp'); });
}else{
$("#chat_"+from+"_txt").append('<li id="' + msg_id + '">'+ msg_txt+'</li>');
$('.hidden_box #chat_'+from+'_nick').live("click", function(){ showChat('#chat_'+from+'_lp'); });
$('.active_box #chat_'+from+'_nick').live("click", function(){ hideChat('#chat_'+from+'_lp'); });
}
});
});
}
You need to use jquery .live() function for your .click() to be applied to elements created after the document load complete.
For instance: $("a.offsite").live("click", function(){ alert("Goodbye!"); }); is an example from here

Reference JS object to DOM element

How can I reference specific DOM element to specific JS object?
For example, i have an array of customers. Using jQuery, for each customer I create LI with checkbox and span for customers name. When checkbox is clicked, I need to do some processing on that customer JS object. The question, how i can get this JS object an easy way.
Currently I have following:
$(customers).each(function(){
$("<li>").append($("<input type=\"checkbox\"").attr("id","chk_" + this.ID)).append($("<span>").text(this.Name)).appendTo("#ulCustomers");
});
$("#ulCustomers input[type=checkbox]").bind("click",function(){
var customerId = $(this).attr("id").replace("chk_","");
var CustomerObj = $(customers).filter(function () { return this.ID == customerId }).get(0);
myProcess(CustomerObj); //Two above two lines are just for select correct customer from array.
});
I believe in world of JS and jQuery exists more elegant way to do it.
Thanks
You can use jquery data function
$(customers).each(function() {
var elem = $("<li><input type='checkbox'><span>" + this.Name + "</span></li>").appendTo("#ulCustomers");
elem.find("input").data("customer", this);
});
$("#ulCustomers input[type=checkbox]").click(function() {
var CustomerObj = $(this).data("customer");
myProcess(CustomerObj);
});
Could you not bind the click event to a closure with a reference to the relevant Customer object?
like this
$(customers)
.each(function(){
var custObj = this;
$("<li>")
.append(
$("<input type=\"checkbox\"")
.append($("<span>")
.text(this.Name))
.appendTo("#ulCustomers")
.bind("click", function(){
myProcess(custObj);
})
});
I would use jQuery data, just like this:
$("checkbox").data('customer', this.ID);
To retrieve the data:
$("#ulCustomers input[type=checkbox]").bind("onchange",function(){
var customerId = $(this).data("customer");
var CustomerObj = $(customers).filter(function () { return this.ID == customerId }).get(0);
myProcess(CustomerObj); //Two above two lines are just for select correct customer from array.
});
Additionally, don't use click event on check-boxes, use onchange event ;)

Categories