calling a function from view and controller - angularjs

Fairly new to angular so I think I'm missing something simple. I have a function that I need to call from both a view and within the controller. From the view I give the option to continue or start over so I have two functions declared as below. both buttons in the view work fine this way.
$scope.start_new = function(){
//logic in here
}
$scope.continue_work = function(){
//logic in here
}
My problem is if it's the first time through I don't want to give the option so I have
//if the variable doesn't exist run the init
if(angular.isUndefined($localStorage.testVar)){
//I've tried these ways
//start_new();
//$scope.start_new;
//$scope.start_new();
}
else{
$scope.active = false; //disply the layer which gives the choice
}
none of these fire the function. If I declare it like this:
function start_new(){
//logic in here
}
it runs fine on the controller load but the button in the view no longer works. The button code looks like this:
<button type="button" ng-click="start_new()" class="btn btn-info btn-lg btn200">Start New</button>
Any help would be greatly appreciated!!
here is the actual code:
stControllers.controller('WorkoutCtrl',['$scope','$routeParams','$localStorage','$filter','$location','Flash',function ($scope,$routeParams,$localStorage,$filter,$location,Flash) {
//set up counter background
$scope.strokeWidth = 20;
$scope.stroke = '#71d2f3';
$scope.background = '#eee';
$scope.size = 205;
$scope.show_list = false;
$scope.active = true;
if(angular.isUndefined($localStorage.currentWorkout)){
//set up current workout
$scope.start_workout();
}
else{
$scope.active = false;
}
$scope.start_workout = function(){
$scope.active = true;
$scope.currentWorkout = $localStorage.userProgramTemplate[$routeParams['day_id']];
$scope.setCount = $localStorage.setCounterTotal[$routeParams['day_id']];
$localStorage.currentWorkout = $localStorage.userProgramTemplate[$routeParams['day_id']];
//set up the workout detail
$scope.workoutName = $localStorage.userProgramDay[$routeParams['day_id']]['program_day_name'];
$scope.workoutDate = new Date();
//workout progress circle
$scope.currentSet = 1
$scope.progress = $scope.currentSet/$scope.setCount;
//start at first group
$scope.workoutIndex = 0;
$scope.groupCounter = 0;
//start at first exercise
$scope.exerciseIndex = 0;
$scope.currentExerciseSet = 1;
$scope.exerciseCounter = {};
$scope.currentExercise = $scope.currentWorkout[$scope.workoutIndex][$scope.exerciseIndex];
$scope.exerciseCounter[$scope.currentExercise.user_workout_group_id] = {};
$scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id] = 1;
$scope.currentExerciseSet = $scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id];
$scope.setProgress = ($scope.currentExerciseSet/$scope.currentExercise.sets) * 100;
//reps
$scope.reps = parseInt($scope.currentExercise.reps);
//weight
$scope.weight = parseInt($scope.currentExercise.weight);
//create a storage variable to store counters in
$localStorage.counters = {};
$localStorage.counters['setCount'] = $scope.setCount;
$localStorage.counters['workoutDate'] = $scope.workoutDate;
$localStorage.counters['workoutName'] = $scope.workoutName;
$localStorage.counters['exerciseIndex'] = $scope.exerciseIndex
$localStorage.counters['currentSet'] = $scope.currentSet;
$localStorage.counters['groupCounter'] = $scope.groupCounter;
$localStorage.counters['workoutIndex'] = $scope.workoutIndex;
$localStorage.counters['exerciseCounter'] = $scope.exerciseCounter;
list();
}
$scope.continue_workout = function(){
$scope.active = true;
$scope.currentWorkout = $localStorage.currentWorkout;
//set these values
$scope.setCount = $localStorage.counters['setCount'];
$scope.workoutDate = $localStorage.counters['workoutDate'];
$scope.workoutName = $localStorage.counters['workoutName'];
$scope.exerciseIndex = $localStorage.counters['exerciseIndex'];//storage
$scope.currentSet = $localStorage.counters['currentSet'];//storage
$scope.groupCounter = $localStorage.counters['groupCounter'];//storage
$scope.workoutIndex = $localStorage.counters['workoutIndex'];//storage
$scope.exerciseCounter = $localStorage.counters['exerciseCounter'];//storage
$scope.currentExercise = $scope.currentWorkout[$scope.workoutIndex][$scope.exerciseIndex];
if(angular.isUndefined($scope.exerciseCounter[$scope.currentExercise.user_workout_group_id])){
$scope.exerciseCounter[$scope.currentExercise.user_workout_group_id] = {};
}
if(angular.isUndefined($scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id])){
$scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id] = 0;
}
$scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id] = $scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id];// + 1;
$scope.currentExerciseSet = $scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id];
//increment the progress bars
$scope.setProgress = ($scope.currentExerciseSet/$scope.currentExercise.sets) * 100;
$scope.progress = $scope.currentSet/$scope.setCount;
//set the projected reps and weight
$scope.reps = parseInt($scope.currentExercise.reps);
$scope.weight = parseInt($scope.currentExercise.weight);
list();
}
$scope.next = function(){
//record the prvious info
$localStorage.currentWorkout[$scope.workoutIndex][$scope.exerciseIndex]['reps'] = $scope.reps;
$localStorage.currentWorkout[$scope.workoutIndex][$scope.exerciseIndex]['weight'] = $scope.weight;
$localStorage.currentWorkout[$scope.workoutIndex][$scope.exerciseIndex]['date'] = $filter('date')(new Date(), "yyyy-MM-dd HH:mm:ss");
$localStorage.currentWorkout[$scope.workoutIndex][$scope.exerciseIndex]['set'] = $scope.currentExerciseSet;
//increment the counters
$scope.exerciseIndex++;
$scope.currentSet++;
$scope.groupCounter++;
//check for end of set
if($scope.currentWorkout[$scope.workoutIndex].length <= $scope.groupCounter){
$scope.groupCounter = 0;
$scope.exerciseIndex = 0;
$scope.currentExerciseSet = 1;
$scope.workoutIndex++;
//check if it's the end of the workout
if($scope.currentWorkout.length <= $scope.workoutIndex){
var message = '<strong> Workour complete</strong>';
Flash.create('success', message, 'custom-class');
if(angular.isUndefined($localStorage.history)){
$localStorage.history = [];
}
$localStorage.history.push($scope.currentWorkout);
delete $scope.currentWorkout;
delete $localStorage.currentWorkout;
delete $localStorage.counters;
//move workout into history and unset current workout variable
$location.path('/home');
}
}
$scope.currentExercise = $scope.currentWorkout[$scope.workoutIndex][$scope.exerciseIndex];
if(angular.isUndefined($scope.exerciseCounter[$scope.currentExercise.user_workout_group_id])){
$scope.exerciseCounter[$scope.currentExercise.user_workout_group_id] = {};
}
if(angular.isUndefined($scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id])){
$scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id] = 0;
}
$scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id] = $scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id] + 1;
//set up exercise progess
$scope.currentExerciseSet = $scope.exerciseCounter[$scope.currentExercise.user_workout_group_id][$scope.currentExercise.exercise_id];
//increment the progress bars
$scope.setProgress = ($scope.currentExerciseSet/$scope.currentExercise.sets) * 100;
$scope.progress = $scope.currentSet/$scope.setCount;
//set the projected reps and weight
$scope.reps = parseInt($scope.currentExercise.reps);
$scope.weight = parseInt($scope.currentExercise.weight);
//set up some variable in local storage to use if we resume a workout
$localStorage.counters['exerciseIndex'] = $scope.exerciseIndex;;
$localStorage.counters['currentSet'] = $scope.currentSet;
$localStorage.counters['groupCounter'] = $scope.groupCounter;
$localStorage.counters['workoutIndex'] = $scope.workoutIndex;
$localStorage.counters['exerciseCounter'] = $scope.exerciseCounter;
}
function list(){
$scope.workout_list = $localStorage.userProgramDay[$localStorage.counters['workoutIndex']];
//console.log($scope.workout_list)
}
}]);

