javascript - coldfusion - working with a list - javascript

This is probably easy for someone.
I am returning a list of campaignIDs (12,45,66) via JSON to a javascript variable
var campaignList = res.DATA.CAMPAIGNS
Now, given a specified campaignID passed in the URL
var campaignId ='<cfoutput>#url.campaignID#</cfoutput>'
I want to check if the returned list contains this campaignID
Any help much appreciated.

Plenty of ways to do it, but I like nice data structures, so ...
Split the list on comma, then loop over list, looking for value:
function campaignExists(campaignList,campaignId) {
aCampaignList = campaignList.split(',');
for (i=0;i<aCampaignList.length;i++) {
if (aCampaignList[i]==campaignId)
return true;
}
return false;
}

Since Array.indexOf sadly isn't cross browser, you're looking at something like:
// assume there is no match
var match_found = false;
// iterate over the campaign list looking for a match,
// set "match_found" to true if we find one
for (var i = 0; i < campaignList.length; i += 1) {
if (parseInt(campaignList[i]) === parseInt(campaignId)) {
match_found = true;
break;
}
}
If you need to do this repeatedly, wrap it in a function

Here's a bit of a "out of the box" solution. You could create a struct for your property id's that you pass into the json searilizer have the key and the value the same. Then you can test the struct for hasOwnProperty. For example:
var campaignIDs = {12 : 12, 45 : 45, 66 : 66};
campaignIDs.hasOwnProperty("12"); //true
campaignIDs.hasOwnProperty("32"); //false
This way if the list is pretty long you wont have to loop through all of the potential properties to find a match. Here's a fiddle to see it in action:
http://jsfiddle.net/bittersweetryan/NeLfk/

I don't like Billy's answer to this, variables within the function have been declared in the global scope and it is somewhat over complicated. If you have a list of ids as a string in your js just search for the id you have from user input.
var patt = new RegExp("(^|,)" + campaignId + "(,|$)");
var foundCampaign = campaignList.search(patt) != -1;

Related

String control in loops

I have a big question.
I have many Strings in my Programm and want to check these Strings on there values.
I wrote a Loop for it, but insted of the Definition of an String he is creating a new value. It's basicly really difficult to discribe, also because i am basicly German.
But i can give you my current code, so maybee you will see what I mean:
{
var Loch1G = $('#m1-Rundenanalyse-Datum').val(); //In the strings just the number is changing
var Loch2G = $('#m1-Rundenanalyse-Turnier').val();
x=1
while (x <= 2) {
if ("Loch" + x + "G" == ""){ //Next String is genrated (x=x+1)
alert("Eingabe war leer");
}
x=x+1
}
}
How can I solve this?
I'd suggest using an array to store the values you want to check:
var lochs = [];
lochs.push($('#m1-Rundenanalyse-Datum').val());
lochs.push($('#m1-Rundenanalyse-Turnier').val());
for (var i = 0, len = lochs.length; i < len; i++){
if (lochs[i] == ''){
alert("Eingabe war leer");
}
}
JS Fiddle demos: passes (no alert), fails (alert)
This suggestion is based on my presumption that you're trying to create the names of the vars you want to check, which won't work, whereas this approach lets you store all values (however many) in the same array and then iterate over that array to find any values that are equal to an empty string.
If you really want to stick with your current approach, you could do the following:
{
window.Loch1G = $('#m1-Rundenanalyse-Datum').val(); //In the strings just the number is changing
window.Loch2G = $('#m1-Rundenanalyse-Turnier').val();
var x=1;
while (x <= 2) {
if (window["Loch" + x + "G"] == ""){ //Next String is genrated (x=x+1)
alert("Eingabe war leer");
}
x=x+1;
}
}
But I can't think why you'd want to; plus the use of global variables is poor practice as it explicitly makes those variables available to every closure within the document, which allows them to be easily, and accidentally, overwritten.
In a reasonably up-to-date browser, that implements Array.prototype.every, you could dispense with the explicit iteration:
var lochs = [];
lochs.push($('#m1-Rundenanalyse-Datum').val());
lochs.push($('#m1-Rundenanalyse-Turnier').val());
if (!lochs.every(function(a){ return a !== ''; })) {
alert("Eingabe war leer");
}
JS Fiddle demos: passes (no alert), fails (alerts).

