Storing a function name in object and calling it later - javascript

I am working on a single page application, and I've so far successfully created a system that easily lets me switch between pages, now I think I need a way to call specific functions when opening a certain page.
For each page I have a function declared, for example #page1 has page1_func, #page2 has page2_func and so on.
The pages are all stored in this fashion
var appPages = {
"page1": {
"id": "#page1",
"title": "Page 1 Title",
"callback": page1_func
},
"page2": {
"id": "#page2",
"title": "Page 2 Title",
"callback": page2_func
}
};
There's another function that takes care of the navigation, which when called with fetches the information about that page i.e its title and id to update the DOM.
I also want that function to actually be able to call the functions that's in the page's callback property.
function NavigateToPage( page ) {
..
..
appPages[ page ].callback( "some args" );
}
However this isn't working as I am declaring functions at the end of the script, but as far as I know declare a function at the end or the beginning it doesn't matter, it is always available though in my case the console tells me the page1_func isn't defined.
I need help with a better solution to this problem

This is works though.
const appPages = {
page1: {
id: '#page1',
title: 'Page 1 Title',
callback: page1_fn,
},
page2: {
id: '#page2',
title: 'Page 2 Title',
callback: page2_fn,
}
};
function triggerCallback(page) {
appPages[page].callback('args...');
}
triggerCallback('page1');
function page1_fn(arg) {
document.write(arg);
}
function page2_fn(arg) {
document.write(arg);
}

Related

Read Content from a JSON file to be able to complement my url search within cypress

I'm currently working with some testing files that will be looking into some records that will provide me some data to be able to do a web search. However, I just want to read a specific input from my file. For the same reason, I added the following:
describe('Search', function () {
beforeEach(() => {
cy.login()
cy.fixture('latestLead.json').then(function (lead) {
this.lead = lead
})
it('Convert Lead to an Opportunity', () => {
cy.readFile('cypress/fixture/latestLead.json').then(r => {
r.forEach((item: any) => {
cy.log(item.Id);
});
});
})
})
My json file is the following:
{
"status": 0,
"result": {
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "Lead",
"url": "/services/data/v51.0/sobjects/Test/11111111"
},
"Id": "1111111111111",
"Name": "Andres Test Test"
}
]
}
}
The main issues issue is telling me that 'any' is not right, and my cypress will not run. However, I would like to see if it is a better way to get the 'Id' from my json file. Does anyone have a better idea of how to do this?
I would probably assign the fixture an alias and call that in the tests and have the execution within the cy.get() for the fixture. A few things to note with using fixtures: they are only loaded once, even if data changes.
describe('Search', function () {
cy.fixture('latestLead.json').as('latestLead')
it('Convert Lead to an Opportunity', () => {
cy.get('#latestLead').then((data) => {
var ids = []
data.result.records.forEach((record) => {
ids.push(record.Id)
})
// whatever you need to do with the ids
})
})
})
If you will only ever have the one object in the records array, you could bypass the .forEach() and just reference the variable directly (data.results.records[0].Id).
Also, are you using types anywhere else? I'm not sure why you would set item: any unless you were using types.

How to loop data in different views in ionic

I have five pages with different state. The first page contains object with the format
{
"good": {
"good1": "good",
"good2": "good",
"good3": "good"
},
"bad": {
"bad1": "bad",
"bad2": "bad",
"bad3": "bad"
},
"excellent": {
"excellent1": "excellent",
"excellent2": "excellent",
"excellent3": "excellent"
}
}
this object is saved to localstorage.
This is my codepen where i have tried to show what i really want.The scenario is , good1 value is going to be looping through 4 pages and next time redirect to first page with the next value(ie good2 ) and the next value also goes through the same 4 pages and so on. What i have to do to solve this problem? if i am doing wrong with the object structure, what should be the good approach?
I would recommend that you put your data into a service, then it will be much easier to share it between pages, persist it to local storage and retrieve it.
.factory('amazingData',function() {
var ohYeah = {
'good':{
'good1':'good',
'good2':'good',
'good3':'good'
},
'bad':{
'bad1':'bad',
'bad2':'bad',
'bad3':'bad'
},
'excellent':{
'excellent1':'excellent',
'excellent2':'excellent',
'excellent':'excellent'
}
};
return ohYeah;
})
Now you can use this service and inject it into your controllers:
.controller('homeCtrl',function($scope, amazingData){
$scope.data=amazingData;
})
.controller('pageCtrl',function($scope, amazingData){
$scope.data=amazingData;
})
The data will be the same for all pages.

Limiting fields returned by mongo dynamically

