How to make JavaScript to change string if it matches another string? - javascript

I need to change country-name to "Deutschland" if API gives "Germany" in return. In all other cases code works good. Can't figure out how to do it.
JS:
<script type="text/javascript">
function runOnLoad() {
$.get("https://api.ipdata.co?api-key=6e6bf80b946bedd9daf3c7f799b44683b22333501994fa8af57ce0fa", function (response) {
country_name = response.country_name;
$("#country_name").text(country_name || 'Deutschland');
}, "jsonp");
}
if(document.readyState === "complete") {
runOnLoad();
} else {
window.addEventListener("onload", runOnLoad, false);
}
</script>
HTML:
<span id="country_name">Deutschland</span>

Use the conditional operator inside .text:
$("#country_name").text(country_name === 'Germany' ? 'Deutschland' : country_name);
Keep in mind that it's not a good idea to implicitly create global variables (it'll even throw an error in strict mode) - best to explicitly declare the country_name variable in the .get callback:
var country_name = response.country_name;
or, in ES6 syntax:
const { country_name } = response;
Or, if you need to have multiple conditions for the name that gets displayed, you can nest the conditional operator (which makes things hard to read), or use if/else:
const displayCountryName = str => $("#country_name").text(str);
// ...
const { country_name } = response;
if (country_name === 'Germany') {
displayCountryName('Deutschland');
} else if (!country_name) {
displayCountryName(/* insert your custom value here */);
} else {
displayCountryName(country_name);
}
Or, in full:
function runOnLoad() {
const displayCountryName = str => $("#country_name").text(str);
$.get("https://api.ipdata.co?api-key=6e6bf80b946bedd9daf3c7f799b44683b22333501994fa8af57ce0fa", function (response) {
const { country_name } = response;
if (country_name === 'Germany') {
displayCountryName('Deutschland');
} else if (!country_name) {
displayCountryName(/* insert your custom value here */);
} else {
displayCountryName(country_name);
}
}, "jsonp");
}
if(document.readyState === "complete") {
runOnLoad();
} else {
window.addEventListener("onload", runOnLoad, false);
}
If you're using jQuery, there's no need to have an if/else check for the readyState - use $ instead:
$(runOnLoad);
Live example:
function runOnLoad() {
const displayCountryName = str => $("#country_name").text(str);
$.get("https://api.ipdata.co?api-key=6e6bf80b946bedd9daf3c7f799b44683b22333501994fa8af57ce0fa", function(response) {
const {
country_name
} = response;
if (country_name === 'Germany') {
displayCountryName('Deutschland');
} else if (!country_name) {
displayCountryName( /* insert your custom value here */ );
} else {
displayCountryName(country_name);
}
}, "jsonp");
}
$(runOnLoad);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="country_name"></div>

Related

parse JSON object with value passed as single quote string

