How to search in array - javascript

I have JavaScript array contains links something like this:
var urls = ['url1','url2','url3'];
if (urls.indexOf(window.location.hostname) > -1)
{
// do something ...
}
else {
window.location.href = 'redirect url';
}
this code work well, but I tried to convert it to an array of objects like this:
var urls = [
{
'url':'url1'
},
{
'url':'url2'
},
{
'url':'url3'
},
];
if (urls.url.indexOf(window.location.hostname) > -1)
{
// do something ...
}
else {
window.location.href = 'redirect url';
}
But this code is not working!!
How I can convert the first code into array of objects, or how I can search in array?

Easiest solution is to use array.some
if(urls.some(function(item) { return item.url == window.location.hostname;})) {
// do something ...
} else {
window.location.href = 'redirect url';
}
more readably
var found = urls.some(function(item) {
return item.url == window.location.hostname;
});
if(found) {
// do something ...
} else {
window.location.href = 'redirect url';
}

First of all: Both definitions of your urls variable are JSON:
first definition is an array of Strings in JSON notation
second definition is an array of objects, each consisting of one property url as a string.
In order to search through the second one, you need to iterate over the objects array explicitly and compare the property explicitly (as one approach):
var found = false;
for ( var n = 0; n < urls.length; n++ )
{
if ( urls[n].url == window.location.hostname )
{
/// do something
found = true;
break;
}
}
if ( !found )
{
// do something other
}

Or may be
if(urls.map(function(obj){ return obj.url}).indexOf(window.location.hostname)>0){
// do something ...
}
else {
window.location.href = 'redirect url';
}

Using lodash version 4 or later, you could do this:
if (_(urls).map('url').includes(window.location.hostname)) {
// do something...
} else {
window.location.href = 'redirect url';
}

When it comes to arrays of objects you cannot access elements like what you have done in your code. You have to use a loop to travers through the elements or an inbuilt functions like filter,map.Without using inbuilt functions you can do something like this to get your work done.
function to search for a particular url in the array
function findURL(array,url) {
for (var i = 0; i < array.length; i++) {
if (array[i].url == url) {
return i;
}
}
return -1;
}
Put below piece of code where you want to check the condition
var urls = [
{
'url':'url1'
},
{
'url':'url2'
},
];
if(findURL(urls,window.location.hostname) > -1){
//do something ..
}else{
window.location.href = 'redirect url';
}
There are some answers which describe how to apply filter and map methods in your scenario.Therefore I thing i don't want to put those in my answer.
If you use jquery there is a function called grep which returns an array of items found.
var urls = [
{
'url':'url1'
},
{
'url':'url2'
},
];
var result = $.grep(urls, function(e){ return e.url == window.location.hostname; });
if (result.length == 0) { // nothing found
window.location.href = 'redirect url';
} else if (result.length == 1) { // one item found
//do something ..
// you can access the found item by result[0].foo if you want
} else { // multiple items found
}

Related

chrome.webRequest.onBeforeRequest.addListener not blocking an array of urls

