How do I make an array of CSS classes, not the CSS class names? I need the "." and everything.
I need users to be able to click on certain buttons, and add the classes the button belongs to into an array.
I used this before:
var myPicks[];
$('.button').click( function() {
var hello = " " + $(this).attr('class').split(' ')[0];
myPicks.push(hello);
}
But that seems to add the name of the classes, not the classes themselves. It's possible I'm wrong and there's something wrong with another part of my JQuery code.
Try
var myPicks = [];
$('.button').click( function() {
Array.prototype.push.apply(myPicks, $.map($(this).attr('class').split(' '), function(value, idx){
return '.' + value
}))
console.log('myPicks', myPicks)
});
if you want only unique classes
var myPicks = [];
$('.button').click( function() {
$.each($(this).attr('class').split(' '), function(idx, value){
var selector = '.' + value;
if($.inArray(selector, myPicks) == -1){
myPicks.push(selector)
}
})
console.log('myPicks', myPicks)
});
Demo: Fiddle
I will not recommend save the name of the class with the dot included into that array(), It will be useless if you need it later for something else.
(Or your goint to need to split it again)
Instead, I suggest to save it like you have now and then and only when you needed, add the dot to that value
like:
var myPicks = new Array();
myPicks[0] = "something";
// original value:
var newValue = myPicks[0]; // newValue == 'something'
//used as ID:
var newValue = '#' + myPicks[0]; // newValue == '#something'
// used as a class:
var newValue = '.' + myPicks[0]; // newValue == '.something'
BUT, of course if you need that way... just replace the PUSH function and add the dot to it:
var newHello = '.' + hello;
myPicks.push(newHello);
Related
Is it possible to select elements based on mutually exclusive data attributes, for example: I'd like to .show() any divs with data attribute of country="united-kingdom" and also with type="partner" OR "director"? Something like:
$('.post[data-country="united-kingdom"]&[data-type="partner,director"]').show();
or
$('.post[data-country="united-kingdom"]&[data-type="partner"]or[data-type="director"]').show();
I'd like to .show() any divs with data attribute of country="united-kingdom" and also with type="partner" OR "director"?
Then you want a selector group:
$('.post[data-country="united-kingdom"][data-type="partner"], .post[data-country="united-kingdom"][data-type="director"]').show();
That says: Match any element which
Has class post, has data-country set to united-kingdom, and has data-type set to partner
or
Has class post, has data-country set to united-kingdom, and has data-type set to director
The "or" part comes from the ,, which is what makes it a selector group rather than a single selector.
In a comment, you've said:
The user might select ten or more of each taxonomy term which requires generating loads of permutations of this conditional.
In that case, you may be better off with filter:
var countries = ["united-kingdom"]; // This would be created from inputs
var types = ["partner", "director"]; // This too
then
var results = $(".post[data-country][data-type]").filter(function() {
var $this = $(this);
return countries.indexOf($this.attr("data-country") != -1 &&
types.indexOf($this.attr("data-type") != -1;
});
In ES2016 or above, you could use Array#includes — which gives you a simple boolean — instead of Array#indexOf which you have to check against -1; and there'a polyfill you can use in ES2015 and earlier...:
var results = $(".post[data-country][data-type]").filter(function() {
var $this = $(this);
return countries.includes($this.attr("data-country") &&
types.includes($this.attr("data-type");
});
This can even be taken further:
var criteria = {};
// From inputs, ...
criteria["country"] = ["united-kingdom"];
criteria["type"] = ["parter", "director"];
then
var keys = Object.keys(criteria);
var selector= ".post" + keys.map(function(key) {
return "[data-" + key + "]";
}).join();
var results = $(selector).filter(function() {
var $this = $(this);
return keys.every(function(key) {
return criteria[key].includes($this.attr("data-" + key));
});
});
And as long as we're thinking about ES2015 and ES2016:
const keys = Object.keys(criteria);
const results = $(selector).filter(() => {
const $this = $(this);
return keys.every(key => criteria[key].includes($this.attr("data-" + key)));
});
or if you really want to go crazy:
const keys = Object.keys(criteria);
const results = $(selector).filter(() =>
keys.every(key => criteria[key].includes(this.getAttribute("data-" + key)))
);
You can add multiple selectors separated by a comma
$('.post[data-country="united-kingdom"][data-type="artist"], .post[data-country="united-kingdom"][data-type="partner"]').show();
Or use a filter with a selector
$('.post[data-country="united-kingdom"]').filter('[data-type="artist"], [data-type="partner"]').show();
or a filter with a callback
var countries = ["united-kingdom", "india", "france"],
types = ["artist", "partner"];
$('.post').filter(function() {
return types.indexOf( $(this).data('type') ) !== -1 &&
contries.indexOf( $(this).data('coutry') ) !== -1;
}).show()
This code works but will quickly be inefficient (already so?) as my var list grows.
I am adding Twitter streams to pages with their new API. That means I need to provide them some info manually and they return an ID string. That's OK, no workaround.
This example uses the info I need for just three streams but the list will quickly grow to dozens or even more.
function isValidTweets(ts_titletweets) {
var widgetid = $('#TweetStuff').attr('data-widget-id');
var jackID = '243441836335697920'; //IDs associated with streams
var jillID = '243398621595312128';
var harryID = '243398621595312130';
var ts_titletweets = title.toLowerCase(); //title is parsed from URL elsewhere
validtweets = "jack|jill|harry"; // if the title doesn't match then no streams should be used
if (validtweets.indexOf(ts_titletweets.toLowerCase() + "|") > -1) {
console.log('TweetsEnabled');
if (ts_titletweets == "jack")
{widgetid = jackID;
console.log(widgetid + title)}
else if (ts_titletweets == "jill")
{widgetid = jillID;
console.log(widgetid + title)}
else if (ts_titletweets == "harry")
{widgetid = harryID;
console.log(widgetid + title)};
$('#TweetStuff').html("<a class=\"twitter-timeline\" width=\"500\" height=\"600\" data-widget-id=" + widgetid + "></a>");
$("#newTweetsButton").delay(3000).show(0);
$("#filters").css({'margin' : '-30px 0px 0px 0px'});
return true;
} console.log('no Tweets');
return false;
}
I'm certain I'm manually reentering and want to avoid that as the list grows.
Any and all suggestions are much appreciated for a grateful newbie.
Thanks!
UPDATED TYPOS
I would create an object that has properties that correspond to the person's name. You then store the id against that. Next you can check whether it exists and execute your code.
http://jsfiddle.net/7PSNt/1/
var title = 'jill'; //hard coded for demo purposes
var myObject = {
'jack': 1,
'jill': 2,
'harry': 3
};
//I assume title is just one of the keys above (jack, jill, harry)
var ts_titletweets = title.toLowerCase();
//if the object contains a property for the title then we can proceed
var tweetID = myObject[ts_titletweets];
if (tweetID != undefined) {
widgetid = tweetID;
console.log(widgetid + ':' + title)
}
Not really sure what you are asking, but here's some stuff that might help:
// define an object with name: id pairs
var twitterIds = {
'jack': '243441836335697920',
'jill': '243398621595312128',
'harry': '243398621595312130'
};
foreach(var name in twitterIds) {
// name = jack
// twitterIds[name] = '243441836335697920'
}
function loadTweets ( name ) {
if( name && twitterIds[name] ) {
// load stream here. Use twitterIds[name] to get the twitter id
}
}
For efficiency, try this:
//cache of static jQuery objects
var $$ = {
'TweetStuff': $('#TweetStuff'),
'newTweetsButton': $("#newTweetsButton"),
'filters': $("#filters")
};
//define the ids in an outer scope - this gives isValidTweets less work to do each time it is called
var ids = {
jack: '243441836335697920',
jill: '243398621595312128',
harry: '243398621595312130'
};
function isValidTweets(title) {
var t = title.toLowerCase();
var widgetid = ids[t] || $$.TweetStuff.attr('data-widget-id');
$$.TweetStuff.html("<a class=\"twitter-timeline\" width=\"500\" height=\"600\" data-widget-id=" + widgetid + "></a>");
$$.newTweetsButton.delay(3000).show(0);
$$.filters.css({'margin' : '-30px 0px 0px 0px'});
console.log('Tweets: ' + (ids[t] ? (widgetid + ' - ' + title) : 'none'));
return !!ids[t];//true or false
}
I'm not sure I understand what's going on in the code, but what you could be using is a lookup-table.
var ids = {
'jack': '243441836335697920',
'jill': '243398621595312128',
'harry': '243398621595312130'
};
if (/*whatever*/) {
widgetid = ids[ts_titletweets];
console.log(widgetid + title);
}
I have multiple checkbox in my page. i want to retrieve its values if checked.
Here is HTML Code..
<input name="ctl1189" type="checkbox" id="chkTicket_189310" class=" chkTicket" value="189310">
<input name="ctl1190" type="checkbox" id="chkTicket_189311" class=" chkTicket" value="189311">
And So on..
Javascript Code:
function updateTicketAction() {
var allUpdatedVendorTickets = $('.chkTicket').filter(function() { return this.value != $input.is(':unchecked'); });
var sFinalUpdateList = '';
allUpdatedVendorTickets.each(function() {
var ids = $(this).attr('id').split('_')[1];
sFinalUpdateList += ((sFinalUpdateList == '') ? '' : '|') + ids + ',' + $(this).val();
});
alert(sFinalUpdateList);
}
function updateTicketAction() {
var sFinalUpdateList = '';
$("input.chkTicket:checked").each(
function() {
var ids = $(this).attr('id').split('_');
var id = ids[1];
sFinalUpdateList += ((sFinalUpdateList == '') ? '' : '|') + id + ',' + $(this).val();
}
);
alert(sFinalUpdateList);
}
http://jquery-howto.blogspot.com/2008/12/how-to-check-if-checkbox-is-checked.html
I just created a fiddle. Look in the JavaScript console for the resulting object, which you can then further process.
Code:
var checkedCheckboxes = $('.chkTicket:checked'),
results = {};
checkedCheckboxes.each(function () {
var key = $(this).attr('id').split('_')[1];
results[key] = $(this).val();
});
function alertResults(results) {
var text = '', sep = '';
$.each(results, function (key, value) {
text += sep + key + '=' + value;
sep = '|';
});
alert(text);
}
alertResults(results);
console.log(results);
try this code
var collect='';
$('input:checked').each(function(i,e){
collect+=(collect===''? $(e).attr('name')+'='+$(e).val():','+$(e).attr('name')+'='+$(e).val());
alert(collect);
})
Here is a jsfiddle snippet that returns all checked inputs..
One question though, why do you split your id-attribute when you have your id stored in value-attribute? Anyways, hope this works for you!
function updateTicketAction() {
var allUpdatedVendorTickets = $('.chkTicket:checked');
var sFinalUpdateList = '';
allUpdatedVendorTickets.each(function () {
sFinalUpdateList += ((sFinalUpdateList == '') ? '' : '|') + $(this).val();
});
alert(sFinalUpdateList);
}
Or you can use map():
var el = $('input[type=checkbox]:checked').map(function(i,e){
var id = $(e).attr('id').replace('chkTicket_', '');
var val = $(e).val();
return {
'id' : id,
'value' : val
}
});
console.log(el[0].id);
Your filter function is wrong.
this.value != $input.is(':unchecked');
You're comparing a .value property (string) to the return value of the .is jQuery method (boolean). It's similar to:
'value' != !true //checked
'value' != !false //unchecked
Both will always return true - unless value is 0 or an empty string which evaluates to a falsy value and the right side of the expression evaluates to false, for which the != different operator will return false.
So, your filter's callback doesn't filter anything at all, except taking out checked boxes with value 0 or no value (which is unintentional).
You can avoid using a filter function by using the :checked selector:
var allUpdatedVendorTickets = $('.chkTicket:checked');
Now you'll have a jQuery object containing only the checked .chkTicket, much better.
Next thing, you're making bad use of strings.
"189310,189310|189311,189311"
That's what your function is generating. Every time you need to manipulate those results, you'll have to split the string at |, creating a new array. It's much better to store it as an array already.
var sFinalUpdateList = [];
Assuming your keys and values are always the same as in your example, you should store them only once as well.
allUpdatedVendorTickets.each(function() {
sFinalUpdateList.push(this.value);
});
This will generate a much more clean and maintainable array with only the checked boxes' values:
sFinalUpdateList =>
[0] -> "189310"
[1] -> "189311"
You can obtain their IDs by appending chkTicket_ to those values.
jsFiddle
I have a problem to manipulate checkbox values. The ‘change’ event on checkboxes returns an object, in my case:
{"val1":"member","val2":"book","val3":"journal","val4":"new_member","val5":"cds"}
The above object needed to be transformed in order the search engine to consume it like:
{ member,book,journal,new_member,cds}
I have done that with the below code block:
var formcheckbox = this.getFormcheckbox();
formcheckbox.on('change', function(checkbox, value){
var arr=[];
for (var i in value) {
arr.push(value[i])
};
var wrd = new Array(arr);
var joinwrd = wrd.join(",");
var filter = '{' + joinwrd + '}';
//console.log(filter);
//Ext.Msg.alert('Output', '{' + joinwrd + '}');
});
The problem is that I want to the “change” event’s output (“var filter” that is producing the: { member,book,journal,new_member,cds}) to use it elsewhere. I tried to make the whole event a variable (var output = “the change event”) but it doesn’t work.
Maybe it is a silly question but I am a newbie and I need a little help.
Thank you in advance,
Tom
Just pass filter to the function that will use it. You'd have to call it from inside the change handler anyway if you wanted something to happen:
formcheckbox.on('change', function(cb, value){
//...
var filter = "{" + arr.join(",") + "}";
useFilter(filter);
});
function useFilter(filter){
// use the `filter` var here
}
You could make filter a global variable and use it where ever you need it.
// global variable for the search filter
var filter = null;
var formcheckbox = this.getFormcheckbox();
formcheckbox.on('change', function(checkbox, value){
var arr = [],
i,
max;
// the order of the keys isn't guaranteed to be the same in a for(... in ...) loop
// if the order matters (as it looks like) better get them one by one by there names
for (i = 0, max = 5; i <= max; i++) {
arr.push(value["val" + i]);
}
// save the value in a global variable
filter = "{" + arr.join(",") + "}";
console.log(filter);
});
$('#select_id1, #select_id2, #select_id3').change(function() {
// If '#select_id1' has changed, 'str' should be equal to 'select_id1'.
// If '#select_id2' has changed, 'str' should be equal to 'select_id2'.
// If '#select_id3' has changed, 'str' should be equal to 'select_id3'.
str = <what should be here ?>
});
You can get the id of the element that invoked the change by this.id.
$('#select_id1, #select_id2, #select_id3').change(function() {
str = this.id;
});
Or (less efficiently):
$('#select_id1, #select_id2, #select_id3').change(function() {
str = $(this).attr("id");
});
But basically this is set to the element on which the event took place.
For the more general case, where not only IDs are used, as suggested by #Anurag, you can do the following:
// Save the selector
var selector = ".someClass, #someId, tr.someTrClass";
$(selector).change(function () {
var selectors = selector.split(","),
matching = []; // Remember that each element can
// match more than one selector
for (var i = 0, s; s = selectors[i]; i++) {
if ($(this).is(s)) matching.push(s);
}
str = matching.join(","); // Your list of all matching selectors
});
You can either look at this.id directly or indirectly via a passed in event object:
$('#select_id1, #select_id2, #select_id3').change(function (e) {
alert(e.target.id + ' == ' + this.id + ' ... ' + (e.target.id == this.id));
});
Most people just look at this but there are times when you might be interested in more than just the target of your event.