How to stop a timer upon keydown? - javascript

I have a text input box, which updates the 'ticket' with my the input when the timer finishes, instead of every keystroke which was the previous behaviour. However this causes a reload of the text input often while I am still using it.
I believe the best solution would be for the timer to reset every keydown event, but the few solutions I've tried haven't worked well, so I'd like to see if that's what is the most straightforward route to taker in my situation.
Relevant Code Below
strValue: {
get: function () {
return this.attachment.strValue;
},
set: function (val) {
let self = this; setTimeout(function(){ return self.updateAttachment([self.attachment.id, { strValue: val }]) },8000) },
},
Full section of code:
computed: {
...mapGetters(['allDocumentTypeGroups', 'currentTicketCaseFiles', 'activeAttachmentIndex', 'showAttachmentsPreview', 'activeAttachments']),
attachmentAcceptedLabel() {
return this.attachmentAccepted ? this.t('accepted') : this.t('ignored');
},
attachmentAccepted: {
get: function () {
return !this.attachment.ignoreAttachment;
},
set: function (val) {
return this.updateAttachment([this.attachment.id, { ignoreAttachment: !val }]);
},
},
documentType: {
get: function() {
return this.attachment.documentTypeId;
},
set: function(val) {
return this.updateAttachment([this.attachment.id, { documentTypeId: val }]);
},
},
approveAttachment: {
get: function() {
return this.attachment.approvedAttachment;
},
set: function(val) {
return this.updateAttachment([this.attachment.id, { approvedAttachment: val }]);
},
},
strValue: {
get: function () {
return this.attachment.strValue;
},
set: function (val) {
let timer;
if(timer){
clearTimeout(timer);
}
let self = this;
timer = setTimeout(function(){ return self.updateAttachment([self.attachment.id, { strValue: val }]) },8000) },
},
},

You can use clearTimeout(timer) as shown below:
let timer;
strValue: {
get: function () {
return this.attachment.strValue;
},
set: function (val) {
if(timer){
clearTimeout(timer);
}
let self = this;
timer = setTimeout(function(){ return self.updateAttachment([self.attachment.id, { strValue: val }]) },8000) },
},
},

This is a very simple implementation of a throttled input. Please let me know if I'm missing something.
const input = document.getElementById('input');
const ticket = document.getElementById('ticket');
const threshold = 2000;
let timeout = null;
const onKeydownHandler = () => {
// CLEAR PREVIOUS TIMEOUT WHEN A KEY IS PRESSED.
clearTimeout(timeout);
// "RESTART" THE TIMEOUT.
timeout = setTimeout(() => {
// UPDATE YOUR VALUE HERE.
ticket.innerText = `Ticket Value: ${input.value}`;
}, threshold);
};
input.addEventListener('keydown', onKeydownHandler);
// REMOVE THIS
(() => {
const counter = document.getElementById('counter');
let interval = null;
let count = threshold;
input.addEventListener('keydown', () => {
clearInterval(interval);
count = threshold;
interval = setInterval(() => {
count -= 50;
counter.innerText = `Time Left: ${count}ms`;
if (count <= 0) {
clearInterval(interval);
}
}, 50);
});
counter.innerText = `Time Left: ${count}ms`;
})();
// REMOVE THIS
div {
margin: 20px;
}
<input id='input' type='text' placeholder='Start writing...'></input>
<div>
<span id='ticket'>Ticket Value:</span>
</div>
<!--REMOVE THIS-->
<div>
<span id='counter'></span>
</div>
<!--REMOVE THIS-->

Related

clear interval on another function vue js

