Build a switch based on array - javascript

I want to create a Javascript switch based on an array I'm creating from a query string. I'm not sure how to proceed.
Let's say I have an array like this :
var myArray = ("#general","#controlpanel","#database");
I want to create this...
switch(target){
case "#general":
$("#general").show();
$("#controlpanel, #database").hide();
break;
case "#controlpanel":
$("#controlpanel").show();
$("#general, #database").hide();
break;
case "#database":
$("#database").show();
$("#general, #controlpanel").hide();
break;
}
myArray could contain any amount of elements so I want the switch to be created dynamically based on length of the array. The default case would always be the first option.
The array is created from a location.href with a regex to extract only what I need.
Thanks alot!

#Michael has the correct general answer, but here's a far simpler way to accomplish the same goal:
// Once, at startup
var $items = $("#general,#controlpanel,#database");
// When it's time to show a target
$items.hide(); // Hide 'em all, even the one to show
$(target).show(); // OK, now show just that one
If you really only have an array of selectors then you can create a jQuery collection of them via:
var items = ["#general","#controlpanel","#database"];
var $items = $(items.join(','));
Oh, and "Thanks, Alot!" :)

I think you want an object. Just define keys with the names of your elements to match, and functions as the values. e.g.
var switchObj = {
"#general": function () {
$("#general").show();
$("#controlpanel, #database").hide();
},
"#controlpanel": function () {
$("#controlpanel").show();
$("#general, #database").hide();
},
"#database": function () {
$("#database").show();
$("#general, #controlpanel").hide();
}
}
Then you can just call the one you want with
switchObj[target]();
Granted: this solution is better if you need to do explicitly different things with each element, and unlike the other answers it focused on what the explicit subject of the question was, rather than what the OP was trying to accomplish with said data structure.

Rather than a switch, you need two statements: first, to show the selected target, and second to hide all others.
// Array as a jQuery object instead of a regular array of strings
var myArray = $("#general,#controlpanel,#database");
$(target).show();
// Loop over jQuery list and unless the id of the current
// list node matches the value of target, hide it.
myArray.each(function() {
// Test if the current node's doesn't matche #target
if ('#' + $(this).prop('id') !== target) {
$(this).hide();
}
});
In fact, the first statement can be incorporated into the loop.
var myArray = $("#general,#controlpanel,#database");
myArray.each(function() {
if ('#' + $(this).prop('id') !== target) {
$(this).hide();
}
else {
$(this).show();
}
});

Perhaps you're looking for something like this? Populate myArray with the elements you're using.
var myArray = ["#general","#controlpanel","#database"];
var clone = myArray.slice(0); // Clone the array
var test;
if ((test = clone.indexOf(target)) !== -1) {
$(target).show();
clone.splice(test,1); // Remove the one we've picked up
$(clone.join(',')).hide(); // Hide the remaining array elements
}

here you dont need to explicitly list all the cases, just let the array define them. make sure though, that target exists in the array, otherwise you'll need an if statement.
var target = "#controlpanel";
var items = ["#general","#controlpanel","#database"];
items.splice($.inArray(target, items), 1);
$(target).show();
$(items.join(",")).hide();
items.push(target);

Related

How to remove elements from a selector

I'm struggling to get a piece of code to work but I'm not a jquery guy so please bear with me.
I have an outer DIV ($scope). It contains all kinds of inputs.
I find all the entries for each input type and filter them to get the ones with values. These are stored in $entries.
$inputs contains all the inputs regardless of type or status.
What I'm trying to do is remove $entries from $inputs to leave the difference.
It doesn't work, and at the moment I'm not getting any errors firing back, so nothing to go on.
My first thought is that jquery is unable to match the elements in one list with the other as it just holds an index, not the actual object. This could be totally wrong (please refer back to line 1).
Either way, I need to find a way of getting all elements and segegating them into 2 bits - those with values and those without.
All help appreciated.
function inputLoaded(isPostback) {
if (typeof Page_Validators !== "undefined") {
$scope = $(".active-step:first");
$inputs = $scope.find(inputs);
$cb = $scope.find(checkboxes).filter(":checked");
$rb = $scope.find(radios).filter(":checked");
$sb = $scope.find(selects).filter(function () { return $(this).val() !== "None"; });
$ta = $scope.find(textareas).filter(function () { return $(this).val(); });
$tb = $scope.find(textboxes).filter(function () { return $(this).val(); });
$entries = $cb.add($rb).add($sb).add($ta).add($tb);
// Do things with $entries here
// Get elements that have not got entries
$el = $inputs.remove($entries);
}
}
The not() method can take a jQuery object whose contents will be excluded from the jQuery object you apply it to. It looks exactly like what you're looking for:
// Get elements, excluding entries.
$el = $input.not($entries);