$scope.start_new = function(){
//logic in here
}
and then
//if the variable doesn't exist run the init
if(angular.isUndefined($localStorage.testVar)){
$scope.start_new();
}
else {
$scope.active = false; //display the layer which gives the choice
}
is correct. I can't see exactly what is going on in your code, but I suspect you are calling the function just fine -- you just have some sort of race condition causing it to not work as expected.
Try putting a console.log() in your function to see if it is being hit when you expect it to be hit.
EDIT:
I'm pretty sure this is happening because you are using start_workout() (line 14) before it is defined (line 22). Try moving the function declaration above the //set counter background and the original suggested solution should work.
Typically JS evaluates statements in a top-down fashion; there is a concept known as variable hoisting that causes straight up function a(){} calls to be evaluated immediately -- effectively hoisting them to the top of the code block. This is why the function works fine when you declare it as a free standing function rather than attaching it to $scope.
You can find more information in this SO answer: https://stackoverflow.com/a/261682/2457037

Related

Having an issue figuring out where to do calculations before using Upsert in mongodb

I'm using the angular-fullstack generator so there's 7 files in one endpoint (index, index.spec, orders.controller, orders.events, orders.integration, orders.model, and orders.socket). I'm not sure where to do computation to store in the fields when there is a PUT/Upsert. All the examples that I can google either use virtual fields or have generic code to do the computation. I know the computation I need to do but have no idea where to put it using this generator.
After a bit more searching this morning, I think what I want is to use getters/setters?
It's working in the controller as I presumed but i'm not sure if it's the best place to put these simple
function doCalcsSingle(res) {
var tOrderitems = 0;
var tRecitems = 0;
var tMissingitems = 0;
var today = new Date();
for(var i = 0; i < res.body.items.length; i++) {
res.body.items[i].missingItems = res.body.items[i].numOfOrdItems - res.body.items[i].numOfRecItems;
if(res.body.items[i].missingItems < 0 || !res.body.items[i].missingItems) {
res.body.items[i].missingItems = 0;
}
res.body.items[i].totalPrice = res.body.items[i].numOfOrdItems * res.body.items[i].unitPrice;
tOrderitems = tOrderitems + res.body.items[i].numOfOrdItems;
tRecitems = tRecitems + res.body.items[i].numOfRecItems;
tMissingitems = tMissingitems + res.body.items[i].missingItems;
if(tMissingitems < 0 || !tMissingitems) {
tMissingitems = 0;
}
}
res.body.totalOrdItems = tOrderitems;
res.body.totalRecItem = tRecitems;
res.body.totalItemsMissing = tMissingitems;
res.body.lastUpdated = today;
if(tMissingitems <= 0) {
res.body.activeOrder = false;
res.body.completedDate = today;
} else {
res.body.activeOrder = true;
}
return res;
}