I'm confused how to add a set Interval variable in my vue file myTimer = setInterval(function, time).
The goal of my program is to change the number variable every 3 seconds, to access the object that I created to let it display different background images but I also have 2 buttons that can navigate through the background as well.
This is my template code
<div class="background" :style="{backgroundImage: `url(${Images[`${number}`].picture})`}">
<div class="content_container">
<div v-on:click="prev" class="prevButton"><p><</p></div>
<div class="title_container">
<div class="theTitle"><p>{{Images[`${number}`].Title}}</p></div>
</div>
<div v-on:click="next" class="nextButton"><p>></p></div>
</div>
</div>
This is my set Interval code
export default {
data: () => ({
number: 0,
myTimer
}),
mounted:function() {
this.$nextTick(() => {
this.timer();
});
},
methods:{
timer: function() {
var myTimer = setInterval(this.counter, 3000);
},
counter:function(){
if(this.number >= (this.Images.length -1)){
this.number = 0;
}
else{
this.number +=1;
}
},
next()
{
clearInterval(this.myTimer)
if(this.number >= (this.Images.length -1)){
this.number = 0;
}
else{
this.number +=1;
}
},
I want to clearInterval at the next() function how can I access the variable from another function.
your myTimer need be in this context.
export default {
data: () => ({
number: 0,
myTimer: 0, // init myTimer
}),
mounted: function () {
this.$nextTick(() => {
this.timer();
});
},
methods: {
timer: function () {
this.myTimer = setInterval(this.counter, 3000); // in this.myTimer
},
counter: function () {
if (this.number >= this.Images.length - 1) {
this.number = 0;
} else {
this.number += 1;
}
},
next() {
clearInterval(this.myTimer); // clear
if (this.number >= this.Images.length - 1) {
this.number = 0;
} else {
this.number += 1;
}
this.timer(); // start next
},
},
};

JavaScript Proxy not working properly on ie11

I am building a simple validation library and I need to use Proxy because I want to accept custom validation rules as chain object. I build something and its works properly on modern browsers but not works on IE11, I tried with proxy-polyfill but its also not work properly. My proxy code is below.
function contextProxy(context) {
return new Proxy(context, {
get(obj, prop) {
if (prop in obj) {
return obj[prop];
}
const newContext = contextProxy(context._clone());
if (definedRules.hasOwnProperty(prop)) {
return newContext._takeRule(definedRules[prop]);
}
if (customRules.hasOwnProperty(prop)) {
return newContext._takeRule(customRules[prop]);
}
},
});
}
And I use that proxy;
function validationL() {
return contextProxy(new ValidationLContext());
}
And I have definedRules object;
const definedRules = {
numeric: function () {
return function (text) {
return /^\d+$/.test(text);
};
},
lowercase: function () {
return function (text) {
return /^([a-z]+\s*)+$/.test(text);
};
},
uppercase: function () {
return function (text) {
return /^([A-Z]+\s*)+$/.test(text);
};
},
minLength: function (min) {
return function (text) {
return text.length >= min;
};
},
maxLength: function (max) {
return function (text) {
return text.length <= max;
};
},
alphaNumeric: function () {
return function (text) {
return /^([a-zA-Z0-9 _-]+)$/i.test(text);
};
},
specialChars: function () {
return function (text) {
return !/^([a-zA-Z0-9 _-]+)$/i.test(text);
};
},
email: function () {
return function (text) {
return /^([a-zA-Z0-9_.+-])+\#(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(
text
);
};
}
};
ValidationLContext.js
function ValidationLContext(isNot = false, chain = []) {
this.chain = chain;
this.isNot = isNot;
}
ValidationLContext.prototype.not = function () {
this.isNot = true;
return this;
};
ValidationLContext.prototype._takeRule = function (ruleFn) {
return (...args) => {
this.chain.push({ fn: ruleFn.apply(this, args), isNot: this.isNot });
if (this.isNot) {
this.isNot = false;
}
return this;
};
};
ValidationLContext.prototype.validate = function (text) {
return this.chain.every((c) =>
c.isNot ? !c.fn.call(this, text) : c.fn.call(this, text)
);
};
ValidationLContext.prototype._clone = function () {
return new ValidationLContext(this.isNot, this.chain);
};
export default ValidationLContext;
So library usage like this;
validationL().numeric().minLength(3).validate("123");
validationL().not().numeric().minLength(3).validate("123");
I can use like above on modern browsers like Chrome but when I try on IE11 only not() function works so only objects functions can work.
Can anyone help me with this.

Chromecast custom CAF receiver

I'm having issues with the new CAF receiver not registering the YouTube iframe player as a player, and that it is playing. After 5 minutes connected to the receiver, the connection is broken because it thinks that the player is idle.
This is the sender-code
var metadata = new chrome.cast.media.GenericMediaMetadata();
metadata.title = "Foo - Bar";
metadata.image = 'https://img.youtube.com/vi/IXNrHusLXoM/mqdefault.jpg';
metadata.images = ['https://img.youtube.com/vi/IXNrHusLXoM/mqdefault.jpg'];
var mediaInfo = new chrome.cast.media.MediaInfo();
mediaInfo.contentType = "video/*";
mediaInfo.contentId ="IXNrHusLXoM";
mediaInfo.duration = 300;
var request = new chrome.cast.media.LoadRequest();
request.media = mediaInfo;
request.customData = customData;
request.metadata = metadata;
castSession.loadMedia(request).then(
function() {
console.log('Load succeed');
},
function(errorCode) {
console.log('Error code: ' + errorCode);
});
The receiver code can be found here: https://github.com/zoff-music/zoff-chromecast-receiver/blob/feature/v3/receiver.js
Is there any way of having the new CAF receiver hook into the YouTube iframe player, or "manually" dispatch LOADED, BUFFERING, PLAYING, PAUSED, STOPPED events so that the receiver doesn't disconnect from the sender?
Edit: with the above code, the PlayerState gets to the BUFFERING stage, but stops there. The promise with the log "Load succeed" is never triggered.
I managed to trick the receiver with fake mediaEelement. You can see the code in pastebin
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
var yt_events = {};
var pause_request = false;
var yt_player;
var yt_video_fake = {
removeAttribute: function(attr) {
},
setAttribute: function(attr, val) {
},
getCurrentTimeSec: function() { return yt_player && yt_player.getCurrentTime ? yt_player.getCurrentTime() : 0; },
getDurationSec: function() { return yt_player ? yt_player.getDuration() : 0; },
getVolume: function() {
if(!yt_player || !yt_player.getVolume) {
return 0;
}
var volume = new cast.framework.messages.Volume();
volume.level = yt_player.getVolume() / 100;
volume.muted = yt_player.isMuted() ? true : false;
return volume;
},
setVolume: function(vol) { yt_player && yt_player.setVolume(vol.level * 100); },
getState: function() {
if(!yt_player || !yt_player.getPlayerState) {
return 'IDLE';
}
var state = yt_player.getPlayerState();
var _state;
if(pause_request) {
pause_request = false;
state = YT.PlayerState.PAUSED;
}
switch(state) {
default: case YT.PlayerState.UNSTARTED:
_state = 'IDLE';
break;
case YT.PlayerState.PLAYING:
_state = 'PLAYING';
break;
case YT.PlayerState.PAUSED:
_state = 'PAUSED';
break;
case YT.PlayerState.BUFFERING:
_state = 'BUFFERING';
break;
case YT.PlayerState.ENDED:
_state = 'ENDED';
break;
}
return _state;
},
addEventListener: function(e, func) { },
load: function() {},
play: function() { yt_player && yt_player.playVideo(); },
pause: function() { if(yt_player && yt_player.pauseVideo) {pause_request = true; yt_player.pauseVideo(); }},
seek: function(timeTo) { yt_player && yt_player.seekTo(timeTo, true);},
reset: function() {
if(yt_player) {
try { yt_player.destroy && yt_player.destroy(); } catch(e) {
//console.trace(e);
};
delete yt_player;
}
},
registerErrorCallback: function(func) { yt_events['error'] = func; },
registerEndedCallback: function(func) { yt_events['ended'] = func; },
registerLoadCallback: function(func) { yt_events['load'] = func; },
unregisterErrorCallback: function () { delete yt_events['error'] },
unregisterEndedCallback: function () { delete yt_events['ended']},
unregisterLoadCallback: function () { delete yt_events['load']}
};
Object.defineProperty(yt_video_fake, 'currentTime', {
val1: null,
get: function() { return yt_player && yt_player.getCurrentTime ? yt_player.getCurrentTime() : this.val1; },
set: function(newValue) {
yt_player && yt_player.seekTo(newValue, true);
this.val1 = newValue;
},
enumerable : true,
configurable : true
});
Object.defineProperty(yt_video_fake, 'volume', {
val1: null,
get: function() { var vol = this.getVolume(); if(vol) return vol['level']; return 1; },
set: function(newValue) {
yt_player && yt_player.setVolume && yt_player.setVolume(newValue * 100);
this.val1 = newValue;
},
enumerable : true,
configurable : true
});
Object.defineProperty(yt_video_fake, 'duration', {
val1: null,
get: function() { return this.getDurationSec(); },
set: function() {},
enumerable : true,
configurable : true
});
function YoutubePlayMedia(videoid) {
var yt_container = $('#yt_container');
if(!yt_container.length) {
yt_container = $('<div id="yt_container" style="position:absolute;top:0;left:0;width:100%;height:100%;"></div>');
$('body').append(yt_container);
}
yt_container.html('<iframe id="youtube_container" style="width:100%;height:100%;" frameborder="0" allowfullscreen="1" allow="autoplay; encrypted-media" title="YouTube video player" src="//www.youtube.com/embed/' + videoid +'?autoplay=1&enablejsapi=1&modestbranding=1&controls=0&fs=0&iv_load_policy=3&rel=0&cc_load_policy=1&cc_lang_pref=bg"></iframe>');
yt_player = new YT.Player('youtube_container', {
events: {
'onReady': function(e) {
yt_player.is_loaded = true;
yt_player.playVideo();
},
'onStateChange': function(e) {
switch(e.data) {
case YT.PlayerState.PLAYING:
if(yt_player.is_loaded) {
if(yt_events['load']) {
yt_events['load']();
}
}
break;
case YT.PlayerState.ENDED:
//yt_events['ended'] && yt_events['ended'](e);
break;
}
},
'onError': function(e) {
//yt_events['error'] && yt_events['error'](e);
}
}
});
}
function YoutubeLoadMedia(url) {
current_media_type = 'Youtube';
window.onYouTubeIframeAPIReady = function() {
window.youtube_loaded = true;
YoutubePlayMedia(url);
}
if(!window.youtube_script) {
window.youtube_script = document.createElement('script');
window.youtube_script.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(window.youtube_script, firstScriptTag);
} else {
// Вече имаме api направо действаме
YoutubePlayMedia(url);
}
}
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
loadRequestData => {
if (loadRequestData.media && loadRequestData.media.contentId) {
YoutubeLoadMedia(loadRequestData.media.contentId);
playerManager.setMediaElement(yt_video_fake);
return false;
}
return loadRequestData;
}
);
const options = new cast.framework.CastReceiverOptions();
options.disableIdleTimeout = true;
context.start(options);
The YouTube iframe player is not designed to be a player for a Cast receiver.

