--- 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);
Related
My application is crashing every 4-5 hrs and I am not sure it is happening because of memory leak or any code performance issue.
I have 3-4 functions which have timeouts to call self every 5 sec and they does some data massaging before painting the DOM.
As you can see my snapshots keep on increasing every time I take new snapshot.
Unable to find what exactly is happening. But if we look at the snapshots we can say that the strings has been increasing significantly from snapshot 1 to snapshot 9.
Any help is appreciated.
Sample code:
function fetchSummary() {
if(!$rootScope.pageVisible) {
$scope.fetchSummaryTimeout = $timeout(fetchSummary, 1000);
$scope.lastRefreshedDateTime = new Date();
return;
}
$http
.get(apiUri + '/statusboard/api/summaryDb')
.success(function (response) {
if (response && response.length) {
$scope.databases = response[0];
$scope.fetchSummaryTimeout = $timeout(fetchSummary, 5000);
var i, j, l;
//alert counts
angular.forEach($scope.databases.summary, function (summary) {
if (summary.eventType === "database_connection_alert") {
$scope.connectionCount += summary.count;
}
if (summary.eventType === "database_session_alert" || summary.eventType === "database_load_alert") {
$scope.warnCount += summary.count;
}
});
for (l = 0; l < $scope.databases.components.length; l++) {
var component = $scope.databases.components[l];
//some data stuff
for (j = 0; j < component.summary.length; j++) {
var summary = component.summary[j];
}}
$scope.coloCounts.any = $scope.coloCounts.All + $scope.coloCounts.lvs + $scope.coloCounts.slc + $scope.coloCounts.phx;
for (i = 0; i < $scope.databases.vcsStatus.length; i++) {
//Some stuff
}
}
} else {
$scope.fetchSummaryTimeout = $timeout(fetchSummary, 5000);
}
angular.element("#last-updated, #last-updated-overlay").remove();
})
.error(function () {
$scope.fetchSummaryTimeout = $timeout(fetchSummary, 5000);
});
}
}
"$scope.databases" is the variable every time i set the response to.
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
I have a directive which takes in an array of container objects and $compiles a new container directive for each container and each nested container. It also compiles a resize handle before all containers except the first child. The link function looks like this:
//scope.dock is retrieved from a factory
scope.initContainers = function () {
var prevScope;
for (var i = 0; i < scope.dock.containers.length; i++) {
var newScope = scope.$new(true);
newScope.container = scope.dock.containers[i];
var newElement = '<panel-container class=\"' + scope.dock.containers[i].axis + '" ></panel-container>';
var newTemplate = $compile(newElement)(newScope);
if (i > 0) {
var sizerScope = scope.$new(true);
sizerScope.containerOne = prevScope;
sizerScope.containerTwo = newScope;
var sizerElement = '<resize-handle class=\"' + scope.dock.containers[i].axis + '"></resize-handle>';
var sizerTemplate = $compile(sizerElement)(sizerScope);
element.append(sizerTemplate);
}
element.append(newTemplate);
if (scope.dock.containers[i].containers.length > 0) {
generateContainers(scope.dock.containers[i], newScope, newTemplate);
}
}
return scope;
};
scope.sizeContainers = function () {
scope.$broadcast('size-containers');
};
var generateContainers = function (value, parentScope, parentElement) {
var prevScope;
for (var y = 0; y < value.containers.length; y++) {
var newChildScope = parentScope.$new(true);
newChildScope.container = value.containers[y];
var newChildElement = '<panel-container class=\"' + value.containers[y].axis + '" ></panel-container>';
var newChildTemplate = $compile(newChildElement)(newChildScope);
if (y > 0) {
var sizerScope = parentScope.$new(true);
sizerScope.containerOne = prevScope;
sizerScope.containerTwo = newChildScope;
var sizerElement = '<resize-handle class=\"' + value.containers[y].axis + '"></resize-handle>';
var sizerTemplate = $compile(sizerElement)(sizerScope);
parentElement.append(sizerTemplate);
}
parentElement.append(newChildTemplate);
if(typeof value.containers[y].containers !== 'undefined') {
if (value.containers[y].containers.length > 0) {
generateContainers(value.containers[y], newChildScope, newChildTemplate);
}
}
prevScope = newChildScope;
}
};
scope.initContainers().sizeContainers();
My problem is that the first child layer compiles but the second one does not. It does, however, work when I add scope.$apply to the end of generateContainers. Unfortunately for some reason it is skipping the first child element for each container and throwing a 'digest in progress' error.
Does anyone have any ideas on how to get this to compile?
And could someone explain why scope.$apply() is compiling the second layer only after I explicitly call it, even when $digest is already running?
I fixed this by getting rid of initContainers (since it was exactly the same as generateContainers) and moving that function to the container directive as well. That way the root directive wasn't trying to compile everything.
I have been using this java code to call a random html page from a list of 49 on a set timer (or upon page refresh). I would like to convert it so that a cookie - or something else - saves the pages that have already been shown so that upon refresh the user always receives a new page, until the list is finished, at which point the cookie is emptied/deleted.
I found this code for a cookie image array. Could I use it with this? A variant of this also appears here. Apologies, my coding is pretty poor. Any advice appreciated:
<script type="text/javascript">
var sites = [
"name1.html",
"name2.html",
"name3.html",
"name...etc.html",
"name49.html",
]
$(document).ready(function() {
newPage();
});
function newPage()
{
setTimeout(newPage, 60000);
var min = 0;
var max = 48;
var num = Math.floor(Math.random() * (max - min + 1)) + min;
$('#target').attr('src',sites[num]);
}
</script>
var numSites = 49;
var seen = new Array(numSites);
$(document).ready(function() {
var cookie = unescape(getCookie("seen"));
seen = cookie ? cookie.split(',') : seen;
setTimeout(gotoNext, 60000);
});
function gotoNext() {
var num = getRandom();
var count = 0;
while (seen[num] == 1) {
num++;
if (num >= numSites) {
num = 0;
count++;
if (count > 1) {
resetSeen();
num = getRandom();
}
}
}
seen[num] = 1;
setCookie("seen", escape(seen.join(',')), 365);
window.location = "name" + num + ".html";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name)==0) return c.substring(name.length, c.length);
}
return "";
}
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
function resetSeen() {
for (var i=0; i<numSites; i++) {
seen[i] = "";
}
}
function getRandom() {
return Math.ceil(Math.random() * numSites);
}
It looks like you're using jQuery so I'll recommend using a jquery plugin for managing cookies much more neatly.
Copy & paste the contents of this URL to a new js file on your server and include it after the jquery file: https://raw.githubusercontent.com/carhartl/jquery-cookie/master/jquery.cookie.js
Or you could possibly use the get/set cookie functions from the other answer you mention.
The main thing to remember is that the cookie is stored as a string so you'll be join()ing and split()ing the array.
The other thing to note is that because we want a random item from the items we haven't visited yet it's more efficient to keep track of those rather than the ones we have visited.
What this means is we always choose a random item from what's left instead of looping over everything and checking each time if we've been there already as that would get very inefficient.
var sites = [ 'name1.html', 'name2.html', 'name3.html', ...etc... ],
unvisited = sites.slice(0); // .slice(0) clones the array
// if the cookie has a value then make it into the unvisited array
if ( $.cookie( 'unvisited' ) )
unvisited = $.cookie( 'unvisited' ).split( ',' );
$(document).ready(function() {
newPage();
});
function newPage() {
setTimeout( newPage, 60000 );
// check if the unvisited array needs resetting
if ( unvisited.length == 0 ) {
unvisited = sites.slice(0);
$.removeCookie( 'unvisited' );
}
// get a new index from the unvisited array
var num = Math.floor( Math.random() * unvisited.length );
// remove the item from the array and save the cookie
var site = unvisited.splice( num, 1 )[ 0 ];
// save the unvisited array minus the site we just spliced out
$.cookie( 'unvisited', unvisited.join( ',' ) );
$( '#target' ).attr( 'src', site );
}
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.