Video.JS - Multiple events firing on exact time once - javascript

I'm developing a web application in which I've got a video element. This, as I've had good experiences with it, is controlled via the VideoJS scripts.
However, on my app, there are some points in which the video needs to be paused until played by the user (or by a script, it's not relevant), but not after.
What I have
Basically - and the basic information you need - what I have is an array of items, let's say item_array, with objects in it. Each object has an id, a media object with some information of it, including a src, and an indications array - which would be the pause-times objects. Something like that:
var items_array = [
{
id: 1234,
media: {
id: 2345,
src: 'video_source.mp4',
duration: 302.56
},
indications: [
{
id: 1,
time: 65.380
},
{
id: 2,
time: 89.238
},
{
id: 3,
time: 123.765
}
]
}
]
Of course, I've got the video variable, which stores the VideoJS reference and is accessible all along the code as a global variable (maybe it's useful for you to know that).
What I need
Basically, I need to be able to load a video source and tell the script that the video must pause at 1:05.380, 1:29.238 and 2:03.765, for example.
Once paused, the user can play the video again, and it will not be paused (at least, by the script) again until the next time mark is reached.
Then, the user can specify a new video to load, with its new pause-points, so old pause-points should be removed and new ones set.
Also, it would be necessary to perform other actions apart from pausing the video (such as showing a message, etc.). But it's not necessary for you to know any of these - just I have to be able to write some actions to do on every pause-point.
What I've tried
Well, I've been playing with timeupdate. The first problem is that this only fires every now and then, so video.currentTime() == NN.NNN will not always work.
The script video.currentTime() >= NN.NNN is not possible neither, because the user must be able to play further the pause-time (yes, the event can be set off once reached, but if the user skips it on the time line, the video must not be paused).
So, if the pause-time is at 1:05 and the user skips from 0:45 to 1:25, the pause-time set to 1:05 must not be triggered, thus the video must not be paused - so the line written before does not work as I'd like to.
Thank you everyone in advance for your time and help! If you need any further information, please ask me and I will submit it as soon as I can!
Best regards.

Finally, I've come up with a possible solution. Sure it's not the best in performance, but it does what it's meant to.
I write it here and maybe someone will find it useful.
The solution
What I do is to fire a custom event everytime the timeupdate event is triggered, so I can delete all actions attached to this custom event without breaking VideoJS default event actions.
Then, I set a time_range, so I can make the comparison between video.currentTime() with the desired indication.time without being exact, but with some space to happen.
Finally, when it happens, I pause the video (and show the indication, those actions I told you I needed to do) and set a new property of the indication, has_shown to true.
At every custom_timeupdate I check if the video.currentTime() is inside that space of time I told you and if that indication.has_shown is set to false. If so, the process triggers. If not, nothing happens (so if an indication has already been shown it does not pause the video again).
But, as I wanted it to show it again if the user returned to that point, I set a last check so if video.currentTime() is - a little bit - far from that point, the property has_shown is set to false again.
This is done, of course, for every indication we have.
Here you have the code:
var time_range = 0.125
video.on("timeupdate", function(){
video.trigger("indications_timeupdate")
})
function load_indications(indications){
/*
Function actions ...
*/
// If the video is defined, as we are loading them new, we set off old Indication timers
if(video !== undefined) video.off("indications_timeupdate")
$.each(indications, function(i, ind){
video.on("indications_timeupdate", function(){
if(video.currentTime() >= ind.time - time_range && video.currentTime() <= ind.time + time_range && !ind.has_shown){
video.pause()
ind.has_shown = true
}else if(video.currentTime() >= ind.time + time_range || video.currentTime() <= ind.time - time_range){
ind.has_shown = false
}
})
})
}
As I said, maybe it's not the best solution, but it's the best one that I've been able to think of.
Thank you for your time to everyone who has tried to think of an approach for this question!
Best regards.

Related

Change the leaflet hold touch timing