Angular JS factory function

I want the use set method of factory but both of return default how can I fix that problem?
app.factory("DualListShareFactory", function(){
var selectedArray=[];
return{
getSelectedArray: function () {
return selectedArray;
},
setSelectedArray: function (array){
selectedArray=array;
}
}
});
Using ng-dual List from https://github.com/tushariscoolster/ng-duallist
I'm tkining it not working: DualListShareFactory.setSelectedArray(vm.rightValue);
I use other method for and push but I am received same error .
app.controller("duallist2", function($scope,DualListShareFactory){
var vm=this;
vm.property='duallist2';
activate();
function activate() {
vm.leftValue = [];
vm.rightValue = [];
vm.addValue = [];
vm.removeValue = [];
function loadMoreLeft() {
for (var i = 0; i < $scope.incomingItem.length; i++) {
vm.leftValue.push({
'name': $scope.incomingItem[i]
});
}
};
function loadMoreRight() {
}
vm.options = {
leftContainerScrollEnd: function () {
},
rightContainerScrollEnd: function () {
},
leftContainerSearch: function (text) {
console.log(text)
vm.leftValue = $filter('filter')(leftValue, {
'name': text
})
},
rightContainerSearch: function (text) {
vm.rightValue = $filter('filter')(rightValue, {
'name': text
})
},
leftContainerLabel: 'Gelen Parçalar',
rightContainerLabel: 'Seçilen Parçalar',
onMoveRight: function () {
console.log('right');
console.log(vm.addValue);
},
onMoveLeft: function () {
console.log('left');
console.log(vm.removeValue);
}
};
loadMoreLeft();
var leftValue = angular.copy(vm.leftValue);
var rightValue = angular.copy(vm.rightValue);
} console.log(vm.rightValue);
DualListShareFactory.setSelectedArray(vm.rightValue);
});
I am not this will work but try "this",
app.factory("DualListShareFactory", function(){
this.selectedArray=[];
return{
getSelectedArray: function () {
return this.selectedArray;
},
setSelectedArray: function (array){
this.selectedArray = array;
}
}
});
var app = angular.module("testapp", ["ng-duallist"]);
app.factory("DualListShareFactory", function(){
var selectedArray = [];
return{
getSelectedArray: function () {
return selectedArray
},
setSelectedArray: function (array){
angular.copy(array, selectedArray);
}
}
});
using for this add the other code block before ending function.
onMoveRight: function () {
DualListShareFactory.setSelectedArray(vm.rightValue);
},
onMoveLeft: function () {
DualListShareFactory.setSelectedArray(vm.rightValue);
}
};
loadMoreLeft();
var leftValue = angular.copy(vm.leftValue);
var rightValue = angular.copy(vm.rightValue);