Two Dimensional Array at Server-side Javascript on Xpages

need some help ..
Recently I've just created an array to calculate the value
function Calculate(){
for(x=1;x<7;++x){
var targetArr = [];
for(i=0;i<3;i++){
targetArr[i] = getComponent("product_"+x).getValue();
targetArr[i] = getComponent("quantity_"+x).getValue();
targetArr[i] = getComponent("stock_"+x).getValue();
}
var actualArr = [];
for(i=0;i<3;i++){
actualArr[i] = getComponent("actualProduct_"+x).getValue();
actualArr[i] = getComponent("actualQuantity_"+x).getValue();
actualArr[i] = getComponent("actualStock_"+x).getValue();
}
var achArr = [];
for(i=0;i<3;++i){
if((actualArr[i]>targetArr[i])||(targetArr[i]==0)||(targetArr[i]=="")||(targetArr[i]==null)){
achArr[i] = 1;
}else{
achArr[i] = (actualArr[i] / targetArr[i]);
}
if(isNaN(achArr[i])){
achArr[i] = 0;
}
x0 = achArr[i][x];
x1 = achArr[i][x];
x2 = achArr[i][x];
}
value = 100;
currentDocument.replaceItemValue("achProduct_"+x, x0*Value);
currentDocument.replaceItemValue("achQuantity_"+x, x1*Value);
currentDocument.replaceItemValue("achStock_"+x, x2*Value);
}}
but when i run the script, its got forever looping on my lotus domino server
and when i try to restart the web server its stucked and i have to force closed the server, and manually open it again
anyone can help me to solve my case ? i just need to display the achArr values
I'm trying to decipher your goal here. But first of all, your targetArr and actualArr for loops are wrong.
You'll end up with all values in targetArr equal to getComponent("stock_"+x).getValue()
Similarly, all values in actualArr equal to getComponent("actualStock_"+x).getValue()
And I don't think you even need a 2D array for achArr. I'm not entirely sure what you want to calculate in achArr's values, but I've written the code below. Is this closer to what you want?
function Calculate(){
for(var x=1;x<7;x++){
//Retrieve targetArr values
var targetArr = [];
targetArr[0] = getComponent("product_"+x).getValue();
targetArr[1] = getComponent("quantity_"+x).getValue();
targetArr[2] = getComponent("stock_"+x).getValue();
//Retrieve actualArr values
var actualArr = [];
actualArr[0] = getComponent("actualProduct_"+x).getValue();
actualArr[1] = getComponent("actualQuantity_"+x).getValue();
actualArr[2] = getComponent("actualStock_"+x).getValue();
//Generate achArr values
var achArr = [];
for(var i=0;i<3;i++){
if((actualArr[i]>targetArr[i])||(targetArr[i]==0)||(targetArr[i]=="")||(targetArr[i]==null)){
achArr[i] = 1;
}else{
achArr[i] = (actualArr[i] / targetArr[i]);
}
if(isNaN(achArr[i])){
achArr[i] = 0;
}
}
var value = 100;
currentDocument.replaceItemValue("achProduct_"+x, achArr[0]*value);
currentDocument.replaceItemValue("achQuantity_"+x, achArr[1]*value);
currentDocument.replaceItemValue("achStock_"+x, achArr[2]*value);
}}

