A proper way to declare an JavaScript Options-Object? - javascript

i wanted to access an API which responses with some JSON. Therefore I want to configure an 'options' object, which stores all the data which are needed to access the api (url, tokens, id, etc.).
The following version works:
var Options = function (token, id) {
this.token = token;
this.id = id;
this.host = 'http://super-cool-api.com/';
this.path = 'api/fetch/id/';
this.url = '' + this.host + this.path + this.id + '?token=' + this.token
};
var options = new Options('abc', 3);
// options.url = "http://super-cool-api.com/api/fetch/id/3?token=abc"
Basically 'options.url' is all I want. But I've tried to declare a more comprehensive form for the 'options' object, like this:
var options = {
token : 'abc',
id : 3,
host : 'http://super-cool-api.com/',
path : 'api/fetch/id/',
url : '' + this.host + this.path + this.id + '?token=' + this.token
};
// options.url = "undefinedundefinedundefined?token=undefined"
Okay, I understood that I have to access the values in options.url somehow else. But how? Is this even common practice?
What about my first solution? Is it recommended to do it this way?
Regards,
Christoph

Unfortunately this in your second example points to the object that contains the code, i.e. NOT options, that is why the variables are undefined. The first solution is fine, as would be:
function makeOptions(token, id) {
var host = 'http://super-cool-api.com/',
path : 'api/fetch/id/';
return {
token: token,
id: id,
host: host,
path: path,
url: '' + host + path + id + '?token=' + token
};
}
Choose what suits you best.

Both ways you show are OK ways of doing this, as for the most accepted / standard way of doing it, I wouldn't really know.
Here is an example of how to get the Second Option you showed to work correctly :
Set the url of options to be a function that builds the URL and returns it.
var options = {
token : 'abc',
id : 3,
host : 'http://super-cool-api.com/',
path : 'api/fetch/id/',
url : function() {
return '' + this.host + this.path + this.id + '?token=' + this.token;
}
};
And then you can retrieve the value using the following : var testUrl = options.url();
Here is an example JSFiddle for both of your examples, plus my example (Option 3)

Related

AngularJs destructuring $location

Instead of using:
const ref = $location.protocol() + '://' + $location.host();
i try to do it like this:
const { protocol, host } = $location;
const ref = protocol() + '://' + host();
but it does not seem to work. ( protocol() is not returning anything, same for host() )
However, if I try something like this:
const loc = {
protocol: function(){
return 'http';
},
host: function(){
return 'example.com';
},
};
const { protocol, host } = loc;
document.write(protocol() + '://' + host());
it works. Any ideea why?
Ps. Some sample here, just uncomment the second line and it would not work anymore.
The destructuring assignment syntax is a JavaScript expression that
makes it possible to unpack values from arrays, or properties from
objects, into distinct variables.
You loose reference to this when you de-structure methods,$location.protocol and protocol refer to different this
let a = {
myName : 'my name',
nameLogger(){
return this.myName
}
}
let {nameLogger} = a
console.log( 'Hello ' + nameLogger())
nameLogger = nameLogger.bind(a)
console.log( 'Hello ' + nameLogger())

Using Firebase, how can I pass a created key to another function?

I'm creating a multiuser app and wanted to use keys to product user information. I created a function that updates the child of a database with a generated key. The following function behaves correctly:
unlist(list) {
var postData = {
state: "unlisted",
};
var newPostKey = firebase.database().ref().child('foods').push().key;
var updates = {};
updates['foods' + '/' + list.$key + '/' + 'state' + '/' + newPostKey] = postData;
return firebase.database().ref().update(updates);}
I have a separate function that works similarly to this:
changestate(item) {
var postData = {
state: "listed",
};
var newPostKey = firebase.database().ref().child('foods').push().key;
var updates = {};
updates['foods' + '/' + item.$key + '/' + 'state' + '/' + newPostKey] = postData;
return firebase.database().ref().update(updates);}
In order to make this work correctly, the key that is created from unlist(list) needs to correspond to var newPostKey in changestate(item) and vice versa. How can I make this work?
cfoster5. What I have understood from your question is that the newPostkey from the unlist function should be passed to the changeState(item) function if that's what you want means you can do that by calling promise in the
firebase.database().ref().update(updates).then(function(){
// You can call changestate function and pass the function like below
_changestate(item,newPostkey);
});
and in your changestate function,
changestate=function(item,passedkey){
var newPostKey = passedkey;
}
See my jsfiddle sample