I'm using Leaflet for a mobile app developed with Ionic. I currently have a function to search for certain items near a location specified when you make a single click on the map
$rootScope.map.on('click', function(e) {
if (APP_STATUS == ACTION_SEARCH) {
positionClick = e.latlng;
$scope.positionSearchClose = positionClick;
$scope.userPosition.setLatLng(positionClick);
$scope.popupSearchRoutesClosed = $ionicPopup.show({
template: $scope.getTemplate(),
title: 'Buscando rutas',
scope: $scope,
});
$scope.getRoutesClose(positionClick, ACTION_SEARCH);
}
});
$scope.addButtons();
I want to change this so that the search happens when the user holds the touch for a brief time. I changed the 'click' parameter to 'contextmenu' and I achieved what I was looking for, but I found out that the hold timing was too long. Despite the leaflet doc description of the ContextMenu event being "Also fired on mobile when the user holds a single touch for a second (also called long press)." it feels like that "second" is an eternity.
Is there a way to make it so the function above only triggers when the user holds the touch, but specifying the amount of time of the hold?
it maybe long time. But i've been searching for this for few hours. i found the solution, which may help anyone who comes here.
In leaflet, touch tap delay declared as 1000ms in a settimeout function. And they can be edited.
In leaflet.js find the below code :
// simulate long hold but setting a timeout
this._holdTimeout = setTimeout(bind(function () {
if (this._isTapValid()) {
this._fireClick = false;
this._onUp();
this._simulateEvent('contextmenu', first);
}
}, this), 1000);
now the 1000(1 second) declared here is the timer, you can change the 1000 to whatever you like...like 300 or 500.
if you want to change touch hold(tap) timer dynamically,
create a variable in the leaflet.js beginning
var contextMenuTime = 1000;
and manually apply the variable in js the function
...
this._simulateEvent('contextmenu', first);
}
}, this), contextMenuTime);
now you can control the tap delay by changing the variable value.

JavaScript variables "out of focus"?

I have a function (see below) that writes a message out onto the screen. Whenever you're actively viewing the page that it is running on, it prints out just fine; however, say you're watching a video in another tab and switch back to the tab that is writing out the function, the text comes out all jumble. e.g: "This is a message." generally would come out scrambled like "t isa hismg esseg."
The function in question:
params:
message: string
object: an HTML Object
function writeMessage(message,object){
var i = 0;
var interval = setInterval(function(){
if(i < message.length){
object.append(message.substr(i,1));
i++;
}else{
clearInterval(interval);
}
}, 25);
}
Any idea as to why this happens?
I haven't tested that, but if what the comments say is true, you should be able to avoid that by manually chaining individual delayed operations. Instead of defining one interval, you should be able to call one timeout (setTimeout function), that appends the letter to the object and then calls itself recursively while passing the rest of the message to the recursive call.
In this case, if the device gives your asynchronous action no processor time, at least the subsequent actions won't be created and executed - because only the code in the first (now waiting) action could do that.
Alternatively you can use Reactive Extensions to generate an observable interval, upon which you can subscribe and update the object with your message. If you're not familiar with reactive programming, it might be a huge new topic for you, but I can certainly recommend it - if only just as a brain-teaser to see a different approach to programming.

