Greetings.
I am developing an animated homepage for a Flash-HTML hybrid website, and for the sake of standards, my solution is proving difficult. I am not a Javascript pro, so any help is appreciated!
Here is the run-down:
For Flash users, HTML page loads a variable-height AS3 Flash movie that will start at 556 pixels high, and after finishing its animation sequence, tween via Actionscript + JavaScript to 250 pixels high.
To kick off this movie sequence -- (below-left) -- I am attempting to set the initial height of the Flash movie via MooTools, so if users do not have Flash or Javascript enabled, they will see the shorter-height image area with alternative image content and HTML content revealed (below-right).
Element.setStyle sets the height just fine until swfObject runs, at which point the movie collapses since I am not specifying a height via CSS. If users do not have Flash, it defaults to the height of a static image.
So here is my question: Does anyone know how to dynamically pass a height variable to swfobject when it is set up to width/height # 100%? Am I killing myself for no reason trying to work with two page heights?
Image Sequence:
Left - Initial Flash movie with HTML navigation below
Right - Resized movie at the end of the sequence with HTML nav & content below, looks the same as no-Flash version (static image)
alt text http://client.deicreative.com/op/images/twopages.jpg
^^ should land here for users w/o Flash
<script type="text/javascript">
<!--
window.addEvent('domready', function() {
$('flashContent').setStyle('height', 556); // sets height for initial movie
$('homeContent').setStyle('display', 'none'); // hides homepage text + photos below
doSwfObject(); // attempting to start swfObject after setStyle is done
});
function resizePage(h) { // to be called from AS3
var tweenObj = new Fx.Tween('flashContent');
tweenObj.start('height', h);
}
function doSwfObject(){
var flashvars = {};
var params = { scale: "noScale" };
var attributes = { id: "flashContent", name: "flashContent" };
swfobject.embedSWF("swf/homeMovie.swf", "flashContent", "100%", "100%", "9.0.0", false, flashvars, params, attributes);
alert(document.getElementById('flashContent').style.height);
// alerts & shows correct height, but page collapses after hitting 'ok'
}
//-->
</script>
The simplest solution is to embed your SWF in a wrapper DIV. Set the SWF to 100% width/height of the wrapper DIV, then use JS to resize the wrapper DIV, not the <object> itself. Less buggy that way.
Since SWFObject 2 replaces the target DIV with the object, you'll need an additional div in your markup:
<div id="wrapper">
<div id="flashcontent"></div>
</div>
becomes
<div id="wrapper">
<object id="flashcontent" width="100%" height="100%" (etc.) ></object>
</div>
I think the act of posting something on here helps me think through the problem -- after doing so, the answer became more clear. So here is my solution for anyone who stumbles across this later.
To animate the Flash movie's height to its initial, taller state while preserving shorter height for non-Flash users (see images above), I use JavaScript the same way I would to tween the movie's height once sequence is complete. The result resembles a push-down ad on a newspaper website.
In AS3, after preloading is done, I tell Javascript to tween the height of the flash movie container (simplified, obviously -- there is no preloading code):
package {
import flash.display.MovieClip;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.external.ExternalInterface;
public class HomeMovie extends MovieClip {
private var stageHeight:uint;
public function HomeMovie(){
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;
stageHeight = 556;
// Tell javascript the stage needs resizing.
if (ExternalInterface.available) {
ExternalInterface.call("resizePage", stageHeight);
}
}
}
}
In JavaScript (via MooTools):
<script type="text/javascript">
<!--
window.addEvent('domready', function() { // hide content on home-page below movie
$('homeContent').setStyle('display', 'none');
});
function resizePage(h) {
var tweenObj = new Fx.Tween('flashContent', {
property:'height',
duration:500,
transition:Fx.Transitions.Quad.easeOut
});
tweenObj.start(h);
}
//-->
</script>
I will probably take it one step further and check for Flash before hiding the home-page content, so that it will not occur if the user has Javascript but not Flash. Again, this is all for the sake of standards.
Have you tryed SWFForceSize? It's an SWFObject addon and it could help you. Even if you don't use it, you could take a look at the source code to see how they do things.
Btw you don't need SWF object when using Mootools as it has a call called Swiff that does everything SWFObject does and then some! :D
Related
Im in the process of developing a 'flipbook-style' animation using Skrollr by triggering background image changes when the user scrolls to indicated positions on the page. The issue i'm having is that in browser the image changes are delayed, creating what can only be defined as a 'flicker' of white between the frames.
<div class="section" style="background: url('frame1.png')"
data-560-top="background-image:!url('frame1.png');"
data-440-top="background-image:!url('frame2.png');">
The HTML is simple; it basically states that at 560 pixels from the top of the div (in relation to the browser window), the background should be at frame 1, then as the user scrolls closer to the div (440 pixels from the top of the div) the background image changes to frame 2. I plan to use up to around 20 frames and the images are quite large.
I have created a JSBin here which includes a very simplified sample with images from placehold.it. This includes the Skrollr script and an example layout of a section of my project. The key difference being that the images in my project are of much larger scale.
(function($) {
var cache = [];
// Arguments are image paths relative to the current page.
$.preLoadImages = function() {
var args_len = arguments.length;
for (var i = args_len; i--;) {
var cacheImage = document.createElement('img');
cacheImage.src = arguments[i];
cache.push(cacheImage);
}
};
})(jQuery);
jQuery.preLoadImages(
'http://www.placehold.it/300x200.png',
'http://www.placehold.it/300x200.png'
);
The above snippet seems to be working on Chrome, however the flicker issue remains in Firefox. Based on research, firefox handles cached images differently from Chrome? (e.g Where an image is not considered needed by firefox at a given time, it is trashed?)
I would like to know how I could possibly force all browsers to preload the images efficiently, to potentially avoid the background image flicker upon change. I am still quite new to Javascript/JQuery.
I hope I have provided a clear explanation. All assistance appreciated.
Dan
You can preload images using CSS only, no need for JS. Check out this article for more info. Another interesting way to do it is in the comment section of the article. Basically you assign the background image to a pseudo-element so that is is cached and ready to be used whenever. See this code for an example:
#something:before {
content: url("./img.jpg");
width:0;
height:0;
visibility:hidden;
}
I've been looking around the web for an answer for a couple of hours and cannot find anything so I'm hoping someone can help me.
I want to take the height of a wrapper div who's class is movie and apply it to an inner div who's class is movie-center. How can I do this using JS or jQuery?
I am a newbie when it comes to JS, so I would really appreciate if you could lay everything out for me (including any HTML needed).
Thank you!
EDIT 1: Maybe if I am explaining what I am doing people will have a better understanding. I am making a responsive WordPress theme. As the width of the browser is smaller, the movie widths are smaller. I want the overlay title and graphic to stay in the center. I tried doing this with CSS and it cannot be done fully unless I know the exact height (which I won't because of resizing).
EDIT 2: here is the browser's rendered html code:
<article id="movie-97" class="post-97 movie type-movie status-publish hentry"><a href="http://localhost:8888/movies/hard-truth-levity-hope">
<div class="movie-center">
<div class="movie-overlay">
<div class="movie-play"></div>
<h2 class="movie-title">Hard Truth, Levity and Hope</h2>
</div> <!-- end .movie-overlay -->
</div> <!-- end .movie-center -->
<div class="movie-thumb"><img width="480" height="270" src="http://localhost:8888/wp-content/uploads/2014/03/truth-levity-hope.jpg" class="attachment-movie-thumb wp-post-image" alt="Hard Truth, Levity and Hope" /></div>
EDIT 3: Here's a Pastebin for my website. Note: it has been stripped down to only show the essential parts of the site.
What you've done is the correct way. Make sure you've loaded jQuery properly and try to wrap your code inside DOM ready handler $(document).ready(function() {...}); or shorter form $(function() {...});
$(function() {
$('.movie').each(function() {
var h = $(this).height();
$(this).find('.movie-center').height(h);
});
});
Edit: Since you're using Wordpress, there's probably a conflict happen here, try to use:
jQuery(document).ready(function($) {
$('window').resize(function() {
$('.movie').each(function() {
var h = $(this).height();
$(this).find('.movie-center').height(h);
});
}).resize();
});
Please try this :
/* Get height of .movie thumb preview */
jQuery(document).ready(function($) {
$('.movie').each(function() {
var h = $(this).height();
console.log(h);
$(this).find('.movie-center').first().css('height',h);
console.log($(this).find('.movie-center').first().height())
});
});
Connor,
This will get you what you're looking for:
jQuery(document).ready(function($) {
$('.movie').each(function() {
var h = $(this).height();
$(this).find('.movie-center').height(h);
});
});
A quick explanation. You'll notice that jQuery's .height() function is called twice. First, without any params and then with h passed in.
Pull up your JS console (cmd+opt+j if you're using Chrome) to see how this actually works.
The question at the top of this page has an id of #question-header, so if you enter this in the console $('#question-header').height() you'll see that it returns 36. That's because that element is 36 pixels tall.
So, calling .height without any params will return the height of the selected element. But, we can set the height by passing in a number. Try this by pasting this in to the JS console:
$('#question-header').height(1000)
The header is now 1000px tall!
The third line of the code basically says, "Hey, within this particular instance of the .movie article, find the .movie-center element and set the height.
So, there you go. Some working code and hopefully an explanation as to exactly why/how to use it in the future.
I am trying to make a flipbook using turn.js that has the same functionality as the example on the website http://www.turnjs.com/samples/magazine/
When looking at how to achieve this I came across these pages
http://www.turnjs.com/docs/Method:_zoom
http://turnjs.com/docs/How_to_add_zoom_to_turn.js
But after following these instructions on the pages my flipbook works nothing like the sample one.
I tried using the sample provided and breaking it down into sections to get mine working but I have not gotten any closer to solving this problem and the sample contains a bunch of other scripts and I am not sure if they are required for the zoom or are used for other things.
Not sure if I am missing something really simple or if my code is really off but my html looks something like this.
Right now all I get when clicking the zoom button is that the book scales up 150%
Was wondering if anyone could tell me what I am missing to get that zoom?
<div class="row">
<div id="zoom-viewport">
<div id="flipbook">
// wordpress loop
<div class="page">
// page contents
</div>
// end loop
</div>
</div>
</div>
and jQuery
//----------------------------
// Initialize
var _width = $('#flipbook-wrap').width(),
_height = Math.round(70.909090909/100*_width),
_winWidth = $window.width(),
_winHeight = $window.height();
$("#flipbook").turn({
width: _width,
height: _height,
autoCenter: true
});
//----------------------------
// Zoom in button
$('.fullscreen').click(function(e){
e.preventDefault();
$("#flipbook").turn("zoom", 1.5);
});
Your code isn't showing everything (e.g. where ".fullscreen" or the "zoom button" is in your HTML), so my answer may not be precise.
Looking at the sample, you should find the code:
$('.magazine-viewport').zoom('zoomIn', pos);
This seems to differ from turn('zoom', ...), and appears to be undocumented. This is a function that will zoom in the element defined as a turn object. I believe, for you, this is your "#flipbook" element, instead of ".magazine-viewport".
The parameters are "zoomIn" and pos, which may be a different functionality that what you're using currently. The "pos" appears to be a JS object that contains "x" and "y" properties, meant to define where you clicked on the magazine. These coordinates are relative to the magazine, not the whole screen, so keep that in mind.
So, I think you need something like this (at least try it at a starting point):
$('#flipbook').click(function(e) {
var pos = {
x: e.pageX - $(this).offset().left,
y: e.pageY - $(this).offset().top
};
$('#flipbook').zoom('zoomIn', pos);
});
Hope this helps!
To get zoom to work with turn.js, there are three things you need to do:
Setup the proper dom structure, zoom won't work without the "container" div to wrap the flipbook.
<div class="magazine-viewport">
<div class="container">
<div class='magazine'>
<div id='p1'><img src='book_1.jpg'></div>
<div id='p2'><img src='book_2.jpg'></div>
</div>
</div>
</div>
Setup the js events
$( document ).ready(function() {
//Initialize the turn.js flipbook
$('.magazine').turn({
width: 1136,
height:734,
pages:100,
autoCenter: false,
when:{
missing: function (e, pages) {
for (var i = 0; i < pages.length; i++) {
$('.magazine').turn('addPage',page[pages[i]],pages[i]);
}
}
}
});
//Initialize the zoom viewport
$('.magazine-viewport').zoom({
flipbook: $('.magazine')
});
//Binds the single tap event to the zoom function
$('.magazine-viewport').bind('zoom.tap', zoomTo);
//Optional, calls the resize function when the window changes, useful when viewing on tablet or mobile phones
$(window).resize(function() {
resizeViewport();
}).bind('orientationchange', function() {
resizeViewport();
});
//Must be called initially to setup the size
resizeViewport();
}
function page(num){
var elem = $('<div />',{}).html('<div><img src="book_'+num+'.jpg></div>');
return elem;
}
function zoomTo(event) {
setTimeout(function() {
if ($('.magazine-viewport').data().regionClicked) {
$('.magazine-viewport').data().regionClicked = false;
} else {
if ($('.magazine-viewport').zoom('value')==1) {
$('.magazine-viewport').zoom('zoomIn', event);
} else {
$('.magazine-viewport').zoom('zoomOut');
}
}
}, 1);
}
function resizeViewport() {
var width = $(window).width(),
height = $(window).height(),
options = $('.magazine').turn('options');
$('.magazine-viewport').css({
width: width,
height: height
}).zoom('resize');
}
Define proper css styles for the elements, the trick here is that the negative coordinates of the magazine class is compensated by the top & left offsets of the container class.
.magazine-viewport .container{
position:absolute;
top:367px;
left:568px;
width:1136px;
height:734px;
margin:auto;
}
.magazine-viewport .magazine{
width:1136px;
height:734px;
left:-568px;
top:-367px;
}
/* Important: the image size must be set to 100%.
* Otherwise the position of the images would be messed up upon zooming.
*/
.magazine img{
width:100%;
height:100%;
}
That should get it to work, if you want to load a larger version of the image upon zooming, take a look at the loadSmallPage() & loadLargePage() functions in the magazine example.
I had the same problem, but I decided to just use a third party zoom plugin (Jack Moore's jQuery zoom). It turns out the example in the site is a lot more complicated, with a json to create diferent regions and images for each paragraph.
It really depends on what you're using turn.js for, but I think the documentation isn't right, or the software itself is missing something. Either way, I do suggest you look into using some other solution for the problem.
turn.js provides an example with zoom. The difficulty to make it work is to gather all the required files. But if you watch the code, it is possible. Say the root is magazine, it goes two folders up to get lib and extras folders where java scripts are laying. In addition, you have to add the "default" and large pages in the pages folder. When you get the sample, there are only the thumbnails in. Say for 1-thumb.jpg, you have to add 1.jpg and 1-large.jpg
There is a very usefull Firefox plugin to get them : CacheViewer.
I have managed to do it with my book, and reorganize the paths in the code to have something cleaner: put lib and extras at the same level than pages. A recursive grep for "/../../" will give you all the locations in html and js code.
I'm using epiceditor within my site, and I am populating it with markdown embedded on the page by the server. Currently when epiceditor displays, it has a very small default height, with scroll bars to handle viewing the entire content. I can manually set the height of the div, and for now that's the best I've been able to do (I've set it to something reasonably large: 800px). However I would like its height to always be enough to fit the entire content without scroll-bars. Essentially something like overflow:visible.
Here's the relevant portions so far
<html>
<head>
<script src="/assets/javascripts/epiceditor/js/epiceditor.min.js" type="text/javascript"></script>
<script id="postMarkdown" type="text/markdown" data-postId="1">
#Markdowns in here
...
</script>
<style>
#epiceditor{
height: 800px;
}
</style>
<script src="/assets/javascripts/thrown/posts/edit.js" type="text/javascript"></script>
</head>
<body>
<div id="epiceditor">
</div>
</body>
</html>
And heres the edit.js source (its compiled from coffescript)
$ ->
postMarkdown = $("#postMarkdown").first()
options =
basePath : '../../assets/javascripts/epiceditor'
editor = new EpicEditor(options).load()
postId = postMarkdown.data('postId')
markdown = postMarkdown.html()
editor.importFile('posts/'+postId,markdown);
editor.reflow();
I was hoping reflow might expand the height after the content was inserted, however no such luck. However If I resize the div and call reflow, It does resize properly.
I've inspected the markup it creates in hopes I could determine the height and resize its container and tell it to reflow. However it seems it contains multiple iframes, and at a glance I didn't expect that to be a quick change, or if it would even be possible. However I'd welcome any solution.
I also understand that if I size its container to the right height, epiceditor will fill the proper space. However I want its height to be the amount needed to render, such that the editor takes up the right space in the rest of the sites design. Therefore if there something I can set in EpicEditor to have it not overflow in the manner it is, or a way to determine the height after it loads, I'm set.
Thanks for any help.
I'm the guy who made EpicEditor, here's a solution for you:
var editor = new EpicEditor({
basePath: 'https://raw.github.com/OscarGodson/EpicEditor/develop/epiceditor'
});
var updateEditorHeight = function () {
editorHeight = $(editor.getElement('editor').body).height();
// +20 for padding
$('#epiceditor').height(editorHeight + 20);
editor.reflow();
}
editor.load(function (){
updateEditorHeight();
});
editor.on('update', function () {
// You should probably put a check here so it doesn't
// run for every update, but just on update, AND if the
// element's height is different then before.
updateEditorHeight();
});
Also, in the CSS I added a overflow: hidden to epiceditor's wrapper so the scrollbars don't appear as it grows.
DEMO: http://jsbin.com/eyidey/1/
DEMO CODE: http://jsbin.com/eyidey/1/edit
UPDATE
As of EpicEditor 0.2.2 autogrow is built in. Just turn on the autogrow option.
I have this code below:
<script type="text/javascript">
jwplayer("container").setup({
flashplayer: "http://test.captive-portal.com/jwplayer/player.swf",
file: "http://content.captive-portal.com/files/video/cirque-du-soleil/mob.mp4",
image: "http://content.captive-portal.com/files/video/cirque-du-soleil/mob.jpg",
height: 285,
width: 480,
});
</script>
The whole page is here (in case you need it): video page.
What I'm trying to do is to change the 4 lines: file: (...), image (...), height(...) and width (...) depending of the resolution of the window. I have managed to do this with css, so styles are applied correctly, but this is javascript and I don't really know how to modify it. I was trying to place 2 similar scripts on one page in divs and hide the small one in case of big screen or hide a big one in case of small screen but it didn't work. Video didn't play. I think this may be caused by some scripts in the flash player file.
Is there any way to set conditions for those 4 lines depending of the screen resolution?
Thank you very much for your help in advance.
Those parameters are simply an object.
So you should be able to create that object out of the jwplayer call, and simply pass it in. e.g
var params = {};
params.flashplayer = "http://test.captive-portal.com/jwplayer/player.swf";
if(!mobile){ //you need to handle checking for mobile devices
params.file = "http://content.captive-portal.com/files/video/cirque-du-soleil/desktop.mp4";
params.image = "http://content.captive-portal.com/files/video/cirque-du-soleil/desktop.jpg";
params.height = 570;
params.width = 960;
}else{
//set params in same way but with mobile settings
}
jwplayer("container").setup(params);
If you later want to just resize the player. JwPlayer has a 'resize' function that you can call: jwplayer.resize(width,height)