breaking out of an underscore each

I am trying to find a model within a collection with an attribute equal to html select option value.
<div id="hospital-details">
<select name="hospitalnames">
<option><%- model.get('name') %></option>
</select>
</div>
whenever hospital name is changed, jquery change callback is triggered to find locationModel with selected option value as attribute value as shown below,
$('select[name="hospitalnames"]').change(function() {
var name = $(this).val();
locationListCollection.each(function(locationModel) {
if ($.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
return false; // control is returned to underscore.min.js
}
});
});
console.log(that.locationModel); // this is not being displayed at all
After the locationModel with an attribute is found, I am unable to come out the loop. Any help ? At this moment I have looked into
this but without success.
You're using the wrong method if you're searching for the first match. Collections have lots of Underscore methods mixed in, in particular they have find mixed in:
find _.find(list, iterator, [context])
Looks through each value in the list, returning the first one that passes a truth test (iterator), or undefined if no value passes the test.
Something like this:
var name = $.trim($(this).val());
that.locationModel = locationListCollection.find(function(locationModel) {
return $.trim(locationModel.get('name')) == name;
});
and if the names in your model are pre-trimmed and nice and clean, then you could use findWhere:
findWhere collection.findWhere(attributes)
Just like where, but directly returns only the first model in the collection that matches the passed attributes.
like this:
var name = $.trim($(this).val());
that.locationModel = locationListCollection.findWhere({ name: name });
BTW, this:
console.log(locationModel);
won't give you anything because locationModel and that.locationModel are different things.
You can always go oldschool.
$('select[name="hospitalnames"]').change(function() {
var name = $(this).val();
for (var i = 0; i < locationListCollection.length; ++i) {
var locationModel = locationListCollection.models[i];
if ($.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
break;
}
}
});
Try this,
var name = $(this).val();
var flag=true;
locationListCollection.each(function(locationModel) {
if (flag && $.trim(locationModel.get('name')) == $.trim(name)) {
that.locationModel = locationModel;
flag=false;
//return false;// to break the $.each loop
}
});
The short is no.
If you take a look at underscore's source you'll see that they use a breaker object to quickly stop a .each() but that is only available internally.
I would not recommend this but you could always modify the source to expose this breaker object (see baseline setup in the annotated source
http://underscorejs.org/docs/underscore.html). Then you would just return this object instead of returning false. But you would probably need to remove the native forEach call to keep the behaviour consistent. So it's not worth it!
_.each(function(arr) {
if(condition) {
return _.breaker; // Assuming you changed the source.
}
});
Since you are searching for a single item instead of .each() use:
var locationModel = _.find(arr, function(item) {
return $.trim(locationModel.get('name')) == $.trim(name);
));

How to check if two jQuery selectors have selected the same element

Is there a way for me to progamatically determine if two jQuery selectors have selected the same exact element? I am trying to loop over a set of divs and skip one of them. What I would like is something like this:
var $rows, $row, $row_to_skip;
$rows = $('.row-class')
$row_to_skip = $('#skipped_row')
$.each($rows, function (id, row) {
$row = $(row);
if (!$row == $row_to_skip) {
// Do some stuff here.
};
});
You can pass jQuery objects into .not():
$rows.not($row_to_skip).each(function() {
...
});
You can use .is()
if (!$row.is($row_to_skip)) {
// Do some stuff here.
};
You can compare the actual DOM element selected by jQuery:
var row_to_skip = $row_to_skip.get(0);
$.each($rows, function (id, row) {
if (row !== row_to_skip) {
// Do some stuff here.
}
});
Two jQuery objects will always be different from each other, even if they select the same elements (just like two empty objects are different).
However in your case, instead of comparing inside the loop, it's cleaner to just remove the element from the set:
$('.row-class').not("#skipped_row").each(function() {
// do stuff
});

Searching for an element in a Json object

I have an array of object (JSONized). Something like this :
popUpList = [{
"id":1,
"Name":"My Pop Up",
"VideoUrl":"www.xyz.com/pqr",
"AddToBasketUrl":"www.abc.com?addtoBaketid=1",
"addedToBasket": true
},
{
"id":2,
"Name":"My 2nd Pop Up",
"VideoUrl":"www.xyz.com/mno",
"AddToBasketUrl":"www.abc.com?addtoBaketid=2",
"addedToBasket": false
}]
My situation is a clip can be either added from he pop up or the main page. So, I need to edit the JSON object when something is added to basket from the page.
I tried using $.inArray() and similar methods. i reckon either I am not doing it the right way or missing something. Or, this cannot work for JSON objects and I have to loop through every object.
Any help will be appreciated.
Array.indexOf (what $.inArray is) does need the element to search for and returns its index.
If you need to search for an element you don't know before, you will need to loop manually (Libs like Underscore have helpers):
var idToSearchFor = …;
for (var i=0; i<popUpList.length; i++)
if (popUpList[i].id == idToSearchFor) {
// do something
}
If you want to build an index for faster accessing popups, you can do that as well. It also has the advantage of being unambiguous (only one element per id):
var popUpsById = {};
for (var i=0; i<popUpList.length; i++)
popUpsById[popUpList[i].id] = popUpList[i];
if (idToSearchFor in popUpsById)
// do something with popUpsById[idToSearchFor]
else
// create one?
I'm not quite sure what you want to search explicitely, you can access each value in your object by using:
vat id = "1";
// this given example wont work for you bec. of your structure
// but its all about the idea.
var objectOne = yourJsonObject[id];
// You can also append them
var myValue = yourJsonObject.address.zip;
And similiar on any other item of the fetched first object.
For that I would create a custom search function which would look like that:
$.each(popUpList, function(i, v) {
var entryYouWantToFind = "addedToBasket";
if(v[entryYouWantToFind])
{
// do your stuff here.
}
}
});
I hope I could give you the hint.

