Getting a Callback after visjs finishes loading chart - javascript

I'd like to get a callback from visjs after it finishes loading a chart so I can then unhide the chart and stop a loading animation. However, i don't see anyway to registrar a callback in the docs.
Now, I'm new to javascript so perhaps i'm not thinking about this correctly? Hoping someone can point me in the right direction. Thanks!

I'm one of the creators of vis.js.
The visualizations of vis.js should load synchronously so there is no need for a callback. After checking though for the Timeline and Graph2d I saw this is not the case anymore, this is no intentional behavior. I've opened an issue for this here: https://github.com/almende/vis/issues/1541
I don't know which visualization you're using, but a workaround for the Timeline and Graph2d is: the visualization is loaded synchronously, and the items are loaded on the next tick. So you can set a callback on a timeout after 0 ms:
var timeline = new vis.Timeline(...);
alert('The Timeline is visible but the items not yet (this is a bug)')
setTimeout(function () {
alert('Now everything is loaded!');
}, 0);

i solved the trouble with change event on first show.
var firstshow=true;
$scope.timeline.on("changed", function (properties) {
if(firstshow)
{
$scope.timeline.focus($scope.timeline.getVisibleItems());
firstshow=false;
}

The solution that worked for me was this:
timeline.on('finishedRedraw', function() {
console.log('do something');
});

Seems this still hasn't been fixed. You can also hook into the currentTimeTick Timeline event. Note this events keep triggering so you can unsubscribe after the first time it triggers.
this.timeline.on("currentTimeTick", (prop) => {
// Do something here
// After fired the first time we un-subscribed
this.timeline.off("currentTimeTick")
})

Related

Prevent render of fabric-js canvas until fully populated

In FabricJS canvas.loadFromJSON() seems to run some sort of renderAll function even if not specified? As I'm both loading images from JSON and some from another function, I would like the canvas to stay empty until everything is loaded and then render everything simultaneously.
I have created a short fiddle with a simplified version: https://jsfiddle.net/Xikura/cas6j7b3/168/
The fiddle toggles one of the layers then redraws the canvas, especially if you disable caching you can see that the props shows up on it's own, then the rest of the images a bit later.
Quite minor one might say, but when there are between 10 and 30 images with various blend-settings, the loading could take some time until common images starts to get cached, moving around on the early visible props isn't doing my solution much good...
I see the documentation of loadFromJSON adds the renderAll() in it's callback, I trigger my own preload images in that same callback instead, to be able to add the other images.
if (!jsonCanvas) {
// First load
preload(images);
} else {
// Loading from saved JSON
canvas.loadFromJSON(jsonCanvas, function () {
preload(images);
});
}
Right now I can't seem to grasp why loadFromJSON seem to trigger some sort of render so the props are displayed first? Does FabricJS have any functionality I could use to prevent a render until I trigger it myself with renderAll() ?
I found the FabricJS-setting which one would think would solve this: renderOnAddRemove which I set to false, it did fix some other render-difficulties I had earlier, but had no effect on the loadFromJSON-part.
So I have been working the whole day on this, but after completing my question I decided to give it a rest and move on to other problems. By accident while trying to optimize the performance of my application I stumbeled upon this Improving FabricJS speed-site, which both answers my question and solves my problem.
By switching out loadFromJSON with fabric.util.enlivenObjects I'm able to trigger my own callback and not the (undocumented?) canvas.renderAll() which loadFromJSON calls.
if (!jsonCanvas) {
// First load
preload(images);
} else {
// Loading from saved JSON
fabric.util.enlivenObjects(jsonCanvas.objects, (objs) => {
objs.forEach((item) => {
canvas.add(item);
});
preload(images);
})
}
I updated my fiddle to include this fix.

Phaser : how to catch the game.scale.refresh end event

I am actualy developing my first game using phaser and I did a function resize to resize the game follow the size of the screen and at the end of this function I do :
game.scale.refresh();
But I would like to catch the event of this function like this :
var scaleRefresh = game.scale.refresh();
scaleRefresh.onComplete.add(function(){
//DO stuff
});
But it's not work how can I do this?
Are you sure that you need a resize function? I didn't implement it, and my game already does something similar when your desired behavior.
Which SCALE_MODE are you using? try to use 'USER_SCALE'.
Also, the documentation about Refresh doesn't say something about an onComplete event. but:
"The queued layout refresh is not immediate but will run promptly in an upcoming preRender."
https://phaser.io/docs/2.4.4/Phaser.ScaleManager.html#refresh
Seems that you could do your "onComplete" logic at "preRender" on your state.

Running function on window scroll once in jQuery

I'm creating my portfolio and I'm trying to make my skill bars load when I go to "My skills" section. I want them to do it only once, either when someone scroll to this section or goes to it straight away from the navigation. This is my code:
var skills = $('#mySkills');
var skillsPositionTop = skills.position().top;
$(window).on("resize scroll", function (){
if (pageYOffset<skillsPositionTop-20 && pageYOffset>skillsPositionTop-80){
console.log ("here is my loading script");
}
});
It doesn't work when I use one instead of on, doesn't work when I created one more function on window with one inside my if statement.
I was trying exit the function with return or return false as well and here, on stack overflow I found something about flag, which I didn't fully understand but I tried different combinations with it.
Can someone please help me with it? I've seen there is a library for this type of effects, but there is no point of installing any just for one thing...
Edit. Console.log represens my loading code.
You can set a namespace at .on() for resize, scroll events, use .off() within if statement to remove namespaced events.
var skills = $('#mySkills');
var skillsPositionTop = skills.position().top;
$(window).on("resize.once scroll.once", function (){
if (pageYOffset<skillsPositionTop-20 && pageYOffset>skillsPositionTop-80) {
$(this).off("resize.once").off("scroll.once");
console.log ("here is my loading script");
}
});

Example on how to use seek(time, [callback]) in Flowplayer

I'm trying to understand the flowplayer API, I'll be honest, I really need examples to get this stuff. I know some of you ninjas know what you're doing quite easily.
I am building a video training page for someone. It uses a PHP (kirbycms) framework to generate pages. I understand how to drop my variables and all that stuff. I have the videos working. It would be largely beneficial if I could have cue points that trigger things, and buttons that seek to specific time codes. It would be best if I can use PHP to define a string for these links.
I am looking for an example on how to use seek(time, [callback])
I am also looking for an example of
$(".player").bind("cuepoint", function(e, api, cuepoint) {
// here we use custom properties left, top and html
$("#info").html(cuepoint.html).animate({
left: cuepoint.left,
top: cuepoint.top
});
});
Update
Included bootply, this still does not work for me. Is it because my controls are outside of the flowplayer window?
http://bootply.com/86532
seek function (as documentation says: CLICK) is for jumping into given time on the timeline:
seek(time, [callback])
It takes two arguments: time in seconds and a callback - function that will be executed after jumping into that time on the timeline. Assuming that you are using jQuery you can write something like this to jump into 15.5s of the movie if you click button and then alert some message (just a simple example):
flowplayer(function (api, root) {
$("#someButton").on('click' function(e){
e.preventDefault();
api.seek(15.5, function(){
alert("you've jumped to 15.5s of the movie!");
});
});
});
Flowplayer doesn't do what you're after. In fact, seek() pretty much does the opposite- it triggers the video to jump to that point in time (and optionally calls back when its done).
If you want to set cuepoints and have the video trigger code when the video reaches those points in time, have a look at addEventListener("timeupdate", callback), see docs.
You might also want to check out popcornjs.

jQuery selector :not(:animated)

We're trying to make sure our JavaScript menu, which loads content, doesn't get overrun with commands before the content in question loads and is unfurled via .show('blind', 500), because then the animations run many times over, and it doesn't look so great. So I've got about six selectors that look like this:
("#center_content:not(:animated)")
And it doesn't seem to be having any effect. Trying only :animated has the expected effect (it never works, because it doesn't start animated), and trying :not(div) also has this effect (because #center_content is a div). For some reason, :not(:animated) seems not to be changing the results, because even when I trigger the selector while the div in question is visibly animated, the code runs. I know I've had success with this sort of thing before, but the difference here eludes me.
$("#center_content:not(:animated)").hide("blind", 500, function () {
var selector_str = 'button[value="' + url + '"]';
//alert(selector_str);
var button = $(selector_str);
//inspectProperties(button);
$("#center_content:not(:animated)").load(url, CenterContentCallback);
if (button) {
$("#navigation .active").removeClass("active");
button.addClass("active");
LoadSubNav(button);
}
});
I hope this provides sufficient context. I feel like the second selector is overkill (since it would only be run if the first selector succeeded), but I don't see how that would cause it to behave in this way.
Here's the snippet that seemed to be working in the other context:
function clearMenus(callback) {
$('[id$="_wrapper"]:visible:not(:animated)').hide("blind", 500, function() {
$('[id^="edit_"]:visible:not(:animated)').hide("slide", 200, function() {
callback();
});
});
}
Here, the animations queue instead of interrupt each other, but it occurs to me that the selector still doesn't seem to be working - the animations and associated loading events shouldn't be running at all, because the selectors should fail. While the queueing is nice behavior for animations to display, it made me realize that I seem to have never gotten this selector to work. Am I missing something?
Sometimes it's helpful to use .stop() and stop the current animation before you start the new animation.
$("#center_content").stop().hide("blind", 500, function () {});
Really depends on how it behaves within your environment. Remember that .stop() will stop the animation as it was (eg. halfway through hiding or fading)
I don't know if I understand it correctly, but if you want to make sure the user doesn't trigger the menu animation again while it's currently animating(causing it to queue animations and look retarded, this works and should help. I use an if-statement. And before any mouseover/off animation I add .stop(false, true).
$('whatever').click(function(){
//if center_content is not currently animated, do this:
if ($("#center_content").not(":animated")) {
$(this).hide(etc. etc. etc.)
}
//else if center_content IS currently animated, do nothing.
else {
return false;}
});
another example i found elsewhere:
if($("#someElement").is(":animated")) {
...
}
if($("#someElement:animated").length) {
...
}
// etc
then you can do:
$("#showBtn").attr("disabled", $("#someElement").is(":animated"));

Categories

Resources