javascript: when declaring a prototype method: error is invalid left hand side for assignment

I am new to object oriented javascript. Trying to make an object constructor.
Here is my code
function Collection() {
this.ports = build_ports_collection();
this.all_things = build_things_collection();
this.added_things = function() {
this.added_things.total_added = 0;
var temp = this.all_things;
temp.splice($(sth).val(), 1);
this.added_things.all = temp;
};
};
Collection.ports.prototype.reload = function() {
Collection.ports = build_ports_collection();
};
Collection.all_things.prototype.reload = function() {
Collection.all_things = build_things_collection();
};
Collection.added_things.all.prototype.reload() = function() {
var temp = Collection.all_things;
temp.splice($(sth).val(), 1);
Collection.added_things.all = temp;
};
Collection.added_things.prototype.add_things = function() {
this.added_things.total_added++;
add_things();
};
Collection.added_things.prototype.remove_things = function() {
this.added_things.total_added--;
remove_things();
};
I am getting error in the line Collection.added_things.all.prototype.reload()=....
netbeans reports: invalid left hand side for assignment.
here my intention was to bind a method reload() to Collection.added_things.all so that it will be shared among all instances of Collection
What point i am missing ?
Not sure if this is the answer you're looking for, but this came to mind.
Collection.added_things.all.prototype.reload() = function() {
var temp = Collection.all_things;
temp.splice($(sth).val(), 1);
Collection.added_things.all = temp;
};
There, you are assigning stuff to the prototype of Collection.added_things.all, while
this.added_things = function() {
this.added_things.total_added = 0;
var temp = this.all_things;
temp.splice($(sth).val(), 1);
this.added_things.all = temp;
};
is the first to declare the .all on Collection.added_things - basically, you are trying to assign a value to a property/variable/pointer that does not exist until added_things is first called.

Issues with using setTimeout inside of a for loop with arrays

--- UPDATE ---
Here is another attempt... The issue seems to be that the animation only happens to the third item in the for loop array I'm assuming because of the setTimeout delay. How can I have the animation fire for each item (3) with a delay?
// Breadcrumb Animation
(function(){
var header = document.getElementById("header"),
header2 = document.getElementById("header-secondary"),
banner = document.getElementById("banner");
var bcLink = [header, header2, banner];
var myTime = '';
var myItem = '';
function delay() {
setTimeout(fadeIn, myTime);
function fadeIn() {
if( myItem.style.opacity !== '1' ) {
console.log(myItem);
setInterval(function(){
myItem.style.opacity = parseFloat(myItem.style.opacity) + 0.1;
}, 100);
}
}
}
var i, len=bcLink.length;
for(var i = 0; i < len; i++) {
bcLink[i].style.opacity = 0;
myItem = bcLink[i];
myTime = myTime = parseInt(myTime + 2000)
delay();
}
})();
--- END UPDATE ---
The code below works but I was trying to optimize my code by creating a foor loop that will loop through each of the items (my attempt is commented out). I'm currently using 3 items on my page (header, header2, banner) that will load one after the other, but the second should not start until the first loads, the third should not start until the second item loads, and so on. This code will eventually be used for breadcrumbs where the amount of items will be uncertain but they will still load one after the other. Any help is greatly appreciated.
(function(){
var header = document.getElementById("header"),
header2 = document.getElementById("header-secondary"),
banner = document.getElementById("banner");
var bcLink = [header, header2, banner];
var myTime = '';
function fadeIn(name, speed) {
if( name.style.opacity !== '1' ) {
setInterval(function(){
name.style.opacity = parseFloat(name.style.opacity) + 0.1;
}, speed);
}
}
function delay(funct, time) {
setTimeout(function() {funct}, time);
}
bcLink[0].style.opacity = 0;
bcLink[1].style.opacity = 0;
bcLink[2].style.opacity = 0;
setTimeout(function(){fadeIn(bcLink[0], 100)}, 0);
setTimeout(function(){fadeIn(bcLink[1], 100)}, 1000);
setTimeout(function(){fadeIn(bcLink[2], 100)}, 2000);
// for(var i = 0; i < bcLink.length; i++) {
// bcLink[i].style.opacity = 0;
// delay(fadeIn(bcLink[i],100), i + 000);
// }
})();
use jQuery animation queue, not timeout.
http://blog.bigbinary.com/2010/02/02/understanding-jquery-effects-queue.html
Try changing:
delay(fadeIn(bcLink[i],100), i + 000);
to:
setTimeout(function(){fadeIn(bcLink[i], 100)}, i * 1000);

