AngularJS undefined function - javascript

I have two angularJS $scope functions inside a main one. When calling the play() function there is an error stating that getPhoneGapPath() is undefined. What is the solution to this
My Code:
function DontAsk($scope){
$scope.getPhoneGapPath = function(){
var path = window.location.pathname;
path = path.substr( 0, path.length - 10 );
return 'file://' + path;
}
$scope.play= function(){
var os = navigator.platform;
if (os=='iPhone'){
var url = "sounds/DontEventAsk.mp3";
}
else{
var url = getPhoneGapPath() + "sounds/DontEventAsk.mp3";
}
var my_media = new Media(url,
// success callback
function() {
console.log("playAudio():Audio Success");
},
// error callback
function(err) {
console.log("playAudio():Audio Error: "+JSON.stringify(err));
});
// Play audio
my_media.play();
}}
Ideally I would want the getPhoneGapPath() to be defined and also outside the main function because I have multiple functions like the DontAsk() one.
Thanks a lot.

var url = $scope.getPhoneGapPath() + "sounds/DontEventAsk.mp3";

There is no getPhoneGapPath function in the scope. You are defining this function as a property of the $scope object, so you should use it accordingly:
$scope.getPhoneGapPath()

Related

How to add a callback to phantomJS onLoadFinished

I'm trying to automate the navigation of some web pages with phantomJS.
What i'm trying to create is a pattern for testing and navigation, so far i got this.
For a moment ignore all the potential null pointers due to empty arrays and such :)
testSuite.js
var webPage = require('webpage');
// Test suite definition
function testSuite(name){
this.name=name;
this.startDate=new Date();
this.tests=[];
this.add=function(test){
this.tests.push(test);
};
this.start=function(){
console.log("Test Suite ["+this.name+"] - Start");
this.next();
},
this.next=function(){
console.log("neeext");
console.log(this.tests.length);
var test=this.tests[0];
this.tests.splice(0,1);
console.log("Test ["+ test.name+"]");
test.execute();
};
}
//Test definition
function test(name,testFunction){
this.name=name;
this.execute=testFunction;
}
module.exports.testSuite=testSuite;
module.exports.test=test;
FirstPageModule.js
var currentPage;
function onPageLoadFinished(status) {
var url = currentPage.url;
var filename='snapshot.png';
console.log("---------------------------------------------------------------");
console.log("Status: " + status);
console.log("Loaded: " + url);
console.log("Render filename:" + filename);
console.log("---------------------------------------------------------------");
if(status == 'success'){
currentPage.render(filename);
}
if(status=='fail'){
console.log("Status: " + status);
}
}
function open(){
currentPage.open("http://localhost:8080");
}
function login(){
var username="topSecretUsername";
var password="topSecretPassord";
currentPage.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js");
currentPage.evaluate(function(user,pass) {
$("#user").val(user);
$("#pass").val(pass);
},username,password);
currentPage.render("page.png");
currentPage.evaluate(function(){
$('#loginButton').click();
});
}
function FirstPage(){
var page = webPage.create();
currentPage=page;
this.testSuite = new testSuite("FirstPageModule");
this.testSuite.add(new test("Open First Page",open));
this.testSuite.add(new test("Login",login));
var onLoadFinished=onPageLoadFinished;
var callNextTest=this.testSuite.next;
currentPage.onLoadFinished=function(status){
onLoadFinished.apply(this,arguments);
callNextTest();
};
page.onConsoleMessage = function(msg) {
console.log(msg);
}
}
module.exports=new FirstPage();
PageTests.js
var firstPage=require('./FirstPageModule.js');
firstPage.testSuite.start();
What i want to do is to have a sequential execution of isolated functions, after each function gets executed, i take a screenshot and call the next function.
But, for some reason, the next method on the testSuite isn't getting called, or the method on the second test isn't getting executed.
What am i doing wrong?
Just make available the logName variable in the "global" scope :
var logName;
function onPageLoadComplete(status){
console.log(status);
// Call the logName function
if(typeof(logName) == "function"){
logName();
}
}
function test(){
var page = webPage.create();
this.name="TestName";
// Update logName value as a function.
logName = function(){
console.log(this.name);
}
page.onLoadFinished = onPageLoadComplete;
}
Primary, it doesn't seems to be related to phantomjs but only plain javascript, i hope that's what you need, otherwise please be more specific with your question.
You can create your own page.get implementation with a callback when a page is fully loaded.
ex: create a file module pageSupport.js
// attach listeners
Object.prototype.listeners = {};
// store and fire listeners
Object.prototype.addEventListener = function(event, callback) {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(callback);
this[event] = function(e) {
if (listeners[event]) {
listeners[event].forEach(function(listener) {
listener.call(null, e);
});
}
}
}
// create a new reference to webpage.open method
Object.prototype._open = Object.open;
// receive an url and
// return a function success that will be called when page is loaded.
Object.prototype.get = function(url) {
return {
success : function(callback) {
this.open(url);
this.addEventListener('onLoadFinished', function(status) {
if (status == 'success') {
return callback(status);
}
});
}.bind(this)
}
}
// export as phantomjs module.
exports.Object = Object;
So you can call this module in your script and uses it as follows:
var page = require('webpage').create();
require('./pageSupport');
page.get('http://stackoverflow.com').success(function(status) {
// Now this callback will be called only when the page is fully loaded \o/
console.log(status); // logs success
});

