How to extract partial JSON from API response? - javascript

Load when the browser is open
Thats my previous question related to this topic.
My problem is that the server api i use has added a new item to the list and as i stated in the previous question im not very skilled with API's or jQuery, therefore i would like to know what can you recomend me to read about this and also pratical solutions. I need to make it so the field that the js uses is only {"name":"Arthas","slug":"arthas","build":"12340","status":1} and not the rest.
Many thanks in advance.
This is the api -> http://api.neverendless-wow.com/server-status
{"servers":[{"name":"Arthas","slug":"arthas","build":"12340","status":1},{"name":"Deathwing","slug":"deathwing","build":"13623","status":1}],"alerts":[]}
This is my current js
function checkStatus()
{
jQuery.getJSON("http://api.neverendless-wow.com/server-status",function(data){
if (data.status == '1') {jQuery('#ServStat').addClass('online').removeClass('offline').attr('label','Online');}
else {jQuery('#ServStat').addClass('offline').removeClass('online').attr('label','Offline');}});
}
checkStatus();
{
setInterval(changeState, 300000)
}

You need to use data as array (data[0]) and hence your code will be as follows:
function checkStatus()
{
jQuery.getJSON("http://api.neverendless-wow.com/server-status",function(data){
if (data.servers[0].status == '1') {
jQuery('#ServStat').addClass('online').removeClass('offline').attr('label','Online');
}
else {
jQuery('#ServStat').addClass('offline').removeClass('online').attr('label','Offline');
}
});
}
checkStatus();
{
setInterval(changeState, 300000)
}

I would probably go with something like this:
// check server status
function checkStatus()
{
$.getJSON(server_url, function(data) {
// reset
var mode = "Offline";
$('.status').removeClass('online').addClass('offline');
// is available?
if (data !== null && data.servers !== null && data.servers[0].status === 1) {
mode = "Online";
$('.status').removeClass('offline').addClass('online');
}
// Extract data from received JSON string is exists
extractData(data);
// set needed attributes
$('.status')
.attr('label', mode)
.text('Servers are ' + mode);
});
}
Live demo available on JsBin

Related

API Request Function Clean Up AngularJS