I am trying to block an array of urls based on user input. I have the url array in JSON format, but the sites are not actually being blocked when I navigate to them. If I use only one site, instead of an array, it does get blocked successfully. Here is the function.
function addListener(){
chrome.webRequest.onBeforeRequest.addListener(
function(){ return {cancel: true}; },
{
urls: blockedUrls()
},
["blocking"]
);
}
And here is my function blockedUrls.
var blockedUrls = function () {
chrome.storage.sync.get(['block'], function(result) {
if (typeof result.block === 'undefined') {
//blocks is not yet set
var jobj = ["*://www.whatever.com/*"];
return [jobj[0]];
console.log("not set");
}
else{
var xt = JSON.parse(result.block);
console.log(JSON.stringify(xt.urls));
return JSON.stringify(xt.urls);
}
});
return ["*://www.whatever.com/*"];
}
The console.log does print out what I want, which is this (some were just used for testing obviously)
["doesntexist.com","*://www.yahoo.com/*","*://www.xbox.com/*","*://www.hello.com/*","*://www.es/*"]
And, if it helps, here is where the sites get initially set into chrome storage, from the variable request.newSites.
var jsonStr = '{"urls":["doesntexist.com"]}';
var obj = JSON.parse(jsonStr);
//add url matching patterns to the urls from user input
for (var i = 0; i < request.newSite.length; i++){
obj['urls'].push( '*://www.' + request.newSite[i] + '/*');
}
jsonStr = JSON.stringify(obj);
chrome.storage.sync.set({'block': jsonStr}, function(){
addListener();
});
Thanks in advance.
There are a couple of problems with your code:
1) chrome.storage.sync.get's callback function is asynchronous. Therefore, in your function blockedUrls the return value will always be ["*://www.whatever.com/*"], because the line return ["*://www.whatever.com/*"]; will run before chrome.storage.sync.get's callback function.
2) The second argument of chrome.webRequest.onBeforeRequest listener should be an object in the following form:
{urls: theUrls} where theUrls is an Array of strings, not a string.
Apart from that, you can take advantage of the fact that chrome.storage can store objects and arrays directly, so there is no need to stringify them.
Try with:
var obj = {urls: ['*://doesntexist.com/*']};
for (var i = 0, j = request.newSite.length; i < j; i++){
obj.urls.push( '*://www.' + request.newSite[i] + '/*');
}
chrome.storage.sync.set({block: obj}, function(){
addListener();
});
function addListener() {
chrome.storage.sync.get('block', function (result) {
var myUrls = result.block || ["*://www.whatever.com/*"];
chrome.webRequest.onBeforeRequest.addListener(function(){
return {cancel: true}
},
{urls: myUrls},
["blocking"] );
});
}
chrome.storage.sync.get is an asyncronous function. Therefor it will not return your url list.
What you probably meant to do was the following:
function addListener(){
chrome.storage.sync.get(['block'], function(result) {
let urls;
if (typeof result.block === 'undefined') {
//blocks is not yet set
var jobj = ["*://www.whatever.com/*"];
urls = [jobj[0]];
console.log("not set");
}
else{
var xt = JSON.parse(result.block);
console.log(JSON.stringify(xt.urls));
urls = JSON.stringify(xt.urls);
}
chrome.webRequest.onBeforeRequest.addListener(
function(){ return {cancel: true}; },
{
urls: urls
},
["blocking"]
);
});
}

JSON.stringify not making proper json

I am making an API service to send data to my API endpoint but I'm having a bit of trouble with it.
function getStockLevel(articleCodes) {
var ajaxCallData = [], stockLevels = [];
articleCodes.forEach(function(articleCode) {
if (isLocalStorageSupported() === true) {
if (localStorage.getItem(articleCode) === null) {
ajaxCallData.push(articleCode);
} else {
var localData = JSON.parse(localStorage.getItem(articleCode));
if ((Date.now() / 1000) >= localData['timestamp']) {
ajaxCallData.push(articleCode);
} else {
stockLevels[articleCode] = localData['stock'];
}
}
} else {
ajaxCallData.push(articleCode);
}
});
if (typeof ajaxCallData !== 'undefined' && ajaxCallData.length > 0) {
var article_codes = JSON.stringify(ajaxCallData);
$.ajax({
url : url,
dataType : 'json',
type : 'POST',
contentType : 'application/json',
data : {
article_codes : article_codes
},
success : function(result) {
console.log(result);
for (var code in result) {
if (result.hasOwnProperty(code)) {
var stockLevel = result[code];
stockLevels[code] = stockLevel;
if (isLocalStorageSupported() === true) {
var localStorageData = [];
localStorageData['stock'] = stockLevel;
localStorageData['timestamp'] = (Date.now() / 1000) + 120;
localStorage.setItem(code, JSON.stringify(localStorageData))
}
}
}
}
});
}
}
var codes = [40200, 40201];
var result = getStockLevel(codes);
I am using Ajax and jQuery to send an array of integers to my endpoint but if I check the data that's coming into my endpoint it returns: article_codes=%5B40200%2C40201%5D instead of the json I am expecting.
If I pass the ajaxCallData directly to the data property of the ajax call I get the same result except both values have the same key like so:
article_codes=40200&article_codes=40201
Any help would be appreciated.
data : ajaxCallData
Try Passing it in like this.
ajaxCallData already was an object with the articles_codes set as a key.
You don't need to JSON.stringify it at all.
I found the solution.
Balthasar was pretty close actually.
I needed to set the data like so data : article_codes
I now get the proper data in my endpoint controller.
Thanks for the help everyone!

Check if url hash exists