TypeScript - JavaScript using knockout.js not working in IE8 - "Object doesn't support this property or method"

I have this code (also shown below) that is giving me an error in IE8 but is fine in Chrome and PhantomJS.
The error is "Object doesn't support this property or method knockout-2.2.1.debug.js, line 2319 character 35", which is called from currentPage(pages[pages.indexOf(current) + steps]);
I have no clue why it's not working, so any help would be greatly appreciated!
var Page = (function () {
function Page(index, name, canNavigateToPage, navigatedToThisPage) {
this.index = index;
this.name = name;
this.canNavigateToPage = canNavigateToPage;
this.navigatedToThisPage = navigatedToThisPage;
}
Page.prototype.navigateToPage = function () {
if (this.canNavigateToPage()) {
this.navigatedToThisPage(this);
}
};
return Page;
})();
var AccountSearchParameters = (function () {
function AccountSearchParameters() {
this.reference = ko.observable();
this.scheme = ko.observable();
this.lastName = ko.observable();
this.sufficientInputToSearchForAccount = ko.computed(function () {
return this.reference() && this.scheme() && this.lastName();
}, this);
}
return AccountSearchParameters;
})();
function viewModel() {
var self = this,
currentPage = ko.observable(),
accountSearchParameters = new AccountSearchParameters(),
forwardPageProgressionGuards = {
'1': function canMoveToPage2() {
return accountSearchParameters.sufficientInputToSearchForAccount();
},
'2': function canMoveToPage3() {
return true;
},
'3': function canMoveToPage4() {
return true;
}
},
canMoveToNextPage = function (currentlyOnPage) {
function disallowPageMovementNotExplicitlyDefined() {
return false;
}
return (forwardPageProgressionGuards[currentlyOnPage] || disallowPageMovementNotExplicitlyDefined)();
},
canMoveToPreviousPage = function (currentlyOnPage) {
return currentlyOnPage > 1;
},
pages = [
new Page(1, 'Customer details', function () {
return true;
}, function (page) {
currentPage(page);
}),
new Page(2, 'Bank details', forwardPageProgressionGuards['1'], currentPage),
new Page(3, 'Payment details', forwardPageProgressionGuards['2'], currentPage),
new Page(4, 'Confirmation', function () {
return true;
}, currentPage)],
pageNavigator = function (canNavigate, steps) {
current = currentPage();
console.log(canNavigate(current.index));
if (canNavigate(current.index)) {
currentPage(pages[pages.indexOf(current) + steps]);
}
};
currentPage(pages[0]);
self.page = ko.computed(function () {
return currentPage();
});
self.accountSearchParameters = accountSearchParameters;
self.nextPage = function () {
pageNavigator(canMoveToNextPage, 1);
};
self.previousPage = function () {
pageNavigator(canMoveToPreviousPage, -1);
};
self.canMoveToNext = ko.computed(function () {
return canMoveToNextPage(currentPage().index);
});
return self;
}
$(function () {
ko.applyBindings(viewModel());
});
indexOf in IE8 does not supported, use $.inArray

Categories