From 2146bc03b797d51a2d2fe8b13c9730319b780814 Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Fri, 9 May 2014 18:50:24 +0200 Subject: [PATCH] Fixed mini video sizing in Firefox by implementing object-fit shim. Updated Modernizr to latest version with object-fit detection. --- src/styles/components/_audiovideo.scss | 5 +- static/js/libs/modernizr.js | 779 ++++--------------------- static/js/services/videolayout.js | 303 +++++----- 3 files changed, 272 insertions(+), 815 deletions(-) diff --git a/src/styles/components/_audiovideo.scss b/src/styles/components/_audiovideo.scss index 9d804296..70171d5c 100644 --- a/src/styles/components/_audiovideo.scss +++ b/src/styles/components/_audiovideo.scss @@ -45,7 +45,7 @@ } } -.mainScreenshare #audiovideo { +.mainScreenshare #audiovideo { @include breakpt($breakpoint-video-medium, max-width, only screen) { display: none; } @@ -97,6 +97,9 @@ transform: scale(-1, 1); z-index: 2; } + video { + object-fit: contain; + } } .audiovideo { diff --git a/static/js/libs/modernizr.js b/static/js/libs/modernizr.js index 07ea93fa..a2707e57 100644 --- a/static/js/libs/modernizr.js +++ b/static/js/libs/modernizr.js @@ -1,85 +1,39 @@ -/*! - * Modernizr v2.7.1 - * www.modernizr.com - * - * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton - * Available under the BSD and MIT licenses: www.modernizr.com/license/ - */ - -/* - * Modernizr tests which native CSS3 and HTML5 features are available in - * the current UA and makes the results available to you in two ways: - * as properties on a global Modernizr object, and as classes on the - * element. This information allows you to progressively enhance - * your pages with a granular level of control over the experience. - * - * Modernizr has an optional (not included) conditional resource loader - * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). - * To get a build that includes Modernizr.load(), as well as choosing - * which tests to include, go to www.modernizr.com/download/ - * - * Authors Faruk Ates, Paul Irish, Alex Sexton - * Contributors Ryan Seddon, Ben Alman +/* Modernizr 2.8.1 (Custom Build) | MIT & BSD + * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-css_objectfit */ +; window.Modernizr = (function( window, document, undefined ) { - var version = '2.7.1', + var version = '2.8.0', Modernizr = {}, - /*>>cssclasses*/ - // option for enabling the HTML classes to be added enableClasses = true, - /*>>cssclasses*/ docElement = document.documentElement, - /** - * Create our "modernizr" element that we do most feature tests on. - */ mod = 'modernizr', modElem = document.createElement(mod), mStyle = modElem.style, - /** - * Create the input element for various Web Forms feature tests. - */ - inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ , + inputElem = document.createElement('input') , - /*>>smile*/ smile = ':)', - /*>>smile*/ toString = {}.toString, - // TODO :: make the prefixes more granular - /*>>prefixes*/ - // List of property values to set for css tests. See ticket #21 prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), - /*>>prefixes*/ - /*>>domprefixes*/ - // Following spec is to expose vendor-specific style properties as: - // elem.style.WebkitBorderRadius - // and the following would be incorrect: - // elem.style.webkitBorderRadius - // Webkit ghosts their properties in lowercase but Opera & Moz do not. - // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ - // erik.eae.net/archives/2008/03/10/21.48.10/ - // More here: github.com/Modernizr/Modernizr/issues/issue/21 omPrefixes = 'Webkit Moz O ms', cssomPrefixes = omPrefixes.split(' '), domPrefixes = omPrefixes.toLowerCase().split(' '), - /*>>domprefixes*/ - /*>>ns*/ ns = {'svg': 'http://www.w3.org/2000/svg'}, - /*>>ns*/ tests = {}, inputs = {}, @@ -89,54 +43,38 @@ window.Modernizr = (function( window, document, undefined ) { slice = classes.slice, - featureName, // used in testing loop + featureName, - /*>>teststyles*/ - // Inject element with style element and some CSS rules injectElementWithStyles = function( rule, callback, nodes, testnames ) { var style, ret, node, docOverflow, div = document.createElement('div'), - // After page load injecting a fake body doesn't work so check if body exists - body = document.body, - // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. - fakeBody = body || document.createElement('body'); + body = document.body, + fakeBody = body || document.createElement('body'); if ( parseInt(nodes, 10) ) { - // In order not to give false positives we create a node for each test - // This also allows the method to scale for unspecified uses - while ( nodes-- ) { + while ( nodes-- ) { node = document.createElement('div'); node.id = testnames ? testnames[nodes] : mod + (nodes + 1); div.appendChild(node); } } - // '].join(''); + style = ['­',''].join(''); div.id = mod; - // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. - // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 - (body ? div : fakeBody).innerHTML += style; + (body ? div : fakeBody).innerHTML += style; fakeBody.appendChild(div); if ( !body ) { - //avoid crashing IE8, if background image is used - fakeBody.style.background = ''; - //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible - fakeBody.style.overflow = 'hidden'; + fakeBody.style.background = ''; + fakeBody.style.overflow = 'hidden'; docOverflow = docElement.style.overflow; docElement.style.overflow = 'hidden'; docElement.appendChild(fakeBody); } ret = callback(div, rule); - // If this is done after page load we don't want to remove the body so check if body exists - if ( !body ) { + if ( !body ) { fakeBody.parentNode.removeChild(fakeBody); docElement.style.overflow = docOverflow; } else { @@ -146,17 +84,12 @@ window.Modernizr = (function( window, document, undefined ) { return !!ret; }, - /*>>teststyles*/ - /*>>mq*/ - // adapted from matchMedia polyfill - // by Scott Jehl and Paul Irish - // gist.github.com/786768 testMediaQuery = function( mq ) { var matchMedia = window.matchMedia || window.msMatchMedia; if ( matchMedia ) { - return matchMedia(mq).matches; + return matchMedia(mq) && matchMedia(mq).matches || false; } var bool; @@ -170,18 +103,8 @@ window.Modernizr = (function( window, document, undefined ) { return bool; }, - /*>>mq*/ - - - /*>>hasevent*/ - // - // isEventSupported determines if a given element supports the given event - // kangax.github.com/iseventsupported/ - // - // The following results are known incorrects: - // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative - // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 - // ... + + isEventSupported = (function() { var TAGNAMES = { @@ -195,20 +118,17 @@ window.Modernizr = (function( window, document, undefined ) { element = element || document.createElement(TAGNAMES[eventName] || 'div'); eventName = 'on' + eventName; - // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those - var isSupported = eventName in element; + var isSupported = eventName in element; if ( !isSupported ) { - // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element - if ( !element.setAttribute ) { + if ( !element.setAttribute ) { element = document.createElement('div'); } if ( element.setAttribute && element.removeAttribute ) { element.setAttribute(eventName, ''); isSupported = is(element[eventName], 'function'); - // If property was created, "remove it" (by setting value to `undefined`) - if ( !is(element[eventName], 'undefined') ) { + if ( !is(element[eventName], 'undefined') ) { element[eventName] = undefined; } element.removeAttribute(eventName); @@ -220,11 +140,8 @@ window.Modernizr = (function( window, document, undefined ) { } return isEventSupported; })(), - /*>>hasevent*/ - // TODO :: Add flag for hasownprop ? didn't last time - // hasOwnProperty shim by kangax needed for Safari 2.0 support _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { @@ -233,13 +150,11 @@ window.Modernizr = (function( window, document, undefined ) { }; } else { - hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ + hasOwnProp = function (object, property) { return ((property in object) && is(object.constructor.prototype[property], 'undefined')); }; } - // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js - // es5.github.com/#x15.3.4.5 if (!Function.prototype.bind) { Function.prototype.bind = function bind(that) { @@ -283,54 +198,22 @@ window.Modernizr = (function( window, document, undefined ) { }; } - /** - * setCss applies given styles to the Modernizr DOM node. - */ function setCss( str ) { mStyle.cssText = str; } - /** - * setCssAll extrapolates all vendor-specific css strings. - */ function setCssAll( str1, str2 ) { return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); } - /** - * is returns a boolean for if typeof obj is exactly type. - */ function is( obj, type ) { return typeof obj === type; } - /** - * contains returns a boolean for if substr is found within str. - */ function contains( str, substr ) { return !!~('' + str).indexOf(substr); } - /*>>testprop*/ - - // testProps is a generic CSS / DOM property test. - - // In testing support for a given CSS property, it's legit to test: - // `elem.style[styleName] !== undefined` - // If the property is supported it will return an empty string, - // if unsupported it will return undefined. - - // We'll take advantage of this quick test and skip setting a style - // on our modernizr element, but instead just testing undefined vs - // empty string. - - // Because the testing of the CSS property names (with "-", as - // opposed to the camelCase DOM properties) is non-portable and - // non-standard but works in WebKit and IE (but not Gecko or Opera), - // we explicitly reject properties with dashes so that authors - // developing in WebKit or IE first don't end up with - // browser-specific content by accident. - function testProps( props, prefixed ) { for ( var i in props ) { var prop = props[i]; @@ -340,83 +223,39 @@ window.Modernizr = (function( window, document, undefined ) { } return false; } - /*>>testprop*/ - // TODO :: add testDOMProps - /** - * testDOMProps is a generic DOM property test; if a browser supports - * a certain property, it won't return undefined for it. - */ function testDOMProps( props, obj, elem ) { for ( var i in props ) { var item = obj[props[i]]; if ( item !== undefined) { - // return the property name as a string - if (elem === false) return props[i]; + if (elem === false) return props[i]; - // let's bind a function - if (is(item, 'function')){ - // default to autobind unless override - return item.bind(elem || obj); + if (is(item, 'function')){ + return item.bind(elem || obj); } - // return the unbound function or obj or value - return item; + return item; } } return false; } - /*>>testallprops*/ - /** - * testPropsAll tests a list of DOM properties we want to check against. - * We specify literally ALL possible (known and/or likely) properties on - * the element including the non-vendor prefixed one, for forward- - * compatibility. - */ function testPropsAll( prop, prefixed, elem ) { var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); - // did they call .prefixed('boxSizing') or are we just testing a prop? - if(is(prefixed, "string") || is(prefixed, "undefined")) { + if(is(prefixed, "string") || is(prefixed, "undefined")) { return testProps(props, prefixed); - // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) - } else { + } else { props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); return testDOMProps(props, prefixed, elem); } - } - /*>>testallprops*/ - - - /** - * Tests - * ----- - */ - - // The *new* flexbox - // dev.w3.org/csswg/css3-flexbox - - tests['flexbox'] = function() { + } tests['flexbox'] = function() { return testPropsAll('flexWrap'); - }; - - // The *old* flexbox - // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ - - tests['flexboxlegacy'] = function() { - return testPropsAll('boxDirection'); - }; - - // On the S60 and BB Storm, getContext exists, but always returns undefined - // so we actually have to call getContext() to verify - // github.com/Modernizr/Modernizr/issues/issue/97/ - - tests['canvas'] = function() { + }; tests['canvas'] = function() { var elem = document.createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); }; @@ -425,28 +264,12 @@ window.Modernizr = (function( window, document, undefined ) { return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); }; - // webk.it/70117 is tracking a legit WebGL feature detect proposal - // We do a soft detect which may false positive in order to avoid - // an expensive context creation: bugzil.la/732441 tests['webgl'] = function() { return !!window.WebGLRenderingContext; }; - /* - * The Modernizr.touch test only indicates if the browser supports - * touch events, which does not necessarily reflect a touchscreen - * device, as evidenced by tablets running Windows 7 or, alas, - * the Palm Pre / WebOS (touch) phones. - * - * Additionally, Chrome (desktop) used to lie about its support on this, - * but that has since been rectified: crbug.com/36415 - * - * We also test for Firefox 4 Multitouch Support. - * - * For more info, see: modernizr.github.com/Modernizr/touch.html - */ tests['touch'] = function() { var bool; @@ -463,15 +286,6 @@ window.Modernizr = (function( window, document, undefined ) { }; - // geolocation is often considered a trivial feature detect... - // Turns out, it's quite tricky to get right: - // - // Using !!navigator.geolocation does two things we don't want. It: - // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 - // 2. Disables page caching in WebKit: webk.it/43956 - // - // Meanwhile, in Firefox < 8, an about:config setting could expose - // a false positive that would throw an exception: bugzil.la/688158 tests['geolocation'] = function() { return 'geolocation' in navigator; @@ -483,31 +297,18 @@ window.Modernizr = (function( window, document, undefined ) { }; - // Chrome incognito mode used to throw an exception when using openDatabase - // It doesn't anymore. tests['websqldatabase'] = function() { return !!window.openDatabase; }; - // Vendors had inconsistent prefixing with the experimental Indexed DB: - // - Webkit's implementation is accessible through webkitIndexedDB - // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB - // For speed, we don't test the legacy (and beta-only) indexedDB tests['indexedDB'] = function() { return !!testPropsAll("indexedDB", window); }; - // documentMode logic from YUI to filter out IE8 Compat Mode - // which false positives. tests['hashchange'] = function() { return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); }; - // Per 1.6: - // This used to be Modernizr.historymanagement but the longer - // name has been deprecated in favor of a shorter and property-matching one. - // The old API is still available in 1.6, but as of 2.0 will throw a warning, - // and in the first release thereafter disappear entirely. tests['history'] = function() { return !!(window.history && history.pushState); }; @@ -517,52 +318,28 @@ window.Modernizr = (function( window, document, undefined ) { return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); }; - // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10 - // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17. - // FF10 still uses prefixes, so check for it until then. - // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/ tests['websockets'] = function() { return 'WebSocket' in window || 'MozWebSocket' in window; }; - // css-tricks.com/rgba-browser-support/ tests['rgba'] = function() { - // Set an rgba() color and check the returned value - setCss('background-color:rgba(150,255,150,.5)'); return contains(mStyle.backgroundColor, 'rgba'); }; tests['hsla'] = function() { - // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, - // except IE9 who retains it as hsla - - setCss('background-color:hsla(120,40%,100%,.5)'); + setCss('background-color:hsla(120,40%,100%,.5)'); return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); }; tests['multiplebgs'] = function() { - // Setting multiple images AND a color on the background shorthand property - // and then querying the style.background property value for the number of - // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! - - setCss('background:url(https://),url(https://),red url(https://)'); - - // If the UA supports multiple backgrounds, there should be three occurrences - // of the string "url(" in the return value for elemStyle.background - - return (/(url\s*\(.*?){3}/).test(mStyle.background); - }; + setCss('background:url(https://),url(https://),red url(https://)'); - - - // this will false positive in Opera Mini - // github.com/Modernizr/Modernizr/issues/396 - - tests['backgroundsize'] = function() { + return (/(url\s*\(.*?){3}/).test(mStyle.background); + }; tests['backgroundsize'] = function() { return testPropsAll('backgroundSize'); }; @@ -571,41 +348,27 @@ window.Modernizr = (function( window, document, undefined ) { }; - // Super comprehensive table about all the unique implementations of - // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance tests['borderradius'] = function() { return testPropsAll('borderRadius'); }; - // WebOS unfortunately false positives on this test. tests['boxshadow'] = function() { return testPropsAll('boxShadow'); }; - // FF3.0 will false positive on this test tests['textshadow'] = function() { return document.createElement('div').style.textShadow === ''; }; tests['opacity'] = function() { - // Browsers that actually have CSS Opacity implemented have done so - // according to spec, which means their return values are within the - // range of [0.0,1.0] - including the leading zero. + setCssAll('opacity:.55'); - setCssAll('opacity:.55'); - - // The non-literal . in this regex is intentional: - // German Chrome returns this value as 0,55 - // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 - return (/^0.55$/).test(mStyle.opacity); + return (/^0.55$/).test(mStyle.opacity); }; - // Note, Android < 4 will pass this test, but can only animate - // a single property at a time - // daneden.me/2011/12/putting-up-with-androids-bullshit/ tests['cssanimations'] = function() { return testPropsAll('animationName'); }; @@ -617,23 +380,13 @@ window.Modernizr = (function( window, document, undefined ) { tests['cssgradients'] = function() { - /** - * For CSS Gradients syntax, please see: - * webkit.org/blog/175/introducing-css-gradients/ - * developer.mozilla.org/en/CSS/-moz-linear-gradient - * developer.mozilla.org/en/CSS/-moz-radial-gradient - * dev.w3.org/csswg/css3-images/#gradients- - */ - var str1 = 'background-image:', str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', str3 = 'linear-gradient(left top,#9f9, white);'; setCss( - // legacy webkit syntax (FIXME: remove when syntax not in use anymore) - (str1 + '-webkit- '.split(' ').join(str2 + str1) + - // standard syntax // trailing 'background-image:' - prefixes.join(str3 + str1)).slice(0, -str1.length) + (str1 + '-webkit- '.split(' ').join(str2 + str1) + + prefixes.join(str3 + str1)).slice(0, -str1.length) ); return contains(mStyle.backgroundImage, 'gradient'); @@ -654,15 +407,9 @@ window.Modernizr = (function( window, document, undefined ) { var ret = !!testPropsAll('perspective'); - // Webkit's 3D transforms are passed off to the browser's own graphics renderer. - // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in - // some conditions. As a result, Webkit typically recognizes the syntax but - // will sometimes throw a false positive, thus we must do a more thorough check: - if ( ret && 'webkitPerspective' in docElement.style ) { + if ( ret && 'webkitPerspective' in docElement.style ) { - // Webkit allows this media query to succeed only if the feature is enabled. - // `@media (transform-3d),(-webkit-transform-3d){ ... }` - injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { + injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { ret = node.offsetLeft === 9 && node.offsetHeight === 3; }); } @@ -675,13 +422,7 @@ window.Modernizr = (function( window, document, undefined ) { }; - /*>>fontface*/ - // @font-face detection routine by Diego Perini - // javascript.nwbox.com/CSSSupport/ - // false positives: - // WebOS github.com/Modernizr/Modernizr/issues/342 - // WP7 github.com/Modernizr/Modernizr/issues/538 tests['fontface'] = function() { var bool; @@ -695,9 +436,7 @@ window.Modernizr = (function( window, document, undefined ) { return bool; }; - /*>>fontface*/ - // CSS generated content detection tests['generatedcontent'] = function() { var bool; @@ -707,35 +446,16 @@ window.Modernizr = (function( window, document, undefined ) { return bool; }; - - - - // These tests evaluate support of the video/audio elements, as well as - // testing what types of content they support. - // - // We're using the Boolean constructor here, so that we can extend the value - // e.g. Modernizr.video // true - // Modernizr.video.ogg // 'probably' - // - // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 - // thx to NielsLeenheer and zcorpan - - // Note: in some older browsers, "no" was a return value instead of empty string. - // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 - // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 - tests['video'] = function() { var elem = document.createElement('video'), bool = false; - // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 - try { + try { if ( bool = !!elem.canPlayType ) { bool = new Boolean(bool); bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); - // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 - bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); + bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); } @@ -755,10 +475,7 @@ window.Modernizr = (function( window, document, undefined ) { bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); - // Mimetypes accepted: - // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements - // bit.ly/iphoneoscodecs - bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); + bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); bool.m4a = ( elem.canPlayType('audio/x-m4a;') || elem.canPlayType('audio/aac;')) .replace(/^no$/,''); } @@ -768,23 +485,6 @@ window.Modernizr = (function( window, document, undefined ) { }; - // In FF4, if disabled, window.localStorage should === null. - - // Normally, we could not test that directly and need to do a - // `('localStorage' in window) && ` test first because otherwise Firefox will - // throw bugzil.la/365772 if cookies are disabled - - // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem - // will throw the exception: - // QUOTA_EXCEEDED_ERRROR DOM Exception 22. - // Peculiarly, getItem and removeItem calls do not throw. - - // Because we are forced to try/catch this, we'll go aggressive. - - // Just FWIW: IE8 Compat mode supports these features completely: - // www.quirksmode.org/dom/html5.html - // But IE8 doesn't support either with local files - tests['localstorage'] = function() { try { localStorage.setItem(mod, mod); @@ -816,79 +516,43 @@ window.Modernizr = (function( window, document, undefined ) { }; - // Thanks to Erik Dahlstrom tests['svg'] = function() { return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; }; - // specifically for SVG inline in HTML, not within XHTML - // test page: paulirish.com/demo/inline-svg tests['inlinesvg'] = function() { var div = document.createElement('div'); div.innerHTML = ''; return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; }; - // SVG SMIL animation tests['smil'] = function() { return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); }; - // This test is only for clip paths in SVG proper, not clip paths on HTML content - // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg - // However read the comments to dig into applying SVG clippaths to HTML content here: - // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 tests['svgclippaths'] = function() { return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); }; - /*>>webforms*/ - // input features and input types go directly onto the ret object, bypassing the tests loop. - // Hold this guy to execute in a moment. function webforms() { - /*>>input*/ - // Run through HTML5's new input attributes to see if the UA understands any. - // We're using f which is the element created early on - // Mike Taylr has created a comprehensive resource for testing these attributes - // when applied to all input types: - // miketaylr.com/code/input-type-attr.html - // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary - - // Only input placeholder is tested while textarea's placeholder is not. - // Currently Safari 4 and Opera 11 have support only for the input placeholder - // Both tests are available in feature-detects/forms-placeholder.js - Modernizr['input'] = (function( props ) { + Modernizr['input'] = (function( props ) { for ( var i = 0, len = props.length; i < len; i++ ) { attrs[ props[i] ] = !!(props[i] in inputElem); } if (attrs.list){ - // safari false positive's on datalist: webk.it/74252 - // see also github.com/Modernizr/Modernizr/issues/146 - attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); + attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); } return attrs; })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); - /*>>input*/ - - /*>>inputtypes*/ - // Run through HTML5's new input types to see if the UA understands any. - // This is put behind the tests runloop because it doesn't return a - // true/false like all the other tests; instead, it returns an object - // containing each input type with its corresponding true/false value - - // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ - Modernizr['inputtypes'] = (function(props) { + Modernizr['inputtypes'] = (function(props) { for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { inputElem.setAttribute('type', inputElemType = props[i]); bool = inputElem.type !== 'text'; - // We first check to see if the type we give it sticks.. - // If the type does, we feed it a textual value, which shouldn't be valid. - // If the value doesn't stick, we know there's input sanitization which infers a custom UI - if ( bool ) { + if ( bool ) { inputElem.value = smile; inputElem.style.cssText = 'position:absolute;visibility:hidden;'; @@ -898,29 +562,18 @@ window.Modernizr = (function( window, document, undefined ) { docElement.appendChild(inputElem); defaultView = document.defaultView; - // Safari 2-4 allows the smiley as a value, despite making a slider - bool = defaultView.getComputedStyle && + bool = defaultView.getComputedStyle && defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && - // Mobile android web browser has false positive, so must - // check the height to see if the widget is actually there. - (inputElem.offsetHeight !== 0); + (inputElem.offsetHeight !== 0); docElement.removeChild(inputElem); } else if ( /^(search|tel)$/.test(inputElemType) ){ - // Spec doesn't define any special parsing or detectable UI - // behaviors so we pass these through as true - - // Interestingly, opera fails the earlier test, so it doesn't - // even make it here. - - } else if ( /^(url|email)$/.test(inputElemType) ) { - // Real url and email support comes with prebaked validation. - bool = inputElem.checkValidity && inputElem.checkValidity() === false; + } else if ( /^(url|email)$/.test(inputElemType) ) { + bool = inputElem.checkValidity && inputElem.checkValidity() === false; } else { - // If the upgraded input compontent rejects the :) text, we got a winner - bool = inputElem.value != smile; + bool = inputElem.value != smile; } } @@ -928,44 +581,19 @@ window.Modernizr = (function( window, document, undefined ) { } return inputs; })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); - /*>>inputtypes*/ - } - /*>>webforms*/ - - - // End of test definitions - // ----------------------- - - - - // Run through all tests and detect their support in the current UA. - // todo: hypothetically we could be doing an array of tests and use a basic loop here. + } for ( var feature in tests ) { if ( hasOwnProp(tests, feature) ) { - // run the test, throw the return value into the Modernizr, - // then based on that boolean, define an appropriate className - // and push it into an array of classes we'll join later. - featureName = feature.toLowerCase(); + featureName = feature.toLowerCase(); Modernizr[featureName] = tests[feature](); classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); } } - /*>>webforms*/ - // input tests need to run. Modernizr.input || webforms(); - /*>>webforms*/ - /** - * addTest allows the user to define their own feature tests - * the result will be added onto the Modernizr object, - * as well as an appropriate className set on the html element - * - * @param feature - String naming the feature - * @param test - Function returning true if feature is supported, false if not - */ Modernizr.addTest = function ( feature, test ) { if ( typeof feature == 'object' ) { for ( var key in feature ) { @@ -978,12 +606,7 @@ window.Modernizr = (function( window, document, undefined ) { feature = feature.toLowerCase(); if ( Modernizr[feature] !== undefined ) { - // we're going to quit if you're trying to overwrite an existing test - // if we were to allow it, we'd do this: - // var re = new RegExp("\\b(no-)?" + feature + "\\b"); - // docElement.className = docElement.className.replace( re, '' ); - // but, no rly, stuff 'em. - return Modernizr; + return Modernizr; } test = typeof test == 'function' ? test() : test; @@ -995,57 +618,40 @@ window.Modernizr = (function( window, document, undefined ) { } - return Modernizr; // allow chaining. + return Modernizr; }; - // Reset modElem.cssText to nothing to reduce memory footprint. setCss(''); modElem = inputElem = null; - /*>>shiv*/ - /** - * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed - */ ;(function(window, document) { - /*jshint evil:true */ - /** version */ - var version = '3.7.0'; + var version = '3.7.0'; - /** Preset options */ - var options = window.html5 || {}; + var options = window.html5 || {}; - /** Used to skip problem elements */ - var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; + var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; - /** Not all elements can be cloned in IE **/ - var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; + var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; - /** Detect whether the browser supports default html5 styles */ - var supportsHtml5Styles; + var supportsHtml5Styles; - /** Name of the expando, to work with multiple documents or to re-shiv one document */ - var expando = '_html5shiv'; + var expando = '_html5shiv'; - /** The id for the the documents expando */ - var expanID = 0; + var expanID = 0; - /** Cached data for each document */ - var expandoData = {}; + var expandoData = {}; - /** Detect whether the browser supports unknown elements */ - var supportsUnknownElements; + var supportsUnknownElements; (function() { try { var a = document.createElement('a'); a.innerHTML = ''; - //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles - supportsHtml5Styles = ('hidden' in a); + supportsHtml5Styles = ('hidden' in a); supportsUnknownElements = a.childNodes.length == 1 || (function() { - // assign a false positive if unable to shiv - (document.createElement)('a'); + (document.createElement)('a'); var frag = document.createDocumentFragment(); return ( typeof frag.cloneNode == 'undefined' || @@ -1054,23 +660,13 @@ window.Modernizr = (function( window, document, undefined ) { ); }()); } catch(e) { - // assign a false positive if detection fails => unable to shiv - supportsHtml5Styles = true; + supportsHtml5Styles = true; supportsUnknownElements = true; } }()); - /*--------------------------------------------------------------------------*/ - - /** - * Creates a style sheet with the given CSS text and adds it to the document. - * @private - * @param {Document} ownerDocument The document. - * @param {String} cssText The CSS text. - * @returns {StyleSheet} The style element. - */ - function addStyleSheet(ownerDocument, cssText) { + function addStyleSheet(ownerDocument, cssText) { var p = ownerDocument.createElement('p'), parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; @@ -1078,23 +674,12 @@ window.Modernizr = (function( window, document, undefined ) { return parent.insertBefore(p.lastChild, parent.firstChild); } - /** - * Returns the value of `html5.elements` as an array. - * @private - * @returns {Array} An array of shived element node names. - */ - function getElements() { + function getElements() { var elements = html5.elements; return typeof elements == 'string' ? elements.split(' ') : elements; } - /** - * Returns the data associated to the given document - * @private - * @param {Document} ownerDocument The document. - * @returns {Object} An object of data. - */ - function getExpandoData(ownerDocument) { + function getExpandoData(ownerDocument) { var data = expandoData[ownerDocument[expando]]; if (!data) { data = {}; @@ -1105,14 +690,7 @@ window.Modernizr = (function( window, document, undefined ) { return data; } - /** - * returns a shived element for the given nodeName and document - * @memberOf html5 - * @param {String} nodeName name of the element - * @param {Document} ownerDocument The context document. - * @returns {Object} The shived element. - */ - function createElement(nodeName, ownerDocument, data){ + function createElement(nodeName, ownerDocument, data){ if (!ownerDocument) { ownerDocument = document; } @@ -1132,23 +710,10 @@ window.Modernizr = (function( window, document, undefined ) { node = data.createElem(nodeName); } - // Avoid adding some elements to fragments in IE < 9 because - // * Attributes like `name` or `type` cannot be set/changed once an element - // is inserted into a document/fragment - // * Link elements with `src` attributes that are inaccessible, as with - // a 403 response, will cause the tab/window to crash - // * Script elements appended to fragments will execute when their `src` - // or `text` property is set - return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; + return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; } - /** - * returns a shived DocumentFragment for the given document - * @memberOf html5 - * @param {Document} ownerDocument The context document. - * @returns {Object} The shived DocumentFragment. - */ - function createDocumentFragment(ownerDocument, data){ + function createDocumentFragment(ownerDocument, data){ if (!ownerDocument) { ownerDocument = document; } @@ -1166,13 +731,7 @@ window.Modernizr = (function( window, document, undefined ) { return clone; } - /** - * Shivs the `createElement` and `createDocumentFragment` methods of the document. - * @private - * @param {Document|DocumentFragment} ownerDocument The document. - * @param {Object} data of the document. - */ - function shivMethods(ownerDocument, data) { + function shivMethods(ownerDocument, data) { if (!data.cache) { data.cache = {}; data.createElem = ownerDocument.createElement; @@ -1182,8 +741,7 @@ window.Modernizr = (function( window, document, undefined ) { ownerDocument.createElement = function(nodeName) { - //abort shiv - if (!html5.shivMethods) { + if (!html5.shivMethods) { return data.createElem(nodeName); } return createElement(nodeName, ownerDocument, data); @@ -1192,8 +750,7 @@ window.Modernizr = (function( window, document, undefined ) { ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + 'var n=f.cloneNode(),c=n.createElement;' + 'h.shivMethods&&(' + - // unroll the `createElement` calls - getElements().join().replace(/[\w\-]+/g, function(nodeName) { + getElements().join().replace(/[\w\-]+/g, function(nodeName) { data.createElem(nodeName); data.frag.createElement(nodeName); return 'c("' + nodeName + '")'; @@ -1202,15 +759,7 @@ window.Modernizr = (function( window, document, undefined ) { )(html5, data.frag); } - /*--------------------------------------------------------------------------*/ - - /** - * Shivs the given document. - * @memberOf html5 - * @param {Document} ownerDocument The document to shiv. - * @returns {Document} The shived document. - */ - function shivDocument(ownerDocument) { + function shivDocument(ownerDocument) { if (!ownerDocument) { ownerDocument = document; } @@ -1218,12 +767,9 @@ window.Modernizr = (function( window, document, undefined ) { if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) { data.hasCSS = !!addStyleSheet(ownerDocument, - // corrects block display not defined in IE6/7/8/9 - 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' + - // adds styling not present in IE6/7/8/9 - 'mark{background:#FF0;color:#000}' + - // hides non-rendered elements - 'template{display:none}' + 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' + + 'mark{background:#FF0;color:#000}' + + 'template{display:none}' ); } if (!supportsUnknownElements) { @@ -1232,175 +778,70 @@ window.Modernizr = (function( window, document, undefined ) { return ownerDocument; } - /*--------------------------------------------------------------------------*/ - - /** - * The `html5` object is exposed so that more elements can be shived and - * existing shiving can be detected on iframes. - * @type Object - * @example - * - * // options can be changed before the script is included - * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false }; - */ - var html5 = { - - /** - * An array or space separated string of node names of the elements to shiv. - * @memberOf html5 - * @type Array|String - */ - 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video', - - /** - * current version of html5shiv - */ - 'version': version, - - /** - * A flag to indicate that the HTML5 style sheet should be inserted. - * @memberOf html5 - * @type Boolean - */ - 'shivCSS': (options.shivCSS !== false), - - /** - * Is equal to true if a browser supports creating unknown/HTML5 elements - * @memberOf html5 - * @type boolean - */ - 'supportsUnknownElements': supportsUnknownElements, - - /** - * A flag to indicate that the document's `createElement` and `createDocumentFragment` - * methods should be overwritten. - * @memberOf html5 - * @type Boolean - */ - 'shivMethods': (options.shivMethods !== false), - - /** - * A string to describe the type of `html5` object ("default" or "default print"). - * @memberOf html5 - * @type String - */ - 'type': 'default', - - // shivs the document according to the specified `html5` object options - 'shivDocument': shivDocument, - - //creates a shived element - createElement: createElement, - - //creates a shived documentFragment - createDocumentFragment: createDocumentFragment - }; + var html5 = { + + 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video', + + 'version': version, + + 'shivCSS': (options.shivCSS !== false), - /*--------------------------------------------------------------------------*/ + 'supportsUnknownElements': supportsUnknownElements, - // expose html5 - window.html5 = html5; + 'shivMethods': (options.shivMethods !== false), + + 'type': 'default', + + 'shivDocument': shivDocument, + + createElement: createElement, + + createDocumentFragment: createDocumentFragment + }; - // shiv the document - shivDocument(document); + window.html5 = html5; + + shivDocument(document); }(this, document)); - /*>>shiv*/ - // Assign private properties to the return object with prefix Modernizr._version = version; - // expose these for the plugin API. Look in the source for how to join() them against your input - /*>>prefixes*/ Modernizr._prefixes = prefixes; - /*>>prefixes*/ - /*>>domprefixes*/ Modernizr._domPrefixes = domPrefixes; Modernizr._cssomPrefixes = cssomPrefixes; - /*>>domprefixes*/ - - /*>>mq*/ - // Modernizr.mq tests a given media query, live against the current state of the window - // A few important notes: - // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false - // * A max-width or orientation query will be evaluated against the current state, which may change later. - // * You must specify values. Eg. If you are testing support for the min-width media query use: - // Modernizr.mq('(min-width:0)') - // usage: - // Modernizr.mq('only screen and (max-width:768)') + Modernizr.mq = testMediaQuery; - /*>>mq*/ - /*>>hasevent*/ - // Modernizr.hasEvent() detects support for a given event, with an optional element to test on - // Modernizr.hasEvent('gesturestart', elem) Modernizr.hasEvent = isEventSupported; - /*>>hasevent*/ - /*>>testprop*/ - // Modernizr.testProp() investigates whether a given style property is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testProp('pointerEvents') Modernizr.testProp = function(prop){ return testProps([prop]); }; - /*>>testprop*/ - /*>>testallprops*/ - // Modernizr.testAllProps() investigates whether a given style property, - // or any of its vendor-prefixed variants, is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testAllProps('boxSizing') Modernizr.testAllProps = testPropsAll; - /*>>testallprops*/ - /*>>teststyles*/ - // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards - // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) Modernizr.testStyles = injectElementWithStyles; - /*>>teststyles*/ - - - /*>>prefixed*/ - // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input - // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' - - // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. - // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: - // - // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); - - // If you're trying to ascertain which transition end event to bind to, you might do something like... - // - // var transEndEventNames = { - // 'WebkitTransition' : 'webkitTransitionEnd', - // 'MozTransition' : 'transitionend', - // 'OTransition' : 'oTransitionEnd', - // 'msTransition' : 'MSTransitionEnd', - // 'transition' : 'transitionend' - // }, - // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; - Modernizr.prefixed = function(prop, obj, elem){ if(!obj) { return testPropsAll(prop, 'pfx'); } else { - // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' - return testPropsAll(prop, obj, elem); + return testPropsAll(prop, obj, elem); } }; - /*>>prefixed*/ - /*>>cssclasses*/ - // Remove "no-js" class from element, if it exists: docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + - // Add the new classes to the element. - (enableClasses ? ' js ' + classes.join(' ') : ''); - /*>>cssclasses*/ + (enableClasses ? ' js ' + classes.join(' ') : ''); return Modernizr; })(this, this.document); + +// dev.opera.com/articles/view/css3-object-fit-object-position/ + +Modernizr.addTest('object-fit', + !!Modernizr.prefixed('objectFit') +);; \ No newline at end of file diff --git a/static/js/services/videolayout.js b/static/js/services/videolayout.js index 1fd36af2..e11c2aba 100644 --- a/static/js/services/videolayout.js +++ b/static/js/services/videolayout.js @@ -18,17 +18,17 @@ * along with this program. If not, see . * */ -define(["jquery", "underscore"], function($, _) { +define(["jquery", "underscore", "modernizr"], function($, _, Modernizr) { - var dynamicCSSContainer = "audiovideo-dynamic"; - var renderers = {}; + var dynamicCSSContainer = "audiovideo-dynamic"; + var renderers = {}; - var getRemoteVideoSize = function(videos, peers) { - var size = { - width: 1920, - height: 1080 - } - if (videos.length) { + var getRemoteVideoSize = function(videos, peers) { + var size = { + width: 1920, + height: 1080 + } + if (videos.length) { if (videos.length === 1) { var remoteVideo = peers[videos[0]].element.find("video").get(0); size.width = remoteVideo.videoWidth; @@ -37,34 +37,36 @@ define(["jquery", "underscore"], function($, _) { } } return size; - } + } - // videoLayout - return ["$window", function($window) { + var objectFitSupport = Modernizr["object-fit"] && true; - // Video layout with all videos rendered the same size. - var OnePeople = function(container, scope, controller) { - }; + // videoLayout + return ["$window", function($window) { - OnePeople.prototype.name = "onepeople"; + // Video layout with all videos rendered the same size. + var OnePeople = function(container, scope, controller) { + }; - OnePeople.prototype.render = function(container, size, scope, videos, peers) { + OnePeople.prototype.name = "onepeople"; - if (this.closed) { - return; - } + OnePeople.prototype.render = function(container, size, scope, videos, peers) { + + if (this.closed) { + return; + } var videoWidth; var videoHeight; if (videos.length) { - var remoteSize = getRemoteVideoSize(videos, peers); + var remoteSize = getRemoteVideoSize(videos, peers); videoWidth = remoteSize.width; videoHeight = remoteSize.height; } if (!videoWidth) { - // XXX(longsleep): Improve this condition - its crap to compare style opacity (tm)! + // XXX(longsleep): Improve this condition - its crap to compare style opacity (tm)! if (scope.localVideo.style.opacity === '1') { videoWidth = scope.localVideo.videoWidth; videoHeight = scope.localVideo.videoHeight; @@ -92,6 +94,17 @@ define(["jquery", "underscore"], function($, _) { //console.log("resize", container, videos.length, aspectRatio, innerHeight, innerWidth); var extraCSS = {}; + if (!objectFitSupport) { + // Make mini video fit into available space on browsers with no object-fit support. + // http://caniuse.com/object-fit + var aspectRatioLocal = scope.localVideo.videoWidth/scope.localVideo.videoHeight; + extraCSS = { + ".renderer-onepeople .miniVideo": { + width: ($(scope.mini).height()*aspectRatioLocal)+"px" + } + }; + } + if (videos.length === 1) { var newVideoWidth = innerWidth < aspectRatio * innerHeight ? innerWidth : aspectRatio * innerHeight; var newVideoHeight = innerHeight < innerWidth / aspectRatio ? innerHeight : innerWidth / aspectRatio; @@ -124,100 +137,100 @@ define(["jquery", "underscore"], function($, _) { */ container.style.width = newContainerWidth + "px"; container.style.left = ((innerWidth - newContainerWidth) / 2) + 'px'; - extraCSS = { + extraCSS = $.extend(extraCSS, { ".renderer-onepeople .remoteVideos": { ">div": { width: singleVideoWidth+"px", height: singleVideoHeight+"px" } } - }; + }); } $.injectCSS(extraCSS, { truncateFirst: true, containerName: dynamicCSSContainer }); - }; - - OnePeople.prototype.close = function(container, scope, controller) { - - this.closed = true; + }; - }; + OnePeople.prototype.close = function(container, scope, controller) { + this.closed = true; - // Smally inherits from OnePeople - var Smally = function(container, scope, controller) { - // Call super. - OnePeople.call(this, container, scope, controller); - } - Smally.prototype = Object.create(OnePeople.prototype); - Smally.prototype.constructor = Smally; - Smally.prototype.name = "smally"; + }; - // A view with one selectable large video. The others are small. - var ConferenceKiosk = function(container, scope, controller) { - this.remoteVideos = $(container).find(".remoteVideos"); - this.bigVideo = $("
").addClass("bigVideo").get(0); - this.remoteVideos.before(this.bigVideo); - - this.big = null; - this.remoteVideos.on("click", ".remoteVideo", _.bind(function(event) { - if ($(event.currentTarget).hasClass("remoteVideo")) { - event.stopPropagation(); - this.makeBig($(event.currentTarget)); - } - }, this)); + // Smally inherits from OnePeople + var Smally = function(container, scope, controller) { + // Call super. + OnePeople.call(this, container, scope, controller); + } + Smally.prototype = Object.create(OnePeople.prototype); + Smally.prototype.constructor = Smally; + Smally.prototype.name = "smally"; + + // A view with one selectable large video. The others are small. + var ConferenceKiosk = function(container, scope, controller) { + + this.remoteVideos = $(container).find(".remoteVideos"); + this.bigVideo = $("
").addClass("bigVideo").get(0); + this.remoteVideos.before(this.bigVideo); + + this.big = null; + this.remoteVideos.on("click", ".remoteVideo", _.bind(function(event) { + if ($(event.currentTarget).hasClass("remoteVideo")) { + event.stopPropagation(); + this.makeBig($(event.currentTarget)); + } + }, this)); - }; + }; - ConferenceKiosk.prototype.name = "conferencekiosk"; + ConferenceKiosk.prototype.name = "conferencekiosk"; - ConferenceKiosk.prototype.makeBig = function(remoteVideo) { + ConferenceKiosk.prototype.makeBig = function(remoteVideo) { - if (this.big === remoteVideo) { - return; - } + if (this.big === remoteVideo) { + return; + } - if (this.big) { - // Add old video back. - this.big.insertAfter(remoteVideo); - this.big.find("video").get(0).play(); - } + if (this.big) { + // Add old video back. + this.big.insertAfter(remoteVideo); + this.big.find("video").get(0).play(); + } - this.big = remoteVideo; - remoteVideo.appendTo(this.bigVideo); - remoteVideo.find("video").get(0).play(); + this.big = remoteVideo; + remoteVideo.appendTo(this.bigVideo); + remoteVideo.find("video").get(0).play(); - }; + }; - ConferenceKiosk.prototype.render = function(container, size, scope, videos, peers) { + ConferenceKiosk.prototype.render = function(container, size, scope, videos, peers) { - var big = this.big; - if (big) { - var currentbigpeerid = this.big.data("peerid"); - if (!peers[currentbigpeerid]) { - console.log("Current big peer is no longer there", currentbigpeerid); - this.big = big = null; - } - } - if (!big) { - if (videos.length) { - this.makeBig(peers[videos[0]].element); - this.bigVideo.style.opacity = 1; - } + var big = this.big; + if (big) { + var currentbigpeerid = this.big.data("peerid"); + if (!peers[currentbigpeerid]) { + console.log("Current big peer is no longer there", currentbigpeerid); + this.big = big = null; + } + } + if (!big) { + if (videos.length) { + this.makeBig(peers[videos[0]].element); + this.bigVideo.style.opacity = 1; + } - } + } - var remoteSize = getRemoteVideoSize(videos, peers); - var aspectRatio = remoteSize.width/remoteSize.height; + var remoteSize = getRemoteVideoSize(videos, peers); + var aspectRatio = remoteSize.width/remoteSize.height; var innerHeight = size.height - 110; var innerWidth = size.width; var extraCSS = {}; - var bigVideoWidth = innerWidth < aspectRatio * innerHeight ? innerWidth : aspectRatio * innerHeight; + var bigVideoWidth = innerWidth < aspectRatio * innerHeight ? innerWidth : aspectRatio * innerHeight; var bigVideoHeight = innerHeight < innerWidth / aspectRatio ? innerHeight : innerWidth / aspectRatio; this.bigVideo.style.width = bigVideoWidth + 'px'; @@ -225,7 +238,7 @@ define(["jquery", "underscore"], function($, _) { // Make space for own video on the right if width goes low. if (((size.width - (videos.length-1) * 192) / 2) < 192) { - extraCSS = { + extraCSS = { ".renderer-conferencekiosk .remoteVideos": { "margin-right": "192px", "overflow-x": "auto", @@ -239,65 +252,65 @@ define(["jquery", "underscore"], function($, _) { containerName: dynamicCSSContainer }); - }; - - ConferenceKiosk.prototype.close = function(container, scope, controller) { - this.closed = true; - if (this.big) { - this.remoteVideos.append(this.big); - this.big.find("video").get(0).play(); - } - this.big = null; - this.bigVideo.remove() - this.bigVideo = null; - this.remoteVideos = null; - }; - - - // Register renderers. - renderers[OnePeople.prototype.name] = OnePeople; - renderers[Smally.prototype.name] = Smally; - renderers[ConferenceKiosk.prototype.name] = ConferenceKiosk; - - - // Public api. - var current = null; - return { - update: function(name, size, scope, controller) { - - var videos = _.keys(controller.peers); - var peers = controller.peers; - var container = scope.container; - var layoutparent = scope.layoutparent; - - if (!current) { - current = new renderers[name](container, scope, controller) - console.log("Created new video layout renderer", name, current); - $(layoutparent).addClass("renderer-"+name); - return true; - } else { - if (current.name !== name) { - current.close(container, scope, controller); - $(container).removeAttr("style"); - $(layoutparent).removeClass("renderer-"+current.name); - current = new renderers[name](container, scope, controller) - $(layoutparent).addClass("renderer-"+name); - console.log("Switched to new video layout renderer", name, current); - return true; - } - } - - return current.render(container, size, scope, videos, peers); - - }, - register: function(name, impl) { - renderers[name] = impl; - }, - layouts: function() { - return _.keys(renderers); - } - } - - }]; + }; + + ConferenceKiosk.prototype.close = function(container, scope, controller) { + this.closed = true; + if (this.big) { + this.remoteVideos.append(this.big); + this.big.find("video").get(0).play(); + } + this.big = null; + this.bigVideo.remove() + this.bigVideo = null; + this.remoteVideos = null; + }; + + + // Register renderers. + renderers[OnePeople.prototype.name] = OnePeople; + renderers[Smally.prototype.name] = Smally; + renderers[ConferenceKiosk.prototype.name] = ConferenceKiosk; + + + // Public api. + var current = null; + return { + update: function(name, size, scope, controller) { + + var videos = _.keys(controller.peers); + var peers = controller.peers; + var container = scope.container; + var layoutparent = scope.layoutparent; + + if (!current) { + current = new renderers[name](container, scope, controller) + console.log("Created new video layout renderer", name, current); + $(layoutparent).addClass("renderer-"+name); + return true; + } else { + if (current.name !== name) { + current.close(container, scope, controller); + $(container).removeAttr("style"); + $(layoutparent).removeClass("renderer-"+current.name); + current = new renderers[name](container, scope, controller) + $(layoutparent).addClass("renderer-"+name); + console.log("Switched to new video layout renderer", name, current); + return true; + } + } + + return current.render(container, size, scope, videos, peers); + + }, + register: function(name, impl) { + renderers[name] = impl; + }, + layouts: function() { + return _.keys(renderers); + } + } + + }]; }); \ No newline at end of file