I want to check if there is a hash in the url :
This should return true:
domain.com/balbla#hash
This should return false:
domain.com/balbla
So I use URI.js to grab the hash
var uriFragment = new URI(window.location.href).fragment();
if (uriFragment.length) {
console.log('yep')
} else {
console.log('nope')
}
But that never returns nope even if there is no hash in the url.
Why not using directly location.hash
if(location.hash.length > 0) {
console.log('yep')
}else {
console.log('nop')
}
Below code will give the list of hash tags in array format.
var hash = window.location.hash;
return result = hash.split('#').reduce(function (result, item) {
var parts = item.split('=');
result[parts[0]] = parts[1];
return result;
}, {});

JSON object and string function

I am trying to call startsWith() string function on a JSON property value:
{"message":"xyzabc"}
var jsonResponse = JSON.parse(httpResponse.text);
var stringMessage = jsonResponse.message.toString();
if(stringMessage.startsWith('xyz')) {
...
}
but I get the error:
Object xyzabc has no method 'startsWith'
How can I do that?
The code is running on server side, Express on Node.js
It may be happen that your browser does not support the startsWith() function so you can use use the RegExp to overcame this problem like this...
var jsonObject={message:"xyzHELLO"};
var regex=new RegExp("^xyz");
if(regex.test(jsonObject["message"])){
alert("hello");
}
Live Demo HERE
[EDIT]
If you want to add the function startsWith() in your each and every string than you can add like this
if (String.prototype.startsWith !== "function") {
String.prototype.startsWith = function (searching) {
var regex = new RegExp("^" + searching);
if (regex.test(this.toString())) {
return true;
}
else {
return false;
}
}
}
and after that you can use like this:
var jsonObject = { message: "xyzHELLO" };
if (jsonObject["message"].toString().startsWith("xyz")) {
alert("start with");
}
else {
alert("not start with");
}
[EDIT]
if (String.prototype.startsWith !== "function") {
String.prototype.startsWith = function (searching) {
if (this.toString().indexOf(searching) == 0) {
return true;
}
else {
return false;
}
}
}
As per the comment by #nnnnnn and I also think it is good practice if we use the native function of the JavaScript, Thanks #nnnnnn.
Please double check your input JSON. Your code works like a charm with a correct JSON input in httpResponse.text.
var json = '{"message": "xyztest"}';
var jsonResponse = JSON.parse(json);
var stringMessage = jsonResponse.message.toString();
if(stringMessage.startsWith('xyz')) {
alert('It works!');
}
Also please make sure the browser you are working in supports startsWith method. Here you can find a list with all supported browsers.
If you need to work around the browser compatibility issues, you can use the widely supported indexOf method.
if(stringMessage.indexOf('xyz') === 0) {
alert('It works!');
}
HERE is a Fiddle for both cases.
Apparently, Js has startsWith function for the strings. However, using your own function to see if the string starts with the value should cause no error.
function StartsWith(s1, s2) {
return (s1.length >= s2.length && s1.substr(0, s2.length) == s2);
}
var jsonResponse = JSON.parse(httpResponse.text);
var stringMessage = jsonResponse.message.toString();
if(StartsWith(stringMessage,'xyz')) {
//Doing Stuff!
}

get object data , load 2 condition the same time

var id = "displayImage1";
//my object
var json = {
displayImage1: {
object: "style1"
},
displayImage2: {
object: "style2"
},
displayImage3: {
object: "style3"
}
};
function JsonLoad(_id){
checkImgCanvas = _id;
for (var i in json) {
if(i === checkImgCanvas){
alert("yes got it");
}else{
alert("not object found");
}
}
}
i am using this function to check if any json object value match the id value , if yes load "yes got it" else load "not object found". i do get the match but it also load "not object found" 2 times , i have no idea why ? it should not load the else condition cause i have match in my json object.
how do i make this function if match load "yes" if no load else condition.(load once)
Demo
Since your for loop executes even after you found your result, you are getting the "no object found" message. You should exit your loop once you found your desired result and to achieve that, you can use break; after your success alert message
function JsonLoad(_id){
var matchFound = false;
for (var i in json) {
if(i === _id) {
matchFound = true;
break;
}
}
if(matchFound) {
alert("yes got it");
}else{
alert("not object found");
}
}
You can use Array.prototype.some()
The some() method tests whether some element in the array passes the test implemented by the provided function.
var json = { displayImage1: { object: "style1" }, displayImage2: { object: "style2" }, displayImage3: { object: "style3" } };
function JsonLoad(_id) {
!Object.keys(json).some(function (k) {
if (k === _id) {
document.write('yes got it<br>')
return true;
}
}) && document.write('not object found<br>');
}
JsonLoad('displayImage0');
JsonLoad('displayImage1');

Categories