select an array of elements and use them

Using this syntax:
var position = array($('#ipadmenu > section').attr('data-order'));
I cannot get my code to work. I have never used arrays before so im kind of lost on how to use them. (especially in jquery).
How would I make an array of all section elements and associate the value of data-order to that list. Example:
first section - data-order:1
second section - data-order:2
etc and then use that info afterwards.
Thank you!
Since .attr just gets one attribute -- the first one found by the jQuery selector -- you need to build your array element by element. One way to do that is .each (you can also use .data to extract data attributes):
var position = new Array;
$('#ipadmenu > section').each(function() {
position.push($(this).data('order'));
});
alert(position[0]); // alerts "1"
This will be an indexed array, not an associative array. To build one of those (which in JavaScript is technically an object, not any kind of array) just change the inner part of your .each loop:
var position = {};
$('#ipadmenu > section').each(function(i) {
position["section"+i] = $(this).data('order');
});
The resulting object position can now be accessed like:
alert(position['section1']); // alerts "1"
A different approach involves using jQuery.map, but since that only works on arrays, not jQuery objects, you need to use jQuery.makeArray to convert your selection into a true array first:
var position = $.map($.makeArray($('#ipadmenu > section')), function() {
return $(this).data('order');
} ); // position is now an indexed array
This approach is technically shorter than using .each, but I find it less clear.
Javascript:
var orders = [];
$('#ipadmenu > section').each(function() {
orders.push($(this).data('order'))
});
HTML:
<div id="ipadmenu">
<section data-order="1">1</section>
<section data-order="2">2</section>
</div>
You will want to do something like this:
// Get the elements and put them in an array
var position = $('#ipadmenu section').toArray();
console.log(position);
// Loop through the array
for (var i = 0; i < position.length; i++){
// Display the attribute value for each one
console.log("Section " + i + ": " + $(position[i]).attr('data-order'));
}
Working example here: http://jsfiddle.net/U6n8E/3/

Categories

Resources