I am trying to create a simple 3 image slideshow with a next and back button in Flash CC using HTML5 Canvas. I'm new to javascript and seem to be having an issue with it working.
this.stop();
this.next_btn.addEventListener("click", playClickNext.bind(this));
function playClickNext()
{
this.gotoAndStop(this.currentFrame + 1);
}
this.back_btn.addEventListener("click", playClickBack.bind(this));
function playClickBack()
{
this.gotoAndStop(this.currentFrame - 1);
}
I'm getting it to publish and the next button works but sometimes goes to the wrong frame. The back button sometimes work and sometimes doesn't. The most common thing it does is also go back to a random frame when clicked.
Thanks for any help!
I put together a quick sample, and got a similar result. The issue for me was that the frame that the script was on would fire any time you went to that frame. This meant that the listeners on the button would pile up, and fire multiple times.
The ideal solution is to pull the code out of the FLA, and into your HTML/JS app. You can target the timeline directly using the instance names. For example, in my app, it is all on the main timeline, so you can use:
exportRoot.next_btn.addEventListener("click", handler);
To solve it without rearchitecting, you could also just ensure that either:
Your frame with the script is never navigated to. You could make your "first" frame 2 frames long, and put the code on frame 1, and the stop() on frame 2. Then just ensure you never gotoAndStop on 1. You will have to put restrictions on both previous and next, because you can gotoAndStop at a higher frame than the max, and it will wrap.
Remove all the event listeners each frame. The way you set up your listeners using bind is problematic for removal, so I recommend just removing all listeners.
I uploaded a quick sample here [ https://dl.dropboxusercontent.com/u/2224806/Nav.fla ] that uses the second approach, mainly because it is an easy fix.
Sorry, link expired
Let me know if this solves your issue, or if it is related to something else.
Related
So I have a very specific problem that presented itself recently (right before our planned launch day tomorrow) and I am not completely sure how to solve it. I have built our website of an HTML-template with my modest front-end skills and we are very pleased with it. However, I can't seem to solve this.
The problem:
I have a filter system that allows a user to filter articles that are presented on a page. A user can even fill in this filter on the home page, direct to the page with the articles and have the filter applied. However, if then the filter is broadened (less strict) and new articles present itself, the pictures do not show up. Found out this is the case because the flexslider behind it has to be initialized again which happens on a window load (e.g. when the window is resized). The function that controls the initialization of the flexslider is in an external js file and I am not sure whether I can call on it from my own custom.js file, so I am thinking of just calling a resize/reload window function to active it.
The question:
Can I run a resize window function (or something that activates the flexslider) without hindering user experience (more specifically, without ACTUALLY resizing/reloading the window)? I will run this on a change in the filter.
I know this is a very specific question but hopefully somebody can help me out.
Take care!
p.s. it would be ideal if I could run the actual function that loads the flexslider but this is located in an external js file.
EDIT:
Briefly some additional info. If I go straight to the article page, it has no filter active and thus shows all articles, if I then start flipping through the filter, all is good. It is however only if I arrive from the homepage with a set filter that the problems arise. You then arrive on the article page which shows only the articles that are within the boundaries, and when the filter is taken away it has problems loading the images of the new articles showing up. As if it had not loaded these because they were not open on window load the first time.
You can trigger a resize event by creating a new event and passing it into the dispatchEvent command on window. There's a nice guide here. You'll want the type of event to be resize, since that's what it's listening for.
window.dispatchEvent(new Event('resize'))
This will work for events that were added via jQuery as well as events added via addEventListener.
I managed to solve it after all by delaying the function that drops the filter values into my inputs so it loads in all images initially before applying the filter. It happens at such speed it's hardly noticeable.
Also, I did try to initiate a window resize function, it did work without actually resizing anything, but unfortunately the images did not load in properly (overlap and such).
Anyway, it has been solved. Thanks for all the input!
I'm working on new skins for my video.js player. I already added un handler. Now, I want to add the current timer on it which has to follow the progress bar.
There are two prototypes: one for the handler and the other for the timer. How can I add the timer into the handler ?
If you're referring to just the currentTime, you can listen to the timeupdate event. Assuming you've got a reference to your player:
player.on('timeupdate', function() {
// do whatever you want with the time update
});
That being said, if all you're working on is building a new skin, you're throwing away a lot of work already done for you by not simply styling elements that are already in place. CurrentTimeDisplay will already handle keeping the vjs-current-time class updated.
My suggestion would be to try and get as far as possible using nothing but CSS, then when you find yourself limited move on to JS. If you get to the point you need extra listeners, the events documentation are going to be the first place you'll want to look.
Since some time last year, YouTube made it so that every page is not actually loading an entirely new page, but primarily just re-loading the contents in div#content. You can notice this when you click on a link in YouTube and see the red loading bar at the top of the page.
I have a Greasemonkey script that modified elements on YouTube, but now that YouTube doesn't reload the entire page, the Greasemonkey script no longer fires on every "new" page. How can I make the Greasemonkey script fire on every "new" page that I load on YouTube?
I'm using jQuery in this Greasemonkey script. I tried using functions like .on() with DOMNodeInserted but I can't find the right combination to make it work properly. With the event listeners that I've been using, I end up running my script hundreds of times for each page load, such as with the following:
$('div#page').on('DOMNodeInserted', 'div#content', function() { });
Another solution I was thinking of was making all links on YouTube load pages like normal, without the new way that they are doing it.
I figured it out myself after some research. First off, I don't like solutions that use setTimeout. This is often one method suggested in favor over the deprecated DOMNodeInserted for instance (which I use in some of my scripts, but try to avoid as much as possible), but if possible, I always prefer a solution where the script actually executes after a specific event. I've posted the solution I initially used in the first section below, then the final solution I used in the second section. All code below requires jQuery.
Decent solution, but not the best
At first, I had a solution where I added a click event to all A elements, which would run a timer that ran my script after 2 seconds. This isn't elegant, because if the page loads quickly, then there's a split second where the script hasn't run. And if the page loads for more than two seconds, then the script doesn't run at all. Script below:
$('a').click(function()
{
setTimeout(youtubeFunction, 2000);
});
Much better solution
So I began looking for a solution that was related to what I wanted to accomplish. I eventually found other people with a similar problem to mine (such as people wanting to create a Chrome script that modifies YouTube pages). This led me to this particular Stack Overflow solution, which basically says that the red loading bar at the top of YouTube pages was a CSS transition element, and that it created a transitionend (case sensitive) event when it was finished. The code in the linked solution wasn't complete (for me anyway), but it did explain how to achieve a working solution. The code I have runs only once per page, which is perfect. So here's what I have now:
function youtubePageChange()
{
youtubeFunction();
$('body').on('transitionend', function(event)
{
if (event.target.id != 'progress') return false;
youtubeFunction();
});
}
$(youtubePageChange);
To explain the code above, basically I run the code once for when you first load a YouTube page (such as by typing the URL in the address bar). Then for every subsequent click that requires the progress bar, the code runs again.
Red progress bar code
Oh, and for future reference, when the red progress bar appears at the top of YouTube pages, the site temporarily adds a new DIV to the end of BODY, with the following code:
<div id="progress" class="waiting" style="transition-duration: 400ms; width: 99%;"><dt></dt><dd></dd></div>
You can set a listener which gets called when the page has finished loading.
This is for the new YouTube material design:
body.addEventListener("yt-navigate-finish", function() {
//your code
});
And this for the old:
window.addEventListener("spfdone", function() {
//your code
});
(if you are using *monkey, you'll need to use unsafeWindow)
Keep in mind that the old design will be discontinued, so your script may not work after that.
Hooking into the popstate might be an option, but i was unable to make that work correctly for some reason (youtube may be preventing it from propagating), so i came up with this that shows the concept:
var currentState = "";
setInterval(function(){
if (currentState != history.state["spf-referer"]) {
currentState = history.state["spf-referer"];
console.log("Do Stuff!");
}
},250)
Just watches for the history.state to change, at which point it will log. The state should change any time the url changes, even if it wasn't due to a page reload.
I'm trying to achieve the following:
I have a javascript object that fetches two flash objects.
The two flash objects are then added to the page, the first one I set with play=true and
the second one I set with play=false.
I'm presenting the one with play=true right after download, and placing the other with play=false in an hidden container.
When I press the first one it interacts with my javacsript and in turn the js code
hides the first flash div container and changes the second flash (the hidden one)
div container to be shown.
With that being done I also change the play attribute of this flash from false to true so it will start playing.
The two actions, changing DOM visibility and changing the play attribute to true, are done
in two different setTimeout functions (design constraint!).
The issue I have is that on IE10 on WIN8 the flash object doesn't adhere to the play command.
To be more exact with my actions, I'm fetching the flash obj using:
var myObj = document.getElementById("MY_OBJ_ID"), and then I try to set the play to true by doing myObj.Play(); using the standard Play() method flash exposes.
Off course I check that the object exist before excuting the Play().
In addition, after I press the first flash that suppose to set all of the above in motion,
and nothing happens... If I write the same lines manually in the console:
var myObj = document.getElementById("MY_OBJ_ID");
myObj.Play();
Then the movie plays and everything works.
And I'll mention again, this happens only on IE10 on WIN8.
I'll appreciate any assistance with this issue, I'm breaking my back over this and can't figure it out.
Update - 30/06:
I think I figured out the issues somewhat, the play is not occurring indeed.
In IE 10 you can query the flash obj with flashObj.Playing attribute and I see that it's returning false.
In that case I just call the function with setTimeout and every time and check the attribute status until it's true.
But I see that this attribute is not valid in other browser, and in all browsers there's another API function - flashObj.IsPlaying().
Is there a cross-browser implementation that will let me check if a flash object is in playing state or not?
Let's say something like this:
flashObj.TGetPropertyAsNumber("/", 4) >= 1) || flashObj["IsPlaying"]()
It will check if the first frame or even more has already been played, or check if the "IsPlaying" is returning true?
Update - 01/07:
Well, the above method proved to work correctly on all browsers, so my issue is somewhat resolved.
In order to know if the flash player has loaded I need to preform the above check and if the flash isn't loaded I call the function I use to set play again with setTimeout.
But I'm still perplexed from IE10 on WIN8 behavior.
I don't understand why the flashObj.Play() works first time on all browsers first time I call it and in IE10 I need to do setTimeout for this to work.
I am creating an app using jQuery Mobile and PhoneGap.
I "delegate" a button on "tap" to perform some heavy processing and display a loading spinner. If users continue to tap on my app, the taps get queued up and fall through to be processed by the app after the heavy processing completes - and end up clicking on unwanted stuff.
How can I prevent this?
(From what I understand, stopImmediatePropagation doesn't help as these are new user events.)
Thanks
To inactive taps on the whole page you could overlay the whole page with a transparent div. Although it might be considered a borderline hack - this would actually use minimal js and css!
The caveat is that it would not give any visual indicator that the page is inactivated.
To do that one could, use a semitransparent gray for the overlay or, as I've done below, show a loading message.
First off, a small CSS discussion:
To make the div cover the whole page set width and height 100%. To position it correctly, use position:absolute and for the transparent background use an rgba background-color property (see below). You should also declare a z-index (can be increased if needed) to ensure that it goes on top of everything else and remove tap-callout using the -webkit-tap-highlight-color property. Set display to none and then show it during your heavy lifting.
I made a jsfiddle which hopefully clears things up.
Here I've made div with an id of "inactivator" which features the properties discussed above.
I've also made a button with an id of "inactivate" to which I've delegated jQuery's show function.
I also took the liberty to add jQuery Mobile's default loading message to show simultaneously just to give a visual indicator of the app thinking (so it's not mistaken for lag).
Here I've added a timeout function so that the loading message and "inactivator" hides after 5 second. Obviously in your case the same code should instead be fired upon completion of your "heavy processing" rather than after five seconds.
(New, additional answer since I didn't understand the question correctly but the old answer still might be helpful to other people.)
The easiest way I can think of is inactivating the button at the start of your javascript function and then reactivating it when it's suitable:
$('#YourButton').addClass('ui-disabled');
At the end of your function (or whenever you'd want it active again:
$('#YourButton').removeClass('ui-disabled');
So it took me a while to figure it out... you have to return FALSE from the delegate function for parent elements to ignore the event. The return false line below fixes my issue:
$(document).delegate("#finish", "tap", onFinish);
var onFinish = function() {
$.mobile.loadingMessage = "Finishing...";
$.mobile.showPageLoadingMsg();
setTimeout(function(){
HEAVYPROCESSING();
$.mobile.changePage($("#choosearticle"));
}, 50);
return false; // important - stops the two click fall through problem!
}