Calling function defined in an object - javascript

I have an object that defines the name and parameters of a function to be called in the click event of a page element.
object_array = [
{
id: "id1",
onclick: "load_file(filename.php);",
},
{
id: "id2",
onclick: "open_url('http://url.com');",
}
];
That information must be retrieved dynamically. I'd like in the click event to call the onclick function for a given object in the array.
$('element').click(function() {
// call object.onclick
});
Seems that eval() is not a good choice. Is there a different way of calling that function?

You should refactor the object_array to:
[{
id: "id1",
action: "load_file",
url: "filename.php"
}, {
id: "id2",
action: "open_url",
url: 'http://url.com'
}];
Then you can call it with:
var actions = {
load_file: function(url) {
...
},
open_url: function(url) {
...
},
...
};
object_array.forEach(function(ob) {
$("#"+ob.id).click(function() {
actions[ob.action](ob.url);
});
});
If you have more complex arguments, you could also deliver an arguments array instead of url and use apply() on the function.
Or, if you just want a lookup-table of functions, use:
var object = {
"id1": function() {
load_file('filename.php');
},
"id2": function() {
open_url('http://url.com');
}
};
$('element').click(function() {
object[this.id]();
});

Here's a working jsfiddle:
http://jsfiddle.net/Zh6Fv/1/
Like so:
object_array = [
{
id: "id1",
// Encapsulate in an anonymous function
onclick: function(){ load_file('filename.php'); },
},
{
id: "id2",
// Encapsulate in an anonymous function
onclick: function(){ open_url('http://url.com'); },
}
];
Then actually bind it it like this ::
$('element').click(obj.onclick);
Presumably you would be using it like this::
object_array.forEach(function(obj){
// Note there is no need to wrap the obj.onclick
// into another anonymous function anymore!
$("#" + obj.id).click(obj.onclick);
});
Here's a working jsfiddle:
http://jsfiddle.net/Zh6Fv/1/

you can declare a function like
onclick : function()
{
action(arguments);
}

Related

How to call method from template in Vue.js?

I have my vue instance:
var testOptions = new Vue({
el: '#testOptions',
methods: {
getURL: function () {
return (window.location.href);
},
testOne: function () {
console.log('!!');
},
testTwo: function () {
console.log('!!!!');
}
},
data: {
shares: [
{ text: 'testOne', icon: 'ico_test1.svg',func: testOne() },
{ text: 'testTwo', icon: 'ico_test2.svg', func: testTwo() },
]
}
});
Is it possible to call my method testOne/testTwo which I pass to shares array like this:
<li v-on:click="share.func" class="test-options__option">
{{share.text}}
</li>
Yes, it is possible.
Instead of calling the function inside each share, just pass the reference to it.
You need to use this. as those are instance functions.
shares: [
{ text: 'testOne' icon: 'ico_test1.svg', func: this.testOne },
{ text: 'testTwo' icon: 'ico_test2.svg', func: this.testTwo },
]
Also, data property should be a Function that returns object (the actual data) and it's a good practice to add that property onto the top of your Vue component.
Fiddle: http://jsfiddle.net/vnef5d4c/11/

unable to access function from another function using this within same object

I have the following:
$scope.option = {
generateID:function(){
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
},
values : [
{id:this.generateId()},
{id:this.generateId()},
{id:this.generateId()},
{id:this.generateId()}
],
markCorrect : function(option){
},
remove:function(option)
{
this.values = this.values.filter(function(value){return value.id!=option.id})
}
}
I always get a this.generateId is not a function error. I am pretty sure that i am missing something fundamental here!
It may be better to store the id generator function in a separate function so it is easier to reference:
function generateId = function() {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
}
$scope.option = {
generateID: generateId,
values : [
{id: generateId()},
{id: generateId()},
{id: generateId()},
{id: generateId()}
],
markCorrect : function(option){
},
remove:function(option)
{
this.values = this.values.filter(function(value){return value.id!=option.id})
}
}
The primary issue is that you're trying to access properties of $scope.option in the middle of declaring it. Try doing something like this instead:
$scope.option = (function () {
function generateId () {
/* logic */
}
return {
values: [
{id: generateId()}
// ...
],
markCorrect: function () {},
remove: function () {}
};
}) ();
This is the 'revealing module pattern', i.e. a function that returns an object forming a closure on some other data or functionality.
There is a typo; rename generateID to generateId.

Meteor: Composite publish to get data from two collections