I use Meteor to query a mongo collection. It has for example the following entry:
{
"_id": "uCfwxKXyZygcWQeiS",
"gameType": "foobar",
"state": "starting",
"hidden": {
"correctAnswer": "secret",
"someOtherStuff": "foobar"
},
"personal": {
"Y73uBhuDq2Bhk4d8W": {
"givenAnswer": "another secret",
},
"hQphob8s92gbEMXbY": {
"givenAnswer": "i have no clue"
}
}
}
What I am trying to do now is:
don't return the values behind "hidden"
from the "personal" embedded document only return the values for the asking user
In code it would look something like this:
Meteor.publish('game', function() {
this.related(function(user) {
var fields = {};
fields.hidden = 0;
fields.personal = 0;
fields['personal.' + this.userId] = 1;
return Games.find({}, {fields: fields});
}, Meteor.users.find(this.userId, {fields: {'profile.gameId': 1}}));
}
Obviously this won't work, because MongoDB won't allow mixed includes and excludes. On the other hand, I cannot switch to "specify only the included fields", because they can vary from gameType to gameType and it would become a large list.
I really hope that you can help me out of this. What can I do to solve the problem?
Typical example of where to use the directly controlled publication features (the this.added/removed/changed methods).
See the second example block a bit down the page at http://docs.meteor.com/api/pubsub.html#Meteor-publish.
With this pattern you get complete control of when and what to publish.

Dynamically Load ng-options from API with Angular

I would like to dynamically load select elements from an API request.
Here is my controller:
var myApp = angular.module('myApp',[]).controller('tripCtrl', function($scope){
//Call to API to get people
$scope.people = [
{
"id": 1,
"name": "Joe Hamlet"
},
{
"id": 2,
"name": "Mary Jane"
},
{
"id": 3,
"name": "Tom Lee"
}
];
//Call to API to get the element to load
$scope.selectElement =
{
"Options": "person[dynamicValue] as person[dynamicDisplayName] for person in people",
"DisplayName": "name",
"Value": "id"
};
//Dynamicly load properties
$scope.dynamicValue = $scope.selectElement.DisplayName;
$scope.dynamicDisplayName = $scope.selectElement.Value;
});
HTML:
<select ng-model="selectedPerson" ng-options="{{selectElement.Options}}">
<option value="">Select</option>
</select>
{{selectedPerson}}
I created a JSFiddle trying to accomplish this. http://jsfiddle.net/HB7LU/9493/
I found this question which I was able to implement, but when I tried to set the ng-options from the Element's Options property, it failed to load. When inspected the HTML the code looks to be set properly, but the model binding isn't working.
Edit 12/28/2014:
After updating the Angular version in the original JS Fiddle, it worked properly, however when I expanded to use an actually API, I found another issue with loading ng-options dynamically. Here is the more in depth JS Fiddle: http://jsfiddle.net/zjFp4/330/
Also here is my updated controller. The dataService.getElement() calls a hard coded string, where as the dataService.getElementFromApi() calls the same exact string, just from json-generator (which is the mock API). When inspected the objects set from the API, everything is there, so it must be an issue with the binding in Angular. Any ideas on how to fix this?
function tripCtrl($scope, dataService) {
//Call to API to get people
dataService.getPeople().then(
function (event) {
$scope.people = event;
},
function (s) {
console.log(s); }
);
//Call to API to get the element to load
$scope.selectElement = dataService.getElement();
dataService.getElementFromApi().then(
function (event) {
$scope.apiElement = event;
$scope.dynamicValue = $scope.apiElement.Value;
$scope.dynamicDisplayName = $scope.apiElement.DisplayName;
},
function (s) {
console.log(s); }
);
}

select2: load asynchronous data through promise

What is the best place to load the options for select2 asynchronously. I want the same facility as ajax, but instead of select2 sending an ajax request, it needs to load the values asynchronously from a promise object. Below code works, in which I load the data in query, but which means every keystroke, invocation of select dropdown, it will query the data. so, what is the correct configuration?
code:
var items2 = [
{
"Id": 1,
"Name": "First"
},
{
"Id": 2,
"Name": "Second"
},
{
"Id": 3,
"Name": "Third"
}
];
var names = function () {
var deferred = $q.defer();
$timeout(function () {
deferred.resolve(items2);
}, 200);
return deferred.promise;
};
var query: function (query) {
var results = [];
names().then(function(d){
$.each(d, function(index, item){
results.push({
id: item.Id,
text: item.Name
});
});
query.callback({ results: results });
})
};
Edit
looking at the source, it looks like it only allows either ajax or local for querying data. It would have been ideal if local takes a function which returns the data. Am I on the right track? is there an easy way to patch it?
thanks
// exports
window.Select2 = {
query: {
ajax: ajax,
local: local,
tags: tags
}, util: {
debounce: debounce,
markMatch: markMatch,
escapeMarkup: defaultEscapeMarkup,
stripDiacritics: stripDiacritics
}, "class": {
"abstract": AbstractSelect2,
"single": SingleSelect2,
"multi": MultiSelect2
}
};
Edit2:
'local` indeed accepts a function. but it doesn't play nicely with remote data, as the data is received with a delay (async), drop down is not populated with the new data. I have to close and open the drop-down again. This is not intuitive for the user.
As far I see, select2 invokes an ajax call for each key stroke, and opening the select box. I can get the same behavior using query (with promise) as in the original question. I was expecting select2 loads the data once, then do rest locally (search, and further invocation till any data change). looks like this is not an option. I may just cache my results locally. Better answer welcome.

Categories