I an getting aws event parameter as follow in the lambda call.
let event = { pathParameters: '{"foo":"35314"}' }
When I am trying to validate the parameter in condition , it cant find foo key on pathParameters
Here my condition check
if (event.pathParameters && event.pathParameters.foo) {
//do something
} else {
console.log('fail');
}
It going in else condition . I tried JSON.parse(JSON.strinify(event)). It did not help. I do get the Object if I do JSON.parse(event.pathParameters).
Any way to resolve the issue on root level object.
No, you can't parse the event to get access to the '{"foo": "35314}'", you need to parse the event.pathParameters value to get the actual foo and its value, 35314
let event = { pathParameters: '{"foo":"35314"}' }
if (event.pathParameters && JSON.parse(event.pathParameters).foo) {
console.log("'foo' =", JSON.parse(event.pathParameters).foo);
} else {
console.log('fail');
}
This is because the data that you are getting has JSON as stringified in pathParameters, so you'll have to parse with that key something like
JSON.parse(event.pathParameters).foo
let event = { pathParameters: '{"foo":"35314"}' } // foo is a string
if (event.pathParameters) {
try {
const { foo } = JSON.parse(event.pathParameters);
// use foo
} catch (jsonError) {
console.log('There was some json parse error', jsonError);
}
} else {
console.log('fail');
}
You need to parse the data from event.pathParameters
function doSomething(event) {
let pathParametersObj = JSON.parse(event.pathParameters);
if (pathParametersObj && pathParametersObj.foo) {
//do something
console.log('pass');
} else {
console.log('fail');
}
}
let event1 = {
pathParameters: '{"foo":"35314"}'
}
let event2 = {
pathParameters: null
}
doSomething(event1);
doSomething(event2);

jQuery each with ajax call will continue before it's finished

I have some jQuery which uses an each loop to go through values entered in a repeated form field on a Symfony 3 CRM. There is a $.post which sends the entered value to a function that checks for duplicates in the database, and if it's a duplicate it adds something to an array, otherwise it adds a blank value to indicate it's not a dupe. Once these have been done, it then checks the final array and adds any errors to the error block to display to the user.
However, it seems that the array is ALWAYS blank and I belivee it's because it's running the code that displays the errors BEFORE it's actually finished getting the response.
Here is my code:
$('#puppy_form').on('submit', function() {
var bitch_errors = [];
var dog_errors = [];
// NOTE: Bitch and dog names need to be checked differently so we know which error is assigned to which input
$('.check_bitch_name').each( function(i, obj) {
// need to check each name for validity and duplication.
var entered_bitch_name = obj.value;
var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
if(!pattern.test(entered_bitch_name)) {
bitch_errors[i+1] = "invalid";
} else {
// now to check for duplicates
$.post('/check-puppy-name', { name: entered_bitch_name }
).done(function (response) {
if(response == 'duplicate') {
bitch_errors[i+1] = "duplicate";
} else {
bitch_errors[i+1] = "";
}
});
}
});
$('.check_dog_name').each( function(i, obj) {
// need to check each name for validity and duplication.
var entered_dog_name = obj.value;
var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
if(!pattern.test(entered_dog_name)) {
dog_errors[i+1] = "invalid";
} else {
// now to check for duplicates
$.post('/check-puppy-name', { name: entered_dog_name }
).done(function (response) {
if(response == 'duplicate') {
dog_errors[i+1] = "duplicate";
} else {
dog_errors[i+1] = "";
}
});
}
});
if(count(bitch_errors) == 0 && count(dog_errors) == 0) {
return true;
}
// loop through the errors and assign them to the correct input
$.each( bitch_errors, function( key, value ) {
if (value == "invalid") {
$('input[name="bitch_name['+key+']"]').parent().addClass('has-error');
$('input[name="bitch_name['+key+']"]').next('.error-message').html('Names must be at least two words, and only contain letters');
return false;
} else if(value == "duplicate") {
$('input[name="bitch_name['+key+']"]').parent().addClass('has-error');
$('input[name="bitch_name['+key+']"]').next('.error-message').html('Sorry, this name has already been taken');
return false;
}
});
$.each( dog_errors, function( key, value ) {
if(value != "") {
if (value == "invalid") {
$('input[name="dog_name['+key+']"]').parent().addClass('has-error');
$('input[name="dog_name['+key+']"]').next('.error-message').html('Names must be at least two words, and only contain letters');
return false;
} else if(value == "duplicate") {
$('input[name="dog_name['+key+']"]').parent().addClass('has-error');
$('input[name="dog_name['+key+']"]').next('.error-message').html('Sorry, this name has already been taken');
return false;
}
}
});
return false;
});
Basically, it first checks that the inputted name is valid, then posts off and checks for dupes. The issue is, even though it does the validity check (and prints errors accordingly) it seems to ignore the dupe check and carry on before it's even called back the first response.
How can I make sure it's finished it's checking before going on and adding the errors to the form? I've tried other solutions including attempting to implement the $.when functionality in jQuery but I don't really understand how to make it work. Any help appreciated.
First, write a function that returns an asynchronous promise to give you a value for one dog:
function checkDog(name) {
var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
if(!pattern.test(name)) {
return $.Deferred().resolve("invalid");
} else {
return $.post('/check-puppy-name', { name: name } )
.then(function (response) {
if (response === 'duplicate') {
return 'duplicate';
} else {
return '';
}
});
}
}
Then you can write one that handles multiple dogs, also returning a promise (which won't itself be resolved until every dog has been checked):
function checkDogs(array) {
return $.when.apply($, array.map(checkDog));
}
Note that there's no DOM-related code yet. You can now write a function that gets the values from a bunch of DOM inputs and returns them in an array:
function getInputValues($selector) {
return $selector.get().map(function(el) {
return el.value;
});
}
So now (on submit) you can check your two sets of inputs and then finally when both of these are available, you can examine the results and update the DOM:
$('#puppy_form').on('submit', function() {
var bitch_names = getInputValues($('.check_bitch_name'));
var dog_names = getInputValues($('.check_dog_name'));
var bitch_promises = checkDogs(bitch_names);
var dog_promises = checkDogs(dog_names);
$.when(bitch_promises, dog_promises).then(function(bitch_errors, dog_errors) {
// update the DOM based on the passed arrays
...
});
});
You are right, ajax calls are like their name says asynchronous. Therefor you can only rely on the .done function. A simple solution would be to initialize a counter variable at the beginning for bitches and dogs and in the according done function you decrement it until it reaches zero. Then, also in the done function, you put an if that calls validation of the error arrays. Here is UNTESTED code to show what I mean:
$('#puppy_form').on('submit', function() {
/*
here you get the initial count for bitches and dogs
*/
var bitch_count = $('.check_bitch_name').length;
var dog_count = $('.check_dog_name').length;
var bitch_errors = [];
var dog_errors = [];
// NOTE: Bitch and dog names need to be checked differently so we know which error is assigned to which input
$('.check_bitch_name').each( function(i, obj) {
// need to check each name for validity and duplication.
var entered_bitch_name = obj.value;
var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
if(!pattern.test(entered_bitch_name)) {
bitch_errors[i+1] = "invalid";
} else {
// now to check for duplicates
$.post('/check-puppy-name', { name: entered_bitch_name }
).done(function (response) {
if(response == 'duplicate') {
bitch_errors[i+1] = "duplicate";
} else {
bitch_errors[i+1] = "";
}
/*
now on every checked name you decrement the counter
and if both counters reach zero you can be sure you
checked all and only now you call your validation
*/
bitch_count--;
if(bitch_count === 0 && dog_count === 0) {
return validateErrors();
}
});
}
});
$('.check_dog_name').each( function(i, obj) {
// need to check each name for validity and duplication.
var entered_dog_name = obj.value;
var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
if(!pattern.test(entered_dog_name)) {
dog_errors[i+1] = "invalid";
} else {
// now to check for duplicates
$.post('/check-puppy-name', { name: entered_dog_name }
).done(function (response) {
if(response == 'duplicate') {
dog_errors[i+1] = "duplicate";
} else {
dog_errors[i+1] = "";
}
/*
same here
*/
dog_count--;
if(bitch_count === 0 && dog_count === 0) {
return validateErrors();
}
});
}
});
}
/*
...and finally all code that should be processed after the ajax calls
*/
function validateErrors() {
if(count(bitch_errors) == 0 && count(dog_errors) == 0) {
return true;
}
// loop through the errors and assign them to the correct input
$.each( bitch_errors, function( key, value ) {
if (value == "invalid") {
$('input[name="bitch_name['+key+']"]').parent().addClass('has-error');
$('input[name="bitch_name['+key+']"]').next('.error-message').html('Names must be at least two words, and only contain letters');
return false;
} else if(value == "duplicate") {
$('input[name="bitch_name['+key+']"]').parent().addClass('has-error');
$('input[name="bitch_name['+key+']"]').next('.error-message').html('Sorry, this name has already been taken');
return false;
}
});
$.each( dog_errors, function( key, value ) {
if(value != "") {
if (value == "invalid") {
$('input[name="dog_name['+key+']"]').parent().addClass('has-error');
$('input[name="dog_name['+key+']"]').next('.error-message').html('Names must be at least two words, and only contain letters');
return false;
} else if(value == "duplicate") {
$('input[name="dog_name['+key+']"]').parent().addClass('has-error');
$('input[name="dog_name['+key+']"]').next('.error-message').html('Sorry, this name has already been taken');
return false;
}
}
});
return false;
});
You could use the async lib to manage these requests and collect the results which will then be passed into the final callback where you can process them.
I haven't tried to run this code but hopefully it will get you close enough if not already there.
async.parallel({
bitch_errors: function(callback) {
var bitch_errors = [];
async.forEachOf($('.check_bitch_name'), function(obj, i, cb) {
// need to check each name for validity and duplication.
var entered_bitch_name = obj.value;
var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
if(!pattern.test(entered_bitch_name)) {
bitch_errors[i+1] = "invalid";
cb();
} else {
// now to check for duplicates
$.post('/check-puppy-name', { name: entered_bitch_name }
).done(function (response) {
if(response == 'duplicate') {
bitch_errors[i+1] = "duplicate";
} else {
bitch_errors[i+1] = "";
}
cb();
});
}
}, function () {
callback(null, bitch_errors);
});
},
dog_errors: function(callback) {
var dog_errors = [];
async.forEachOf($('.check_dog_name'), function(obj, i, cb) {
// need to check each name for validity and duplication.
var entered_dog_name = obj.value;
var pattern = /^[a-zA-Z,.]+\s[a-zA-Z,.]+(\s[a-zA-Z,.]+){0,}$/;
if(!pattern.test(entered_dog_name)) {
dog_errors[i+1] = "invalid";
cb();
} else {
// now to check for duplicates
$.post('/check-puppy-name', { name: entered_dog_name }
).done(function (response) {
if(response == 'duplicate') {
dog_errors[i+1] = "duplicate";
} else {
dog_errors[i+1] = "";
}
cb();
});
}
}, function () {
callback(null, dog_errors);
});
}
}, function(err, results) {
// you can now access your results like so
if(count(results.bitch_errors) == 0 && count(results.dog_errors) == 0) {
// ... rest of your code
});

Meteor call template method from another method

I want to call a method within a method for clientside but I don't know how to handle it, i've tried by calling like myFunction()and this.myFunction() but it is not working... This is my code
Template.decision.rendered = function () {
if ($(".active").length == 0) {
var random = Math.floor(Math.random() * 1000);
var $items = $(".item");
$items.eq(random % $items.length).addClass("active");
}
$.each($(".item"), function (index, value) {
if (Session.get($(this).attr('id'))) {
this.showResults(value.option);
}
});
};
Template.decision.showResults = function($option) {
$('#result').html('Option ' + $option + ' is voted');
};
As you can see I want to call showResults for each item inside rendered callback...
Found it using Template.decision.showResults(); silly me.
I think that a better way depending on what you are trying to do would be either to use a Session variable or a Meteor Method:
Session Variable.
Template.decision.created = function() {
Session.setDefault('showResults', false);
}
Template.decision.rendered = function() {
// [...]
$.each($(".item"), function (index, value) {
if (Session.get($(this).attr('id'))) {
Session.set('showResults', true);
}
});
}
Template.decision.showResults = function() {
return Session.get('showResults');
}
// in your template
<template name="decision">
{{#if showResults}}
<p>Here is the results.</p>
{{/if}}
</template>
Meteor Method.
// On the client.
Template.decision.rendered = function() {
// [...]
$.each($(".item"), function (index, value) {
if (Session.get($(this).attr('id'))) {
Meteor.call('showResults', function(error, result) {
if (!error and result === true) {
$('.class').hide() // It is here that you modify the DOM element according to the server response and your needs.
}
});
}
});
}
// Server-side method
// But, if you want it to react like a stub, put it inside your lib folder.
Meteor.methods({
showResults: function() {
// do your thing
result = true; // let's say everything works as expected on server-side, we return true
return result;
}
});

Calling functions in an async function javascript (Meteor) Getting undefined

The issue seems to be that calling the function vote_ipcheck() and vote_cookie_check() both are throwing an error Uncaught TypeError: undefined is not a function. If I put the contents of the function inside the $.getJSON call then it's not an issue, however calling the function throws that error.
If anyone's got an idea as to why something like this is occurring, it would be great.
if (ip_check) {
$.getJSON("http://smart-ip.net/geoip-json?callback=?", function(data){
console.log(data.host);
var vote_ipcheck = vote_ipcheck(data.host);
var vote_cookie_check = vote_cookie_check();
if (vote_ipcheck && vote_cookie_check) {
Router.go('pollyResults', {_id: id});
} else if (vote_ipcheck == false && vote_cookie_check == false) {
update_poll();
}
});
}
function vote_cookie_check() {
// Handling the cookie business
console.log(ReactiveCookie.list());
if (ReactiveCookie.get('voted')) {
var object_voted = JSON.parse(ReactiveCookie.get('voted'));
if (id in object_voted) {
if (object_voted[id] == true) {
return true;
}
} else {
object_voted[id] = true;
ReactiveCookie.set('voted', JSON.stringify(object_voted), {days: 365});
return false;
}
} else {
var object_voted = {};
object_voted[id] = true;
ReactiveCookie.set('voted', JSON.stringify(object_voted), {days: 365});
return false;
}
}
function vote_ipcheck(ip) {
ip_voted = ip_array.indexOf(ip);
if (ip_voted > -1) {
return true;
}
else {
Polls.update({_id: id}, {$push : {already_voted : ip}});
return false;
}
}
Do not redefine vote_ipcheck and vote_cookie_check in the local scope if you want to use global functions with these names. Give the local variables different names.
var ipcheck = vote_ipcheck(data.host);
var cookie_check = vote_cookie_check();
if (ipcheck && cookie_check) {
Router.go('pollyResults', {_id: id});
} else if (ipcheck == false && cookie_check == false) {
update_poll();
}

Validation function with return value

I have a common validation function
function connect_and_update_destination() {
var flag = true;
// Validate IP
if (!validate_ip_address()) {
alert(protect.lang.enter_valid_ip);
return;
}
if ($('#pjm_alias').val() === '') {
$('#pjm_alias').focus();
alert(protect.lang.enter_alias);
return;
}
if ($('#pjm_auth_name').val() === '') {
$('#pjm_auth_name').focus();
alert(protect.lang.enter_auth_name);
return;
}
if ($('#pjm_auth_password').val() === '') {
$('#pjm_auth_password').focus();
alert(protect.lang.enter_auth_pwd);
return;
}
var ip = $('#pjm_ip1').val()+'.'+$('#pjm_ip2').val()+'.'+$('#pjm_ip3').val()+'.'+$('#pjm_ip4').val();
return establish_connection(ip, $('#pjm_alias').val(), $('#pjm_auth_name').val(), $('#pjm_auth_password').val());
}
After successful validation it always return establish_connection(), My problem is that am calling this connect_and_update_destination() like this,
function first_call(){
connect_and_update_destination();
}
function second_call(){
connect_and_update_destination();
}
When first call i need to return after successful validation establish_connection(), But when ever i called its using second function [second_call()] it should not return establish_connection() insted of return establish_connection() i need to only return . But how can i do this, Means i dont want to enter establish_connection() when ever i call using second_call().
Thanks in advance.
You could do something as simple as passing a variable.
function connect_and_update_destination(establishConnection) {
...
if(!establishConnection)
return;
return establish_connection(ip, $('#pjm_alias').val(), $('#pjm_auth_name').val(), $('#pjm_auth_password').val());
}
function first_call(){
connect_and_update_destination(true);
}
function second_call(){
connect_and_update_destination(false);
}
For a more generic solution, you could pass a callback:
function connect_and_update_destination(callback) {
...
if(typeof callback === 'function') {
return callback(ip);
}
return;
}
function first_call() {
var result = connect_and_update_destination(function(ip) {
return establish_connection(ip, $('#pjm_alias').val(), $('#pjm_auth_name').val(), $('#pjm_auth_password').val());
});
}
function second_call() {
connect_and_update_destination();
}
You could add a parameter to the connect_and_update_destination function:
function connect_and_update_destination(establishConnection) {
var flag = true;
// Validate IP
if (!validate_ip_address()) {
alert(protect.lang.enter_valid_ip);
return;
}
if ($('#pjm_alias').val() === '') {
$('#pjm_alias').focus();
alert(protect.lang.enter_alias);
return;
}
if ($('#pjm_auth_name').val() === '') {
$('#pjm_auth_name').focus();
alert(protect.lang.enter_auth_name);
return;
}
if ($('#pjm_auth_password').val() === '') {
$('#pjm_auth_password').focus();
alert(protect.lang.enter_auth_pwd);
return;
}
if (!establishConnection) {
return;
}
var ip = $('#pjm_ip1').val()+'.'+$('#pjm_ip2').val()+'.'+$('#pjm_ip3').val()+'.'+$('#pjm_ip4').val();
return establish_connection(ip, $('#pjm_alias').val(), $('#pjm_auth_name').val(), $('#pjm_auth_password').val());
}
and then:
function first_call() {
connect_and_update_destination(true);
}
function second_call() {
connect_and_update_destination(false);
}

Categories

Resources