I have a React.js component that renders a list of elements on page load, but this list can be updated with a filter that will remove certain elements from the list and save the modified list in the component's state. I managed to make this functionnality work, so the state is updated correctly.
While the elements get re-rendred correcly, less space is used when less elements are rendred. When this happens, the page's height doesn't shrink to adapt to the new size occupied by the page and leaves empty content under my footer, which is the last element of my page.
Edit :
I looked a bit more into this and I think React.js may not be the cause of my problem. I call a function that uses imagesLoaded and Wookmark jQuery plugins after each update of the component's state and it looks like calling this function after each state change does not work well. Is there something I should change in the called function or I should call the function at another point in time?
var ActivityListClass = React.createClass({
loggedInUser: {},
componentDidUpdate: function() {
activityListImageResponsiveness(); // This is the function
},
componentDidMount: function() {
var theActivityList = this;
var activitiesGetListener = postal.subscribe({
channel: "activities",
topic: "list",
callback: function(data, envelope) {
var dataClone = $.extend(true, {}, data);
dataClone.activities.shift();
theActivityList.setState({data: dataClone.activities});
theActivityList.loggedInUser = dataClone.loggedInUser;
}
});
},
getInitialState: function() {
return {data: []};
},
render: function() {
var i = 0;
var activityNodes = this.state.data.map(function(activity) {
var currentId = i;
i++;
return (
<ActivityClass key={currentId} data={activity} />
);
});
return (
<section id="listArticles">
{activityNodes}
</section>
);
}
});
And the function called is defined like this :
function activityListImageResponsiveness() {
$('#listArticles').imagesLoaded(function() {
// Get a reference to your grid items.
var $handler = $('#listArticles article');
$handler.on("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend", function(event) {
if(event.originalEvent.propertyName == 'top'){
$('#listArticles').trigger("refreshWookmark");
}
});
// Prepare layout options.
var options = {
align: 'left',
autoResize: true, // This will auto-update the layout when the browser window is resized.
container: $('#listArticles'), // Optional, used for some extra CSS styling
direction: 'left',
fillEmptySpace: true, // Optional, fill the bottom of each column with widths of flexible height
flexibleWidth: '16.635%',
itemWidth: $handler.width(), // Optional, the width of a grid item
offset: 42, // Optional, the distance between grid items
verticalOffset: 15
};
var $window = $(window);
$window.resize(function() {
var windowWidth = $window.width(),
newOptions = {
flexibleWidth: '16.635%',
itemWidth: 208
};
// NOTE: These values are the same as the "media queries" of the CSS file.
if(windowWidth >= 1263){
newOptions.flexibleWidth = '16.635%';
newOptions.itemWidth = 208;
} else if (windowWidth >= 1132){
newOptions.flexibleWidth = '21.05263157894737%';
newOptions.itemWidth = 236;
}else if(windowWidth >= 1014){
newOptions.flexibleWidth = '20.71713147410359%';
newOptions.itemWidth = 208;
}else if(windowWidth >= 852){
newOptions.flexibleWidth = '27.99525504151839%';
newOptions.itemWidth = 236;
}else if(windowWidth >= 764){
newOptions.flexibleWidth = '27.51322751322751%';
newOptions.itemWidth = 208;
}else if(windowWidth >= 626){
newOptions.flexibleWidth = '42.58064516129032%';
newOptions.itemWidth = 264;
}else if(windowWidth >= 515){
newOptions.flexibleWidth = '40.7843137254902%';
newOptions.itemWidth = 208;
}else{
newOptions.flexibleWidth = '83.80952380952381%';
newOptions.itemWidth = 264;
}
$handler.wookmark(newOptions);
});
// Call the layout function.
$handler.wookmark(options);
});
}
I found that Wookmark leaves behind invisible divs in the listArticles section that contains my rendered elements, which explains why I had a weird blank space in the bottom of my page. I tried removing all these divs before each render with $("#listArticles .wookmark-placeholder").remove(); It looks like it's working, but renders of the component are a bit slower.
To do this, I added the componentWillUpdate function to my React component:
componentWillUpdate: function() {
$("#listArticles .wookmark-placeholder").remove();
},
Related
I'm using an existing code, written not by me and I have a very limited experience in Java. The code creates a filtered gallery with 15 pics per page using isotope.pkgd.min. Each pic can be opened in a popup, magnific popup.
The problem: I have a filter item e.g. nature with 30-40 pics. The code creates two pages with 15 items per page. However also the popup shows only 15 items and not 30-40. What do I need to do, in order to show 30-40 items in popup but keep 15 items per page in the gallery? Many thanks in advance for your help
$(document).ready(function () {
/*************** Gallery ******************/
var itemSelector = ".tm-gallery-item";
var responsiveIsotope = [ [480, 4], [720, 6] ];
var itemsPerPageDefault = 15;
var itemsPerPage = defineItemsPerPage();
var currentNumberPages = 1;
var currentPage = 1;
var currentFilter = '*';
var filterValue = "";
var pageAttribute = 'data-page';
var pagerClass = 'isotope-pager';
var $container = $('.tm-gallery-container').isotope({
itemSelector: itemSelector
});
function adjustGalleryLayout(currentPopup) {
if(currentPopup == 'gallery') {
// layout Isotope after each image loads
$container.imagesLoaded().progress( function() {
$container.isotope('layout');
});
}
}
/************** Popup *****************/
$('#inline-popups').magnificPopup({
delegate: 'a',
removalDelay: 500, //delay removal by X to allow out-animation
callbacks: {
beforeOpen: function() {
this.st.mainClass = this.st.el.attr('data-effect');
},
open: function() {
adjustGalleryLayout($.magnificPopup.instance.content.attr('id'));
}
},
midClick: true, // allow opening popup on middle mouse click. Always set it to true if you don't provide alternative source.
showCloseBtn: false
});
$('.tm-close-popup').on( "click", function() {
$.magnificPopup.close();
});
var popupInstance = $.magnificPopup.instance;
$('.tm-btn-next').on("click", function(e) {
popupInstance.next();
adjustGalleryLayout(popupInstance.content.attr('id'));
});
$('.tm-btn-contact').on("click", function(e) {
popupInstance.goTo(4);
})
// update items based on current filters
function changeFilter(selector) { $container.isotope({ filter: selector });
$(selector).magnificPopup({
delegate: 'a',
type:'image',
gallery:{
enabled:true
}
})
}
// grab all checked filters and goto page on fresh isotope output
function goToPage(n) {
currentPage = n;
var selector = itemSelector;
var exclusives = [];
if(currentFilter != '*') {
exclusives.push(selector + '.' + currentFilter);
}
// smash all values back together for 'and' filtering
filterValue = exclusives.length ? exclusives.join('') : '*';
a=exclusives;
// add page number to the string of filters
var wordPage = currentPage.toString();
filterValue += ('.'+wordPage);
changeFilter(filterValue);
}
// determine page breaks based on window width and preset values
function defineItemsPerPage() {
var pages = itemsPerPageDefault;
for( var i = 0; i < responsiveIsotope.length; i++ ) {
if( $(window).width() <= responsiveIsotope[i][0] ) {
pages = responsiveIsotope[i][1];
break;
}
}
return pages;
}
function setPagination() {
var SettingsPagesOnItems = function(){
var itemsLength = $container.children(itemSelector).length;
var pages = Math.ceil(itemsLength / itemsPerPage);
var item = 1;
var page = 1;
var selector = itemSelector;
var exclusives = [];
if(currentFilter != '*') {
exclusives.push(selector + '.' + currentFilter);
}
// smash all values back together for 'and' filtering
filterValue = exclusives.length ? exclusives.join('') : '*';
// find each child element with current filter values
$container.children(filterValue).each(function(){
// increment page if a new one is needed
if( item > itemsPerPage ) {
page++;
item = 1;
}
// add page number to element as a class
wordPage = page.toString();
var classes = $(this).attr('class').split(' ');
var lastClass = classes[classes.length-1];
// last class shorter than 4 will be a page number, if so, grab and replace
if(lastClass.length < 4){
$(this).removeClass();
classes.pop();
classes.push(wordPage);
classes = classes.join(' ');
$(this).addClass(classes);
} else {
// if there was no page number, add it
$(this).addClass(wordPage);
}
item++;
});
currentNumberPages = page;
}();
// create page number navigation
var CreatePagers = function() {
var $isotopePager = ( $('.'+pagerClass).length == 0 ) ? $('<div class="'+pagerClass+' tm-paging"></div>') : $('.'+pagerClass);
$isotopePager.html('');
if(currentNumberPages > 1){
for( var i = 0; i < currentNumberPages; i++ ) {
var $pager = '';
if(currentPage == i+1) {
$pager = $('');
} else {
$pager = $('');
}
$pager.html(i+1);
$pager.click(function(){
$('.tm-paging-link').removeClass('active');
$(this).addClass('active');
var page = $(this).eq(0).attr(pageAttribute);
goToPage(page);
});
$pager.appendTo($isotopePager);
}
}
$container.after($isotopePager);
}();
}
setPagination();
goToPage(1);
//event handlers
$('.tm-gallery-link').click(function(e) {
var filter = $(this).data('filter');
currentFilter = filter;
setPagination();
goToPage(1);
$('.tm-gallery-link').removeClass('active');
$(e.target).addClass('active');
})
//Handle window resize
$(window).resize(function(){
itemsPerPage = defineItemsPerPage();
setPagination();
goToPage(1);
});
});
I am developing a website using VueJs and I have used JQuery for the scroll function.
I am incrementing the page no when the user scrolls to the bottom of the page.
At first (page = 1) it shows just one request.
But when scroll down then two requests are firing at once (page = 2, page = 3).
getDisplay() function used to get the data and I have set LIMIT and OFFSET values for that.
mounted: function() {
this.getDisplay();
this.bindScroll();
},
methods: {
bindScroll: function(){
var vm = this;
$(window).bind('scroll', function () {
if ($(window).scrollTop() === $(document).height() - $(window).height()) {
if(vm.isMorePost > 0){
vm.showLoading = 1;
vm.page++;
vm.getDisplay();
}
}
})
},
getDisplay: function() {
var input = {
name: this.userId,
recordPerPage: this.recordPerPage,
page: this.page
};
this.loadingIcon = 1;
this.$http.get('/display-view/show/get-user-display', {params: input}).then(function(response) {
this.display = this.display.concat(response.data.data);
this.isMorePost = (response.data.data.length);
if(response.data.data.length == 0){
this.showLoading = 0
}else {
this.showLoading = 1
}
}.bind(this));
}
},
I need to fire just one request with incremented page no when the user meets bottom of the page. How can I solve this?
I have a directive in a table element that allows horizontal scroll. I have a fixed header which left position I update by binding the scroll event to the element that holds the directive(the table):
The link function of the directive updates the header position on the screen and brings a div over the table to block pointer-events.
It is obvious that this function forces some style recalc so my question is:
In the angular.js world what would be the best aproach. Should I use $animate, should I be setting the timeout the way I do it, would I avoid extended frames by requesting an animation frame(how is that done for this example?). Which way is best for performance?
Here is my current directive:
app.directive('checkScroll', function() {
return {
// require: '^?listeditorController',
link: function(scope, elem, attrs) {
var timer = null;
var screenBlock= document.getElementsByClassName('blockEventsScreen')[0];
// var lastLeft = 0;
// requestAnimationFrame( scope.onScroll );
elem.bind('scroll', function() {
if(timer !== null) {
//clear previous timer that turned off the during scroll tweaks
clearTimeout(timer);
clearInterval(scope.interval);
scope.interval = undefined;
//This sets the left style attribute of the table header container to the same value as the table body
var el=document.getElementsByClassName('fixedHeader')[0];
var newLeft = elem[0].getElementsByClassName('superResponsive')[0].getBoundingClientRect().left;
screenBlock.style['transform'] = 'translateX(0px)';
screenBlock.style['msTransform'] = 'translateX(0px)';
screenBlock.style['MozTransform'] = 'translateX(0px)';
screenBlock.style['WebkitTransform'] = 'translateX(0px)';
screenBlock.style['OTransform'] = 'translateX(0px)';
// var diff= Math.abs(newLeft - lastLeft );
// if(diff>0){
el.style['transform'] = 'translateX('+newLeft+'px)';
el.style['msTransform'] = 'translateX('+newLeft+'px)';
el.style['MozTransform'] = 'translateX('+newLeft+'px)';
el.style['WebkitTransform'] = 'translateX('+newLeft+'px)';
el.style['OTransform'] = 'translateX('+newLeft+'px)';
// lastLeft=newLeft;
// scope.$apply(function(){
// $scope.headerLeft=newLeft+'px';
// });
// requestAnimationFrame( scope.onScroll );
// }
}
timer = setTimeout(function() {
//remove screen of table to enable pointer-events
screenBlock.style['transform'] = 'translateX(-10000px)';
screenBlock.style['msTransform'] = 'translateX(-10000px)';
screenBlock.style['MozTransform'] = 'translateX(-10000px)';
screenBlock.style['WebkitTransform'] = 'translateX(-10000px)';
screenBlock.style['OTransform'] = 'translateX(-10000px)';
//restart scaleheader after scrolling
scope.interval = setInterval( function(){scope.scaleHeader();}, 200);
}, 200);
});
}
}
});
The following piece of code loads the next page, when the user scrolls to the bottom. However, sometimes it is repeating itself — when the user scrolls too rapidly, or scrolls whilst the AJAX is still being loaded.
Is there a way to prevent it from firing multiple times? So for example, nothing can be loaded while the AJAX is being called, or the AJAX can only be called once a second?
Any help would be great.
$(window).scroll(function() {
if( $(window).scrollTop() + $(window).height() == $(document).height()) {
if (firstURL !== null) {
$.get(firstURL, function(html) { // this gets called multiple times on erratic scrolling
firstURL = '';
var q = $(html).find('.post');
l = $(html).filter('div.bottom-nav');
if( l[0].childNodes.length > 0 ){
firstURL = l[0].children[0].getAttribute('href');
} else {
firstURL = null;
}
q.imagesLoaded( function() {
jQuery(".content").append(q).masonry( 'appended', q, true );
});
});
}
}
});
Just add a flag :
var ready = true; //Assign the flag here
$(window).scroll(function() {
//Check the flag here. Check it first, it's better performance wise.
if(ready && $(window).scrollTop() + $(window).height() == $(document).height()) {
ready = false; //Set the flag here
if (firstURL !== null) {
$.get(firstURL, function(html) { // this gets called multiple times on erratic scrolling
firstURL = '';
var q = $(html).find('.post');
l = $(html).filter('div.bottom-nav');
if( l[0].childNodes.length > 0 ){
firstURL = l[0].children[0].getAttribute('href');
} else {
firstURL = null;
}
q.imagesLoaded( function() {
jQuery(".content").append(q).masonry( 'appended', q, true );
});
}).always(function(){
ready = true; //Reset the flag here
});
}
}
});
I had a similar issue, that scrolling the window fired my function multiple times (manupulating my img slider's properties). To effectively deal with that matter you can defer the execution of scroll handler and use an additional 'page is being scrolled' flag to prevent multiple handler calls.
Check out the example below, you can surely addopt the approach to your case.
$(function()
{
var pageFold = 175; //scrolling threshold
var doScroll = false; //init
var timeoutScroll = 100; //delay
var windowScrolled = false; //initial scrolling indicatior
var windowScrolling = false; //current scrolling status indicator
//load next page handler
function loadNextPage()
{
if(windowScrolling != true)
{
//and do ajax stuff - your code
}
}
//check if page scrolled below threshold handler
function foldedBelow()
{
//nice scrolled px amount detection
return (Math.max($('body').scrollTop(), $('html').scrollTop()) > pageFold);
}
//actual scrolled handler
function doWindowScroll()
{
windowScrolled = true;
if(foldedBelow())
{
loadNextPage();
}
windowScrolling = false;
}
//deffered scroll hook
$(window).scroll(function(e){
windowScrolling = true;
clearTimeout(doScroll);
doScroll = setTimeout(doWindowScroll, timeoutScroll);
});
});
When I did something like this I implemented a timed scroll handler that calls a custom scrolled_to_bottom-event.
(function($, window, document){
"use strict";
var $document = $(document);
var $window = $(window);
var _throttleTimer = null;
var _throttleDelay = 100;
function ScrollHandler(event) {
//throttle event:
clearTimeout(_throttleTimer);
_throttleTimer = setTimeout(function () {
if ($window.scrollTop() + $window.height() > $document.height() - 400) {
console.log('fire_scrolled_to_bottom');
$document.trigger('scrolled_to_bottom');
}
}, _throttleDelay);
}
$document.ready(function () {
$window
.off('scroll', ScrollHandler)
.on('scroll', ScrollHandler);
});
}(jQuery, window, document));
And then in my object handling the reload I bound that event with a flag-check if it was already loading.
handler = {
...,
isLoading: false,
bind: {
var self = this;
$document.on('scrolled_to_bottom', function () {
if (self.isLoading) {
return;
}
self.nextPage();
});
}
nextPage(): function () {
var self = this;
this.isLoading = true;
$.ajax({
url: url,
data: self.searchData,
dataType: "json",
type: "POST",
success: function (json) {
// do what you want with respone
},
error: function (xhr, statusText, errorThrown) {
bootbox.alert('An error occured.');
},
complete: function () {
self.isLoading = false;
}
});
},
init: function () {
this.doInitStuff();
this.bind();
}
}
This way I seperated the concerns and can reuse the triggering nicely, and easily add functionality if other things should happen on reload.
Try storing some kind of data that stores whether the page is currently loading new items. Maybe like this:
$(window).data('ajaxready', true).scroll(function(e) {
if ($(window).data('ajaxready') == false) return;
if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
$('div#loadmoreajaxloader').show();
$(window).data('ajaxready', false);
$.ajax({
cache: false,
url: 'loadmore.php?lastid=' + $('.postitem:last').attr('id'),
success: function(html) {
if (html) {
$('#postswrapper').append(html);
$('div#loadmoreajaxloader').hide();
} else {
$('div#loadmoreajaxloader').html();
}
$(window).data('ajaxready', true);
}
});
}
});
Right before the Ajax request is sent, a flag is cleared signifying that the document is not ready for more Ajax requests. Once the Ajax completes successfully, it sets the flag back to true, and more requests can be triggered.
copied : jQuery Infinite Scroll - event fires multiple times when scrolling is fast
Here is my solution. You can get an idea and apply it to yours. Also to help others.
You can execute your method first with condition: if(loadInterval ===
null). That means if we already waited for 5 secs.
Assign loadInterval = setTimeout(), then nullify the variable after 5 secs.
Here is sample code.
//declare outside
var loadInterval = null;
// .....
// .....
$(window).scroll(function() {
if ($('.loadmore').isOnScreen() === true) {
//No waiting registered, we can run loadMore
if(loadInterval === null) {
// This console.log executes in 5 seconds interval
console.log('Just called ' + new Date());
// your code in here is prevented from running many times on scroll
// Register setTimeout() to wait for some seconds.
// The code above will not run until this is nullified
loadInterval = setTimeout(function(){
//Nullified interval after 5 seconds
loadInterval = null;}
, 5000);
}
}
});
I post here the IsOnScreen() plugin for jQuery (i found it on stackoverflow :)
$.fn.isOnScreen = function() {
var win = $(window);
var viewport = {
top: win.scrollTop(),
left: win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};
I am able to create a full background video using jquery on a new page, but I am having issues filling an existing container on a page with the video. I am looking to be able to use this code to add the video to a couple of different containers on a single page. Such as a section and the hero unit. Although for now I am just trying to figure out how to add it to the hero unit and I can go from there. I tried replacing all videobg class and videobg_wrapper classes with the hero class, although it still isn't working.
Can anyone assist me? Any help would be appreciated. Here is a jfiddle with the jquery and css class.
Jfiddle with code: http://jsfiddle.net/NN276/12/
Fullscreen Jfiddle: http://jsfiddle.net/NN276/12/embedded/result/
Here is an attempt to change videobg to the hero class:
(function( $ ){
$.fn.videoBG = function( selector, options ) {
var options = {};
if (typeof selector == "object") {
options = $.extend({}, $.fn.videoBG.defaults, selector);
}
else if (!selector) {
options = $.fn.videoBG.defaults;
}
else {
return $(selector).videoBG(options);
}
var container = $(this);
// check if elements available otherwise it will cause issues
if (!container.length)
return;
// container to be at least relative
if (container.css('position') == 'static' || !container.css('position'))
container.css('position','relative');
// we need a width
if (options.width == 0)
options.width = container.width();
// we need a height
if (options.height == 0)
options.height = container.height();
// get the wrapper
var wrap = $.fn.videoBG.wrapper();
wrap.height(options.height)
.width(options.width);
// if is a text replacement
if (options.textReplacement) {
// force sizes
options.scale = true;
// set sizes and forcing text out
container.width(options.width)
.height(options.height)
.css('text-indent','-9999px');
}
else {
// set the wrapper above the video
wrap.css('z-index',options.zIndex+1);
}
// move the contents into the wrapper
wrap.html(container.clone(true));
// get the video
var video = $.fn.videoBG.video(options);
// if we are forcing width / height
if (options.scale) {
// overlay wrapper
wrap.height(options.height)
.width(options.width);
// video
video.height(options.height)
.width(options.width);
}
// add it all to the container
container.html(wrap);
container.append(video);
return video.find("video")[0];
}
// set to fullscreen
$.fn.videoBG.setFullscreen = function($el) {
var windowWidth = $(window).width(),
windowHeight = $(window).height();
$el.css('min-height',0).css('min-width',0);
$el.parent().width(windowWidth).height(windowHeight);
// if by width
if (windowWidth / windowHeight > $el.aspectRatio) {
$el.width(windowWidth).height('auto');
// shift the element up
var height = $el.height();
var shift = (height - windowHeight) / 2;
if (shift < 0) shift = 0;
$el.css("top",-shift);
} else {
$el.width('auto').height(windowHeight);
// shift the element left
var width = $el.width();
var shift = (width - windowWidth) / 2;
if (shift < 0) shift = 0;
$el.css("left",-shift);
// this is a hack mainly due to the iphone
if (shift === 0) {
var t = setTimeout(function() {
$.fn.videoBG.setFullscreen($el);
},500);
}
}
$('body > .hero').width(windowWidth).height(windowHeight);
}
// get the formatted video element
$.fn.videoBG.video = function(options) {
$('html, body').scrollTop(-1);
// video container
var $div = $('<div/>');
$div.addClass(hero')
.css('position',options.position)
.css('z-index',options.zIndex)
.css('top',0)
.css('left',0)
.css('height',options.height)
.css('width',options.width)
.css('opacity',options.opacity)
.css('overflow','hidden');
// video element
var $video = $('<video/>');
$video.css('position','absolute')
.css('z-index',options.zIndex)
.attr('poster',options.poster)
.css('top',0)
.css('left',0)
.css('min-width','100%')
.css('min-height','100%');
if (options.autoplay) {
$video.attr('autoplay',options.autoplay);
}
// if fullscreen
if (options.fullscreen) {
$video.bind('canplay',function() {
// set the aspect ratio
$video.aspectRatio = $video.width() / $video.height();
$.fn.videoBG.setFullscreen($video);
})
// listen out for screenresize
var resizeTimeout;
$(window).resize(function() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function() {
$.fn.videoBG.setFullscreen($video);
},100);
});
$.fn.videoBG.setFullscreen($video);
}
// video standard element
var v = $video[0];
// if meant to loop
if (options.loop) {
loops_left = options.loop;
// cant use the loop attribute as firefox doesnt support it
$video.bind('ended', function(){
// if we have some loops to throw
if (loops_left)
// replay that bad boy
v.play();
// if not forever
if (loops_left !== true)
// one less loop
loops_left--;
});
}
// when can play, play
$video.bind('canplay', function(){
if (options.autoplay)
// replay that bad boy
v.play();
});
// if supports video
if ($.fn.videoBG.supportsVideo()) {
// supports webm
if ($.fn.videoBG.supportType('webm')){
// play webm
$video.attr('src',options.webm);
}
// supports mp4
else if ($.fn.videoBG.supportType('mp4')) {
// play mp4
$video.attr('src',options.mp4);
// $video.html('<source src="'.options.mp4.'" />');
}
// throw ogv at it then
else {
// play ogv
$video.attr('src',options.ogv);
}
}
// image for those that dont support the video
var $img = $('<img/>');
$img.attr('src',options.poster)
.css('position','absolute')
.css('z-index',options.zIndex)
.css('top',0)
.css('left',0)
.css('min-width','100%')
.css('min-height','100%');
// add the image to the video
// if suuports video
if ($.fn.videoBG.supportsVideo()) {
// add the video to the wrapper
$div.html($video);
}
// nope - whoa old skool
else {
// add the image instead
$div.html($img);
}
// if text replacement
if (options.textReplacement) {
// force the heights and widths
$div.css('min-height',1).css('min-width',1);
$video.css('min-height',1).css('min-width',1);
$img.css('min-height',1).css('min-width',1);
$div.height(options.height).width(options.width);
$video.height(options.height).width(options.width);
$img.height(options.height).width(options.width);
}
if ($.fn.videoBG.supportsVideo()) {
v.play();
}
return $div;
}
// check if suuports video
$.fn.videoBG.supportsVideo = function() {
return (document.createElement('video').canPlayType);
}
// check which type is supported
$.fn.videoBG.supportType = function(str) {
// if not at all supported
if (!$.fn.videoBG.supportsVideo())
return false;
// create video
var v = document.createElement('video');
// check which?
switch (str) {
case 'webm' :
return (v.canPlayType('video/webm; codecs="vp8, vorbis"'));
break;
case 'mp4' :
return (v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"'));
break;
case 'ogv' :
return (v.canPlayType('video/ogg; codecs="theora, vorbis"'));
break;
}
// nope
return false;
}
// get the overlay wrapper
$.fn.videoBG.wrapper = function() {
var $wrap = $('<div/>');
$wrap.addClass('videoBG_wrapper')
.css('position','absolute')
.css('top',0)
.css('left',0);
return $wrap;
}
// these are the defaults
$.fn.videoBG.defaults = {
mp4:'',
ogv:'',
webm:'',
poster:'',
autoplay:true,
loop:true,
scale:false,
position:"absolute",
opacity:1,
textReplacement:false,
zIndex:0,
width:0,
height:0,
fullscreen:false,
imgFallback:true
}
})( jQuery );
$(document).ready(function() {
$('body').videoBG({
position:"fixed",
zIndex:0,
mp4:'http://www.pete.dj/video/video.mp4',
ogv:'http://www.pete.dj/video/video.ogv',
webm:'http://www.pete.dj/video/video.webm',
opacity:1,
fullscreen:true,
});
})
Not the complete solution as they all don't play immediately, but somewhere to start.
$('.hero').each(function() {
$(this).videoBG({
position:"relative",
zIndex:0,
mp4:'http://www.pete.dj/video/video.mp4',
ogv:'http://www.pete.dj/video/video.ogv',
webm:'http://www.pete.dj/video/video.webm',
opacity:1,
fullscreen:false,
});
});
Working JSFiddle: http://jsfiddle.net/NN276/15/
Also, the creator provides the following warning on his plugin site.
Don't abuse this code... Don't use it too often, too many video
instances will slow down the browser.
Please bear in mind bandwidth usage for both you, and your visitors