Get "Missing client_id parameter" error on Facebook login using node.js /express.js

I'm a front end developer trying to do backend stuff using express js, so this might be an easy one.
This is my problem:
I want a user to login using Facebook Social Login.
I have manage to set up the front end part so I have a:
* access_token
* app_id
* app_secret
Now I want to get a refresh-token on my backend, it looks like this:
var app_id = '122345abcd';
var app_secret = '111xxxx';
var accessToken = req.body.accessToken;
var baseURL = 'https://graph.facebook.com';
var url = baseURL + '/oauth/access_token?' +
'grant_type=fb_exchange_token&' +
'client_id=' + app_id + '&' +
'client_secret=' + app_secret + '&' +
'fb_exchange_token=' + accessToken;
request({
url: url,
json: true
}, function(error, response, body) {
console.log(body.error.message);
});
This generates a very nice URL that looks right. It can look like this:
https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&
client_id=122345abcd&
client_secret=111xxxx&
fb_exchange_token=EAACjzsDAL4oBALxjCRB5cTYTIdyTVYyg6z6do4IoN8R9b65dtGR7DCMvLNr4cRjeTxZBH7SGH0PNqLL5wfxf73lGORjkD0ZCP5c6WTkdTnCfvAPUZCTouRtTYY89UAgZAxO8GgGpjzZCSwB7W95YCVHKDKpNrcTH5R93bInV0UQZDZD
But what I get back is this.
"Missing client_id parameter."
What have I missed?
There's clearly and client_id in the url, even though it's the app_id. But that seems to be right.
I have followed this guide:
https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
UPDATE: The guide above say you shall use & in the URL. That is what breaks things. Use & instead.
var url = baseURL + '/oauth/access_token?' +
'grant_type=fb_exchange_token&' +
'client_id=' + app_id + '&' +
'client_secret=' + app_secret + '&' +
'fb_exchange_token=' + accessToken;

Typescript Collections not initialized

Background:
I have a jquery click function which should delete a picture from a model. For that I am sending an ajax request to my controller. To get the URL of this action I wrote an ActionResolver which works similar to the HTML helper of MVC. As you see in the code I used typescript and typescript collections.
My problem now is that as soon as the browser reaches "var routeValues = new collections. Dictionary();" it errors with "Uncaught ReferenceError: collections is not defined". I wrote at the top of the ts file "/// < reference path="typings/collections/collections.ts" />" so I can't figure out why it's not defined.
If anyone has a hint I would really appreciate it as I am just getting started with jscript and typedscript. :)
$(function () {
$(".jsPictureDelete").click(function () {
var controller = $("#Controller").attr('value');
var id = $("#Id").attr('value');
var propertyName = this.id.replace("pictureDeleteBtn", "");
var routeValues = new collections.Dictionary<string, string>();
routeValues.setValue("id", id);
routeValues.setValue("propertyName", propertyName);
var action : Action = new Action("DeletePicture", controller, routeValues);
//var url = '/' + controller + '/DeletePicture/' + id + '?propertyName=' + propertyName;
var url = action.ResolveAction();
$.ajax({
type: "GET",
url: url,
contentType: 'application/json; charset=utf-8',
success: function (returndata : any) {
alert("worked");
}
});
});
});
class Action {
private _controller: string;
private _action: string;
private _routevalues = new collections.Dictionary<string, string>();
constructor(action: string, controller: string, routevalues = new collections.Dictionary<string, string>()) {
this._controller = controller;
this._action = action;
this._routevalues = routevalues;
}
public ResolveAction() : string {
var result: string = "/" + this._controller + "/" + this._action;
var attrib: boolean = false;
if (this._routevalues.containsKey("id")) {
result += "/" + this._routevalues.getValue("id") + "?";
}
Object.keys(this._routevalues).forEach(function (key) {
if (key !== "id") {
result += key + "=" + this._routevalues[key] + "&";
attrib = true;
}
});
if (attrib) {
result = result.substring(0, result.length - 1);
}
return result;
}
}
referencing the collections.ts file only provides intellisense support in the editor.
you have to include that file (js equivalent?) in your webpage too.
You need to compile it with the --out flag.
Reference: https://youtube.com/watch?hd=1&v=KDrWLMUY0R0