Can I loop through 2 objects at the same time in JavaScript?

related (sort of) to this question. I have written a script that will loop through an object to search for a certain string in the referring URL. The object is as follows:
var searchProviders = {
"google": "google.com",
"bing": "bing.com",
"msn": "search.msn",
"yahoo": "yahoo.co",
"mywebsearch": "mywebsearch.com",
"aol": "search.aol.co",
"baidu": "baidu.co",
"yandex": "yandex.com"
};
The for..in loop I have used to loop through this is:
for (var mc_u20 in mc_searchProviders && mc_socialNetworks) {
if(!mc_searchProviders.hasOwnProperty(mc_u20)) {continue;}
var mc_URL = mc_searchProviders[mc_u20];
if (mc_refURL.search(mc_URL) != -1) {
mc_trackerReport(mc_u20);
return false;
}
Now I have another object let's call it socialNetworks which has the following construct:
var socialNetworks = {"facebook" : "facebook.co" }
My question is, can I loop through both of these objects using just one function? the reason I ask is the variable mc_u20 you can see is passed back to the mc_trackerReport function and what I need is for the mc_u20 to either pass back a value from the searchProviders object or from the socialNetworks object. Is there a way that I can do this?
EDIT: Apologies as this wasn't explained properly. What I am trying to do is, search the referring URL for a string contained within either of the 2 objects. So for example I'm doing something like:
var mc_refURL = document.referrer +'';
And then searching mc_refURL for one of the keys in the object, e.g. "google.com", "bing.com" etc. 9this currently works (for just one object). The resulting key is then passed to another function. What I need to do is search through the second object too and return that value. Am I just overcomplicating things?
If I understand your question correctly, you have a variable mc_refURL which contains some URL. You want to search through both searchProviders and socialNetworks to see if that URL exists as a value in either object, and if it does you want to call the mc_trackerReport() function with the property name that goes with that URL.
E.g., for mc_refURL === "yahoo.co" you want to call mc_trackerReport("yahoo"), and for mc_ref_URL === "facebook.co" you want to call mc_trackerReport("facebook").
You don't say what to do if the same URL appears in both objects, so I'll assume you want to use whichever is found first.
I wouldn't create a single merged object with all the properties, because that would lose information if the same property name appeared in both original objects with a different URL in each object such as in an example like a searchProvider item "google" : "google.co" and a socialNetworks item "google" : "plus.google.com".
Instead I'd suggest making an array that contains both objects. Loop through that array and at each iteration run your original loop. Something like this:
var urlLists = [
mc_searchProviders,
mc_socialNetworks
],
i,
mc_u20;
for (i = 0; i < urlLists.length; i++) {
for (mc_u20 in urlLists[i]) {
if(!urlLists[i].hasOwnProperty(mc_u20))
continue;
if (mc_refURL.search(urlLists[i][mc_u20]) != -1) {
mc_trackerReport(mc_u20);
return false;
}
}
}
The array of objects approach is efficient, with no copying properties around or anything, and also if you later add another list of URLs, say programmingForums or something you simply add that to the end of the array.
You could combine the two objects into one before your loop. There's several approaches here:
How can I merge properties of two JavaScript objects dynamically?
var everything = searchProviders;
for (var attrname in socialNetworks) { everything[attrname] = socialNetworks[attrname]; }
for(var mc_u20 in everything) {
// ...
}
for (var i = 0; i < mc_searchProviders.length; i++) {
var searchProvider = mc_searchProviders[i];
var socialNetwork = mc_socialNetworks[i];
if (socialNetwork != undefined) {
// Code.
}
}
Or am i horribly misunderstanding something?

How should I store and retrieve dictionary words

I have a JavaScript variable that holds an array of dictionary words like
var words = ['and','cat', n1, n2, n3 and so on ]
This array holds about 58020 words.
What i have done is created an auto complete jQuery plugin that displays the words from the dictionary array in a drop down list when the user starts typing text into the text box. But the browser crashes at some point because I think the looping through each word is making the process slow.
How can i overcome this?
Here is the function that checks the word array and outputs the words if found
$(textInput).keyup(function(e) {
var text = $(this).val();
var foundTag = false;
for (var i = 0; i < settings.tags.length; i++) {
var tagName = settings.tags[i].toLowerCase();
if (tagName.startsWith(text)) {
if (text != '') {
foundTag = true;
$(settings.tagContainer).append(GetDivDropDownItem(settings.tags[i]));
}
else {
}
}
}
});
Edit
$(textInput).keyup(function(e) {
var text = $(this).val();
var foundTag = false;
for (var i = 0; i < settings.words.length; i++) {
var tagName = settings.words[i].toLowerCase();
if (tagName.startsWith(text)) {
if (text != '') {
foundTag = true;
$(settings.tagContainer).append(GetDivDropDownItem(settings.words[i]));
}
else {
}
}
}
});
var GetDivDropDownItem = function(text) {
var cWidth = $(container).css("width");
cWidth = cWidth.split("px")[0];
var tag = $("<div/>");
$(tag).css("paddingLeft", "5px");
$(tag).css("paddingRight", "5px");
$(tag).css("paddingBottom", "5px");
$(tag).css("paddingTop", "5px");
$(tag).css("width", cWidth - 10);
$(tag).css("float", "left");
$(tag).css("fontFamily", "Arial");
$(tag).css("fontSize", "12px");
$(tag).css("color", "#6A6B6C");
$(tag).text(text);
return $(tag);
};
You need to use better datastructures and algorithms. In general, I would suggest doing some research on pre-existing work before trying to tackle any problem.
This is an article that may be of help: http://orion.lcg.ufrj.br/Dr.Dobbs/books/book5/chap08.htm
See this benchmarks and comparisons done by jQuery creator John Resig:
http://ejohn.org/blog/revised-javascript-dictionary-search/
Basically the answer is a simple trie structure, if you really want to do it pure-JS.
By not putting 58.000 words in a Javascript array.
Use a webservice that holds all the dictionary words in a database, and query that.
edit: If you really insist on storing this in a javascript array, group the words by their first two characters. Easy to implement and around 600 times faster already.
A trie data structure would be good for a dictionnary.
Assuming settings.tags is the array of dictionary words, this code is going to be very cumbersome, since you're looping through the entire array with each keyup event.
I would suggest that you organize the dictionary words in a structure that allows you to go to the words very quickly. Perhaps a binary tree or just an associative array.

Need help with setting multiple array values to null in a loop - javascript

I have been working on creating a custom script to help manage a secret questions form for a login page. I am trying to make all the seperate select lists dynamic, in that if a user selects a question in one, it will no longer be an option in the rest, and so on. Anyways, the problem I am having is when I try to set the variables in the other lists to null. I am currently working with only 3 lists, so I look at one list, and find/delete matches in the other 2 lists. Here is my loop for deleting any matches.
for(i=0; i<array1.length; i++) {
if(array2[i].value == txtbox1.value) {
document.questions.questions2.options[i] = null
}
if(array3[i].value == txtbox1.value) {
document.questions.questions3.options[i] = null
}
}
This works fine if both the matches are located at the same value/position in the array. But if one match is at array1[1] and the other match is at array3[7] for example, then only the first match gets deleted and not the second. Is there something I am missing? Any help is appreciated. Thanks!
I don't see too many choices here, considering that the position in each array can vary.
Do it in separate loops, unless of course you repeat values in both arrays and share the same position
EDTI I figured out a simple solution, it may work, create a function. How about a function wich recives an array as parameter.
Something like this:
function finder(var array[], var valueToFound, var question) {
for (i=0; i<array.lenght; i++) {
if (array[i].value == valueToFound) {
switch (question) {
case 1: document.questions.questions1.options[i] = null;
break;
}
return;
}
}
}
I think i make my point, perhaps it can take you in the right direction
My bet is that the code isn't getting to array3[7] because either it doesn't exist or that array2 is too short and you're getting a JavaScript exception that's stopping the code from doing the check. Is it possible that array2 and array3 are shorter than array1?
It is more code, but I would do it like this:
var selectedvalue == txtbox1.value;
for(i=0; i<array2.length; i++) { // iterate over the length of array2, not array1
if(array2[i].value == selectedvalue) {
document.questions.questions2.options[i] = null;
break; // found it, move on
}
}
for(i=0; i<array3.length; i++) {
if(array3[i].value == selectedvalue) {
document.questions.questions3.options[i] = null;
break; // you're done
}
}

How to turn this JavaScript string "myArray[0].myPrice" in to a reference to myPrice?

If I have a string of "myArray[0].myPrice", how do I turn this in to a reference to myPrice?
This is the code context:
binding.value = convert(binding.data[binding.field],
binding.converter, binding.data, elem);
binding.field is what contains "myArray[0].myPrice".
binding.data has a reference to the hierarchical object which has an Array property of myArray, and the first element is an object with a property of myPrice.
EDIT: based on the answers, this worked:
binding.value = convert(eval('(binding.data.' + binding.field + ')'),
binding.converter, binding.data, elem);
Is it good to use eval like this? I thought eval was going away in newer JavaScript?
You can use eval, but here is a better solution:
// The following code results in the same as that scary eval(...)
var data = binding.data,
chain = binding.field.split(/[\.\[\]]+/);
for (var i = 0; data[chain[i]]; i++) {
data = data[chain[i]];
}
// Embrace JavaScript Awesomeness!
A breakdown of what I'm doing here:
In JS any property can be called as object[propertyName].
That includes arrays, i.e. a[3] is the same as a['3'].
Therefore, we split the string using one of the characters: ., [, ]. The + is there because without it if you have a[3].b[3] the ]. will give you an empty
string.
We might get an empty string in the end, but that's not a problem since "" is like false in JS.
You could go further and filter out all the invalid variable names, which in javascript is a name that does not conform to [a-zA-Z_$][0-9a-zA-Z_$]*. But I am not quite sure as to why one would do that...
Well, it ain't exactly pretty, but it doesn't use eval:
var str = 'myArray[0].myPrice';
var parts = str.split(/[\[\].]+/);
doSomething(window[parts[0]][parts[1]][parts[2]]);
where window[parts[0]][parts[1]][parts[2]] is the actual reference. Not sure why you'd have a string version and one loaded into memory, though.
Depending on the current context, this might work:
eval("myArray[0].myPrice")
try
var a = eval("myArray[0].myPrice".split('.')[1]);
However this will probably not work in the context you run it in since myPrice will be referring to window.myPrice which I doubt would be defined as anything.
Your best bet here is to define myArray in a scope that can be accessed from anywhere (such as window.AppNS.Data.myArray) and then use the eval() function to access this.
var a = eval("window.AppNS.Data." + "myArray[0].myPrice")
alert(a) // the contents of myPrice are revealed
Here is something similar to the logic we use in the template engine pure.js
var obj = {
myArr:[
{price:15}
],
anObj:{
prop:'ABC'
}
};
function getRef(o, path){
var props = path.split(/\./),
prop,
isArr = /([^\[]+)(\[(\d+)\])*/,
i = 0, ii = props.length;
while(i < ii){
prop = props[i].match(isArr);
o = o[prop[1]];
if(prop[2]){
o = o[+prop[3]];
}
i++;
}
return o;
}
console.log(getRef(obj, 'myArr[0].price')); // --> 15
console.log(getRef(obj, 'anObj.prop')); // --> ABC

Categories