I try to use reywood:publish-composite. But something I'm doing wrong as I want to load the article-data and the assigned literature-data.
I think my main problem is to set the route correctly to get the data into the variables, which I could use in the template.
Persume I would open /article/BpsCfbhZuoXfEvREG:
publications.js
Meteor.publishComposite('articles', function(){
return {
find: function(){
return Articles.find();
},
children: [{
find: function(article){
return Literature.find({'article.detail.reference': article._id})
}
}]
}
});
router.js
Router.route('/article/:_id', {
name: 'article',
waitOn: function() {
return Meteor.subscribe('articles'); /* correct? */
},
data: function () {
return {
article: Articles.findOne({
_id: this.params._id
}),
references: Literature.find({}) /* guess, this is wrong */
};
}
});
Literature has this structure and I'm looking for reference:
{
"_id" : "YAEYvJ7tvXxTvnFtv",
"article" : [
{
"title" : "Article 1",
"detail" : [
{
"reference" : "BpsCfbhZuoXfEvREG",
"year" : 2000,
}
]
}
]
}
You want to load an individual article? That looks like what you are doing but you are subscribing to all articles. You could pass the parameter to your subscription.
waitOn: function () {
return Meteor.subscribe('article', this.params._id);
}
Secondly, since your Literature is an array of objects, you should use $elemMatch
Meteor.publishComposite('article', function (articleId) {
check(articleId, String);
return {
find: function () {
return Articles.find(articleId);
},
children: [{
find: function (article) {
return Literature.find({
'article.detail': {
$elemMatch: {
'reference': article._id
}
}
});
}
}]
}
});

Nested JavaScript functions

I would like to make nested JavaScript functions as a prove of concept. I found an example and modified it a little to fit my prove of concent:
var t = {
nestedOne: {
nest: function() {
alert('nest');
this.nestedTwo.nest2();
},
nest3: function() {
alert('nest3');
},
nestedTwo: {
nest2: function() {
alert('nest2');
t.nestedOne.nest3();
}
}
}
};
t.nestedOne.nest();
// *** Output is nest, nest2 and nest3 ***
This works, but I wonder why in nest2, I have to call by t.nestedOne.nest3, and not this.nestedOne.nest3, similar to how I call from nest2.
Its all about the context of this
The easiest way to explain, is to make a slight change to your code:
var t = {
nestedOne: {
nest: function() {
console.log('nest',this);
this.nestedTwo.nest2();
},
nest3: function() {
console.log('nest3',this);
},
nestedTwo: {
nest2: function() {
console.log('nest2',this);
t.nestedOne.nest3();
}
}
}
};
t.nestedOne.nest();
The output from the above is
nest Object { nestedTwo={...}, nest=function(), nest3=function()}
nest2 Object { nest2=function()}
nest3 Object { nestedTwo={...}, nest=function(), nest3=function()}
Note that in the second call, this refers to the function, no longer the object.
Now, you can make the following 2 changes
call next2 passing in the context of this:
this.nestedTwo.nest2.call(this);
use this in nest2:
this.nest3();
And all works as expected:
var t = {
nestedOne: {
nest: function() {
console.log('nest',this);
this.nestedTwo.nest2.call(this);
},
nest3: function() {
console.log('nest3',this);
},
nestedTwo: {
nest2: function() {
console.log('nest2',this);
this.nest3();
}
}
}
};
t.nestedOne.nest();
The context of a function call is determined by the object on which the function is called, not the left-most object in the path used to get to it.
this:
this.nestedTwo.nest2();
^^^^^^^^^
not this:
this.nestedTwo.nest2();
^^^^

How do I access a method outside of object while using a constructor function?

I'm trying to get the member ID for a Trello account and then use that member ID in a constructor function to generate boards. My problem is that I can't access the member ID that I return outside of the object I created. How do I access the memberID outside of the TrellloConnect object?
Here is the code:
var TrelloConnect = {
init: function(config) {
this.config = config;
this.doAuthorize();
this.updateLogStatus();
this.bindLogIn();
this.bindLogOut();
this.whenAuthorized();
this.getMemberID();
},
bindLogIn: function() {
this.config.connectButton.click(function() {
Trello.authorize({
type: "redirect",
success: this.doAuthorize,
name: "WonderBoard",
expiration: "never"
});
});
},
bindLogOut: function() {
this.config.disconnectButton.click(function() {
var self = TrelloConnect;
Trello.deauthorize();
self.updateLogStatus();
});
},
doAuthorize: function() {
var self = TrelloConnect;
self.updateLogStatus();
},
updateLogStatus: function() {
var isLoggedIn = Trello.authorized();
this.config.loggedOutContainer.toggle(!isLoggedIn);
this.config.loggedInContainer.toggle(isLoggedIn);
},
whenAuthorized: function() {
Trello.authorize({
interactive: false,
success: TrelloConnect.doAuthorize
});
},
getMemberID: function() {
Trello.members.get("me", function(member) {
console.log(member.id);
return member.id;
});
}
};
TrelloConnect.init({
connectButton: $('#connectLink'),
disconnectButton: $('#disconnect'),
loggedInContainer: $('#loggedin'),
loggedOutContainer: $('#loggedout')
});
function Board(memberID) {
console.log(memberID);
}
var board = new Board(TrelloConnect.getMemberID());
Trello.members.get is an asynchronous function (i.e. it takes a callback instead of returning a value); you'll need to use a callback if you want to do something with the data that it fetches.
If you change getMemberID to take a callback
...
getMemberID: function(callback) {
Trello.members.get("me", function(member){
callback(member.id);
});
}
...
... then you could do something like this:
TrelloConnect.getMemberId(function(id){
new Board(id);
});

Categories

Resources