how to properly handle variable scope in AngularJS

In my AnlgularJS controller, my first order of business is to determine if the app is running in dev, or test.
For that purpoer, I make a call to an api, an an answer back (that part is verified to work).
Depending on the environment, I need to set the value for the $scope.uploadUrl, so my file uploader directive would know which url is to target for its file uploads.
For some reason, by the time the uploader is executed, that url value is lost.
Here is the relevant part of my controller:
$scope.uploadUrl = '';
console.log('This is FileUploadController');
function getEnvironment (){
$http.get('/environment').success(function(response) {
$scope.currentEnvironment = response.environment;
if(response.environment === 'test'){
$scope.uploadUrl = 'http://test_url:3001/api/files';
}
if(response.environment === 'dev'){
$scope.uploadUrl = 'http://dev_url:3000/api/files';
}
console.log('Current Environment is: ' + $scope.currentEnvironment
+ ' so the uploadUrl should be: ' + $scope.uploadUrl);
});
}
getEnvironment();
var selectedCategory;
var selectedDataVersion;
var uploader = $scope.uploader = new FileUploader({
//url: 'http://dctool-lnx.cloudapp.net:3001/api/files',
url: $scope.uploadUrl,
tabName: 'sheet1'
});
What is the proper way to re-structure this code, to make the value, set within my getEnvironment function to live long enough?
For some reason, by the time the uploader is executed, that url value is lost.
Not really, actual reason is by the time uploaded is executed, url value has not been assigned yet because the operation that assigns the value is async (AsycJAX) in nature.
So basically you need to wait for that operation to complete, you can do so by utilizing the promise returned by the operation.
//return promise from the function
function getEnvironment (){
return $http.get('/environment')....
}
//Make a call chain it through and register runUploader
getEnvironment().then(runUploader);
var selectedCategory;
var selectedDataVersion;
function runUploader(){
var uploader = $scope.uploader = new FileUploader({
//url: 'http://dctool-lnx.cloudapp.net:3001/api/files',
url: $scope.uploadUrl,
tabName: 'sheet1'
});
}
I don't think your problem has to do with the life time. The problem I see there is that, when you create your uploader, the AJAX call has not returned yet.
Try this:
$scope.uploadUrl = '';
$scope.uploader;
var selectedCategory;
var selectedDataVersion;
var uploader;
console.log('This is FileUploadController');
function initUploader()
{
uploader = $scope.uploader = new FileUploader({
//url: 'http://dctool-lnx.cloudapp.net:3001/api/files',
url: $scope.uploadUrl,
tabName: 'sheet1'
});
}
function getEnvironment (){
$http.get('/environment').success(function(response) {
$scope.currentEnvironment = response.environment;
if(response.environment === 'test'){
$scope.uploadUrl = 'http://test_url:3001/api/files';
}
if(response.environment === 'dev'){
$scope.uploadUrl = 'http://dev_url:3000/api/files';
}
initUploader();
console.log('Current Environment is: ' + $scope.currentEnvironment
+ ' so the uploadUrl should be: ' + $scope.uploadUrl);
});
}
getEnvironment();

Service function returning empty object

