diff --git a/Gemfile.lock b/Gemfile.lock index d60ff37f..6713e2fc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -114,7 +114,7 @@ GEM font-awesome-rails (4.2.0.0) railties (>= 3.2, < 5.0) formatador (0.2.5) - formtastic (2.3.0) + formtastic (2.3.1) actionpack (>= 3.0) fssm (0.2.10) geocoder (1.2.4) @@ -160,7 +160,7 @@ GEM jbuilder (2.1.3) activesupport (>= 3.0.0, < 5) multi_json (~> 1.2) - jquery-rails (3.1.1) + jquery-rails (3.1.2) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) jquery-turbolinks (2.1.0) @@ -282,7 +282,7 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sprockets-rails (2.1.3) + sprockets-rails (2.1.4) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (~> 2.8) @@ -313,7 +313,7 @@ GEM warden (1.2.3) rack (>= 1.0) webrick (1.3.1) - webshims-rails (1.14.6) + webshims-rails (1.15.2) rails (> 3.1.0) PLATFORMS diff --git a/public/webshims/extras/modernizr-custom.js b/public/webshims/extras/modernizr-custom.js deleted file mode 100644 index faae2ae5..00000000 --- a/public/webshims/extras/modernizr-custom.js +++ /dev/null @@ -1,511 +0,0 @@ -/* Modernizr 2.7.1 (Custom Build) | MIT & BSD - * Build: http://modernizr.com/download/#-canvas-audio-video-input-inputtypes-geolocation-shiv-addtest-prefixed-testprop-testallprops-prefixes-domprefixes - */ -; - - - -window.Modernizr = (function( window, document, undefined ) { - - var version = '2.7.1', - - Modernizr = {}, - - - docElement = document.documentElement, - - mod = 'modernizr', - modElem = document.createElement(mod), - mStyle = modElem.style, - - inputElem = document.createElement('input') , - - smile = ':)', - - toString = {}.toString, - - prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), - - - - omPrefixes = 'Webkit Moz O ms', - - cssomPrefixes = omPrefixes.split(' '), - - domPrefixes = omPrefixes.toLowerCase().split(' '), - - - tests = {}, - inputs = {}, - attrs = {}, - - classes = [], - - slice = classes.slice, - - featureName, - - - - _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; - - if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { - hasOwnProp = function (object, property) { - return _hasOwnProperty.call(object, property); - }; - } - else { - hasOwnProp = function (object, property) { - return ((property in object) && is(object.constructor.prototype[property], 'undefined')); - }; - } - - - if (!Function.prototype.bind) { - Function.prototype.bind = function bind(that) { - - var target = this; - - if (typeof target != "function") { - throw new TypeError(); - } - - var args = slice.call(arguments, 1), - bound = function () { - - if (this instanceof bound) { - - var F = function(){}; - F.prototype = target.prototype; - var self = new F(); - - var result = target.apply( - self, - args.concat(slice.call(arguments)) - ); - if (Object(result) === result) { - return result; - } - return self; - - } else { - - return target.apply( - that, - args.concat(slice.call(arguments)) - ); - - } - - }; - - return bound; - }; - } - - function setCss( str ) { - mStyle.cssText = str; - } - - function setCssAll( str1, str2 ) { - return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); - } - - function is( obj, type ) { - return typeof obj === type; - } - - function contains( str, substr ) { - return !!~('' + str).indexOf(substr); - } - - function testProps( props, prefixed ) { - for ( var i in props ) { - var prop = props[i]; - if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { - return prefixed == 'pfx' ? prop : true; - } - } - return false; - } - - function testDOMProps( props, obj, elem ) { - for ( var i in props ) { - var item = obj[props[i]]; - if ( item !== undefined) { - - if (elem === false) return props[i]; - - if (is(item, 'function')){ - return item.bind(elem || obj); - } - - return item; - } - } - return false; - } - - function testPropsAll( prop, prefixed, elem ) { - - var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), - props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); - - if(is(prefixed, "string") || is(prefixed, "undefined")) { - return testProps(props, prefixed); - - } else { - props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); - return testDOMProps(props, prefixed, elem); - } - } - - - - tests['canvas'] = function() { - var elem = document.createElement('canvas'); - return !!(elem.getContext && elem.getContext('2d')); - }; tests['geolocation'] = function() { - return 'geolocation' in navigator; - }; - - - tests['video'] = function() { - var elem = document.createElement('video'), - bool = false; - - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); - - bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); - - bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); - } - - } catch(e) { } - - return bool; - }; - - tests['audio'] = function() { - var elem = document.createElement('audio'), - bool = false; - - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); - bool.mp3 = elem.canPlayType('audio/mpeg;') .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$/,''); - } - } catch(e) { } - - return bool; - }; function webforms() { - Modernizr['input'] = (function( props ) { - for ( var i = 0, len = props.length; i < len; i++ ) { - attrs[ props[i] ] = !!(props[i] in inputElem); - } - if (attrs.list){ - attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); - } - return attrs; - })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); - 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'; - - if ( bool ) { - - inputElem.value = smile; - inputElem.style.cssText = 'position:absolute;visibility:hidden;'; - - if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { - - docElement.appendChild(inputElem); - defaultView = document.defaultView; - - bool = defaultView.getComputedStyle && - defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && - (inputElem.offsetHeight !== 0); - - docElement.removeChild(inputElem); - - } else if ( /^(search|tel)$/.test(inputElemType) ){ - } else if ( /^(url|email)$/.test(inputElemType) ) { - bool = inputElem.checkValidity && inputElem.checkValidity() === false; - - } else { - bool = inputElem.value != smile; - } - } - - inputs[ props[i] ] = !!bool; - } - return inputs; - })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); - } - for ( var feature in tests ) { - if ( hasOwnProp(tests, feature) ) { - featureName = feature.toLowerCase(); - Modernizr[featureName] = tests[feature](); - - classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); - } - } - - Modernizr.input || webforms(); - - - Modernizr.addTest = function ( feature, test ) { - if ( typeof feature == 'object' ) { - for ( var key in feature ) { - if ( hasOwnProp( feature, key ) ) { - Modernizr.addTest( key, feature[ key ] ); - } - } - } else { - - feature = feature.toLowerCase(); - - if ( Modernizr[feature] !== undefined ) { - return Modernizr; - } - - test = typeof test == 'function' ? test() : test; - - if (typeof enableClasses !== "undefined" && enableClasses) { - docElement.className += ' ' + (test ? '' : 'no-') + feature; - } - Modernizr[feature] = test; - - } - - return Modernizr; - }; - - - setCss(''); - modElem = inputElem = null; - - ;(function(window, document) { - var version = '3.7.0'; - - var options = window.html5 || {}; - - var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/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; - - var supportsHtml5Styles; - - var expando = '_html5shiv'; - - var expanID = 0; - - var expandoData = {}; - - var supportsUnknownElements; - - (function() { - try { - var a = document.createElement('a'); - a.innerHTML = ''; - supportsHtml5Styles = ('hidden' in a); - - supportsUnknownElements = a.childNodes.length == 1 || (function() { - (document.createElement)('a'); - var frag = document.createDocumentFragment(); - return ( - typeof frag.cloneNode == 'undefined' || - typeof frag.createDocumentFragment == 'undefined' || - typeof frag.createElement == 'undefined' - ); - }()); - } catch(e) { - supportsHtml5Styles = true; - supportsUnknownElements = true; - } - - }()); - - function addStyleSheet(ownerDocument, cssText) { - var p = ownerDocument.createElement('p'), - parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; - - p.innerHTML = 'x'; - return parent.insertBefore(p.lastChild, parent.firstChild); - } - - function getElements() { - var elements = html5.elements; - return typeof elements == 'string' ? elements.split(' ') : elements; - } - - function getExpandoData(ownerDocument) { - var data = expandoData[ownerDocument[expando]]; - if (!data) { - data = {}; - expanID++; - ownerDocument[expando] = expanID; - expandoData[expanID] = data; - } - return data; - } - - function createElement(nodeName, ownerDocument, data){ - if (!ownerDocument) { - ownerDocument = document; - } - if(supportsUnknownElements){ - return ownerDocument.createElement(nodeName); - } - if (!data) { - data = getExpandoData(ownerDocument); - } - var node; - - if (data.cache[nodeName]) { - node = data.cache[nodeName].cloneNode(); - } else if (saveClones.test(nodeName)) { - node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); - } else { - node = data.createElem(nodeName); - } - - return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; - } - - function createDocumentFragment(ownerDocument, data){ - if (!ownerDocument) { - ownerDocument = document; - } - if(supportsUnknownElements){ - return ownerDocument.createDocumentFragment(); - } - data = data || getExpandoData(ownerDocument); - var clone = data.frag.cloneNode(), - i = 0, - elems = getElements(), - l = elems.length; - for(;i + // + // - + // - + // - - + + // - + // - + + /* + // + */ + //
- - + + //>removeCombos< addPolyfill('feature-dummy', { test: true, loaded: true, c: removeCombos }); - + webshims.$ = $; $.webshims = webshims; $.webshim = webshim; diff --git a/public/webshims/shims/canvas-blob.js b/public/webshims/shims/canvas-blob.js new file mode 100644 index 00000000..c851ff2b --- /dev/null +++ b/public/webshims/shims/canvas-blob.js @@ -0,0 +1,97 @@ +/* + * JavaScript Canvas to Blob 2.0.5 + * https://github.com/blueimp/JavaScript-Canvas-to-Blob + * + * Copyright 2012, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + * + * Based on stackoverflow user Stoive's code snippet: + * http://stackoverflow.com/q/4998908 + */ + +/*jslint nomen: true, regexp: true */ +/*global window, atob, Blob, ArrayBuffer, Uint8Array, define */ + +(function (window) { + 'use strict'; + var CanvasPrototype = window.HTMLCanvasElement && + window.HTMLCanvasElement.prototype, + hasBlobConstructor = window.Blob && (function () { + try { + return Boolean(new Blob()); + } catch (e) { + return false; + } + }()), + hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && + (function () { + try { + return new Blob([new Uint8Array(100)]).size === 100; + } catch (e) { + return false; + } + }()), + BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || + window.MozBlobBuilder || window.MSBlobBuilder, + dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob && + window.ArrayBuffer && window.Uint8Array && function (dataURI) { + var byteString, + arrayBuffer, + intArray, + i, + mimeString, + bb; + if (dataURI.split(',')[0].indexOf('base64') >= 0) { + // Convert base64 to raw binary data held in a string: + byteString = atob(dataURI.split(',')[1]); + } else { + // Convert base64/URLEncoded data component to raw binary data: + byteString = decodeURIComponent(dataURI.split(',')[1]); + } + // Write the bytes of the string to an ArrayBuffer: + arrayBuffer = new ArrayBuffer(byteString.length); + intArray = new Uint8Array(arrayBuffer); + for (i = 0; i < byteString.length; i += 1) { + intArray[i] = byteString.charCodeAt(i); + } + // Separate out the mime component: + mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; + // Write the ArrayBuffer (or ArrayBufferView) to a blob: + if (hasBlobConstructor) { + return new Blob( + [hasArrayBufferViewSupport ? intArray : arrayBuffer], + {type: mimeString} + ); + } + bb = new BlobBuilder(); + bb.append(arrayBuffer); + return bb.getBlob(mimeString); + }; + if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) { + if (CanvasPrototype.mozGetAsFile) { + CanvasPrototype.toBlob = function (callback, type, quality) { + if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) { + callback(dataURLtoBlob(this.toDataURL(type, quality))); + } else { + callback(this.mozGetAsFile('blob', type)); + } + }; + } else if (CanvasPrototype.toDataURL && dataURLtoBlob) { + CanvasPrototype.toBlob = function (callback, type, quality) { + callback(dataURLtoBlob(this.toDataURL(type, quality))); + }; + } + } + if (typeof define === 'function' && define.amd) { + define(function () { + return dataURLtoBlob; + }); + } else { + window.dataURLtoBlob = dataURLtoBlob; + } +}(this)); + +webshim.isReady('canvas-blob', true); diff --git a/public/webshims/shims/combos/1.js b/public/webshims/shims/combos/1.js index eca02f30..ab108637 100644 --- a/public/webshims/shims/combos/1.js +++ b/public/webshims/shims/combos/1.js @@ -524,20 +524,6 @@ webshims.isReady('swfmini', true); } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } @@ -606,9 +592,16 @@ webshims.isReady('swfmini', true); })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -704,7 +697,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -890,6 +885,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -1054,6 +1050,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -1076,6 +1073,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); diff --git a/public/webshims/shims/combos/10.js b/public/webshims/shims/combos/10.js index b385b1f9..6950280f 100644 --- a/public/webshims/shims/combos/10.js +++ b/public/webshims/shims/combos/10.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('
').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -3045,7 +3045,8 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine (function(){ var picker = {}; - var assumeVirtualKeyBoard = (window.Modernizr && (Modernizr.touchevents || Modernizr.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); + var modern = window.Modernizr; + var assumeVirtualKeyBoard = (modern && (modern.touchevents || modern.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); webshims.inlinePopover = { _create: function(){ this.element = $('
').data('wspopover', this); diff --git a/public/webshims/shims/combos/11.js b/public/webshims/shims/combos/11.js index 8e810bbe..2c8d3b36 100644 --- a/public/webshims/shims/combos/11.js +++ b/public/webshims/shims/combos/11.js @@ -1814,7 +1814,8 @@ (function(){ var picker = {}; - var assumeVirtualKeyBoard = (window.Modernizr && (Modernizr.touchevents || Modernizr.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); + var modern = window.Modernizr; + var assumeVirtualKeyBoard = (modern && (modern.touchevents || modern.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); webshims.inlinePopover = { _create: function(){ this.element = $('
').data('wspopover', this); diff --git a/public/webshims/shims/combos/12.js b/public/webshims/shims/combos/12.js index d9b3804c..a497911c 100644 --- a/public/webshims/shims/combos/12.js +++ b/public/webshims/shims/combos/12.js @@ -281,9 +281,16 @@ webshims.isReady('swfmini', true); })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -379,7 +386,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -565,6 +574,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -729,6 +739,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -751,6 +762,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); @@ -835,8 +847,12 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u var lastCue = this.cues[this.cues.length-1]; if(lastCue && lastCue.startTime > cue.startTime){ webshims.error("cue startTime higher than previous cue's startTime"); + return; } } + if(cue.startTime >= cue.endTime ){ + webshim.error('startTime >= endTime of cue: '+ cue.text); + } if(cue.track && cue.track.removeCue){ cue.track.removeCue(cue); } @@ -928,6 +944,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u for(i = 0, len = added.length; i < len; i++){ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: added[i]})); } + //todo: remove if(baseData.scriptedTextTracks || removed.length){ $(this).triggerHandler('updatetrackdisplay'); } @@ -944,7 +961,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u setTimeout(function(){ $(track).closest('audio, video').triggerHandler('updatetrackdisplay'); trackData.isTriggering = false; - }, 1); + }, 9); } }; var isDefaultTrack = (function(){ @@ -1137,15 +1154,10 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u error: error }); }; - if($.ajax && $.ajaxSettings.xhr){ - if(isDisabled){ - setTimeout(createAjax, loadingTracks * 2); - } else { - createAjax(); - } + if(isDisabled){ + setTimeout(createAjax, loadingTracks * 2); } else { - webshims.ready('jajax', createAjax); - webshims.loader.loadList(['jajax']); + createAjax(); } } catch(er){ error(); diff --git a/public/webshims/shims/combos/13.js b/public/webshims/shims/combos/13.js index 9a839aa2..12cb9955 100644 --- a/public/webshims/shims/combos/13.js +++ b/public/webshims/shims/combos/13.js @@ -58,9 +58,16 @@ })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -156,7 +163,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -342,6 +351,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -506,6 +516,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -528,6 +539,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); @@ -612,8 +624,12 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u var lastCue = this.cues[this.cues.length-1]; if(lastCue && lastCue.startTime > cue.startTime){ webshims.error("cue startTime higher than previous cue's startTime"); + return; } } + if(cue.startTime >= cue.endTime ){ + webshim.error('startTime >= endTime of cue: '+ cue.text); + } if(cue.track && cue.track.removeCue){ cue.track.removeCue(cue); } @@ -705,6 +721,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u for(i = 0, len = added.length; i < len; i++){ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: added[i]})); } + //todo: remove if(baseData.scriptedTextTracks || removed.length){ $(this).triggerHandler('updatetrackdisplay'); } @@ -721,7 +738,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u setTimeout(function(){ $(track).closest('audio, video').triggerHandler('updatetrackdisplay'); trackData.isTriggering = false; - }, 1); + }, 9); } }; var isDefaultTrack = (function(){ @@ -914,15 +931,10 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u error: error }); }; - if($.ajax && $.ajaxSettings.xhr){ - if(isDisabled){ - setTimeout(createAjax, loadingTracks * 2); - } else { - createAjax(); - } + if(isDisabled){ + setTimeout(createAjax, loadingTracks * 2); } else { - webshims.ready('jajax', createAjax); - webshims.loader.loadList(['jajax']); + createAjax(); } } catch(er){ error(); diff --git a/public/webshims/shims/combos/15.js b/public/webshims/shims/combos/15.js index 986d8323..4bb2d83d 100644 --- a/public/webshims/shims/combos/15.js +++ b/public/webshims/shims/combos/15.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1532,20 +1532,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } @@ -1653,7 +1639,6 @@ var isPlaceholderOptionSelected = function(select){ }; var emptyJ = $([]); -//TODO: cache + perftest var getGroupElements = function(elem){ elem = $(elem); var name, form; @@ -1723,7 +1708,7 @@ var validityRules = { $.each({tooShort: ['minLength', -1], tooLong: ['maxLength', 1]}, function(name, props){ validityRules[name] = function(input, val, cache){ //defaultValue is not the same as dirty flag, but very similiar - if(cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;} + if(!val || cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;} cacheType(cache, input[0]); diff --git a/public/webshims/shims/combos/16.js b/public/webshims/shims/combos/16.js index 0022b246..6d835b00 100644 --- a/public/webshims/shims/combos/16.js +++ b/public/webshims/shims/combos/16.js @@ -287,11 +287,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -904,33 +900,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1755,20 +1755,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } @@ -1876,7 +1862,6 @@ var isPlaceholderOptionSelected = function(select){ }; var emptyJ = $([]); -//TODO: cache + perftest var getGroupElements = function(elem){ elem = $(elem); var name, form; @@ -1946,7 +1931,7 @@ var validityRules = { $.each({tooShort: ['minLength', -1], tooLong: ['maxLength', 1]}, function(name, props){ validityRules[name] = function(input, val, cache){ //defaultValue is not the same as dirty flag, but very similiar - if(cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;} + if(!val || cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;} cacheType(cache, input[0]); @@ -3253,9 +3238,16 @@ webshims.defineNodeNamesProperties(['input', 'button'], formSubmitterDescriptors })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -3351,7 +3343,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -3537,6 +3531,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -3701,6 +3696,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -3723,6 +3719,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); diff --git a/public/webshims/shims/combos/17.js b/public/webshims/shims/combos/17.js index 2c752f22..e6eb2bd2 100644 --- a/public/webshims/shims/combos/17.js +++ b/public/webshims/shims/combos/17.js @@ -2430,7 +2430,8 @@ webshims.register('form-number-date-api', function($, webshims, window, document (function(){ var picker = {}; - var assumeVirtualKeyBoard = (window.Modernizr && (Modernizr.touchevents || Modernizr.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); + var modern = window.Modernizr; + var assumeVirtualKeyBoard = (modern && (modern.touchevents || modern.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); webshims.inlinePopover = { _create: function(){ this.element = $('
').data('wspopover', this); diff --git a/public/webshims/shims/combos/2.js b/public/webshims/shims/combos/2.js index 9061890a..258147b9 100644 --- a/public/webshims/shims/combos/2.js +++ b/public/webshims/shims/combos/2.js @@ -287,11 +287,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -904,33 +900,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1755,20 +1755,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } @@ -2134,9 +2120,16 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -2232,7 +2225,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -2418,6 +2413,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -2582,6 +2578,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -2604,6 +2601,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); diff --git a/public/webshims/shims/combos/21.js b/public/webshims/shims/combos/21.js index 1ca9a7f1..fd661965 100644 --- a/public/webshims/shims/combos/21.js +++ b/public/webshims/shims/combos/21.js @@ -92,52 +92,46 @@ } return; } - createAjax = function(){ - $.ajax({ - url: 'http://freegeoip.net/json/', - dataType: 'jsonp', - cache: true, - jsonp: 'callback', - success: function(data){ - locationAPIs--; - if(!data){return;} - pos = pos || { - coords: { - latitude: data.latitude, - longitude: data.longitude, - altitude: null, - accuracy: 43000, - altitudeAccuracy: null, - heading: parseInt('NaN', 10), - velocity: null - }, - //extension similiar to FF implementation - address: { - city: data.city, - country: data.country_name, - countryCode: data.country_code, - county: "", - postalCode: data.zipcode, - premises: "", - region: data.region_name, - street: "", - streetNumber: "" - } - }; - endCallback(); - }, - error: function(){ - locationAPIs--; - endCallback(); - } - }); - }; - if($.ajax){ - createAjax(); - } else { - webshims.ready('jajax', createAjax); - webshims.loader.loadList(['jajax']); - } + + $.ajax({ + url: 'http://freegeoip.net/json/', + dataType: 'jsonp', + cache: true, + jsonp: 'callback', + success: function(data){ + locationAPIs--; + if(!data){return;} + pos = pos || { + coords: { + latitude: data.latitude, + longitude: data.longitude, + altitude: null, + accuracy: 43000, + altitudeAccuracy: null, + heading: parseInt('NaN', 10), + velocity: null + }, + //extension similiar to FF implementation + address: { + city: data.city, + country: data.country_name, + countryCode: data.country_code, + county: "", + postalCode: data.zipcode, + premises: "", + region: data.region_name, + street: "", + streetNumber: "" + } + }; + endCallback(); + }, + error: function(){ + locationAPIs--; + endCallback(); + } + }); + clearTimeout(googleTimer); if (!window.google || !window.google.loader) { googleTimer = setTimeout(function(){ @@ -179,10 +173,7 @@ }; return api; })()); - - webshims.ready('WINDOWLOAD', function(){ - webshims.loader.loadList(['jajax']); - }); + webshims.isReady('geolocation', true); })(webshims.$); ;webshims.register('details', function($, webshims, window, doc, undefined, options){ @@ -459,12 +450,13 @@ }; - mediaelement.jarisEvent = {}; + mediaelement.jarisEvent = mediaelement.jarisEvent || {}; var localConnectionTimer; var onEvent = { onPlayPause: function(jaris, data, override){ var playing, type; var idled = data.paused || data.ended; + if(override == null){ try { playing = data.api.api_get("isPlaying"); @@ -478,12 +470,15 @@ type = data.paused ? 'pause' : 'play'; data._ppFlag = true; trigger(data._elem, type); + + } + if(!data.paused || playing == idled || playing == null){ if(data.readyState < 3){ setReadyState(3, data); } - if(!data.paused){ - trigger(data._elem, 'playing'); - } + } + if(!data.paused){ + trigger(data._elem, 'playing'); } }, onSeek: function(jaris, data){ @@ -1235,11 +1230,11 @@ options.changeSWF(vars, elem, canPlaySrc, data, 'embed'); clearTimeout(data.flashBlock); - swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "9.0.115", false, vars, params, attrs, function(swfData){ + swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "11.3", false, vars, params, attrs, function(swfData){ if(swfData.success){ var fBlocker = function(){ - if((!swfData.ref.parentNode && box[0].parentNode) || swfData.ref.style.display == "none"){ - box.addClass('flashblocker-assumed'); + if((!swfData.ref.parentNode) || swfData.ref.style.display == "none"){ + $(elem).trigger('flashblocker'); webshims.warn("flashblocker assumed"); } @@ -1473,8 +1468,19 @@ webshim.error('canvas.drawImage feature is needed. In IE8 flashvanvas pro can be used'); } + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + if(this._wsIsLoading){ + if(!this._wsLoadingCbs){ + this._wsLoadingCbs = []; + } + this._wsLoadingCbs.push(cb); + } else { + cb.call(this, this); + } + }; + CanvasRenderingContext2D.prototype.drawImage = function(elem){ - var data, img, args, imgData; + var data, img, args, imgData, hadCachedImg; var context = this; if(isVideo[elem.nodeName] && (data = webshims.data(elem, 'mediaelement')) && data.isActive == 'third' && data.api.api_image){ @@ -1492,18 +1498,39 @@ } args = slice.call(arguments, 1); - img = new Image(); + + if(options.canvasSync && data.canvasImg){ + args.unshift(data.canvasImg); + _drawImage.apply(context, args); + args = slice.call(arguments, 1); + hadCachedImg = true; + } + + img = document.createElement('img'); //todo find a performant sync way img.onload = function(){ args.unshift(this); - _drawImage.apply(context, args); img.onload = null; + + if(options.canvasSync){ + data.canvasImg = img; + if(hadCachedImg && options.noDoubbleDraw){ + return; + } + } + _drawImage.apply(context, args); + context._wsIsLoading = false; + if(context._wsLoadingCbs && context._wsLoadingCbs.length){ + while(context._wsLoadingCbs.length){ + context._wsLoadingCbs.shift().call(context, context); + } + } }; img.src = 'data:image/jpeg;base64,'+imgData; - - if(img.complete){ + this._wsIsLoading = true; + if(img.complete && img.onload){ img.onload(); } return; @@ -1737,8 +1764,12 @@ var lastCue = this.cues[this.cues.length-1]; if(lastCue && lastCue.startTime > cue.startTime){ webshims.error("cue startTime higher than previous cue's startTime"); + return; } } + if(cue.startTime >= cue.endTime ){ + webshim.error('startTime >= endTime of cue: '+ cue.text); + } if(cue.track && cue.track.removeCue){ cue.track.removeCue(cue); } @@ -1830,6 +1861,7 @@ for(i = 0, len = added.length; i < len; i++){ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: added[i]})); } + //todo: remove if(baseData.scriptedTextTracks || removed.length){ $(this).triggerHandler('updatetrackdisplay'); } @@ -1846,7 +1878,7 @@ setTimeout(function(){ $(track).closest('audio, video').triggerHandler('updatetrackdisplay'); trackData.isTriggering = false; - }, 1); + }, 9); } }; var isDefaultTrack = (function(){ @@ -2039,15 +2071,10 @@ error: error }); }; - if($.ajax && $.ajaxSettings.xhr){ - if(isDisabled){ - setTimeout(createAjax, loadingTracks * 2); - } else { - createAjax(); - } + if(isDisabled){ + setTimeout(createAjax, loadingTracks * 2); } else { - webshims.ready('jajax', createAjax); - webshims.loader.loadList(['jajax']); + createAjax(); } } catch(er){ error(); diff --git a/public/webshims/shims/combos/22.js b/public/webshims/shims/combos/22.js index d5da49db..824dba25 100644 --- a/public/webshims/shims/combos/22.js +++ b/public/webshims/shims/combos/22.js @@ -214,8 +214,12 @@ webshims.register('details', function($, webshims, window, doc, undefined, optio var lastCue = this.cues[this.cues.length-1]; if(lastCue && lastCue.startTime > cue.startTime){ webshims.error("cue startTime higher than previous cue's startTime"); + return; } } + if(cue.startTime >= cue.endTime ){ + webshim.error('startTime >= endTime of cue: '+ cue.text); + } if(cue.track && cue.track.removeCue){ cue.track.removeCue(cue); } @@ -307,6 +311,7 @@ webshims.register('details', function($, webshims, window, doc, undefined, optio for(i = 0, len = added.length; i < len; i++){ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: added[i]})); } + //todo: remove if(baseData.scriptedTextTracks || removed.length){ $(this).triggerHandler('updatetrackdisplay'); } @@ -323,7 +328,7 @@ webshims.register('details', function($, webshims, window, doc, undefined, optio setTimeout(function(){ $(track).closest('audio, video').triggerHandler('updatetrackdisplay'); trackData.isTriggering = false; - }, 1); + }, 9); } }; var isDefaultTrack = (function(){ @@ -516,15 +521,10 @@ webshims.register('details', function($, webshims, window, doc, undefined, optio error: error }); }; - if($.ajax && $.ajaxSettings.xhr){ - if(isDisabled){ - setTimeout(createAjax, loadingTracks * 2); - } else { - createAjax(); - } + if(isDisabled){ + setTimeout(createAjax, loadingTracks * 2); } else { - webshims.ready('jajax', createAjax); - webshims.loader.loadList(['jajax']); + createAjax(); } } catch(er){ error(); diff --git a/public/webshims/shims/combos/23.js b/public/webshims/shims/combos/23.js index ca2406ff..98b2b17c 100644 --- a/public/webshims/shims/combos/23.js +++ b/public/webshims/shims/combos/23.js @@ -281,9 +281,16 @@ webshims.isReady('swfmini', true); })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -379,7 +386,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -565,6 +574,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -729,6 +739,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -751,6 +762,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); diff --git a/public/webshims/shims/combos/25.js b/public/webshims/shims/combos/25.js index 13176bb7..4ca46549 100644 --- a/public/webshims/shims/combos/25.js +++ b/public/webshims/shims/combos/25.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1229,11 +1229,11 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine })(); }); -;webshim.register('filereader', function($, webshim, window, document, undefined, featureOptions){ +;webshim.register('filereader-xhr', function($, webshim, window, document, undefined, featureOptions){ "use strict"; var mOxie, moxie, hasXDomain; - var FormData = $.noop; - var sel = 'input[type="file"].ws-filereader'; + var sel = 'input[type="file"].ws-filereader, input[type="file"].ws-capture'; + var hasFlash = swfmini.hasFlashPlayerVersion('10.3'); var loadMoxie = function (){ webshim.loader.loadList(['moxie']); }; @@ -1345,7 +1345,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } ); var shimMoxiePath = webshim.cfg.basePath+'moxie/'; - var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf/moxie.xap on your server an configure filereader options: "swfpath"/"xappath"'; + var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf on your server an configure filereader options: "swfpath"'; var testMoxie = function(options){ return (options.wsType == 'moxie' || (options.data && options.data instanceof mOxie.FormData) || (options.crossDomain && $.support.cors !== false && hasXDomain != 'no' && !noxhr.test(options.dataType || ''))); }; @@ -1528,6 +1528,10 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }; + webshim.loader.addModule('moxie', { + src: 'moxie/js/moxie-'+ (hasFlash ? 'swf' : 'html4') + }); + if(!featureOptions.progress){ featureOptions.progress = 'onprogress'; } @@ -1539,9 +1543,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine if(!featureOptions.swfpath){ featureOptions.swfpath = shimMoxiePath+'flash/Moxie.min.swf'; } - if(!featureOptions.xappath){ - featureOptions.xappath = shimMoxiePath+'silverlight/Moxie.min.xap'; - } if($.support.cors !== false || !window.XDomainRequest){ delete transports.xdomain; @@ -1568,8 +1569,8 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine writeable: false, get: function(){ if(this.type != 'file'){return null;} - if(!$(this).hasClass('ws-filereader')){ - webshim.info("please add the 'ws-filereader' class to your input[type='file'] to implement files-property"); + if(!$(this).is('.ws-filereader, .ws-capture')){ + webshim.info("please add the 'ws-filereader'/'ws-capture' class to your input[type='file'] to implement files-property"); } return webshim.data(this, 'fileList') || []; } @@ -1591,11 +1592,66 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine }); webshim.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){ - if(value === '' && this.type == 'file' && $(this).hasClass('ws-filereader')){ + if(value === '' && this.type == 'file' && $(this).is('.ws-filereader, .ws-capture')){ webshim.data(this, 'fileList', []); } }); + if(!document.createElement('canvas').toBlob){ + + webshim.defineNodeNameProperty('canvas', 'toBlob', { + prop: { + value: function(cb, type, qualitiy){ + var dataURL; + var $canvas = $(this); + if(!type){ + type = 'image/jpeg'; + } + if(type == 'image/jpeg' && !qualitiy){ + qualitiy = 0.8; + } + loadMoxie(); + setTimeout(function(){ + dataURL = $canvas.callProp('getAsDataURL', [type, qualitiy]); + webshim.ready('moxie', function(){ + var img = new mOxie.Image(); + + img.onload = function() { + var blob = img.getAsBlob(); + webshim.defineProperty(blob, '_wsDataURL', { + value: dataURL, + enumerable: false + }); + cb(blob); + }; + img.load(dataURL); + }); + }, 9); + } + } + }); + + webshim.ready('url', function(){ + var _nativeCreateObjectURL = URL.createObjectURL; + var _nativeRevokeObjectURL = URL.revokeObjectURL; + + URL.createObjectURL = function(obj){ + var url = obj; + if(obj._wsimgDataURL) { + url = obj._wsimgDataURL; + } else if(_nativeCreateObjectURL){ + return _nativeCreateObjectURL.apply(this, arguments); + } + return url; + }; + + URL.revokeObjectURL = function(url){ + if (_nativeRevokeObjectURL){ + return _nativeRevokeObjectURL.apply(this, arguments); + } + }; + }); + } window.FileReader = notReadyYet; window.FormData = notReadyYet; @@ -1605,7 +1661,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine mOxie = window.mOxie; mOxie.Env.swf_url = featureOptions.swfpath; - mOxie.Env.xap_url = featureOptions.xappath; window.FileReader = mOxie.FileReader; @@ -1644,7 +1699,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine return moxieData; }; - FormData = window.FormData; createFilePicker = _createFilePicker; transports.moxie = createMoxieTransport; @@ -1829,12 +1883,13 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine }; - mediaelement.jarisEvent = {}; + mediaelement.jarisEvent = mediaelement.jarisEvent || {}; var localConnectionTimer; var onEvent = { onPlayPause: function(jaris, data, override){ var playing, type; var idled = data.paused || data.ended; + if(override == null){ try { playing = data.api.api_get("isPlaying"); @@ -1848,12 +1903,15 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine type = data.paused ? 'pause' : 'play'; data._ppFlag = true; trigger(data._elem, type); + + } + if(!data.paused || playing == idled || playing == null){ if(data.readyState < 3){ setReadyState(3, data); } - if(!data.paused){ - trigger(data._elem, 'playing'); - } + } + if(!data.paused){ + trigger(data._elem, 'playing'); } }, onSeek: function(jaris, data){ @@ -2605,11 +2663,11 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine options.changeSWF(vars, elem, canPlaySrc, data, 'embed'); clearTimeout(data.flashBlock); - swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "9.0.115", false, vars, params, attrs, function(swfData){ + swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "11.3", false, vars, params, attrs, function(swfData){ if(swfData.success){ var fBlocker = function(){ - if((!swfData.ref.parentNode && box[0].parentNode) || swfData.ref.style.display == "none"){ - box.addClass('flashblocker-assumed'); + if((!swfData.ref.parentNode) || swfData.ref.style.display == "none"){ + $(elem).trigger('flashblocker'); webshims.warn("flashblocker assumed"); } @@ -2843,8 +2901,19 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshim.error('canvas.drawImage feature is needed. In IE8 flashvanvas pro can be used'); } + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + if(this._wsIsLoading){ + if(!this._wsLoadingCbs){ + this._wsLoadingCbs = []; + } + this._wsLoadingCbs.push(cb); + } else { + cb.call(this, this); + } + }; + CanvasRenderingContext2D.prototype.drawImage = function(elem){ - var data, img, args, imgData; + var data, img, args, imgData, hadCachedImg; var context = this; if(isVideo[elem.nodeName] && (data = webshims.data(elem, 'mediaelement')) && data.isActive == 'third' && data.api.api_image){ @@ -2862,18 +2931,39 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } args = slice.call(arguments, 1); - img = new Image(); + + if(options.canvasSync && data.canvasImg){ + args.unshift(data.canvasImg); + _drawImage.apply(context, args); + args = slice.call(arguments, 1); + hadCachedImg = true; + } + + img = document.createElement('img'); //todo find a performant sync way img.onload = function(){ args.unshift(this); - _drawImage.apply(context, args); img.onload = null; + + if(options.canvasSync){ + data.canvasImg = img; + if(hadCachedImg && options.noDoubbleDraw){ + return; + } + } + _drawImage.apply(context, args); + context._wsIsLoading = false; + if(context._wsLoadingCbs && context._wsLoadingCbs.length){ + while(context._wsLoadingCbs.length){ + context._wsLoadingCbs.shift().call(context, context); + } + } }; img.src = 'data:image/jpeg;base64,'+imgData; - - if(img.complete){ + this._wsIsLoading = true; + if(img.complete && img.onload){ img.onload(); } return; diff --git a/public/webshims/shims/combos/27.js b/public/webshims/shims/combos/27.js index ab2667a2..880c79cb 100644 --- a/public/webshims/shims/combos/27.js +++ b/public/webshims/shims/combos/27.js @@ -1250,11 +1250,11 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u }); -;webshim.register('filereader', function($, webshim, window, document, undefined, featureOptions){ +;webshim.register('filereader-xhr', function($, webshim, window, document, undefined, featureOptions){ "use strict"; var mOxie, moxie, hasXDomain; - var FormData = $.noop; - var sel = 'input[type="file"].ws-filereader'; + var sel = 'input[type="file"].ws-filereader, input[type="file"].ws-capture'; + var hasFlash = swfmini.hasFlashPlayerVersion('10.3'); var loadMoxie = function (){ webshim.loader.loadList(['moxie']); }; @@ -1366,7 +1366,7 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u } ); var shimMoxiePath = webshim.cfg.basePath+'moxie/'; - var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf/moxie.xap on your server an configure filereader options: "swfpath"/"xappath"'; + var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf on your server an configure filereader options: "swfpath"'; var testMoxie = function(options){ return (options.wsType == 'moxie' || (options.data && options.data instanceof mOxie.FormData) || (options.crossDomain && $.support.cors !== false && hasXDomain != 'no' && !noxhr.test(options.dataType || ''))); }; @@ -1549,6 +1549,10 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u } }; + webshim.loader.addModule('moxie', { + src: 'moxie/js/moxie-'+ (hasFlash ? 'swf' : 'html4') + }); + if(!featureOptions.progress){ featureOptions.progress = 'onprogress'; } @@ -1560,9 +1564,6 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u if(!featureOptions.swfpath){ featureOptions.swfpath = shimMoxiePath+'flash/Moxie.min.swf'; } - if(!featureOptions.xappath){ - featureOptions.xappath = shimMoxiePath+'silverlight/Moxie.min.xap'; - } if($.support.cors !== false || !window.XDomainRequest){ delete transports.xdomain; @@ -1589,8 +1590,8 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u writeable: false, get: function(){ if(this.type != 'file'){return null;} - if(!$(this).hasClass('ws-filereader')){ - webshim.info("please add the 'ws-filereader' class to your input[type='file'] to implement files-property"); + if(!$(this).is('.ws-filereader, .ws-capture')){ + webshim.info("please add the 'ws-filereader'/'ws-capture' class to your input[type='file'] to implement files-property"); } return webshim.data(this, 'fileList') || []; } @@ -1612,11 +1613,66 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u }); webshim.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){ - if(value === '' && this.type == 'file' && $(this).hasClass('ws-filereader')){ + if(value === '' && this.type == 'file' && $(this).is('.ws-filereader, .ws-capture')){ webshim.data(this, 'fileList', []); } }); + if(!document.createElement('canvas').toBlob){ + + webshim.defineNodeNameProperty('canvas', 'toBlob', { + prop: { + value: function(cb, type, qualitiy){ + var dataURL; + var $canvas = $(this); + if(!type){ + type = 'image/jpeg'; + } + if(type == 'image/jpeg' && !qualitiy){ + qualitiy = 0.8; + } + loadMoxie(); + setTimeout(function(){ + dataURL = $canvas.callProp('getAsDataURL', [type, qualitiy]); + webshim.ready('moxie', function(){ + var img = new mOxie.Image(); + + img.onload = function() { + var blob = img.getAsBlob(); + webshim.defineProperty(blob, '_wsDataURL', { + value: dataURL, + enumerable: false + }); + cb(blob); + }; + img.load(dataURL); + }); + }, 9); + } + } + }); + + webshim.ready('url', function(){ + var _nativeCreateObjectURL = URL.createObjectURL; + var _nativeRevokeObjectURL = URL.revokeObjectURL; + + URL.createObjectURL = function(obj){ + var url = obj; + if(obj._wsimgDataURL) { + url = obj._wsimgDataURL; + } else if(_nativeCreateObjectURL){ + return _nativeCreateObjectURL.apply(this, arguments); + } + return url; + }; + + URL.revokeObjectURL = function(url){ + if (_nativeRevokeObjectURL){ + return _nativeRevokeObjectURL.apply(this, arguments); + } + }; + }); + } window.FileReader = notReadyYet; window.FormData = notReadyYet; @@ -1626,7 +1682,6 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u mOxie = window.mOxie; mOxie.Env.swf_url = featureOptions.swfpath; - mOxie.Env.xap_url = featureOptions.xappath; window.FileReader = mOxie.FileReader; @@ -1665,7 +1720,6 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u return moxieData; }; - FormData = window.FormData; createFilePicker = _createFilePicker; transports.moxie = createMoxieTransport; diff --git a/public/webshims/shims/combos/28.js b/public/webshims/shims/combos/28.js index de2b950b..8c626b0a 100644 --- a/public/webshims/shims/combos/28.js +++ b/public/webshims/shims/combos/28.js @@ -97,7 +97,6 @@ var isPlaceholderOptionSelected = function(select){ }; var emptyJ = $([]); -//TODO: cache + perftest var getGroupElements = function(elem){ elem = $(elem); var name, form; @@ -167,7 +166,7 @@ var validityRules = { $.each({tooShort: ['minLength', -1], tooLong: ['maxLength', 1]}, function(name, props){ validityRules[name] = function(input, val, cache){ //defaultValue is not the same as dirty flag, but very similiar - if(cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;} + if(!val || cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;} cacheType(cache, input[0]); diff --git a/public/webshims/shims/combos/3.js b/public/webshims/shims/combos/3.js index 86f4f3c9..adfb33d3 100644 --- a/public/webshims/shims/combos/3.js +++ b/public/webshims/shims/combos/3.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1532,20 +1532,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } diff --git a/public/webshims/shims/combos/30.js b/public/webshims/shims/combos/30.js index c286f446..eac80544 100644 --- a/public/webshims/shims/combos/30.js +++ b/public/webshims/shims/combos/30.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1532,20 +1532,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } diff --git a/public/webshims/shims/combos/31.js b/public/webshims/shims/combos/31.js index 2e084432..63d04c5f 100644 --- a/public/webshims/shims/combos/31.js +++ b/public/webshims/shims/combos/31.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1532,20 +1532,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } diff --git a/public/webshims/shims/combos/34.js b/public/webshims/shims/combos/34.js index bedbe63e..879cc92e 100644 --- a/public/webshims/shims/combos/34.js +++ b/public/webshims/shims/combos/34.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1297,8 +1297,12 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine var lastCue = this.cues[this.cues.length-1]; if(lastCue && lastCue.startTime > cue.startTime){ webshims.error("cue startTime higher than previous cue's startTime"); + return; } } + if(cue.startTime >= cue.endTime ){ + webshim.error('startTime >= endTime of cue: '+ cue.text); + } if(cue.track && cue.track.removeCue){ cue.track.removeCue(cue); } @@ -1390,6 +1394,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine for(i = 0, len = added.length; i < len; i++){ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: added[i]})); } + //todo: remove if(baseData.scriptedTextTracks || removed.length){ $(this).triggerHandler('updatetrackdisplay'); } @@ -1406,7 +1411,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine setTimeout(function(){ $(track).closest('audio, video').triggerHandler('updatetrackdisplay'); trackData.isTriggering = false; - }, 1); + }, 9); } }; var isDefaultTrack = (function(){ @@ -1599,15 +1604,10 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine error: error }); }; - if($.ajax && $.ajaxSettings.xhr){ - if(isDisabled){ - setTimeout(createAjax, loadingTracks * 2); - } else { - createAjax(); - } + if(isDisabled){ + setTimeout(createAjax, loadingTracks * 2); } else { - webshims.ready('jajax', createAjax); - webshims.loader.loadList(['jajax']); + createAjax(); } } catch(er){ error(); diff --git a/public/webshims/shims/combos/4.js b/public/webshims/shims/combos/4.js index 785741a4..a71f92e4 100644 --- a/public/webshims/shims/combos/4.js +++ b/public/webshims/shims/combos/4.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ diff --git a/public/webshims/shims/combos/5.js b/public/webshims/shims/combos/5.js index 09538282..c95d3972 100644 --- a/public/webshims/shims/combos/5.js +++ b/public/webshims/shims/combos/5.js @@ -2641,7 +2641,8 @@ webshims.register('form-native-extend', function($, webshims, window, doc, undef (function(){ var picker = {}; - var assumeVirtualKeyBoard = (window.Modernizr && (Modernizr.touchevents || Modernizr.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); + var modern = window.Modernizr; + var assumeVirtualKeyBoard = (modern && (modern.touchevents || modern.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); webshims.inlinePopover = { _create: function(){ this.element = $('
').data('wspopover', this); diff --git a/public/webshims/shims/combos/6.js b/public/webshims/shims/combos/6.js index db0ae019..a9f8bbba 100644 --- a/public/webshims/shims/combos/6.js +++ b/public/webshims/shims/combos/6.js @@ -2641,7 +2641,8 @@ webshims.register('form-native-extend', function($, webshims, window, doc, undef (function(){ var picker = {}; - var assumeVirtualKeyBoard = (window.Modernizr && (Modernizr.touchevents || Modernizr.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); + var modern = window.Modernizr; + var assumeVirtualKeyBoard = (modern && (modern.touchevents || modern.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); webshims.inlinePopover = { _create: function(){ this.element = $('
').data('wspopover', this); diff --git a/public/webshims/shims/combos/7.js b/public/webshims/shims/combos/7.js index b128ff2c..e70a5838 100644 --- a/public/webshims/shims/combos/7.js +++ b/public/webshims/shims/combos/7.js @@ -287,11 +287,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -904,33 +900,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1755,20 +1755,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } @@ -2446,9 +2432,16 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -2544,7 +2537,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -2730,6 +2725,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -2894,6 +2890,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -2916,6 +2913,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); diff --git a/public/webshims/shims/combos/8.js b/public/webshims/shims/combos/8.js index 820250d8..2c5ee658 100644 --- a/public/webshims/shims/combos/8.js +++ b/public/webshims/shims/combos/8.js @@ -287,11 +287,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -904,33 +900,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -1755,20 +1755,6 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } @@ -2149,9 +2135,16 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -2247,7 +2240,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -2433,6 +2428,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -2597,6 +2593,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -2619,6 +2616,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); diff --git a/public/webshims/shims/combos/9.js b/public/webshims/shims/combos/9.js index 342012d7..076397dd 100644 --- a/public/webshims/shims/combos/9.js +++ b/public/webshims/shims/combos/9.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ @@ -3045,7 +3045,8 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine (function(){ var picker = {}; - var assumeVirtualKeyBoard = (window.Modernizr && (Modernizr.touchevents || Modernizr.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); + var modern = window.Modernizr; + var assumeVirtualKeyBoard = (modern && (modern.touchevents || modern.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); webshims.inlinePopover = { _create: function(){ this.element = $('
').data('wspopover', this); diff --git a/public/webshims/shims/combos/98.js b/public/webshims/shims/combos/98.js index 96b97139..a6524844 100644 --- a/public/webshims/shims/combos/98.js +++ b/public/webshims/shims/combos/98.js @@ -475,7 +475,8 @@ webshims.register('jmebase', function($, webshims, window, doc, undefined){ })(); var ios = /iP(hone|od|ad)/i.test(navigator.platform); var ios6 = ios && parseInt(((navigator.appVersion).match(/OS (\d+)_\d+/) || ['','8'])[1], 10) < 7; - var hasYtBug = (!window.Modernizr || !Modernizr.videoautoplay) && (ios || /android/i.test(navigator.userAgent)); + var modern = window.Modernizr; + var hasYtBug = (!modern || !modern.videoautoplay) && (ios || /android/i.test(navigator.userAgent)); var loadLazy = function(){ if(!loadLazy.loaded){ loadLazy.loaded = true; @@ -596,7 +597,8 @@ webshims.register('jmebase', function($, webshims, window, doc, undefined){ if(!e){ e.type = 'playing'; } - if(isInitial && (!isYt || !hasYtBug || e.type == 'playing' || data.media.prop('readyState') > 1)){ + + if(isInitial && (!isYt || !hasYtBug || e.type == 'playing' || data.media.prop('readyState') || data.media.prop('networkState'))){ isInitial = false; data.player.removeClass('initial-state'); } diff --git a/public/webshims/shims/combos/99.js b/public/webshims/shims/combos/99.js index dd0a805d..40bcc07a 100644 --- a/public/webshims/shims/combos/99.js +++ b/public/webshims/shims/combos/99.js @@ -475,7 +475,8 @@ webshims.register('jmebase', function($, webshims, window, doc, undefined){ })(); var ios = /iP(hone|od|ad)/i.test(navigator.platform); var ios6 = ios && parseInt(((navigator.appVersion).match(/OS (\d+)_\d+/) || ['','8'])[1], 10) < 7; - var hasYtBug = (!window.Modernizr || !Modernizr.videoautoplay) && (ios || /android/i.test(navigator.userAgent)); + var modern = window.Modernizr; + var hasYtBug = (!modern || !modern.videoautoplay) && (ios || /android/i.test(navigator.userAgent)); var loadLazy = function(){ if(!loadLazy.loaded){ loadLazy.loaded = true; @@ -596,7 +597,8 @@ webshims.register('jmebase', function($, webshims, window, doc, undefined){ if(!e){ e.type = 'playing'; } - if(isInitial && (!isYt || !hasYtBug || e.type == 'playing' || data.media.prop('readyState') > 1)){ + + if(isInitial && (!isYt || !hasYtBug || e.type == 'playing' || data.media.prop('readyState') || data.media.prop('networkState'))){ isInitial = false; data.player.removeClass('initial-state'); } diff --git a/public/webshims/shims/dom-extend.js b/public/webshims/shims/dom-extend.js index 83594f13..bb800076 100644 --- a/public/webshims/shims/dom-extend.js +++ b/public/webshims/shims/dom-extend.js @@ -64,11 +64,7 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine webshims.assumeARIA = true; if($('').attr('type') == 'text' || $('').attr('novalidate') === "" || ('required' in $('')[0].attributes)){ - webshims.error("IE browser modes are busted in IE10+. Please test your HTML/CSS/JS with a real IE version or at least IETester or similiar tools"); - } - - if('debug' in webshims){ - webshims.error('Use webshims.setOptions("debug", true||false||"noCombo"); to debug flag'); + webshims.error("IE browser modes are busted in IE10+. Make sure to run IE in edge mode (X-UA-Compatible). Please test your HTML/CSS/JS with a real IE version or at least IETester or similar tools. "); } if (!webshims.cfg.no$Switch) { @@ -681,33 +677,37 @@ webshims.register('dom-extend', function($, webshims, window, document, undefine } }, handler: (function(){ + var evt; var trigger = function(){ - $(document).triggerHandler('updateshadowdom'); + $(document).triggerHandler('updateshadowdom', [evt]); + }; + var timed = function(){ + if(evt && evt.type == 'resize'){ + var width = $window.width(); + var height = $window.width(); + + if(height == lastHeight && width == lastWidth){ + return; + } + lastHeight = height; + lastWidth = width; + } + + if(evt && evt.type != 'docresize'){ + docObserve.height = docObserve.getHeight(); + docObserve.width = docObserve.getWidth(); + } + + if(window.requestAnimationFrame){ + requestAnimationFrame(trigger); + } else { + setTimeout(trigger, 0); + } }; return function(e){ clearTimeout(resizeTimer); - resizeTimer = setTimeout(function(){ - if(e.type == 'resize'){ - var width = $window.width(); - var height = $window.width(); - - if(height == lastHeight && width == lastWidth){ - return; - } - lastHeight = height; - lastWidth = width; - - docObserve.height = docObserve.getHeight(); - docObserve.width = docObserve.getWidth(); - } - - if(window.requestAnimationFrame){ - requestAnimationFrame(trigger); - } else { - setTimeout(trigger, 0); - } - - }, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); + evt = e; + resizeTimer = setTimeout(timed, (e.type == 'resize' && !window.requestAnimationFrame) ? 50 : 9); }; })(), _create: function(){ diff --git a/public/webshims/shims/es6.js b/public/webshims/shims/es6.js index 595f0b26..63a28bbe 100755 --- a/public/webshims/shims/es6.js +++ b/public/webshims/shims/es6.js @@ -1,11 +1,13 @@ -// ES6-shim 0.8.0 (c) 2013 Paul Miller (paulmillr.com) +// ES6-shim 0.15.0 (c) 2013-2014 Paul Miller (http://paulmillr.com) // ES6-shim may be freely distributed under the MIT license. // For more details and documentation: // https://github.com/paulmillr/es6-shim/ + webshim.register('es6', function($, webshim, window, document, undefined){ 'use strict'; + var isCallableWithoutNew = function(func) { try { func(); } catch (e) { return false; } @@ -99,7 +101,7 @@ webshim.register('es6', function($, webshim, window, document, undefined){ // work properly with each other, even though we don't have full Iterator // support. That is, `Array.from(map.keys())` will work, but we don't // pretend to export a "real" Iterator interface. - var $iterator$ = (typeof Symbol === 'object' && Symbol.iterator) || + var $iterator$ = (typeof Symbol === 'function' && Symbol.iterator) || '_es6shim_iterator_'; // Firefox ships a partial implementation using the name @@iterator. // https://bugzilla.mozilla.org/show_bug.cgi?id=907077#c14 @@ -328,8 +330,8 @@ webshim.register('es6', function($, webshim, window, document, undefined){ // Bits to bytes bytes = []; while (str.length) { - bytes.push(parseInt(str.substring(0, 8), 2)); - str = str.substring(8); + bytes.push(parseInt(str.slice(0, 8), 2)); + str = str.slice(8); } return bytes; } @@ -351,9 +353,9 @@ webshim.register('es6', function($, webshim, window, document, undefined){ // Unpack sign, exponent, fraction bias = (1 << (ebits - 1)) - 1; - s = parseInt(str.substring(0, 1), 2) ? -1 : 1; - e = parseInt(str.substring(1, 1 + ebits), 2); - f = parseInt(str.substring(1 + ebits), 2); + s = parseInt(str.slice(0, 1), 2) ? -1 : 1; + e = parseInt(str.slice(1, 1 + ebits), 2); + f = parseInt(str.slice(1 + ebits), 2); // Produce number if (e === (1 << ebits) - 1) { @@ -388,7 +390,7 @@ webshim.register('es6', function($, webshim, window, document, undefined){ }()); defineProperties(String, { - fromCodePoint: function() { + fromCodePoint: function(_) { // length = 1 var points = _slice.call(arguments, 0, arguments.length); var result = []; var next; @@ -677,15 +679,17 @@ webshim.register('es6', function($, webshim, window, document, undefined){ }, fill: function(value) { - var start = arguments[1], end = arguments[2]; // fill.length===1 + var start = arguments.length > 1 ? arguments[1] : undefined; + var end = arguments.length > 2 ? arguments[2] : undefined; var O = ES.ToObject(this); var len = ES.ToLength(O.length); - start = ES.ToInteger(start===undefined ? 0 : start); - end = ES.ToInteger(end===undefined ? len : end); + start = ES.ToInteger(start === undefined ? 0 : start); + end = ES.ToInteger(end === undefined ? len : end); var relativeStart = start < 0 ? Math.max(len + start, 0) : Math.min(start, len); + var relativeEnd = end < 0 ? len + end : end; - for (var i = relativeStart; i < len && i < end; ++i) { + for (var i = relativeStart; i < len && i < relativeEnd; ++i) { O[i] = value; } return O; @@ -755,9 +759,7 @@ webshim.register('es6', function($, webshim, window, document, undefined){ }, isInteger: function(value) { - return typeof value === 'number' && - !Number.isNaN(value) && - Number.isFinite(value) && + return Number.isFinite(value) && ES.ToInteger(value) === value; }, @@ -813,20 +815,13 @@ webshim.register('es6', function($, webshim, window, document, undefined){ throw new TypeError('target must be an object'); } return Array.prototype.reduce.call(arguments, function(target, source) { - if (!ES.TypeIsObject(source)) { - throw new TypeError('source must be an object'); - } - return Object.keys(source).reduce(function(target, key) { + return Object.keys(Object(source)).reduce(function(target, key) { target[key] = source[key]; return target; }, target); }); }, - getOwnPropertyKeys: function(subject) { - return Object.keys(subject); - }, - is: function(a, b) { return ES.SameValue(a, b); }, @@ -955,7 +950,6 @@ webshim.register('es6', function($, webshim, window, document, undefined){ clz32: function(value) { // See https://bugs.ecmascript.org/show_bug.cgi?id=2465 value = Number(value); - if (Number.isNaN(value)) return NaN; var number = ES.ToUint32(value); if (number === 0) { return 32; @@ -1064,6 +1058,8 @@ webshim.register('es6', function($, webshim, window, document, undefined){ imul: function(x, y) { // taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + x = ES.ToUint32(x); + y = ES.ToUint32(y); var ah = (x >>> 16) & 0xffff; var al = x & 0xffff; var bh = (y >>> 16) & 0xffff; @@ -1523,7 +1519,7 @@ webshim.register('es6', function($, webshim, window, document, undefined){ }; addIterator(MapIterator.prototype); - function Map() { + function Map(iterable) { var map = this; map = emulateES6construct(map); if (!map._es6map) { @@ -1541,7 +1537,6 @@ webshim.register('es6', function($, webshim, window, document, undefined){ }); // Optionally initialize map from iterable - var iterable = arguments[0]; if (iterable !== undefined && iterable !== null) { var it = ES.GetIterator(iterable); var adder = map.set; @@ -1709,7 +1704,7 @@ webshim.register('es6', function($, webshim, window, document, undefined){ // Sets containing only string or numeric keys, we use an object // as backing storage and lazily create a full Map only when // required. - var SetShim = function Set() { + var SetShim = function Set(iterable) { var set = this; set = emulateES6construct(set); if (!set._es6set) { @@ -1722,7 +1717,6 @@ webshim.register('es6', function($, webshim, window, document, undefined){ }); // Optionally initialize map from iterable - var iterable = arguments[0]; if (iterable !== undefined && iterable !== null) { var it = ES.GetIterator(iterable); var adder = set.add; @@ -1754,7 +1748,7 @@ webshim.register('es6', function($, webshim, window, document, undefined){ Object.keys(set._storage).forEach(function(k) { // fast check for leading '$' if (k.charCodeAt(0) === 36) { - k = k.substring(1); + k = k.slice(1); } else { k = +k; } diff --git a/public/webshims/shims/filereader.js b/public/webshims/shims/filereader-xhr.js similarity index 86% rename from public/webshims/shims/filereader.js rename to public/webshims/shims/filereader-xhr.js index 98f8f6f8..b2f7f2d2 100644 --- a/public/webshims/shims/filereader.js +++ b/public/webshims/shims/filereader-xhr.js @@ -1,8 +1,8 @@ -webshim.register('filereader', function($, webshim, window, document, undefined, featureOptions){ +webshim.register('filereader-xhr', function($, webshim, window, document, undefined, featureOptions){ "use strict"; var mOxie, moxie, hasXDomain; - var FormData = $.noop; - var sel = 'input[type="file"].ws-filereader'; + var sel = 'input[type="file"].ws-filereader, input[type="file"].ws-capture'; + var hasFlash = swfmini.hasFlashPlayerVersion('10.3'); var loadMoxie = function (){ webshim.loader.loadList(['moxie']); }; @@ -114,7 +114,7 @@ webshim.register('filereader', function($, webshim, window, document, undefined, } ); var shimMoxiePath = webshim.cfg.basePath+'moxie/'; - var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf/moxie.xap on your server an configure filereader options: "swfpath"/"xappath"'; + var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf on your server an configure filereader options: "swfpath"'; var testMoxie = function(options){ return (options.wsType == 'moxie' || (options.data && options.data instanceof mOxie.FormData) || (options.crossDomain && $.support.cors !== false && hasXDomain != 'no' && !noxhr.test(options.dataType || ''))); }; @@ -297,6 +297,10 @@ webshim.register('filereader', function($, webshim, window, document, undefined, } }; + webshim.loader.addModule('moxie', { + src: 'moxie/js/moxie-'+ (hasFlash ? 'swf' : 'html4') + }); + if(!featureOptions.progress){ featureOptions.progress = 'onprogress'; } @@ -308,9 +312,6 @@ webshim.register('filereader', function($, webshim, window, document, undefined, if(!featureOptions.swfpath){ featureOptions.swfpath = shimMoxiePath+'flash/Moxie.min.swf'; } - if(!featureOptions.xappath){ - featureOptions.xappath = shimMoxiePath+'silverlight/Moxie.min.xap'; - } if($.support.cors !== false || !window.XDomainRequest){ delete transports.xdomain; @@ -337,8 +338,8 @@ webshim.register('filereader', function($, webshim, window, document, undefined, writeable: false, get: function(){ if(this.type != 'file'){return null;} - if(!$(this).hasClass('ws-filereader')){ - webshim.info("please add the 'ws-filereader' class to your input[type='file'] to implement files-property"); + if(!$(this).is('.ws-filereader, .ws-capture')){ + webshim.info("please add the 'ws-filereader'/'ws-capture' class to your input[type='file'] to implement files-property"); } return webshim.data(this, 'fileList') || []; } @@ -360,11 +361,66 @@ webshim.register('filereader', function($, webshim, window, document, undefined, }); webshim.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){ - if(value === '' && this.type == 'file' && $(this).hasClass('ws-filereader')){ + if(value === '' && this.type == 'file' && $(this).is('.ws-filereader, .ws-capture')){ webshim.data(this, 'fileList', []); } }); + if(!document.createElement('canvas').toBlob){ + + webshim.defineNodeNameProperty('canvas', 'toBlob', { + prop: { + value: function(cb, type, qualitiy){ + var dataURL; + var $canvas = $(this); + if(!type){ + type = 'image/jpeg'; + } + if(type == 'image/jpeg' && !qualitiy){ + qualitiy = 0.8; + } + loadMoxie(); + setTimeout(function(){ + dataURL = $canvas.callProp('getAsDataURL', [type, qualitiy]); + webshim.ready('moxie', function(){ + var img = new mOxie.Image(); + + img.onload = function() { + var blob = img.getAsBlob(); + webshim.defineProperty(blob, '_wsDataURL', { + value: dataURL, + enumerable: false + }); + cb(blob); + }; + img.load(dataURL); + }); + }, 9); + } + } + }); + + webshim.ready('url', function(){ + var _nativeCreateObjectURL = URL.createObjectURL; + var _nativeRevokeObjectURL = URL.revokeObjectURL; + + URL.createObjectURL = function(obj){ + var url = obj; + if(obj._wsimgDataURL) { + url = obj._wsimgDataURL; + } else if(_nativeCreateObjectURL){ + return _nativeCreateObjectURL.apply(this, arguments); + } + return url; + }; + + URL.revokeObjectURL = function(url){ + if (_nativeRevokeObjectURL){ + return _nativeRevokeObjectURL.apply(this, arguments); + } + }; + }); + } window.FileReader = notReadyYet; window.FormData = notReadyYet; @@ -374,7 +430,6 @@ webshim.register('filereader', function($, webshim, window, document, undefined, mOxie = window.mOxie; mOxie.Env.swf_url = featureOptions.swfpath; - mOxie.Env.xap_url = featureOptions.xappath; window.FileReader = mOxie.FileReader; @@ -413,7 +468,6 @@ webshim.register('filereader', function($, webshim, window, document, undefined, return moxieData; }; - FormData = window.FormData; createFilePicker = _createFilePicker; transports.moxie = createMoxieTransport; diff --git a/public/webshims/shims/form-core.js b/public/webshims/shims/form-core.js index 5e5d824b..430ae199 100644 --- a/public/webshims/shims/form-core.js +++ b/public/webshims/shims/form-core.js @@ -301,20 +301,6 @@ webshims.register('form-core', function($, webshims, window, document, undefined } }); - $(function(){ - var fileReaderReady = ('FileReader' in window && 'FormData' in window); - if(!fileReaderReady){ - webshims.addReady(function(context){ - if(!fileReaderReady && !modules.filereader.loaded && !modules.moxie.loaded){ - if(context.querySelector('input.ws-filereader')){ - webshims.reTest(['filereader', 'moxie']); - fileReaderReady = true; - } - } - }); - } - }); - if(options.addValidators && options.fastValidators){ webshims.reTest(['form-validators', 'form-validation']); } diff --git a/public/webshims/shims/form-number-date-ui.js b/public/webshims/shims/form-number-date-ui.js index 8bd8941e..fd736828 100644 --- a/public/webshims/shims/form-number-date-ui.js +++ b/public/webshims/shims/form-number-date-ui.js @@ -1194,7 +1194,8 @@ webshims.register('form-number-date-ui', function($, webshims, window, document, (function(){ var picker = {}; - var assumeVirtualKeyBoard = (window.Modernizr && (Modernizr.touchevents || Modernizr.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); + var modern = window.Modernizr; + var assumeVirtualKeyBoard = (modern && (modern.touchevents || modern.touch)) || (/android|iphone|ipad|ipod|blackberry|iemobile/i.test(navigator.userAgent.toLowerCase())); webshims.inlinePopover = { _create: function(){ this.element = $('
').data('wspopover', this); diff --git a/public/webshims/shims/form-shim-extend.js b/public/webshims/shims/form-shim-extend.js index c2e72c07..b73c4ec8 100644 --- a/public/webshims/shims/form-shim-extend.js +++ b/public/webshims/shims/form-shim-extend.js @@ -97,7 +97,6 @@ var isPlaceholderOptionSelected = function(select){ }; var emptyJ = $([]); -//TODO: cache + perftest var getGroupElements = function(elem){ elem = $(elem); var name, form; @@ -167,7 +166,7 @@ var validityRules = { $.each({tooShort: ['minLength', -1], tooLong: ['maxLength', 1]}, function(name, props){ validityRules[name] = function(input, val, cache){ //defaultValue is not the same as dirty flag, but very similiar - if(cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;} + if(!val || cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;} cacheType(cache, input[0]); diff --git a/public/webshims/shims/form-validation.js b/public/webshims/shims/form-validation.js index 279601eb..abe904e4 100644 --- a/public/webshims/shims/form-validation.js +++ b/public/webshims/shims/form-validation.js @@ -32,7 +32,8 @@ webshims.register('form-validation', function($, webshims, window, document, und var nonFormFilter = function(){ return !$.prop(this, 'form'); }; - var getGroupElements = webshims.modules["form-core"].getGroupElements || function(elem){ + var modules = webshims.modules; + var getGroupElements = modules["form-core"].getGroupElements || function(elem){ elem = $(elem); var name; var form; @@ -207,8 +208,8 @@ webshims.register('form-validation', function($, webshims, window, document, und iVal.fieldWrapper = ':not(span):not(label):not(em):not(strong):not(p):not(.ws-custom-file)'; } - if(!webshims.modules["form-core"].getGroupElements){ - webshims.modules["form-core"].getGroupElements = getGroupElements; + if(!modules["form-core"].getGroupElements){ + modules["form-core"].getGroupElements = getGroupElements; } $(document.body || 'html') @@ -364,7 +365,7 @@ webshims.register('form-validation', function($, webshims, window, document, und this._shadowAdded = true; } - element = $(element || this.options.prepareFor).getNativeElement() ; + element = $(element || this.options.prepareFor).getNativeElement(); var that = this; var closeOnOutSide = function(e){ @@ -971,7 +972,7 @@ webshims.register('form-validation', function($, webshims, window, document, und $.data(this, 'wsCustomFile', {showSelected: showSelected}); - $('button', $module).attr('tabindex', '-1'); + $('button:not(.ws-capture-button)', $module).attr('tabindex', '-1'); $file .on('change.webshim', showSelected) @@ -993,6 +994,18 @@ webshims.register('form-validation', function($, webshims, window, document, und } + $(function(){ + var fileReaderReady = ('FileReader' in window && 'FormData' in window); + if(!fileReaderReady){ + webshims.addReady(function(context){ + if(!fileReaderReady && !modules.filereader.loaded && context.querySelector('input.ws-filereader')){ + webshims.reTest(['filereader']); + fileReaderReady = true; + } + }); + } + }); + webshims.addReady(function(context, contextElem){ $(context.querySelectorAll('.ws-custom-file')).add($(contextElem).filter('.ws-custom-file')).each(customFile); }); diff --git a/public/webshims/shims/form-validators.js b/public/webshims/shims/form-validators.js index 54d5dc66..484c0389 100644 --- a/public/webshims/shims/form-validators.js +++ b/public/webshims/shims/form-validators.js @@ -261,8 +261,8 @@ webshims.ready('form-validation', function(){ if(!val || !pattern){return;} return !(new RegExp('(' + pattern + ')', 'i').test(val)); }, 'This format is not allowed here.'); - - if(!('tooShort' in ($('').prop('validity') || {}))){ + + if($('').prop('minLength') === undefined || !('tooShort' in ($('').prop('validity') || {}))){ addCustomValidityRule('tooShort', function(elem, val){ var minlength; if(!val || val == elem.defaultValue || !(minlength = elem.getAttribute('minlength'))){return;} @@ -281,9 +281,12 @@ webshims.ready('form-validation', function(){ data.grouprequired.checkboxes .off('click.groupRequired') .on('click.groupRequired', function(){ - webshims.refreshCustomValidityRules(elem); + if((data.customMismatchedRule == 'grouprequired') == this.checked){ + $(elem).trigger('updatevalidation.webshims'); + } }) ; + data.grouprequired.checkboxes.not(elem).removeData('grouprequired'); } @@ -332,14 +335,14 @@ webshims.ready('form-validation', function(){ addCustomValidityRule('dependent', function(elem, val, data){ data = data.dependentValidation; if( !data ){return;} - var specialVal; var depFn = function(e){ var val = $.prop(data.masterElement, data["from-prop"]); - if(specialVal){ - val = $.inArray(val, specialVal) !== -1; - } - if(data.toggle){ + if(data.specialVal){ + val = $.inArray(val, data.specialVal) !== -1; + } if(data.toggle){ val = !val; + } else { + val = !!val; } $.prop( elem, data.prop, val); if(iValClasses && e){ @@ -370,14 +373,13 @@ webshims.ready('form-validation', function(){ } if(data["from-prop"].indexOf('value:') === 0){ - specialVal = data["from-prop"].replace('value:', '').split('||'); + data.specialVal = data["from-prop"].replace('value:', '').split('||'); data["from-prop"] = 'value'; - } - + data = $.data(elem, 'dependentValidation', $.extend({_init: true}, dependentDefaults, data)); - if(data.prop !== "value" || specialVal){ + if(data.prop !== "value" || data.specialVal){ $(data.masterElement.type === 'radio' && getGroupElements(data.masterElement) || data.masterElement).on('change', depFn); } else { $(data.masterElement).on('change', function(){ @@ -393,7 +395,7 @@ webshims.ready('form-validation', function(){ } } - if(data.prop == "value" && !specialVal){ + if(data.prop == "value" && !data.specialVal){ return ($.prop(data.masterElement, 'value') != val); } else { depFn(); @@ -412,7 +414,6 @@ webshims.ready('form-validation', function(){ if(!val || !data.ajaxvalidate){return;} var opts; if(!data.remoteValidate){ - webshims.loader.loadList(['jajax']); if(typeof data.ajaxvalidate == 'string'){ data.ajaxvalidate = {url: data.ajaxvalidate, depends: $([])}; } else { diff --git a/public/webshims/shims/geolocation.js b/public/webshims/shims/geolocation.js index eae3ed35..c873ff0d 100644 --- a/public/webshims/shims/geolocation.js +++ b/public/webshims/shims/geolocation.js @@ -92,52 +92,46 @@ } return; } - createAjax = function(){ - $.ajax({ - url: 'http://freegeoip.net/json/', - dataType: 'jsonp', - cache: true, - jsonp: 'callback', - success: function(data){ - locationAPIs--; - if(!data){return;} - pos = pos || { - coords: { - latitude: data.latitude, - longitude: data.longitude, - altitude: null, - accuracy: 43000, - altitudeAccuracy: null, - heading: parseInt('NaN', 10), - velocity: null - }, - //extension similiar to FF implementation - address: { - city: data.city, - country: data.country_name, - countryCode: data.country_code, - county: "", - postalCode: data.zipcode, - premises: "", - region: data.region_name, - street: "", - streetNumber: "" - } - }; - endCallback(); - }, - error: function(){ - locationAPIs--; - endCallback(); - } - }); - }; - if($.ajax){ - createAjax(); - } else { - webshims.ready('jajax', createAjax); - webshims.loader.loadList(['jajax']); - } + + $.ajax({ + url: 'http://freegeoip.net/json/', + dataType: 'jsonp', + cache: true, + jsonp: 'callback', + success: function(data){ + locationAPIs--; + if(!data){return;} + pos = pos || { + coords: { + latitude: data.latitude, + longitude: data.longitude, + altitude: null, + accuracy: 43000, + altitudeAccuracy: null, + heading: parseInt('NaN', 10), + velocity: null + }, + //extension similiar to FF implementation + address: { + city: data.city, + country: data.country_name, + countryCode: data.country_code, + county: "", + postalCode: data.zipcode, + premises: "", + region: data.region_name, + street: "", + streetNumber: "" + } + }; + endCallback(); + }, + error: function(){ + locationAPIs--; + endCallback(); + } + }); + clearTimeout(googleTimer); if (!window.google || !window.google.loader) { googleTimer = setTimeout(function(){ @@ -179,9 +173,6 @@ }; return api; })()); - - webshims.ready('WINDOWLOAD', function(){ - webshims.loader.loadList(['jajax']); - }); + webshims.isReady('geolocation', true); })(webshims.$); diff --git a/public/webshims/shims/jajax.js b/public/webshims/shims/jajax.js deleted file mode 100644 index 2204011a..00000000 --- a/public/webshims/shims/jajax.js +++ /dev/null @@ -1,1262 +0,0 @@ -(function(){ - var jQuery = window.webshims && webshims.$ || window.jQuery; - - var rnotwhite = (/\S+/g); - var nonce = jQuery.now(); - var rquery = (/\?/); - var init = jQuery.fn.init; - - jQuery.parseJSON = function( data ) { - return window.JSON.parse( data + "" ); - }; - - // Cross-browser xml parsing - jQuery.parseXML = function( data ) { - var xml, tmp; - if ( !data || typeof data !== "string" ) { - return null; - } - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data, "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; - }; - - (function(){ - var - // Document location - ajaxLocParts, - ajaxLocation, - - rhash = /#.*$/, - rts = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat("*"); - -// #8138, IE may throw an exception when accessing -// a field from window.location if document.domain has been set - try { - ajaxLocation = location.href; - } catch( e ) { - // Use the href attribute of an A element - // since IE will modify it given document.location - ajaxLocation = document.createElement( "a" ); - ajaxLocation.href = ""; - ajaxLocation = ajaxLocation.href; - } - -// Segment location into parts - ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport - function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; - - if ( jQuery.isFunction( func ) ) { - // For each dataType in the dataTypeExpression - while ( (dataType = dataTypes[i++]) ) { - // Prepend if requested - if ( dataType.charAt( 0 ) === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); - - // Otherwise append - } else { - (structure[ dataType ] = structure[ dataType ] || []).push( func ); - } - } - } - }; - } - -// Base inspection function for prefilters and transports - function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - }); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); - } - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 - function ajaxExtend( target, src ) { - var deep, key, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; - } - - /* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ - function ajaxHandleResponses( s, jqXHR, responses ) { - var firstDataType, ct, finalDataType, type, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } - } - - /* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ - function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s[ "throws" ] ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; - } - } - } - } - } - } - - return { state: "success", data: response }; - } - - jQuery.extend({ - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: ajaxLocation, - type: "GET", - isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /xml/, - html: /html/, - json: /json/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": jQuery.parseJSON, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var // Cross-domain detection vars - parts, - // Loop variable - i, - // URL without anti-cache param - cacheURL, - // Response headers as string - responseHeadersString, - // timeout handle - timeoutTimer, - - // To know if global events are to be dispatched - fireGlobals, - - transport, - // Response headers - responseHeaders, - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - // Callbacks context - callbackContext = s.context || s, - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks("once memory"), - // Status-dependent callbacks - statusCode = s.statusCode || {}, - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - // The jqXHR state - state = 0, - // Default abort message - strAbort = "canceled", - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( state === 2 ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( (match = rheaders.exec( responseHeadersString )) ) { - responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match == null ? null : match; - }, - - // Raw string - getAllResponseHeaders: function() { - return state === 2 ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - var lname = name.toLowerCase(); - if ( !state ) { - name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( !state ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( state < 2 ) { - for ( code in map ) { - // Lazy-add the new callback in a way that preserves old ones - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } else { - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ).complete = completeDeferred.add; - jqXHR.success = jqXHR.done; - jqXHR.error = jqXHR.fail; - - // Remove hash character (#7531: and string promotion) - // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; - - // A cross-domain request is in order when we have a protocol:host:port mismatch - if ( s.crossDomain == null ) { - parts = rurl.exec( s.url.toLowerCase() ); - s.crossDomain = !!( parts && - ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || - ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== - ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) - ); - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( state === 2 ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - fireGlobals = s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger("ajaxStart"); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - cacheURL = s.url; - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // If data is available, append data to url - if ( s.data ) { - cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add anti-cache in url if needed - if ( s.cache === false ) { - s.url = rts.test( cacheURL ) ? - - // If there is already a '_' parameter, set its value - cacheURL.replace( rts, "$1_=" + nonce++ ) : - - // Otherwise add one to the end - cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; - } - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? - s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { - // Abort if not done already and return - return jqXHR.abort(); - } - - // aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - for ( i in { success: 1, error: 1, complete: 1 } ) { - jqXHR[ i ]( s[ i ] ); - } - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = setTimeout(function() { - jqXHR.abort("timeout"); - }, s.timeout ); - } - - try { - state = 1; - transport.send( requestHeaders, done ); - } catch ( e ) { - // Propagate exception as error if not done - if ( state < 2 ) { - done( -1, e ); - // Simply rethrow otherwise - } else { - throw e; - } - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Called once - if ( state === 2 ) { - return; - } - - // State is "done" now - state = 2; - - // Clear timeout if it exists - if ( timeoutTimer ) { - clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader("Last-Modified"); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader("etag"); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - // We extract error from statusText - // then normalize statusText and status for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger("ajaxStop"); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } - }); - - jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - // shift arguments if data argument was omitted - if ( jQuery.isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - return jQuery.ajax({ - url: url, - type: method, - dataType: type, - data: data, - success: callback - }); - }; - }); - -// Attach a bunch of functions for handling common AJAX events - jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { - jQuery.fn[ type ] = function( fn ) { - return this.on( type, fn ); - }; - }); - })(); - - - (function(){ - var oldCallbacks = [], - rjsonp = /(=)\?(?=&|$)|\?\?/; - -// Default jsonp settings - jQuery.ajaxSetup({ - jsonp: "callback", - jsonpCallback: function() { - var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); - this[ callback ] = true; - return callback; - } - }); - -// Detect, normalize options and install callbacks for jsonp requests - jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { - - var callbackName, overwritten, responseContainer, - jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? - "url" : - typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" - ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? - s.jsonpCallback() : - s.jsonpCallback; - - // Insert callback into url or form data - if ( jsonProp ) { - s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); - } else if ( s.jsonp !== false ) { - s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters["script json"] = function() { - if ( !responseContainer ) { - jQuery.error( callbackName + " was not called" ); - } - return responseContainer[ 0 ]; - }; - - // force json dataType - s.dataTypes[ 0 ] = "json"; - - // Install callback - overwritten = window[ callbackName ]; - window[ callbackName ] = function() { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always(function() { - // Restore preexisting value - window[ callbackName ] = overwritten; - - // Save back as free - if ( s[ callbackName ] ) { - // make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // save the callback name for future use - oldCallbacks.push( callbackName ); - } - - // Call if it was a function and we have a response - if ( responseContainer && jQuery.isFunction( overwritten ) ) { - overwritten( responseContainer[ 0 ] ); - } - - responseContainer = overwritten = undefined; - }); - - // Delegate to script - return "script"; - } - }); - })(); - - (function(){ - // Keep a copy of the old load method - var _load = jQuery.fn.load; - - /** - * Load a url into a page - */ - jQuery.fn.load = function( url, params, callback ) { - if ( typeof url !== "string" && _load ) { - return _load.apply( this, arguments ); - } - - var selector, response, type, - self = this, - off = url.indexOf(" "); - - if ( off >= 0 ) { - selector = url.slice( off, url.length ); - url = url.slice( 0, off ); - } - - // If it's a function - if ( jQuery.isFunction( params ) ) { - - // We assume that it's the callback - callback = params; - params = undefined; - - // Otherwise, build a param string - } else if ( params && typeof params === "object" ) { - type = "POST"; - } - - // If we have elements to modify, make the request - if ( self.length > 0 ) { - jQuery.ajax({ - url: url, - - // if "type" variable is undefined, then "GET" method will be used - type: type, - dataType: "html", - data: params - }).done(function( responseText ) { - - // Save response for use in complete callback - response = arguments; - - self.html( selector ? - - // If a selector was specified, locate the right elements in a dummy div - // Exclude scripts to avoid IE 'Permission Denied' errors - jQuery("
").append( jQuery.parseHTML( responseText ) ).find( selector ) : - - // Otherwise use the full result - responseText ); - - }).complete( callback && function( jqXHR, status ) { - self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); - }); - } - - return this; - }; - - })(); - (function(){ -// Install script dataType - jQuery.ajaxSetup({ - accepts: { - script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /(?:java|ecma)script/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } - }); - -// Handle cache's special case and global - jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - s.global = false; - } - }); - -// Bind script tag hack transport - jQuery.ajaxTransport( "script", function(s) { - - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - - var script, - head = document.head || jQuery("head")[0] || document.documentElement; - - return { - - send: function( _, callback ) { - - script = document.createElement("script"); - - script.async = true; - - if ( s.scriptCharset ) { - script.charset = s.scriptCharset; - } - - script.src = s.url; - - // Attach handlers for all browsers - script.onload = script.onreadystatechange = function( _, isAbort ) { - - if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { - - // Handle memory leak in IE - script.onload = script.onreadystatechange = null; - - // Remove the script - if ( script.parentNode ) { - script.parentNode.removeChild( script ); - } - - // Dereference the script - script = null; - - // Callback if not abort - if ( !isAbort ) { - callback( 200, "success" ); - } - } - }; - - // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending - // Use native DOM manipulation to avoid our domManip AJAX trickery - head.insertBefore( script, head.firstChild ); - }, - - abort: function() { - if ( script ) { - script.onload( undefined, true ); - } - } - }; - } - }); - })(); - (function(){ - var support = jQuery.support; -// Create the request object -// (This is still attached to ajaxSettings for backward compatibility) - jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ? - // Support: IE6+ - function() { - - // XHR cannot access local files, always use ActiveX for that case - return !this.isLocal && - - // Support: IE7-8 - // oldIE XHR does not support non-RFC2616 methods (#13240) - // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx - // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9 - // Although this check for six methods instead of eight - // since IE also does not support "trace" and "connect" - /^(get|post|head|put|delete|options)$/i.test( this.type ) && - - createStandardXHR() || createActiveXHR(); - } : - // For all other browsers, use the standard XMLHttpRequest object - createStandardXHR; - - var xhrId = 0, - xhrCallbacks = {}, - xhrSupported = jQuery.ajaxSettings.xhr(); - -// Support: IE<10 -// Open requests must be manually aborted on unload (#5280) - if ( window.ActiveXObject ) { - jQuery( window ).on( "unload", function() { - for ( var key in xhrCallbacks ) { - xhrCallbacks[ key ]( undefined, true ); - } - }); - } - -// Determine support properties - support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); - xhrSupported = support.ajax = !!xhrSupported; - -// Create transport if the browser can provide an xhr - if ( xhrSupported ) { - - jQuery.ajaxTransport(function( options ) { - // Cross domain only allowed if supported through XMLHttpRequest - if ( !options.crossDomain || support.cors ) { - - var callback; - - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(), - id = ++xhrId; - - // Open the socket - xhr.open( options.type, options.url, options.async, options.username, options.password ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers["X-Requested-With"] ) { - headers["X-Requested-With"] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - // Support: IE<9 - // IE's ActiveXObject throws a 'Type Mismatch' exception when setting - // request header to a null-value. - // - // To keep consistent with other XHR implementations, cast the value - // to string and ignore `undefined`. - if ( headers[ i ] !== undefined ) { - xhr.setRequestHeader( i, headers[ i ] + "" ); - } - } - - // Do send the request - // This may raise an exception which is actually - // handled in jQuery.ajax (so no try/catch here) - xhr.send( ( options.hasContent && options.data ) || null ); - - // Listener - callback = function( _, isAbort ) { - var status, statusText, responses; - - // Was never called and is aborted or complete - if ( callback && ( isAbort || xhr.readyState === 4 ) ) { - // Clean up - delete xhrCallbacks[ id ]; - callback = undefined; - xhr.onreadystatechange = jQuery.noop; - - // Abort manually if needed - if ( isAbort ) { - if ( xhr.readyState !== 4 ) { - xhr.abort(); - } - } else { - responses = {}; - status = xhr.status; - - // Support: IE<10 - // Accessing binary-data responseText throws an exception - // (#11426) - if ( typeof xhr.responseText === "string" ) { - responses.text = xhr.responseText; - } - - // Firefox throws an exception when accessing - // statusText for faulty cross-domain requests - try { - statusText = xhr.statusText; - } catch( e ) { - // We normalize with Webkit giving an empty statusText - statusText = ""; - } - - // Filter status for non standard behaviors - - // If the request is local and we have data: assume a success - // (success with no data won't get notified, that's the best we - // can do given current implementations) - if ( !status && options.isLocal && !options.crossDomain ) { - status = responses.text ? 200 : 404; - // IE - #1450: sometimes returns 1223 when it should be 204 - } else if ( status === 1223 ) { - status = 204; - } - } - } - - // Call complete if needed - if ( responses ) { - complete( status, statusText, responses, xhr.getAllResponseHeaders() ); - } - }; - - if ( !options.async ) { - // if we're in sync mode we fire the callback - callback(); - } else if ( xhr.readyState === 4 ) { - // (IE6 & IE7) if it's in cache and has been - // retrieved directly we need to fire the callback - setTimeout( callback ); - } else { - // Add to the list of active xhr callbacks - xhr.onreadystatechange = xhrCallbacks[ id ] = callback; - } - }, - - abort: function() { - if ( callback ) { - callback( undefined, true ); - } - } - }; - } - }); - } - -// Functions to create xhrs - function createStandardXHR() { - try { - return new window.XMLHttpRequest(); - } catch( e ) {} - } - - function createActiveXHR() { - try { - return new window.ActiveXObject( "Microsoft.XMLHTTP" ); - } catch( e ) {} - } - })(); - webshims.isReady('jajax', true); -})(); diff --git a/public/webshims/shims/jme/controls.css b/public/webshims/shims/jme/controls.css index e7a02e5a..10ece81e 100644 --- a/public/webshims/shims/jme/controls.css +++ b/public/webshims/shims/jme/controls.css @@ -1,5 +1,5 @@ /* thx to http://icomoon.io */ -.mediaplayer[data-state="waiting"] > .jme-media-overlay, .mediaplayer .fullscreen, .mediaplayer .fullscreen.state-exitfullscreen, .mediaplayer .mediaconfigmenu, .mediaplayer.initial-state > .jme-media-overlay, .mediaplayer button.play-pause, .mediaplayer button.play-pause.state-playing, .mediaplayer .mute-unmute, .mediaplayer[data-volume="medium"] .mute-unmute, .mediaplayer[data-volume="low"] .mute-unmute, .mediaplayer[data-volume="no"] .mute-unmute, .mediaplayer .state-unmute.mute-unmute, .mediaplayer .captions, .mediaplayer .subtitle-menu button[aria-checked="true"], .mediaplayer .subtitle-menu button, .mediaplayer .playlist-next, .mediaplayer .playlist-prev, .mediaplayer .chapters, .mediaplayer.ended-state > .jme-media-overlay { +.mediaplayer[data-state="waiting"] > div.jme-media-overlay, .mediaplayer .fullscreen, .mediaplayer .fullscreen.state-exitfullscreen, .mediaplayer .mediaconfigmenu, .mediaplayer.initial-state > .jme-media-overlay, .mediaplayer button.play-pause, .mediaplayer button.play-pause.state-playing, .mediaplayer .mute-unmute, .mediaplayer[data-volume="medium"] .mute-unmute, .mediaplayer[data-volume="low"] .mute-unmute, .mediaplayer[data-volume="no"] .mute-unmute, .mediaplayer .state-unmute.mute-unmute, .mediaplayer .captions, .mediaplayer .subtitle-menu button[aria-checked="true"], .mediaplayer .subtitle-menu button, .mediaplayer .playlist-next, .mediaplayer .playlist-prev, .mediaplayer .chapters, .mediaplayer.ended-state > .jme-media-overlay { font-family: 'jme'; speak: none; font-style: normal; @@ -13,7 +13,7 @@ -moz-osx-font-smoothing: grayscale; } -.mediaplayer[data-state="waiting"] > .jme-media-overlay:before { +.mediaplayer[data-state="waiting"] > div.jme-media-overlay:before { content: "\e612"; } @@ -300,10 +300,10 @@ .mediaplayer[data-state="waiting"] { cursor: default; } -.mediaplayer[data-state="waiting"] > .jme-media-overlay { +.mediaplayer[data-state="waiting"] > div.jme-media-overlay { background-position: 4px 4px; } -.mediaplayer[data-state="waiting"] > .jme-media-overlay:before { +.mediaplayer[data-state="waiting"] > div.jme-media-overlay:before { -webkit-animation-name: jmespin; -webkit-animation-iteration-count: infinite; -webkit-animation-duration: 1100ms; diff --git a/public/webshims/shims/jme/controls.scss b/public/webshims/shims/jme/controls.scss index e9744c7d..6cf683af 100644 --- a/public/webshims/shims/jme/controls.scss +++ b/public/webshims/shims/jme/controls.scss @@ -4,6 +4,7 @@ font-family: 'jme'; src: url('jme.eot'); } + @font-face { font-family: 'jme'; src: url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AAA5sAAoAAAAADiQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAACq0AAAqt29xKpU9TLzIAAAukAAAAYAAAAGAIIvzPY21hcAAADAQAAABMAAAATBpVzHBnYXNwAAAMUAAAAAgAAAAIAAAAEGhlYWQAAAxYAAAANgAAADb/1ko1aGhlYQAADJAAAAAkAAAAJAQCAh9obXR4AAAMtAAAAHgAAAB4NSAB521heHAAAA0sAAAABgAAAAYAHlAAbmFtZQAADTQAAAEVAAABFQcRlmFwb3N0AAAOTAAAACAAAAAgAAMAAAEABAQAAQEBBGptZQABAgABADr4HAL4GwP4GAQeCgAZU/+Lix4KABlT/4uLDAeLa/i0+HQFHQAAAQAPHQAAAQURHQAAAAkdAAAKpBIAHwEBBAcJCw4TGB0iJywxNjtARUpPVFleY2htcnd8gYaLkGptZWptZXUwdTF1MjB1RTYwMHVFNjAxdUU2MDJ1RTYwM3VFNjA0dUU2MDV1RTYwNnVFNjA3dUU2MDh1RTYwOXVFNjBBdUU2MEJ1RTYwQ3VFNjBEdUU2MEV1RTYwRnVFNjEwdUU2MTF1RTYxMnVFNjEzdUU2MTR1RTYxNXVFNjE2dUU2MTd1RTYxOHVFNjE5AAACAYkAHAAeAgABAAQABwAKAA0BJAGCAZ8BuwHiAgoCngLwA1EDvgPMA+oEsAU6BZEFuQYFBoAHcwe1B/sIaQikCMgJJQlf/JQO/JQO/JQO+5QO+IL4ABX7f7sFiYuJi4mLCPt/WwWDioWEi4MIi/uyBYuDkYWTiQj3f1wFjYqNi42MCPd/ugWTjZGRi5MIi/eyBYuThZKDjAj7o/twFXtncnlpi1KLZbqLz4vQsbnEi6yLpXqbaYyIi4iKiIqIiYiIighvfwWFiISOiJGHlIOVfot2i3xyi2eLZ5pyoIuai5KajZGNj42NjoyOjY+LjokIp38FjoqNiYyIjYeLiImICPd/ixV6Z3J5aYtTi2W6i8+L0LG5w4uti6R6m2mNiIuIioiJiImIiIoIcH8FhIiEjoiRh5SDlX6Ldot9cotni2eZcqCLmouSmo6RjI+NjY+Mjo2Oi4+JCKZ/BY6KjomMiIyHi4iKiAgO+En4KRVduUuoRIv7AosuRmYqCMd0BabU0r/di8CLu3auaAhDQ/dUi4v3VEBABftJ/AkVVotboGiuCNPT+1SLi/tU1tYFuV3LbtKL9wKL6NCw7AhPogVwQkRXOYsIDvgU+DQVi/wUS4uL90T7NPs0i/f09zT7NIv3RAUO9xSrFYv4FMuLi/tE9zT3NIv79Ps09zSL+0QFDvh1+FUVi/tLRdI2NmG14OBE0QVF+7sVNzbRRftLi4v3S9FF4N8FDvd491gVi/tLRdE2N2G13+BF0QX4SPdnFTc20UX7S4uL90vRReDfBQ74lPdEFYvrQpcFiJSHlIeUCLbHR89PYAWCj4KPgo4If9Qri39CBYKIgoeChwhPtkdHtk8Fh4KHgoiCCEJ/iyvVfwWOgo6Cj4MIYE7PR8i2BZOHlIiUiAiXQeuLl9UFlI6UjpOPCMhgz89gyAWPk46UjpQI1ZcF+5R7FWiLbqiLrouuqKiui66LqG6LaItobm5oiwgOi/h0FfcUi4v7FPsUiwX3VOsV99SLi0v71IsF+1QrFfcUi4v7FPsUiwX3VOsV99SLi0v71IsF+1QrFfcUi4v7FPsUiwX3VOsV99SLi0v71IsFDveU+HQV+yGL+wf7B4v7IYv7IfcH+wf3IYv3IYv3B/cHi/chi/ch+wf3B/shiwiL/GQV+weLLuiL9weL9wfo6PcHi/cHi+gui/sHi/sHLi77B4sIS/fUFfdU+wT7VPsEBQ73lPh0Ffshi/sH+weL+yGL+yH3B/sH9yGL9yGL9wf3B4v3IYv3IfsH9wf7IYsIi/xkFfsHiy7oi/cHi/cH6Oj3B4v3B4voLov7B4v7By4u+weLCCv3xBXLi4v7VEuLBfcU91QVy4uL+1RLiwUOyfhdFfgY+338GPt9BQ6i+F0V91aLi/xm+1aLBfek+GYV91aLi/xm+1aLBQ6r+FGeFYWLhY2GkIKUi5uUlLe3o8WLyYvJc8Vft4KUi5uUlJSUm4uUgsBWqEWLQItAbkVWVgiGhoWJhYsINrgVhYuEjoePgZWLmpWUzM2L9UrNgZSLmpWVlJSai5WCtGKhVYtRi1F1VWJihoeFiIWLCDa4FYSLhY6HkIGUi5qVlLO0i81jtIGUi5qVlJSVmouUgcdQiytPUIeGhYiFiwhB9+AVmJiVhot5CIv8MgWLeYGHfpcI+w33DTuLi/dU24v3DfcNBQ73/MsVhYuEjoePgZWLmpWUzM2L9UrNgZSLmpWVlJSai5WCtGKhVYtRi1F1VWJihoeFiIWLCDa4FYSLhY6HkIGUi5qVlLO0i81jtIGUi5qVlJSVmouUgcdQiytPUIeGhYiFiwhB9+AVmJiVhot5CIv8MgWLeYGHfpcI+w33DTuLi/dU24v3DfcNBQ73p/cBFYSLhY6HkIGUi5qVlLO0i81jtIGUi5qVlJSVmouUgcdQiytPUIeGhYiFiwhB9+AVmJiVhot5CIv8MgWLeYGHfpcI+w33DTuLi/dU24v3DfcNBQ73XfhNFZiYlYaLeQiL/DIFi3mBh36XCPsN9w07i4v3VNuL9w33DQUO9134TRWYmJWGi3kIi/wyBYt5gYd+lwj7DfcNO4uL91Tbi/cN9w0F96v7oxWLYWGLVcFVVWGLi7XBwVXBi7W1i8FVwcG1i4thVVUFDvhE9xQVdIt3gnx8CPtr9gWMj4uQi4+Lj4uQio8I92v2BZp8n4Kii7eLr6+Lt4u3Z69fi1+LZ2eLX4uHi4aMhwj7ayAFfJp3lHSLX4tnZ4tfi1+vZ7eLoouflJqaCPdrIAWKh4uGi4eLX69nt4u3i6+vi7eLt2evX4sIDviU93QViqyErX6pfap4pnOic6JvnW2XbJdqkWuKa4pqhG5+bX5xeXR0dXN6cH9ugG2Fa4xsCIxskWuYb5hunXGhdqF2pnqngKiAqoWpjKmMqZGnl6eYpJyfoaCgm6WWppGckJ2NnAiMi4uLjIudi5mai5yLjIuMi4wIi4sFWDYVf3B6c3d3dnhye3CBcYBuhm+Mb4xvkXGWcZd0m3ifeJ98o4GlgaSGp4ymjKaRppakCJajmqKfnZ6eopmklaOUppCliqWKpYajgKKAoXydeZx4mXWUc5R0kHGKcgiLiwWLiouKi4qLe5d9nIqHeYZ6hHsIDvhU+HQV/FSLi/yU+JSLi/hUS8sF+1RLFcuLi/sUS4uL9xQF91T8FBX8FIuL+BSri4v7NPe0i4v3NLCLpnCL+/kFDvh/+CQVQ5U7kTiLOIs7hUOBflWDUItMi0yTUJhV04Hbhd6L3ovbkdOVmMGTxovKi8qDxn7BCPu/+6QVi/dU9zQr+zQrBQ73VMsV99SLi0v71IsFi/eUFffUi4tL+9SLBYv3lBX31IuLS/vUiwUr6xWL+xRri4vra4uLqwWr+5sVi3LLi4trK4uL1Mupi6RLi4ur64uLQgWL+wsVi/s0K4uLq8uLi6tLi4ury4uLq0uLi6sFDov4dBWL/JT4lIuL+JT8lIsF+HT8dBX8VIuL+FT4VIuL/FQFK/gEFfs0+zQr60tL9zT7NPd093RLywUOi/h0FYv8lPiUi4v4lPyUiwX4dPx0FfxUi4v4VPhUi4v8VAUO9930FSL1i/chy4uL+wfiNQX7C/fdFfshi/sH+weL+yGL+yH3B/sH9yGL9yGL9wf3B4v3IYv3IfsH9wf7IYsIi/xUFSGLNeGL9Yv14eH1i/WL4TWLIYshNTUhiwgOy/d0FfcU9xRLi/sU+xT3FPsUy4sF91T3lBVLi/cU+xT7FPsUy4v3FPcUBfuE91QVO/wUu4vb+BQFDviUFPiUFYsMCgAAAAADAgABkAAFAAABTAFmAAAARwFMAWYAAAD1ABkAhAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAEAAAOYZAeD/4P/gAeAAIAAAAAEAAAAAAAAAAAAAACAAAAAAAAIAAAADAAAAFAADAAEAAAAUAAQAOAAAAAoACAACAAIAAQAg5hn//f//AAAAAAAg5gD//f//AAH/4xoEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAQAAAnhtIV8PPPUACwIAAAAAAM9LhLwAAAAAz0uEvAAA/+ACIAHgAAAACAACAAAAAAAAAAEAAAHg/+AAAAIgAAAAAAIgAAEAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAQAAAAIAAAQCAAAAAgAAoAIAAIACAAAfAgAAHwIAAAACAAAAAgAAAAIAAAACAAA+AgAAFwIgAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAABACAAAAAgAAAAIAACACAAAAAgAAAAIAAAACAAAAAABQAAAeAAAAAAAOAK4AAQAAAAAAAQAGAAAAAQAAAAAAAgAOACsAAQAAAAAAAwAGABwAAQAAAAAABAAGADkAAQAAAAAABQAWAAYAAQAAAAAABgADACIAAQAAAAAACgAoAD8AAwABBAkAAQAGAAAAAwABBAkAAgAOACsAAwABBAkAAwAGABwAAwABBAkABAAGADkAAwABBAkABQAWAAYAAwABBAkABgAGACUAAwABBAkACgAoAD8AagBtAGUAVgBlAHIAcwBpAG8AbgAgADEALgAwAGoAbQBlam1lAGoAbQBlAFIAZQBnAHUAbABhAHIAagBtAGUARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('woff'), @@ -235,7 +236,7 @@ $browser-context: 16; // Default &[data-state="waiting"] { cursor: default; - > .jme-media-overlay { + > div.jme-media-overlay { @extend %icon-spinner; background-position: 4px 4px; diff --git a/public/webshims/shims/jme/mediacontrols.js b/public/webshims/shims/jme/mediacontrols.js index cd4b3663..30573d0e 100644 --- a/public/webshims/shims/jme/mediacontrols.js +++ b/public/webshims/shims/jme/mediacontrols.js @@ -52,7 +52,8 @@ webshims.register('mediacontrols', function($, webshims, window){ })(); var ios = /iP(hone|od|ad)/i.test(navigator.platform); var ios6 = ios && parseInt(((navigator.appVersion).match(/OS (\d+)_\d+/) || ['','8'])[1], 10) < 7; - var hasYtBug = (!window.Modernizr || !Modernizr.videoautoplay) && (ios || /android/i.test(navigator.userAgent)); + var modern = window.Modernizr; + var hasYtBug = (!modern || !modern.videoautoplay) && (ios || /android/i.test(navigator.userAgent)); var loadLazy = function(){ if(!loadLazy.loaded){ loadLazy.loaded = true; @@ -173,7 +174,8 @@ webshims.register('mediacontrols', function($, webshims, window){ if(!e){ e.type = 'playing'; } - if(isInitial && (!isYt || !hasYtBug || e.type == 'playing' || data.media.prop('readyState') > 1)){ + + if(isInitial && (!isYt || !hasYtBug || e.type == 'playing' || data.media.prop('readyState') || data.media.prop('networkState'))){ isInitial = false; data.player.removeClass('initial-state'); } diff --git a/public/webshims/shims/mediacapture-picker.js b/public/webshims/shims/mediacapture-picker.js new file mode 100644 index 00000000..4e540b49 --- /dev/null +++ b/public/webshims/shims/mediacapture-picker.js @@ -0,0 +1,42 @@ +webshim.register('mediacapture-picker', function($, webshim, window, document, undefined, featureOptions){ + "use strict"; + + function PhotoShooter($dom){ + this.$dom = $dom; + this._createDom(); + this.requestMedia(); + } + + PhotoShooter.prototype = { + _createDom: function(){ + this.$dom.html('
' + + '' + + '
' + + '
' + + '
' + + '
') + ; + }, + requestMedia: function(){ + var that = this; + + + navigator.getUserMedia( + {video: {minWidth: 200, audio: false}}, + function(stream){ + that.stream = stream; + $('video', that.$dom).prop('src', URL.createObjectURL(stream)); + }, + function(){ + + } + ); + $('video', that.$dom).removeClass('ws-usermedia'); + + } + }; + + webshim.mediacapture.showContent = function($fileinput, $button, popover){ + var stream = new PhotoShooter(popover.contentElement); + }; +}); diff --git a/public/webshims/shims/mediacapture.js b/public/webshims/shims/mediacapture.js new file mode 100644 index 00000000..a41bef6e --- /dev/null +++ b/public/webshims/shims/mediacapture.js @@ -0,0 +1,159 @@ +webshim.register('mediacapture', function($, webshim, window, document, undefined, featureOptions){ + "use strict"; + var hasCamera = -1; + var checkCameras = $.noop; + var sel = 'input[type="file"].ws-filereader, input[type="file"].ws-capture'; + var cameraListPromise = $.Deferred(); + + // + + (function(){ + var tmp; + + var hasNativeUserMedia = !!(navigator.getUserMedia && !navigator.wsGetUserMedia); + var hasFlash = swfmini.hasFlashPlayerVersion('11.3'); + var writeToStorage = function(){ + try{ + sessionStorage.setItem('wsCameras', JSON.stringify(hasCamera)); + } catch (e){} + }; + var reject = function(){ + hasCamera = 0; + writeToStorage(); + cameraListPromise.reject(hasCamera); + }; + var resolve = function(){ + writeToStorage(); + cameraListPromise.resolve(hasCamera); + }; + try { + tmp = JSON.parse(sessionStorage.getItem('wsCameras')); + if(tmp == null){ + hasCamera = -1; + } + } catch(e){} + + if(hasCamera === 0 || (hasCamera == -1 && !hasNativeUserMedia && !hasFlash)){ + reject(); + } else if(hasFlash){ + checkCameras = function(){ + var mediaOptions = webshim.cfg.mediaelement; + var playerSwfPath = mediaOptions.playerPath || (webshim.cfg.basePath + "swf/" + (mediaOptions.playerName || 'JarisFLVPlayer.swf')); + var id = 'wscameralistdetection'; + var vars = { + controltype: '1', + jsapi: '1', + source: '', + id: id, + evtId: id + }; + var attrs = { + id: id, + name: id + }; + var params = { + allowscriptaccess: 'always', + allowNetworking: 'all' + }; + var $dom = $('
') + .css({position: 'absolute', left: -999, width: 5, height: 5, overflow: 'hidden'}) + .appendTo('body') + ; + + webshim.mediaelement.jarisEvent = webshim.mediaelement.jarisEvent || {}; + webshim.mediaelement.jarisEvent[id] = function(jaris){ + hasCamera = jaris.cameras; + $dom.remove(); + if(hasCamera){ + resolve(); + } else { + reject(); + } + }; + + + checkCameras = $.noop; + swfmini.embedSWF(playerSwfPath, id, "100%", "100%", "11.3", false, vars, params, attrs); + }; + + } else { + hasCamera = -1; + resolve(); + } + })(); + var loadPicker = function(){ + webshim.ready('WINDOWLOAD', function(){ + webshim.loader.loadList(['mediacapture-picker']); + }); + loadPicker = $.noop; + }; + + + var _createPhotoPicker = function(){ + if($(this).is('[capture].ws-filereader, .ws-capture') && webshim.implement(this, 'capture')){ + var $wrapper, $customFile; + var $fileinput = $(this); + var $button = $(''); + var popover = webshim.objectCreate(webshim.wsPopover, {}, $.extend({prepareFor: $button})); + popover.element.addClass('capture-popover input-picker'); + + if($fileinput.is('.ws-custom-file > *')){ + $customFile = $fileinput.closest('.ws-custom-file'); + $wrapper = $('
').insertAfter($customFile); + $wrapper.append($button).append($customFile); + } else { + $fileinput.before($button); + } + popover.element.insertAfter($button); + + $button.on('click', function(){ + webshim.mediacapture.showContent($fileinput, $button, popover); + popover.show(); + }); + loadPicker(); + } + }; + var createPhotoPicker = function (){ + var elem = this; + checkCameras(); + + cameraListPromise.done(function(){ + _createPhotoPicker.call(elem); + }); + }; + + webshim.mediacapture = { + showContent: function($fileinput, $button, popover){ + webshim.loader.loadList(['mediacapture-picker']); + webshim.ready('mediacapture-picker', function(){ + webshim.mediacapture.showContent($fileinput, $button, popover); + }); + } + }; + webshim.defineNodeNamesBooleanProperty('input', 'capture'); + + if(hasCamera){ + + cameraListPromise.done(function(){ + createPhotoPicker = _createPhotoPicker; + webshim.loader.addModule('mediacapture-picker', { + noAutoCallback: true, + css: 'styles/forms-picker.css', + options: featureOptions + }); + + }); + + webshim.addReady(function(context, insertedElement){ + $(sel, context).add(insertedElement.filter(sel)) + .filter('[accept*="image"], :not([accept]), [accept=""]') + .each(createPhotoPicker) + ; + }); + + webshim.ready('WINDOWLOAD', checkCameras); + } + if(document.readyState == 'complete'){ + webshim.isReady('WINDOWLOAD', true); + } +}); diff --git a/public/webshims/shims/mediaelement-core.js b/public/webshims/shims/mediaelement-core.js index 2cd8b91f..1655a844 100644 --- a/public/webshims/shims/mediaelement-core.js +++ b/public/webshims/shims/mediaelement-core.js @@ -58,9 +58,16 @@ })(); } + if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){ + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + cb.call(this, this); + }; + } + webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){ var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); var mediaelement = webshims.mediaelement; + var allowYtLoading = false; mediaelement.parseRtmp = function(data){ var src = data.src.split('://'); @@ -156,7 +163,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u return function(){ if(loaded || !hasYt){return;} loaded = true; - webshims.loader.loadScript("https://www.youtube.com/player_api"); + if(allowYtLoading){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } $(function(){ webshims._polyfill(["mediaelement-yt"]); }); @@ -342,6 +351,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u } }); if(!requested && hasYt && !mediaelement.createSWF){ + allowYtLoading = true; loadYt(); } }; @@ -506,6 +516,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u .add(insertedElement.filter('video, audio')) .each(function(){ if(!mediaelement.canNativePlaySrces(this)){ + allowYtLoading = true; loadThird(); handleMedia = true; return false; @@ -528,6 +539,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u mediaelement.loadDebugger(); }); } + //set native implementation ready, before swf api is retested if(hasNative){ webshims.isReady('mediaelement-core', true); diff --git a/public/webshims/shims/mediaelement-jaris.js b/public/webshims/shims/mediaelement-jaris.js index b326b11b..be5e4514 100644 --- a/public/webshims/shims/mediaelement-jaris.js +++ b/public/webshims/shims/mediaelement-jaris.js @@ -124,12 +124,13 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document, }; - mediaelement.jarisEvent = {}; + mediaelement.jarisEvent = mediaelement.jarisEvent || {}; var localConnectionTimer; var onEvent = { onPlayPause: function(jaris, data, override){ var playing, type; var idled = data.paused || data.ended; + if(override == null){ try { playing = data.api.api_get("isPlaying"); @@ -143,12 +144,15 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document, type = data.paused ? 'pause' : 'play'; data._ppFlag = true; trigger(data._elem, type); + + } + if(!data.paused || playing == idled || playing == null){ if(data.readyState < 3){ setReadyState(3, data); } - if(!data.paused){ - trigger(data._elem, 'playing'); - } + } + if(!data.paused){ + trigger(data._elem, 'playing'); } }, onSeek: function(jaris, data){ @@ -900,11 +904,11 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document, options.changeSWF(vars, elem, canPlaySrc, data, 'embed'); clearTimeout(data.flashBlock); - swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "9.0.115", false, vars, params, attrs, function(swfData){ + swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "11.3", false, vars, params, attrs, function(swfData){ if(swfData.success){ var fBlocker = function(){ - if((!swfData.ref.parentNode && box[0].parentNode) || swfData.ref.style.display == "none"){ - box.addClass('flashblocker-assumed'); + if((!swfData.ref.parentNode) || swfData.ref.style.display == "none"){ + $(elem).trigger('flashblocker'); webshims.warn("flashblocker assumed"); } @@ -1138,8 +1142,19 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document, webshim.error('canvas.drawImage feature is needed. In IE8 flashvanvas pro can be used'); } + CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){ + if(this._wsIsLoading){ + if(!this._wsLoadingCbs){ + this._wsLoadingCbs = []; + } + this._wsLoadingCbs.push(cb); + } else { + cb.call(this, this); + } + }; + CanvasRenderingContext2D.prototype.drawImage = function(elem){ - var data, img, args, imgData; + var data, img, args, imgData, hadCachedImg; var context = this; if(isVideo[elem.nodeName] && (data = webshims.data(elem, 'mediaelement')) && data.isActive == 'third' && data.api.api_image){ @@ -1157,18 +1172,39 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document, } args = slice.call(arguments, 1); - img = new Image(); + + if(options.canvasSync && data.canvasImg){ + args.unshift(data.canvasImg); + _drawImage.apply(context, args); + args = slice.call(arguments, 1); + hadCachedImg = true; + } + + img = document.createElement('img'); //todo find a performant sync way img.onload = function(){ args.unshift(this); - _drawImage.apply(context, args); img.onload = null; + + if(options.canvasSync){ + data.canvasImg = img; + if(hadCachedImg && options.noDoubbleDraw){ + return; + } + } + _drawImage.apply(context, args); + context._wsIsLoading = false; + if(context._wsLoadingCbs && context._wsLoadingCbs.length){ + while(context._wsLoadingCbs.length){ + context._wsLoadingCbs.shift().call(context, context); + } + } }; img.src = 'data:image/jpeg;base64,'+imgData; - - if(img.complete){ + this._wsIsLoading = true; + if(img.complete && img.onload){ img.onload(); } return; diff --git a/public/webshims/shims/mediaelement-yt.js b/public/webshims/shims/mediaelement-yt.js index c308279f..56396387 100644 --- a/public/webshims/shims/mediaelement-yt.js +++ b/public/webshims/shims/mediaelement-yt.js @@ -2,13 +2,21 @@ webshims.register('mediaelement-yt', function($, webshims, window, document, und "use strict"; var mediaelement = webshims.mediaelement; var ytAPI = $.Deferred(); +var loadYTAPI = function(){ + if(!window.YT){ + webshims.loader.loadScript("https://www.youtube.com/player_api"); + } + loadYTAPI = $.noop; +}; +var modern = window.Modernizr; +var assumeYTBug = (!modern || !modern.videoautoplay) && /iP(hone|od|ad)|android/i.test(navigator.userAgent); window.onYouTubePlayerAPIReady = function() { ytAPI.resolve(); + loadYTAPI = $.noop; }; if(window.YT && YT.Player){ window.onYouTubePlayerAPIReady(); } - var getProps = { paused: true, ended: false, @@ -45,7 +53,6 @@ var getSetProps = { volume: 1, muted: false }; -var getSetPropKeys = Object.keys(getSetProps); var playerStateObj = $.extend({ isActive: 'html5', @@ -193,7 +200,6 @@ var getComputedDimension = (function(){ var setElementDimension = function(data){ var dims; - var elem = data._elem; var box = data.shadowElem; if(data.isActive == 'third'){ if(data && data._ytAPI && data._ytAPI.getPlaybackQuality){ @@ -439,9 +445,9 @@ var addYtAPI = function(mediaElm, elemId, data, ytParams){ var currentTime = data._ytAPI.getCurrentTime(); if(data.currentTime != currentTime){ data.currentTime = currentTime; - $(mediaElm).trigger('timeupdate'); + $.event.trigger('timeupdate', null, mediaElm, true); } - }, 350); + }, 270); }; data._metatrys = 0; @@ -569,7 +575,9 @@ mediaelement.createSWF = function(mediaElem, src, data){ var ytParams = getYtParams(src.src); var hasControls = $.prop(mediaElem, 'controls'); var attrStyle = {}; - + + loadYTAPI(); + if((attrStyle.height = $.attr(mediaElem, 'height') || '') || (attrStyle.width = $.attr(mediaElem, 'width') || '')){ $(mediaElem).css(attrStyle); webshims.warn("width or height content attributes used. Webshims prefers the usage of CSS (computed styles or inline styles) to detect size of a video/audio. It's really more powerfull."); @@ -739,8 +747,12 @@ mediaelement.createSWF = function(mediaElem, src, data){ var data = getYtDataFromElem(this); if(data){ if(data._ytAPI && data._ytAPI[ytName]){ - data._ytAPI[ytName](); - handlePlayPauseState(name, data); + if(assumeYTBug && !data.readyState && !data.networkState && data._ppFlag === undefined){ + webshims.warn('youtube video play needs to be directly activated by user, if you use a video overlay set pointer-events to none.'); + } else { + data._ytAPI[ytName](); + handlePlayPauseState(name, data); + } } } else { return mediaSup[name].prop._supvalue.apply(this, arguments); diff --git a/public/webshims/shims/combos/26.js b/public/webshims/shims/moxie/js/moxie-html4.js similarity index 76% rename from public/webshims/shims/combos/26.js rename to public/webshims/shims/moxie/js/moxie-html4.js index 5d2bf15d..a2edc2d3 100644 --- a/public/webshims/shims/combos/26.js +++ b/public/webshims/shims/moxie/js/moxie-html4.js @@ -5131,436 +5131,6 @@ define("moxie/xhr/XMLHttpRequest", [ return XMLHttpRequest; }); -// Included from: src/javascript/runtime/flash/Runtime.js - -/** - * Runtime.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/*global ActiveXObject:true */ - -/** -Defines constructor for Flash runtime. - -@class moxie/runtime/flash/Runtime -@private -*/ -define("moxie/runtime/flash/Runtime", [ - "moxie/core/utils/Basic", - "moxie/core/utils/Env", - "moxie/core/utils/Dom", - "moxie/core/Exceptions", - "moxie/runtime/Runtime" -], function(Basic, Env, Dom, x, Runtime) { - - var type = 'flash', extensions = {}; - - /** - Get the version of the Flash Player - - @method getShimVersion - @private - @return {Number} Flash Player version - */ - function getShimVersion() { - var version; - - try { - version = navigator.plugins['Shockwave Flash']; - version = version.description; - } catch (e1) { - try { - version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); - } catch (e2) { - version = '0.0'; - } - } - version = version.match(/\d+/g); - return parseFloat(version[0] + '.' + version[1]); - } - - /** - Constructor for the Flash Runtime - - @class FlashRuntime - @extends Runtime - */ - function FlashRuntime(options) { - var I = this, initTimer; - - options = Basic.extend({ swf_url: Env.swf_url }, options); - - Runtime.call(this, options, type, { - access_binary: function(value) { - return value && I.mode === 'browser'; - }, - access_image_binary: function(value) { - return value && I.mode === 'browser'; - }, - display_media: Runtime.capTrue, - do_cors: Runtime.capTrue, - drag_and_drop: false, - report_upload_progress: function() { - return I.mode === 'client'; - }, - resize_image: Runtime.capTrue, - return_response_headers: false, - return_response_type: function(responseType) { - if (responseType === 'json' && !!window.JSON) { - return true; - } - return !Basic.arrayDiff(responseType, ['', 'text', 'document']) || I.mode === 'browser'; - }, - return_status_code: function(code) { - return I.mode === 'browser' || !Basic.arrayDiff(code, [200, 404]); - }, - select_file: Runtime.capTrue, - select_multiple: Runtime.capTrue, - send_binary_string: function(value) { - return value && I.mode === 'browser'; - }, - send_browser_cookies: function(value) { - return value && I.mode === 'browser'; - }, - send_custom_headers: function(value) { - return value && I.mode === 'browser'; - }, - send_multipart: Runtime.capTrue, - slice_blob: function(value) { - return value && I.mode === 'browser'; - }, - stream_upload: function(value) { - return value && I.mode === 'browser'; - }, - summon_file_dialog: false, - upload_filesize: function(size) { - return Basic.parseSizeStr(size) <= 2097152 || I.mode === 'client'; - }, - use_http_method: function(methods) { - return !Basic.arrayDiff(methods, ['GET', 'POST']); - } - }, { - // capabilities that require specific mode - access_binary: function(value) { - return value ? 'browser' : 'client'; - }, - access_image_binary: function(value) { - return value ? 'browser' : 'client'; - }, - report_upload_progress: function(value) { - return value ? 'browser' : 'client'; - }, - return_response_type: function(responseType) { - return Basic.arrayDiff(responseType, ['', 'text', 'json', 'document']) ? 'browser' : ['client', 'browser']; - }, - return_status_code: function(code) { - return Basic.arrayDiff(code, [200, 404]) ? 'browser' : ['client', 'browser']; - }, - send_binary_string: function(value) { - return value ? 'browser' : 'client'; - }, - send_browser_cookies: function(value) { - return value ? 'browser' : 'client'; - }, - send_custom_headers: function(value) { - return value ? 'browser' : 'client'; - }, - stream_upload: function(value) { - return value ? 'client' : 'browser'; - }, - upload_filesize: function(size) { - return Basic.parseSizeStr(size) >= 2097152 ? 'client' : 'browser'; - } - }, 'client'); - - - // minimal requirement for Flash Player version - if (getShimVersion() < 10) { - this.mode = false; // with falsy mode, runtime won't operable, no matter what the mode was before - } - - - Basic.extend(this, { - - getShim: function() { - return Dom.get(this.uid); - }, - - shimExec: function(component, action) { - var args = [].slice.call(arguments, 2); - return I.getShim().exec(this.uid, component, action, args); - }, - - init: function() { - var html, el, container; - - container = this.getShimContainer(); - - // if not the minimal height, shims are not initialized in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc) - Basic.extend(container.style, { - position: 'absolute', - top: '-8px', - left: '-8px', - width: '9px', - height: '9px', - overflow: 'hidden' - }); - - // insert flash object - html = '' + - '' + - '' + - '' + - ''; - - if (Env.browser === 'IE') { - el = document.createElement('div'); - container.appendChild(el); - el.outerHTML = html; - el = container = null; // just in case - } else { - container.innerHTML = html; - } - - // Init is dispatched by the shim - initTimer = setTimeout(function() { - if (I && !I.initialized) { // runtime might be already destroyed by this moment - I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); - } - }, 5000); - }, - - destroy: (function(destroy) { // extend default destroy method - return function() { - destroy.call(I); - clearTimeout(initTimer); // initialization check might be still onwait - options = initTimer = destroy = I = null; - }; - }(this.destroy)) - - }, extensions); - } - - Runtime.addConstructor(type, FlashRuntime); - - return extensions; -}); - -// Included from: src/javascript/runtime/flash/file/Blob.js - -/** - * Blob.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/flash/file/Blob -@private -*/ -define("moxie/runtime/flash/file/Blob", [ - "moxie/runtime/flash/Runtime", - "moxie/file/Blob" -], function(extensions, Blob) { - - var FlashBlob = { - slice: function(blob, start, end, type) { - var self = this.getRuntime(); - - if (start < 0) { - start = Math.max(blob.size + start, 0); - } else if (start > 0) { - start = Math.min(start, blob.size); - } - - if (end < 0) { - end = Math.max(blob.size + end, 0); - } else if (end > 0) { - end = Math.min(end, blob.size); - } - - blob = self.shimExec.call(this, 'Blob', 'slice', start, end, type || ''); - - if (blob) { - blob = new Blob(self.uid, blob); - } - return blob; - } - }; - - return (extensions.Blob = FlashBlob); -}); - -// Included from: src/javascript/runtime/flash/file/FileInput.js - -/** - * FileInput.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/flash/file/FileInput -@private -*/ -define("moxie/runtime/flash/file/FileInput", [ - "moxie/runtime/flash/Runtime" -], function(extensions) { - - var FileInput = { - init: function(options) { - this.getRuntime().shimExec.call(this, 'FileInput', 'init', { - name: options.name, - accept: options.accept, - multiple: options.multiple - }); - this.trigger('ready'); - } - }; - - return (extensions.FileInput = FileInput); -}); - -// Included from: src/javascript/runtime/flash/file/FileReader.js - -/** - * FileReader.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/flash/file/FileReader -@private -*/ -define("moxie/runtime/flash/file/FileReader", [ - "moxie/runtime/flash/Runtime", - "moxie/core/utils/Encode" -], function(extensions, Encode) { - - var _result = ''; - - function _formatData(data, op) { - switch (op) { - case 'readAsText': - return Encode.atob(data, 'utf8'); - case 'readAsBinaryString': - return Encode.atob(data); - case 'readAsDataURL': - return data; - } - return null; - } - - var FileReader = { - read: function(op, blob) { - var target = this, self = target.getRuntime(); - - // special prefix for DataURL read mode - if (op === 'readAsDataURL') { - _result = 'data:' + (blob.type || '') + ';base64,'; - } - - target.bind('Progress', function(e, data) { - if (data) { - _result += _formatData(data, op); - } - }); - - return self.shimExec.call(this, 'FileReader', 'readAsBase64', blob.uid); - }, - - getResult: function() { - return _result; - }, - - destroy: function() { - _result = null; - } - }; - - return (extensions.FileReader = FileReader); -}); - -// Included from: src/javascript/runtime/flash/file/FileReaderSync.js - -/** - * FileReaderSync.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/flash/file/FileReaderSync -@private -*/ -define("moxie/runtime/flash/file/FileReaderSync", [ - "moxie/runtime/flash/Runtime", - "moxie/core/utils/Encode" -], function(extensions, Encode) { - - function _formatData(data, op) { - switch (op) { - case 'readAsText': - return Encode.atob(data, 'utf8'); - case 'readAsBinaryString': - return Encode.atob(data); - case 'readAsDataURL': - return data; - } - return null; - } - - var FileReaderSync = { - read: function(op, blob) { - var result, self = this.getRuntime(); - - result = self.shimExec.call(this, 'FileReaderSync', 'readAsBase64', blob.uid); - if (!result) { - return null; // or throw ex - } - - // special prefix for DataURL read mode - if (op === 'readAsDataURL') { - result = 'data:' + (blob.type || '') + ';base64,' + result; - } - - return _formatData(result, op, blob.type); - } - }; - - return (extensions.FileReaderSync = FileReaderSync); -}); - // Included from: src/javascript/runtime/Transporter.js /** @@ -5698,10 +5268,10 @@ define("moxie/runtime/Transporter", [ return Transporter; }); -// Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js +// Included from: src/javascript/image/Image.js /** - * XMLHttpRequest.js + * Image.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. @@ -5710,141 +5280,598 @@ define("moxie/runtime/Transporter", [ * Contributing: http://www.plupload.com/contributing */ -/** -@class moxie/runtime/flash/xhr/XMLHttpRequest -@private -*/ -define("moxie/runtime/flash/xhr/XMLHttpRequest", [ - "moxie/runtime/flash/Runtime", +define("moxie/image/Image", [ "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/Exceptions", + "moxie/file/FileReaderSync", + "moxie/xhr/XMLHttpRequest", + "moxie/runtime/Runtime", + "moxie/runtime/RuntimeClient", + "moxie/runtime/Transporter", + "moxie/core/utils/Env", + "moxie/core/EventTarget", "moxie/file/Blob", "moxie/file/File", - "moxie/file/FileReaderSync", - "moxie/xhr/FormData", - "moxie/runtime/Transporter" -], function(extensions, Basic, Blob, File, FileReaderSync, FormData, Transporter) { - - var XMLHttpRequest = { + "moxie/core/utils/Encode" +], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) { + /** + Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data. - send: function(meta, data) { - var target = this, self = target.getRuntime(); + @class Image + @constructor + @extends EventTarget + */ + var dispatches = [ + 'progress', - function send() { - meta.transport = self.mode; - self.shimExec.call(target, 'XMLHttpRequest', 'send', meta, data); - } + /** + Dispatched when loading is complete. + @event load + @param {Object} event + */ + 'load', - function appendBlob(name, blob) { - self.shimExec.call(target, 'XMLHttpRequest', 'appendBlob', name, blob.uid); - data = null; - send(); - } + 'error', + /** + Dispatched when resize operation is complete. + + @event resize + @param {Object} event + */ + 'resize', - function attachBlob(blob, cb) { - var tr = new Transporter(); + /** + Dispatched when visual representation of the image is successfully embedded + into the corresponsing container. - tr.bind("TransportingComplete", function() { - cb(this.result); - }); + @event embedded + @param {Object} event + */ + 'embedded' + ]; - tr.transport(blob.getSource(), blob.type, { - ruid: self.uid - }); - } + function Image() { + RuntimeClient.call(this); - // copy over the headers if any - if (!Basic.isEmptyObj(meta.headers)) { - Basic.each(meta.headers, function(value, header) { - self.shimExec.call(target, 'XMLHttpRequest', 'setRequestHeader', header, value.toString()); // Silverlight doesn't accept integers into the arguments of type object - }); - } + Basic.extend(this, { + /** + Unique id of the component - // transfer over multipart params and blob itself - if (data instanceof FormData) { - var blobField; - data.each(function(value, name) { - if (value instanceof Blob) { - blobField = name; - } else { - self.shimExec.call(target, 'XMLHttpRequest', 'append', name, value); - } - }); + @property uid + @type {String} + */ + uid: Basic.guid('uid_'), - if (!data.hasBlob()) { - data = null; - send(); + /** + Unique id of the connected runtime, if any. + + @property ruid + @type {String} + */ + ruid: null, + + /** + Name of the file, that was used to create an image, if available. If not equals to empty string. + + @property name + @type {String} + @default "" + */ + name: "", + + /** + Size of the image in bytes. Actual value is set only after image is preloaded. + + @property size + @type {Number} + @default 0 + */ + size: 0, + + /** + Width of the image. Actual value is set only after image is preloaded. + + @property width + @type {Number} + @default 0 + */ + width: 0, + + /** + Height of the image. Actual value is set only after image is preloaded. + + @property height + @type {Number} + @default 0 + */ + height: 0, + + /** + Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded. + + @property type + @type {String} + @default "" + */ + type: "", + + /** + Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded. + + @property meta + @type {Object} + @default {} + */ + meta: {}, + + /** + Alias for load method, that takes another mOxie.Image object as a source (see load). + + @method clone + @param {Image} src Source for the image + @param {Boolean} [exact=false] Whether to activate in-depth clone mode + */ + clone: function() { + this.load.apply(this, arguments); + }, + + /** + Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File, + native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL, + Image will be downloaded from remote destination and loaded in memory. + + @example + var img = new mOxie.Image(); + img.onload = function() { + var blob = img.getAsBlob(); + + var formData = new mOxie.FormData(); + formData.append('file', blob); + + var xhr = new mOxie.XMLHttpRequest(); + xhr.onload = function() { + // upload complete + }; + xhr.open('post', 'upload.php'); + xhr.send(formData); + }; + img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg) + + + @method load + @param {Image|Blob|File|String} src Source for the image + @param {Boolean|Object} [mixed] + */ + load: function() { + // this is here because to bind properly we need an uid first, which is created above + this.bind('Load Resize', function() { + _updateInfo.call(this); + }, 999); + + this.convertEventPropsToHandlers(dispatches); + + _load.apply(this, arguments); + }, + + /** + Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions. + + @method downsize + @param {Number} width Resulting width + @param {Number} [height=width] Resulting height (optional, if not supplied will default to width) + @param {Boolean} [crop=false] Whether to crop the image to exact dimensions + @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) + */ + downsize: function(opts) { + var defaults = { + width: this.width, + height: this.height, + crop: false, + preserveHeaders: true + }; + + if (typeof(opts) === 'object') { + opts = Basic.extend(defaults, opts); } else { - var blob = data.getBlob(); - if (blob.isDetached()) { - attachBlob(blob, function(attachedBlob) { - blob.destroy(); - appendBlob(blobField, attachedBlob); - }); - } else { - appendBlob(blobField, blob); - } - } - } else if (data instanceof Blob) { - if (data.isDetached()) { - attachBlob(data, function(attachedBlob) { - data.destroy(); - data = attachedBlob.uid; - send(); + opts = Basic.extend(defaults, { + width: arguments[0], + height: arguments[1], + crop: arguments[2], + preserveHeaders: arguments[3] }); - } else { - data = data.uid; - send(); - } - } else { - send(); - } - }, - - getResponse: function(responseType) { - var frs, blob, self = this.getRuntime(); - - blob = self.shimExec.call(this, 'XMLHttpRequest', 'getResponseAsBlob'); - - if (blob) { - blob = new File(self.uid, blob); - - if ('blob' === responseType) { - return blob; } - try { - frs = new FileReaderSync(); - - if (!!~Basic.inArray(responseType, ["", "text"])) { - return frs.readAsText(blob); - } else if ('json' === responseType && !!window.JSON) { - return JSON.parse(frs.readAsText(blob)); + try { + if (!this.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } - } finally { - blob.destroy(); + + // no way to reliably intercept the crash due to high resolution, so we simply avoid it + if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { + throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); + } + + this.getRuntime().exec.call(this, 'Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders); + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); } + }, + + /** + Alias for downsize(width, height, true). (see downsize) + + @method crop + @param {Number} width Resulting width + @param {Number} [height=width] Resulting height (optional, if not supplied will default to width) + @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) + */ + crop: function(width, height, preserveHeaders) { + this.downsize(width, height, true, preserveHeaders); + }, + + getAsCanvas: function() { + if (!Env.can('create_canvas')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + var runtime = this.connectRuntime(this.ruid); + return runtime.exec.call(this, 'Image', 'getAsCanvas'); + }, + + /** + Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsBlob + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {Blob} Image as Blob + */ + getAsBlob: function(type, quality) { + if (!this.size) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + if (!type) { + type = 'image/jpeg'; + } + + if (type === 'image/jpeg' && !quality) { + quality = 90; + } + + return this.getRuntime().exec.call(this, 'Image', 'getAsBlob', type, quality); + }, + + /** + Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsDataURL + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {String} Image as dataURL string + */ + getAsDataURL: function(type, quality) { + if (!this.size) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + return this.getRuntime().exec.call(this, 'Image', 'getAsDataURL', type, quality); + }, + + /** + Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsBinaryString + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {String} Image as binary string + */ + getAsBinaryString: function(type, quality) { + var dataUrl = this.getAsDataURL(type, quality); + return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)); + }, + + /** + Embeds a visual representation of the image into the specified node. Depending on the runtime, + it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare, + can be used in legacy browsers that do not have canvas or proper dataURI support). + + @method embed + @param {DOMElement} el DOM element to insert the image object into + @param {Object} [options] + @param {Number} [options.width] The width of an embed (defaults to the image width) + @param {Number} [options.height] The height of an embed (defaults to the image height) + @param {String} [type="image/jpeg"] Mime type + @param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg + @param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions + */ + embed: function(el) { + var self = this + , imgCopy + , type, quality, crop + , options = arguments[1] || {} + , width = this.width + , height = this.height + , runtime // this has to be outside of all the closures to contain proper runtime + ; + + function onResize() { + // if possible, embed a canvas element directly + if (Env.can('create_canvas')) { + var canvas = imgCopy.getAsCanvas(); + if (canvas) { + el.appendChild(canvas); + canvas = null; + imgCopy.destroy(); + self.trigger('embedded'); + return; + } + } + + var dataUrl = imgCopy.getAsDataURL(type, quality); + if (!dataUrl) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + + if (Env.can('use_data_uri_of', dataUrl.length)) { + el.innerHTML = ''; + imgCopy.destroy(); + self.trigger('embedded'); + } else { + var tr = new Transporter(); + + tr.bind("TransportingComplete", function() { + runtime = self.connectRuntime(this.result.ruid); + + self.bind("Embedded", function() { + // position and size properly + Basic.extend(runtime.getShimContainer().style, { + //position: 'relative', + top: '0px', + left: '0px', + width: imgCopy.width + 'px', + height: imgCopy.height + 'px' + }); + + // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's + // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and + // sometimes 8 and they do not have this problem, we can comment this for now + /*tr.bind("RuntimeInit", function(e, runtime) { + tr.destroy(); + runtime.destroy(); + onResize.call(self); // re-feed our image data + });*/ + + runtime = null; + }, 999); + + runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height); + imgCopy.destroy(); + }); + + tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, Basic.extend({}, options, { + required_caps: { + display_media: true + }, + runtime_order: 'flash,silverlight', + container: el + })); + } + } + + try { + if (!(el = Dom.get(el))) { + throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR); + } + + if (!this.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { + throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); + } + + type = options.type || this.type || 'image/jpeg'; + quality = options.quality || 90; + crop = Basic.typeOf(options.crop) !== 'undefined' ? options.crop : false; + + // figure out dimensions for the thumb + if (options.width) { + width = options.width; + height = options.height || width; + } else { + // if container element has measurable dimensions, use them + var dimensions = Dom.getSize(el); + if (dimensions.w && dimensions.h) { // both should be > 0 + width = dimensions.w; + height = dimensions.h; + } + } + + imgCopy = new Image(); + + imgCopy.bind("Resize", function() { + onResize.call(self); + }); + + imgCopy.bind("Load", function() { + imgCopy.downsize(width, height, crop, false); + }); + + imgCopy.clone(this, false); + + return imgCopy; + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + }, + + /** + Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object. + + @method destroy + */ + destroy: function() { + if (this.ruid) { + this.getRuntime().exec.call(this, 'Image', 'destroy'); + this.disconnectRuntime(); + } + this.unbindAll(); } - return null; - }, + }); - abort: function(upload_complete_flag) { - var self = this.getRuntime(); - self.shimExec.call(this, 'XMLHttpRequest', 'abort'); + function _updateInfo(info) { + if (!info) { + info = this.getRuntime().exec.call(this, 'Image', 'getInfo'); + } - this.dispatchEvent('readystatechange'); - // this.dispatchEvent('progress'); - this.dispatchEvent('abort'); + this.size = info.size; + this.width = info.width; + this.height = info.height; + this.type = info.type; + this.meta = info.meta; - //if (!upload_complete_flag) { - // this.dispatchEvent('uploadprogress'); - //} + // update file name, only if empty + if (this.name === '') { + this.name = info.name; + } } - }; + - return (extensions.XMLHttpRequest = XMLHttpRequest); + function _load(src) { + var srcType = Basic.typeOf(src); + + try { + // if source is Image + if (src instanceof Image) { + if (!src.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + _loadFromImage.apply(this, arguments); + } + // if source is o.Blob/o.File + else if (src instanceof Blob) { + if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + _loadFromBlob.apply(this, arguments); + } + // if native blob/file + else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) { + _load.call(this, new File(null, src), arguments[1]); + } + // if String + else if (srcType === 'string') { + // if dataUrl String + if (/^data:[^;]*;base64,/.test(src)) { + _load.call(this, new Blob(null, { data: src }), arguments[1]); + } + // else assume Url, either relative or absolute + else { + _loadFromUrl.apply(this, arguments); + } + } + // if source seems to be an img node + else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') { + _load.call(this, src.src, arguments[1]); + } + else { + throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR); + } + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + } + + + function _loadFromImage(img, exact) { + var runtime = this.connectRuntime(img.ruid); + this.ruid = runtime.uid; + runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact)); + } + + + function _loadFromBlob(blob, options) { + var self = this; + + self.name = blob.name || ''; + + function exec(runtime) { + self.ruid = runtime.uid; + runtime.exec.call(self, 'Image', 'loadFromBlob', blob); + } + + if (blob.isDetached()) { + this.bind('RuntimeInit', function(e, runtime) { + exec(runtime); + }); + + // convert to object representation + if (options && typeof(options.required_caps) === 'string') { + options.required_caps = Runtime.parseCaps(options.required_caps); + } + + this.connectRuntime(Basic.extend({ + required_caps: { + access_image_binary: true, + resize_image: true + } + }, options)); + } else { + exec(this.connectRuntime(blob.ruid)); + } + } + + + function _loadFromUrl(url, options) { + var self = this, xhr; + + xhr = new XMLHttpRequest(); + + xhr.open('get', url); + xhr.responseType = 'blob'; + + xhr.onprogress = function(e) { + self.trigger(e); + }; + + xhr.onload = function() { + _loadFromBlob.call(self, xhr.response, true); + }; + + xhr.onerror = function(e) { + self.trigger(e); + }; + + xhr.onloadend = function() { + xhr.destroy(); + }; + + xhr.bind('RuntimeError', function(e, err) { + self.trigger('RuntimeError', err); + }); + + xhr.send(null, options); + } + } + + // virtual world will crash on you if image has a resolution higher than this: + Image.MAX_RESIZE_WIDTH = 6500; + Image.MAX_RESIZE_HEIGHT = 6500; + + Image.prototype = EventTarget.instance; + + return Image; }); // Included from: src/javascript/runtime/html4/Runtime.js @@ -6836,10 +6863,10 @@ define("moxie/runtime/html4/xhr/XMLHttpRequest", [ return (extensions.XMLHttpRequest = XMLHttpRequest); }); -// Included from: src/javascript/runtime/silverlight/Runtime.js +// Included from: src/javascript/runtime/html5/utils/BinaryReader.js /** - * RunTime.js + * BinaryReader.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. @@ -6848,207 +6875,1630 @@ define("moxie/runtime/html4/xhr/XMLHttpRequest", [ * Contributing: http://www.plupload.com/contributing */ -/*global ActiveXObject:true */ - /** -Defines constructor for Silverlight runtime. - -@class moxie/runtime/silverlight/Runtime +@class moxie/runtime/html5/utils/BinaryReader @private */ -define("moxie/runtime/silverlight/Runtime", [ - "moxie/core/utils/Basic", - "moxie/core/utils/Env", - "moxie/core/utils/Dom", - "moxie/core/Exceptions", - "moxie/runtime/Runtime" -], function(Basic, Env, Dom, x, Runtime) { - - var type = "silverlight", extensions = {}; +define("moxie/runtime/html5/utils/BinaryReader", [], function() { + return function() { + var II = false, bin; - function isInstalled(version) { - var isVersionSupported = false, control = null, actualVer, - actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0; + // Private functions + function read(idx, size) { + var mv = II ? 0 : -8 * (size - 1), sum = 0, i; - try { - try { - control = new ActiveXObject('AgControl.AgControl'); + for (i = 0; i < size; i++) { + sum |= (bin.charCodeAt(idx + i) << Math.abs(mv + i*8)); + } - if (control.IsVersionSupported(version)) { - isVersionSupported = true; + return sum; + } + + function putstr(segment, idx, length) { + length = arguments.length === 3 ? length : bin.length - idx - 1; + bin = bin.substr(0, idx) + segment + bin.substr(length + idx); + } + + function write(idx, num, size) { + var str = '', mv = II ? 0 : -8 * (size - 1), i; + + for (i = 0; i < size; i++) { + str += String.fromCharCode((num >> Math.abs(mv + i*8)) & 255); + } + + putstr(str, idx, size); + } + + // Public functions + return { + II: function(order) { + if (order === undefined) { + return II; + } else { + II = order; + } + }, + + init: function(binData) { + II = false; + bin = binData; + }, + + SEGMENT: function(idx, length, segment) { + switch (arguments.length) { + case 1: + return bin.substr(idx, bin.length - idx - 1); + case 2: + return bin.substr(idx, length); + case 3: + putstr(segment, idx, length); + break; + default: return bin; + } + }, + + BYTE: function(idx) { + return read(idx, 1); + }, + + SHORT: function(idx) { + return read(idx, 2); + }, + + LONG: function(idx, num) { + if (num === undefined) { + return read(idx, 4); + } else { + write(idx, num, 4); + } + }, + + SLONG: function(idx) { // 2's complement notation + var num = read(idx, 4); + + return (num > 2147483647 ? num - 4294967296 : num); + }, + + STRING: function(idx, size) { + var str = ''; + + for (size += idx; idx < size; idx++) { + str += String.fromCharCode(read(idx, 1)); } - control = null; - } catch (e) { - var plugin = navigator.plugins["Silverlight Plug-In"]; + return str; + } + }; + }; +}); - if (plugin) { - actualVer = plugin.description; +// Included from: src/javascript/runtime/html5/image/JPEGHeaders.js - if (actualVer === "1.0.30226.2") { - actualVer = "2.0.30226.2"; +/** + * JPEGHeaders.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/JPEGHeaders +@private +*/ +define("moxie/runtime/html5/image/JPEGHeaders", [ + "moxie/runtime/html5/utils/BinaryReader" +], function(BinaryReader) { + + return function JPEGHeaders(data) { + var headers = [], read, idx, marker, length = 0; + + read = new BinaryReader(); + read.init(data); + + // Check if data is jpeg + if (read.SHORT(0) !== 0xFFD8) { + return; + } + + idx = 2; + + while (idx <= data.length) { + marker = read.SHORT(idx); + + // omit RST (restart) markers + if (marker >= 0xFFD0 && marker <= 0xFFD7) { + idx += 2; + continue; + } + + // no headers allowed after SOS marker + if (marker === 0xFFDA || marker === 0xFFD9) { + break; + } + + length = read.SHORT(idx + 2) + 2; + + // APPn marker detected + if (marker >= 0xFFE1 && marker <= 0xFFEF) { + headers.push({ + hex: marker, + name: 'APP' + (marker & 0x000F), + start: idx, + length: length, + segment: read.SEGMENT(idx, length) + }); + } + + idx += length; + } + + read.init(null); // free memory + + return { + headers: headers, + + restore: function(data) { + var max, i; + + read.init(data); + + idx = read.SHORT(2) == 0xFFE0 ? 4 + read.SHORT(4) : 2; + + for (i = 0, max = headers.length; i < max; i++) { + read.SEGMENT(idx, 0, headers[i].segment); + idx += headers[i].length; + } + + data = read.SEGMENT(); + read.init(null); + return data; + }, + + strip: function(data) { + var headers, jpegHeaders, i; + + jpegHeaders = new JPEGHeaders(data); + headers = jpegHeaders.headers; + jpegHeaders.purge(); + + read.init(data); + + i = headers.length; + while (i--) { + read.SEGMENT(headers[i].start, headers[i].length, ''); + } + + data = read.SEGMENT(); + read.init(null); + return data; + }, + + get: function(name) { + var array = []; + + for (var i = 0, max = headers.length; i < max; i++) { + if (headers[i].name === name.toUpperCase()) { + array.push(headers[i].segment); } + } + return array; + }, - actualVerArray = actualVer.split("."); + set: function(name, segment) { + var array = [], i, ii, max; - while (actualVerArray.length > 3) { - actualVerArray.pop(); + if (typeof(segment) === 'string') { + array.push(segment); + } else { + array = segment; + } + + for (i = ii = 0, max = headers.length; i < max; i++) { + if (headers[i].name === name.toUpperCase()) { + headers[i].segment = array[ii]; + headers[i].length = array[ii].length; + ii++; } - - while ( actualVerArray.length < 4) { - actualVerArray.push(0); + if (ii >= array.length) { + break; } + } + }, - reqVerArray = version.split("."); + purge: function() { + headers = []; + read.init(null); + read = null; + } + }; + }; +}); - while (reqVerArray.length > 4) { - reqVerArray.pop(); - } +// Included from: src/javascript/runtime/html5/image/ExifParser.js - do { - requiredVersionPart = parseInt(reqVerArray[index], 10); - actualVersionPart = parseInt(actualVerArray[index], 10); - index++; - } while (index < reqVerArray.length && requiredVersionPart === actualVersionPart); +/** + * ExifParser.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ - if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) { - isVersionSupported = true; +/** +@class moxie/runtime/html5/image/ExifParser +@private +*/ +define("moxie/runtime/html5/image/ExifParser", [ + "moxie/core/utils/Basic", + "moxie/runtime/html5/utils/BinaryReader" +], function(Basic, BinaryReader) { + + return function ExifParser() { + // Private ExifParser fields + var data, tags, Tiff, offsets = {}, tagDescs; + + data = new BinaryReader(); + + tags = { + tiff : { + /* + The image orientation viewed in terms of rows and columns. + + 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. + 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. + 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. + 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. + 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. + 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. + 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. + 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. + */ + 0x0112: 'Orientation', + 0x010E: 'ImageDescription', + 0x010F: 'Make', + 0x0110: 'Model', + 0x0131: 'Software', + 0x8769: 'ExifIFDPointer', + 0x8825: 'GPSInfoIFDPointer' + }, + exif : { + 0x9000: 'ExifVersion', + 0xA001: 'ColorSpace', + 0xA002: 'PixelXDimension', + 0xA003: 'PixelYDimension', + 0x9003: 'DateTimeOriginal', + 0x829A: 'ExposureTime', + 0x829D: 'FNumber', + 0x8827: 'ISOSpeedRatings', + 0x9201: 'ShutterSpeedValue', + 0x9202: 'ApertureValue' , + 0x9207: 'MeteringMode', + 0x9208: 'LightSource', + 0x9209: 'Flash', + 0x920A: 'FocalLength', + 0xA402: 'ExposureMode', + 0xA403: 'WhiteBalance', + 0xA406: 'SceneCaptureType', + 0xA404: 'DigitalZoomRatio', + 0xA408: 'Contrast', + 0xA409: 'Saturation', + 0xA40A: 'Sharpness' + }, + gps : { + 0x0000: 'GPSVersionID', + 0x0001: 'GPSLatitudeRef', + 0x0002: 'GPSLatitude', + 0x0003: 'GPSLongitudeRef', + 0x0004: 'GPSLongitude' + } + }; + + tagDescs = { + 'ColorSpace': { + 1: 'sRGB', + 0: 'Uncalibrated' + }, + + 'MeteringMode': { + 0: 'Unknown', + 1: 'Average', + 2: 'CenterWeightedAverage', + 3: 'Spot', + 4: 'MultiSpot', + 5: 'Pattern', + 6: 'Partial', + 255: 'Other' + }, + + 'LightSource': { + 1: 'Daylight', + 2: 'Fliorescent', + 3: 'Tungsten', + 4: 'Flash', + 9: 'Fine weather', + 10: 'Cloudy weather', + 11: 'Shade', + 12: 'Daylight fluorescent (D 5700 - 7100K)', + 13: 'Day white fluorescent (N 4600 -5400K)', + 14: 'Cool white fluorescent (W 3900 - 4500K)', + 15: 'White fluorescent (WW 3200 - 3700K)', + 17: 'Standard light A', + 18: 'Standard light B', + 19: 'Standard light C', + 20: 'D55', + 21: 'D65', + 22: 'D75', + 23: 'D50', + 24: 'ISO studio tungsten', + 255: 'Other' + }, + + 'Flash': { + 0x0000: 'Flash did not fire.', + 0x0001: 'Flash fired.', + 0x0005: 'Strobe return light not detected.', + 0x0007: 'Strobe return light detected.', + 0x0009: 'Flash fired, compulsory flash mode', + 0x000D: 'Flash fired, compulsory flash mode, return light not detected', + 0x000F: 'Flash fired, compulsory flash mode, return light detected', + 0x0010: 'Flash did not fire, compulsory flash mode', + 0x0018: 'Flash did not fire, auto mode', + 0x0019: 'Flash fired, auto mode', + 0x001D: 'Flash fired, auto mode, return light not detected', + 0x001F: 'Flash fired, auto mode, return light detected', + 0x0020: 'No flash function', + 0x0041: 'Flash fired, red-eye reduction mode', + 0x0045: 'Flash fired, red-eye reduction mode, return light not detected', + 0x0047: 'Flash fired, red-eye reduction mode, return light detected', + 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode', + 0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected', + 0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected', + 0x0059: 'Flash fired, auto mode, red-eye reduction mode', + 0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode', + 0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode' + }, + + 'ExposureMode': { + 0: 'Auto exposure', + 1: 'Manual exposure', + 2: 'Auto bracket' + }, + + 'WhiteBalance': { + 0: 'Auto white balance', + 1: 'Manual white balance' + }, + + 'SceneCaptureType': { + 0: 'Standard', + 1: 'Landscape', + 2: 'Portrait', + 3: 'Night scene' + }, + + 'Contrast': { + 0: 'Normal', + 1: 'Soft', + 2: 'Hard' + }, + + 'Saturation': { + 0: 'Normal', + 1: 'Low saturation', + 2: 'High saturation' + }, + + 'Sharpness': { + 0: 'Normal', + 1: 'Soft', + 2: 'Hard' + }, + + // GPS related + 'GPSLatitudeRef': { + N: 'North latitude', + S: 'South latitude' + }, + + 'GPSLongitudeRef': { + E: 'East longitude', + W: 'West longitude' + } + }; + + function extractTags(IFD_offset, tags2extract) { + var length = data.SHORT(IFD_offset), i, ii, + tag, type, count, tagOffset, offset, value, values = [], hash = {}; + + for (i = 0; i < length; i++) { + // Set binary reader pointer to beginning of the next tag + offset = tagOffset = IFD_offset + 12 * i + 2; + + tag = tags2extract[data.SHORT(offset)]; + + if (tag === undefined) { + continue; // Not the tag we requested + } + + type = data.SHORT(offset+=2); + count = data.LONG(offset+=2); + + offset += 4; + values = []; + + switch (type) { + case 1: // BYTE + case 7: // UNDEFINED + if (count > 4) { + offset = data.LONG(offset) + offsets.tiffHeader; + } + + for (ii = 0; ii < count; ii++) { + values[ii] = data.BYTE(offset + ii); + } + + break; + + case 2: // STRING + if (count > 4) { + offset = data.LONG(offset) + offsets.tiffHeader; + } + + hash[tag] = data.STRING(offset, count - 1); + + continue; + + case 3: // SHORT + if (count > 2) { + offset = data.LONG(offset) + offsets.tiffHeader; + } + + for (ii = 0; ii < count; ii++) { + values[ii] = data.SHORT(offset + ii*2); + } + + break; + + case 4: // LONG + if (count > 1) { + offset = data.LONG(offset) + offsets.tiffHeader; + } + + for (ii = 0; ii < count; ii++) { + values[ii] = data.LONG(offset + ii*4); + } + + break; + + case 5: // RATIONAL + offset = data.LONG(offset) + offsets.tiffHeader; + + for (ii = 0; ii < count; ii++) { + values[ii] = data.LONG(offset + ii*4) / data.LONG(offset + ii*4 + 4); + } + + break; + + case 9: // SLONG + offset = data.LONG(offset) + offsets.tiffHeader; + + for (ii = 0; ii < count; ii++) { + values[ii] = data.SLONG(offset + ii*4); + } + + break; + + case 10: // SRATIONAL + offset = data.LONG(offset) + offsets.tiffHeader; + + for (ii = 0; ii < count; ii++) { + values[ii] = data.SLONG(offset + ii*4) / data.SLONG(offset + ii*4 + 4); + } + + break; + + default: + continue; + } + + value = (count == 1 ? values[0] : values); + + if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') { + hash[tag] = tagDescs[tag][value]; + } else { + hash[tag] = value; + } + } + + return hash; + } + + function getIFDOffsets() { + var idx = offsets.tiffHeader; + + // Set read order of multi-byte data + data.II(data.SHORT(idx) == 0x4949); + + // Check if always present bytes are indeed present + if (data.SHORT(idx+=2) !== 0x002A) { + return false; + } + + offsets.IFD0 = offsets.tiffHeader + data.LONG(idx += 2); + Tiff = extractTags(offsets.IFD0, tags.tiff); + + if ('ExifIFDPointer' in Tiff) { + offsets.exifIFD = offsets.tiffHeader + Tiff.ExifIFDPointer; + delete Tiff.ExifIFDPointer; + } + + if ('GPSInfoIFDPointer' in Tiff) { + offsets.gpsIFD = offsets.tiffHeader + Tiff.GPSInfoIFDPointer; + delete Tiff.GPSInfoIFDPointer; + } + return true; + } + + // At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported + function setTag(ifd, tag, value) { + var offset, length, tagOffset, valueOffset = 0; + + // If tag name passed translate into hex key + if (typeof(tag) === 'string') { + var tmpTags = tags[ifd.toLowerCase()]; + for (var hex in tmpTags) { + if (tmpTags[hex] === tag) { + tag = hex; + break; } } } - } catch (e2) { - isVersionSupported = false; + offset = offsets[ifd.toLowerCase() + 'IFD']; + length = data.SHORT(offset); + + for (var i = 0; i < length; i++) { + tagOffset = offset + 12 * i + 2; + + if (data.SHORT(tagOffset) == tag) { + valueOffset = tagOffset + 8; + break; + } + } + + if (!valueOffset) { + return false; + } + + data.LONG(valueOffset, value); + return true; } - return isVersionSupported; + + // Public functions + return { + init: function(segment) { + // Reset internal data + offsets = { + tiffHeader: 10 + }; + + if (segment === undefined || !segment.length) { + return false; + } + + data.init(segment); + + // Check if that's APP1 and that it has EXIF + if (data.SHORT(0) === 0xFFE1 && data.STRING(4, 5).toUpperCase() === "EXIF\0") { + return getIFDOffsets(); + } + return false; + }, + + TIFF: function() { + return Tiff; + }, + + EXIF: function() { + var Exif; + + // Populate EXIF hash + Exif = extractTags(offsets.exifIFD, tags.exif); + + // Fix formatting of some tags + if (Exif.ExifVersion && Basic.typeOf(Exif.ExifVersion) === 'array') { + for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) { + exifVersion += String.fromCharCode(Exif.ExifVersion[i]); + } + Exif.ExifVersion = exifVersion; + } + + return Exif; + }, + + GPS: function() { + var GPS; + + GPS = extractTags(offsets.gpsIFD, tags.gps); + + // iOS devices (and probably some others) do not put in GPSVersionID tag (why?..) + if (GPS.GPSVersionID && Basic.typeOf(GPS.GPSVersionID) === 'array') { + GPS.GPSVersionID = GPS.GPSVersionID.join('.'); + } + + return GPS; + }, + + setExif: function(tag, value) { + // Right now only setting of width/height is possible + if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') {return false;} + + return setTag('exif', tag, value); + }, + + + getBinary: function() { + return data.SEGMENT(); + }, + + purge: function() { + data.init(null); + data = Tiff = null; + offsets = {}; + } + }; + }; +}); + +// Included from: src/javascript/runtime/html5/image/JPEG.js + +/** + * JPEG.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/JPEG +@private +*/ +define("moxie/runtime/html5/image/JPEG", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/html5/image/JPEGHeaders", + "moxie/runtime/html5/utils/BinaryReader", + "moxie/runtime/html5/image/ExifParser" +], function(Basic, x, JPEGHeaders, BinaryReader, ExifParser) { + + function JPEG(binstr) { + var _binstr, _br, _hm, _ep, _info, hasExif; + + function _getDimensions() { + var idx = 0, marker, length; + + // examine all through the end, since some images might have very large APP segments + while (idx <= _binstr.length) { + marker = _br.SHORT(idx += 2); + + if (marker >= 0xFFC0 && marker <= 0xFFC3) { // SOFn + idx += 5; // marker (2 bytes) + length (2 bytes) + Sample precision (1 byte) + return { + height: _br.SHORT(idx), + width: _br.SHORT(idx += 2) + }; + } + length = _br.SHORT(idx += 2); + idx += length - 2; + } + return null; + } + + _binstr = binstr; + + _br = new BinaryReader(); + _br.init(_binstr); + + // check if it is jpeg + if (_br.SHORT(0) !== 0xFFD8) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + + // backup headers + _hm = new JPEGHeaders(binstr); + + // extract exif info + _ep = new ExifParser(); + hasExif = !!_ep.init(_hm.get('app1')[0]); + + // get dimensions + _info = _getDimensions.call(this); + + Basic.extend(this, { + type: 'image/jpeg', + + size: _binstr.length, + + width: _info && _info.width || 0, + + height: _info && _info.height || 0, + + setExif: function(tag, value) { + if (!hasExif) { + return false; // or throw an exception + } + + if (Basic.typeOf(tag) === 'object') { + Basic.each(tag, function(value, tag) { + _ep.setExif(tag, value); + }); + } else { + _ep.setExif(tag, value); + } + + // update internal headers + _hm.set('app1', _ep.getBinary()); + }, + + writeHeaders: function() { + if (!arguments.length) { + // if no arguments passed, update headers internally + return (_binstr = _hm.restore(_binstr)); + } + return _hm.restore(arguments[0]); + }, + + stripHeaders: function(binstr) { + return _hm.strip(binstr); + }, + + purge: function() { + _purge.call(this); + } + }); + + if (hasExif) { + this.meta = { + tiff: _ep.TIFF(), + exif: _ep.EXIF(), + gps: _ep.GPS() + }; + } + + function _purge() { + if (!_ep || !_hm || !_br) { + return; // ignore any repeating purge requests + } + _ep.purge(); + _hm.purge(); + _br.init(null); + _binstr = _info = _hm = _ep = _br = null; + } + } + + return JPEG; +}); + +// Included from: src/javascript/runtime/html5/image/PNG.js + +/** + * PNG.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/PNG +@private +*/ +define("moxie/runtime/html5/image/PNG", [ + "moxie/core/Exceptions", + "moxie/core/utils/Basic", + "moxie/runtime/html5/utils/BinaryReader" +], function(x, Basic, BinaryReader) { + + function PNG(binstr) { + var _binstr, _br, _hm, _ep, _info; + + _binstr = binstr; + + _br = new BinaryReader(); + _br.init(_binstr); + + // check if it's png + (function() { + var idx = 0, i = 0 + , signature = [0x8950, 0x4E47, 0x0D0A, 0x1A0A] + ; + + for (i = 0; i < signature.length; i++, idx += 2) { + if (signature[i] != _br.SHORT(idx)) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + } + }()); + + function _getDimensions() { + var chunk, idx; + + chunk = _getChunkAt.call(this, 8); + + if (chunk.type == 'IHDR') { + idx = chunk.start; + return { + width: _br.LONG(idx), + height: _br.LONG(idx += 4) + }; + } + return null; + } + + function _purge() { + if (!_br) { + return; // ignore any repeating purge requests + } + _br.init(null); + _binstr = _info = _hm = _ep = _br = null; + } + + _info = _getDimensions.call(this); + + Basic.extend(this, { + type: 'image/png', + + size: _binstr.length, + + width: _info.width, + + height: _info.height, + + purge: function() { + _purge.call(this); + } + }); + + // for PNG we can safely trigger purge automatically, as we do not keep any data for later + _purge.call(this); + + function _getChunkAt(idx) { + var length, type, start, CRC; + + length = _br.LONG(idx); + type = _br.STRING(idx += 4, 4); + start = idx += 4; + CRC = _br.LONG(idx + length); + + return { + length: length, + type: type, + start: start, + CRC: CRC + }; + } + } + + return PNG; +}); + +// Included from: src/javascript/runtime/html5/image/ImageInfo.js + +/** + * ImageInfo.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/ImageInfo +@private +*/ +define("moxie/runtime/html5/image/ImageInfo", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/html5/image/JPEG", + "moxie/runtime/html5/image/PNG" +], function(Basic, x, JPEG, PNG) { + /** + Optional image investigation tool for HTML5 runtime. Provides the following features: + - ability to distinguish image type (JPEG or PNG) by signature + - ability to extract image width/height directly from it's internals, without preloading in memory (fast) + - ability to extract APP headers from JPEGs (Exif, GPS, etc) + - ability to replace width/height tags in extracted JPEG headers + - ability to restore APP headers, that were for example stripped during image manipulation + + @class ImageInfo + @constructor + @param {String} binstr Image source as binary string + */ + return function(binstr) { + var _cs = [JPEG, PNG], _img; + + // figure out the format, throw: ImageError.WRONG_FORMAT if not supported + _img = (function() { + for (var i = 0; i < _cs.length; i++) { + try { + return new _cs[i](binstr); + } catch (ex) { + // console.info(ex); + } + } + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + }()); + + Basic.extend(this, { + /** + Image Mime Type extracted from it's depths + + @property type + @type {String} + @default '' + */ + type: '', + + /** + Image size in bytes + + @property size + @type {Number} + @default 0 + */ + size: 0, + + /** + Image width extracted from image source + + @property width + @type {Number} + @default 0 + */ + width: 0, + + /** + Image height extracted from image source + + @property height + @type {Number} + @default 0 + */ + height: 0, + + /** + Sets Exif tag. Currently applicable only for width and height tags. Obviously works only with JPEGs. + + @method setExif + @param {String} tag Tag to set + @param {Mixed} value Value to assign to the tag + */ + setExif: function() {}, + + /** + Restores headers to the source. + + @method writeHeaders + @param {String} data Image source as binary string + @return {String} Updated binary string + */ + writeHeaders: function(data) { + return data; + }, + + /** + Strip all headers from the source. + + @method stripHeaders + @param {String} data Image source as binary string + @return {String} Updated binary string + */ + stripHeaders: function(data) { + return data; + }, + + /** + Dispose resources. + + @method purge + */ + purge: function() {} + }); + + Basic.extend(this, _img); + + this.purge = function() { + _img.purge(); + _img = null; + }; + }; +}); + +// Included from: src/javascript/runtime/html5/image/MegaPixel.js + +/** +(The MIT License) + +Copyright (c) 2012 Shinichi Tomita ; + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +/** + * Mega pixel image rendering library for iOS6 Safari + * + * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel), + * which causes unexpected subsampling when drawing it in canvas. + * By using this library, you can safely render the image with proper stretching. + * + * Copyright (c) 2012 Shinichi Tomita + * Released under the MIT license + */ + +/** +@class moxie/runtime/html5/image/MegaPixel +@private +*/ +define("moxie/runtime/html5/image/MegaPixel", [], function() { + + /** + * Rendering image element (with resizing) into the canvas element + */ + function renderImageToCanvas(img, canvas, options) { + var iw = img.naturalWidth, ih = img.naturalHeight; + var width = options.width, height = options.height; + var x = options.x || 0, y = options.y || 0; + var ctx = canvas.getContext('2d'); + if (detectSubsampling(img)) { + iw /= 2; + ih /= 2; + } + var d = 1024; // size of tiling canvas + var tmpCanvas = document.createElement('canvas'); + tmpCanvas.width = tmpCanvas.height = d; + var tmpCtx = tmpCanvas.getContext('2d'); + var vertSquashRatio = detectVerticalSquash(img, iw, ih); + var sy = 0; + while (sy < ih) { + var sh = sy + d > ih ? ih - sy : d; + var sx = 0; + while (sx < iw) { + var sw = sx + d > iw ? iw - sx : d; + tmpCtx.clearRect(0, 0, d, d); + tmpCtx.drawImage(img, -sx, -sy); + var dx = (sx * width / iw + x) << 0; + var dw = Math.ceil(sw * width / iw); + var dy = (sy * height / ih / vertSquashRatio + y) << 0; + var dh = Math.ceil(sh * height / ih / vertSquashRatio); + ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh); + sx += d; + } + sy += d; + } + tmpCanvas = tmpCtx = null; } /** - Constructor for the Silverlight Runtime + * Detect subsampling in loaded image. + * In iOS, larger images than 2M pixels may be subsampled in rendering. + */ + function detectSubsampling(img) { + var iw = img.naturalWidth, ih = img.naturalHeight; + if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, -iw + 1, 0); + // subsampled image becomes half smaller in rendering size. + // check alpha channel value to confirm image is covering edge pixel or not. + // if alpha value is 0 image is not covering, hence subsampled. + return ctx.getImageData(0, 0, 1, 1).data[3] === 0; + } else { + return false; + } + } - @class SilverlightRuntime - @extends Runtime - */ - function SilverlightRuntime(options) { - var I = this, initTimer; - options = Basic.extend({ xap_url: Env.xap_url }, options); + /** + * Detecting vertical squash in loaded image. + * Fixes a bug which squash image vertically while drawing into canvas for some images. + */ + function detectVerticalSquash(img, iw, ih) { + var canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = ih; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + var data = ctx.getImageData(0, 0, 1, ih).data; + // search image edge pixel position in case it is squashed vertically. + var sy = 0; + var ey = ih; + var py = ih; + while (py > sy) { + var alpha = data[(py - 1) * 4 + 3]; + if (alpha === 0) { + ey = py; + } else { + sy = py; + } + py = (ey + sy) >> 1; + } + canvas = null; + var ratio = (py / ih); + return (ratio === 0) ? 1 : ratio; + } - Runtime.call(this, options, type, { - access_binary: Runtime.capTrue, - access_image_binary: Runtime.capTrue, - display_media: Runtime.capTrue, - do_cors: Runtime.capTrue, - drag_and_drop: false, - report_upload_progress: Runtime.capTrue, - resize_image: Runtime.capTrue, - return_response_headers: function(value) { - return value && I.mode === 'client'; - }, - return_response_type: function(responseType) { - if (responseType !== 'json') { - return true; + return { + isSubsampled: detectSubsampling, + renderTo: renderImageToCanvas + }; +}); + +// Included from: src/javascript/runtime/html5/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/Image +@private +*/ +define("moxie/runtime/html5/image/Image", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/core/utils/Encode", + "moxie/file/File", + "moxie/runtime/html5/image/ImageInfo", + "moxie/runtime/html5/image/MegaPixel", + "moxie/core/utils/Mime", + "moxie/core/utils/Env" +], function(extensions, Basic, x, Encode, File, ImageInfo, MegaPixel, Mime, Env) { + + function HTML5Image() { + var me = this + , _img, _imgInfo, _canvas, _binStr, _blob + , _modified = false // is set true whenever image is modified + , _preserveHeaders = true + ; + + Basic.extend(this, { + loadFromBlob: function(blob) { + var comp = this, I = comp.getRuntime() + , asBinary = arguments.length > 1 ? arguments[1] : true + ; + + if (!I.can('access_binary')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + _blob = blob; + + if (blob.isDetached()) { + _binStr = blob.getSource(); + _preload.call(this, _binStr); + return; } else { - return !!window.JSON; + _readAsDataUrl.call(this, blob.getSource(), function(dataUrl) { + if (asBinary) { + _binStr = _toBinary(dataUrl); + } + _preload.call(comp, dataUrl); + }); } }, - return_status_code: function(code) { - return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]); + + loadFromImage: function(img, exact) { + this.meta = img.meta; + + _blob = new File(null, { + name: img.name, + size: img.size, + type: img.type + }); + + _preload.call(this, exact ? (_binStr = img.getAsBinaryString()) : img.getAsDataURL()); }, - select_file: Runtime.capTrue, - select_multiple: Runtime.capTrue, - send_binary_string: Runtime.capTrue, - send_browser_cookies: function(value) { - return value && I.mode === 'browser'; + + getInfo: function() { + var I = this.getRuntime(), info; + + if (!_imgInfo && _binStr && I.can('access_image_binary')) { + _imgInfo = new ImageInfo(_binStr); + } + + info = { + width: _getImg().width || 0, + height: _getImg().height || 0, + type: _blob.type || Mime.getFileMime(_blob.name), + size: _binStr && _binStr.length || _blob.size || 0, + name: _blob.name || '', + meta: _imgInfo && _imgInfo.meta || this.meta || {} + }; + + return info; }, - send_custom_headers: function(value) { - return value && I.mode === 'client'; + + downsize: function() { + _downsize.apply(this, arguments); }, - send_multipart: Runtime.capTrue, - slice_blob: Runtime.capTrue, - stream_upload: true, - summon_file_dialog: false, - upload_filesize: Runtime.capTrue, - use_http_method: function(methods) { - return I.mode === 'client' || !Basic.arrayDiff(methods, ['GET', 'POST']); - } - }, { - // capabilities that require specific mode - return_response_headers: function(value) { - return value ? 'client' : 'browser'; + + getAsCanvas: function() { + if (_canvas) { + _canvas.id = this.uid + '_canvas'; + } + return _canvas; }, - return_status_code: function(code) { - return Basic.arrayDiff(code, [200, 404]) ? 'client' : ['client', 'browser']; + + getAsBlob: function(type, quality) { + if (type !== this.type) { + // if different mime type requested prepare image for conversion + _downsize.call(this, this.width, this.height, false); + } + return new File(null, { + name: _blob.name || '', + type: type, + data: me.getAsBinaryString.call(this, type, quality) + }); }, - send_browser_cookies: function(value) { - return value ? 'browser' : 'client'; + + getAsDataURL: function(type) { + var quality = arguments[1] || 90; + + // if image has not been modified, return the source right away + if (!_modified) { + return _img.src; + } + + if ('image/jpeg' !== type) { + return _canvas.toDataURL('image/png'); + } else { + try { + // older Geckos used to result in an exception on quality argument + return _canvas.toDataURL('image/jpeg', quality/100); + } catch (ex) { + return _canvas.toDataURL('image/jpeg'); + } + } }, - send_custom_headers: function(value) { - return value ? 'client' : 'browser'; + + getAsBinaryString: function(type, quality) { + // if image has not been modified, return the source right away + if (!_modified) { + // if image was not loaded from binary string + if (!_binStr) { + _binStr = _toBinary(me.getAsDataURL(type, quality)); + } + return _binStr; + } + + if ('image/jpeg' !== type) { + _binStr = _toBinary(me.getAsDataURL(type, quality)); + } else { + var dataUrl; + + // if jpeg + if (!quality) { + quality = 90; + } + + try { + // older Geckos used to result in an exception on quality argument + dataUrl = _canvas.toDataURL('image/jpeg', quality/100); + } catch (ex) { + dataUrl = _canvas.toDataURL('image/jpeg'); + } + + _binStr = _toBinary(dataUrl); + + if (_imgInfo) { + _binStr = _imgInfo.stripHeaders(_binStr); + + if (_preserveHeaders) { + // update dimensions info in exif + if (_imgInfo.meta && _imgInfo.meta.exif) { + _imgInfo.setExif({ + PixelXDimension: this.width, + PixelYDimension: this.height + }); + } + + // re-inject the headers + _binStr = _imgInfo.writeHeaders(_binStr); + } + + // will be re-created from fresh on next getInfo call + _imgInfo.purge(); + _imgInfo = null; + } + } + + _modified = false; + + return _binStr; }, - use_http_method: function(methods) { - return Basic.arrayDiff(methods, ['GET', 'POST']) ? 'client' : ['client', 'browser']; + + destroy: function() { + me = null; + _purge.call(this); + this.getRuntime().getShim().removeInstance(this.uid); } }); - // minimal requirement - if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') { - this.mode = false; + function _getImg() { + if (!_canvas && !_img) { + throw new x.ImageError(x.DOMException.INVALID_STATE_ERR); + } + return _canvas || _img; } - Basic.extend(this, { - getShim: function() { - return Dom.get(this.uid).content.Moxie; - }, + function _toBinary(str) { + return Encode.atob(str.substring(str.indexOf('base64,') + 7)); + } - shimExec: function(component, action) { - var args = [].slice.call(arguments, 2); - return I.getShim().exec(this.uid, component, action, args); - }, - init : function() { - var container; + function _toDataUrl(str, type) { + return 'data:' + (type || '') + ';base64,' + Encode.btoa(str); + } - container = this.getShimContainer(); - container.innerHTML = '' + - '' + - '' + - '' + - '' + - '' + - ''; + function _preload(str) { + var comp = this; - // Init is dispatched by the shim - initTimer = setTimeout(function() { - if (I && !I.initialized) { // runtime might be already destroyed by this moment - I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); - } - }, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac) - }, + _img = new Image(); + _img.onerror = function() { + _purge.call(this); + comp.trigger('error', x.ImageError.WRONG_FORMAT); + }; + _img.onload = function() { + comp.trigger('load'); + }; - destroy: (function(destroy) { // extend default destroy method - return function() { - destroy.call(I); - clearTimeout(initTimer); // initialization check might be still onwait - options = initTimer = destroy = I = null; + _img.src = /^data:[^;]*;base64,/.test(str) ? str : _toDataUrl(str, _blob.type); + } + + + function _readAsDataUrl(file, callback) { + var comp = this, fr; + + // use FileReader if it's available + if (window.FileReader) { + fr = new FileReader(); + fr.onload = function() { + callback(this.result); }; - }(this.destroy)) + fr.onerror = function() { + comp.trigger('error', x.ImageError.WRONG_FORMAT); + }; + fr.readAsDataURL(file); + } else { + return callback(file.getAsDataURL()); + } + } - }, extensions); + function _downsize(width, height, crop, preserveHeaders) { + var self = this + , scale + , mathFn + , x = 0 + , y = 0 + , img + , destWidth + , destHeight + , orientation + ; + + _preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString()) + + // take into account orientation tag + orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1; + + if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation + // swap dimensions + var tmp = width; + width = height; + height = tmp; + } + + img = _getImg(); + + // unify dimensions + if (!crop) { + scale = Math.min(width/img.width, height/img.height); + } else { + // one of the dimensions may exceed the actual image dimensions - we need to take the smallest value + width = Math.min(width, img.width); + height = Math.min(height, img.height); + + scale = Math.max(width/img.width, height/img.height); + } + + // we only downsize here + if (scale > 1 && !crop && preserveHeaders) { + this.trigger('Resize'); + return; + } + + // prepare canvas if necessary + if (!_canvas) { + _canvas = document.createElement("canvas"); + } + + // calculate dimensions of proportionally resized image + destWidth = Math.round(img.width * scale); + destHeight = Math.round(img.height * scale); + + // scale image and canvas + if (crop) { + _canvas.width = width; + _canvas.height = height; + + // if dimensions of the resulting image still larger than canvas, center it + if (destWidth > width) { + x = Math.round((destWidth - width) / 2); + } + + if (destHeight > height) { + y = Math.round((destHeight - height) / 2); + } + } else { + _canvas.width = destWidth; + _canvas.height = destHeight; + } + + // rotate if required, according to orientation tag + if (!_preserveHeaders) { + _rotateToOrientaion(_canvas.width, _canvas.height, orientation); + } + + _drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight); + + this.width = _canvas.width; + this.height = _canvas.height; + + _modified = true; + self.trigger('Resize'); + } + + + function _drawToCanvas(img, canvas, x, y, w, h) { + if (Env.OS === 'iOS') { + // avoid squish bug in iOS6 + MegaPixel.renderTo(img, canvas, { width: w, height: h, x: x, y: y }); + } else { + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, x, y, w, h); + } + } + + + /** + * Transform canvas coordination according to specified frame size and orientation + * Orientation value is from EXIF tag + * @author Shinichi Tomita + */ + function _rotateToOrientaion(width, height, orientation) { + switch (orientation) { + case 5: + case 6: + case 7: + case 8: + _canvas.width = height; + _canvas.height = width; + break; + default: + _canvas.width = width; + _canvas.height = height; + } + + /** + 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. + 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. + 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. + 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. + 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. + 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. + 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. + 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. + */ + + var ctx = _canvas.getContext('2d'); + switch (orientation) { + case 2: + // horizontal flip + ctx.translate(width, 0); + ctx.scale(-1, 1); + break; + case 3: + // 180 rotate left + ctx.translate(width, height); + ctx.rotate(Math.PI); + break; + case 4: + // vertical flip + ctx.translate(0, height); + ctx.scale(1, -1); + break; + case 5: + // vertical flip + 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.scale(1, -1); + break; + case 6: + // 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.translate(0, -height); + break; + case 7: + // horizontal flip + 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.translate(width, -height); + ctx.scale(-1, 1); + break; + case 8: + // 90 rotate left + ctx.rotate(-0.5 * Math.PI); + ctx.translate(-width, 0); + break; + } + } + + + function _purge() { + if (_imgInfo) { + _imgInfo.purge(); + _imgInfo = null; + } + _binStr = _img = _canvas = _blob = null; + _modified = false; + } } - Runtime.addConstructor(type, SilverlightRuntime); - - return extensions; + return (extensions.Image = HTML5Image); }); -// Included from: src/javascript/runtime/silverlight/file/Blob.js +// Included from: src/javascript/runtime/html4/image/Image.js /** - * Blob.js + * Image.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. @@ -7058,129 +8508,17 @@ define("moxie/runtime/silverlight/Runtime", [ */ /** -@class moxie/runtime/silverlight/file/Blob +@class moxie/runtime/html4/image/Image @private */ -define("moxie/runtime/silverlight/file/Blob", [ - "moxie/runtime/silverlight/Runtime", - "moxie/core/utils/Basic", - "moxie/runtime/flash/file/Blob" -], function(extensions, Basic, Blob) { - return (extensions.Blob = Basic.extend({}, Blob)); +define("moxie/runtime/html4/image/Image", [ + "moxie/runtime/html4/Runtime", + "moxie/runtime/html5/image/Image" +], function(extensions, Image) { + return (extensions.Image = Image); }); -// Included from: src/javascript/runtime/silverlight/file/FileInput.js - -/** - * FileInput.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/file/FileInput -@private -*/ -define("moxie/runtime/silverlight/file/FileInput", [ - "moxie/runtime/silverlight/Runtime" -], function(extensions) { - - var FileInput = { - init: function(options) { - - function toFilters(accept) { - var filter = ''; - for (var i = 0; i < accept.length; i++) { - filter += (filter !== '' ? '|' : '') + accept[i].title + " | *." + accept[i].extensions.replace(/,/g, ';*.'); - } - return filter; - } - - this.getRuntime().shimExec.call(this, 'FileInput', 'init', toFilters(options.accept), options.name, options.multiple); - this.trigger('ready'); - } - }; - - return (extensions.FileInput = FileInput); -}); - -// Included from: src/javascript/runtime/silverlight/file/FileReader.js - -/** - * FileReader.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/file/FileReader -@private -*/ -define("moxie/runtime/silverlight/file/FileReader", [ - "moxie/runtime/silverlight/Runtime", - "moxie/core/utils/Basic", - "moxie/runtime/flash/file/FileReader" -], function(extensions, Basic, FileReader) { - return (extensions.FileReader = Basic.extend({}, FileReader)); -}); - -// Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js - -/** - * FileReaderSync.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/file/FileReaderSync -@private -*/ -define("moxie/runtime/silverlight/file/FileReaderSync", [ - "moxie/runtime/silverlight/Runtime", - "moxie/core/utils/Basic", - "moxie/runtime/flash/file/FileReaderSync" -], function(extensions, Basic, FileReaderSync) { - return (extensions.FileReaderSync = Basic.extend({}, FileReaderSync)); -}); - -// Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js - -/** - * XMLHttpRequest.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/xhr/XMLHttpRequest -@private -*/ -define("moxie/runtime/silverlight/xhr/XMLHttpRequest", [ - "moxie/runtime/silverlight/Runtime", - "moxie/core/utils/Basic", - "moxie/runtime/flash/xhr/XMLHttpRequest" -], function(extensions, Basic, XMLHttpRequest) { - return (extensions.XMLHttpRequest = Basic.extend({}, XMLHttpRequest)); -}); - -expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/core/utils/Events"]); +expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"]); })(this);/** * o.js * @@ -7231,477 +8569,3 @@ Globally exposed namespace with the most frequently used public classes and hand } return o; })(this); -;webshim.register('filereader', function($, webshim, window, document, undefined, featureOptions){ - "use strict"; - var mOxie, moxie, hasXDomain; - var FormData = $.noop; - var sel = 'input[type="file"].ws-filereader'; - var loadMoxie = function (){ - webshim.loader.loadList(['moxie']); - }; - var _createFilePicker = function(){ - var $input, picker, $parent, onReset; - var input = this; - - if(webshim.implement(input, 'filepicker')){ - - input = this; - $input = $(this); - $parent = $input.parent(); - onReset = function(){ - if(!input.value){ - $input.prop('value', ''); - } - }; - - $input.attr('tabindex', '-1').on('mousedown.filereaderwaiting click.filereaderwaiting', false); - $parent.addClass('ws-loading'); - picker = new mOxie.FileInput({ - browse_button: this, - accept: $.prop(this, 'accept'), - multiple: $.prop(this, 'multiple') - }); - - $input.jProp('form').on('reset', function(){ - setTimeout(onReset); - }); - picker.onready = function(){ - $input.off('.fileraderwaiting'); - $parent.removeClass('ws-waiting'); - }; - - picker.onchange = function(e){ - webshim.data(input, 'fileList', e.target.files); - $input.trigger('change'); - }; - picker.onmouseenter = function(){ - $input.trigger('mouseover'); - $parent.addClass('ws-mouseenter'); - }; - picker.onmouseleave = function(){ - $input.trigger('mouseout'); - $parent.removeClass('ws-mouseenter'); - }; - picker.onmousedown = function(){ - $input.trigger('mousedown'); - $parent.addClass('ws-active'); - }; - picker.onmouseup = function(){ - $input.trigger('mouseup'); - $parent.removeClass('ws-active'); - }; - - webshim.data(input, 'filePicker', picker); - - webshim.ready('WINDOWLOAD', function(){ - var lastWidth; - $input.onWSOff('updateshadowdom', function(){ - var curWitdth = input.offsetWidth; - if(curWitdth && lastWidth != curWitdth){ - lastWidth = curWitdth; - picker.refresh(); - } - }); - }); - - webshim.addShadowDom(); - - picker.init(); - if(input.disabled){ - picker.disable(true); - } - } - }; - var getFileNames = function(file){ - return file.name; - }; - var createFilePicker = function(){ - var elem = this; - loadMoxie(); - $(elem) - .on('mousedown.filereaderwaiting click.filereaderwaiting', false) - .parent() - .addClass('ws-loading') - ; - webshim.ready('moxie', function(){ - createFilePicker.call(elem); - }); - }; - var noxhr = /^(?:script|jsonp)$/i; - var notReadyYet = function(){ - loadMoxie(); - webshim.error('filereader/formdata not ready yet. please wait for moxie to load `webshim.ready("moxie", callbackFn);`` or wait for the first change event on input[type="file"].ws-filereader.') - }; - var inputValueDesc = webshim.defineNodeNameProperty('input', 'value', { - prop: { - get: function(){ - var fileList = webshim.data(this, 'fileList'); - - if(fileList && fileList.map){ - return fileList.map(getFileNames).join(', '); - } - - return inputValueDesc.prop._supget.call(this); - } - } - } - ); - var shimMoxiePath = webshim.cfg.basePath+'moxie/'; - var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf/moxie.xap on your server an configure filereader options: "swfpath"/"xappath"'; - var testMoxie = function(options){ - return (options.wsType == 'moxie' || (options.data && options.data instanceof mOxie.FormData) || (options.crossDomain && $.support.cors !== false && hasXDomain != 'no' && !noxhr.test(options.dataType || ''))); - }; - var createMoxieTransport = function (options){ - - if(testMoxie(options)){ - var ajax; - webshim.info('moxie transfer used for $.ajax'); - if(hasXDomain == 'no'){ - webshim.error(crossXMLMessage); - } - return { - send: function( headers, completeCallback ) { - - var proressEvent = function(obj, name){ - if(options[name]){ - var called = false; - ajax.addEventListener('load', function(e){ - if(!called){ - options[name]({type: 'progress', lengthComputable: true, total: 1, loaded: 1}); - } else if(called.lengthComputable && called.total > called.loaded){ - options[name]({type: 'progress', lengthComputable: true, total: called.total, loaded: called.total}); - } - }); - obj.addEventListener('progress', function(e){ - called = e; - options[name](e); - }); - } - }; - ajax = new moxie.xhr.XMLHttpRequest(); - - ajax.open(options.type, options.url, options.async, options.username, options.password); - - proressEvent(ajax.upload, featureOptions.uploadprogress); - proressEvent(ajax.upload, featureOptions.progress); - - ajax.addEventListener('load', function(e){ - var responses = { - text: ajax.responseText, - xml: ajax.responseXML - }; - completeCallback(ajax.status, ajax.statusText, responses, ajax.getAllResponseHeaders()); - }); - - if(options.xhrFields && options.xhrFields.withCredentials){ - ajax.withCredentials = true; - } - - if(options.timeout){ - ajax.timeout = options.timeout; - } - - $.each(headers, function(name, value){ - ajax.setRequestHeader(name, value); - }); - - - ajax.send(options.data); - - }, - abort: function() { - if(ajax){ - ajax.abort(); - } - } - }; - } - }; - var transports = { - //based on script: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest - xdomain: (function(){ - var httpRegEx = /^https?:\/\//i; - var getOrPostRegEx = /^get|post$/i; - var sameSchemeRegEx = new RegExp('^'+location.protocol, 'i'); - return function(options, userOptions, jqXHR) { - - // Only continue if the request is: asynchronous, uses GET or POST method, has HTTP or HTTPS protocol, and has the same scheme as the calling page - if (!options.crossDomain || options.username || (options.xhrFields && options.xhrFields.withCredentials) || !options.async || !getOrPostRegEx.test(options.type) || !httpRegEx.test(options.url) || !sameSchemeRegEx.test(options.url) || (options.data && options.data instanceof mOxie.FormData) || noxhr.test(options.dataType || '')) { - return; - } - - var xdr = null; - webshim.info('xdomain transport used.'); - - return { - send: function(headers, complete) { - var postData = ''; - var userType = (userOptions.dataType || '').toLowerCase(); - - xdr = new XDomainRequest(); - if (/^\d+$/.test(userOptions.timeout)) { - xdr.timeout = userOptions.timeout; - } - - xdr.ontimeout = function() { - complete(500, 'timeout'); - }; - - xdr.onload = function() { - var allResponseHeaders = 'Content-Length: ' + xdr.responseText.length + '\r\nContent-Type: ' + xdr.contentType; - var status = { - code: xdr.status || 200, - message: xdr.statusText || 'OK' - }; - var responses = { - text: xdr.responseText, - xml: xdr.responseXML - }; - try { - if (userType === 'html' || /text\/html/i.test(xdr.contentType)) { - responses.html = xdr.responseText; - } else if (userType === 'json' || (userType !== 'text' && /\/json/i.test(xdr.contentType))) { - try { - responses.json = $.parseJSON(xdr.responseText); - } catch(e) { - - } - } else if (userType === 'xml' && !xdr.responseXML) { - var doc; - try { - doc = new ActiveXObject('Microsoft.XMLDOM'); - doc.async = false; - doc.loadXML(xdr.responseText); - } catch(e) { - - } - - responses.xml = doc; - } - } catch(parseMessage) {} - complete(status.code, status.message, responses, allResponseHeaders); - }; - - // set an empty handler for 'onprogress' so requests don't get aborted - xdr.onprogress = function(){}; - xdr.onerror = function() { - complete(500, 'error', { - text: xdr.responseText - }); - }; - - if (userOptions.data) { - postData = ($.type(userOptions.data) === 'string') ? userOptions.data : $.param(userOptions.data); - } - xdr.open(options.type, options.url); - xdr.send(postData); - }, - abort: function() { - if (xdr) { - xdr.abort(); - } - } - }; - }; - })(), - moxie: function (options, originalOptions, jqXHR){ - if(testMoxie(options)){ - loadMoxie(options); - var ajax; - - var tmpTransport = { - send: function( headers, completeCallback ) { - ajax = true; - webshim.ready('moxie', function(){ - if(ajax){ - ajax = createMoxieTransport(options, originalOptions, jqXHR); - tmpTransport.send = ajax.send; - tmpTransport.abort = ajax.abort; - ajax.send(headers, completeCallback); - } - }); - }, - abort: function() { - ajax = false; - } - }; - return tmpTransport; - } - } - }; - - if(!featureOptions.progress){ - featureOptions.progress = 'onprogress'; - } - - if(!featureOptions.uploadprogress){ - featureOptions.uploadprogress = 'onuploadprogress'; - } - - if(!featureOptions.swfpath){ - featureOptions.swfpath = shimMoxiePath+'flash/Moxie.min.swf'; - } - if(!featureOptions.xappath){ - featureOptions.xappath = shimMoxiePath+'silverlight/Moxie.min.xap'; - } - - if($.support.cors !== false || !window.XDomainRequest){ - delete transports.xdomain; - } - - - $.ajaxTransport("+*", function( options, originalOptions, jqXHR ) { - var ajax, type; - - if(options.wsType || transports[transports]){ - ajax = transports[transports](options, originalOptions, jqXHR); - } - if(!ajax){ - for(type in transports){ - ajax = transports[type](options, originalOptions, jqXHR); - if(ajax){break;} - } - } - return ajax; - }); - - webshim.defineNodeNameProperty('input', 'files', { - prop: { - writeable: false, - get: function(){ - if(this.type != 'file'){return null;} - if(!$(this).hasClass('ws-filereader')){ - webshim.info("please add the 'ws-filereader' class to your input[type='file'] to implement files-property"); - } - return webshim.data(this, 'fileList') || []; - } - } - } - ); - - webshim.reflectProperties(['input'], ['accept']); - - if($('').prop('multiple') == null){ - webshim.defineNodeNamesBooleanProperty(['input'], ['multiple']); - } - - webshim.onNodeNamesPropertyModify('input', 'disabled', function(value, boolVal, type){ - var picker = webshim.data(this, 'filePicker'); - if(picker){ - picker.disable(boolVal); - } - }); - - webshim.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){ - if(value === '' && this.type == 'file' && $(this).hasClass('ws-filereader')){ - webshim.data(this, 'fileList', []); - } - }); - - - window.FileReader = notReadyYet; - window.FormData = notReadyYet; - webshim.ready('moxie', function(){ - var wsMimes = 'application/xml,xml'; - moxie = window.moxie; - mOxie = window.mOxie; - - mOxie.Env.swf_url = featureOptions.swfpath; - mOxie.Env.xap_url = featureOptions.xappath; - - window.FileReader = mOxie.FileReader; - - window.FormData = function(form){ - var appendData, i, len, files, fileI, fileLen, inputName; - var moxieData = new mOxie.FormData(); - if(form && $.nodeName(form, 'form')){ - appendData = $(form).serializeArray(); - for(i = 0; i < appendData.length; i++){ - if(Array.isArray(appendData[i].value)){ - appendData[i].value.forEach(function(val){ - moxieData.append(appendData[i].name, val); - }); - } else { - moxieData.append(appendData[i].name, appendData[i].value); - } - } - - appendData = form.querySelectorAll('input[type="file"][name]'); - - for(i = 0, len = appendData.length; i < appendData.length; i++){ - inputName = appendData[i].name; - if(inputName && !$(appendData[i]).is(':disabled')){ - files = $.prop(appendData[i], 'files') || []; - if(files.length){ - if(files.length > 1 || (moxieData.hasBlob && moxieData.hasBlob())){ - webshim.error('FormData shim can only handle one file per ajax. Use multiple ajax request. One per file.'); - } - for(fileI = 0, fileLen = files.length; fileI < fileLen; fileI++){ - moxieData.append(inputName, files[fileI]); - } - } - } - } - } - - return moxieData; - }; - FormData = window.FormData; - - createFilePicker = _createFilePicker; - transports.moxie = createMoxieTransport; - - featureOptions.mimeTypes = (featureOptions.mimeTypes) ? wsMimes+','+featureOptions.mimeTypes : wsMimes; - try { - mOxie.Mime.addMimeType(featureOptions.mimeTypes); - } catch(e){ - webshim.warn('mimetype to moxie error: '+e); - } - - }); - - webshim.addReady(function(context, contextElem){ - $(context.querySelectorAll(sel)).add(contextElem.filter(sel)).each(createFilePicker); - }); - webshim.ready('WINDOWLOAD', loadMoxie); - - if(webshim.cfg.debug !== false && featureOptions.swfpath.indexOf((location.protocol+'//'+location.hostname)) && featureOptions.swfpath.indexOf(('https://'+location.hostname))){ - webshim.ready('WINDOWLOAD', function(){ - - var printMessage = function(){ - if(hasXDomain == 'no'){ - webshim.error(crossXMLMessage); - } - }; - - try { - hasXDomain = sessionStorage.getItem('wsXdomain.xml'); - } catch(e){} - printMessage(); - if(hasXDomain == null){ - try { - $.ajax({ - url: 'crossdomain.xml', - type: 'HEAD', - dataType: 'xml', - success: function(){ - hasXDomain = 'yes'; - }, - error: function(){ - hasXDomain = 'no'; - }, - complete: function(){ - try { - sessionStorage.setItem('wsXdomain.xml', hasXDomain); - } catch(e){} - printMessage(); - } - }); - } catch(e){} - } - }); - } - if(document.readyState == 'complete'){ - webshims.isReady('WINDOWLOAD', true); - } -}); diff --git a/public/webshims/shims/moxie/js/moxie.js b/public/webshims/shims/moxie/js/moxie-swf.js similarity index 81% rename from public/webshims/shims/moxie/js/moxie.js rename to public/webshims/shims/moxie/js/moxie-swf.js index 500fb2cd..d5fd8281 100644 --- a/public/webshims/shims/moxie/js/moxie.js +++ b/public/webshims/shims/moxie/js/moxie-swf.js @@ -5131,6 +5131,749 @@ define("moxie/xhr/XMLHttpRequest", [ return XMLHttpRequest; }); +// Included from: src/javascript/runtime/Transporter.js + +/** + * Transporter.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/runtime/Transporter", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Encode", + "moxie/runtime/RuntimeClient", + "moxie/core/EventTarget" +], function(Basic, Encode, RuntimeClient, EventTarget) { + function Transporter() { + var mod, _runtime, _data, _size, _pos, _chunk_size; + + RuntimeClient.call(this); + + Basic.extend(this, { + uid: Basic.guid('uid_'), + + state: Transporter.IDLE, + + result: null, + + transport: function(data, type, options) { + var self = this; + + options = Basic.extend({ + chunk_size: 204798 + }, options); + + // should divide by three, base64 requires this + if ((mod = options.chunk_size % 3)) { + options.chunk_size += 3 - mod; + } + + _chunk_size = options.chunk_size; + + _reset.call(this); + _data = data; + _size = data.length; + + if (Basic.typeOf(options) === 'string' || options.ruid) { + _run.call(self, type, this.connectRuntime(options)); + } else { + // we require this to run only once + var cb = function(e, runtime) { + self.unbind("RuntimeInit", cb); + _run.call(self, type, runtime); + }; + this.bind("RuntimeInit", cb); + this.connectRuntime(options); + } + }, + + abort: function() { + var self = this; + + self.state = Transporter.IDLE; + if (_runtime) { + _runtime.exec.call(self, 'Transporter', 'clear'); + self.trigger("TransportingAborted"); + } + + _reset.call(self); + }, + + + destroy: function() { + this.unbindAll(); + _runtime = null; + this.disconnectRuntime(); + _reset.call(this); + } + }); + + function _reset() { + _size = _pos = 0; + _data = this.result = null; + } + + function _run(type, runtime) { + var self = this; + + _runtime = runtime; + + //self.unbind("RuntimeInit"); + + self.bind("TransportingProgress", function(e) { + _pos = e.loaded; + + if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) { + _transport.call(self); + } + }, 999); + + self.bind("TransportingComplete", function() { + _pos = _size; + self.state = Transporter.DONE; + _data = null; // clean a bit + self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || ''); + }, 999); + + self.state = Transporter.BUSY; + self.trigger("TransportingStarted"); + _transport.call(self); + } + + function _transport() { + var self = this, + chunk, + bytesLeft = _size - _pos; + + if (_chunk_size > bytesLeft) { + _chunk_size = bytesLeft; + } + + chunk = Encode.btoa(_data.substr(_pos, _chunk_size)); + _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size); + } + } + + Transporter.IDLE = 0; + Transporter.BUSY = 1; + Transporter.DONE = 2; + + Transporter.prototype = EventTarget.instance; + + return Transporter; +}); + +// Included from: src/javascript/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/image/Image", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/Exceptions", + "moxie/file/FileReaderSync", + "moxie/xhr/XMLHttpRequest", + "moxie/runtime/Runtime", + "moxie/runtime/RuntimeClient", + "moxie/runtime/Transporter", + "moxie/core/utils/Env", + "moxie/core/EventTarget", + "moxie/file/Blob", + "moxie/file/File", + "moxie/core/utils/Encode" +], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) { + /** + Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data. + + @class Image + @constructor + @extends EventTarget + */ + var dispatches = [ + 'progress', + + /** + Dispatched when loading is complete. + + @event load + @param {Object} event + */ + 'load', + + 'error', + + /** + Dispatched when resize operation is complete. + + @event resize + @param {Object} event + */ + 'resize', + + /** + Dispatched when visual representation of the image is successfully embedded + into the corresponsing container. + + @event embedded + @param {Object} event + */ + 'embedded' + ]; + + function Image() { + RuntimeClient.call(this); + + Basic.extend(this, { + /** + Unique id of the component + + @property uid + @type {String} + */ + uid: Basic.guid('uid_'), + + /** + Unique id of the connected runtime, if any. + + @property ruid + @type {String} + */ + ruid: null, + + /** + Name of the file, that was used to create an image, if available. If not equals to empty string. + + @property name + @type {String} + @default "" + */ + name: "", + + /** + Size of the image in bytes. Actual value is set only after image is preloaded. + + @property size + @type {Number} + @default 0 + */ + size: 0, + + /** + Width of the image. Actual value is set only after image is preloaded. + + @property width + @type {Number} + @default 0 + */ + width: 0, + + /** + Height of the image. Actual value is set only after image is preloaded. + + @property height + @type {Number} + @default 0 + */ + height: 0, + + /** + Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded. + + @property type + @type {String} + @default "" + */ + type: "", + + /** + Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded. + + @property meta + @type {Object} + @default {} + */ + meta: {}, + + /** + Alias for load method, that takes another mOxie.Image object as a source (see load). + + @method clone + @param {Image} src Source for the image + @param {Boolean} [exact=false] Whether to activate in-depth clone mode + */ + clone: function() { + this.load.apply(this, arguments); + }, + + /** + Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File, + native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL, + Image will be downloaded from remote destination and loaded in memory. + + @example + var img = new mOxie.Image(); + img.onload = function() { + var blob = img.getAsBlob(); + + var formData = new mOxie.FormData(); + formData.append('file', blob); + + var xhr = new mOxie.XMLHttpRequest(); + xhr.onload = function() { + // upload complete + }; + xhr.open('post', 'upload.php'); + xhr.send(formData); + }; + img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg) + + + @method load + @param {Image|Blob|File|String} src Source for the image + @param {Boolean|Object} [mixed] + */ + load: function() { + // this is here because to bind properly we need an uid first, which is created above + this.bind('Load Resize', function() { + _updateInfo.call(this); + }, 999); + + this.convertEventPropsToHandlers(dispatches); + + _load.apply(this, arguments); + }, + + /** + Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions. + + @method downsize + @param {Number} width Resulting width + @param {Number} [height=width] Resulting height (optional, if not supplied will default to width) + @param {Boolean} [crop=false] Whether to crop the image to exact dimensions + @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) + */ + downsize: function(opts) { + var defaults = { + width: this.width, + height: this.height, + crop: false, + preserveHeaders: true + }; + + if (typeof(opts) === 'object') { + opts = Basic.extend(defaults, opts); + } else { + opts = Basic.extend(defaults, { + width: arguments[0], + height: arguments[1], + crop: arguments[2], + preserveHeaders: arguments[3] + }); + } + + try { + if (!this.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // no way to reliably intercept the crash due to high resolution, so we simply avoid it + if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { + throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); + } + + this.getRuntime().exec.call(this, 'Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders); + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + }, + + /** + Alias for downsize(width, height, true). (see downsize) + + @method crop + @param {Number} width Resulting width + @param {Number} [height=width] Resulting height (optional, if not supplied will default to width) + @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) + */ + crop: function(width, height, preserveHeaders) { + this.downsize(width, height, true, preserveHeaders); + }, + + getAsCanvas: function() { + if (!Env.can('create_canvas')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + var runtime = this.connectRuntime(this.ruid); + return runtime.exec.call(this, 'Image', 'getAsCanvas'); + }, + + /** + Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsBlob + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {Blob} Image as Blob + */ + getAsBlob: function(type, quality) { + if (!this.size) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + if (!type) { + type = 'image/jpeg'; + } + + if (type === 'image/jpeg' && !quality) { + quality = 90; + } + + return this.getRuntime().exec.call(this, 'Image', 'getAsBlob', type, quality); + }, + + /** + Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsDataURL + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {String} Image as dataURL string + */ + getAsDataURL: function(type, quality) { + if (!this.size) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + return this.getRuntime().exec.call(this, 'Image', 'getAsDataURL', type, quality); + }, + + /** + Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsBinaryString + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {String} Image as binary string + */ + getAsBinaryString: function(type, quality) { + var dataUrl = this.getAsDataURL(type, quality); + return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)); + }, + + /** + Embeds a visual representation of the image into the specified node. Depending on the runtime, + it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare, + can be used in legacy browsers that do not have canvas or proper dataURI support). + + @method embed + @param {DOMElement} el DOM element to insert the image object into + @param {Object} [options] + @param {Number} [options.width] The width of an embed (defaults to the image width) + @param {Number} [options.height] The height of an embed (defaults to the image height) + @param {String} [type="image/jpeg"] Mime type + @param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg + @param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions + */ + embed: function(el) { + var self = this + , imgCopy + , type, quality, crop + , options = arguments[1] || {} + , width = this.width + , height = this.height + , runtime // this has to be outside of all the closures to contain proper runtime + ; + + function onResize() { + // if possible, embed a canvas element directly + if (Env.can('create_canvas')) { + var canvas = imgCopy.getAsCanvas(); + if (canvas) { + el.appendChild(canvas); + canvas = null; + imgCopy.destroy(); + self.trigger('embedded'); + return; + } + } + + var dataUrl = imgCopy.getAsDataURL(type, quality); + if (!dataUrl) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + + if (Env.can('use_data_uri_of', dataUrl.length)) { + el.innerHTML = ''; + imgCopy.destroy(); + self.trigger('embedded'); + } else { + var tr = new Transporter(); + + tr.bind("TransportingComplete", function() { + runtime = self.connectRuntime(this.result.ruid); + + self.bind("Embedded", function() { + // position and size properly + Basic.extend(runtime.getShimContainer().style, { + //position: 'relative', + top: '0px', + left: '0px', + width: imgCopy.width + 'px', + height: imgCopy.height + 'px' + }); + + // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's + // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and + // sometimes 8 and they do not have this problem, we can comment this for now + /*tr.bind("RuntimeInit", function(e, runtime) { + tr.destroy(); + runtime.destroy(); + onResize.call(self); // re-feed our image data + });*/ + + runtime = null; + }, 999); + + runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height); + imgCopy.destroy(); + }); + + tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, Basic.extend({}, options, { + required_caps: { + display_media: true + }, + runtime_order: 'flash,silverlight', + container: el + })); + } + } + + try { + if (!(el = Dom.get(el))) { + throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR); + } + + if (!this.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { + throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); + } + + type = options.type || this.type || 'image/jpeg'; + quality = options.quality || 90; + crop = Basic.typeOf(options.crop) !== 'undefined' ? options.crop : false; + + // figure out dimensions for the thumb + if (options.width) { + width = options.width; + height = options.height || width; + } else { + // if container element has measurable dimensions, use them + var dimensions = Dom.getSize(el); + if (dimensions.w && dimensions.h) { // both should be > 0 + width = dimensions.w; + height = dimensions.h; + } + } + + imgCopy = new Image(); + + imgCopy.bind("Resize", function() { + onResize.call(self); + }); + + imgCopy.bind("Load", function() { + imgCopy.downsize(width, height, crop, false); + }); + + imgCopy.clone(this, false); + + return imgCopy; + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + }, + + /** + Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object. + + @method destroy + */ + destroy: function() { + if (this.ruid) { + this.getRuntime().exec.call(this, 'Image', 'destroy'); + this.disconnectRuntime(); + } + this.unbindAll(); + } + }); + + + function _updateInfo(info) { + if (!info) { + info = this.getRuntime().exec.call(this, 'Image', 'getInfo'); + } + + this.size = info.size; + this.width = info.width; + this.height = info.height; + this.type = info.type; + this.meta = info.meta; + + // update file name, only if empty + if (this.name === '') { + this.name = info.name; + } + } + + + function _load(src) { + var srcType = Basic.typeOf(src); + + try { + // if source is Image + if (src instanceof Image) { + if (!src.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + _loadFromImage.apply(this, arguments); + } + // if source is o.Blob/o.File + else if (src instanceof Blob) { + if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + _loadFromBlob.apply(this, arguments); + } + // if native blob/file + else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) { + _load.call(this, new File(null, src), arguments[1]); + } + // if String + else if (srcType === 'string') { + // if dataUrl String + if (/^data:[^;]*;base64,/.test(src)) { + _load.call(this, new Blob(null, { data: src }), arguments[1]); + } + // else assume Url, either relative or absolute + else { + _loadFromUrl.apply(this, arguments); + } + } + // if source seems to be an img node + else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') { + _load.call(this, src.src, arguments[1]); + } + else { + throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR); + } + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + } + + + function _loadFromImage(img, exact) { + var runtime = this.connectRuntime(img.ruid); + this.ruid = runtime.uid; + runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact)); + } + + + function _loadFromBlob(blob, options) { + var self = this; + + self.name = blob.name || ''; + + function exec(runtime) { + self.ruid = runtime.uid; + runtime.exec.call(self, 'Image', 'loadFromBlob', blob); + } + + if (blob.isDetached()) { + this.bind('RuntimeInit', function(e, runtime) { + exec(runtime); + }); + + // convert to object representation + if (options && typeof(options.required_caps) === 'string') { + options.required_caps = Runtime.parseCaps(options.required_caps); + } + + this.connectRuntime(Basic.extend({ + required_caps: { + access_image_binary: true, + resize_image: true + } + }, options)); + } else { + exec(this.connectRuntime(blob.ruid)); + } + } + + + function _loadFromUrl(url, options) { + var self = this, xhr; + + xhr = new XMLHttpRequest(); + + xhr.open('get', url); + xhr.responseType = 'blob'; + + xhr.onprogress = function(e) { + self.trigger(e); + }; + + xhr.onload = function() { + _loadFromBlob.call(self, xhr.response, true); + }; + + xhr.onerror = function(e) { + self.trigger(e); + }; + + xhr.onloadend = function() { + xhr.destroy(); + }; + + xhr.bind('RuntimeError', function(e, err) { + self.trigger('RuntimeError', err); + }); + + xhr.send(null, options); + } + } + + // virtual world will crash on you if image has a resolution higher than this: + Image.MAX_RESIZE_WIDTH = 6500; + Image.MAX_RESIZE_HEIGHT = 6500; + + Image.prototype = EventTarget.instance; + + return Image; +}); + // Included from: src/javascript/runtime/flash/Runtime.js /** @@ -5561,143 +6304,6 @@ define("moxie/runtime/flash/file/FileReaderSync", [ return (extensions.FileReaderSync = FileReaderSync); }); -// Included from: src/javascript/runtime/Transporter.js - -/** - * Transporter.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -define("moxie/runtime/Transporter", [ - "moxie/core/utils/Basic", - "moxie/core/utils/Encode", - "moxie/runtime/RuntimeClient", - "moxie/core/EventTarget" -], function(Basic, Encode, RuntimeClient, EventTarget) { - function Transporter() { - var mod, _runtime, _data, _size, _pos, _chunk_size; - - RuntimeClient.call(this); - - Basic.extend(this, { - uid: Basic.guid('uid_'), - - state: Transporter.IDLE, - - result: null, - - transport: function(data, type, options) { - var self = this; - - options = Basic.extend({ - chunk_size: 204798 - }, options); - - // should divide by three, base64 requires this - if ((mod = options.chunk_size % 3)) { - options.chunk_size += 3 - mod; - } - - _chunk_size = options.chunk_size; - - _reset.call(this); - _data = data; - _size = data.length; - - if (Basic.typeOf(options) === 'string' || options.ruid) { - _run.call(self, type, this.connectRuntime(options)); - } else { - // we require this to run only once - var cb = function(e, runtime) { - self.unbind("RuntimeInit", cb); - _run.call(self, type, runtime); - }; - this.bind("RuntimeInit", cb); - this.connectRuntime(options); - } - }, - - abort: function() { - var self = this; - - self.state = Transporter.IDLE; - if (_runtime) { - _runtime.exec.call(self, 'Transporter', 'clear'); - self.trigger("TransportingAborted"); - } - - _reset.call(self); - }, - - - destroy: function() { - this.unbindAll(); - _runtime = null; - this.disconnectRuntime(); - _reset.call(this); - } - }); - - function _reset() { - _size = _pos = 0; - _data = this.result = null; - } - - function _run(type, runtime) { - var self = this; - - _runtime = runtime; - - //self.unbind("RuntimeInit"); - - self.bind("TransportingProgress", function(e) { - _pos = e.loaded; - - if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) { - _transport.call(self); - } - }, 999); - - self.bind("TransportingComplete", function() { - _pos = _size; - self.state = Transporter.DONE; - _data = null; // clean a bit - self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || ''); - }, 999); - - self.state = Transporter.BUSY; - self.trigger("TransportingStarted"); - _transport.call(self); - } - - function _transport() { - var self = this, - chunk, - bytesLeft = _size - _pos; - - if (_chunk_size > bytesLeft) { - _chunk_size = bytesLeft; - } - - chunk = Encode.btoa(_data.substr(_pos, _chunk_size)); - _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size); - } - } - - Transporter.IDLE = 0; - Transporter.BUSY = 1; - Transporter.DONE = 2; - - Transporter.prototype = EventTarget.instance; - - return Transporter; -}); - // Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js /** @@ -5847,10 +6453,10 @@ define("moxie/runtime/flash/xhr/XMLHttpRequest", [ return (extensions.XMLHttpRequest = XMLHttpRequest); }); -// Included from: src/javascript/runtime/html4/Runtime.js +// Included from: src/javascript/runtime/flash/runtime/Transporter.js /** - * Runtime.js + * Transporter.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. @@ -5859,273 +6465,34 @@ define("moxie/runtime/flash/xhr/XMLHttpRequest", [ * Contributing: http://www.plupload.com/contributing */ -/*global File:true */ - /** -Defines constructor for HTML4 runtime. - -@class moxie/runtime/html4/Runtime +@class moxie/runtime/flash/runtime/Transporter @private */ -define("moxie/runtime/html4/Runtime", [ - "moxie/core/utils/Basic", - "moxie/core/Exceptions", - "moxie/runtime/Runtime", - "moxie/core/utils/Env" -], function(Basic, x, Runtime, Env) { - - var type = 'html4', extensions = {}; +define("moxie/runtime/flash/runtime/Transporter", [ + "moxie/runtime/flash/Runtime", + "moxie/file/Blob" +], function(extensions, Blob) { - function Html4Runtime(options) { - var I = this - , Test = Runtime.capTest - , True = Runtime.capTrue - ; - - Runtime.call(this, options, type, { - access_binary: Test(window.FileReader || window.File && File.getAsDataURL), - access_image_binary: false, - display_media: Test(extensions.Image && (Env.can('create_canvas') || Env.can('use_data_uri_over32kb'))), - do_cors: false, - drag_and_drop: false, - filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest - return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10); - }()), - resize_image: function() { - return extensions.Image && I.can('access_binary') && Env.can('create_canvas'); - }, - report_upload_progress: false, - return_response_headers: false, - return_response_type: function(responseType) { - if (responseType === 'json' && !!window.JSON) { - return true; - } - return !!~Basic.inArray(responseType, ['text', 'document', '']); - }, - return_status_code: function(code) { - return !Basic.arrayDiff(code, [200, 404]); - }, - select_file: function() { - return Env.can('use_fileinput'); - }, - select_multiple: false, - send_binary_string: false, - send_custom_headers: false, - send_multipart: true, - slice_blob: false, - stream_upload: function() { - return I.can('select_file'); - }, - summon_file_dialog: Test(function() { // yeah... some dirty sniffing here... - return (Env.browser === 'Firefox' && Env.version >= 4) || - (Env.browser === 'Opera' && Env.version >= 12) || - !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']); - }()), - upload_filesize: True, - use_http_method: function(methods) { - return !Basic.arrayDiff(methods, ['GET', 'POST']); - } - }); - - - Basic.extend(this, { - init : function() { - this.trigger("Init"); - }, - - destroy: (function(destroy) { // extend default destroy method - return function() { - destroy.call(I); - destroy = I = null; - }; - }(this.destroy)) - }); - - Basic.extend(this.getShim(), extensions); - } - - Runtime.addConstructor(type, Html4Runtime); - - return extensions; -}); - -// Included from: src/javascript/core/utils/Events.js - -/** - * Events.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -define('moxie/core/utils/Events', [ - 'moxie/core/utils/Basic' -], function(Basic) { - var eventhash = {}, uid = 'moxie_' + Basic.guid(); - - // IE W3C like event funcs - function preventDefault() { - this.returnValue = false; - } - - function stopPropagation() { - this.cancelBubble = true; - } - - /** - Adds an event handler to the specified object and store reference to the handler - in objects internal Plupload registry (@see removeEvent). - - @method addEvent - @for Utils - @static - @param {Object} obj DOM element like object to add handler to. - @param {String} name Name to add event listener to. - @param {Function} callback Function to call when event occurs. - @param {String} [key] that might be used to add specifity to the event record. - */ - var addEvent = function(obj, name, callback, key) { - var func, events; - - name = name.toLowerCase(); - - // Add event listener - if (obj.addEventListener) { - func = callback; - - obj.addEventListener(name, func, false); - } else if (obj.attachEvent) { - func = function() { - var evt = window.event; - - if (!evt.target) { - evt.target = evt.srcElement; - } - - evt.preventDefault = preventDefault; - evt.stopPropagation = stopPropagation; - - callback(evt); - }; - - obj.attachEvent('on' + name, func); - } - - // Log event handler to objects internal mOxie registry - if (!obj[uid]) { - obj[uid] = Basic.guid(); - } - - if (!eventhash.hasOwnProperty(obj[uid])) { - eventhash[obj[uid]] = {}; - } - - events = eventhash[obj[uid]]; - - if (!events.hasOwnProperty(name)) { - events[name] = []; - } - - events[name].push({ - func: func, - orig: callback, // store original callback for IE - key: key - }); - }; - - - /** - Remove event handler from the specified object. If third argument (callback) - is not specified remove all events with the specified name. - - @method removeEvent - @static - @param {Object} obj DOM element to remove event listener(s) from. - @param {String} name Name of event listener to remove. - @param {Function|String} [callback] might be a callback or unique key to match. - */ - var removeEvent = function(obj, name, callback) { - var type, undef; - - name = name.toLowerCase(); - - if (obj[uid] && eventhash[obj[uid]] && eventhash[obj[uid]][name]) { - type = eventhash[obj[uid]][name]; - } else { - return; - } - - for (var i = type.length - 1; i >= 0; i--) { - // undefined or not, key should match - if (type[i].orig === callback || type[i].key === callback) { - if (obj.removeEventListener) { - obj.removeEventListener(name, type[i].func, false); - } else if (obj.detachEvent) { - obj.detachEvent('on'+name, type[i].func); - } - - type[i].orig = null; - type[i].func = null; - type.splice(i, 1); - - // If callback was passed we are done here, otherwise proceed - if (callback !== undef) { - break; - } - } - } - - // If event array got empty, remove it - if (!type.length) { - delete eventhash[obj[uid]][name]; - } - - // If mOxie registry has become empty, remove it - if (Basic.isEmptyObj(eventhash[obj[uid]])) { - delete eventhash[obj[uid]]; - - // IE doesn't let you remove DOM object property with - delete - try { - delete obj[uid]; - } catch(e) { - obj[uid] = undef; + var Transporter = { + getAsBlob: function(type) { + var self = this.getRuntime() + , blob = self.shimExec.call(this, 'Transporter', 'getAsBlob', type) + ; + if (blob) { + return new Blob(self.uid, blob); } + return null; } }; - - - /** - Remove all kind of events from the specified object - - @method removeAllEvents - @static - @param {Object} obj DOM element to remove event listeners from. - @param {String} [key] unique key to match, when removing events. - */ - var removeAllEvents = function(obj, key) { - if (!obj || !obj[uid]) { - return; - } - - Basic.each(eventhash[obj[uid]], function(events, name) { - removeEvent(obj, name, key); - }); - }; - return { - addEvent: addEvent, - removeEvent: removeEvent, - removeAllEvents: removeAllEvents - }; + return (extensions.Transporter = Transporter); }); -// Included from: src/javascript/runtime/html4/file/FileInput.js +// Included from: src/javascript/runtime/flash/image/Image.js /** - * FileInput.js + * Image.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. @@ -6135,1052 +6502,69 @@ define('moxie/core/utils/Events', [ */ /** -@class moxie/runtime/html4/file/FileInput +@class moxie/runtime/flash/image/Image @private */ -define("moxie/runtime/html4/file/FileInput", [ - "moxie/runtime/html4/Runtime", +define("moxie/runtime/flash/image/Image", [ + "moxie/runtime/flash/Runtime", "moxie/core/utils/Basic", - "moxie/core/utils/Dom", - "moxie/core/utils/Events", - "moxie/core/utils/Mime", - "moxie/core/utils/Env" -], function(extensions, Basic, Dom, Events, Mime, Env) { - - function FileInput() { - var _uid, _files = [], _mimes = [], _options; - - function addInput() { - var comp = this, I = comp.getRuntime(), shimContainer, browseButton, currForm, form, input, uid; - - uid = Basic.guid('uid_'); - - shimContainer = I.getShimContainer(); // we get new ref everytime to avoid memory leaks in IE - - if (_uid) { // move previous form out of the view - currForm = Dom.get(_uid + '_form'); - if (currForm) { - Basic.extend(currForm.style, { top: '100%' }); - } - } - - // build form in DOM, since innerHTML version not able to submit file for some reason - form = document.createElement('form'); - form.setAttribute('id', uid + '_form'); - form.setAttribute('method', 'post'); - form.setAttribute('enctype', 'multipart/form-data'); - form.setAttribute('encoding', 'multipart/form-data'); - - Basic.extend(form.style, { - overflow: 'hidden', - position: 'absolute', - top: 0, - left: 0, - width: '100%', - height: '100%' - }); - - input = document.createElement('input'); - input.setAttribute('id', uid); - input.setAttribute('type', 'file'); - input.setAttribute('name', _options.name || 'Filedata'); - input.setAttribute('accept', _mimes.join(',')); - - Basic.extend(input.style, { - fontSize: '999px', - opacity: 0 - }); - - form.appendChild(input); - shimContainer.appendChild(form); - - // prepare file input to be placed underneath the browse_button element - Basic.extend(input.style, { - position: 'absolute', - top: 0, - left: 0, - width: '100%', - height: '100%' - }); - - if (Env.browser === 'IE' && Env.version < 10) { - Basic.extend(input.style, { - filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)" - }); - } - - input.onchange = function() { // there should be only one handler for this - var file; - - if (!this.value) { - return; - } - - if (this.files) { - file = this.files[0]; - } else { - file = { - name: this.value - }; - } - - _files = [file]; - - this.onchange = function() {}; // clear event handler - addInput.call(comp); - - // after file is initialized as o.File, we need to update form and input ids - comp.bind('change', function onChange() { - var input = Dom.get(uid), form = Dom.get(uid + '_form'), file; - - comp.unbind('change', onChange); - - if (comp.files.length && input && form) { - file = comp.files[0]; - - input.setAttribute('id', file.uid); - form.setAttribute('id', file.uid + '_form'); - - // set upload target - form.setAttribute('target', file.uid + '_iframe'); - } - input = form = null; - }, 998); - - input = form = null; - comp.trigger('change'); - }; - - - // route click event to the input - if (I.can('summon_file_dialog')) { - browseButton = Dom.get(_options.browse_button); - Events.removeEvent(browseButton, 'click', comp.uid); - Events.addEvent(browseButton, 'click', function(e) { - if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file] - input.click(); - } - e.preventDefault(); - }, comp.uid); - } - - _uid = uid; - - shimContainer = currForm = browseButton = null; - } - - Basic.extend(this, { - init: function(options) { - var comp = this, I = comp.getRuntime(), shimContainer; - - // figure out accept string - _options = options; - _mimes = options.accept.mimes || Mime.extList2mimes(options.accept, I.can('filter_by_extension')); - - shimContainer = I.getShimContainer(); - - (function() { - var browseButton, zIndex, top; - - browseButton = Dom.get(options.browse_button); - - // Route click event to the input[type=file] element for browsers that support such behavior - if (I.can('summon_file_dialog')) { - if (Dom.getStyle(browseButton, 'position') === 'static') { - browseButton.style.position = 'relative'; - } - - zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1; - - browseButton.style.zIndex = zIndex; - shimContainer.style.zIndex = zIndex - 1; - } - - /* Since we have to place input[type=file] on top of the browse_button for some browsers, - browse_button loses interactivity, so we restore it here */ - top = I.can('summon_file_dialog') ? browseButton : shimContainer; - - Events.addEvent(top, 'mouseover', function() { - comp.trigger('mouseenter'); - }, comp.uid); - - Events.addEvent(top, 'mouseout', function() { - comp.trigger('mouseleave'); - }, comp.uid); - - Events.addEvent(top, 'mousedown', function() { - comp.trigger('mousedown'); - }, comp.uid); - - Events.addEvent(Dom.get(options.container), 'mouseup', function() { - comp.trigger('mouseup'); - }, comp.uid); - - browseButton = null; - }()); - - addInput.call(this); - - shimContainer = null; - - // trigger ready event asynchronously - comp.trigger({ - type: 'ready', - async: true - }); - }, - - getFiles: function() { - return _files; - }, - - disable: function(state) { - var input; - - if ((input = Dom.get(_uid))) { - input.disabled = !!state; - } - }, - - destroy: function() { - var I = this.getRuntime() - , shim = I.getShim() - , shimContainer = I.getShimContainer() - ; - - Events.removeAllEvents(shimContainer, this.uid); - Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); - Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid); - - if (shimContainer) { - shimContainer.innerHTML = ''; - } - - shim.removeInstance(this.uid); - - _uid = _files = _mimes = _options = shimContainer = shim = null; - } - }); - } - - return (extensions.FileInput = FileInput); -}); - -// Included from: src/javascript/runtime/html5/Runtime.js - -/** - * Runtime.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/*global File:true */ - -/** -Defines constructor for HTML5 runtime. - -@class moxie/runtime/html5/Runtime -@private -*/ -define("moxie/runtime/html5/Runtime", [ - "moxie/core/utils/Basic", - "moxie/core/Exceptions", - "moxie/runtime/Runtime", - "moxie/core/utils/Env" -], function(Basic, x, Runtime, Env) { - - var type = "html5", extensions = {}; - - function Html5Runtime(options) { - var I = this - , Test = Runtime.capTest - , True = Runtime.capTrue - ; - - var caps = Basic.extend({ - access_binary: Test(window.FileReader || window.File && window.File.getAsDataURL), - access_image_binary: function() { - return I.can('access_binary') && !!extensions.Image; - }, - display_media: Test(Env.can('create_canvas') || Env.can('use_data_uri_over32kb')), - do_cors: Test(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()), - drag_and_drop: Test(function() { - // this comes directly from Modernizr: http://www.modernizr.com/ - var div = document.createElement('div'); - // IE has support for drag and drop since version 5, but doesn't support dropping files from desktop - return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && (Env.browser !== 'IE' || Env.version > 9); - }()), - filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest - return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10); - }()), - return_response_headers: True, - return_response_type: function(responseType) { - if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported - return true; - } - return Env.can('return_response_type', responseType); - }, - return_status_code: True, - report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload), - resize_image: function() { - return I.can('access_binary') && Env.can('create_canvas'); - }, - select_file: function() { - return Env.can('use_fileinput') && window.File; - }, - select_folder: function() { - return I.can('select_file') && Env.browser === 'Chrome' && Env.version >= 21; - }, - select_multiple: function() { - // it is buggy on Safari Windows and iOS - return I.can('select_file') && - !(Env.browser === 'Safari' && Env.os === 'Windows') && - !(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.4", '<')); - }, - send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))), - send_custom_headers: Test(window.XMLHttpRequest), - send_multipart: function() { - return !!(window.XMLHttpRequest && new XMLHttpRequest().upload && window.FormData) || I.can('send_binary_string'); - }, - slice_blob: Test(window.File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice)), - stream_upload: function(){ - return I.can('slice_blob') && I.can('send_multipart'); - }, - summon_file_dialog: Test(function() { // yeah... some dirty sniffing here... - return (Env.browser === 'Firefox' && Env.version >= 4) || - (Env.browser === 'Opera' && Env.version >= 12) || - (Env.browser === 'IE' && Env.version >= 10) || - !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']); - }()), - upload_filesize: True - }, - arguments[2] - ); - - Runtime.call(this, options, (arguments[1] || type), caps); - - - Basic.extend(this, { - - init : function() { - this.trigger("Init"); - }, - - destroy: (function(destroy) { // extend default destroy method - return function() { - destroy.call(I); - destroy = I = null; - }; - }(this.destroy)) - }); - - Basic.extend(this.getShim(), extensions); - } - - Runtime.addConstructor(type, Html5Runtime); - - return extensions; -}); - -// Included from: src/javascript/runtime/html5/file/FileReader.js - -/** - * FileReader.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/html5/file/FileReader -@private -*/ -define("moxie/runtime/html5/file/FileReader", [ - "moxie/runtime/html5/Runtime", - "moxie/core/utils/Encode", - "moxie/core/utils/Basic" -], function(extensions, Encode, Basic) { - - function FileReader() { - var _fr, _convertToBinary = false; - - Basic.extend(this, { - - read: function(op, blob) { - var target = this; - - _fr = new window.FileReader(); - - _fr.addEventListener('progress', function(e) { - target.trigger(e); - }); - - _fr.addEventListener('load', function(e) { - target.trigger(e); - }); - - _fr.addEventListener('error', function(e) { - target.trigger(e, _fr.error); - }); - - _fr.addEventListener('loadend', function() { - _fr = null; - }); - - if (Basic.typeOf(_fr[op]) === 'function') { - _convertToBinary = false; - _fr[op](blob.getSource()); - } else if (op === 'readAsBinaryString') { // readAsBinaryString is depricated in general and never existed in IE10+ - _convertToBinary = true; - _fr.readAsDataURL(blob.getSource()); - } - }, - - getResult: function() { - return _fr && _fr.result ? (_convertToBinary ? _toBinary(_fr.result) : _fr.result) : null; - }, - - abort: function() { - if (_fr) { - _fr.abort(); - } - }, - - destroy: function() { - _fr = null; - } - }); - - function _toBinary(str) { - return Encode.atob(str.substring(str.indexOf('base64,') + 7)); - } - } - - return (extensions.FileReader = FileReader); -}); - -// Included from: src/javascript/runtime/html4/file/FileReader.js - -/** - * FileReader.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/html4/file/FileReader -@private -*/ -define("moxie/runtime/html4/file/FileReader", [ - "moxie/runtime/html4/Runtime", - "moxie/runtime/html5/file/FileReader" -], function(extensions, FileReader) { - return (extensions.FileReader = FileReader); -}); - -// Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js - -/** - * XMLHttpRequest.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/html4/xhr/XMLHttpRequest -@private -*/ -define("moxie/runtime/html4/xhr/XMLHttpRequest", [ - "moxie/runtime/html4/Runtime", - "moxie/core/utils/Basic", - "moxie/core/utils/Dom", - "moxie/core/utils/Url", - "moxie/core/Exceptions", - "moxie/core/utils/Events", + "moxie/runtime/Transporter", "moxie/file/Blob", - "moxie/xhr/FormData" -], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) { + "moxie/file/FileReaderSync" +], function(extensions, Basic, Transporter, Blob, FileReaderSync) { - function XMLHttpRequest() { - var _status, _response, _iframe; + var Image = { + loadFromBlob: function(blob) { + var comp = this, self = comp.getRuntime(); - function cleanup(cb) { - var target = this, uid, form, inputs, i, hasFile = false; - - if (!_iframe) { - return; + function exec(srcBlob) { + self.shimExec.call(comp, 'Image', 'loadFromBlob', srcBlob.uid); + comp = self = null; } - uid = _iframe.id.replace(/_iframe$/, ''); - - form = Dom.get(uid + '_form'); - if (form) { - inputs = form.getElementsByTagName('input'); - i = inputs.length; - - while (i--) { - switch (inputs[i].getAttribute('type')) { - case 'hidden': - inputs[i].parentNode.removeChild(inputs[i]); - break; - case 'file': - hasFile = true; // flag the case for later - break; - } - } - inputs = []; - - if (!hasFile) { // we need to keep the form for sake of possible retries - form.parentNode.removeChild(form); - } - form = null; - } - - // without timeout, request is marked as canceled (in console) - setTimeout(function() { - Events.removeEvent(_iframe, 'load', target.uid); - if (_iframe.parentNode) { // #382 - _iframe.parentNode.removeChild(_iframe); - } - - // check if shim container has any other children, if - not, remove it as well - var shimContainer = target.getRuntime().getShimContainer(); - if (!shimContainer.children.length) { - shimContainer.parentNode.removeChild(shimContainer); - } - - shimContainer = _iframe = null; - cb(); - }, 1); - } - - Basic.extend(this, { - send: function(meta, data) { - var target = this, I = target.getRuntime(), uid, form, input, blob; - - _status = _response = null; - - function createIframe() { - var container = I.getShimContainer() || document.body - , temp = document.createElement('div') - ; - - // IE 6 won't be able to set the name using setAttribute or iframe.name - temp.innerHTML = ''; - _iframe = temp.firstChild; - container.appendChild(_iframe); - - /* _iframe.onreadystatechange = function() { - console.info(_iframe.readyState); - };*/ - - Events.addEvent(_iframe, 'load', function() { // _iframe.onload doesn't work in IE lte 8 - var el; - - try { - el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document; - - // try to detect some standard error pages - if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error - _status = el.title.replace(/^(\d+).*$/, '$1'); - } else { - _status = 200; - // get result - _response = Basic.trim(el.body.innerHTML); - - // we need to fire these at least once - target.trigger({ - type: 'progress', - loaded: _response.length, - total: _response.length - }); - - if (blob) { // if we were uploading a file - target.trigger({ - type: 'uploadprogress', - loaded: blob.size || 1025, - total: blob.size || 1025 - }); - } - } - } catch (ex) { - if (Url.hasSameOrigin(meta.url)) { - // if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm - // which obviously results to cross domain error (wtf?) - _status = 404; - } else { - cleanup.call(target, function() { - target.trigger('error'); - }); - return; - } - } - - cleanup.call(target, function() { - target.trigger('load'); - }); - }, target.uid); - } // end createIframe - - // prepare data to be sent and convert if required - if (data instanceof FormData && data.hasBlob()) { - blob = data.getBlob(); - uid = blob.uid; - input = Dom.get(uid); - form = Dom.get(uid + '_form'); - if (!form) { - throw new x.DOMException(x.DOMException.NOT_FOUND_ERR); - } - } else { - uid = Basic.guid('uid_'); - - form = document.createElement('form'); - form.setAttribute('id', uid + '_form'); - form.setAttribute('method', meta.method); - form.setAttribute('enctype', 'multipart/form-data'); - form.setAttribute('encoding', 'multipart/form-data'); - form.setAttribute('target', uid + '_iframe'); - - I.getShimContainer().appendChild(form); - } - - if (data instanceof FormData) { - data.each(function(value, name) { - if (value instanceof Blob) { - if (input) { - input.setAttribute('name', name); - } - } else { - var hidden = document.createElement('input'); - - Basic.extend(hidden, { - type : 'hidden', - name : name, - value : value - }); - - // make sure that input[type="file"], if it's there, comes last - if (input) { - form.insertBefore(hidden, input); - } else { - form.appendChild(hidden); - } - } - }); - } - - // set destination url - form.setAttribute("action", meta.url); - - createIframe(); - form.submit(); - target.trigger('loadstart'); - }, - - getStatus: function() { - return _status; - }, - - getResponse: function(responseType) { - if ('json' === responseType) { - // strip off
..
tags that might be enclosing the response - if (Basic.typeOf(_response) === 'string' && !!window.JSON) { - try { - return JSON.parse(_response.replace(/^\s*]*>/, '').replace(/<\/pre>\s*$/, '')); - } catch (ex) { - return null; - } - } - } else if ('document' === responseType) { - - } - return _response; - }, - - abort: function() { - var target = this; - - if (_iframe && _iframe.contentWindow) { - if (_iframe.contentWindow.stop) { // FireFox/Safari/Chrome - _iframe.contentWindow.stop(); - } else if (_iframe.contentWindow.document.execCommand) { // IE - _iframe.contentWindow.document.execCommand('Stop'); - } else { - _iframe.src = "about:blank"; - } - } - - cleanup.call(this, function() { - // target.dispatchEvent('readystatechange'); - target.dispatchEvent('abort'); + if (blob.isDetached()) { // binary string + var tr = new Transporter(); + tr.bind("TransportingComplete", function() { + exec(tr.result.getSource()); }); + tr.transport(blob.getSource(), blob.type, { ruid: self.uid }); + } else { + exec(blob.getSource()); } - }); - } + }, - return (extensions.XMLHttpRequest = XMLHttpRequest); -}); + loadFromImage: function(img) { + var self = this.getRuntime(); + return self.shimExec.call(this, 'Image', 'loadFromImage', img.uid); + }, -// Included from: src/javascript/runtime/silverlight/Runtime.js - -/** - * RunTime.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/*global ActiveXObject:true */ - -/** -Defines constructor for Silverlight runtime. - -@class moxie/runtime/silverlight/Runtime -@private -*/ -define("moxie/runtime/silverlight/Runtime", [ - "moxie/core/utils/Basic", - "moxie/core/utils/Env", - "moxie/core/utils/Dom", - "moxie/core/Exceptions", - "moxie/runtime/Runtime" -], function(Basic, Env, Dom, x, Runtime) { - - var type = "silverlight", extensions = {}; - - function isInstalled(version) { - var isVersionSupported = false, control = null, actualVer, - actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0; - - try { - try { - control = new ActiveXObject('AgControl.AgControl'); - - if (control.IsVersionSupported(version)) { - isVersionSupported = true; - } - - control = null; - } catch (e) { - var plugin = navigator.plugins["Silverlight Plug-In"]; - - if (plugin) { - actualVer = plugin.description; - - if (actualVer === "1.0.30226.2") { - actualVer = "2.0.30226.2"; - } - - actualVerArray = actualVer.split("."); - - while (actualVerArray.length > 3) { - actualVerArray.pop(); - } - - while ( actualVerArray.length < 4) { - actualVerArray.push(0); - } - - reqVerArray = version.split("."); - - while (reqVerArray.length > 4) { - reqVerArray.pop(); - } - - do { - requiredVersionPart = parseInt(reqVerArray[index], 10); - actualVersionPart = parseInt(actualVerArray[index], 10); - index++; - } while (index < reqVerArray.length && requiredVersionPart === actualVersionPart); - - if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) { - isVersionSupported = true; - } - } + getAsBlob: function(type, quality) { + var self = this.getRuntime() + , blob = self.shimExec.call(this, 'Image', 'getAsBlob', type, quality) + ; + if (blob) { + return new Blob(self.uid, blob); } - } catch (e2) { - isVersionSupported = false; - } + return null; + }, - return isVersionSupported; - } - - /** - Constructor for the Silverlight Runtime - - @class SilverlightRuntime - @extends Runtime - */ - function SilverlightRuntime(options) { - var I = this, initTimer; - - options = Basic.extend({ xap_url: Env.xap_url }, options); - - Runtime.call(this, options, type, { - access_binary: Runtime.capTrue, - access_image_binary: Runtime.capTrue, - display_media: Runtime.capTrue, - do_cors: Runtime.capTrue, - drag_and_drop: false, - report_upload_progress: Runtime.capTrue, - resize_image: Runtime.capTrue, - return_response_headers: function(value) { - return value && I.mode === 'client'; - }, - return_response_type: function(responseType) { - if (responseType !== 'json') { - return true; - } else { - return !!window.JSON; - } - }, - return_status_code: function(code) { - return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]); - }, - select_file: Runtime.capTrue, - select_multiple: Runtime.capTrue, - send_binary_string: Runtime.capTrue, - send_browser_cookies: function(value) { - return value && I.mode === 'browser'; - }, - send_custom_headers: function(value) { - return value && I.mode === 'client'; - }, - send_multipart: Runtime.capTrue, - slice_blob: Runtime.capTrue, - stream_upload: true, - summon_file_dialog: false, - upload_filesize: Runtime.capTrue, - use_http_method: function(methods) { - return I.mode === 'client' || !Basic.arrayDiff(methods, ['GET', 'POST']); + getAsDataURL: function() { + var self = this.getRuntime() + , blob = self.Image.getAsBlob.apply(this, arguments) + , frs + ; + if (!blob) { + return null; } - }, { - // capabilities that require specific mode - return_response_headers: function(value) { - return value ? 'client' : 'browser'; - }, - return_status_code: function(code) { - return Basic.arrayDiff(code, [200, 404]) ? 'client' : ['client', 'browser']; - }, - send_browser_cookies: function(value) { - return value ? 'browser' : 'client'; - }, - send_custom_headers: function(value) { - return value ? 'client' : 'browser'; - }, - use_http_method: function(methods) { - return Basic.arrayDiff(methods, ['GET', 'POST']) ? 'client' : ['client', 'browser']; - } - }); - - - // minimal requirement - if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') { - this.mode = false; - } - - - Basic.extend(this, { - getShim: function() { - return Dom.get(this.uid).content.Moxie; - }, - - shimExec: function(component, action) { - var args = [].slice.call(arguments, 2); - return I.getShim().exec(this.uid, component, action, args); - }, - - init : function() { - var container; - - container = this.getShimContainer(); - - container.innerHTML = '' + - '' + - '' + - '' + - '' + - '' + - ''; - - // Init is dispatched by the shim - initTimer = setTimeout(function() { - if (I && !I.initialized) { // runtime might be already destroyed by this moment - I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); - } - }, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac) - }, - - destroy: (function(destroy) { // extend default destroy method - return function() { - destroy.call(I); - clearTimeout(initTimer); // initialization check might be still onwait - options = initTimer = destroy = I = null; - }; - }(this.destroy)) - - }, extensions); - } - - Runtime.addConstructor(type, SilverlightRuntime); - - return extensions; -}); - -// Included from: src/javascript/runtime/silverlight/file/Blob.js - -/** - * Blob.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/file/Blob -@private -*/ -define("moxie/runtime/silverlight/file/Blob", [ - "moxie/runtime/silverlight/Runtime", - "moxie/core/utils/Basic", - "moxie/runtime/flash/file/Blob" -], function(extensions, Basic, Blob) { - return (extensions.Blob = Basic.extend({}, Blob)); -}); - -// Included from: src/javascript/runtime/silverlight/file/FileInput.js - -/** - * FileInput.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/file/FileInput -@private -*/ -define("moxie/runtime/silverlight/file/FileInput", [ - "moxie/runtime/silverlight/Runtime" -], function(extensions) { - - var FileInput = { - init: function(options) { - - function toFilters(accept) { - var filter = ''; - for (var i = 0; i < accept.length; i++) { - filter += (filter !== '' ? '|' : '') + accept[i].title + " | *." + accept[i].extensions.replace(/,/g, ';*.'); - } - return filter; - } - - this.getRuntime().shimExec.call(this, 'FileInput', 'init', toFilters(options.accept), options.name, options.multiple); - this.trigger('ready'); + frs = new FileReaderSync(); + return frs.readAsDataURL(blob); } }; - return (extensions.FileInput = FileInput); + return (extensions.Image = Image); }); -// Included from: src/javascript/runtime/silverlight/file/FileReader.js - -/** - * FileReader.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/file/FileReader -@private -*/ -define("moxie/runtime/silverlight/file/FileReader", [ - "moxie/runtime/silverlight/Runtime", - "moxie/core/utils/Basic", - "moxie/runtime/flash/file/FileReader" -], function(extensions, Basic, FileReader) { - return (extensions.FileReader = Basic.extend({}, FileReader)); -}); - -// Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js - -/** - * FileReaderSync.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/file/FileReaderSync -@private -*/ -define("moxie/runtime/silverlight/file/FileReaderSync", [ - "moxie/runtime/silverlight/Runtime", - "moxie/core/utils/Basic", - "moxie/runtime/flash/file/FileReaderSync" -], function(extensions, Basic, FileReaderSync) { - return (extensions.FileReaderSync = Basic.extend({}, FileReaderSync)); -}); - -// Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js - -/** - * XMLHttpRequest.js - * - * Copyright 2013, Moxiecode Systems AB - * Released under GPL License. - * - * License: http://www.plupload.com/license - * Contributing: http://www.plupload.com/contributing - */ - -/** -@class moxie/runtime/silverlight/xhr/XMLHttpRequest -@private -*/ -define("moxie/runtime/silverlight/xhr/XMLHttpRequest", [ - "moxie/runtime/silverlight/Runtime", - "moxie/core/utils/Basic", - "moxie/runtime/flash/xhr/XMLHttpRequest" -], function(extensions, Basic, XMLHttpRequest) { - return (extensions.XMLHttpRequest = Basic.extend({}, XMLHttpRequest)); -}); - -expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/core/utils/Events"]); +expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image"]); })(this);/** * o.js * diff --git a/public/webshims/shims/moxie/silverlight/Moxie.cdn.xap b/public/webshims/shims/moxie/silverlight/Moxie.cdn.xap deleted file mode 100644 index f0d499f9..00000000 Binary files a/public/webshims/shims/moxie/silverlight/Moxie.cdn.xap and /dev/null differ diff --git a/public/webshims/shims/moxie/silverlight/Moxie.min.xap b/public/webshims/shims/moxie/silverlight/Moxie.min.xap deleted file mode 100644 index 40b12c2b..00000000 Binary files a/public/webshims/shims/moxie/silverlight/Moxie.min.xap and /dev/null differ diff --git a/public/webshims/shims/sticky.js b/public/webshims/shims/sticky.js new file mode 100644 index 00000000..881b3c30 --- /dev/null +++ b/public/webshims/shims/sticky.js @@ -0,0 +1,585 @@ +webshim.register('sticky', function($, webshim, window, document, undefined, featureOptions){ + + "use strict"; + + var uid = 0; + var stickys = 0; + var $window = $(window); + + function getCssValue(property, value, noPrefixes) { + var prop = property + ':', + el = document.createElement('test'), + mStyle = el.style; + + if (!noPrefixes) { + mStyle.cssText = prop + [ '-webkit-', '-moz-', '-ms-', '-o-', '' ].join(value + ';' + prop) + value + ';'; + } else { + mStyle.cssText = prop + value; + } + + return mStyle[ property ]; + } + + function getPos() { + return { + top: $.css(this, 'top'), + bottom: $.css(this, 'bottom') + }; + } + + var getWinScroll = (function () { + var docElem; + var prop = 'pageYOffset'; + + return (prop in window) ? + function () { + return window[ prop ]; + } : + ((docElem = document.documentElement), function () { + return docElem.scrollTop; + }) + ; + })(); + var isTouch = 'ontouchstart' in window || window.matchMedia('(max-device-width: 721px)').matches; + var support = { + fixed: getCssValue('position', 'fixed', true), + sticky: getCssValue('position', 'sticky') + }; + + var stickyMixin = { + getPosition: function () { + + if(!this.isSticky){ + this.position = { + top: this.$el.css('top'), + bottom: this.$el.css('bottom') + }; + + if ((( + (this.position.top != 'auto' && this.position.bottom != 'auto') || + this.position.top == 'auto' && this.position.bottom == 'auto')) && this.$el.css('position') == 'static') { + this.position = $.swap(this.$el[0], {position: 'absolute'}, getPos); + } + + if (this.position.top !== 'auto') { + this.ankered = 'top'; + } else if (this.position.bottom !== 'auto') { + this.ankered = 'bottom'; + } + + if(this.ankered == 'top'){ + this.position.top = parseFloat(this.position.top, 10) || 0; + } else if(this.ankered == 'bottom'){ + this.position.bottom = parseFloat(this.position.bottom, 10) || 0; + } + + } + }, + update: function (full) { + if (!this.disabled && this.$el[0].offsetWidth) { + if (full) { + if(this.isSticky){ + this.removeSticky(); + } + this.getPosition(); + } + this.updateDimension(); + } + }, + setTdWidth: function(){ + if(this.isTable){ + this.$el.find('td, th').each(this._setInlineWidth); + } + }, + _setInlineWidth: function(){ + $.data(this, 'inlineWidth', this.style.width); + $(this).innerWidth($(this).innerWidth()); + }, + _restoreInlineWidth: function(){ + this.style.width = $.data(this, 'inlineWidth') || ''; + $.removeData(this, 'inlineWidth'); + }, + removeSticky: function(){ + this.$el.removeClass('ws-sticky-on'); + this.$el.css(this.stickyData.inline); + this.$placeholder.detach(); + this.isSticky = false; + + if(this.isTable){ + this.$el.find('td, th').each(this._restoreInlineWidth); + } + }, + commonAddEvents: function(){ + var enableDisable; + var that = this; + var update = function() { + that.update(); + }; + + var stickyMedia = this.$el.data('stickymedia'); + var media = window.matchMedia && stickyMedia ? matchMedia(stickyMedia) : false; + $window.one('load', update); + $(document).on('updateshadowdom' + this.evtid, update); + + + this.$el.on('updatesticky'+ this.evtid, function(e){ + that.update(true); + e.stopPropagation(); + }); + + this.$el.on('disablesticky'+ this.evtid, function(e){ + that.disable(true); + e.stopPropagation(); + }); + + this.$el.on('enablesticky'+ this.evtid, function(e){ + that.disable(false); + e.stopPropagation(); + }); + + this.$el.on('remove'+ this.evtid+' destroysticky'+ this.evtid, function(e) { + + $window.off(that.evtid); + $(document).off(that.evtid); + that.$el.off(that.evtid); + that.$parent.off(that.evtid); + that.$el.removeData('wsSticky').removeClass('ws-sticky'); + if (that.$placeholder) { + that.$el.removeClass('ws-sticky-on'); + that.$placeholder.remove(); + } + stickys--; + e.stopPropagation(); + }); + + if(media && media.addListener){ + enableDisable = function(){ + that.disable(!media.matches); + }; + media.addListener(enableDisable); + enableDisable(); + } + }, + disable: function(disable){ + if(!arguments.length){ + return this.disabled; + } + if(this.disabled != disable){ + this.disabled = !!disable; + if(this.disabled){ + if(this.isSticky){ + this.removeSticky(); + } + } else { + this.update(true); + } + } + }, + setSticky: function(){ + + if (!this.$placeholder) { + this.$placeholder = this.isTable ? $(this.$el[0].cloneNode(true)) : $(document.createElement(this.$el[0].nodeName || 'div')); + this.$placeholder.addClass('ws-fixedsticky-placeholder').removeClass('ws-sticky'); + } + + this.setTdWidth(); + + this.$placeholder + .insertAfter(this.$el) + .outerHeight(this.stickyData.outerHeight, true) + .outerWidth(this.stickyData.outerWidth) + ; + + this.isSticky = true; + this.$el.addClass('ws-sticky-on'); + + if(!this.isTable){ + if( this.stickyData.width != this.$el.width()){ + this.$el.width(this.stickyData.width); + } + } + }, + getCommonStickyData: function(){ + var marginTop = (parseFloat(this.$el.css('marginTop'), 10) || 0); + + this.stickyData.scrollTop = this.stickyData.top - marginTop; + + this.stickyData.outerHeight = this.$el.outerHeight(true); + + this.stickyData.bottom = this.stickyData.top + this.stickyData.outerHeight - marginTop; + + this.stickyData.width = this.$el.width(); + this.stickyData.outerWidth = this.$el.outerWidth(); + + this.stickyData.marginLeft = parseFloat(this.$el.css('marginLeft'), 10) || 0; + this.stickyData.offsetLeft = this.$el[0].offsetLeft; + + this.stickyData.inline.width = this.elStyle.width; + this.stickyData.inline.marginLeft = this.elStyle.marginLeft; + + if(this.ankered == 'top'){ + this.stickyData.inline.top = this.elStyle.top; + } else if(this.ankered == 'bottom'){ + this.stickyData.inline.bottom = this.elStyle.bottom; + } + }, + getCommonParentData: function(){ + this.parentData.paddingTop = (parseFloat(this.$parent.css('paddingTop'), 10) || 0); + + this.parentData.offsetTop = this.$parent.offset().top; + this.parentData.top = this.parentData.offsetTop + (parseFloat(this.$parent.css('borderTopWidth'), 10) || 0) + this.parentData.paddingTop; + + this.parentData.height = this.$parent.height(); + this.parentData.bottom = this.parentData.top + this.parentData.height; + } + }; + + if(isTouch && featureOptions.touchStrategy == 'disable'){return;} + + + function Sticky(dom) { + + uid++; + stickys++; + + this.evtid = '.wsstickyid' + uid; + this.$el = $(dom).data('wsSticky', this); + this.isTable = this.$el.is('thead, tbody, tfoot'); + this.$parent = this.$el.parent(); + this.elStyle = dom.style; + + + this.ankered = ''; + this.isSticky = false; + this.$placeholder = null; + + this.stickyData = {inline: {}}; + this.parentData = {}; + + this.getParentData = this.getCommonParentData; + + + this.addEvents(); + this.update(true); + } + + $.extend(Sticky.prototype, stickyMixin, { + addEvents: function () { + var that = this; + + this.commonAddEvents(); + + $window + .on('scroll' + this.evtid, function () { + if (!that.disabled && that.ankered && that.$el[0].offsetWidth) { + that.updatePos(); + } + }) + ; + }, + + getStickyData: function(){ + this.stickyData.top = this.$el.offset().top; + + this.getCommonStickyData(); + }, + + updateDimension: function(fromPos){ + if(this.isSticky){ + this.removeSticky(); + } + this.getParentData(); + this.getStickyData(); + + if (this.ankered == 'bottom') { + this.viewportBottomAnker = $window.height() - this.position.bottom; + } + + if(!fromPos && this.ankered){ + this.updatePos(true); + } + }, + updatePos: function(fromDimension){ + var offset, shouldSticky, shouldMoveWith; + var scroll = getWinScroll(); + + if (this.ankered == 'top') { + offset = scroll + this.position.top; + if(this.stickyData.scrollTop < offset && scroll - 9 <= this.parentData.bottom){ + shouldMoveWith = ((offset + this.stickyData.outerHeight) - this.parentData.bottom) * -1; + + shouldSticky = true; + } + } else if (this.ankered == 'bottom') { + offset = scroll + this.viewportBottomAnker; + + if(this.stickyData.bottom > offset && + offset + 9 >= this.parentData.top){ + shouldSticky = true; + + shouldMoveWith = offset - this.parentData.top - this.stickyData.outerHeight; + } + } + + if (shouldSticky) { + if (!this.isSticky) { + + //updateDimension before layout trashing + if(!fromDimension){ + this.updateDimension(true); + } + + this.setSticky(); + } + + + if(shouldMoveWith < 0){ + if(this.ankered == 'top'){ + this.elStyle.top = this.position.top + shouldMoveWith +'px'; + } else if(this.ankered == 'bottom'){ + this.elStyle.bottom = this.position.bottom + shouldMoveWith +'px'; + } + } + } else if (this.isSticky) { + this.removeSticky(); + } + } + }); + + + function StickyParent(dom) { + + uid++; + stickys++; + + this.evtid = '.wsstickyid' + uid; + this.$el = $(dom).data('wsSticky', this); + this.isTable = this.$el.is('thead, tbody, tfoot'); + this.$parent = this.$el.parent(); + this.elStyle = dom.style; + + + this.ankered = ''; + this.isSticky = false; + this.$placeholder = null; + + this.stickyData = {inline: {}}; + this.parentData = {}; + + if(this.$parent.css('position') == 'static'){ + this.$parent.css('position', 'relative'); + } + + this.updatePos2 = this.updatePos2.bind(this); + + this.addEvents(); + this.update(true); + + } + + $.extend(StickyParent.prototype, stickyMixin, { + addEvents: function () { + var that = this; + + this.commonAddEvents(); + + this.$parent + .on('scroll' + this.evtid, function () { + if (that.ankered && that.$el[0].offsetWidth) { + that.updatePos(); + } + }) + ; + }, + getStickyData: function(){ + this.stickyData.top = this.$el[0].offsetTop; + + this.getCommonStickyData(); + }, + getParentData: function(){ + this.getCommonParentData(); + + this.parentData.offsetBottom = this.parentData.top + this.$parent.outerHeight(); + }, + updateDimension: function(fromPos){ + var add; + if(this.isSticky){ + this.removeSticky(); + } + this.getParentData(); + this.getStickyData(); + + this.viewport = $window.height(); + + if(this.ankered == 'top'){ + add = Math.abs(this.position.top) + 9; + } else if(this.ankered == 'bottom') { + add = Math.abs(this.position.bottom) + 9; + this.viewportBottomAnker = this.viewport - this.parentData.bottom; + this.compareBottom = this.stickyData.bottom + this.position.bottom; + + this.addBottom = (this.parentData.bottom - this.parentData.paddingTop) - this.viewport; + } + + this.viewPortMax = this.parentData.offsetBottom + add + 10; + this.viewPortMin = this.parentData.offsetTop - add - this.viewport; + + if(!fromPos){ + this.updatePos(true); + } + }, + updatePos: function(fromDimension){ + var offset, shouldSticky; + var scroll = this.$parent[0].scrollTop; + + if (this.ankered == 'top') { + offset = scroll + this.position.top ; + if(this.stickyData.scrollTop - this.parentData.paddingTop < offset){ + shouldSticky = true; + } + } else if (this.ankered == 'bottom') { + if(scroll + this.parentData.height < this.compareBottom){ + shouldSticky = true; + } + } + + if (shouldSticky) { + if (!this.isSticky) { + + //updateDimension before layout trashing + if(!fromDimension){ + this.updateDimension(true); + } + + this.setSticky(); + + $window + .off('scroll' + this.evtid, this.updatePos2) + .on('scroll' + this.evtid, this.updatePos2) + ; + this.updatePos2(true); + } + } else if (this.isSticky) { + this.removeSticky(); + $window.off('scroll' + this.evtid, this.updatePos2); + } + }, + updatePos2: function(init){ + var scrollTop = getWinScroll(); + + if(init === true || (this.viewPortMax > scrollTop && scrollTop > this.viewPortMin)){ + + if(this.ankered == 'top'){ + if(init === true || (this.viewPortMax > scrollTop && scrollTop > this.viewPortMin)){ + this.elStyle.top = this.position.top + this.parentData.top - scrollTop +'px'; + } + } else if(this.ankered == 'bottom'){ + this.elStyle.bottom = this.position.bottom + (scrollTop - this.addBottom) +'px'; + } + } + } + }); + + var loadDomSupport = function(){ + loadDomSupport = $.noop; + webshim.ready('WINDOWLOAD', function(){ + webshim.loader.loadList(['dom-extend']); + webshim.ready('dom-extend', function(){ + webshim.addShadowDom(); + }); + }); + }; + + var addSticky = function(){ + var stickyData = $.data(this, 'wsSticky'); + if(!stickyData){ + var $parent = $(this).parent(); + $(this).addClass('ws-sticky'); + if(($parent.css('overflowY') || $parent.css('overflow') || 'visible') == 'visible'){ + new Sticky(this); + } else { + //webshim.warn('currently not supported'); + new StickyParent(this); + } + loadDomSupport(); + } else if(stickyData.disable) { + stickyData.disable(false); + } + }; + + if (!support.sticky && support.fixed) { + var selectors = {}; + var createUpdateDomSearch = function(media, sels){ + var i, created, elems; + + var updated = []; + + if(!selectors[media]){ + selectors[media] = {sels: {}, string: '', + fn: function(context, insertedElement){ + var elems = $(selectors[media].string, context).add(insertedElement.filter(selectors[media].string)); + if(media){ + elems.data('stickymedia', media); + } + elems.each(addSticky); + } + }; + created = true; + } + + for(i = 0; i < sels.length; i++){ + if(!selectors[media].sels[sels[i]]){ + selectors[media].sels[sels[i]] = true; + updated.push(sels[i]); + } + } + + if(!created && !updated.length){return;} + + selectors[media].string = Object.keys(selectors[media].sels).join(', '); + + if(created){ + $(function(){ + webshim.addReady(selectors[media].fn); + }); + } else if($.isReady){ + elems = $(updated.join(', ')); + if(media){ + elems.data('stickymedia', media); + } + elems.each(addSticky); + } + }; + createUpdateDomSearch('', ['.ws-sticky']); + + $(function(){ + $(document).on('wssticky', function(e){ + addSticky.call(e.target); + }); + }); + + + if(featureOptions.parseCSS){ + if(window.Polyfill && Polyfill.prototype && Polyfill.prototype.doMatched){ + var onEnableRule = function(rule){ + var curSelectors = rule.getSelectors().split(/\,\s*/g); + var media = (!rule._rule.media || !rule._rule.media.length) ? '' : rule.getMedia(); + createUpdateDomSearch(media || '', curSelectors); + }; + + Polyfill({declarations:["position:sticky"]}) + .doMatched(function(rules){ + rules.each(onEnableRule); + }) + ; + + } else { + webshim.warn('Polyfill for CSS polyfilling made easy has to be included'); + } + } + } + + if(document.readyState == 'complete'){ + webshim.isReady('WINDOWLOAD', true); + } +}); diff --git a/public/webshims/shims/styles/forms-picker.css b/public/webshims/shims/styles/forms-picker.css index 8783940d..f7b99ae9 100644 --- a/public/webshims/shims/styles/forms-picker.css +++ b/public/webshims/shims/styles/forms-picker.css @@ -439,3 +439,23 @@ SASS: } /* helper classes to hide show/hide specific picker features */ +.capture-popover .ws-po-box { + padding-left: 0.30769em; + padding-right: 0.30769em; +} + +.ws-videocapture-view { + position: relative; + height: 0; + width: 100%; + padding-bottom: 70%; +} +.ws-videocapture-view .ws-video-overlay, +.ws-videocapture-view video, +.ws-videocapture-view .polyfill-video { + position: absolute !important; + top: 0; + left: 0; + width: 100% !important; + height: 100% !important; +} diff --git a/public/webshims/shims/styles/scss/forms-picker.scss b/public/webshims/shims/styles/scss/forms-picker.scss index 7ff1d465..a80f4519 100644 --- a/public/webshims/shims/styles/scss/forms-picker.scss +++ b/public/webshims/shims/styles/scss/forms-picker.scss @@ -474,3 +474,26 @@ $button-bgcolor: #f5f5f5; @extend %#{$class}; } } + +.capture-popover .ws-po-box { + padding-left: em(4); + padding-right: em(4); +} + +.ws-videocapture-view { + position: relative; + height: 0; + width: 100%; + padding-bottom: 70%; + + .ws-video-overlay, + video, + .polyfill-video { + position: absolute !important; + top: 0; + left: 0; + width: 100% !important; + height: 100% !important; + } +} + diff --git a/public/webshims/shims/styles/scss/shim.scss b/public/webshims/shims/styles/scss/shim.scss index 60879d69..c7e97f63 100644 --- a/public/webshims/shims/styles/scss/shim.scss +++ b/public/webshims/shims/styles/scss/shim.scss @@ -602,7 +602,8 @@ summary.summary-has-focus { outline-offset: -1px; } -.ws-custom-file { +.ws-custom-file, +.ws-capture-file { position: relative; overflow: hidden; @@ -632,7 +633,9 @@ summary.summary-has-focus { margin-right: 0.4em; float: left; } +} +.ws-custom-file { .ws-file-value { display: block; overflow: hidden; @@ -640,39 +643,6 @@ summary.summary-has-focus { text-overflow: ellipsis; } - &:hover > button, - &.ws-mouseenter > button, - > input[type="file"]:focus ~ button { - background: #fff; - border-color: #999; - background: #eee linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1)); - } - - - &:hover > .ws-file-value, - &.ws-mouseenter > .ws-file-value, - > input[type="file"]:focus ~ .ws-file-value { - border-color: #999; - } - - &.ws-active > button, - > input[type="file"]:active ~ button { - border-color: #000; - } - - - &.ws-active > .ws-file-value, - > input[type="file"]:active ~ .ws-file-value { - border-color: #000; - } - - > input[type="file"][disabled] ~ .ws-file-value, - > input[type="file"][disabled] ~ button { - border-color: #bbb; - background: #eee; - color: #999; - } - > input[type="file"], .ws-coverfile { position: absolute; @@ -717,4 +687,74 @@ summary.summary-has-focus { > .moxie-shim { z-index: 20; } + + &:hover > button, + &.ws-mouseenter > button, + > input[type="file"]:focus ~ button { + background: #fff; + border-color: #999; + background: #eee linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1)); + } + + + &:hover > .ws-file-value, + &.ws-mouseenter > .ws-file-value, + > input[type="file"]:focus ~ .ws-file-value { + border-color: #999; + } + + &.ws-active > button, + > input[type="file"]:active ~ button { + border-color: #000; + } + + + &.ws-active > .ws-file-value, + > input[type="file"]:active ~ .ws-file-value { + border-color: #000; + } + + > input[type="file"][disabled] ~ .ws-file-value, + > input[type="file"][disabled] ~ button { + border-color: #bbb; + background: #eee; + color: #999; + } +} + +.ws-sticky { + top: auto; + left: auto !important; + right: auto !important; + bottom: auto; + position: static; + position: -webkit-sticky; + position: -moz-sticky; + position: -ms-sticky; + position: -o-sticky; + position: sticky; + float: none !important; + margin-left: 0; + margin-right: 0; +} + +thead.ws-sticky, +tbody.ws-sticky, +tfoot.ws-sticky { + margin-left: -0.8px; + margin-right: -1px; +} + +.ws-sticky.ws-sticky-on { + position: fixed !important; +} + +.ws-fixedsticky-placeholder { + position: static !important; + visibility: hidden !important; + padding: 0; + border: none; + margin: 0; + left: -999px; + zoom: 1; } diff --git a/public/webshims/shims/styles/shim-ext.css b/public/webshims/shims/styles/shim-ext.css index faada291..a4d94aec 100644 --- a/public/webshims/shims/styles/shim-ext.css +++ b/public/webshims/shims/styles/shim-ext.css @@ -5,7 +5,8 @@ top: -999999px; } -.ws-po-box button, .ws-custom-file > button { +.ws-po-box button, .ws-custom-file > button, +.ws-capture-file > button { display: inline-block; overflow: visible; position: relative; @@ -21,11 +22,13 @@ line-height: inherit; touch-action: none; } -.ws-po-box button::-moz-focus-inner, .ws-custom-file > button::-moz-focus-inner { +.ws-po-box button::-moz-focus-inner, .ws-custom-file > button::-moz-focus-inner, +.ws-capture-file > button::-moz-focus-inner { border: 0; padding: 0; } -.ws-po-box button[disabled], .ws-custom-file > button[disabled] { +.ws-po-box button[disabled], .ws-custom-file > button[disabled], +.ws-capture-file > button[disabled] { cursor: default; color: #888; } @@ -587,17 +590,22 @@ summary.summary-has-focus { outline-offset: -1px; } -.ws-custom-file { +.ws-custom-file, +.ws-capture-file { position: relative; overflow: hidden; } .ws-custom-file > button, -.ws-custom-file > input { +.ws-custom-file > input, +.ws-capture-file > button, +.ws-capture-file > input { box-sizing: border-box; cursor: pointer; } .ws-custom-file > button, -.ws-custom-file > .ws-file-value { +.ws-custom-file > .ws-file-value, +.ws-capture-file > button, +.ws-capture-file > .ws-file-value { position: relative; z-index: 0; display: inline-block; @@ -607,40 +615,18 @@ summary.summary-has-focus { color: #333; transition: 400ms all; } -.ws-custom-file > button { +.ws-custom-file > button, +.ws-capture-file > button { margin-right: 0.4em; float: left; } + .ws-custom-file .ws-file-value { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } -.ws-custom-file:hover > button, .ws-custom-file.ws-mouseenter > button, -.ws-custom-file > input[type="file"]:focus ~ button { - background: #fff; - border-color: #999; - background: #eeeeee linear-gradient(transparent, rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1)); -} -.ws-custom-file:hover > .ws-file-value, .ws-custom-file.ws-mouseenter > .ws-file-value, -.ws-custom-file > input[type="file"]:focus ~ .ws-file-value { - border-color: #999; -} -.ws-custom-file.ws-active > button, -.ws-custom-file > input[type="file"]:active ~ button { - border-color: #000; -} -.ws-custom-file.ws-active > .ws-file-value, -.ws-custom-file > input[type="file"]:active ~ .ws-file-value { - border-color: #000; -} -.ws-custom-file > input[type="file"][disabled] ~ .ws-file-value, -.ws-custom-file > input[type="file"][disabled] ~ button { - border-color: #bbb; - background: #eee; - color: #999; -} .ws-custom-file > input[type="file"], .ws-custom-file .ws-coverfile { position: absolute; @@ -680,6 +666,67 @@ summary.summary-has-focus { .ws-custom-file > .moxie-shim { z-index: 20; } +.ws-custom-file:hover > button, .ws-custom-file.ws-mouseenter > button, +.ws-custom-file > input[type="file"]:focus ~ button { + background: #fff; + border-color: #999; + background: #eeeeee linear-gradient(transparent, rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1)); +} +.ws-custom-file:hover > .ws-file-value, .ws-custom-file.ws-mouseenter > .ws-file-value, +.ws-custom-file > input[type="file"]:focus ~ .ws-file-value { + border-color: #999; +} +.ws-custom-file.ws-active > button, +.ws-custom-file > input[type="file"]:active ~ button { + border-color: #000; +} +.ws-custom-file.ws-active > .ws-file-value, +.ws-custom-file > input[type="file"]:active ~ .ws-file-value { + border-color: #000; +} +.ws-custom-file > input[type="file"][disabled] ~ .ws-file-value, +.ws-custom-file > input[type="file"][disabled] ~ button { + border-color: #bbb; + background: #eee; + color: #999; +} + +.ws-sticky { + top: auto; + left: auto !important; + right: auto !important; + bottom: auto; + position: static; + position: -webkit-sticky; + position: -moz-sticky; + position: -ms-sticky; + position: -o-sticky; + position: sticky; + float: none !important; + margin-left: 0; + margin-right: 0; +} + +thead.ws-sticky, +tbody.ws-sticky, +tfoot.ws-sticky { + margin-left: -0.8px; + margin-right: -1px; +} + +.ws-sticky.ws-sticky-on { + position: fixed !important; +} + +.ws-fixedsticky-placeholder { + position: static !important; + visibility: hidden !important; + padding: 0; + border: none; + margin: 0; + left: -999px; + zoom: 1; +} /* style picker api */ /* how to use: diff --git a/public/webshims/shims/styles/shim.css b/public/webshims/shims/styles/shim.css index ae1a9b09..5765edb8 100644 --- a/public/webshims/shims/styles/shim.css +++ b/public/webshims/shims/styles/shim.css @@ -5,7 +5,8 @@ top: -999999px; } -.ws-po-box button, .ws-custom-file > button { +.ws-po-box button, .ws-custom-file > button, +.ws-capture-file > button { display: inline-block; overflow: visible; position: relative; @@ -21,11 +22,13 @@ line-height: inherit; touch-action: none; } -.ws-po-box button::-moz-focus-inner, .ws-custom-file > button::-moz-focus-inner { +.ws-po-box button::-moz-focus-inner, .ws-custom-file > button::-moz-focus-inner, +.ws-capture-file > button::-moz-focus-inner { border: 0; padding: 0; } -.ws-po-box button[disabled], .ws-custom-file > button[disabled] { +.ws-po-box button[disabled], .ws-custom-file > button[disabled], +.ws-capture-file > button[disabled] { cursor: default; color: #888; } @@ -587,17 +590,22 @@ summary.summary-has-focus { outline-offset: -1px; } -.ws-custom-file { +.ws-custom-file, +.ws-capture-file { position: relative; overflow: hidden; } .ws-custom-file > button, -.ws-custom-file > input { +.ws-custom-file > input, +.ws-capture-file > button, +.ws-capture-file > input { box-sizing: border-box; cursor: pointer; } .ws-custom-file > button, -.ws-custom-file > .ws-file-value { +.ws-custom-file > .ws-file-value, +.ws-capture-file > button, +.ws-capture-file > .ws-file-value { position: relative; z-index: 0; display: inline-block; @@ -607,40 +615,18 @@ summary.summary-has-focus { color: #333; transition: 400ms all; } -.ws-custom-file > button { +.ws-custom-file > button, +.ws-capture-file > button { margin-right: 0.4em; float: left; } + .ws-custom-file .ws-file-value { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } -.ws-custom-file:hover > button, .ws-custom-file.ws-mouseenter > button, -.ws-custom-file > input[type="file"]:focus ~ button { - background: #fff; - border-color: #999; - background: #eeeeee linear-gradient(transparent, rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1)); -} -.ws-custom-file:hover > .ws-file-value, .ws-custom-file.ws-mouseenter > .ws-file-value, -.ws-custom-file > input[type="file"]:focus ~ .ws-file-value { - border-color: #999; -} -.ws-custom-file.ws-active > button, -.ws-custom-file > input[type="file"]:active ~ button { - border-color: #000; -} -.ws-custom-file.ws-active > .ws-file-value, -.ws-custom-file > input[type="file"]:active ~ .ws-file-value { - border-color: #000; -} -.ws-custom-file > input[type="file"][disabled] ~ .ws-file-value, -.ws-custom-file > input[type="file"][disabled] ~ button { - border-color: #bbb; - background: #eee; - color: #999; -} .ws-custom-file > input[type="file"], .ws-custom-file .ws-coverfile { position: absolute; @@ -680,3 +666,64 @@ summary.summary-has-focus { .ws-custom-file > .moxie-shim { z-index: 20; } +.ws-custom-file:hover > button, .ws-custom-file.ws-mouseenter > button, +.ws-custom-file > input[type="file"]:focus ~ button { + background: #fff; + border-color: #999; + background: #eeeeee linear-gradient(transparent, rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1)); +} +.ws-custom-file:hover > .ws-file-value, .ws-custom-file.ws-mouseenter > .ws-file-value, +.ws-custom-file > input[type="file"]:focus ~ .ws-file-value { + border-color: #999; +} +.ws-custom-file.ws-active > button, +.ws-custom-file > input[type="file"]:active ~ button { + border-color: #000; +} +.ws-custom-file.ws-active > .ws-file-value, +.ws-custom-file > input[type="file"]:active ~ .ws-file-value { + border-color: #000; +} +.ws-custom-file > input[type="file"][disabled] ~ .ws-file-value, +.ws-custom-file > input[type="file"][disabled] ~ button { + border-color: #bbb; + background: #eee; + color: #999; +} + +.ws-sticky { + top: auto; + left: auto !important; + right: auto !important; + bottom: auto; + position: static; + position: -webkit-sticky; + position: -moz-sticky; + position: -ms-sticky; + position: -o-sticky; + position: sticky; + float: none !important; + margin-left: 0; + margin-right: 0; +} + +thead.ws-sticky, +tbody.ws-sticky, +tfoot.ws-sticky { + margin-left: -0.8px; + margin-right: -1px; +} + +.ws-sticky.ws-sticky-on { + position: fixed !important; +} + +.ws-fixedsticky-placeholder { + position: static !important; + visibility: hidden !important; + padding: 0; + border: none; + margin: 0; + left: -999px; + zoom: 1; +} diff --git a/public/webshims/shims/swf/JarisFLVPlayer.swf b/public/webshims/shims/swf/JarisFLVPlayer.swf index 6d1fb7f8..cdf8259f 100644 Binary files a/public/webshims/shims/swf/JarisFLVPlayer.swf and b/public/webshims/shims/swf/JarisFLVPlayer.swf differ diff --git a/public/webshims/shims/track-ui.js b/public/webshims/shims/track-ui.js index e18dcb6b..983fefb2 100644 --- a/public/webshims/shims/track-ui.js +++ b/public/webshims/shims/track-ui.js @@ -48,7 +48,10 @@ webshims.register('track-ui', function($, webshims, window, document, undefined) var usesNativeTrack = function(){ return !options.override && support.texttrackapi; }; - + var requestAnimationFrame = window.cancelAnimationFrame && window.requestAnimationFrame || function(fn){ + setTimeout(fn, 17); + }; + var cancelAnimationFrame = window.cancelAnimationFrame || window.clearTimeout; var trackDisplay = { update: function(baseData, media){ if(!baseData.activeCues.length){ @@ -169,20 +172,42 @@ webshims.register('track-ui', function($, webshims, window, document, undefined) return $.extend([], cueListProto); }; } + + function triggerCueEvent(cue, type, baseData, media, trackIndex){ + var trackElem, compareTrack; + var cueChange = $.Event('cuechange'); + if(!baseData.trackElements){ + baseData.trackElements = media[0].getElementsByTagName('track'); + } + + trackElem = baseData.trackElements[trackIndex]; + + if(trackElem){ + compareTrack = (webshims.data(trackElem, 'trackData') || {track: $.prop(trackElem, 'track')}).track; + if(compareTrack != cue.track){ + trackElem = null; + } + } + $.event.trigger(cueChange, null, cue.track, true); + + if(trackElem){ + $.event.trigger(cueChange, null, trackElem, true); + } + + $.event.trigger(type, null, cue, true); + } - mediaelement.getActiveCue = function(track, media, time, baseData){ + mediaelement.getActiveCue = function(track, media, time, baseData, trackIndex){ if(!track._lastFoundCue){ track._lastFoundCue = {index: 0, time: 0}; } - if(support.texttrackapi && !options.override && !track._shimActiveCues){ + if(!track._shimActiveCues && support.texttrackapi && !options.override){ track._shimActiveCues = mediaelement.createCueList(); } var i = 0; - var len; - var cue; - + var len, cue, delay; for(; i < track.shimActiveCues.length; i++){ cue = track.shimActiveCues[i]; if(cue.startTime > time || cue.endTime < time){ @@ -191,10 +216,20 @@ webshims.register('track-ui', function($, webshims, window, document, undefined) if(cue.pauseOnExit){ $(media).pause(); } - $(track).triggerHandler('cuechange'); - $(cue).triggerHandler('exit'); - } else if(track.mode == 'showing' && showTracks[track.kind] && $.inArray(cue, baseData.activeCues) == -1){ - baseData.activeCues.push(cue); + + + triggerCueEvent(cue, 'exit', baseData, media, trackIndex); + + + } else { + delay = cue.endTime - time; + if(baseData.nextUpdateDelay > delay){ + baseData.nextUpdateDelay = delay; + baseData.nextEvent = cue.endTime; + } + if(track.mode == 'showing' && showTracks[track.kind] && $.inArray(cue, baseData.activeCues) == -1){ + baseData.activeCues.push(cue); + } } } @@ -210,20 +245,182 @@ webshims.register('track-ui', function($, webshims, window, document, undefined) if(track.mode == 'showing' && showTracks[track.kind]){ baseData.activeCues.push(cue); } - $(track).triggerHandler('cuechange'); - $(cue).triggerHandler('enter'); - + + triggerCueEvent(cue, 'enter', baseData, media, trackIndex); + track._lastFoundCue.time = time; track._lastFoundCue.index = i; - + + delay = cue.endTime - time; + if(baseData.nextUpdateDelay > delay){ + baseData.nextUpdateDelay = delay; + baseData.nextEvent = cue.endTime; + } } if(cue.startTime > time){ + delay = cue.startTime - time; + if(baseData.nextUpdateDelay > delay){ + baseData.nextUpdateDelay = delay; + baseData.nextEvent = cue.startTime; + } break; } } }; - + var filterTrackImplementation = function(){ + return webshims.implement(this, 'trackui'); + }; + var implementTrackUi = function(){ + var baseData, trackList, updateTimer, updateTimer2, lastDelay, lastTime, invalidTracksTimer; + var treshHold = 0.27; + var elem = $(this); + var recheckI = 0; + var recheckId; + var reCheck = function(){ + recheckI++; + + //if recheckI is over 5 video might be paused, stalled or waiting, + //in this case abort and wait for the next play, playing or timeupdate event + if(recheckI < 9){ + if(elem.prop('currentTime') > baseData.nextEvent){ + recheckI = undefined; + getDisplayCues(); + } else { + recheckId = requestAnimationFrame(reCheck); + } + } else { + recheckI = undefined; + } + }; + var getDisplayCues = function(e){ + var track, time; + if(!trackList || !baseData){ + trackList = elem.prop('textTracks'); + baseData = webshims.data(elem[0], 'mediaelementBase') || webshims.data(elem[0], 'mediaelementBase', {}); + + if(!baseData.displayedActiveCues){ + baseData.displayedActiveCues = []; + } + } + + if (!trackList){return;} + time = elem.prop('currentTime'); + + if(!time && time !== 0){return;} + + if(baseData.nextEvent && e && e.type == 'timeupdate' && time >= lastTime && baseData.nextEvent - time > treshHold && time - lastTime < 9){ + return; + } + + lastTime = time; + lastDelay = baseData.nextUpdateDelay; + baseData.nextUpdateDelay = Number.MAX_VALUE; + baseData.activeCues = []; + for(var i = 0, len = trackList.length; i < len; i++){ + track = trackList[i]; + if(track.mode != 'disabled' && track.cues && track.cues.length){ + mediaelement.getActiveCue(track, elem, time, baseData, i); + } + } + trackDisplay.update(baseData, elem); + + clearTimeout(updateTimer); + + if(baseData.nextUpdateDelay <= treshHold && (e || lastDelay != baseData.nextUpdateDelay) && baseData.nextUpdateDelay > 0){ + + lastDelay = baseData.nextUpdateDelay; + + clearTimeout(updateTimer2); + + if(recheckId){ + cancelAnimationFrame(recheckId); + } + recheckI = 0; + updateTimer2 = setTimeout(reCheck, (baseData.nextUpdateDelay * 1000) + 9); + } else if(baseData.nextUpdateDelay >= Number.MAX_VALUE){ + baseData.nextEvent = time + 2; + } + }; + var invalidateTrackElems = function(){ + if(baseData && baseData.trackElements){ + delete baseData.trackElements; + } + }; + var onUpdatCues = function(e){ + if(baseData && e && (e.type == 'addtrack' || e.type == 'removetrack')){ + clearTimeout(invalidTracksTimer); + invalidTracksTimer = setTimeout(invalidateTrackElems, 39); + } + clearTimeout(updateTimer); + updateTimer = setTimeout(getDisplayCues, 40); + }; + var addTrackView = function(){ + if(!trackList) { + if(baseData && 'blockTrackListUpdate' in baseData){ + baseData.blockTrackListUpdate = true; + } + trackList = elem.prop('textTracks'); + if(baseData && baseData.blockTrackListUpdate){ + baseData.blockTrackListUpdate = false; + } + } + //as soon as change on trackList is implemented in all browsers we do not need to have 'updatetrackdisplay' anymore + $( [trackList] ) + .off('.trackview') + .on('change.trackview addtrack.trackview removetrack.trackview', onUpdatCues) + ; + elem + .off('.trackview') + .on('emptied.trackview', invalidateTrackElems) + .on('play.trackview playing.trackview updatetrackdisplay.trackview seeked.trackview', onUpdatCues) + .on('timeupdate.trackview', getDisplayCues) + ; + }; + + elem.on('remove', function(e){ + if(!e.originalEvent && baseData && baseData.trackDisplay){ + setTimeout(function(){ + baseData.trackDisplay.remove(); + }, 4); + } + }); + + if(!usesNativeTrack()){ + addTrackView(); + } else { + + if(elem.hasClass('nonnative-api-active')){ + addTrackView(); + } + elem + .on('mediaelementapichange trackapichange', function(){ + + if(!usesNativeTrack() || elem.hasClass('nonnative-api-active')){ + addTrackView(); + } else { + clearTimeout(updateTimer); + clearTimeout(updateTimer2); + if(recheckId){ + cancelAnimationFrame(recheckId); + } + + trackList = elem.prop('textTracks'); + baseData = webshims.data(elem[0], 'mediaelementBase') || webshims.data(elem[0], 'mediaelementBase', {}); + $.each(trackList, function(i, track){ + if(track._shimActiveCues){ + delete track._shimActiveCues; + } + }); + $( [trackList] ).off('.trackview'); + trackDisplay.hide(baseData); + elem.off('.trackview'); + } + }) + ; + } + }; + if(usesNativeTrack()){ (function(){ var block; @@ -265,102 +462,8 @@ webshims.register('track-ui', function($, webshims, window, document, undefined) webshims.addReady(function(context, insertedElement){ $('video, audio', context) .add(insertedElement.filter('video, audio')) - .filter(function(){ - return webshims.implement(this, 'trackui'); - }) - .each(function(){ - var baseData, trackList, updateTimer, updateTimer2; - - var elem = $(this); - var getDisplayCues = function(e){ - var track; - var time; - - if(!trackList || !baseData){ - trackList = elem.prop('textTracks'); - baseData = webshims.data(elem[0], 'mediaelementBase') || webshims.data(elem[0], 'mediaelementBase', {}); - if(!baseData.displayedActiveCues){ - baseData.displayedActiveCues = []; - } - } - - if (!trackList){return;} - time = elem.prop('currentTime'); - - if(!time && time !== 0){return;} - baseData.activeCues = []; - for(var i = 0, len = trackList.length; i < len; i++){ - track = trackList[i]; - if(track.mode != 'disabled' && track.cues && track.cues.length){ - mediaelement.getActiveCue(track, elem, time, baseData); - } - } - - trackDisplay.update(baseData, elem); - - }; - var onUpdate = function(e){ - clearTimeout(updateTimer); - if(e){ - if(e.type == 'timeupdate'){ - getDisplayCues(); - } - updateTimer2 = setTimeout(onUpdate, 90); - } else { - updateTimer = setTimeout(getDisplayCues, 9); - } - }; - var addTrackView = function(){ - if(!trackList) { - trackList = elem.prop('textTracks'); - } - //as soon as change on trackList is implemented in all browsers we do not need to have 'updatetrackdisplay' anymore - $( [trackList] ).on('change', onUpdate); - elem - .off('.trackview') - .on('play.trackview timeupdate.trackview updatetrackdisplay.trackview', onUpdate) - ; - }; - - elem.on('remove', function(e){ - if(!e.originalEvent && baseData && baseData.trackDisplay){ - setTimeout(function(){ - baseData.trackDisplay.remove(); - }, 4); - } - }); - - if(!usesNativeTrack()){ - addTrackView(); - } else { - - if(elem.hasClass('nonnative-api-active')){ - addTrackView(); - } - elem - .on('mediaelementapichange trackapichange', function(){ - - if(!usesNativeTrack() || elem.hasClass('nonnative-api-active')){ - addTrackView(); - } else { - clearTimeout(updateTimer); - clearTimeout(updateTimer2); - - trackList = elem.prop('textTracks'); - baseData = webshims.data(elem[0], 'mediaelementBase') || webshims.data(elem[0], 'mediaelementBase', {}); - - $.each(trackList, function(i, track){ - if(track._shimActiveCues){ - delete track._shimActiveCues; - } - }); - trackDisplay.hide(baseData); - elem.off('.trackview'); - } - }) - ; - } - }) + .filter(filterTrackImplementation) + .each(implementTrackUi) ; }); }); diff --git a/public/webshims/shims/track.js b/public/webshims/shims/track.js index 5bed9760..a982affd 100644 --- a/public/webshims/shims/track.js +++ b/public/webshims/shims/track.js @@ -66,8 +66,12 @@ webshims.register('track', function($, webshims, window, document, undefined){ var lastCue = this.cues[this.cues.length-1]; if(lastCue && lastCue.startTime > cue.startTime){ webshims.error("cue startTime higher than previous cue's startTime"); + return; } } + if(cue.startTime >= cue.endTime ){ + webshim.error('startTime >= endTime of cue: '+ cue.text); + } if(cue.track && cue.track.removeCue){ cue.track.removeCue(cue); } @@ -159,6 +163,7 @@ webshims.register('track', function($, webshims, window, document, undefined){ for(i = 0, len = added.length; i < len; i++){ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: added[i]})); } + //todo: remove if(baseData.scriptedTextTracks || removed.length){ $(this).triggerHandler('updatetrackdisplay'); } @@ -175,7 +180,7 @@ webshims.register('track', function($, webshims, window, document, undefined){ setTimeout(function(){ $(track).closest('audio, video').triggerHandler('updatetrackdisplay'); trackData.isTriggering = false; - }, 1); + }, 9); } }; var isDefaultTrack = (function(){ @@ -368,15 +373,10 @@ webshims.register('track', function($, webshims, window, document, undefined){ error: error }); }; - if($.ajax && $.ajaxSettings.xhr){ - if(isDisabled){ - setTimeout(createAjax, loadingTracks * 2); - } else { - createAjax(); - } + if(isDisabled){ + setTimeout(createAjax, loadingTracks * 2); } else { - webshims.ready('jajax', createAjax); - webshims.loader.loadList(['jajax']); + createAjax(); } } catch(er){ error(); diff --git a/public/webshims/shims/usermedia-core.js b/public/webshims/shims/usermedia-core.js index 22ab9137..da54c3bc 100644 --- a/public/webshims/shims/usermedia-core.js +++ b/public/webshims/shims/usermedia-core.js @@ -5,6 +5,7 @@ webshim.register('usermedia-core', function($, webshim, window, document, undefi var addUnPrefixed = function(){ navigator.getUserMedia = navigator[webshim.prefixed('getUserMedia', navigator)]; }; + if(srcObjectName != 'srcObject'){ var hasURL = !!(window.URL && URL.createObjectURL); webshim.defineNodeNamesProperty(['audio', 'video'], 'srcObject', { @@ -23,6 +24,32 @@ webshim.register('usermedia-core', function($, webshim, window, document, undefi }); } + (function(){ + var streams = {}; + var _nativeCreateObjectURL = URL.createObjectURL; + var _nativeRevokeObjectURL = URL.revokeObjectURL; + + URL.createObjectURL = function(stream){ + + var url = stream; + if(_nativeCreateObjectURL && !stream._wsStreamId){ + url = _nativeCreateObjectURL.apply(this, arguments); + } else if(stream._wsStreamId) { + url = stream._wsStreamId; + streams[url] = stream; + } + return url; + }; + + URL.revokeObjectURL = function(url){ + if(streams[url]){ + delete streams[url]; + } else if (_nativeRevokeObjectURL){ + return _nativeRevokeObjectURL.apply(this, arguments); + } + }; + })(); + webshim.ready(webshim.modules["usermedia-shim"].loaded ? 'usermedia-api' : 'usermedia-shim', addUnPrefixed); }); diff --git a/public/webshims/shims/usermedia-shim.js b/public/webshims/shims/usermedia-shim.js index 3cabe13c..9ceb6a2a 100644 --- a/public/webshims/shims/usermedia-shim.js +++ b/public/webshims/shims/usermedia-shim.js @@ -1,18 +1,15 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefined, options){ "use strict"; var addMediaAPI; - var streamUrlPrefix = 'webshimstream'; var id = 0; - var streams = {}; var streamCb = {}; var hasSwf = swfmini.hasFlashPlayerVersion('11.3'); - var mediaOptions = webshim.cfg.mediaelement; var mediaelement = webshim.mediaelement; var flashEvents = { - NOT_SUPPORTED_ERROR: 1, - PERMISSION_DENIED: 1, + NotSupportedError: 1, + PermissionDeniedError: 1, //not implemented yet - MANDATORY_UNSATISFIED_ERROR: 1, + ConstraintNotSatisfiedError: 1, onUserSuccess: 1 }; var noSource = function(){ @@ -51,6 +48,13 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi }; addMediaAPI(); + /* + { width: 650 }, + { width: { min: 650 }}, + { frameRate: 60 }, + { width: { max: 800 }}, + { facingMode: "user" } + */ mediaelement.createSWF(media, {srcProp: src, streamrequest: true, type: 'jarisplayer/stream'}); } @@ -73,6 +77,8 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi function LocalMediaStream(data, api, id){ + data._cTNow = Date.now(); + data._cTID = false; webshim.defineProperties(this, { _swf: { value: api, @@ -92,20 +98,34 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi LocalMediaStream.prototype = { - currentTime: 0, stop: function(){ + if(this._data._cTID){ + clearInterval(this._data._cTID); + } mediaelement.queueSwfMethod(this._data._elem, 'api_detach', [], this._data); - }, - getAudioTracks: $.noop, - getVideoTracks: $.noop + this._data.ended = true; + $(this._data._elem).trigger('ended'); + } }; webshim.usermedia = { attach: function(elem, canPlaySrc, data){ + var $media; if(data._usermedia == canPlaySrc.srcProp){ mediaelement.queueSwfMethod(data._elem, 'api_attach', [], data); - $(data._elem).trigger('loadstart'); + $media = $(data._elem).trigger('loadstart'); + data._cTID = setInterval(function(){ + if(data.ended){ + clearInterval(data._cTID); + } else if(!data.paused){ + data.currentTime = (Date.now() - data._cTNow) / 1000; + $media.triggerHandler('timeupdate'); + } + }, 250); + if(!data.paused){ + mediaelement.queueSwfMethod(data._elem, 'api_play', [], data); + } } else { webshim.error('something went wrong'); } @@ -120,30 +140,7 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi } }; - URL._nativeCreateObjectURL = URL.createObjectURL; - URL._nativeRevokeObjectURL = URL.revokeObjectURL; - URL.createObjectURL = function(stream){ - - var url = ''; - if(URL._nativeCreateObjectURL && !stream._wsStreamId){ - url = URL._nativeCreateObjectURL(stream); - } else if(stream._wsStreamId) { - url = stream._wsStreamId; - streams[url] = stream; - } - return url; - }; - - URL.revokeObjectURL = function(url){ - if(streams[url]){ - delete streams[url]; - } - if(URL._nativeRevokeObjectURL){ - return URL._nativeRevokeObjectURL(url); - } - }; - webshim.usermediastreams = streams; addMediaAPI = function(){ if(!webshim.mediaelement.createSWF){return;} @@ -161,10 +158,10 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi streamCb[data._usermedia].fail({name: jaris.type}); }; $.extend(mediaelement.onEvent, { - NOT_SUPPORTED_ERROR: fail, - PERMISSION_DENIED: fail, + NotSupportedError: fail, + PermissionDeniedError: fail, //not implemented yet - MANDATORY_UNSATISFIED_ERROR: fail, + ConstraintNotSatisfiedError: fail, onUserSuccess: function(jaris, data){ revert(data); streamCb[data._usermedia].success(new LocalMediaStream(data, data.api, data._usermedia));