I have an AngularJS page which contains the following buttons:
<button class="ui button" ng-click="startTimer()" ng-show="!timerRunning">START</button>
<button class="ui button" ng-click="stopTimer()" ng-show="timerRunning">STOP</button>
I also have this piece of code defined in my controller:
$scope.timerRunning = false;
$scope.timerDone = false;
$scope.startTimer = function () {
$scope.$broadcast('timer-start');
$scope.timerRunning = true;
$scope.timerDone = false;
};
$scope.stopTimer = function () {
$scope.$broadcast('timer-stop');
$scope.timerRunning = false;
$scope.timerDone = true;
};
$scope.$on('timer-stopped', function (event, data) {
console.log('Timer Stopped - data = ', data);
});
$scope.$on('timer-tick', function (event, args) {
if (args.millis == 0) {
$scope.stopTimer();
}
});
I would expect that when timer hits 0 (it's a countdown timer taken from here) the flag timerDone and timerRunning would be changed and so would the buttons display. But in fact it doesn't happen. I debugged it and saw that I get into the stopTimer() method and that the variables are changed but the buttons stay hidden/shown respectively as they were before the timer hit 0.
I guess I'm missing something with the scope here as I'm pretty new to angular but I just couldn't figure out how to overcome this.
Looks like it was a prototypal inheritance issue like Rob J was right. What I did was to fix the even listener as follows (added $scope.$apply()):
$scope.$on('timer-tick', function (event, args) {
if (args.millis == 0) {
$scope.stopTimer();
$scope.$apply();
}
});
Related
I'm using the iteminvokedHandler and was wonder if there is a better way to interact with the listView.
Currently using this:
WinJS.UI.processAll(root).then(function () {
var listview = document.querySelector('#myNotePad').winControl;
listview.addEventListener("iteminvoked", itemInvokedHandler,false);
function itemInvokedHandler(e) {
e.detail.itemPromise.done(function (invokedItem) {
myEdit();
});
};
});
The problem is that everytime I click on the listview myEdit() is run and propagates within the listview. I was wondering how to do it once and stop invoking listview until I am done with myEdit? Is there a simpler way to handle such a situation as this?
Simple yet hard to see when you have a mind block and forget some of the basics (yes yes I'm still learning):
var testtrue = true;
WinJS.UI.processAll(root).then(function () {
var listview = document.querySelector('#myNotePad').winControl;
listview.addEventListener("iteminvoked", itemInvokedHandler,false);
function itemInvokedHandler(e) {
e.detail.itemPromise.done(function (invokedItem) {
if (testtrue === true){
myEdit();
}
});
};
});
In myEdit:
function myEdit() {
var theelem = document.querySelector(".win-selected #myNotes");
var gestureObject = new MSGesture();
gestureObject.target = theelem;
theelem.gestureObject = gestureObject;
theelem.addEventListener("pointerdown", pointerDown, false);
theelem.addEventListener("MSGestureHold", gestureHold, false);
function pointerDown(e) {
e.preventDefault();
e.target.gestureObject.addPointer(e.pointerId);
}
function gestureHold(e) {
if (e.detail === e.MSGESTURE_FLAG_BEGIN && test === true) {
e.preventDefault();
editNotes();
} else {
}
console.log(e);
}
theelem.addEventListener("contextmenu", function (e) {
e.preventDefault();}, false); //Preventing system menu
};
function editNotes() {
//The Code I wish to execute
return test = false;
};
What I needed was a conditional statement so that it would run if true and not if false. That same test needed to be done in the gestureHold otherwise it would continue to fire myEdit on the invoked item because of the way the gesture is attached to the item the first time it is run.
I have a function which will take some time to run on click event.
Following is merely an example and setTimeout is there only to simulate time it may take to run it. How can I ensure when a user click on an item any previous running function(s) is(are) cancelled and only the latest onclick function is fired?
i.e. if a user clicked on it 10 times. I want to only execute the only the 10th click not the 9 clicks before.
I am hoping for a pure/vanilla js solution... NOT jQuery
(function () {
var nav = document.querySelector('.nav__toggle');
var toggleState = function (elem, one, two) {
var elem = document.querySelector(elem);
elem.setAttribute('data-state', elem.getAttribute('data-state') === one ? two : one);
};
nav.onclick = function (e) {
setTimeout(function(){
toggleState('.nav ul', 'closed', 'open');
}, 5000);
e.preventDefault();
};
})();
fiddle: http://jsfiddle.net/6p94p48m/
You need to debounce your click handler.
var button = document.getElementById("debounced");
var clickHandler = function() {
alert('click handler');
}
var debounce = function(f, debounceTimeout) {
var to;
return function() {
clearTimeout(to);
to = setTimeout(f, debounceTimeout);
}
}
button.addEventListener('click', debounce(clickHandler, 5000));
<button id="debounced" href="#">debounced</button>
Or use underscore/lodash https://lodash.com/docs#debounce
In a DOJO widget there is code in the postCreate and destroy method to create/start and stop a timer like you can see below. Depending on the value in a drop down box the timer is started or stopped. This works fine so far.
postCreate: function() {
var deferred = this.own(<...some action...>)[0];
deferred.then(
lang.hitch(this, function(result) {
this.t = new dojox.timing.Timer(result.autoRefreshInterval * 1000);
this.t.onTick = lang.hitch(this, function() {
console.info("get new data");
});
this.t.onStart = function() {
console.info("starting timer");
};
this.t.onStop = function() {
console.info("timer stopped");
};
})
);
this.selectAutoRefresh.on("change", lang.hitch(this, function(value) {
if (value == "Automatic") {
this.t.start();
} else {
this.t.stop();
}
}));
},
When leaving the page the timer is still active so I want to stop it when I leave the page using DOJOs destroy() method.
destroy: function() {
this.t.stop();
},
This however throws a this.t.stop is not a function exception. It seems like this.t is not created in the context of the widget although I use lang.hitch(this...
What am I missing here?
I solved that by just renaming the variable t to refreshTimer. Maybe t is some kind of reserved variable in Dojo?
I'm having some trouble with this website I am building. I am modifying the existing pre-loader to have a button before continuing on to the home page. The issue is I can't point the button click to the correct function for a reason that i really can't figure out. Here is the appropriate code:
Revision: Just to clarify, I'm aiming to get this button click to replicate the function performed in the final code extract: this.parent.endLoader(); but am not having any success.
The click:
<script>
$(document).on('click', '.qLbtns', function(){
$(this).EndLoader();
});
</script>
The js bind:
$.fn.EndLoader = function(){
return this.each(function(){
this.endLoader();
});
};
The function i am trying to point to:
QueryLoader2.prototype.endLoader = function () {
this.destroyed = true;
this.onLoadComplete();
};
Which is effective within this function:
PreloadImage.prototype.completeLoading = function () {
this.parent.imageDone++;
var percentage = (this.parent.imageDone / this.parent.imageCounter) * 100;
this.parent.overlayLoader.updatePercentage(percentage);
if (this.parent.imageDone == this.parent.imageCounter || percentage >= 100) {
this.parent.endLoader();
}
};
I have come to a standstill in terms on threading together a sequence of Animations and then a controller action.
What I basically want to do is basically
1. click on a button/div, 2.Trigger an Animation, 3. Once animation is complete run a function in a controller that resets the button/div
I have completed steps 1 & 2 and just need to get the last bit done.
Here is the Button
<button ng-class="{'clicked':clicked, 'correct' : answer.answer == 'correct' }"
ng-click="clicked = true"
ng-repeat='answer in answers'
type="button"
class="btn btn-answers answer-animation">
{{ answer.es }}
</button>
Here is the animation
app.animation('.answer-animation', function(){
return {
beforeAddClass: function(element, className, done){
if (className === 'clicked') {
if( $(element).hasClass('correct') ){
$(element).addClass('animated bounce');
} else {
$(element).addClass('animated wobble');
}
}
else {
done();
}
}
};
});
And here is the last step the controller, I want the trigger the submitAnswer function inside this controller, after the animation has finished. The main bit is submitAnswer
app.controller('Game', function($scope, $http, $location, QA, Rounds ) {
//Reset all QA buckets
QA.reset();
$scope.round = 1;
$scope.playing = true;
QA.setUpGameData();
$scope.answers = QA.answers();
$scope.question = QA.question();
$scope.submitAnswer = function(question, answer){
if($scope.round <= Rounds) {
if(question.en === answer.en){
$scope.round++;
QA.setUpGameData();
$scope.answers = QA.answers();
$scope.question = QA.question();
if($scope.round === Rounds + 1){
$scope.playing = false;
$scope.message = 'Amazing well done!';
$scope.score = ($scope.round-1) * 1000;
}
}
else {
$scope.playing = false;
$scope.message = 'Sorry Wrong Answer :(';
$scope.score = ($scope.round-1) * 1000;
}
}
};
})
I have tried writing the ng-click in the HTML like so
ng-click="clicked = true;submitAnswer(question, answer)"
and then setting a $timeout on the submintAnswer function, but does really get the UX the app deserves.
Again ultimately I want a way to trigger the submitAnswer function in the controller after the animation is completed.
You can get the $scope of an element using,
var $scope = angular.element(element).scope();
Though there are some problems with syncing the scope if this happens.