How can I prevent this arbitrary text truncation in AS3

Below is code that populates a menu. Everything seems to work great, with no errors thrown, except for one crucial part. My megaPages array has the values ["HOME","BABIES","BRIDALS","MISC","WEDDINGS","ABOUT"], but the actual text that displays on screen (which is produced by megaPages) is like this:
As you can see, some of the text is arbitrarily being truncated. I've traced the text strings as they get passed through the various functions at various stages of the menu-build, and they are always right, but somehow when each DisplayObject make it on screen, letters get ommitted (notice though that 'HOME' abd 'ABOUT' are fine). I don't even know where to start with this problem.
function buildMenu() {
var itemMCs = new Array();
for (var i = 0; i < megaPages.length; i++) {
megaPages[i] = megaPages[i].toUpperCase();
trace(megaPages[i]); // at each iteration, traces as follows "HOME","BABIES","BRIDALS","MISC","WEDDINGS","ABOUT"
var textMC = createText(megaPages[i]);
var itemMC = new MovieClip();
if (i!=0) {
var newLink = new PlateLink();
newLink.y = 0;
itemMC.addChild(newLink);
}
var newPlate = new Plate();
if (i==0) {
newPlate.y = 0;
} else {
newPlate.y = newLink.height - 2;
}
newPlate.x = 0;
newPlate.width = textMC.width + (plateMargin*2);
itemMC.addChild(newPlate);
if (i!=0) {
newLink.x = (newPlate.width/2) - (newLink.width/2);
}
textMC.x = plateMargin;
textMC.y = newPlate.y + .5;
itemMC.addChild(textMC);
itemMCs.push(itemMC);
itemMC.x = (homeplateref.x + (homeplateref.width/2)) - (itemMC.width/2);
if (i==0) {
itemMC.y = homeplateref.y;
} else {
itemMC.y = itemMCs[i-1].y + (itemMCs[i-1].height - 6);
}
menuRef.addChild(itemMC);
}
}
function createText(menuTitle) {
trace(menuTitle);
var textContainer : MovieClip = new MovieClip();
var myFont = new Font1();
var backText = instantText(menuTitle, 0x000000);
backText.x = 1;
backText.y = 1;
var frontText = instantText(menuTitle, 0xFFFFFF);
frontText.x = 0;
frontText.y = 0;
textContainer.addChild(backText);
textContainer.addChild(frontText);
return textContainer;
}
function instantText(textContent, color) {
trace(textContent); // again, traces the right text each time it is fired
var myFont = new Font1();
var myFormat:TextFormat = new TextFormat();
myFormat.size = 18;
myFormat.align = TextFormatAlign.CENTER;
myFormat.font = myFont.fontName;
var myText:TextField = new TextField();
myText.defaultTextFormat = myFormat;
myText.embedFonts = true;
myText.antiAliasType = AntiAliasType.ADVANCED;
myText.text = textContent;
myText.textColor = color;
myText.autoSize = TextFieldAutoSize.LEFT;
trace(myText.text);
return myText;
}
You need to embed all the necessary characters for the font you're using.
For textfields created in Flash:
Select the TextField, and hit the 'Embed' button in the properties panel.
For dynamically created textfields:
When you set the font to export (Font1 in your case) make sure to include all the characters you need.
You can choose to embed all uppercase characters, or just type in the ones you need for those specific menu items.

Resources