Dynamic arrays in Javascript/JQuery - javascript

Why does my array length always come out to 0 even though var email is equal to a string. (I've alerted out var email and the data is there).
var emails = new Array();
//get all the emails
$('.emailBox input').each(function (i)
{
var email = $(this).val();
if(email != '')
{
emails[email] = email;
alert(emails.length);
}
});

Because you're adding a property to the array.
var a = [];
a.foo = 42;
a.length === 0; // true
Instead try
emails.push(email);
This is the same as emails[emails.length] = email
As an aside:
var emails = new Array();
Is bad. You should be using [] instead of new Array() mainly because it's more terse and readable.
if (email != '') {
The above can be replace with if (email) { in case jQuery ever returns undefined or null
To make the entire code more elegant you should use
var emails = $('.emailBox input').map(function() {
return this.value;
}).filter(function (k, v) { return v; }).get();
Or without jQuery
var emails = [].map.call(document.querySelectorAll(".emailBox input"), function (v) {
return v.value;
}).filter(function (v) { return v; });
Although you'll need a QSA shim and a ES5 shim for legacy platform support.
Edit:
If you want the array to be unique then reduce it.
var arr = arr.reduce(function (memo, val, key, arr) {
// if the first index of the value is the index then add it.
// if the first index is different then we already have it.
if (arr.indexOf(val) === key) {
memo.push(val);
}
return memo;
}, []);

You could do all of that using a few jQuery methods.
var emails = $('.emailBox input')
.map(function() { return $(this).val() || null; })
.get();
jsFiddle.

emails[email] = email isn't doing what you want it to do. Try
emails.push(email);

Related

How to get value from one of several possible URL parameters?

I want to retrieve values form url parameters, but the parameters are not constant: it can be "referer=" or "utm_source=" or "source=".
I can get the value with
url.searchParams.get("referer");
Complete script for now :
function() {
var url_string = window.location.href;
var url = new URL(url_string);
var ref = url.searchParams.get("referer");
if (ref == undefined) {
return "No Referer";
} else {
return ref;
}
}
Can I include some regex like:
var ref = url.searchParams.get.match(/referer|source|utm\_source/g);
Can I include some regex
No. That isn't a feature of get.
You can use a set of ||s:
var ref = url.searchParams.get("referer") || url.searchParams.get("source") || url.searchParams.get("utm_source");
Or take an array of key names, map them to the values in the URL, filter out any which don't have a value, then take the first (and presumably only) value off the array.
var possible_key_names = ["referer", "source", "utm_source"];
var ref = possible_key_names
.map(name => url.searchParams.get(name))
.filter(value => !!value)
.shift();
You can loop over the searchParams like so:
var url = new URL("https://example.com/page?referer=&utm_source=google");
var value;
for (var [key, val] of url.searchParams) {
if (key.match(/^(referer|source|utm_source)$/) && val !== "") {
value = val;
break;
}
}
console.log(value);

Perform conditional map join

I have to join an array of javascript object property, but to add the property value to the string I have to check if another property is not undefined or false:
What I do now:
var out = [];
$scope.grid.dataSource.data().map(function (user) {
if (angular.isDefined(user.Selected) && user.Selected == true)
out.push(user.UserPersonID);
});
var ids = out.join(",");
I'd like do something like this:
var ids = $scope.grid.dataSource.data().map(function (user) { if (user.Selected) return user.UserPersonID; }).join(",");
But if the user.Selected is not true I'll obtain a long list of , ('123,,,234,,,').
How can I get the same result without using the out array?
You're looking for the Array filter method:
var out = $scope.grid.dataSource.data().filter(function(user) {
return angular.isDefined(user.Selected) && user.Selected;
}).map(function (user) {
return user.UserPersonID;
});

Syntax problems. Knockout. For filtering

I'm working with jquery, Json data and knockout. What i did is to get a data, add to binded table and a filter field for name.
The thing is, that filter field works not as i want it to work. Because it matches the whole word. That is the code:
self.filter = ko.observable();
self.tickets = ko.computed(function () {
var filter = self.filter(),
arr = [];
if (filter) {
ko.utils.arrayForEach(self.ticketViewModel(), function (item) {
if (item.Name() == filter || item.Status() == filter) {
arr.push(item);
}
});
} else {
arr = self.ticketViewModel();
}
return arr;
});
So i'm trying to make that it would start filtering from the first letter. And i found several methods, which should work, but i can't get the result because i always get various errors of syntax. Maybe who have used these could help me out. The code for it:
self.filter = ko.observable().toString().toLowerCase();
self.tickets = ko.computed(function () {
var filter = self.filter(),
arr = [];
if (!filter) {
arr = self.ticketViewModel();
} else {
ko.utils.arrayFilter(self.ticketViewModel(), function (item) {
if (ko.utils.stringStartsWith(item.Name().toLowerCase()), filter)
arr.push(item);
})
}
return arr;
});
The last error i got was - Uncaught TypeError: string is not a function on line
var filter = self.filter()
The same error i got a few times, but after fixing that i get another ones when usually i get back to it again... And sorry for my english.
I can post the whole code if needed.
Managed to find an answer myself, finally.
Instead of using ko.util.stringStartsWith(), i'm using a simple Javascript checking. And it works perfectly. Maybe it will be useful for someone.
self.filterName = ko.observable('');
self.filterCompany = ko.observable('');
self.filterStatus = ko.observable('');
self.tickets = ko.computed(function () {
return ko.utils.arrayFilter(self.ticketViewModel(), function (rec) {
return (
(
(self.filterName().length == 0 || (rec.Name().toLowerCase().indexOf(self.filterName().toLowerCase()) > -1)) &&
(self.filterCompany().length == 0 || (rec.CompanyName().toLowerCase().indexOf(self.filterCompany().toLowerCase()) > -1)) &&
(self.filterStatus().length == 0 || (rec.Status().toLowerCase().indexOf(self.filterStatus().toLowerCase()) > -1))
)
)
});
});

Emberjs: Paginating Fixture Data

I'm building a search box that filters through records and looks for any entity that has the specified number in the searchBy category:
MyApp.SearchController = Em.ObjectController.extend({
searchTerm: "",
searchBy: "id",
searchFor: "customer",
results: function(){
if(this.get('searchTerm') !== ""){
var searchObj = {};
searchObj[this.get('searchBy')] = this.get('searchTerm');
var that = this;
return this.store.all(this.get('searchFor'))
.filter(function(entity){
return ('' + entity.get(that.get('searchBy'))).indexOf(that.get('searchTerm')) != -1;
});
} else return [];
}.property('searchTerm', 'searchBy', 'searchFor'),
...
});
However there is a large CPU spike as soon as i hit '1' as it will filter through every record and check each id.
Is there a way to limit the filter so that it only returns the first 10 matches?
There are a few things you can do, first off, throttling/debounce should probably be used here, http://emberjs.com/api/classes/Ember.run.html#method_debounce. Here's an example of debouncing, start typing, it won't start searching until you've stopped typing for at least 500 ms. http://emberjs.jsbin.com/covovaye/2/edit
You don't need to call all, then filter, just call filter and send it a function as the filter. Additionally you can save quite a few calls to get by getting searchBy and searchTerm, then using those variables over and over, instead of calling get over and over.
results: function(){
if(this.get('searchTerm') !== ""){
var searchObj = {},
searchBy = this.get('searchBy'),
searchTerm = this.get('searchTerm');
searchObj[searchBy] = searchTerm;
var that = this;
return this.store.filter(this.get('searchFor'), function(entity){
return ('' + entity.get(searchBy)).indexOf(searchTerm) != -1;
});
} else return [];
}.property('searchTerm', 'searchBy', 'searchFor')
If you really wanted to get the first 10 you could use slice
results: function(){
if(this.get('searchTerm') !== ""){
var searchObj = {},
searchBy = this.get('searchBy'),
searchTerm = this.get('searchTerm');
searchObj[searchBy] = searchTerm;
var that = this;
return this.store.all(this.get('searchFor'))
.toArray()
.slice(0,10)
.filter(function(entity){
return ('' + entity.get(searchBy)).indexOf(searchTerm) != -1;
});
} else return [];
}.property('searchTerm', 'searchBy', 'searchFor')

Why can't jQuery update array data before ajax post?

I am trying to create an array and get all values of a form submission and put them in that array. I need to do this because during the .each function of this code I must do additional encryption to all the values per client. This is a form with hundreds of fields that are changing. So it must be an array to work. I tried to do following and several other types like it in jQuery but no dice. Can anyone help? Thanks.
Edit: Posted my working solution. Thanks for the help.
Edit 2: Accept sabithpocker's answer as it allowed me to keep my key names.
var inputArray = {};
//jQuery(this).serializeArray() = [{name: "field1", value:"val1"}, {name:field2...}...]
jQuery(this).serializeArray().each(function(index, value) {
inputArray[value.name] = encrypt(value.value);
});
//now inputArray = [{name: "field1", value:"ENCRYPTED_val1"}, {name:field2...}...]
//now to form the POST message
postMessages = [];
$(inputArray).each(function(i,v){
postMessages.push(v.name + "=" + v.value);
});
postMessage = postMessages.join('&');
Chack serializeArray() to see the JSON array format.
http://jsfiddle.net/kv9U3/
So clearly the issue is that this in your case is not the array as you suppose. Please clarify what this pointer refers to, or just verify yourselves by doing a console.log(this)
As you updated your answer, in your case this pointer refers to the form you submitted, how do you want to iterate over the form? what are you trying to achieve with the each?
UPDATE
working fiddle with capitalizing instead of encrypting
http://jsfiddle.net/kv9U3/6/
$('#x').submit(function (e) {
e.preventDefault();
var inputArray = [];
console.log(jQuery(this).serializeArray());
jQuery(jQuery(this).serializeArray()).each(function (index, value) {
item = {};
item[value.name] = value.value.toUpperCase();
inputArray[index] = item;
});
console.log(inputArray);
postMessages = [];
$(inputArray).each(function (i, v) {
for(var k in v)
postMessages[i] = k + "=" + v[k];
console.log(i, v);
});
postMessage = postMessages.join('&');
console.log(postMessage);
return false;
});
The problem is that #cja_form won't list its fields using each. You can use serialize() instead:
inputArray = jQuery(this).serialize();
Further edition, if you need to edit each element, you can use this:
var input = {};
$(this).find('input, select, textarea').each(function(){
var element = $(this);
input[element.attr('name')] = element.val();
});
Full code
jQuery(document).ready(function($){
$("#cja_form").submit(function(event){
$("#submitapp").attr("disabled","disabled");
$("#cja_status").html('<div class="cja_pending">Please wait while we process your application.</div>');
var input = {};
$(this).find('input, select, textarea').each(function(){
var element = $(this);
input[element.attr('name')] = element.val();
});
$.post('../wp-content/plugins/coffey-jobapp/processes/public-form.php', input)
.success(function(result){
if (result.indexOf("success") === -1) {
$("#submitapp").removeAttr('disabled');
$("#cja_status").html('<div class="cja_fail">'+result+'</div>');
}
else {
page = document.URL;
if (page.indexOf('?') === -1) {
window.location = page + '?action=success';
}
else {
window.location = page + '&action=success';
}
}
})
.error(function(){
$("#submitapp").removeAttr('disabled');
$("#cja_status").html('<div class="cja_fail"><strong>Failed to submit article! Check your internet connection.</strong></div>');
});
event.preventDefault();
event.returnValue = false;
return false;
});
});
Original answer:
There are no associative arrays in javascript, you need a hash/object:
var input = {};
jQuery(this).each(function(k, v){
input[k] = v;
});
Here is my working solution. In this example it adds cat to all the entries and then sends it to the PHP page as an array. From there I access my array via $_POST['data']. I found this solution on http://blog.johnryding.com/post/1548511993/how-to-submit-javascript-arrays-through-jquery-ajax-call
jQuery(document).ready(function () {
jQuery("#cja_form").submit(function(event){
jQuery("#submitapp").attr("disabled","disabled");
jQuery("#cja_status").html('<div class="cja_pending">Please wait while we process your application.</div>');
var data = [];
jQuery.each(jQuery(this).serializeArray(), function(index, value) {
data[index] = value.value + "cat";
});
jQuery.post('../wp-content/plugins/coffey-jobapp/processes/public-form.php', {'data[]': data})
.success(function(result){
if (result.indexOf("success") === -1) {
jQuery("#submitapp").removeAttr('disabled');
jQuery("#cja_status").html('<div class="cja_fail">'+result+'</div>');
} else {
page = document.URL;
if(page.indexOf('?') === -1) {
window.location = page+'?action=success';
} else {
window.location = page+'&action=success';
}
}
})
.error(function(){
jQuery("#submitapp").removeAttr('disabled');
jQuery("#cja_status").html('<div class="cja_fail"><strong>Failed to submit article! Check your internet connection.</strong></div>');
});
event.preventDefault();
event.returnValue = false;
});
});

Categories

Resources