What are the (dis)advantages of simulating keypresses? Is there a better way? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
Suppose I have the following code, which listens to an input element, specifically executing a callback when the user hits Enter:
...
document.getElementById('human_input').onkeyup = (function (indicate) {
return function(e) {
var e = e || window.event; // for IE8
if (e.keyCode === 13) { // if user presses 'Enter' key*
indicate('User has submitted text');
}
}
})(indicate);
[*keyCode reference here.]
...
What indicate does isn't really the point here but some code is applied to the argument 'User has submitted text' to display it somewhere.
Now, what if I want some script to listen in the same way to an 'invisible input' which is to be filled out, not by a human but by a separate part of the code?
Say that a black box script function called fillHidden() fills out the hidden_input field at some specified point.
document.getElementById('hidden_input').value = 'All filled out.'; // for example
How would a very separate listener script module find out about the value. Would it be enough to say do this...
document.getElementById('hidden_input').onkeyup = (function (indicate) {
return function(e) {
var e = e || window.event; // for IE8
if (e.keyCode === 13) { // if user presses 'Enter' key
indicate('User has submitted text');
}
}
})(indicate);
And have the fillHidden() code do this:
document.getElementById('hidden_input').value = 'All filled out.'; // for example
document.getElementById('hidden_input').onkeyup({keyCode: 13}); // simulate keypress
Or is that bad practice? There have been questions about how to do this or even simulate keyboard shortcuts but I could find nothing on the actual merits or otherwise of simulating keypresses.
Is there a better way, a pattern perhaps, or an interlocking system of callbacks, that can enable these modules to interact whilst separate? I have seen videos of Nicholas Zakas talking about this kind of architecture as 'loose coupling' and a book I have called JavaScript Patterns (Stefanov, 2010) alludes to possibilities of a subscriber/publisher model. What would be the advantages of these compared with a simulated keypress, especially when the simulated keypress makes for a kind of symmetry with the user's side of events? And what kind of disadvantages/dangers might one expect when simulating keypresses?
This is all very... abstract.
Which is all well and good.
It's not necessarily the goal of SO to come up with solutions to abstractions like this, because there are a million ways of doing them.
However, a few key points:
Unless you're linking simulated code to user-generated events in some way, the browser is likely going to prevent your simulations from taking over for the user
(imagine browsers letting any JS on the page simulate any keypress or any mouse-click at any time).
This typically means that you're tightly-bound, using some library which isn't meant for consumer use, using browser-specific (ie: FireFox/Chrome/IE) plug-ins which users must install/run, or bust. Pick one (or more).
Custom-Events, with callbacks, as a rule are what will allow you to keep your programs separate, but have them function together.
Zakas does some great talks on Sandboxing, but those are very enterprise-level, end-game type things. They're fantastic, and library builders and system-engineers should totally consider them, but for making the average page, it'd be better to complete the 100 lines you need to write, rather than build out a full framework, with a library which both wraps every module in an enclosure, and injects itself into that module.
That's where Pub-Sub (and Observer)/Moderator(or Mediator) come into play.
Any of the above might also be called an "emitter" or a "generator", et cetera, depending on the library.
Each one of the above is created in basically the same way, and does the same sort of thing.
The goal is to relay results to an audience who wants to listen.
The speaker chooses when to notify the audience, and what to tell them.
The audience chooses to tune in at any time, to await the next broadcast (which might never come, but at least they were paying attention for it), or they can choose to tune out and stop listening for broadcasts.
The differences between them, then, is how the "speaker" knows about the thing that's happening.
Publisher-Subscriber
In publisher-subscriber, the speaker IS the object that makes things happen.
Look at Twitter.
You sign up for a Twitter account. Once you have it, you can follow anyone you want.
Any time they tweet, you get notified about it.
Anybody can follow you, so that any time you tweet, they are notified about it.
The person who is doing the action publishes that action to any subscribers who want to hear it. There might be 3000 subscribers and one publisher (a newsletter), or 3000 publishers and one subscriber...
There might be publishers who won't subscribe, or subscribers who won't publish... ...but that's the paradigm.
Observer
In observer, you're talking about an object which is coupled to the thing doing the work.
It might be tight. It might be loose. But there's a thing doing something, and there's a thing that knows exactly what it's doing. Then people bug the watcher for updates.
Think of the days of Baseball, where people listened to the games on radio.
The observer would be the radio-commentator.
He wasn't the one hitting the ball or stealing bases. He was the one in the booth, who saw everything going on, and knew what it all meant, and turned it into user-friendly information for all of the people listening at home.
These days, players can tweet about plays as they're making them, directly to all of their fans (pub-sub), and I'm sure that FourSquare will find a way to get their geo down to the per-base accuracy, for hands-off updating of who the king of third-base is (for once, it's not Jeff, in his cramped Z28).
Mediator/Moderator
In this case, we're talking about an object which everybody knows about, but nobody knows about one another.
Imagine a call-in talk-radio show.
Everybody knows the show. Everybody can call into the show, and talk with the host. But other than coincidence, nobody knows anything about the other listeners.
It's a little bit different than pub-sub, because everybody's a publisher, but you don't have to know somebody's Twitter handle to hear from them. You can say Hey Twitter, any time anybody in the world mentions #browns, let me know. I'm starving..
It's a little different from observer because while the moderator IS watching the person who does the work, anybody can be doing the work at any time.
Which one is the right one?
It all depends on what you need, and what you're actually intending to do with it.
Here's how we might make a Moderator:
var Moderator = function () {
var events = {},
notify = function (evtName, data) {
var evt = events[evtName];
if (!evt) { return; }
evt.forEach(function (func) { func(data); });
},
listen = function (evtName, callback) {
events[evtName] = events[evtName] || [];
events[evtName].push(callback);
},
ignore = function (evtName, callback) {
var evt = events[evtName];
if (!evt) { return; }
evt.forEach(function (func, i, arr) {
if (func === callback) { arr.splice(i, 1); }
});
};
return { ignore : ignore,
listen : listen,
notify : notify };
};
Pretty simple and straightforward, right?
Of course, this isn't particularly filled with bells and whistles, like subscribing to only the next time an event fires, or the next-3 times, or whatever...
We might use it like this:
var Game = function () {
var game_moderator = Moderator(),
scoreboard = Scoreboard(),
messages = MessageBoard(),
player_one = Player(),
player_two = Player();
function initialize () {
player_one.initialize(game_moderator);
player_two.initialize(game_moderator);
game_moderator.listen("player:death", scoreboard.update);
game_moderator.listen("player:death", messages.add_kill);
game_moderator.listen("chat:input", messages.add_msg );
}
function start() {}
/* update... draw... etc... */
return {
load : load,
initialize : initialize,
start : start
};
};
var game = Game(),
loading = game.load();
loading.done(function () {
var initializing = game.initialize();
initializing.done(game.start);
});
Meanwhile, Player might look like this:
var Player = function (name) {
var system,
health = 30,
damage = [],
attack = function () { /* ... */ },
hurt = function (amt, type, from) {
health -= amt;
damage.push({ amount : amt, type : type, from : from });
},
die = function () {
var killing_blow = damage[damage.length - 1];
killing_blow.player = name;
system.notify("player:death", killing_blow);
},
update = function () {
if (health <= 0) { die(); }
},
draw = function () {},
initialize = function (sys) { system = sys; };
return {
initialize : initialize,
update : update,
draw : draw,
hurt : hurt
/* ... */
};
};
So looking back into the Game.initialize function, we can see that we've got a scoreboard and a message panel which are both going to do things with "player:death" events.
Because of the way the players are called and defined, I'm injecting a reference to the moderator, during their initialization (so that I can keep everything separate: dependency-injection).
But player_one knows nothing about player_two, scoreboard knows nothing about anything, except that something occasionally calls its .update method and passes in kill information, and messages gets all kinds of love, but it's the kind where everybody's a stranger...
Going back to your original problem:
If your hidden-input is being filled in by spying on key-presses, why not build an Observer?
Build an observer which connects to a keyup event-listener and a keydown event-listener.
Have that observer turn those events into useful information (for instance: when you hold a key down, the keydown event fires dozens of times per second -- you probably don't want that... so alert when a new key is added, or alert when a pressed key is released).
Have the hidden-input subscribe to that.
When the hidden-input is full, or however your requirements are operating... ...and you want to fire an event off, have a global-moderator (or a moderator which is at the top level of the system that hidden-input is a part of).
From there, fire an event called "hidden-input-filled" or whatever is meaningful.
The people who care about that happening can subscribe to that event through the moderator.
That is, of course, if your program is built in such a way that nobody should know about the hidden-input, BUT there are people who should know about hidden-input's events.
If there are only a select group of things which should know about hidden-input, and those are the only things which should know about its events, and hidden-input should also be able to know something about them, then make them pub-sub.
Or mix and match your connections:
The idea is to build communication which makes sense and tells people what they need to know, and no more.
So if Twitter-users should be sub-pub, but different widgets on the page (timeline vs search vs recent-pictures, etc) shouldn't know much about one another (and certainly not make every picture able to share with every timeline update), then make a global moderator that the whole widget can communicate to other widgets through (like when timelines need to update based on search results), and inside of each widget, have a moderator and/or pub-sub for different connections, between components.
Hope that helps, and I hope that explains why it's easier to engineer a loosely-coupled, large program by doing this, rather than by hijacking real events, and then firing fake ones down the line, intended to target different areas of your program.
In all honesty, if your full site, with all of its programs comes down to: "I've got this input that does this thing, and another input that does another thing", the answer is that it really doesn't matter too much.
When you get to: "I've got a page with 8 spaces for different widgets, and there are 16 possible widgets which could be loaded in any of those 8 slots at any time, and there are some major actions in some widgets which should cause responses in other widgets, and there are lots of events that each widget needs to control internally, and we need to pipe in an AJAX library and a DOM/MVC(or MVVM) libarary to control all of the stuff that goes on inside of each widget, itself, and there's only one of me..."
That's when it's a great idea to hammer out this stuff and hammer out Promises/Deferreds/Futures, and break your big ideas out into smaller pieces, spread out over different points in the life of the running application.

javascript, while loop

i'm trying to get my script to wait for user input (click of a button) before continuing, this is v feasible in other languages, but seems impossible in js. basically, i want the user to select an option within a given time frame, if the user selects the wrong option, they're told..script then conts...otherwise, if after a certain amount of time theres no response...script just continues again sowing them the correct ans, but there seems to be nothing in js to make the script wait for that user input! ive tried a while loop, but that is just a big no no in js, ive used settimeout but has no real effect because the script just continues like normal then performs an action after x amount of time, ive tried setting variables and letting the script cont only if it is of a particular value, which is set only if the user clicks...eg var proceed=false, this is only set to true if the user clicks a button, but it still doesn't work... ive tried sooo many other solutions but nothing actually seems to be working. i like the idea of a while loop, because it doeas exactly what i want it to so, but if completly freezes my browser, is there a more effecient type of loop that will will peroform in the same manner with crashing my browser?
heres my code below that compltely freezes my computer. this method is called within a for loop which calls another method after it.
function getUserResp(){
$("#countdown").countdown({seconds: 15});
setTimeout("proceed=true", 16000);
$("#ans1").click(function(){
ansStr=$(this).text();
checkAns(ansStr);
});
$("#ans2").click(function(){
ansStr=$(this).text();
checkAns(ansStr);
});
$("#ans3").click(function(){
ansStr=$(this).text();
checkAns(ansStr);
});
would like something like this.....or just some sort of loop to make the script wait before going ahead so at least it gives the user some time to respond rather than running straight though!
do{
$(".ans").mouseover(function(){
$(this).addClass("hilite").fadeIn(800);
});
$(".ans").mouseout(function(){
$(this).removeClass("hilite");
});
}while(proceed==false);
}
You're doing it wrong.
JavaScript in the browser uses an event-driven model. There's no main function, just callbacks that are called when an event happens (such as document ready or anchor clicked). If you want something to happen after a user clicks something, then put a listener on that thing.
What you've done just keeps adding an event listener every time round the loop.
If you want to wait for user input then just don't do anything - the browser waits for user input (it's got an internal event loop). The worst thing you can do is try to reimplement your own event loop on top of the browser's.
You need to learn JavaScript. Trying to write JavaScript like you would another language only leads to pain and suffering. Seriously.
Douglas Crockford said it best:
JavaScript is a language that most people don’t bother to learn before they use. You can’t do that with any other language, and you shouldn’t want to, and you shouldn’t do that with this language either. Programming is a serious business, and you should have good knowledge about what you’re doing, but most people feel that they ought to be able to program in this language without any knowledge at all, and it still works. It’s because the language has enormous expressive power, and that’s not by accident.
You can't block the Javascript from running in the same way that you can in some other imperative languages. There's only one thread for Javascript in the browser, so if you hang it in a loop, nothing else can happen.
You must use asynchronous, event-driven programming. Setting a click handler (or whatever) combined with a timeout is the right way to start. Start a 15 second setTimeout. Inside the click handler for the answers, cancel the timeout. This way the timeout's handler only happens if the user doesn't click an answer.
For example:
var mytimeout = setTimeout(15000, function() {
// This is an anonymous function that will be called when the timer goes off.
alert("You didn't answer in time.");
// Remove the answer so the user can't click it anymore, etc...
$('#ans').hide();
});
$('#ans').click(function() {
// Clear the timeout, so it will never fire the function above.
clearTimeout(mytimeout);
alert("You picked an answer!");
});
See how the code must be structured such that it's event-driven. There's no way to structure it to say "do this thing, and wait here for an answer."
You're looking at client-side javascript as if it wasn't already in an event-driven loop. All you need to do is wait for the appropriate event to happen, and if it hasn't happened yet, continue to wait, or else perform some default action.
You don't need to:
create main loop: // All
wait for user input // Of
timer = start_timer() // This
// Is done for you
if [user has input data]:
process_data()
else if [timer > allowed_time]:
process_no_data()
else:
wait() // By the Browser
You only need the middle part. All you need to do is (Actual javascript follows, not pseudo-code):
// First, store all of the answer sections,
// so you're not grabbing them every time
// you need to check them.
var answers = {};
answers.ans1 = $("#ans1");
answers.ans2 = $("#ans2");
answers.ans3 = $("#ans3");
// This is a flag. We'll use it to check whether we:
// A. Have waited for 16 seconds
// B. Have correct user input
var clear_to_proceed = false;
var timer_id;
// Now we need to set up a function to check the answers.
function check_answers() {
if ( ! clear_to_proceed ) {
clear_to_proceed = checkAns(answers.ans1.text());
clear_to_proceed = checkAns(answers.ans2.text());
clear_to_proceed = checkAns(answers.ans3.text());
// I assume checkAns returns
// true if the answer is correct
// and false if it is wrong
}
if ( clear_to_proceed ) {
clearTimeout(timer_id);
return true; // Or do whatever needs be done,
// as the client has answered correctly
} else {
// If we haven't set a timer yet, set one
if ( typeof timer_id === 'undefined' ) {
timer_id = setTimeout(function(){
// After 16 seconds have passed we'll check their
// answers one more time and then force the default.
check_answers();
clear_to_proceed = true;
check_answers();
}, 16000);
}
return false; // We're just waiting for now.
}
}
// Finally, we check the answers any time the user interact
// with the answer elements.
$("#ans1,#ans2,#ans3").bind("focus blur", function() {
check_answers();
});

Resizing Facebook Application's iFrame w/ New Javascript SDK

Does anyone know what's the replacement method for FB.CanvasClient.startTimerToSizeToContent() to resize iframe content in the new javascript SDK for Facebook?
Or maybe if there is an alternative technique for achieving the same effect?
Thanks
Examples
This function is useful if you know your content will change size, but you don't know when. There will be a slight delay, so if you know when your content changes size, you should call setSize yourself (and save your user's CPU cycles).
window.fbAsyncInit = function() {
FB.Canvas.setAutoResize();
}
If you ever need to stop the timer, just pass false.
FB.Canvas.setAutoResize(false);
If you want the timer to run at a different interval, you can do that too.
FB.Canvas.setAutoResize(91);
Note: If there is only 1 parameter and it is a number, it is assumed to be the interval.
Parameters
Name Type Description
onOrOff Boolean Whether to turn the timer on or off. true == on, false == off. default is true
interval Integer How often to resize (in ms). default is 100ms

Categories

Resources