I am doing an API Request using AngularJS that receives current live promotional offers that are available for a certain market. Market's are organized by ADI.
Not all markets will have multiple offers LIVE at any given moment, so I am having trouble distinguishing that. Sometimes there will be 0, 1 or even 2 but that is the most that a market can have live at the same time. If you see my code below you can notice my API call, then based on my response, I go in and get more properties like the expiration date, campaign state, and etc.
So for markets that have one 1 offer live, it gives me an error because it will trying to loop through and find the [1]. How do you recommend cleaning this function up so that I can not have errors if the market does not have multiple live offers.
You will also notice a property is_primary, I want to change that to a boolean value. So if the answer is equals to 1, then make the answer true, so that I can just display that on the front end. If the answer equals to 0 then its false.
$scope.offersNow = function () {
if (offer.campaign_state === 'live') {
var config = { method: 'get', url : $scope.config.url + '/offers/' + $scope.offer.market_adi};
console.log($scope.offer.market_adi);
$http(config).success(function(response, status){
if(status === 200) {
if (response.length > 0) {
response[1].Expiration_Date = moment.utc(response[1].Expiration_Date).format('MM-DD-YYYY');
response[1].isPrimary = response[1].is_primary;
console.log(response[1]);
console.log(response[1].isPrimary);
console.log(response[1].Expiration_Date);
}
console.log(response.length);
response[0].Expiration_Date = moment.utc(response[0].Expiration_Date).format('MM-DD-YYYY');
response[0].isPrimary = response[0].is_primary;
console.log(response[0]);
console.log(response[0].isPrimary);
console.log(response[0].Expiration_Date);
}
else{
alert("Is Not Working");
}
});
}
};
What do you suggest doing at this point that will make my code more efficient and will work in many other cases?
You can use the Array.map function to loop through the response array and add any additional properties. You also don't need to check if the length is greater than 0 with the map function.
$scope.offersNow = function () {
if (offer.campaign_state === 'live') {
var config = { method: 'get', url : $scope.config.url + '/offers/' + $scope.offer.market_adi};
console.log($scope.offer.market_adi);
$http(config).success(function(response, status){
if(status === 200) {
response.map(function(offer, index, arr) {
offer.Expiration_Date = moment.utc(offer.Expiration_Date).format('MM-DD-YYYY');
offer.isPrimary = offer.is_primary;
console.log(offer);
console.log(offer.isPrimary);
console.log(offer.Expiration_Date);
return offer;
}
}
else{
alert("Is Not Working");
}
});
}
};

Calling api client to modify the data of parent api client call

client.post(config.apiUrl+"cart", args, function(data,response) {
if (data.status == 'success') {
for (var key in data.data.cart_items_list) {
if (data.data.cart_items_list.hasOwnProperty(key)) {
data.data.cart_items_list[key].child.prodqty = function () {
client.get(config.apiUrl+"product/"+data.data.cart_items_list[key].child.child_id+"/quantity", function(invdata, invresponse) {
if(invdata.status == 'success'){
console.log(invdata.data);
return invdata.data;
console.log(data.data.cart_items_list[key].child.prodqty);
}
})
}
}
}
console.log(data.data.cart_items_list);
}
})
Above is piece of code I have written to get one modify the data I got from api client call.
The first api call will a json data. I am looping thru that data to get one value from another api and append to parent's json data
console.log(data.data.cart_items_list[key].child.prodqty); line prints the correct value in my logs, but console.log(data.data.cart_items_list); this is not having the newly(child.prodqty) appended value in it.
I am very much new in Node.js so I don't know whether I am doing it correct
EDIT:
if I console.log(data.data.cart_items_list); the output has prodqty in it. but its coming like this. prodqty: [Function]
For default you say that data.data.cart_items_list get prodqty: [Function]. If you get the prodqty value you need to set this value in data.data.cart_items_list, thus you can catch it after the loop. I my opinion, I prefer to create a new var when I set it:
client.post(config.apiUrl+"cart", args, function(data,response) {
var prodqty = {};
if (data.status == 'success') {
for (var key in data.data.cart_items_list) {
if (data.data.cart_items_list.hasOwnProperty(key)) {
data.data.cart_items_list[key].child.prodqty = function () {
client.get(config.apiUrl+"product/"+data.data.cart_items_list[key].child.child_id+"/quantity", function(invdata, invresponse) {
if(invdata.status == 'success'){
console.log(invdata.data);
return invdata.data;
prodqty.key = data.data.cart_items_list[key].child.prodqty; //prodqty associated with his key
console.log(data.data.cart_items_list[key].child.prodqty);
}
})
}
}
}
console.log(JSON.stringify(prodqty));
console.log(data.data.cart_items_list);
}
})
I`ve added a object prodqty. Then I set the prodqty whit his key. I this structure of code there may be a problem. The api use a callback, then when loop finish is posible that the prodqty object doesn´t set the values. For resolve it, You need pass a callback at the second api or wait a time until second api finish:
setTimeout(function(){ console.log(JSON.stringify(prodqty)); }, 3000);` //3 seconds for example

Check if localStorage is available

I know there has been many questions about checking for localStorage but what if someone manually shuts it off in their browser? Here's the code I'm using to check:
localStorage.setItem('mod', 'mod');
if (localStorage.getItem('mod') != null){
alert ('yes');
localStorage.removeItem('mod');
} else {
alert ('no');
}
Simple function and it works. But if I go into my Chrome settings and choose the option "Don't Save Data" (I don't remember exactly what it's called), when I try to run this function I get nothing but Uncaught Error: SecurityError: DOM Exception 18. So is there a way to check if the person has it turned off completely?
UPDATE: This is the second function I tried and I still get no response (alert).
try {
localStorage.setItem('name', 'Hello World!');
} catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
alert('Quota exceeded!');
}
}
Use modernizr's approach:
function isLocalStorageAvailable(){
var test = 'test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch(e) {
return false;
}
}
if(isLocalStorageAvailable()){
// available
}else{
// unavailable
}
It's not as concise as other methods but that's because it's designed to maximise compatibility.
The original source: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js
Working example: http://jsfiddle.net/6sm54/2/
I'd check that localStorage is defined prior to any action that depends on it:
if (typeof localStorage !== 'undefined') {
var x = localStorage.getItem('mod');
} else {
// localStorage not defined
}
UPDATE:
If you need to validate that the feature is there and that it is also not turned off, you have to use a safer approach. To be perfectly safe:
if (typeof localStorage !== 'undefined') {
try {
localStorage.setItem('feature_test', 'yes');
if (localStorage.getItem('feature_test') === 'yes') {
localStorage.removeItem('feature_test');
// localStorage is enabled
} else {
// localStorage is disabled
}
} catch(e) {
// localStorage is disabled
}
} else {
// localStorage is not available
}
Feature-detecting local storage is tricky. You need to actually reach into it. The reason for this is that Safari has chosen to offer a functional localStorage object when in private mode, but with it's quotum set to zero. This means that although all simple feature detects will pass, any calls to localStorage.setItem will throw an exception.
Mozilla's Developer Network entry on the Web Storage API's has a dedicated section on feature detecting local storage. Here is the method recommended on that page:
function storageAvailable(type) {
try {
var storage = window[type],
x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
catch(e) {
return false;
}
}
And here is how you would use it:
if (storageAvailable('localStorage')) {
// Yippee! We can use localStorage awesomeness
}
else {
// Too bad, no localStorage for us
}
If you are using NPM, you can grab storage-available using
npm install -S storage-available
then use the function like so:
if (require('storage-available')('localStorage')) {
// Yippee! We can use localStorage awesomeness
}
Disclaimer: Both the documentation section on MDN and the NPM package were authored by me.
MDN updated the storage detect function. In 2018, it's more reliable:
function storageAvailable() {
try {
var storage = window['localStorage'],
x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
catch(e) {
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
storage && storage.length !== 0;
}
}
Browsers that support localStorage will have a property on the window object named localStorage. However, for various reasons, just asserting that property exists may throw exceptions. If it does exist, that is still no guarantee that localStorage is actually available, as various browsers offer settings that disable localStorage. So a browser may support localStorage, but not make it available to the scripts on the page. One example of that is Safari, which in Private Browsing mode gives us an empty localStorage object with a quota of zero, effectively making it unusable. However, we might still get a legitimate QuotaExceededError, which only means that we've used up all available storage space, but storage is actually available. Our feature detect should take these scenarios into account.
See here for a brief history of feature-detecting localStorage.
With this function you can check if localstorage is available or not, and you keep under control the possible exceptions.
function isLocalStorageAvailable() {
try {
var valueToStore = 'test';
var mykey = 'key';
localStorage.setItem(mykey, valueToStore);
var recoveredValue = localStorage.getItem(mykey);
localStorage.removeItem(mykey);
return recoveredValue === valueToStore;
} catch(e) {
return false;
}
}
It is better to check availability of localStorage in conjunction with cookies, because if cookie is enabled the browser could detect that localStorage is available and type it as object, but provide no possibility to work with it. You use the next function to detect both localStorage and cookies:
const isLocalStorage = () => {
try {
if (typeof localStorage === 'object' && navigator.cookieEnabled) return true
else return false
} catch (e) {
return false
}
}
You can try this method
Anytime validate the content of the localstore
const name = localStorage.getItem('name');
if(name){
console.log('Exists');
}else
{
console.log('Not found');
}
I tried this solution in Chrome, Firefox and Edge and it worked correctly.
if (localStorage.getItem('itemName') === null )
{
// your code here ...
}
if the local variable on localStorage do not exist it will brind false.
You can create a checker function which tries to get a non existing item from the localStorage. When the localStorage is turned on you will normally get null returned. But when the localStorage is turned off an error will be thrown. You don't have to set any item for the checking.
const checkLocalStorage = () => {
try {
localStorage.getItem("x");
return true;
} catch {
return false;
}
}
Modifying Joe's answer to add a getter makes it easier to use. With the below you simply say: if(ls)...
Object.defineProperty(this, "ls", {
get: function () {
var test = 'test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch(e) {
return false;
}
}
});
Here is an easy check:
if(typeof localStorage === 'undefined'){
Use this to check localStorage is set or not. Its help you to get status of Localstorage.
if( window.localStorage.fullName !== undefined){
//action
}else{
}

Can this old-style ajax call be easily done with jquery?

I'm working with some pretty old code and the following is being used to monitor session status. If the user is inactive for X minutes (determined by check_session.php), they are logged out.
The server side stuff works fine. Actually, the existing javascript appears to work OK as well, but looks like it needs cleaning up.
Here's the existing javascript:
function checkSessionStatus()
{
session_http.open('GET', '/check_session.php', true);
session_http.onreadystatechange = handleSessionHttpResponse;
session_http.send(null);
}
function handleSessionHttpResponse()
{
if (session_http.readyState == 4)
{
results = session_http.responseText;
if (results == 'inactive')
{
window.location='/logout.php';
document.getElementById('session_divbox').innerHTML = results;
}
}
}
function get_session_HTTPObject()
{
var xml_session_http;
if (!xml_session_http && typeof XMLHttpRequest != 'undefined')
{
try
{
xml_session_http = new XMLHttpRequest();
}
catch (e)
{
xml_session_http = false;
}
}
return xml_session_http;
}
var session_http = get_session_HTTPObject();
function init_page_header()
{
window.setInterval( 'checkSessionStatus();', 30000);
}
This seems incredibly long for what it is doing.
I am still learning jquery and am able to do some basic ajax calls like this one, which places a returned value in a div:
$(document).ready(function()
{
$('#users_online').load('/show_users_online.php');
var refreshId = setInterval(function()
{
$('#users_online').load('/show_users_online.php');
}, 2000);
$.ajaxSetup({ cache: false });
});
The issue with the first bit of code is that it returns a value of 'inactive', which is then acted on by the client (window redirect).
Is it possible to do this in Jquery without winding up with dozens of lines of code? I may already know how to do this and am not seeing the forest for the trees -- some guidance here is appreciated.
Even if its very vampiric question style, should look like
$.get('/check_session.php', function( data ) {
if( data === 'inactive' ) {
window.location='/logout.php';
document.getElementById('session_divbox').innerHTML = data;
}
});

Casper JS waitForResource with a restful API

We are having a little problem with a functional test with casper.js.
We request the same resource twice, first with the GET and then with POST method.
Now when waiting for the second resource (POST) it matches the first resource and directly goes to the "then" function.
We would like to be able to check for the HTTP method in the "test" function, that way we can identify the resource properly. For now we use the status code (res.status), but that doesn't solve our problem fully, we really need the http method.
// create new email
this.click(xPath('//div[#id="tab-content"]//a[#class="button create"]'));
// GET
this.waitForResource('/some/resource',
function then() {
this.test.assertExists(xPath('//form[#id="email_edit_form"]'), 'Email edit form is there');
this.fill('form#email_edit_form', {
'email_entity[email]': 'test.bruce#im.com',
'email_entity[isMain]': 1
}, true);
// POST
this.waitForResource(
function test(res) {
return res.url.search('/some/resource') !== -1 && res.status === 201;
},
function then() {
this.test.assert(true, 'Email creation worked.');
},
function timeout() {
this.test.fail('Email creation did not work.');
}
);
},
function timeout() {
this.test.fail('Email adress creation form has not been loaded');
});
Or maybe there is a better way to test this scenario? Although since this is a functional test we need to keep all those steps in one test.
You can try to alter the form action url to add some query string, therefore generating a new resource appended to the stack. Could be done this way:
casper.thenEvaluate(function() {
var form = __utils__.findOne('#email_edit_form');
form.setAttribute('action', form.getAttribute('action') + '?plop');
});
That's a hack though, and functional testing should never be achieved that way. Let's hope more information will be added to the response objects in the future.
The res parameter that is passed to the test function has an ID. I created a helper that tests against this ID and blacklists it, so the same resource won't get accepted a second time.
var blackListedResourceIds = [],
testUniqueResource = function (resourceUrl, statusCode) {
return function (res) {
// check if resource was already loaded
var resourceFound = res.url.search(resourceUrl) !== -1;
// check statuscode
if (statusCode !== undefined) {
resourceFound = resourceFound && res.status === statusCode;
}
// check blacklisting
if (!resourceFound || blackListedResourceIds[res.id] !== undefined) {
return false;
} else {
blackListedResourceIds[res.id] = true;
return true;
}
};
};

Categories