/** * full background video * * more info on audio/video media events/attributes/methods * - https://developer.mozilla.org/en-us/docs/web/guide/events/media_events * - http://www.w3schools.com/tags/ref_av_dom.asp */ (function (global) { // define bideo constructor on the global object global.bideo = function () { // plugin options this.opt = null; // the video element this.videoel = null; // approximate loading rate // // the value will be a number like 0.8 // which means to load 4 seconds of the video // it takes 5 seconds. if the number is super low // like 0.2 (regular 3g connections) then you can // decide whether to play the video or not. // this behaviour will be controller with // the `acceptableloadingrate` option. this.approxloadingrate = null; // methods to which `this` will be bound this._resize = null; this._progress = null; // time at which video is initialized this.starttime = null; this.onloadcalled = false; // initialize and setup the video in dom` this.init = function (opt) { // if not set then set to an empty object this.opt = opt = opt || {}; var self = this; self._resize = self.resize.bind(this); // video element self.videoel = opt.videoel; // meta data event self.videoel.addeventlistener('loadedmetadata', self._resize, false); // fired when enough has been buffered to begin the video // self.videoel.readystate === 4 (have_enough_data) self.videoel.addeventlistener('canplay', function () { // play the video when enough has been buffered if (!self.opt.ismobile) { self.opt.onload && self.opt.onload(); if (self.opt.autoplay !== false) self.videoel.play(); } }); // if resizing is required (resize video as window/container resizes) if (self.opt.resize) { global.addeventlistener('resize', self._resize, false); } // start time of video initialization this.starttime = (new date()).gettime(); // create `source` for video this.opt.src.foreach(function (srcob, i, arr) { var key , val , source = document.createelement('source'); // set all the attribute key=val supplied in `src` option for (key in srcob) { if (srcob.hasownproperty(key)) { val = srcob[key]; source.setattribute(key, val); } } self.videoel.appendchild(source); }); if (self.opt.ismobile) { if (self.opt.playbutton) { self.opt.videoel.addeventlistener('timeupdate', function () { if (!self.onloadcalled) { self.opt.onload && self.opt.onload(); self.onloadcalled = true; } }); self.opt.playbutton.addeventlistener('click', function () { self.opt.pausebutton.style.display = 'inline-block'; this.style.display = 'none'; self.videoel.play(); }, false); self.opt.pausebutton.addeventlistener('click', function () { this.style.display = 'none'; self.opt.playbutton.style.display = 'inline-block'; self.videoel.pause(); }, false); } } return; } // called once video metadata is available // // also called when window/container is resized this.resize = function () { // ie/edge still don't support object-fit: cover if ('object-fit' in document.body.style) return; // video's intrinsic dimensions var w = this.videoel.videowidth , h = this.videoel.videoheight; // intrinsic ratio // will be more than 1 if w > h and less if h > w var videoratio = (w / h).tofixed(2); // get the container dom element and its styles // // also calculate the min dimensions required (this will be // the container dimentions) var container = this.opt.container , containerstyles = global.getcomputedstyle(container) , minw = parseint( containerstyles.getpropertyvalue('width') ) , minh = parseint( containerstyles.getpropertyvalue('height') ); // if !border-box then add paddings to width and height if (containerstyles.getpropertyvalue('box-sizing') !== 'border-box') { var paddingtop = containerstyles.getpropertyvalue('padding-top') , paddingbottom = containerstyles.getpropertyvalue('padding-bottom') , paddingleft = containerstyles.getpropertyvalue('padding-left') , paddingright = containerstyles.getpropertyvalue('padding-right'); paddingtop = parseint(paddingtop); paddingbottom = parseint(paddingbottom); paddingleft = parseint(paddingleft); paddingright = parseint(paddingright); minw += paddingleft + paddingright; minh += paddingtop + paddingbottom; } // what's the min:intrinsic dimensions // // the idea is to get which of the container dimension // has a higher value when compared with the equivalents // of the video. imagine a 1200x700 container and // 1000x500 video. then in order to find the right balance // and do minimum scaling, we have to find the dimension // with higher ratio. // // ex: 1200/1000 = 1.2 and 700/500 = 1.4 - so it is best to // scale 500 to 700 and then calculate what should be the // right width. if we scale 1000 to 1200 then the height // will become 600 proportionately. var widthratio = minw / w; var heightratio = minh / h; // whichever ratio is more, the scaling // has to be done over that dimension if (widthratio > heightratio) { var new_width = minw; var new_height = math.ceil( new_width / videoratio ); } else { var new_height = minh; var new_width = math.ceil( new_height * videoratio ); } this.videoel.style.width = new_width + 'px'; this.videoel.style.height = new_height + 'px'; }; }; }(window));