I've got a factory function that won't return a variable I'm trying to set in my controller. I don't get an error though, just the variable won't get set to what it's suppose to.
spApp.factory('SiteService', function ($q){
var rootUrl = window.location.protocol + "//" + window.location.hostname;
var siteMap;
//returns object containing info about all sites within collection
var getSiteMap = function () {
siteMap = {};
var promise = $().SPServices({
operation: "GetAllSubWebCollection",
async: true
});
promise.then(
function (response){
map = {}; //init the map
var web = $(response).find("Web").map(function () {
return $(this).attr('Url');
});
var webTitle = $(response).find("Web").map(function () {
return $(this).attr('Title');
});
// create map
for (var i = 0; i < web.length; i++) {
var item = web[i],
title = webTitle[i],
parts = item.split('/'),
domain = parts.splice(0, 3).join('/'),
current;
if (!map[domain]) map[domain] = {url:domain, title:title ,children:{}};
current = map[domain].children;
for (var index in parts) {
var part = parts[index];
if (!current[part]) {
current[part] = {url:domain+'/'+parts.slice(0,index+1).join('/'), title:title, children:{}};
}
current = current[part].children;
}
}
siteMap = map;
}, function(reason){
alert('FAILED:' + reason);
})
console.log(siteMap);
return siteMap;
}
return{
getSiteMap:getSiteMap
}
});
Try chaining your promises like this:
var getSiteMap = function () {
siteMap = {};
var promise = $().SPServices({
operation: "GetAllSubWebCollection",
async: true
});
return promise.then(function(response){ //return your promise
// all you code
siteMap = map;
return siteMap; //return a value to another .then in the chain
});
}
Use it like this:
SiteService.getSiteMap().then(function(siteMap){
});
The issue you have is that you are working with promises. When you put your console.log outside your then() function, you are logging the variable before it has actually been resolved.
If you put your console.log inside your then() function (after sitemap is assigned), it should show the correct value, but you still won't be able to access it reliably.
I think the simplest way for you to access the siteMap value after it has been populated with data is to pass in a callback function. Eg:
var getSiteMap = function (_callback) {
siteMap = {};
$().SPServices({
operation: "GetAllSubWebCollection",
async: true
}).then(function(response){
// Process the data and set siteMap
// ...
siteMap = map;
// now pass siteMap to the callback
_callback(siteMap);
});
You would then use this in your controller like so:
SiteService.getSiteMap(function(sitemap){
// Do something with your sitemap here
});
Now while this will work, it is just one quick example, and not necessarily the best way. If you don't like callbacks, you could create a second promise that resolves only when siteMap is assigned. Also depending on your use case for getSiteMap(), you may want to cache the value, otherwise the request will be called every time.

Getting a Javascript error that property is not a function

I am struggling to solve this issue. Please look into my code below.
function GenericFormHandler(templateId, webService) {
this.templateId = templateId;
this.webService = webService;
}
GenericFormHandler.prototype.process = function(form, success, failure) {
var request= form.serializeArray();
this.webService(request,
function(data) {
success(data);
},
function(status) {
failure(status);
});
};
I am getting error at this.webService. I am running below function with
function createAccount() {
var form = $("#login");
$(form).validationEngine();
if (!$(form).validationEngine('validate'))
{
return false;
}
var handler = new GenericFormHandler('#template','$.ws.userSignUpRequest');
handler.process(form, function() {
window.location.href = "home.html";
}, function(error) {
});
}
;
I am accessing webService property in method process but it giving me error as property of an object is not a function. How to solve this error?
$.ws.userSignUpRequest is this the reference of the function , then pass it with out the string
var handler = new GenericFormHandler('#template', $.ws.userSignUpRequest);
In your code this.webService is set to a string. A string is not a method which can be called
this.webService(request, ... // you passed the string '$.ws.userSignUpRequest' to this
if $.ws.userSignUpRequest is actually a reference to the webservice (as I suspect it is) then you should pass it directly (without quotes) to the constructor of GenericFormHandler
var handler = new GenericFormHandler('#template',$.ws.userSignUpRequest);

how to determine when a request in completed in mootools?

I am new to moootools and I am creating a Template class,This is my code -
var Template = new Class({
Singleton : true,
template : '',
/* gets the component type template */
get : function(componentType){
var tplUrl = Core.getUrl('backend') + 'response/' + componentType + '/get_template.php',
that = this,
request = new Request({url: tplUrl, method : 'get',onSuccess : function(responseText){
that.template = responseText;
return that;
}}).send();
}
});
What I want to do is this :
var tpl = new Template();
tpl.get('component').setTemplateData({name:'yosy'});
The problem is when I am calling this code :
var tpl = new Template();
console.log( tpl.get('component') );
I am not getting my current Template object,I am getting is 'undefined'.
How I can make this chainable?
You are making an asynchronous call inside the get function. The request may take 100ms, 1s or 10s and by the time the get function finishes and returns, the request will still be pending. Instead what you need to do is, pass a callback function to get and call that on success.
get: function(componentType, successCallback) {
var request = new Request({
..,
onSuccess: successCallback
}).send();
}
Note that you are not returning anything from the get function. One example way to invoke this would be:
tpl.get('component', function(responseText) { alert(responseText); });
Your get function is missing a return value. If you want functions to chain you should return the object itself:
get : function(componentType){
var tplUrl = Core.getUrl('backend') + 'response/' + componentType + '/get_template.php',
that = this,
request = new Request({url: tplUrl, method : 'get',onSuccess : function(responseText){
that.template = responseText;
return that;
}}).send();
return this;
}

Categories