jQuery/Javascript - reload current page with an appended querystring?

I've got a dropdown menu on my form, which when something is selected I need to reload the current page, but with an appended querystring.
How would I go about doing this?
This is an old question but it came up first in google search results.
The solution I went with is similar to jAndy's.
window.location.pathname gives me the page's url without the query string.
I'm then able to build the query string with "?"+$.param({'foo':'bar','base':'ball'}) which I then append to the pathname and set to window.location.href.
window.location.href = window.location.pathname+"?"+$.param({'foo':'bar','base':'ball'})
var params = [
"foo=bar",
"base=ball"
];
window.location.href =
"http://" +
window.location.host +
window.location.pathname +
'?' + params.join('&');
That code within your change event handler will do the trick.
For instance:
$('#my_dropdown_id').bind('change', function(){
var params = [
"foo=bar",
"base=" + $(this).val()
];
window.location.href = "http://" + window.location.host + window.location.pathname + '?' + params.join('&');
});
If you go with the top rated answer, you may want to replace
http://
in the code with
window.location.protocol
so that it works for other protocols, like https or file. So
window.location.href = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + params.join('&');
Actually, there a built-in function of location that you can use, the name of the function is assign.
For appending or modifying there is another built-in function of the URL class that you can use too. the name of the function is searchParams.
So for your case you just need below example:
const url = new URL(location.href);
url.searchParams.set('key', 'value');
location.assign(url.search);
Update 2022
I create a TypeScript function to apply redirect with params more easier:
const isClient = (): boolean => typeof window !== 'undefined';
type ParamsType = { [key: string]: string | number };
const redirectUrl = (url: string, params?: ParamsType): void => {
if (isClient()) {
try {
const _url = new URL(url);
if (params) {
const keyList = Object.keys(params);
for (let i = 0; i < keyList.length; i += 1) {
const key = keyList[i];
_url.searchParams.set(keyList[i], params[key]?.toString());
}
}
window.location.assign(_url.href);
} catch (e) {
throw new Error('The URL is not valid');
}
}
};
export default redirectUrl;
If you want a simple way to preserve the query string and possibly append to it, use window.location.search; here's a snippet:
var search = window.location.search + (window.location.search ? "&" : "?");
search += "param1=foo&param2=bar";
window.location.href = window.location.protocol + "//" + window.location.host + window.location.pathname + search;
You can, of course, use a more sophisticated way of building the rest of your query string, as found in the other examples, but the key is to leverage Location.search.
If you have an existing querystring that you'd like to keep then this version does that and adds your new params to any existing ones. The keys are converted to lowercase so that duplicates are not added. Maintaining the quersytring does make the solution more complicated, so I'd only do this if you need to.
$("#sortby").change(function () {
var queryString = getQueryStrings();
// Add new params to the querystring dictionary
queryString["sortby"] = $("#sortby").val();
window.location.href =
window.location.protocol + "//" +
window.location.host +
window.location.pathname +
createQueryString(queryString);
});
// http://stackoverflow.com/questions/2907482
// Gets Querystring from window.location and converts all keys to lowercase
function getQueryStrings() {
var assoc = {};
var decode = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); };
var queryString = location.search.substring(1);
var keyValues = queryString.split('&');
for (var i in keyValues) {
var key = keyValues[i].split('=');
if (key.length > 1) {
assoc[decode(key[0]).toLowerCase()] = decode(key[1]);
}
}
return assoc;
}
function createQueryString(queryDict) {
var queryStringBits = [];
for (var key in queryDict) {
if (queryDict.hasOwnProperty(key)) {
queryStringBits.push(key + "=" + queryDict[key]);
}
}
return queryStringBits.length > 0
? "?" + queryStringBits.join("&")
: "";
}
I was having a requirement to open a particular tab after reloading. So I just needed to append the #tabs-4 to the current url. I know its irrelevant to current post but it could help others who come to this just like I did.
Using the code
window.location = window.location.pathname
+ window.location.search + '#tabs-4';
did'nt work for me but below code did.
location = "#tabs-4";
location.reload(true);

Categories