From 7da30d42a5c2feeebae2f2e65e7042b3a4bc9117 Mon Sep 17 00:00:00 2001 From: echarp Date: Wed, 3 Sep 2014 00:57:03 +0200 Subject: [PATCH] Bundle update, including new webshims version --- Gemfile.lock | 8 +- public/webshims/extras/modernizr-custom.js | 511 --- public/webshims/polyfiller.js | 284 +- public/webshims/shims/canvas-blob.js | 97 + public/webshims/shims/combos/1.js | 28 +- public/webshims/shims/combos/10.js | 59 +- public/webshims/shims/combos/11.js | 3 +- public/webshims/shims/combos/12.js | 32 +- public/webshims/shims/combos/13.js | 32 +- public/webshims/shims/combos/15.js | 73 +- public/webshims/shims/combos/16.js | 87 +- public/webshims/shims/combos/17.js | 3 +- public/webshims/shims/combos/2.js | 84 +- public/webshims/shims/combos/21.js | 169 +- public/webshims/shims/combos/22.js | 18 +- public/webshims/shims/combos/23.js | 14 +- public/webshims/shims/combos/25.js | 194 +- public/webshims/shims/combos/27.js | 78 +- public/webshims/shims/combos/28.js | 3 +- public/webshims/shims/combos/3.js | 70 +- public/webshims/shims/combos/30.js | 70 +- public/webshims/shims/combos/31.js | 70 +- public/webshims/shims/combos/34.js | 74 +- public/webshims/shims/combos/4.js | 56 +- public/webshims/shims/combos/5.js | 3 +- public/webshims/shims/combos/6.js | 3 +- public/webshims/shims/combos/7.js | 84 +- public/webshims/shims/combos/8.js | 84 +- public/webshims/shims/combos/9.js | 59 +- public/webshims/shims/combos/98.js | 6 +- public/webshims/shims/combos/99.js | 6 +- public/webshims/shims/dom-extend.js | 56 +- public/webshims/shims/es6.js | 52 +- .../{filereader.js => filereader-xhr.js} | 78 +- public/webshims/shims/form-core.js | 14 - public/webshims/shims/form-number-date-ui.js | 3 +- public/webshims/shims/form-shim-extend.js | 3 +- public/webshims/shims/form-validation.js | 23 +- public/webshims/shims/form-validators.js | 29 +- public/webshims/shims/geolocation.js | 91 +- public/webshims/shims/jajax.js | 1262 ------ public/webshims/shims/jme/controls.css | 8 +- public/webshims/shims/jme/controls.scss | 3 +- public/webshims/shims/jme/mediacontrols.js | 6 +- public/webshims/shims/mediacapture-picker.js | 42 + public/webshims/shims/mediacapture.js | 159 + public/webshims/shims/mediaelement-core.js | 14 +- public/webshims/shims/mediaelement-jaris.js | 60 +- public/webshims/shims/mediaelement-yt.js | 28 +- .../{combos/26.js => moxie/js/moxie-html4.js} | 3414 +++++++++++------ .../shims/moxie/js/{moxie.js => moxie-swf.js} | 2224 ++++------- .../shims/moxie/silverlight/Moxie.cdn.xap | Bin 62648 -> 0 bytes .../shims/moxie/silverlight/Moxie.min.xap | Bin 16930 -> 0 bytes public/webshims/shims/sticky.js | 585 +++ public/webshims/shims/styles/forms-picker.css | 20 + .../shims/styles/scss/forms-picker.scss | 23 + public/webshims/shims/styles/scss/shim.scss | 108 +- public/webshims/shims/styles/shim-ext.css | 109 +- public/webshims/shims/styles/shim.css | 109 +- public/webshims/shims/swf/JarisFLVPlayer.swf | Bin 28011 -> 28056 bytes public/webshims/shims/track-ui.js | 325 +- public/webshims/shims/track.js | 18 +- public/webshims/shims/usermedia-core.js | 27 + public/webshims/shims/usermedia-shim.js | 71 +- 64 files changed, 5622 insertions(+), 5704 deletions(-) delete mode 100644 public/webshims/extras/modernizr-custom.js create mode 100644 public/webshims/shims/canvas-blob.js rename public/webshims/shims/{filereader.js => filereader-xhr.js} (86%) delete mode 100644 public/webshims/shims/jajax.js create mode 100644 public/webshims/shims/mediacapture-picker.js create mode 100644 public/webshims/shims/mediacapture.js rename public/webshims/shims/{combos/26.js => moxie/js/moxie-html4.js} (76%) rename public/webshims/shims/moxie/js/{moxie.js => moxie-swf.js} (81%) delete mode 100644 public/webshims/shims/moxie/silverlight/Moxie.cdn.xap delete mode 100644 public/webshims/shims/moxie/silverlight/Moxie.min.xap create mode 100644 public/webshims/shims/sticky.js 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,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) 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 f0d499f923a8289bf2114e999f8284291243865b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62648 zcmY&;1CVF2mv!5=ZM%Egwr$(?v~Alqrfu7{jrp~$o&Q$tx8J7TO;UMPuacLOn{#rb zC<6+H1_T5J1@y~~QFI<0Vr~iu2uKbX2ngw4DdgxVXJl_>Zsy|3;Av!M8yYWXJ;a10 z{t~(?bPkjRC8sTG2URkKwiE`y_X+~XiA_MG$*+wjpw@`U73hXC{pE1_o7Ls@!`~pV zZJD%vm_-{?X1DYhmbw@Klub2%E|};pWhq=)i!FX4TdA?JtLo<-{n`J`Zl5mUMeGus z)`XZYY>@0^g-yD@`b=)1!og%`=Z%P2QwiSqnAcR_BLi^&Da>{({Y{dRQQfv7Or_5! zz|8R`yDTSpCkpAe!zP>-JqK~n`k4JJWFWJ!c_8W~pX_m1*1!#-`2Plu2f`?NvK+s& z0|^Agh71IR@NeMa(jpGdW{gtO5)7`MuBjRW_PD=LdLC%oxoznRmIPVSbD>WQOz|W@ zc~I98f;Mnh^pdy$6g*^GQN4DEA5tH%A64UNbY|Td@JJ#%av0V6J>F`cbA8{x`&yJF z`s8^~C68VvMXg)hyqSotZd^B$cHeFbzO?-q^<+Q~;$_~~6w)=`XUYXn9AU_JS3O}a)_O1|5d_`Xk$Kvo zeDlJmfJU{fVmgeK{MEkss#sfX*=+C8kImMkt~JUD2m?@EFkeERdH82nueE&RSK}Vt zCe2>g{hsH+lZZzfKA&w5aq*OJx3(c@oB-YBdtSQ?x2+p1ez;~O-%tOI0Xk6Lq+;lh zsb>ypduWS&$N4J9^qYL|oteT8=ee`kU1WWC$zCSMe2f-^*Lswol4U}=NY0q{^$~hTwO*t1j(!EiQv!EMsU*pfwX7Bq`CB02`!)OfPkWD^Z}*QLXoO${h5R$E9L8x- znZqadJg+TrDx0k+o_70Xtj^%~pn<6!Nr z<8^L}L8wSOR(FbXBe>vrxLuDNNc;F!vG%4B{0xpEY)N3p3bcGUG7$X{s0J|P5YtB1 z_1A#4>l;)^vzud+8LHge)mJ0JYxC^Kk**HEr=$3K{lhr{n%5JbjIOGu7N-E81-JJ! zO!42actfPTB@XcLkqTxt*Er`F=x%=D$^1${d!%P5V~%ASKJdcr!7a=2#mll7cKse|Zp?HB;~oJ3WmNhdXMs@3yGR zewHxk&t!J|(OD*^l?KDaMTv`ia*bPG7-~JlXW;Sn>3BUkMRD6wGXIFG+;KITx(ZP? zzJ%fmzxtF}H&ZP+v=y;-Et7$&|DBu+`6H{-UFRx;6!3{U%Y49rCKKRk!iljp5?w*T zi9;oE{_I%Z5-X*pBm}dE*kHeN+Wc(ocBfr%hmd`a%T6k}gD#sV6d(^*wPcJTK|&Dq zIkWgf`grM8m_M*ac=`^##$`q)nl#fSLh&r6%Tb;^6{!aqU#uNZ^b3>!wxuHm5f0bM zy}1zRfaEv+1UuT^@qYBZsSM1fOOI~1o<1WnzilCV&w=QhY&&F$a20aNvV^iVE1VnLMw_eUfNUr=(rSH(@Q6<`07~>IQIgC zn1L;ql~l8VHWSbLn9GVsWi&1^!e*cY_f}Vw<@!dx@jxx| zD}GgX#^-4IuLw)ufVIhhj(S4f3S9YBGC^If!~H_nU)j|tYP0ml?R84h^8{b8vD6$} zFcGfKlSp*rT%lsydT}JJPkK}ERtt@icelY`n)s|64&!e6{w&jfJfh#H`A(IO2(_-u zBBo*HEJ(cQ5@3#y6tI{Rt<*MH#2-7C#`i@CDaHH=BOZ5BGG7Q%>Ha)I1OgNBIQr4L zVL6M|!Z=g@Er>C{eO@mK@x$~;>FDqLU=wFRLQYLfYSgPa)AqmRAsC;}b%X%n7Yeai zM|PSNB*qX?gQ<>D@fL{-ifA7nhy+W)^O+3eo{C9L@I|_CD=NK>;>eqVgT&IrZ|$aq zP5QpR<_z<-<0R_n$IdofII~#N$qKA&Y(UJD^yqqj)nXhy_EM@%yKwEK>hNa3{8f*Y za*IFW4wP}yiqS@51KmWgpfWwkg}{PLlyGgdjJYx5&1!sIC5^>?8X)aPEuhvZ!*}|~ zZGSet10s1xq#1)QlbQfG?1|mBB1JacneDB$x0XCt7X6Jqh7DoKz3Gqx;cvc!5b(06NcCAFd20L{Zud)8bAJq>ZUxAYM&$Mm$qEHRQ@NRo!;^f zi7Zs0_s?reGu--x7+lZi?03hS7`4fQ6P53H@N5{PE}YVZCpM||O1M)Gz=`&W{b3O-6qCH}zmI^XA<25_dxN$8ObTK>!f zDAl~FN~sj-J6tu5NBW0yD`gcp)B>5QBJCggKf%x74LTEd2=fWO+P!n61k#{QgT-yz zDJbRxcw=n#(#&JOm)CwimA9)+S+|n^Pz#aBU6RRR34Miebx+f`j^LhrI?CFl$Rtl= z`NmEM6_^(vrOjc|`u6v7WoNk-nP1VFmlw;PMAJqlmu-1Y^v0;cV2sMcd?NiRh^1W? zcV>9eANRM1`-~JxCWZ$eq(@hSi-oQ=hNWjNB0l}jOZUgO!$yfirPi;1N$==Gg8Ey zqEoT_4wipQx0_z}2mZfAz<}@gVgVEg$m|~(`2UE2w2;()6M@v3xI-?au^YcA<$UuJ zI38^)M$*3nNac4lWHooQEKhtDqvz-Fj_4F6R6#5GF+yoZZ zz@t#$X#xKo+Qi)ANN(QF(_JsR&Qjry!>A9D5zXYrX6+dO`|+?Q5HmBlRQa%_7lQaC z@%r^}Cg9gECD{4|_UeaNFy0J#;=RV#1tFDc<4efX$1fh=ve_DFa#QiikJq&cPiwQc z2?&|T5B0fof-J=K8)E(=V);3`mIgv52rke8*f$w=&hNav#`TRT8Mixev&2=9=OZl- zjy4ErRJcW;wq>Alvz)(PmpIpL_T$Cw61Q@?Dgp(y6cJTI-4;JlGIZ@Hs=o-!ve#lV z>1q4k@0?ITVp_q4W`NSvaS^S_SL_ad6@!qDAhzs+e!AP=v}7E6z@;H{EDsKjt$T3a z>#O3$gSRhw*aB%N8+;pxG;V#~k2v+`ChyjMG969uhC}ZpXv#DETOpMo5MYC=>vkN1 z7LJ4;(`lH^9uckwVH?a-jI_q%WKVFOuPe6`te@vyRorVehH&|j_!Um;UHcMelfd24 z71k8Mk!yDpId10z@;uW9-|C+i{MxB1Y(s@UKEjet5~`(DvN--{9-2yMtBA>06G*?L zpP)mzn@PDKkj~sIb@Gs)O??f?A{spfn=T}4<}OshjA4cbI891LaTYGwS<~64m|iY*Y)quuGn zsXtX*gu$X{zI3tROqHEh8dN3l$~P+-8SGA_cmD+>wu){@mReTBLW3B{?4%;R&RN8) zQJPc-B$_34BMPjasB&3+!piJ?XPP{WhV?=6oUCDi4qckRAOlfYAp!jg>@MJGpjecF z#)8c^*mr6IijA>F2*b5T6hua?s6@oi-cuNH1E_d-I)NmevImWI;vwV!+2+n8)axRZ zEtwkMS-y9wDgn$hku=cjEusT$+Ot#%T{V^3X-+K*u{PPLGN`u{M?S}L&SEBYIhZ50 zV_nU)ADhDX57$;8b@&PHNRkj%!bZVlPBPN#>=L9Dk_lVbSJBBYX{oZNw@{y;WEb=} z!z%|n&y6ngD+bb+ot=S>5X`0*op(+cHtXBo1--!qh-==D@CjBda<(SNr2SBWQJ?uL_X0GBLAv zG5e1L&{Ljq-XcQkeL&;kCugYuY0dINk}7%DM&^n>4O+bym0;z#0)P{YH5Av5F ztIi!VSEvEXKQP&S7hxD6YzM)LR}coFH#$2{9NYHcSeYxY-SX1P%ziIqll`ECNW4Mf zvt)zFS-8YhSr;*3hhoJpZwL|LQ?KL5T-bCbnDac4N#Sg|zWjK`;oWX8;t*%9DtU{R z8((5k&x-Qf+_AZKW2|1@BzLxJ_mv@dRrGS_m*K*gaWSOm$gf=;Nd1@JrcCENGw-Ji zPok+RaBRAy(w*tE1SX7ctkB}k0$sr5ZiCGjq%u)^uBgW3$~SgODgS7|qwz2UhOCWaN!ccY6}Tnv*R0g!|aa}%8Tk(ovLoO?VW|gHL3^@EWj<>H+vkY1XjD5Y5|znEI#KMg|&5YUohV zz8y4NQ>^4GIa^6&=ElzG_y28rZN=eu)2$o`i?C#hNEiOzbquB zjl@b1m)wNNYgV1fX~OP*QHxDXWs0J=nwEBosHK2Bhrm`~G*cy^=@t8Ae#(tl)4ur@ zjtisx8af0Ov3M*rEJj0Mr>8P7Pgo+)Z3;mdCsEltkF&*~OI3_NWL48mVNR~3N*y)} zQ;~jx>^wl93Xs+>RAWg7xiHCzK#Bx&BFEJ-UcQ}+G?dY;uYQ#gXZ%$R?yQFV>G6P{ zu=juQ+z#CI2k0N3pZ;xV|Ag)Ts9I$)AyGN8|G>FLWhQQk390vk8p3Hq+DdC5=(3iE z+Ey$*wR17Ae3p#ajd#@j{lON`lT1I*NjdEvC_DMY_szUF|MUCJrbXYm;1`{t*+;T? z{ALNO@58a-)bDvP#K68}dF%I}c;$Hd&fg(fpyz3iyX_F|3QP=|K-^6D9AK;0AYrUn z<#q;USV1?S1NSXN-KBB5gQn}$b;K=TSK;@p*Gx(5aUm5TgzeC1#lMg&>mQuxtwW({kjaC(N?m~!-@m<0NRjU z@}&hbRzGGr*u0>M>v=2hUfj~J^M$C7H+LRMYEiRGxk;aAW)a@9?nGq;iWbMTkOJ~6 zSgt6PyNV&cNK4c}v8$1QIFlej&4bxE2t_^I#KXlAd8N|ZfKh~qVJ{mar0X|rucL$zuM9uq*(Za&Z(CUuc0nJy%{;sX9c$Z8F4|$eEb+A8VJxTX9 zK0aY>H}y=VQ!_9`N?iQk}Z27>-q$T@ggnK78! z+D`XC`{Io>a`E!8Zn5(CNY*BrYb4dCB5v5!lIhTHjYH_L7=oUL0d=vAVnUF?B3@^a z(%Ha;06}N0XBgrkm1j{H(nd%;Tr4}0<7`+31` z-qHK5rtvR%XuRZbJ@SjGpoxX|fkL94Ad7wCsv>+jzwnY!~ZWy4@=&}M!l?xFIr`SkZhhNBhH!B*h?cxj8#bxvI#vcnzw@Xq+6=x` zMW8x-nde;Ejqn+w(`9?>FE&~P_4AUl7T=k`MC?@d=i5=SlXR@uOIlXdn=X;HDrW~p z3Fk*gsXJ%SjbyTRQ^%o|Lqa1i$&Y=lf-0>FV4(e~*3~`Bk7frm9%lqUCAS^d2}oar1l{vFO!5~a z+oi*J0bF9Boua$N>csWC=ohL>?2nZvWN68i$BkJGw%pAsDtL!Zw&mJlv-3D;ZIH%Y zs;e98zYIWjHZqKSxR%Y#m(cqY^@s~Qc_2~k5GXIzbLAPgqeUf2>m>IyMm&#B$OF_; zHt{)~!5vXfgT@j!Tz;<`H+93Hn6d(Np~y|9b0Gl~1(MaZE$9N82w5;v8x9nh(;)S`je$ z2N?npqFsM!yTR{Y5d`jZK??y$Oqr~+_=)*k#UBM}yt_Gy)O8}(wAD(|wR6Ghx^(Vy z$^`AP_+aX5Kz185)Q6U3>y4Z-YK^R0^J~?~*FbO7F@kl5E=|$xtkJzyBs9|PRoh7j zM$^jhj$)gvVGg;gh)f<`8^hwX?Si$dAfDEN*pY$p)x;B%2l}94)OWc1J2ge9?%h&` z!9&`$d%@nTF`kr^X@et3(<-=0Q$$?Si58wlJR;S(f+_g1|AI}kaFD3IPFh8Y$GEC9#dKu3vkdz?%MoU67kSwNGhY83t9j*X~NEJ`S17lss{J&MS=qB zB0a9oJ<2#XxRt8risQR^`DOV@!ANaYIS9A;Vl#;ZpAv+F4l9}jF{)P8l_jfo;wT>z zfT>y!x64pOT0xSf+*6;|=MNZ2-_uUQCy+!1`j(xfi4<~wi9-kD%_nJP&kcyTCxkO| ziuc8`4KfL+AW*TDJIme3sm6_UqsJ}GN^VO*DR)p7R1`|`WHCGY)Qaxj8XRtK% zkWULYoN8hxC+F}C8f6{MOO+K%4R#3naFRI7f#{8?959w@RQwoSL$gFCp%>J8(Sfox zNTftx8KeV5e#%%A9Kau0f>u8^xOL7dq@gEU8}h-V6ok}g%5g|KR7O&un(%|?t+=GR zA!^V!ZkFF_$XRpax;G??g1yzoIWVKlSi65AvRAKW28ju-Ybl?PEbvLR>p>qZG6lzp z|FV_h>ICp0$veYdfONv9pi6AKXdP3nnlZh=Wv+#_vg6^^cUTw)ovqLY7QBB`5IKuZ z3e=h>GV#KeYRldVsOg9T5x*x!{!x?G_oZUo=U0Nib8Nz_8V0R0%$!YDHAcc@BRL(A zM`e-=iLM}Moc;R4)e|Pjei?(-Y)O!nHn0#WW^Hl?Q=5jO%*VO1mM!?F_~ujg)=Y$xlGO`#l~9g?6nAFEF9>Wo9MQ3m{>d7Wp_5f%Weay<^np#Z zLnaz1LwnXgQ0QbIG>m4j7dQPNAxTj%d6c?-5&^w}wu=0UE~(s?CP)UI;8AU9I^i^g zK%@c4!g8dLO~Sjz;(K#F?-Y}5-*zY2{6@c*_QZRi9B2*3LY~~ZV|}j>GZi#uF>Tbw zIYGlmy|^qoftooC0;1!LUOT`%t5=Mr##SG4nd@$%qKDZ)DP)6Bk(wG=FuSb5)JzkA zxKNA2K23xiTNZW#e7h9qNztyMz{%yAh-nll=VD14Q=I&6b8JaAG57mRlYzB2Z`QpB<_Ko<)rZ5V$_KGJm zGTv7@{0m96rPkXFzIX2a`%~fL<$-=)iER$V+@2Kfj-9J=U%ue-NK4&%ak{CkRCU8* zmh@;U0$hI-NHJu-mmoUnu|q88K=mZMX*on*^%u!R?acoUBDml%Y*h23)(hH>#imn@EKijqs{l_lO!ppsa6Z_GN zN83|-vAch3^svD83h;rXp|qGCA>n~*{4v}Mw$>#W`jWCaD~NWQY+Nu|us#|&ziE-l z@&eNc9aL;t#){;jzT4N^r;{ zyQXX#4i8Hz3gKzJX@)HdTF7Mu&!}pDM)}H@G$jC?@x`=`BCA53*~X5U zUfx;)$^yA=1Rwt%P+(U((u^GHngK79XDK~bTLivH;t+E_S*%Dw)w&&cEb-b5`wRt> zIEy6tw?GshT9W|(p#I<}OvVPU%3;=2vNxUNQ0&SYT&0RhlKsAabs;cm0Rzh%FlVIVg zxfAwOVney`=p2^cD&*u*h%iAzSn#Es`67=KD8%x@z^e)?lHt?lKl>2C$vAm07PZM^ zx%V5r!3Qw3t8Nb_+AAmMw)6yt-3R!?{;$4fGQ9nnp<-Upgb*5_lN3e z!REomO_;0hfZU~0ZuWTCz|h z?uQo#92sA7rCP?mVdeyyV*x1pw~Vr3xrv+ic5~Fwe;@R$H$_fTGFSN$s-7S7i+wW& z2+)5CfcuNT`$K=5U&LEYiqS9b!F{V=7=V3CE&6l6Qp)_$+_p*mFugW0V^L`65N>>cLQxPp)y+(O|YjeWsYZ9h;(ywZuwrqR76 zXx4@m5rz>KJfGc00Co-|X4h|;LuQqjidhf+^1KnXDymni!(OKZrc$L6tT5?-Os5Fv zOMDw@A!uJBEOL+-1z?b&S!5*_3tCI}o%;glkZ$@=H9qdPF)v7$7$zJMk<#91?JJ^}z#tzg{(`lL|s8TX%5j0C|uk3$nyGy+YqW(RL1G!(8%izv+g+rXNYEz zrZ>68{azzfO6J2$@+wYyL;pC38sM*-#ypytL4Rz_v|l~i^)bBgn2H}s?6EPtcMVR8 zE2ZTSjq2bsU98-C#N*@;lj4O0gGiU$Cvaf!gAWpgrBDjrh6+PN*;)2I5p9ZfLtf?w zJ+r&lEVSbM^(@Yv-yY*bwq>6A%3D_%EL>YLh4SVh*eG3;6Y-F0Us<6`d&K^@5rF18Rl80vAUYazmvQ+GYvz(^juWZzU}BA1P~i^%P%_Rc4zUYP`Ev=3)vLXPRUJDE{t3I z#oH3TR)|+ImEtd(R8gmO%(+u8HND)D5CVx939)GF#iG}o%sYXq6AtTRIko7RKLD@N zksvBIZ6S#jOCU0f#I4<*O6Hd};>TT_xxs=Y+IZ402NV*+R-*tg~5}~mK-(rgLgEm;HP~ z0r<#4umJUxCE!-z?>beQ zdRkx??PwK9 z$qaPB7)Hnz#49N$I=EODrO^M>_Y3&7yFVXKVE*J`UxVW_zQk+qIsUj>sb1&vQ_txi^Is~b7^Z3z_R~+@E}y5L^XSys zu%9qkA=ad=5i?Xn)qc!(WpSYTiB&CrS$+vUYXRz+1vX8sP9%u6f)BqTPJV>dzlp(I z>KBSUuN*t)l&0$6#BgRAXqff{^?_wzHQyYRnulNMS4CI#&0>Y5Dwfz!pF?cV5FkCu z+Bhvr4e1YtRXP_E8Af-0ic&o^VloGhuh-gtrni3}Ap=)4;+eLM3@ulRC2&LYk4NQs zp+i|l^jYZL=vQ-5Yz*Z*j=&s$aOt16_f(EL(}Y(ZazyzP7jZ`}aI@O50fhZsZd|1* zwWWho5THMVPM%+p;(*=_2%E>xrRNqhwc6>Pve9vj?9DC(C;P#NCHXoJZ}*jK4r=;C zytsh~v{rg0Hd3{&Sq(l=?#)cPxgZi1Z@`>pBa>Sud;-;GT$Lpa@2Dr>mdJW`oeKJ| znA>0e5{*X`*y^b&ld1@N;fm}rQy-{Mf=f_BBU(?FS-OV`Ygwd?`M;uJWcR zFN{=_l*G)#UI??OP2+WE`rNC65R>yX(4!#`M?!l;+kG%{pLS*boGUu~2uLth^yx$u zlW6r7D=ocBAKExHHtSf$?rQXVfqd_r(|ch)c$RHD8!A%5e|2V|M_K2w)r9`(*y<0S zXTphy_Nv%vfW@Us+kO)L3*zR&s<=AEzQu?oAYXH#Z@*lhIRjgo3}cL@#vqTayQ%)E zeOH19Q&-$#%Ly?|E7jjbcz@Sk(eNA8k9*7iqW=amT=e3@Nky*=;{`aPM+a6wedE-v zok0e(t>B9C-DSMBjL6o)D|qo68%y@W6##@01rc%=CW%1dS1m+bp2DkmO4dIKU#HHgtz`+9)`4JwLfzxSFjD~ zMGj>==VWM{4S8Z-_$!~4!C_Z4T|(up9U{JR7WfC>A{P5=zDg_z(0oQ<89{!>p6^k) zn^Z#46c&Lftm(pZHJdz};nDb$61(bK3UL@{Z%$$u`3SnGm?!U$;~OA@;LHx!*dQtY zph&qOOXaT#dP3z?L9Mf4OTFN1)>IjdJ1{{OW#m_%d`FzHiTv`1n*6n&nw%dYUqtnS zIk@gwH96S|EG#pG0aKLP#27JeCBG@6gGVQThjL zhY3OYbbna_GBa4kK`LN9wvP$ORmJL`=W0NWqRAz~KPB2x;oe|eVGsv3kRhWd43jI# z=9n5p0^JPbsIEOB_X~>SlnM~yZf~Zc@O0waz8vizyP}Zt_~W`&GNl`RzF}q!-NSFZ zT8)#MfJRx+$}nBq>C&h)U~7-J7+<&Fi7Bthl^!#n8iZ3@A;U@2G76U3JKtGq}SfB^y`whR;`) zqdN?I9{Qf$1S0zW1b#MYyWvTkhv79YtdtAGE4)C|qk2*fL^7+a`28$%?E*xFCGorArhNg&oa#{*jF#I05fn=B^2LlZBPahuqy)+9Zw5JCV^v z9dwUw)e1zPB797WpO;wCLgu579A_{3SAX3~3;)C~8_EsCH25c~KbbdM8t2p#WWdrc>Ny77 zD*XpM3qO>)pxw@7@sbrAc8YHsB_i@9@OH__^pi+L!sOp|lJG**k6|gW`l*yOoJ094 zkZKh(PQaSrzU}J=+2>4HbFMa%Ed6O@sDxF``v5RbV@y~aModdPGJffTqC{oFdWNuM6wnJ8RwB~^XoytV`Oy^o1h-%u znZ$B6aOYP6O#tYq+Q6t9a~RAz$2LVuEssib9HA^wO85~9z9?vlXGC^_gNf86B@rZ4 zQ{xwUh*-Fk5vDll?9tJD1YwAH5T!30ijq|I@PHghAt3dMT}l1E;E&*NEUEt_Ei<`v zP8COzVX{q4u-z;{st<+2Bwun8^XTcd?(~ORhZZZ&^;SX|C7{zD4Ppf|9R6(Vaw--2 z>3Wj*pM`io3%$*%x~PysW*Wpds(_+nzx2)XLomMjL5qbv`o})bnK+@wP{150ESVOn z$19!Sn*gVI#H1hf>V%quJ`(t*8xu^vJXqz+)zV|)+G?T|S5}I*sP)D*VIKBFp|zwbYi)d2TR4sMn3z`j`&q&_Dso45o<)D;36OlXef0-|YQ#<}X;Eeu zNd{`7xQ=xdh96`RWR3=rKclI!N8R|b zAe|1%E}$TJVI>L}I9z5ENSDN>jFv2!b^`BQ*u}Z?yo)BP6ze6gP)(C4pz6fbGuLxS z!@zv-@M2~TaL1!HFo240l@7WyR`t&-y+@ukpf2*6Ki_zFvZcgxrLiW>3x~c~%ju6r z=tRr22&jxIfcgnZw`4&?x4@&jECDCX)M8)To z0Do8D5M*Z(IjON3`)I3v-j!;O$MCDe(N57O1O$in_7=(5>@!`61xyE!i-i!Ld6oUj z@;AS1(j5O1T`U|H$|Q^Jn=?JoSOgur5`d6^yoh#CwBV$DRQ8315EtPEK32NU z+v@t22SQMg0^o9f+h`CybJt$GWc!D}JIo^o@Pk;!a>WkE z=cw(^p#!$}e$u$|gYFxtPd}MnPw}ffel6?Mik_2mP0+?$+eL>J_cf-Tb zr{t^`1pM%to&Fr;=Jvu^YaS<^L^_t;6g@T;BqOT_g9@Tf%x$=h2rZ4-u{L@5=tuUt=)`&xGa~JjyBOiy7)witPdGSIqy6QDddyoY|;0fmsJ^1UeC-)!;YA5 z@Z!CcfsBp1O;G;ETb^WGXsxVRooM+1ZA4lk{y8BxjUEZ|$;!gH1Irws;|Lqd14q~* zynB9&hsfkcnm@?Z52jC)`eaFb;6efuem?@{NOsChG!7So{*%l12mzJqniGk0w=O(( zEQoASLR?f;$ZOP;(;POTv?vIY#{mqPTY%UP)vNCX2vI^e+!{Aer*5UNf*b9^}p0_+%Zrq7{BbjaZ zSai@N{aA6D<6)iR(Qyd*K_Xbpq}+$4q(J5&TqG(*7C7;dX+rjxk|D&YHxvYkHpmH? zY?TElzI^~f{_7lQ2b;#w&V?1MA5Jc?1o!LSao$jy)mt#ylIy zaGO@|+B5|hE)Fs9(FA5LO5_#xZ|1tT!klpt?hH$#Cteg`9C z@SNe?smjS9^g;DPB9ua-B!6??AR)xCK!Rn)N1~LyRPg4bc?267vFk|&(T?rB!CSpD z!n&c`Vxe||p?JsxeK-O9knsBO+Y6!gBM2yi>+qc+E10jEaG^n4ja^9U-a{k9Rtdv* zx}VL*A(}7~A+2QkcBD@WRg9D-(V6h|1X~M2ZW25U^lm4V;*=Na(14G~Ght6bU`x$2GO4auzp#}RTJ`LVW@ZyP; zzVrUFvjmnM(PRQR{&jLW93f&^_kFu*9%`v|}S)PJD=eYf~BNKx-?L9wEDTZ1r! z<>X4F@buoKaQ^t7P^8fI4UQmWb1EMpG%e*nSsEoLSfR-zAyjA_tqTuSu4XSk8g~b8 z8#7eu>T_39{-dh?4=O9^*(^Yov#&szweDuGiT`v`$*I1Wn~Xi4 zEryR!mNQFCU9sWp3>2s?QWipNJCBf;oxi$gjjL{{Ei?p;8g-@viwS8-cGG$*!A|7a z3|4^2?6pBQTOsaX-kJKiAKPvuLF2tzOQ+YhHR9=Gy^vg}N$m4je=h5|wnUWr2~-x$ zG4;K<|J}J?RGio~5MBz|AvaBusy$K?M+L@$F#~P|>3~ffqoZ8o>GAl5o4P>1%YzUWWIe-josTS2%E@f4aj@iHpJYss0J)q@ znUDc*{-KbVfsr(D`2*7f_Q5NN;2+aHSNM`h#9C7HnQ6RT(o-CGMYVI&n2@DCG8sWK zPc9Q6Y3^9Yh)_E@M$D$u7DZzDAU2u@gG`LuqUl8r6yx{}kKM-_4&S&zWPEOhXdZLZ z$>o|WD0O{M2do-T?9;fnFtI5ZQd6426TzDz5S0l)xsAlEJGUhKcb48d6hgx{al1&w zKmyOdbxwetm=@GHh#50WtYp(xSTsY%-|dl#B`}zGqPci+kvT3d402=mK5`8ITZOz1MOAj>-566>EV=#be;xy$4ujWP|aNQpxv7>HH z^pDpmfbwPZKdKH)_~i`^==Ws0?oyKDq_pWVo^i+3PrxiSa1#rTBHexMUa5}z+87%W zAxnd6LF2h3#T_wsR}MSWm!@!MLNU%0ttG77DwrP) z&cJfBmYjwqdT$6r7&8bbVuwrOsIkm+WH}V008f)X1#?Q3g+`g-^bp!xG-nGZZ!}Vm z8|8y?cPQwCkvfLVF_m?3&lI=ECTLi$*MmQ3 z#@f${PfoMot+JDc@#B_8P@0r5sg&KZj_f7jY8d zJsiMWVy0@`=+J$Dng0Y)RA0}N6Ufxi)V{3(+tnCLk3ZH+yWXE^EBsn(sdzB82ZSM1 z_UOF&%=`1b6EAScx{7c)9<93=mFdErF9&zJV0wL8~$Th8e`uZVYZa@ZxCVIXvh zC=9V3<`FE9=1%mWry)8(Qs@J1=k#w50m4*ZX0L05cT(S$dIfS3hb}HG>O)*s_tdX7 zHW&_ANj|mLbU&i7ZLYoba?or>CkQy0_vg_D-ZB@6G44Jn!$bGD*7OT&eB-9u+-IiI zMjJIztkv57r5ZCdSrQSQ+B&!dQOLnLLDWKxlbUa$xOCB$8lTwe4|>=^>h-LN=Sdhb2LB+*^vJcaC$@3(Gz?8jAmeOGmA%W zccuNjtL5oGp4t$O^9IbX($t<@w2+XIgI0U=&$3o=}NI~uYzskE0->vCb{I@a1yb;!7) zut41bPX{!+J#4`deJ@$fSFQF?(aqB}Ub{zMmqaY&1>AK99=P0&YYKYL7z_=PE7IPO2e``2<6Nd3t{FdWh+>++_dM~aX{#HEPIlzL& zE9x%ThwCw-fMu`n*i&C1GjI&Z^(F>1v*dMy!rPA|O$d%<$kt#wKJ zhZF+?)-Y*(su^6*9zsrR5fsdNABbCWr@nB!T`DRTE$@PGgdiitQoemMMx#SRtY^hh z&{psNbiE-wi_b7R9m)HgXdm|lsQ~-35Cb`@BD~;P5m64M@CVTc3g=&&IdT#o7#Zx- zyy<^lVqL_^lzsyzSF3U>esfLuLb9@{jNdCUXFTZ<5rnMV?odIEYnIgBswjLn%(C9O z!)^t+!08tl>C_dU)wod3hurEDQ|;2)XXj%<|8;JzT*)r&SzvH2uhOB;^Hu#n7da(JSs9;%U?#9c!lDyJlXLQR(*sT|^(D}<~)gE4WLeoy- z_B39-D|6Q`tVQy~G$%hp2I5$aSUZXNH6Qyi0i^idqk}otLpSH>3?@TD;Kk zMSI)^5OW^IM6r;qZ4OXQ$cl{~y^B-VQN}_TN0pq!mT-yvaMIOq-&x&BeArQC; zrMG633qKm0P(p(lHFjogqxZ44%lXaf$Fsr&cDN|1wYS!|ojRu*1EXV)!^@Yos$03% z=+HLaQiwDdFkS*1u*M_ey$cx)hq*v>^K0(DB z%Qx{}1wO+a=<=u`Q#a#=E>5=+n*hW5(4jXZa^3o100eOEybM5msn2LXkMFC!Kc1DI zmzv95nEEoHRHpy{^LSGTCUvaPO$6NMHojzC8nGcDg%{M9jhL{2LBm0wL=W~kC))po z3jD)|K^66bhWp#lF>EKLrcLNwxRR`12Icx*=GrQ;MP{tN1#I|X zQA9;bX=W9X4s^Bbchtn-ZD@ImD|9SAed>%nyVbcICb43ThU%O+T;E=E(q`R%0YpH% zzop$rpzkh-=bM0nQ0iLf2@klMdSy3}bk0j^_1*w4w!OGLVLG!-8aXDk#ak=lTMXx* z%*@n2POIJ8C+N}A9nn%p++xmbgRO^pN;nPECp}ntoyEHUqH1dOqmVMC?}8=M5b>H9 zPE$B%15ze*j|S^a^utmxo$UWKeuQcBb+9Ce?by*_buSUix&GVeF;%ttF)SpytNjnS ztdj+YVWGmgo~k?V0;xAlpS!?3kA3^y%I<9b7UbR zj>?@2fOY>0Qg^A<57Wy*Y`X&)cjQ(QFL|&uCL|b+brvf;@g}In{?}3a2tB_u7Bvs{ zwotSF*HJ?@#(2&Dxl>=DAn5oO3wT6D#p&XZcUd;nv&d>Wx!K7#__G*}dTnRM9PBvfL)B^NGV zLmodzE?n@f&O80@2CTxt_%*V5S&iPWlNWcaYTpj8HNJ{sj&1%UIDO0Xbl+5!MouMx z^?VUi(x?*QFX7$dc9q6lIK_X)q)_$R=fr1g9zrLj*B&M}TKl~BM)0jthJsQ~X{wl_ zvIY@-6dP~lE1}kDdU5tD=kkJ5&xh=;k>U5i#(W^NsxLY<4pDu0`U;;DxkXv-c^+%&g&Tpaw0Bthig%9pJqWF#`zy=H1{~&@C#Z(=X-7Y5 zmA?!7zgFxE;5NP0 zhziL{AlwPK!@NM0W)c!yj}aDegXJElyP?F+)o&A;|Di{NBEc7BB#K{=bRiT!Dv=LR zybZr;h3t<##ze9eKI{U5Jwz~}S6u-U);cS%;HBdd>ox#9G zkPCFT2JRONQS67SpdshtnXR)+kkwanoLDwMWZ)rq@tyyF6j@-EZ2*y zm$8%%dM2J?^y2wNy9p7jn1aDwL~C#sBCI^V07^XX9a+Q*-$NcY6jWc=%QcK6&PIH+ z?5K~|3^JF7iX7bj1!6mv5i7>=jN>{lB9=c#G??SlEVfP@WP^z27A)POxf!S)Gj53z z1@{dVahG@;2u-de02vh-P4a^r7ds7Z;3hUJStj@r-Z_UD0s|YNYYej#H>fSKWgJEFOFo*$m&}aDNR67RL#~x$YV}Pz ze77@}8N`{$%naUyZ?#(77`zreG0ysG`1;|+Jee7SQtcFsn*3Qf;U}qF;P*O+i56i< zAkTANFVBoHkS>OT5a8p2L3~{r$5I_I*M0uzh{7y{<8U!=h`}JlGmM$M(Oh9SLH-8O z#ztsk6SqTclsm7`#-Dg&6WaLY&d?YWHXTjk-9Nkw*+YU%)A1G&(;c?kJ2S?^stahX z@g*`7=Mg$-rBx{k;d-$VhjZjG!^Q0enlGUUwF>Kc9hW~Fc8hbwkI8vPs~!VOM5nh- z>mXmcR70mzt$qX7Gx^PG^^1OGaie8j!pPRGiW^-W%q&`(L6s+9KElf5FebuP<&QA4 zbv*?wZDN=THoF>SO`1u0iv%85JImG;EjfKX2E{GD6#09zT!E+i8g)l^b`Gb5%2q?e zaQ@s4Y&eX1K@ep%1^&2bS3)#)|1a9*2wItpwXB250h*bNbxnz-d*bERX6P;a zfZ!EA3OY;X7Z}O>JX{v{%+}Ie_Ztbz*Ts8K`I9XLJt1gn{|&e@H+Pak)3e+!a5=z+ z*{bd%y|}~Dx_Jvu!W|dmFWXSO8r}SqF<`?3<3wBP0P$H!N%A@3WtrK**-_n$ zZP*=(S#09=pX`1&f2NPpu|7(RB}(%Tg;LXmD236ucU%u+U)|yJbD&htj+f{8#12RF zt$Jg%bQWkz8KE{ZLuxLhYKGOJpG$rsY5SvtR871CNV+TOHdHcxO!PbAQ<{&`y;7lc z&5O`m5h}gMHSz}IaYNh~79(;)TntH&?y5lp(vbH!Pn2UYZRL-8qhZ$i2Ez;nR~!dd zBs5mCgM~-%Xl3QNZ_aHX9G@C{cOJ$`YeK#9DRBorI?>(v@%h%jS-v*4`djY^=eJ^i z1lK+z{@SM>70stFcMaPLzlVg}9jW_!RHVJLoX^*sB_q$W|!4;iaXX~7pf*)hOklr+&*CBu+#p73NAm-D266UD`Jd z)Z1;@%lle60}dSSvpEA6Jg*Pd5iQ%gK@o1)R;I{q360URMSm<-^saACd2SSZ##emvlW5P-6rOv}orY2A7ZHtdH~fdDK;zz=*t zy7qnYqX6uhB3xBOxm&0SV}=B*Ci2Teb=k3SzzPRI`)ygb7gS;kME_ni0KwH{lE>ZS zaFrp~0}Ri^S>a>-57B4i{Z?g4xS+G^`kzvKI28+PKr9xtT`IOgp3eyt)`8VyV<`1q zzQ$^A9WK1$*iDY@w{`h?1MsV^K|7bNVq583X!AoqB-9|~< zLKWT3+aPHhZ^NW&73U`23N+=DDr*VB7Km=)Exb9qWCg9I`|HP|IwOo;mS@Esj&{eM zl0Q8hH8mWV#;3KcgKF&Qd>T3(j8B!+>DaqV5^?(8UG6E!CGC6)pL!>s0;o&@Z?^D2 zxU4Y<%nS!|Y83}$cQfNz-foB}^~zVIT?0!eM1lp2R5ZWJ@fm#P!71NCDf^pMzu6CB z4~?YVt0Q#(-X}%8A73FqXq@)%qum;R{CCI8AHb>o8nGJ@$c4ds=%X_@IK`M1<05w- zHf9#9{smK>kAY6!>0S$2nuqMXV|O`rcm68g$-CWmp@J?q9Vwvg6G8bb-mT^i$IKlE$2ZzNx$96YcSFZ?^KOaLKn1N93G;Mc zcf%a{2-_To9${;kldkpSa$=4>TjjI)EP9fywh#Avmxx@=kgFhb71APCLFOvhy(;e= zlPg|+(WfS#M{m|2g;Mq1NQ!xUp53QbF(C&RRgh8ldenG7K=RRxcs_`@3nQe=d`YM# zBrboBl{w|(TD;22AMm|qm*FJ(zwx&N2M(G`Ui=t9XY5mCU3vvAR_wWaZl}C!bBgJl zXKH)su8sH}{YKJJL&Csf-dixgq{m;FQ0&OS1@|4X91;0q_M|X%kI@?CM;)b!G%|z~*i~WZSC0d1O zg`cW~d@738POS4YD(;0ajaFVmq7d52O_z$H(2B{$wiTUd%asA~aWT}H(j8hXhW7DN zLZY~5(3c3*Dry2(TnrALFnNY+brA>vvHRVzurNp z`g>M!vDkgZ-)f7CrSK29l}4*XODo(b>>G;l7eBfGzyUjzity_m_vBLjn4$Y-~9@`Yoj91q7hpe z*M2aUTN-LTaXmUG8qE&$#>?Mt@m7jDa6p1N#0k&~sc2Vg`Coo)N(aQsC$@TF=(qk` zd{zN6>9Pr+*Bdq5UoyL9$GRL2;r*<0%(%#(E}*%w&_z6|*SToWgIi_nzdpLDp`t-&Othrs{B z3LVwiFTeG7mAB{9WvE++v-LpZTU!0&hRq6aUN>*t&sJhvZv@~L1Q9$3YlwVTy!;bC zJupR&%C@J0hlQ<2Z)$!~K?L{EdOAqIby(Z1dRbOsmYXmOf(V|2Rbjp-UOs%Xp9Q7$ zKc&?Em%KaXef=c@e>(i9!Jh%^O7trPy-d2A!T}alrYOA%QyO4qJQY%|0V!&O#4jjU zE2h$@9I0$m?o~dmd|int)095tH02LUld=}Z%9DzvILdTouJW?dq5M%vD;cF(X;Ee< zGnJe&OX*bRDf5-XlzwG_vQRlnIa*n&EK`nAj#Z9RmMf<#?@-QA&Q#7)ib@Ga&%OMuokP*f`@eS#$0WHV> z7yc(Gjoi$Dt|rkdPVnd(=6U0MXy5vnOyOIm&hRW#+i{m(0%v+a2hBp+mVcA(CL?nb z<(M@t$A7{(I=#qjLPGN6lJ5^E?>Z=X_qgN-q;$}5`+Olt=W|IcuS2nXg%rzrSS-`k zI!b+xl(vH)bM6Ys9C@yUZ<Di2#>AUk5_>EqjnT9a?VIXUtU`}OSB)E!&YCQI)CH)!kjTn3jnZAjYkbf!h#vy)_ z9N&z@_ZIQ}Pl6}M%Yq8$a@(LGnDTPJaAkoC-# zu<#$oHOY1#IYE3z#`RASw@#LMN^WgF!C0&~1UV#Df{M5zWEJi)3?R>Gl_d zC*#0RbNjn6)RF|5K|ISg+Nb zWSNTygY|4Hd_v_G5vL{5V)HB)6pFV97oSX$luD)B@m9#4j@AED+Q6t|T{cVi#95|C z&+@#P&PTKL`G{lNJWkbdUgGwh&`Ge~$Du}-ZakVrrg(|AIpZYasZJ{2lV_BpRBJZp+PN&4Wl!+GuwGQfiXht`QuLWYXGP5_d2 z%CtFArDb3$-aJTU%uFfNU8!aWdm)vl1V5!jWsSViqf%qK{dwU*erjyaCg8W_;O=b2 z-t6Ix<9btu+ajVLH)kWV2StxHwrneWUnX+A)Y*YMeUQo<3A5lH;6~-tM@f~UIqi!o zeH%1v6X)2`MmsJqW!nkQlk|>FQsa>q;5xO6BDQTMKF5N-{50W)Z?65*`}i5XwJ_W^ zWY??Jw4W_4v!xH2jiVvpTwX63dn-L-utR)Br=D{Oz9kIio^jxK{0ombHts#&MQ02s zkbTRm3aF4ZK0nX7(~NhQ!wuiac6G+fPC3*;9D}4_SGf+q{7c&Nj$< z$KLx5-wWPv_>d5vJmD&IB|`?2Bo+WyH$t~F#Q4&93Wg-xLA;1=RwinoeL2oxfbF5#f1Sruwp+x9z_V@M>FV| zYn;0@CnKK~q4|5Jyx*l|wuwR7wpMGF-eRU`d6}5Z6p`Q4)h4({JU)!N&NV`}=ibHP zUT;p_f;vNl01W^dTiSeJ!UUiRKyynr;(vF8 zi}eOq^;}ih39{Ukk>HyO_|EwiNDpl&`05CwmmLOQzT#a2xn21FNA3e;w=MRq6DAo< zCH>^W1otrS<&8&i_i<=+h^@%oNyRfOV5X816!Ns=NdJNx_vZD~j%0O=2kMCSF zLm+~^fZ{BcubJH38FO}mC`#M$d=~TuG~F%kB&W2q7~}DsLwIK3S?a==l{W1OFL^>F z2M3ZTL~?oZ0C*Ih=lB9mj9VyGJ$nYvC_XxH1xksioy?!)l9%}1ruO-$Z59Waf8{9*5cgsxFH4+Gm-u9DGapXz7i%RL7qe!Iws5UmKjeX zdBCAoCb5-?;KYfz0(m6mB~OXuDdLKhNG`7*2%(P!IZ%>RXyWT5X@{H^~Rw{hR_u38p?9rc^R8T#wNv-wt`@ejO!+!+*3~{f3Y zsteyu+vmjgwh2v?E zm?uF!g3K1mOX-i3>(5kLUK#l_-WCiVrAb4387xeBuzvJ`r>!@xe6=IR?06#RP;JIO)I`GSS5w z*4b0J7B?KHgtzYkLu_x)>{{A0D~#Q1)5M-xLF}2uC)#TppKtw}<-1$0_MygG>!L+X zK`v?vVo`%p?g#z5sltYa_TZwmo(SC%?M6p~DT5BiYrO=G;%k3sTUDDw(Y4v=xbLAY zB?RGK<8>I{7wk16-+Ug*eiz}7Is8jWUeLRlM8U1Y2`CNgUlBa}HblZ|o=Cy0F_Lqr32-%hr8-uHwG-^PznV40&UW*Fe@5#Guz^e~!=D-vo8r4iBY zjb1~s6W=S}7+?xaugZ0YY)epIBB(Fvx5pf^bw3arLYZsQc;L}toB1E%vvrl5e)ilA zWbF~lU&Zxd+_;-VH3G|x|84$Q-wIv&~D)apFB&psdBt^QW;Ji%=9iJSBx@h0S4akM4V7t||t+*3!gN_A7cN4Fbz5C0W=owLoCi+EGC9()?LY30h^*Ih`vZ83Zi>}GH zH8;=;g)6+fGgv_3S-Jkjathy(=LV-k{qH9J2r3b;G}7x@a~x2iSj-ev;G`elNktEN zFN)H|SW&*LOq5TATr3H>NV-cR(za`f1RUuB$TLIa*g7oM4Zj24y&iG967yHlP*Cer z)y_~j(>JW8`_?;F{urRfe39ST#f;pCh))(1_lyZT-lN4wV!$R82gdOP#J4{+oF8sEE8( zPG4QeOE;Y({*cE=d6H5)IwI{6o8|tE$V(q7v{+Lgt2{s^J9|67Dq_?sW^pp&Lw+)} zt!=IFrR9##>L+oV2-9nNl#+%%O}P~7T&7l+(uR=tEkVq%RA!*?hh*5_1E!}~BrpuZ z&kPe#grK4aBUI5cIS>T_@H{6%XSz4iJ@qe8SN+XmWM&uNrx@OzE&hwe6btRxdVreC zA->eM5~L=1yXvS0*5sR0w`mYvTkhSb`-HTu!Z)E1s158w=I#)I5+zit$KfulhHv4l z!*fgw(sM|AYv{$t(lK4PtqN2LsrBdx_Vs9jk-sLYKN$=u(M^bg=RH*1uW4^VG_hk#yHYLT`G!E8@MefcFM( zqPLdu^hc$$qd5s}RQN_$Q(e_ToW*mB}NE(vDL)mb918s5jG!)2RMzw9X9 z&r`Ny+2NvwhAk~z)zENUPsZpK236XPDXxb@ z2{!HUpPzj5?Hm6JN?tL^rY(Q?erW7$4zRYIM1`g z3(*bePEoTqx;Zu5i0&LU+l1~cHH#Q#r>a@RF$?7omW^tb&`hdX#B-9GMMNj7S;91> zW(n0MHA}ccbQaxdYPKESPBl9P-Ci|272SR{I}P0hYIZuh1vT4&ZeGpKKzF*Dorx}# zpF`JCv$N2xQ?s4urqyg7-8MDbg>HwM?MAmt&Gw+%r)FoPyHL%}LHBSq+l%g8HCsTp zTg~>NJ44ORMK`Nv=b<}O&CW-+N6j9F?mRWykM0p_b^*GJ)a*iZ=d0Pn(VeYkk3jb@ zHM!O*4)-`{VR_Fr+bGZi;T6CpdeDbn6; z4*boMJ14F51sY)!$M8r|+Q2mlyB4x#>y&nD{nAzr=bt?MO_w%uj`&Wxl7_!FX&cui zZRZw>?;zth&y{ZYn}K#)@Q3GaJ>vW1WSh50e9N2c&kmEec6j@Dt#7h5*FO!rF1$@L zRjpnR;f>tFhbi8fB;)%i9ojg+&Gh(S+V_(;GP51 zu=K@MBU`_g6-8kqT6er0$%2mjQJOGF4a_~`pPxmQFM_)b=cF+Sb!T?GT!+DrVK9op z$$n6WLJHw{Jz4}%Z#c~x;GG|Ae-^qcVMcq^Xd-Hs>a~0m)9|sGdeu9|vedMBf z_pf{HzT3{dyKut`sSiH#vv;<=_Vi0PJh%7u{0X0nedWqeZ#KFg`SrHRkG}8R`p-}P zQ~Rezj=lH`f8Mv`tM95k^?b|kUVZVxQy+fn_3vEwlWWi1Ick6H!42nL@sG9t`LD;< zzvtw$BaP3EvUTeg)&27?N%Q9Kwr@QAociGtUR|>K>GH+r?|Jf7?TBNZ(vSbob;-RO z9=7iP=YtQ=8{PStBcFNvOD_!m^ z<NA7+^&6zhuSAFKW#J8uv7XS41SGu$L z2^SPUI(g047j>Wax%Vyk*`@5_7b0J7-@CK3{^{S}c-^Nj&OZD(cK@r7-qZKgBfr`6 zxN-U1e<*cZAB?>}vorPbmy#n_buYTmynXcCZIQFr{p$5oH*8qDW^~fCbJkyXlCt(s z|Ick~w0eJ}_3N*j*PQjuy1#t;xlgS><+aZ@{PvNrzW2%-zVPp#PkwRjaox}VzpT9p zV2#K6KRz?(ocF9r&dEtmP7;z3A^R>8u_VM+s??UCC6*FJh_tmgN^7aBMf9T9a$CKn zC|VSyRi)Hktrk_fpj36I=>K`1nX?4#z2E!)Rr5LXdFGjCwrA#@cbhl#r}4*T4(xFJ zkK)od?myUhQ{zguZN<6tw~rV8>x=t7nfGbaVY`p4{Nv{n$A(-iYkBkJ@a)#p2CX@~ zx$kGAQuIY%*VbkA>0tTyzVQL4n~XGc`gfsdV7FU$JQHKv7q@9}j}1?k$C!^lvSsO4 zr3VAApLuxxzLN=c=O13Tan&augf-nzGAUqVYJTtSZ><@+b!W`v%~#&s@XkWpxi@tS zkFKxGYxD7?wND&f99sW#{bbjvQNh;!=cnWksBSi7Siq{DL&jPU1%9>oPxIUcuQSW~ zCB_LwbAx_3y23Pd@Q*y|_PbiyLp}QawtvvTs*yQE!@t!Y9sYRa@!MyUj!o}5_A~o| z`%Vuk|6sNQoYPsXBu#ac0>w96vi4zm&9$CKo-A{8L{PBwit_^zo$eP8j4?aPTF=~2x<6v_Bioi8 zEsx7NH~7JMPuLFV+F0M-;u3Y!>KnT4$lv;Yymk8M}1QR_YFDn`l+5LPCjD&qTq-8PaAc4ecP+= zFM0dSlZW1DbMenj>9u~`zJ12KTR%*nyP?a=D>l|M{S4GNjx!3g+I#f0E9;&AMAFAq$P*?mp zoW@`hRUw`F9+&SqR$XY8p_ZK|h3H(F23Xa>^p)V7zDC_I;KXo=Jk!9RQNQAu;!=6d z_8NKgTdFRx{EkYO{=SXIEkxy1Cw>fo>PLyoxsYXFC@(T8DHDE0xaQpt7&?c| z!Hen^Rfi|DtQ7vd8kjBtm{AJGqa1)6vsEl9m64 zj||WEG)I(U$VI0w1Y}#xH6(U^()Q z$3b(O(gy&^SgnF|B4nlwRiFGh-LJ8ns!beP%{Iah@cK1Ulr(-8zhwcX_4NHue(sm7 z;Umt_&0(q;J??kI?^P69WBdP^{QhFpAM;y_YbtD4e=+jjI}_^M&g3WekN4KR_R{!}D$KgQF_1*ZNX;PbToEE2}tT+vRjNws7X*VTK-y48>$_vE% zB(L&(e_+=g{9T$s!{RIxKESJ%6ZZI>D^$YoT*^~GF1lnGRY%DS;LJjQn4BSKb z%#5j(PPJozIuA>#BaHfZBfeZAgC+{PFleTrwc=^NY2>(PR!r7uDYN9hV3nR{68{h9 z5dKAki0$4iU=3{1Yw4PH*BOOw!eM#Tpp@E#V{%R>6VlvmPVcvR*4tv-2{jDxjK>h3 z#uE)OHzvZ#VX$5XN?>-OfL*5p8`KHouz?NqxU`7ZK}}&Djb|w$UN7+GLmVlD6;ns3 zHFo+rC3Z`(kXBSLpwpdcr|Eb$UyZ14K4U@)40OlI+Kqf3{Ls`eS|?Jym>& zt}>Hr8sz5;=@MP8o?@vz$6>2vWXRU@bkrVicgb*xt2{{1n=IbOmpz!fmDRM=>{Sx{ z2V?d-j3qrT#$i9;Hc0+S$sbD8*=u<)dCC8+*mvesv%`gIv=-)Jl|4h)lEgdv5Hat_4otL;!_?KmNWWO5iUOc;W z!cI@S=xL9HYPrWE2y5!Pi}6(XN$4c2944yqNF+y;aZa3Nu?ouA!Hb2FGEfI))&3uN zzk`7GX`IQRi^8&{;>Nw_i7c7$o@|B>e3B2OWRFj>M-J~)HN5A@EUk*l;hY9bVxtU} z4E7)YAG&Oq5-Vm>Db;jfGW$}RJt^tVu}UfDsE6UeFpuhlBNaLtN3Uusn{15$k3*ne z;-!2Fxam7axSWyBh%>88%2X@H;98(Kti)-Ot%UnL&&IvMB$@5B;N4=JM>6%AyT8RK zoghQ~TBV}Sp%u?|SPI5)PivzDEIG^t1AVgD^4C1Opp#Dsj-td6Drkfc)VYhDdb7JY zz$=dnP&)WHO`KCdyWlAE7`SKjhQE)l{@duR(SH-y`)}e3{wA*8-^7{B4pZ|We4xu= zfJsS5E@^fe%xZSPTlU7Z=6}^g$^%R~Ibf8F#o4*Tm|@Z2Kxk>)4PRowp2SY0MVXwy z$VQ(~TS->PYB6Us|+@xYSE?3*XpDGil^^X*ykU zGrd)6WSHp3g6p3+fHr<61EnWlN zyiI;bG@1E(a^lCPFLw(3PMMs9rKn_rFD%C4K|8(3GxO%dYNy6B$G7&`O~<;p0P0t> zEB%w2ib-|7eYo4#hh*06nb6fy&6rYgekkSRCb+BIZuu zku`iO22a>vYF7Oi-h2vmBa!rR{!SQHqLmoQ`RW_pCDy<1OIcu}@--uPnbnnk;BV8^ zSSBTP`0pD&OeXv(^yH$#%_c`y;sb+`jNjc@1<&@*l-|2Rn zZlT+)y@hT^r^cQ=6g=nLMs;6JQ}@&ie)rI9>RwxbI?oGK=h8u*ivT7#lv}hwZZ-ty zti~Wb?q{nteza4a-{yPIZ@-|+B?}FQZ zC%ykNITxBOcheN`tuJ`N6Qt`B8@=ZXB(Fs(-}r*x`hs73jgI?)tM6r%MAB6+Pvp0r z$gmm_x`>hpqR@7+9$n0D-1m6u_XWMSIsE0zax0<)3Q=4yS z!2%_r_(XbE;(qV-3bYwW7rl8{xL?DnD~K30l(+PSAMqo2oud`9c$@IMzw7x9pX|^p zp6s8aO?O5jh7}KdsC#R?l{2Kr(w^Qp)m{#TGUoAaKcFb%w*0KW}DuX8DfYiHih?3v&rpH;&GLjXfkKr zFPquz>7Qax2VqfYs-bd}M|#_cW)I3v3gZKP-6M@f+-XdU54cmawe%mF1>_1E$8$&T zc&0gmR9uVYuz&*$(l`qo*f5~!a6<`ii|Ovw_wf$l{dVUL@3ktQZQbBIjN6oPlRmuU z=pq0bau&aQw0q>E#h9^UqO_RWc=GQ8YnN$4SA(;drZinx2@OE2U(XruVa*tk8LTWA zacs)esxIdy;!#RO2lbg9ZR;lqZ7e)Hs$XA8qliX$Xtb^W?7o8&>G@30d)D%^f?2Y> zi8L2llFV8}u|>QZ5rn!3zz465-O9gwG?ZGHOBkpfo4#dYx0up_p+=8wis+J zB;Ub$dA_wRJT_!CF_Fub6p1@$fqAT`sX98yL=V&AqaXB4I~vG5L+ROoG!R}shPGj{PhavqWep^ew#G&`j zN?PWcq%gBP6NbEj&d{AEqulJnw8Z4j{91rej6=teABM)_nw;hcQ%`q^+>FBFHuVfs zVXMRJwBc^34ULX~YG>R+Vu>RdUlextl&^1^ zGWSAu_G+gy$pq1$1R9PwXRs?HSel@=aezT*`WYjBu6+q+AL6j#`=B=b4!ql8@979y zA_HN?ju5OtP_;bDLoh@I<;EAGm>(%nRIwwp1g~^Bm;5jFaQM~ZzpsEPtmzgwKZJTX zEVIgR4obCFgnNewZaGs&c<#|Ad7oFu@3&~4fhN7%2nVD)#@lK2OtPkq;i2f2xp>zT zcPIZ|9`w*PQ!Ftv@LV9=npD3QpxI$at*uiBynD=>E}O%koH8j;ZQu(nXVcPL_?azq zyEL2Gn?>p=lQB)%Gy9n{4OaG&9x^AZ_-Ok*@=I!JingSCG#vNRh*Xim_lWeAskz}# z_5C#+yTbh26Q`$5EIPH6`(GNsnPk+-r6esfUFp}7O3lepx@bEI{U%&fc!^ss z1`Dv>pyIfPiag>c)z(D^-xV8eEvYSUGkdBYC96*F<^2Nwut z%dp8`rzSUkCf#cF3uzo$oD*l4B}qAy)~V)phq30|ET?33AW}9!{pce4`XAm?Z}J$v z!JC5T#Xr$m23|KNQ#e&QP1VUic(}je5@lFv!dzgwJ6}_n$EZUda7t_@SBA}D@`y86 znq2A6ODi6kpBYoJUoJATA}v?e9Gbq?Ik%W1Ce>9pza zrRM5T{6YjZiNgl73ABb4>TPvcUFk=loKNXpmK9azws7vpY@@ ze?j4JU9w$Qz5(0D1Sv@d34Zau&w|eeFQ#vACne~#*;bwQ99lgmqFWj)MFZ>U`@M*tr`&du-aaFW$=|Qwq zZ(Y>xg;rQAXL4Bn0z&_yDSf$*F7DFkmK>DXB{5l*>_wBSDa-6 z?((d~Sts1amBxfyzWb$--tl@a8zIT^a5E zqR?X8pB(p2lzLGab^f9XQV+)VBH^0wr@VUS%g=!CTgm+5NKq&4(aVKWJ&pwWVoIfA z?U@h%$721b(#ZUx?F0O?iME%h()~Ame|PWrdJbAYQMS78-rs9ppQAR*%>Pf7h*QP& zFJhD|p+OoK<8ILd4Oum)UFYfcTXGo5j(5=jfS=p)j@7+%;)sHC(2sn7FVC}gs(&7G z-1^(lT-vO%d*mcXF5_zC;v6qncklNC&){QW4&nC(WtgCYYk;8Z1%X0dFK`O72&cXJ zK!ZEogr77gqPa2y1GQ)~inIwX>0Hx0b!-!0iLhWlKCQ|hrLN~U^<2-#*HzSw_6COi~haK?hc#lQ2QCuZ%jE)WGzV9hs$T{5@;tXVClQ25#cbtNuOn z(*IRX20i5i=G1(Q^;_!Q2iIzJ`QFQ3WDL`JgScfJb%aXSTBVEdrh}=^FCom5Ugq|< z8U9x`b@YDJQtz<|ZPrx6F%ix^#{h9aj=z~`IMqO>i0_8CuC3%Cpe-gEsWm9d=Q+yb z{E~R(f%lY0DN%QSRdk>fojZxwx;xhOKZ?fT7%cyc9$Gx2YZ+iC9XmHz1VKhW+GTPKrUE&hsXc8o$u_v4hdE(WhXp*RU zn&f;1eu(p7SXO{gw=O5x$OuZ^S#IH9gq~6X>+W*u!*JIN8+}sHp^EZQN{Cr~3|(5l zE^rz=GTf=E+HY{xkVoBH?A=|LS~A&P)0S`8dW)cD=aQ^kS%l6Eme6U)Umml_g*_rpB`y*uhirxE$~Xs!t;LLb8yr-_~F$ZT)yAQhISbZ6 zVXPbkWo)2dL;_T`PCbCDZ@<%|aKs2GU}+^(BWColp~FWttvk4~azx{_v{C&B4;)rH zDs@;{|BCWa<&RXR_Aein_C(q6M@FY*rl;qmjV>KFG;Ku1z)=H-SCWCc0hSp5|HxkB z(f>D#bz|c+Gv?f>YYit@*X4`^DqYenhsQ6ow# zAmh5=q7|dcE1K3Vtf(k|qHavv@`|#tP_5FTSUJ!r99lML_%H}Gt=pxtVqj(e!FAEk zE1^mLM#afc8JiLdvTj}2sUz~Wnb)2BQ6VHe8=4J{Ob|;YYz%T;BTprLlNeB zwi153sOO26tKVAc?>_Zlevx`NpQ~q(xO$i0CO2nMHPqPe`ipuC3o!&3EG&{R4p3ul z3~3PVNa4N^*4R*zj3S-Ugfk6Kfqa4CqF!T%3}|P7)=smqg&M|wPvJBphT9pR0$gfD z{cp@i%og^fjVuuEvaPcPvdDk{Loj|)OcjtR7|&Oz-ojV%nq zlEm3fc8&dMzht+tK_QsSlY}?iXssv`QJ?gbA%f+nMy6WWkW`dx&s>pdVHYw_0RBl> zD+@87uq)v(!fAvn2tUu-mStgA32%|am5tasJ1hGW)-xO1vMd{OnGP7iUIEnD)@*DO zb314 zrm^F>Xh)Za7(`e=I56*sS!2Tpr;%ha;l4bq1c82f-@ErQw7CMc0L zI?@E~Txf!+zG%8SAedclik@R>hMx0OGn6bQT+!LvuKAci z7tZ*B|t|ZVh&*eVJD7l-iN}E6TVW2 z{&}qsYiDbLy&2g8!>t)&CkpRqv9tyBV@nK=Cw!~rvX&P1KH*uy3xt_P7~7d}P!ZPs zF$hPnDw0esLT^7;bfU<@UTd??W?{PtkF-I*{g&{@Hdwp3wy2*^I0KM*_nDVpFtf7| z=JtNo%+BfpGsDbdB$mZ;f$3NvvDU;)Fl8aTpO}rs5bFuY{Qwrk8W0;xESSX;n@TK{ zB@la_EnyB8$r6ceAXbYd6ML6fZCF7dI}SP6!G0#OlayawmP70uuu#aYC9%sCm(IEp z`;Az0){mIRkrhB0@O_71j`LzGSiW##xx^|-vjJ(gg4GMM9PWmaJj52UN!-qw@D|+6 z`mqk)ZPC)gxlGl@-L=P7P3uo1w%CN`f~ z75jnmTSS^qv7ae!6W>DYI?pB+Fnn6a&dv~fk=clS$FBq1$ilb|I4pLd zwtHDRN8L!pvN^UyqPWiEfaQ|SX22Y5zhb=wS~O?(j9d`;{V4i>=6iG2ag%mVocV&941fYsq+xfNO>NQXPk)a6f8 zIm30oi8xqSK24fQz#J?YSQW6AI!u?spP~Hj19lv0H(CS!)_sx=+pHyDNjCfPSvoVYRm7I+khS8k6I%@|fVJiu zh`kT&XV!+p2^{2iLWefn^R1M_m%sv`&)+6?1DFHYHe%s=>UX}Ktkfs=G=HC1vSRx< zt_iaAP2nW}8GZojU}qhHnSmW4)}7ci{)y~OV$brk#0C;u#($=|KLIR`z0H56xT(OB z`8&iIdx11R;TEBTxR>?#yz>k`{Znm2iKVh4d0aW3vBc821(=qPkh zvbqh?id#HH>|i5g5u%S@Ty0TGXCz5YkVT9B6xXLYvO>kC5i1e{{j9VRgM<@`-Kzz9 zPkT{D>`V=o(bAudYvs=_)?h7Kdl=?$vo+@6iA!#SaUH~?#Co*#XDe&4xOV=myO(iR zU&Fa^q=vKLR;?T02U>5y6BPa$!W#QU>kpV{TnLzJTnzFDjmrVcjQS_sIhP>mb{*|5rp>}v7AZPc@UdnT>zLz*vi^l+3{GL zY()znS#d;$*)Uve+s!>XM{U2}k>h8!n)z}T9DuD99dHA%UI5l2E#NkU3kW+?Y?2jQ ztY-k$ZUEt^00F%}Az(Mirv_lzo+J5-gnI%4A@*EAFwAj(2DpTa)iQR2lGh4q0`mAE z)F}kiv86#{l@~eK8$k=a_403@6G6UKiXlJw6*M(=lQ0e}Yitjp&W?WA&^`xj=Gk8W zY-UgJwtTGPe%`&Rvtt2Z9|x8hJ&>~@6kcyK!9;n|ffmj>nXm z>#ZdDC}amnP7r=U_zmIrgufErCe($Zz9ST^)geqF%nf}Pa%oA}k+6htKVBUdJ9o^)ZVZwY^LVJ%!??IHI5usFMZd3|jLKKeK>?ot^Ul{46Q%KkrFoSiDs(>+wV<&^g zP6jI`$w0zUfSgT=$~5LMee^)1#$Jdv>hVZ~KJXdgdedSf&c=v~qfzoNMAhbNqF*w0 zui6f%!A$jyLC+3Cte$;Jcs}|Sqn=$QWHH#k#+da`@)j{4fPQI=QST`&mK;1VCd>q9 z+@R^P|1wCrSJl@ez6N3NsF+%S8)9BD*7TnSb-sZXC?u4#S+VUl_Z(a0Jo8E&)VxG~ zxV_E*y`Jr@gSiCO9iZ=C6-ro(FqSZpFq^QDuoGcd!eYYSgnbDI5Dq3BN;rbBl5jNP z1j45XrxMO2oK5%w;fsXJ2>(U+Z^CtiZxU`Je3x)9;X%S>gz1DivDmiQ`}t^sjdA@`wi@0hz+t&GD}%Ik5MxtkK*ChzlCvOtpk?1xa2fe5(Q0{e21_COk=az5$MoOARhVJN!hF zTZFh91swYbYZ0c$qh?+_wp$@d?jw|K*d;#D0<9YFv~;c-5|1rkK{%0cD&ZW$g@h{z zUysMxX-hoLLhpio2Rj(QL+@apQ}`lSkw9mShnN@EKkD( zoI}=vTw|LOFzq&y?4{Tvr2k0*&UjyvUR)-4I= zkU>ebswc!)PIDutxe-?j=+!%uuy-0KqZhRy?39d>-h_h)M*@bh3CXtspCX)^jCsu@ zoJY8X5a%>K&1rhJDj9Jd;nCPtP^!0*dow-T3AyNDu15I*iv5i6yJTD;G;A1S)!5LK zdVr%+0&NqRD76U?@{Err!0E1d0c5L}Q zU_Zh^tq>QqIu+*RYbd;n!XHyuYyBmJBU)oPmBM{nUjeKnY}e*lH`r-|HXkRPLFj0U zv5&WXF#@c${Wsvpgck{K5jxr-wrF=6a8$c(tB)bYfcEAd`@Fd`;;b$DEa}Mz1^a1)#v`yDD?zslM(!P|~B=&CuUN?I~u^om` zSg9XY>{mlAW?=DkBn#DInUPf!dxkaCEX>3hEc2KJd^PilE^?s-A6X<9R8VF7g| zn+b6?maf=bt%wD%qFBjZ(K^7{_vlz(Ii2iT$xQEP#lYq&_L0^H*o%stqBz>7m(o27 zY;b*P^S1UF3uUY7%R1efL{G!>C1YZu(?2QCp4$Mu|mauFd^%j4)W>2QxWZ0V-tZlN?3^jL#`L{~3 zC}5dvvtrr6ve*xbwE&jQ;!`Ah2v|ebSFuNd<*?*b*=Cc?7S@POQ*4^K4{yXW(|q3A zh|N!tes(U`9?*zcQzg3sERRJf_B*hAxdAkr?Jh_tv@~UHr4`eB$ge4@QfvjVW^A)! zn}IcFKPdJdumTpJE}6+Pj2E)Lin)NbVDlAA1J;rqRxBS_5i@1@O5KW0$?()~6mP}0 zXUK9sVj0WZvTG`CsAUpw&uV4*>fV7>XG+aVi-mPyOH{hR#@horur-P$Hhw>#BO8$A zt8FK?E=!hWv86Nb#4afI8nDhRCR?)iEzj`>S+QbAfpuZeEA}mDc4d1N`vF)txxqFt zVeQPjvs}e&zys@j0HcvV!+w$8%(<%dKm8ANE-zUn})v z%NqIW(2sr9$YXO8@5g%O`ZW8ql3br=e>Naj^(~a8KU<{OdSCk#0)piX6Hl}1CO)5dh8<|) z^NFd9H}$pPG!`Klvj^_w(^$4*b%4!a)r!Rfo5|WVlPoJRLd;?hDAqKvn9X866l+hc zuVSTv(}C?)Y*e5H*jdFE2S$MvcPr_2F9rU>VWIK{?_D)=9C@APbw%P8CU(-EjuUi^m*$>miwU3BR8=T5BfavO}0w0(?Om2TkNc27l3VM?k+xW-NHI`@pdwOP+Ex<1Klr8^-eYe=ly7p4X0LLNm zAu~VhTWcI-9Uu0MxPvU@VPAV5WK}ZGl{l6Qs&GVzW9+tK6C5Xj1@@I}nxhXp&g%E|*jy-%vxa?DyEx8>k6D3Y^MRdU z?G;<%I4?e7#fq%}_9>g9*sG2U;w0Ox*gD7e;&WDB>YIhnuqwqiJAM;q*bj8`P9l`@BJ z!PD6_mi(Ax4+l?#xVDc=HZ1sAV4J*bqV7j_K(W!m&Df9Z`6pDH1<%v{%zjs_I`~E1 zuWZC<$(9Gdr2CB}jPaH1I%_+|SF#&y{up1${$L?vWlO9L-UDp)SgHAT@L}Ce)^(g@ zyMs^bZn3WvI~4q#?oVbPFWKk8Kk68-r`W~d8#=*@h)t$e()0P_Kt7zY1ks}=j0*k#4O zCAMvbY?oW1-|C(G!VKBBde;?wC@*?e*4FC!S?}U2XUcTZu0QpWyw*R|5#6;=MDZ%c zvRxJy&5g5t?Gnu+XR8^-Wiv$cbj5bKB18-?nC+=ib3+WjAQ|If^K|w3)H#xw!YnMF zSI?2T*ADAsi04D+%D6;|JET~nu(SGjep;~>z!Lan#U2FBL|#!X+qzd+gh=GiC{{*n zQMJ^3BCMAok=J`cvS-5j8It%q#b$?%Hl*{_|CD7}9yZO8#Rn{qac_jZY{=u&6x#(X zpC4E35U{3v=0eF%18dG#D|Q)JAunDe*&ksiMN585F}-`Op@_Q|OBU$fY-q!a7t3C$ z=YHAHmiw4WK7A3lGTS|LT`0Q*|8z7ZQ(A0F_kWRFG6)Ai*SmP%GswA9s)=e_E8{=hrEs?KO5 z+iU%Ku}o)*j(h-EsftU0xB0A3;ESii{L+CV--vGT|PS{a|K(v1hrA$*Zy zGk`tH|E1XC$TDpxe_OHFh`p!S4zMzmA5b=rL=Mx2@tcaBiyWE$qwZGP8^RrTuO|N}fo5MT3 z>9bkQcfBcXuC9GctL6uZO*Xw>J3>_R6N()q_QRW=-ZUAj`OLQ@`=qwRxPWhe%h!Sn z`5Bo5o7Vb9*h2n|V($WbkstQcT*N<>%=FKwCdNhFzFD1_0$a>mZT4ukH7?=BUiP4I zIX@*CI~ZkQD|zJ>Ii^1*wtKr|=b{#hm3+odbp<492m2Raq}X*}FY}u_eJ$|{pSer< zMD!5jD}1$L5z&>#S9#xeB}<4NYy3B#qF7$^)5g_&=6lj+`{+r0EuZ$j8e_oL@kJj< z&C2N6#`QdVuZ)`lYy;PSDC3?3wuxu%_qEGgy#9V)$=>3PYs3{vW(tdW+xQkAuUHbW z&3rwvDKMrF7`O0K`_-B~=7@2t`l7*ZL$??U+s+dX_*O{Uc@tv0nT-4MfG@x8-1L!u zT+TuNxMl}EGed;f&RZY!%mv6gdNt?iw(|-vyJ~!gPg0tLVs03B@@mCK#4yvleAPkO zN@HTK8sF#fhh!Zl#TZR{_*BVEZ^zUD_MBpSVv>RVQ?ZX@GJ!2s>|D$N;~u_Bv8xdG z0bi%sO^Ew|Z#m?dUn0a_zFXyIu9IWh%iliYtKUBU-VtB@_VN8kyhmTtKF*HHl|V$D zj;8%Jjt>X@jt?VEhy9KZ<4ni=jt|pKpYo)mGKb1Kud`D;>!|NK?I~V()Hmy&=Dm-q zHD;YM?F^r!*vvZZfvrF4yZU;D?>g#P+bk4c^23s`<#l$jbNrl_!OEZi=wrfqXyf1+%p2)=F6OY>=^-W^A+CkW8W(8d*10|*(zS|e=Vcr_5tMAc#&3FAj`=5Ee8R&D&A;-)C)9B>w!Qgx&OVV=2FLa`-{5Bz8xHIi zulm%(9x*e~_@v(*4pDSc##O}*GjmaL$`_{-1*d!?T&Lb9+7mE6wh!|%!`xVlA6pQ6 zQuwnSw9B)Ht>FeyN;bbSqZN}F;+LOEjFxd6ZJNXs#n7fn9Q3js%q%W@*&1#UZ=7cI z?!^1Clg$BQ?`dBSLE^}1+43i1Hvs$mv@Zv{`0BJT2fN5VD0Y*mhl_5CX>lh-E%Cf!L2(hH zwwSM&J8q4+ws={wdT|@gQDUQ)on_JDrEerlj@!ZNinU(0hR2HR3%+)#FP44lYqR>I zi8t<7bA7Syg2(19a|4ln(O1p{vChNlXX%o~&WpYrl10}`zV=KLCloU^Kz9C;uXWSJ zwM)L%O%vA@b2iXf(ggobvX};I%xS{*ov&Te#mdW)rGU*0G53lbak<2{Db}({W?*?W|h8S>7vSAHwnKOmyN6E$k%NFjRC7TK?NBr=sua$B|`tQD0$`vbq z_tiE}99OJO!by=Qs;^7dHNnCfixD@}Dk!0qrLj1m*eGDl#GIRwO-#trwGb;6dpf~v zX(8Ax$z~;Vw6qi--jXxJ{DiKSRziPUu8>wFlvrAeT*Y1m)<%@v_LTEsOIz{$ZC^P% zhz}I|9?IE4{GiwkDChkm`A^9ViGwZoizbSNBwE-5;(}t)#ER)-N3ga@j1Uiq=M`(5 zIKuLPSgDh&6|hcX8GhCT+Vg=#o1wE<=wiKD7m zoF?{+saIl_u2_7n*s#R0`eO0DVoyR`iTFdY<%z|tMCeSCy`DJ3QX*oAO<`{*uHijJ zU&Zz&mT3=(X^I_B8~}`&C94-_VGoP(#P*oJfE*qcPb&5uv8NRKjo5RF;q|(Q#UjP< z-si*ORmJe$=fh%?WGpD@IZGe0OR6~iNQKk>C4QC ziw8DD+)@nZrE*crB3V`vvZ0FQB@NKZ#Xl6oWB3TM!os~X!zi)N%T9_>Vz*@EJ(c3J zVtGj?MWqO_O12N!W1?8GylA1ih`X$^luT$jvrAt^$P6?&VD`vpoiR#Ym+ljrHi z3VVQL*5s37yyzmCDLgq#H$n7OaR=+2WfO!uP_je88%33PD9~4jDlyc{)>x{wqAW<|p1e^^6{CY>Pyd;`!!lK@R4gcEk7c?Dv3uBA_N*AMSVYQ4mRVw>V)cMM zFH8=}@{&HX%n`|orKVU|wdfiwS>u#7yjtv3tO(dYh0Q71{V7?xh2pDF$$CS&g`(2M zy>rh(vC;22h=pRCWUP5ZWHGV+aq;T8gfAO~0$br1w@9p3aW@*dZHvU<_P)5qVnlm2 zFEyXU7mHIh;=WRGizrUl$3M=du5BMH3XIzT+o9 zV?=Am0d;7m{vqzFf|v+!_AA=J>uBg=%LRK0`UKO2Hle*Q%CBIZ8b3{QiHP%ZFq$ zhV08;K1`BNQvSLwI(D9NKTPs^*8e@#(v<%l_fW0>DlA*z40(P(7HK9J<-je0d6<7fn(xhw4RAHgPq9nPkt{_h_3 zY^uj+JmdG*Ahdil2+K2v%JWakMV8@}RG(%XmHd^vV%Mgk{Ebw!fY$V6?e5$K#p-Ir zO3OP^{~FOhF~=RLnB%4doEhG&5$g+oNM(?ccS*9tPjbd9=j>pr&u5NO_%z8cQTQOG z@-LypJw~68NjtvQ^J!u^zfZk0t*p_nUKH%cT@qPB8Rlsi4ot&va2l2;Bn{hkaVW}N z6f4_bqLkDkeL0uP@_!nRlKN?$Fh1!|NScjEo<~?jl8%&DH_EGL8tz3<>KBWaJ?&YP z=F4R;#g3x1k5k&Il=g)*eEZ)TN%KGHY)bGe1L13A=LXe!J=tGJ7PgXwZGN#k$iBb+ zM``!c*ObmX)Kj1QMflX;>d5{Iji}lFp0>(M^I7np{Q~`Z?L3X~znUkdH zQuehxK3=5o@06pKj^V9ocj`ORF}8L(+D}SH`+4a;3wPU>`u$v}KZJIQxSu3_$$}{i zEnt}q>=Jp@jo|;RQ$evaD0VrO0rd@}uaUly^i4{CWi8ZSU8`nT$KFi$NH|G^3d>si zqtC~LN+l(4Q%OD`$tY^K$EoF~k{7)|UL-yC32$s{CdiV zf_+7nze@K>UWl$4*0Bo|`=cMq*qeV5<{5XEut_YUJ_BO|Gtg#O#+|cPoeWRygc@tU zuxAdebC=}=k|byN&0~JYk+h6Ey}co6=298*GwvnPljj?h=iePG$AbUL^X`?8l*<_s zv1Y7K&Xte3{Q9(6#=S?G?BxQAEud0$q;N5XOR0oX@~B^||BC%T*WFVu7q$Gz4F7fY zy=(gSv7oaZ1>D)O}ZGViT_ z?{fstSd-^0e;@l-Ht#N{#Lk&_mbM2;WU7+Pd;3hU%$n;%d|w31@JJ>e9V#dlN;n%& znoni==Dk%ZzVOUU&-sxY(c&KA9+|%ITnaDD^sHU)CGkI_(Q@yUY)xy+YVmgPm%;J8 zK98^vaE7HFVQ0b;!cxLA!jXhy2qzIv2OO)PP2mNE%L!ivylUCP@v74&I4A5$j|9U*vlF&(AqArISA|z z&MCJhkR+SU&Y57%W{Y!X0KS^@Jm4A#XNWC1^R0Pef6h_}U(0#fS}1Phtb=esqs`XN z!qw;&%o8eW)62hU>4jowi+zt?%nwzDYEn4PUSS6KkfoPvwY3r)2b;*qo9oV3liMHjU zU+xr;OZ#YfJXs!37CNw@U}3$Olv@nB;5Ez=hSx5qvl+QtA@{|(@7NYFyw6xd*CtCC z<`~YfH|tPd)7gv8Ltr2Cs-#w`gz$0OboO%Y=e82DF888sm)M>A3xwC?T(nK09QTQ* zOwj=+#YxtU9TAav*=!1xa10x53q^lu*f_wa~dKRZVslQSGW(=ez*{Q%EO)@FXwEJ7ByhD)Z(Bl!*y>3j(f#?E0Sm-}#>WFLiWQCL2IT2zyy&(y9;?sO z9cVnmlBYY@_+-FJHa)h9El+o)@x_4EP{Ka~Hc|;Y>#%GKL_&VUz!JJTTdEtH+b(bc zm2iP*mOmnJfp{SQ@xV%wRFcH(s)j)@MD1U9>F7{}CF&n8{ z?w0;M!{QKAKt4wILH_%JlXRct?}zXi2=8N8@{a|M)bS=WES2Oll`Nvk$-o0p+AD#_ zsk9Ce+oYJCVmM|`QC_F0B>UJDNHtRT9N~s0_Mip25izcyD5apFtX zzIitE2-fH()kx2={CbY{x~WRuqj@ptjEKQr!?ar%&W9%{oJVNmI7Vz7Tk^W@RP*t6 zuK%w2WV=~Ua~k9_-QJaY#KE@YyaTgJRKa|^Ltj|16y)gD4*h7`%XVy^&5*XV;2nE{ zerQ29q#bR0-(Dt0Lf9e3796p!*I_R#7ta)&u;VQ8xjln&0W8Qgp{IRopAMzEC8o0_ z1$`Lm{A|C@@cE2WG?w#7zfixc0G~#kYY1>;lRSiG?+}jO7{d1#%&->fj~7IULj8F_ zoO$Xy5Wm$g7e5tX_%|p6r&OFTZItZjOqM(AV+s!#JL{7GYmv25l9%ecfTUDk0$4_p zGX0~4`HnLE#KIPi>ug40JHXk67IvL2Dm<=DBArS4w?My;+PQ@8uPhf|7M57*QNH!K zoWs%2lR36%FEas;8IH|5@& znyU#nQtV2q*G5QH9$KnN3}SCX|1F{|aI(0$NfGXRgYd?ECt{%Xrbp-1$; zwOkJ2n<~5t!iJ(nfI&r4vJS#7l0*>J1Kg+Y)@XC+YO=hV@-5ZH7cDehMEjQ2d_>F{ zh{ba5rV{QZ&D~0Z`Uhz3VS};rnyZBF*IlEu$4TcD>2Sm7qC(48r1=#eZ95LBM%%7h ze?%dB0`pnC2daFmy4GOUjeLRKnn?gG2sb@{cR@kI)>4)%M;STIK7R)-cXJ9SYl_bR!+ne14>j7!&kt7ZzCKj)|04w<- z-9>|ewbgxRFtK5}v1St-X~&wuGHI?O+^EBnY}Q?Y`hH20Ts>kFeXP;M3MgDexQcMK z9`!F!_%elm&|iVPk_}5u29|DE4w!9N0hmkSCWe0j78qUuEHb zfL#si0gDYA0DBuY0roY#1vtR41#qz8ZNQ<1?SLZ;?*LXBb^(qyyazbm@IGLb;RC=a zhJAq34Eq6R8a@Ji-f#%8+HeGLzTp_)BE!dk%M70Yt~8tkTxIwiaJAty;5x$>fEx{8 z0&X^(2i#`(8gQrKTfp6hi-3C#-vJ&lTmd|6xC(gOa1HQN!%u*x48H)LHT(wnmEk(z z1;ZbJmkqZ7e=z(B__KkV4eWP=4)CVI0LV0>+05M9V}LOl_EfSq9WY(P7S1L~u15W$ z2|e@+$%`}&lC~u2K(U=j-c_3g`o-E@z~0(?z`ojIzyaDzX2GhoH6|0ALi*E4f2M{$ z`MkCpbgIePd~F|u7il*^zDzp^;g#Akz*X9(fU8NejwBmNvRTu>+BWSpgm-G^0C#KO z0`8?;4p1(KDVHBe@-s<(C&^9i8kW--1%BJt7z;SSh@~BDjEC@0Bi3bvF$Kbv#!SG` z#zy!_0MkW-U?vmR#b!dAb`#nRF`-R2U@Du;ev3?H17`Brn2v zOl6U*D}-a&KLL|S-kz-je3b13Y)SHbl6N8O54e+cf$@7@hZc0kq=4VU&l(>E2{R$a zNVFgp5KbmsLHHiwc|x5PF_y5U4BHU<1|wDxE+gDYc$Sbk$v$B{rxnUjK;c5dWzJqk z&?nqYu|*+>%R;csUxhj$Tv(gzM`8Jw5$+^BOZa6Jej;bRF8;Wc6Uh9hTg`UVoGjZtA1r|-Js-l6!}g#P$#7}^4wGko!KAnm}3 zdo>qYORdjXf3XJJ9=46K&9Ke4y=vQJd*8O-_NC1jkPy%zU`Rk!z>I)^z~sREz?Ojz z29^X43LF<$6}UWbQ{dx4?*`orinZt2%k1U$S@t#d1NO7_%l7Mb?l3t*99XQ=a90H$3qT=d>L{fl!v9?3=JY?h)>n+(+HF+*-Ib{2N19c!Ti#@Sfr0 z!>5HW4SzTMboh7SBEl8XFrqM`ZA6cViipP}#z#zzcs^oY#IlIB5t|~mM(m3?81Zq$ zw-J{keu;2I#zw|Rrbaf5%#Xy~F@m6x?Jzcjp?5-oxnUI%4wwL#&LUVt7>h-;)3x1< zFAFCUb|IWixSsH~8DAT1U_qQ~LCH1?zJPj;!Z!&gTM<99cAzg)HoZghGuxf|{uWLI z`Q)(F877J)1507`VeVTIj+mqz_j8r0 zatU7!nkYcWfm`Ptb)e3RPLy}zufiyKIb<#1>meHe^WE>jq3eD(Y8DgrBTN*npuwu$ zivSlAR@6cqPxx%DWq|VtV{0D*Od@=-Hd?z-+ihg*r`l-ecfxA2xsdR=7>5Z)c%9yW zkLm^i_Ny}t!-Vr{-KqaV9c&qWT?{Xa#k%<8s5q35iNo+D!WnT`yLp8Ev8C~D==`cA zl+Pkul7wyY3We7azC|coOtyK0WVDc;ycUkAIZS|GGy)VXkm0_ndEh&6R0qVb(iuRK zk9Xx*V?fk3LbxUT*AB-dc zE9(Zh8!yb^CiWVjU?0MmGqE)=#_a5MK*4l83Bv1O44T+lK*0<=1;XoLG}_r4fC5(a zX}AL&pozT)rMAP$JsspGo&l0Po(Yo19CxY?<5{>bGRIweMgT(l^M(+9hUeg(x*Yqw z4sQhE9XuE0+W`fu%k%JBKF^16K4B}~6eO()+w$fhX#>bvdtQjgBHj`t_w!bGr;E1% z$pe6b_2TUSd-L{qPmJFWIEX(0IGA?^EaP49&J6DcIGgtXtmY+t; z>?=MB@N51U;5YmUz>9ng;3bY|(xUdEC0m`i(Wp z7H4Z{E3_5adf1l#f9-t@aAet4-hC~#y46zmjCy8vW^DDk$GeMXu{A4cr1@E9e_GwG zQSY|YT6JrF)?<2~x}T)>^xwSKJu_OfAWha4Q!%M^Vpov@sz{L^s8AI{NChfR$`F%e z6O$|n1PG8a1cOc10YXTH6ySX4+l(j|O9J#J(r?<=7v_#t)r7^!%Zh4n28z?r`^Ta%z6+Sp13jVmuYMJSOZiJ5ozW=WZ@p$0#2%iY-|3g7H z;1PZx@RiRBj6M7#Fp2`}KT5K+jqrnkPaynI;0F=T1lE5{h%`k$S zznw>pjr`#8_u}udkq@2tz{vFzZwd>4|K#MGB2Qobd1vC>KlJ?QP3ej}2?5)@q7e!`!j5w%xLOE1%&! zN2ss*ku@@fRTVKiX7)CH%Zk0@^f#n@M{q^2&br;&u`S2(a+Yg#i-U~aYI7vlYYytbNO>2%r~)~&APbR=G4vs0`4aa_HYlcSd5 zm6~-&EY+H(y{CH3-mPt~o3>-wy{*p3R?98BVRpm|>)Fd{+<=+K zpoEOQ00!T%^hjl%qsoS|8}UuPb*F7Q4%&f!Vr@-DF5BjwoZfV+-m-~obr~(T&5FfX zS$2nW`q0W16#FnE*i5=r)4plh%k*tR*}E01&7+}$9!B$O3W>&AtFvZVU<IBBN0nYEXVh0VIgosv4l1s8>-0@gP6zA9 z+5slQ_r*>kZ8mS4kY7!Z?uuFOTD%|>NKCdG(isx7NSJn~+xEKlVO&;)J$Vo=9e>7V zbC-peH|4`&4b}r|kSt_5TWUcxi*iMN^;NzF_Ns~;7IV$4gEc&PqJ{xJu3IcHoHLiL zCRSBNWNMrN_Izbtlx?U7rvp8*V|4_!@Uo*=*sj)Bu8O}}@R@ckv!rF2^2mM3k%Z1G~Sys%ZH#c&n>zqg} zp%KTZ(ndCwNiF5GoRM8i7cx2YPKk0A%AN;LTAx)vaavUpBrS~(1a--EomR)J3%5;) zlN3{2DKk_;61F@rO;mp%vs!c7W~Z_Xj$o4k%vk1#oZ_ObUj@jTbs-!5l+Ez0I z0n*wL+12&Zb&)Tmh$~3&{^e8j@TjW2#Ii z%qkWhu?N6lXrjDDhHu%iE4k`jr1m&cY3@sP}$u09|dSn{R9RfoZl$GeQt%_A6 zpG|-lGtpM+~^@gUzS3?FBja&>Pu|eH7FUot~r}n&WkE*+sjyPwP^L1 zce%ik?6SsEh+@k%t6r5!a7#xDJ9G&3>5vKnr*$3uEP*?`(iH_!jeQMzlQtt)tu4JD zLDgG=b~3wmtEsGK{>QejcRvF|x+iD+ZdQCwq7 zMA*FXgCJQoz0&fifg%1~Kj#`tK2csA#ihYw-x!L8sx6k3*o&(+euIS0zwB<5Ufl45 z$f0U{TNHXUj3s=HN7)B)-wR#6yH>@+W_hM|t;L473xB@8Kgw^h!A9Md!co>b_Q76^ znLNR)WfVaxlgfP8-77b9ev?h;PsMac3hC8Tr6%Rk^T9{C zH1xrA52aIBtP-HZ{<4d4lYVW{yh|K~Fzt{2;;t%fV=R4@3&q--LrylBj~ zR*l5el0I3sCbDG99G`wM58MYk&mG&Xn`)C;!v%7&(X}T9eFS|?X)anRN*p_lLrN5* zp<%K%Rck(im(5e9HX}GrDFH1-#okA^xwUORoRsGn0TO$%La6;DEnWOk$3gpB=LrSn zFr5hQkU(V#&s})Vm(CIfCPYV!JSYT?PrM5@EaWAKTX(v~VgRG{G=YmGZofh;*0)he z5}$FyeyFsGWl#6ffy-=ZWusFKL7~h_V6kiacv=neapxx-xAXDuaJ8krYoE-TB^A5i zOc26mad9;nrUcsu8y$X`LMt~<)3n-EqMJ$+Y$caN`wnpjXuHkImQD8XZcS|T2@hN% z96DA`N_gz*yY5(&U>ypjjgi4mv;y}t?vqgSsqkjoBh42W&Y%(r*a(;-mHkppFL)PM zafU-Ts!bf;2#s+MV)69${pjSQXndWv`6=#9hoXitZrmDP9%&Lq(9(>cE}NYPFtG*1 z(#V*|O<+^F>gJGxFuf_3R@SKU)@F!#^CMVP}q=jUC{mANb&UkL`iytnCY8xrZT9S}E2=#PKKZGw`cUz1cp;}X?0GyB3$KpyQJ_cxD6AGR65^VTN1mZJZ4GR9Iok~UeY8bFvkN- zvayZC`RkY_>-}j((Ql&)B5=}_g3SrA?}6JmQa8m3Z zL^EG)LV)ktCz=8-Mu`2&k%n-Y)!T(@1HTiVR>{i>et#`!sZne`X|9YIBP&nBdrO=_ zEskh3uY~!o=RMM-Iu<=UID>Q2cbo$)e+Bv=8jYrWYeSmMFNUAB;&r1lEZOjz zXn74^+twQzn9aMd6XyE8ebrk{w9VaiFs-s)Ip6QZd@xZlZ$>w02D6ot7j9aLlp2&>zL?3F za!pPTOE43HsGiSbST&=R-`FoAeFQX#$zcLB?k908EU#9xd^Mt%x*2w1K>As1Iwltsk@O&GIrHH)G$ z;=V|e_X5Blj{!o9!FT59z6zp>u(DsB%q5Bz+yM5IVI4kWn%B{_Z&)WNs76L24ALlY z$4?||O4qUNj?Ft#Z((Yd(JP5SuxXxUwGBser!dP1;>b>LWr*Cn(F4l~i=)LZG$+i!9rI955^obkj)Xvr&*?)1mkS6J$rb^)M zBH!`4K>^N;(l|{DL6JNF^I=&ziZyoKLuC0k)r!2OIaL0RWg7vZYXruW4(GngD>0FX zbEEjF7r_2;`xZ_+TA!W!0Fa_X!J!Mfq>{=}K(*N@`d|0>Wrv(o-4AK8F}!nMq~ow` zO`Nm}VR-2(s+XqVkZ%bXw0EsGQ%KGXjxvFbG9h;<5xnX{R%C~bjz@8OVMdbj zd9$c@4is8OJb2n;+v30h)9Y?H@MAqoc`LYtADgCg-Z?+j2a`wF#Z@fV=hedwiwl!k zW}!>PD!Z){h@_st#i%(RPV?jq?lKhp8mIXpB}@ab-73odm#X)auBYkm_BB99$X$WJ zU=0<#uONy=r7XYQyIs4+^P5g%GLnsc{x|7}K8uHM$yC{(jeY8sL-Go{R~$NGdV{JG zhgT*i{7S1UtuZC()78TMFV!t{Y&5ijV2kTjTFZky2y@bLNdM&q%aOU0JqB+sm51$AhW#jW?^^v%ZpI=%KH_S0Lm+Sy2 zL^N7X(Hsah@`!XJ9wk{g($O0XN3)+IUo|k$|G(A_;C+!;4N|U={?GoutW~gc{ zo3Iln7|J;AdPZzR^T;X>Rmqp8(I-djs6{CQA{b6MqiGN03Oya@%TR2&e>0Sf`;lK% zE-hHxc1E42@l@bG6&pta%y%vAb=g%+ zsg_uJvUkC3e#&snj`dVksCb8R$nb=9SIKs$DC^N58_YyiRaNXqn~ockPq8K4bYH)t&c*RYx5rL9@=61!}#WCOsN0YWP!@?7M?N52AYBRQ;P3*~#Nr zzOr%V)3l}e>J?YOVGd{2C0Jl&ctDkPnMvHrRmD~!WD)sH z)pxTVGqdR&1|$6EdhAkiDM4dsu&IYWOojI&-g5zypU(RmgT~CqFl#? z2X9@)nr9r%4cnv?P)@hKQSCI68P#1AOrBTif;zjOvV)!`?F{h4W{G0otywibTfOk{ z0y&ln(+ilJ@K*9_wPwY0*j%BPw2v591|ijnE3Y6$M`$}|y6m(`{}ZOYojM8*H%;Fe zD|Sw{X*FcQ2yp4v5f9Qbacsvl7ZGBqEW(0duwS8-eKF_pGOO2%zOYp=38bCQ7{qsL zUrQef!)?tTUR|g74%#P6epHyOjmloh+q$p5!2AAbJdXytFZHfLm)IQ~hD$X+@)`Tf zxztYN@zY1qkI*i0LRckBI1(h8fv3o^+!R%17xa=>%FKio6WHVIuQVO) zB|Hc9k_^Xp^Lg1gf0cIAWz)ImuJ&N)BMNN=dfj-u=`%iQLUVLL=NjE5Tgl&=b0k_H zB#mfU9UqiB5seP{9=cvYGJP5Ff|i;E*UXGNeGJG@H!qHW&gj5!c6!_ycO-p&qQQbo zk}ggB)0}uizEyJIhkK2=qmae2@f?7z)4pNH#JvLqfNo}YCERGvx!V-+=!TL zUJhsR%|tQ3ws?MQc3da%+&RxV03rpn>u&N}U5smoUSPB58?j!5zjTL3>9JaGvkkGZ zsI%s?)JzXG-nCXw|OSCO2=54aXBGZC%FrI00;Q&8;KT z@6OxRL|LpT1nb$lRyB&Qs;0A=i_`Nw=4e_b6t?Q4zdDR!lnP&w=zeY%m%=+o#LMVY zh~`OuDQl!6XdKboF9Yskx^*_aQV}HVt4LU^kLy!>$4TKH8<#6z55YyfQXLGI9*|+C zc}lBJ*vQgkOS|Q;-@l9P0?vfV_n= zzqX8SpM+jotINatB%miivtX{3jB&C{3P*c6xV!K#*DC<}RJ#MZ^)MK1=fH&DX!t%& zDA)Pn--?d>ORMPe7(}-FmG~Z@?N^T}lfCSzEwn%$-MUZuGCf{FEjbU<(HRyzKM)r5 zeFL24Hd(@BlMJ5-zqOV%Keyf&*1BT!GyRBXTfb8dvu1+-;&Bjf7@bk~L-P*J)JgH0 z7aw>T&Ui4vD)7|W#{*2xXnzRwMojMnm37(bl*So761u^MnSdn=AAoo58=EhUhaIYt z!?b$!Le~ziQ;@3d9=^#OZ>Kk0S50?{$mrg7QJtjch0Q~+A`*PbKT9LER`qHqqCmH; zfPi*&5avFZPzZ$)#ifGKPB`Z6CsQTE>@w3`WE8G$SS_yg+ci>axgxGG(k;OlY1JA@ zt|wJD?IjHpWQ-9Uf?({hb9mF zY>g3rmtWU*^0FsAGANUW7 zA-*Ze)c9T?ny;R=`HHVq&VE zSftI)Sk6wDV$PH`R;&&m#81|oU2eNHJ?mv;XC~9iI9QX1z1Lz->cOd9cfBIr>60!$ zq#{G7Xjj)|v%jT!@x$=!6zQf7V?yY9_qhMuXiPq7^f2B||J&skm-_3A_DrU;TQs)m zM$7aszAYUfRM^M+B}=AN8(#?h{*I0yV6bbzP(#_-7{d;03;&6QpZvGv7rD>*cDLf^ ziXV{nX`)W%QR99^R7v`Y9@0?9BzpzZB#gpurF-hC_3Q|3%mXn~jLW61PVmOSYyC>4 z&rw9iv8mZN@I#_`VH*l$+;7snb8{#Um&a($uFZNHj>;@c>kAf&PH7gQ!qY(g(vLH+ zD*vu1RDVXH&0%A`Yhzm+GKqIZU)e6X$-89n_wYKgA!d(fBs}h7SaDG+^>&PUG{?W* ztDt4&MqvRhiKYR$^t$HhLyH9T>7e*mwQwRJ1G;3B>s1_rxYlmEPBTR+UQHX(3dbK7 z9eClN5~a&-j_X3WTp|WHnydNTwL5tvyDc%+w#uC`)~ILOTl>WxxtVC__jNvRyOjFR zC~>-fZmgDTYz^)^SCvMsc(*piR(cs6;b`C6dqi+@B)WXuI)`uJ&&a0Og-dkQWpCU% zuy+z}$nWnHZLa@4EWWnh8=bDkFjiCJV8|eM4fn^0c zbJZ||R>Uv<+@(pAqh<6?aFT-b=9l;dm|sT}GIr=C47FDg5B9nvv0pybAUSib?tTmA z>I|WtQ7k&Z(R( zcI{5QEl!X^FyfZ93^83qD_SchFKEU{w<_($MutA>T8D|^+ckihqGoDB)hpx z=r*>;B%Irvo0);1;QekH32UcP=_b@wzvCfK+q z?9L?KYevnwDe%M9hpzun!VFJ%+D8H!;OX&>>tZE6{b_OO%^y0cet~4T>M(}?S)VN^ zXohw?*Zo55Ww{(+vCbV#tsWkA4=o`M{uh28ZU0i$M7?=fUl}#+8ADmPn|K2%TZ&U$ zl8;&iCI|#ljLv9pI3FhGr?JvNmdcOs={GmSkxL?6U-8XkGHDZxHZvQ@?lR* z_R2y!F{#nvc6!&Tfjjj|w+5P1O6d1f%E%QUC3HsDzV-czP{cH$vj7o8kplEAW+?NH zncR;9HGF1B&uW%D_J(P#;5TgEL2^>Nl$KB~5oXo?;u9xbDK9UtVtJ=*9kIm-c4n4n ztH33OGLQ00tcOMM_%y;O##P9Zi1cjXON8lBVn)YgCjhBE=q`y-=I>=>6PsM-9b^tw zjAs1RmSHiB4z(zQd^+Z9`MhY1wi@OO#|r|LnxH8X@F0V;A7mbM};m$2Kyor+xKmi}b>Wf49J z7k;oypA$a`t{CR&Jf{e%`soi=gm^Dcz!r9xp)ylB<$;!_G2f6cF*7rTT|DGy6@%lv zRm7XvQt^{q;%e#A#HZ6~sxco2>7n9~zOn8Uvb^%q%Py)!0w8wTl`tko$Bmw#pmcpv z3wKlQ?&rDGlw9>)@to};_N~8h_tQs?q*@Z&13;{>uPkXW%?MW&zPX^2M{_EZj`4iF z?pFXxav72amQ1*1!H`;+e~cv#mT|6aD|))18)5ZZ#Vy>auxEmtat_<_G5gK$HYm`E z6gTC57@C6W0D+NV3Sj#DB!qEJ3ayBY;Fw@(g}FF(Y_yae5bLNDS4(-;>&_$Wt%*DB zC{UE|xVWdgvFqWz^H-q*7f;guAc(h>zo+59?bzs$1jRnjjTIWJ0v~XiDWf z1kqX`4=QTj62^QPvk!L)a#_Sd3ZPKVrCi5R7=Ve2UtF%3(YCw3QcbqfbpwN#yfdbeM#g%rJ?!xfL+83Cm4uL5>%|Ij~88hrY^$IT^7nHbZbbOB`L% zH2s2|a@x$5r`|xjwc+%(GoXd1FG!}ke`x;CqM^cLITiWH)s6PXKS-F35ltwhkrCGNo#{o8k5?$*fd(jYtjbcDLxoR#nK7nzgkL^Oypfr$x!*WIbGs56a~; zOPP)guX-~_d``}pFH=DRJwqsfP#D}lGrk(;Z(Vh+A~RU3*CU^w6O}~% z*EfRDHL1ewP!j^t`DCuYP;R*udZ0ecskD~zk0&98bw%4jSuNsb0-iZe+s5aF+A z2Ak%%2po#T^*qz-1jx{!Eq5SKs&SZyxYgCX4RzR>cW)ONMr?0{+0%9!Bybkk!L~48 zycGCnt0-foeT8Hiix+a$kJHJ>0aPZFW0tkROeGvi@xz z^&(wY)7(hgJrQZ~;)2ZkJ-5$cop9 z>mo#%XFsYi(e>545gmDs3dO|fs;0Jc_nLWq8B+7N?QnebT+;O(_Of3ktf?MK#@@}8Sh!jCkLkv2TNbDX=&7H4Jjf4E z6a}qBPfpP;C}ybfb=CO(l5VYciGiIzr?|-I$htoV$;gSJCtqO}dWzvff!H(--VJDZn)_d`&9(Lig*r|I>Rf z_u4Z;d&%D9^^R^(;M{V48&!4<*{~m6-gDHyS3$nxL9wn$L!Mq^#B+%W%qK(|y(#T| z%%NoNvJOenwA`jR0vDA_^)#fmY?&wt{!|!)q#dbe3sGG|e(7PAE{&~u>|u9UKjf}s z{n@%-mF5@=3Tqp?nxOa4=2hy@9J-eVOz^jxgVS?OXfzSwi>)RlYQ7`okktZCBkgUOG%vM=Os8E??SD zAYE-k*~IW9t64^RqdR*?=bY~e_mcKRnr!Uh1mG=yB=4dZ#is<2Y)j~>nRym#9&wV? z!9_(U|4U_{i56rKAoDtEV`rUzE>{!m;5HjzvGjQz9i8l9(5UTF>-@i01(>Y%Rk=lB6 z2ilLCmQNwa6MigBbU|H#8aG3_k#v7HVEjto(*dLJ@y*9)re^QIbI0g^Z9N~ihR-Jf z0XKE=WTDJya9E4C+%FkP@gqhHO#9J+4MJ9zTJI)A9Q;{qrKV7z4MaA>rJ@swXU{EK zbUApDf})B2T5xm!BKD9AET~ESP4H5wIr#Y#@e&jM2_HQFl>(0qox8Fq=7QUVV&7Q?E*3ymZi)09*!LV;i{_d+v@eV&&BpZ!IGg%H26x);0P zaj1NEJAZ(NTkyL#Cce*45uTAF4u+-FDJoR43Tl)U;cyhpbkX#b7$s8zp@5H{B`u=h zz!EFdaw!9IG?}Czj2$B&a?+qM42z3jh(^RRs}Bi@eWhcR$0Qug)L8l}^Y+k+%Rl3% zaPa;B8T`+TlXI_O4Qq|{|`V=dtt}!soOi^;PV1qRz ze7}gM*jT8bB$34W8JD2BQcfl5P$R?!*&xcJ&R~ni^hZDvrR5W&1DUk8pqQc|_F1ja zBSM8U`iZyA#a2Mc$Of~F2PMO|K{AX=6Rw27Kyr#-d7>#9#ZxGNVS)Jjx0yo|ApG6l zw*x-l-aDoT$%9gO@CzO%K}yPjXFl>}W8ecm^kl5Tz{n#siyc|Hu(3D==Mg7jH98sz z_+=ivyd0@>F%xH3x5FD`M@Vb?cD(wE#6JW>IngT<}qW+*X*F7+RflZRGXh5Tts%pI>NrhyI2 z>#t3F4NR(Rc!EfYW=J`yLO<)upW)gep8b+apzCvsm*V5&@#U##n7DGYQmCaPA`h|p zzdREJmd+RXMio_E^E>l4zIIGcEC;t)a0C*yGC_$|1F<_vUJi;T%Ac=f3{_!L6 zrAUj_|3)z$#iey3>&?s<#>p=}npsZ7!Us#}*IEK;84G;<^!V}jCV$VI_F!q~3C!`@ z&gKge%#_%y0F|9n5D!ll37YzynP8Wa%a^~J*vMfH>w-iq8HWUT699;q+b|y_VvSI# zUPmT{QhLq>R}a#PK0W!BaAN)yD>}iny1JfmiS(IKpAR1h4xQydvV}EWlVFYfN75vw zco1to*p#nGPy!fjfu=qLE$0s6mCUf%^Ot!W*LW~opdVu5&zPBGjDRE#=$?S&0Hq#@ z|BU4DZ0zFjWgk9;lYE0BQR&&xRWFl5PXKhEGD=zUe1rmJeZ7P$8&g5kt?X5=mn!fWM?4nL8+Uyg^c@OhvgcQTgZ2{qWW5r)apyby!n+5u)Sc@V; zwbrlu&{wWTLkVb@_soJoZe8x5dJ*DYc?6J*4ie-K4hH6(_8W)L@Jfubf+VS*5eAaY zf5%G~;!Onw{27G$iw=X)e`B`UKZwmQ#@wJd*B6|T2K=0DQzh^l`-g=S4|6}Da%&WN zuT3Ph80BllrNah^NhP%qqI`4$4IAVfLZqmSbRqy}fC`!Zrx9M|rdSgUoJp?IHzufF zZ444qYYqs62jnp}2xUhS<{U4JAZx5OAe|jme9X!rIU-4=8Bvw)-9kZ2gNPE^C4q|+ z<0`{nE)(nQ=35abG$I_d0X%jxLLOf( z7J4696?@^2$X*1O?=TiLwwW2RFnW9h=}#^S|6eR&V{CcDW{_ndd(e$NWnhukD5{W( zqfnW_$#^sJQHjq#q`Xk*kI7gGrhd({8cl#Dc^Z{af3)j#dpRZ*0j<#y#a;QaxC0HPH z0J&;Xnaf17Saf>KMJr*aWzG??Rxmv z51cKm83K81f~B;A7qq=uuC%cLiG#A^c^(?s=zQ+x(Ae})+38tXSg;6r?cy(zz5c(V zQw!?1+`p?5D7RaGm5_}2#@2{`{=~c`VjWr~Q{5$LMnRrcQY}YK7)ExYW7}`~i=l?S zL1q#%DEocgi`u!@QyO0!Y)Go@_h7r#u{&k79qEmh;~1NYf}h< z#-iX1kcCwMjkUCeZL-SL^8AC$LPn*ykRZu|!ppNRMWhWY4$E6?kAlZvmw`2Bh~O2`L(d<|r%EN~U+wQZ-O^pA<#%U3~3rm@x!%F9v62gTp5kqhzOVx*t9pPjm$i8rdBS(w96SNBop+$rQk!=p%p5A9*MUEU!?ea>Dh}kot zL6;0eof5<*Wkd$yqLMa1G3%if5@GatB&n&A1r4jY)8JwUUwR7k%Gf@k8wfrr2ro%l zMC{5kp(ce4;*eEt`-n^|_^>uUiW@{fX`TMUx?sc$W!e;s*v&55UEP1e zIC#nv8wc4%g&EP@j@|g&y#1IR5{M!^L>;J@v+`{T@39mO@1O=L;qp}pr#4go)Cifp zqoE!5h>IBv7^X@*;Vk-Ns<5Dd6I&I;4N4q5$k3p4m#DWOuCQ@8n16rVx0{)Nuk#9FgtVXJf*a4SfJatAhk`+Ex&pd@R5XdO%tDT2(j8G>FF zYI>7ejS*MD)&f(-6FZlJnEBV(?p3%15!I&kC)nV5#7&S9D&2?Py71fMQ~2oq_wlID zgvw_fc|!6Ht5Blop})|X((}K-RaMfdO`_ry{Vv0#U-yv-%Ix0<;^nq=;lm}!ox?>) z{f%+*;2^$*s~C%We%L)j#)phf6auxc%yc2QpFdmT@`MKTj z+@t@nqqRNYod`+*xPCowpCWNe@$c?tgQW>9h%wZK&B zxpYl%6BzvQR-jZ~b|_^vNUQl$CNlQstVUB_@H;HIs2-}Hh9w>)IWgkG!4uJ`Eap*g zS?=o}SG(U=K$2RJMubEvZ(wdF+xo3f-EEq_iQU50B!|*P)|5(IS3a%ejRH+_zyah zNGngi?#8t6_P6!yNb7XJ6F1HwY9l107W`t1LdPbb##b@GsyGyM1Aq1Yk{#ar!l`)f znI!^Rol=oc*d}Kjs`yeI5&A2J5}Z*hP&u70XZ(RE!%+w=q`8)nHxPEyZ__cfJlRLD%7glZN23A7|KVi_%eE( zx(a1&3Zoi{>-^$V{c{j6M_@MiTZ9HxPnNW;|#o-oNg%m;YQsBu~C;a=8=X zvyK?UoK$o}JOl>C?)rFj(8z5a8tv@OOXYJ6=aB=wNNS54L8t z0)k5x_Z=#Wg0%IMYT7sT9KYQ_mgv8>Im8S#^ciEGNz)6)^(l%-`UBhG8Ft-=moZq;Y&XfHTC>`5d7&6_c(>1ZJw{ZP$3;ATx03ir&TL1fB6jc<d{KenK{iaL_Pm_g~>t>cH2Q$CppZq~Fa7;@DqNIoub4j$X?v z<89ewh*D|CZGXW1;t^<@bOo*ud@s9%2kuVAwxR#^6Lf@h$W?TJbmSMI;1{Nn><>^7 z5Ht`FC@2tadq%N2h@Z2QARr*}KR`f`zMubX!oPmW8#`EAn7g<#cpBT={cjo%lu_(x zDSmq!5(I<|83Y93ztETOnuLs~qqDi5w2UN!tEcP#Wexcc&*s5EK+M1S|7Jm<|HH}% zOaK4aIgJ>ZKi}gp1_uE_`LBMz;QqtPS(}8W&&vP+08Ie^01yBG06}nYO<`_nW@U49E_h*W zY=w_aYQr!PM)!r@LFfRI2u)f{Z3v{x6w`+89eIKU8jX+?Dxa;39w}Fdoj<$?WI1o< zeKT|T`+r}7x6~uJ#4=hJOWvjA3n`=S0GlY#=s=NnNoYc;trXD^q#Y?y-Nn+2SPODO8z30 zn5(zhLMUE6KQT7>Ow>(C@k9rH-84d$i_Zq(w)C6!L0?PJ+TlcbPLp@yrm#8!P)h>@ z6aWAS2mpF@twdg)>>PJM0001v000R9002#Icxh!WWNd8heF=12)sbkurQdtqEwy`* zTDvW;w5`RqEH5&)u`J29uw=`YWF#;VtyWuZxuqw%TiC)jv629B!oCds8gQdvD#kb?YvD zyWM`~6`%otj_>#12Y3|3Ya^Webrj#8IbZj{!_MdDKB}}mKeuaNELl04um=<2;mSyO zWW-KY_D3rdV*Bot4A(K(sbL-?c!N(a{3Xrf5)dRiZOp?rWgVbt@LYMMxNe zxBYemmH2*AYDc&#^ajX20TkxbOM{IU0(kjf_L+Hz7nZvXM7h6FXK3VW0D1V>a~nW8 ze1sS3XXTI<(pz)r+Enyl3ZGq{lI^+(GJ59}aZYU_nTUYY?Md0tPfwOZYiz7dMB{cu z=t??sS(i+c+cZ_pWw(pxR?gypJ>6t%wj#ft*$Hs9_TihYEz_Y%;%X=W;8NA&1}bAD z3y=sEN{&XHAaRN$M<-4(aY~32!j3nVoUZD2DU!*XkP4L{w!~O6TMd;HcDj0K01cuZ ziXsd-NFD-M|2E+Tz5-YB9%Q;r{Rl~z>JbtTRbbwl8k2Js*|Vv}IS6btx67!>H;)@% zAywug=`!qj_*k?A%9d%+F3jrF?D-^*F6@%%LMmhtXP7f@&MEdOh$c{l(S(V>4pBg61C_EVQL~Diz!Ynp=zqA z>DW#Ug6!kePW2EC1YFKR>QO8?4depv6bjUfjPzY3Z(L#hFy=( z6lz=+(0zJ!pHB}sg8^67cAwMdx-muO2{qeP<673+3F#*jZRNpJ{{sI(s68Quq8dt4tX$b;USBhxaWw)x(y*bWO9#f z;3f{SjKPU9gefdowP&FgJx7R3e(ivbDu-F0ni#|WI^xKvq$W=z9jQb$IK(+Ldm|ZL zFK{RC$6R@qdW0%ja~b-n<<~=vl!2lJ;B23xg9)p^u$msic#$6RFEGCf7l z!~t{$zh-Zx0b;67;TI}bcSPr?G=UPKFQF<&*l`=n#k5n6?+38IUct9V`YXi^j1XXw zpJ}01EL3OcU=3)dFkBaWj2dBM9>cJm3=4RKQGNs72cA=Xn!Y?Qc{=4y`Y1U#DN`$!@}}O~o2@ca-L08w zINo%iEu0i@*7K~B_$+pX8Y0Vy(3Q9v85f*QCK2@KS%8NAC2i!lf_s3u-b}V7Wy@6P z#j;)0Pr{@-$W^O6ekIf)rbG<*22wj|l6VVUOF15NXIx8W+C{!uz@dYCRm3(Mi!~Od z=R6fxD`lq$7r|iXl0nZ+&yR^`b)I~xs|MYat?k0hssfW>^`td^S1VzR_?TCwm;ckj*PT~Jt?HR;iMZY{#wq#E_ zJtr^fK2r_u+-9#;*#}hNGE26r>>#uRGSa+Vf~N_($1WqEI4+CRj}TLJ1c&N0M-?`$ zm_{cRsZE|Mv?Cr7)kE_#>n4odw0`u-N`--F8Q`e)Ifm5GT$(r35U!Jqe9Q=#o8FbmEN36?K7!Awu|W~be1rakIXZL zS1<#wRG2ZeN04RGx@D8u<&w?MM21~KHqnpFW*Z)vBZX$mXN7#G`IYqCtR6-a=!v^X zhqE(lvwMMKAI3U8M59&<+8?9QBV%kx#@N?sdDur0HmK&Z&LO9v@(nSAmK!`Hx<#cm z-Kxo+&mv0`D*c+y}y<_WE=L*#HFT>rR&OY>Ag9+}G?#swkIE+H4;f@EJ+$=ITX z3fKi$C6(56>EQBPW~|7D4bHb1^UdNu#_*-PaN(_m`f16BuC1U(#I?*2&I(m7!(8!; zbbT}B8~8~17R*@Rf{&1I;3MT*IAeVaKSI8NljhT5Q0!GP-y#|sQJOPtTvxg-7^F=H zt|?t(IHt;6Mt(4$S1ob+^c&qmm}kH|%j7x4DoEB-SH)&kPCB2sS}n5=+C~;eo`S$t-u(sxQrrum^=YDa;MSyW`vS$$=R6Uj7m;phI6hc zoc32V@Azp>OVCJ>txi%ysuudyP>O z%1lazeL%KB%sYOlYZmhk_0J-DV!b82LvtCyM7{!}w;Dx>B7PPps`z)+PzM(sso{PerwL+y`jjJdJ|9sWqD|=GoD}cI4?vPf zNc;j4FA05IJdTq4>{T^h1dGMEaD#eiDMf9Zb~`Bf1)QX6 z#B5&6i<9HVP8wLBpo%^z&sBC2=TpSFkjnT1uD&m#<}DS=87|P|rc^mX7pGf9HkoNm zp7MWTOqOAs!CeIuQoWzfsW-~e;}A93J|=K#xBVHy?a$KE->-!(q3LvwVP8t&L4FDG3^Ngog%?JG#zAHJIB)2nd_pI+21$%ewJd@)cZDUNXz-urBZ`t!vR97V~i zZx`n|dOX*Hz57QsmP&Dg$^=UY8veXBo0zJZhG zGvEe%7STRd?83`=%!m+R<78?q^eQ!GQSuZ%kka`0;K-@GW+TYQH?Ck_os0Nlht@rTs2 z5-O!OZaOMjO9u*0-3%J`RlKz3R+vFEU8k$&jU{wee0nEXJUm_mwuLJLGIv6_Y4Bx9(D zt)d$}UKM$ytI@+vGaO5UWHc(kVf1>nY_aTTwK8^;W@5)ZGIl&6W5vE7J*J;BRvKp< zV~r;rV~sP8u@A~u#`!i)t}h^B&nA&i|1kLmK4d|mOAs&TH^HGW(x(?w`ok!R;J@7@V)m*_laMD$V z3Pk)kmwa-UNUnBEG2X3{kF}x>6*Om`&VxrL^TAp2A9%v$^Csza*VEL?Ct4qT?l;r= z{MXX|eX8*PQ~7yx<4kkpmKpnF%SroV%Z&Z8<)m}u)*0u>ttXu$x6U|6o;+XcjP=R9|% z=S5k*kT}xC=k9&z?xDNWN4cRdP$cN2xkUu`DjrX=S_{P}vM;8{o|`~XA7>){$S&5O zAe|bE-bf1b_pUX+*HWB3L zk%+1CxGi}rnX#RXv7I+XlWoJMZIFlAY=i0cRi`DBm1QYh-MQ)N5*Jb@-bO~PQ0env zmu&SNRJ#{(Da$Mm(gP|xNi@1vx|ZCGJ2 zbU)*dAzmc$pCDc=@n0ccB5|h%qooorLA*@j>k%)Pcqif&67NHNw!~wI&v8m3NrX!h z6GXU~I374kT1sVomfsnAfb6~B=WL-(+RhL8R>hhCs_N1P&Kk#lke1x5W=QxdB~(b4 zd`Rq8bCMrMfYyG5KBBuwd_-p+4+e8SN1=?tA^U6Gd*njZW$9{mP5LZXijdPbG@!DH z&uKC~1YCYs=pWOU6Woa>Fd>gGCgk&=4#>b|KT0m(UUL)e_T8b!_~SFbBlLCB^q+{z zs~Ym>g}%Wb%=`2}{v7wEDs62&K2Ok>f2+?^WFaUv5tKL)lqSA|bsTIeZW1}FNEQRSVQN?G!_hYdp=RVzWijqIs5G{wrZGSzWy!J!p%WC_QOOX<|>?IS1Mw zo}_ybpTYX)(*2r%vmoFq2)GLZd7Ax9It056&3;y#DbdiYE;NO`gK4wNMK=%KaL%C3 zOQKo%%sx02aAbGR0i)^^(`N*II_EU)@6(Bt!>14R1RSc*Vex3EO_t%bNRAfvyqgZ_ zHQ&wAqC;rWk=5c=msxF?VxYXbGhq5m`=1dnudP%MQ8)UWH6HAitEpR_Bgb_5oT~ji z<($7rinv(hnv96c=aM2|Lh;y(P;2v*FT~%6`5NQ%l;9dg@)6&wFn_IBi01VA=^x1_3enl- zu}@eTx0vD+FA$OBlMvJX0Sy#d8X^8e!h84#;YErR2Tl85=s7B$_K&!^!9af1ZeN}+ z|HeFZA+MqW9vKy8`DO)uo?CshC=SdjPW*r)(X0}Y-?CrgFf*%^BRnD;8hB;v%P;B) z7o zZRs2{XPYz0v#+1-*;SR39Q%eD96RHb!f$V!!EfPJORhCv;rMlp@XGc0{sg|C5O?(G ztx%kz>v8nC-ZBN!4$SduA)N^#Z(R;wcsD>N^7iBVFygknnwjR~P8jCrlu!KsL|&en zy?;vg9w;Wxr@i@4c~7F*FQ-3u(_uZzFQBx4;CbKY;6-r(FTIiYv7STxBA1{gX5w9% zCnSUB44$sijK2{h-;rgMIHpL@f|%FBlHp=4+(ypQ)Tk=+8@w*fGcC=se@5M&*^glo zEuv~(!3BYlyMi+8|G^8}s#;uUy&~@9`1R1wDUZ0;R8x>)=%H8ByA7271tmT!mSkm_ z0!?nPnX|Hfjlk;^tNC*b{tVy-z;%E}^y^RHRKFtcw}`{AJJmyRI(6L24jN}T%n+9u zdO`M>R-W6{3*Yc1AC&hBhsC`@k~Y*M@r<7v$BnP1-BY;clAJnisS_rWSyg;&T~bbc5a;yPpOmge?p!`sX;L$gJKJ-7A$n}5=E|c#J;-& zCx>0JaT0Q!ocIPMb~AScdXm@=bEKi&-|qBr6lUF>Jqy|<&yUJZcz)XA5a*{a%FkZp zIcf_Nt+ave28hl>f2UZgi(xs2px{c6t_%PvDyi~e_Zh!FoEc@Rm zKi$dF5>KF*AM9UK{9kJ%o<}nD8{QOO7Asm2R1r% zta@cIuPV=@7l=>a=z5!J{~poHVji7q?X7#=G!TD>hS$41a$j9)8U<;5{;Q?=s+RDj zo9g7d*xcS%A$SRWe!9e`FG=64PNkq!d=6*eh!l5Q9AkNO)-kB2FVOMHWMVNE>Cr=f zpo+y+m!-&Yq)3<;lP=GlnoU|ZIZ1Mt({k-LvX_Id{ixM*)Jau1=*Ev~SCQDQLd;EK z3#N(@m#%gjmmH=8AC{dgBYXSI(0}lnlbpoi-<&kvPf z#lcim6gp0Y(gi}dUkSZWa})5RH_xi{;&2{1D}>7d`cA~<=-@AW|M!p6;s7@Y5bqpM zrlP~OyP`>ZED?z&GuW_j})UtPI7nn=d%k@fYp%jmDVvS}=y8cRgi zk3`2(iEzBSvSX}29*b;?j(6Gnqa*A4SFaAQjI3O>ykSLsblIAQ`O_;K8%f26qiIHG zG^OTzzonzGnf~2TIH%G7x4EN*lKls|CJ}~F{Huk75Qbrhb3(x|u6qtb40|P;u$Xpd z3lRMNpPpFPI68_7hEv##%7er4k>vV$`%ibdnA>xqGNffdg~7fmGX#QJ%SiG+P%UgcIh5j!876^>Km zP@*v&8yp!%Wc|F(R3e&+?3+h^oTN1GW)M|TpIJ$mbTX@_aOPyGk4eOSY zJX<}-yc=Ls=jodi`AsT1Z#=IKhu6wwtLs(+e_Mo{J8v$o%P#;ph|iy5(3_8{#6|{_ zJWOzEdfPx=cPFfC7T;T&zooksQD{T(FivFiH^uG#>^?#{qvC5$Cr%ge*M%$SgC45= z0`a*VoJ;2>_84A){bc|c!=RU2n|?m z%rji@LyJ;>&d~2voF0ffQ;Huf*WaBkD0eANKWs!i2(P=o?{dMd?qjL}zja@yl!BK3 z%RCp<#Gp2PSs!;5@W?-dO1XZRE5{}yorD*aUQaz9ynHNzg{tbix|q~V)>l044P zA0W7r;Rc4M2gv3_3~vZ1PSiX=rM=1U9forY2(}l@GYsfvILe$089rD*Eq%FwTJ$=n zs)fW~#V}sjT4=zvh2#}a6jF`9D5QS>GsEJbBj|z!LDq-i*+J^xj|cybn%p0}Dd>l% z5U+ybB7nOTYLOrADI$(&-MRU`z;5ff6rwhw4k~>_#F3)~CuxPLHB6;g@)VYA!8w|!RZ1~xayHxq6Sx##r)*N35P`cu zL+XWDv<@GDdzd=kPt;zxHzzH|=eYo@i-_6}4+_arqT-UejVT*#puk?0tn;8scKEB> zjnLHgAPj1RFGSpcm0AShkai=&gWBhjf0K3#!mn#zM$ST=WU3f0)n9_$M_cq85$@7S zKFatI!^1h8&oI26;T;U`XZU1BMuF#bHyZ18#{a03R_`%X9jlSQ*g+aDb$lNEVz;9e zIblaT!b1#iXZXD13<=XRZ!ljq2<|Xq2oEy+oI!TD!=N(nMSSQwrztg7IVabvK*UK_8g>2^;h2+JanyMn@hchL%BhDE%Y&&aTz=ID9j>4nggxjFK^S(gL;kp%WUfM}!8`8rRpCWG z(DH7eC^qXYoJDH$eur>n-oN5(M0pKp&LeoIe>KZos|4V1(Mty5Yb=BN*Wmu0&gr0U zdc#GE0{UTEn@IMub4quhjaitKo`Jtp%spS}3=vy{Kb*u9+u3W>^MKFdD&w@uK z^-pR&Qa_W_6KVsFjNeG=8Fd53$ozSNdJfa_V40+Tq&8!0X`U~rU#o36au3eW>KTB~ z3d(w4?Lq2lN#$#ONPSLH17SU1ghg z3?rF0BqY0V_9=r;3(C4vy922!B=s%rKBTS>Wos{k2PE}8)?NnBN$OuY?QKc@QhNv~ z*W$Ehk7BHB%utVGgo+}8<(W>{Q;@_a;Ok|D~DPP|C*r!xTXJPpjV~S)*>}mP?qWFgQc)oQa+}ZSEb8rRF*Nyw%*BK)tyfwpI(ty^fvAayTj}8>u>YR8kirwF2Ie)YVAUL#Rej_aU_s z&XLqNkXi-RwZdjEIb5(BJ}s%29ev7bs9T!#*41!*jqtN?2Y#ln26wHXUO=h=N+tC& zQl|oNzAKB@7M$)_4_iek)>~NLdN?Yn|3qp7JSr)tu~Rt>-jP%RQX3((Oi;bXu+j+U zNNNzNO>n)Wjw00rKa|uZNHv4CJgapJd}?{ReMzMSzPViJ`H#l=%2s$+rhU_xP_{vN zUAFCQa7~?%{0^>?+u#c_-=7MuaJ0d_lJXZ`@7N9lE3&QafCp9xUH%>0&;h@Z)O$$n zgvxqB1us3R8VlUIid7G z@hU;xYu=>v!r@ivv2vSo7QD1dX#J#luhIuUTb;F1Kis@J+lGF4b9K7RN0fdzYfV-% z0=;Xpk`WkKBl{M0iNH;gQmviJ0K6or71rZQ6!IDb)rQnwXqMFZC^-m+C3OW-`{2Qb zY<)3!T2Szy^^6jO6>A0cnB~Hi%T`G}VZDH(<>s|n&EoQRN;qmLY3jSmv(~H1NQU~Y z^($pGL;cx$M@db}H#RBXfl2wsC*?Z=FRjh?`vs79YPR1$4$Y@#`~4^!J~i9#6Y#L4 z);cd&J^^n_svW6M!h&^KpZFB)S(o*R3*nk|S)ag}XI<7OE(T?N)`FjgQb9r3^^Edq zsFzd%sn5VQk{U|wN!`TMIglji`OX_J{$zKMq zN$THSv$2%o7U6aO;d)280;;zNYL@#QNVhP6VxuGu7eIq?RDdx6JBW+RBQ2say|T3Qu~?utE4Vv$|-fZpQ(2?3u=7{QSVEt zn<eC)Ed_V5i7ens-e7DtuZ}bMh`zAA;}h%;tLt9?n@yJp|tn6#RA; zQI+#^(?W7>bE&@&soQeW9)YjOw0r%(&>n$(+p=k2gVAl$vq~qFufZ#m(%zJ5|Hx^y z7d(ZI{BgDTLAZc>w8>C~WjXwnEKj%wr{+!NG&5&=p4Y3wZpIhVl@i>wP-;}0nGRR7lw*L(8pjUoKH zdagp{JGqu|h1LyD*gxwDwHE|_VAf70PvV!)dO>Z3J7>MDI^l^~Z{XgUa$TvEc;8i9 zA>_SJy+Jw6`$zQ_<*4^>>VsU`-MHRRv{v}C*RPepR^Kj!-M$`#y@UsSEKh=rOoBaEI;a7dRcqlt2OYtV(S^rtEdhLe7N@ z??aek9R|2vhq+xTF6S_}E(LW3wT=OnSp~#?nmlIkd?f^LFm9m$>}r;EzRA%WK{$^CiyvG{dJ9wRpKn{8i?1&0E|DkD>fJ z^9Jsb<=VXBM&z$RcqP18+=!glijSJ(@SnvPNwm_Ei_K#iNj?T^N-jmoyGy=i-k|-Y zt zrS;e&)S_3oMQ^hHZ*sd{k(wt;dq}2;dX4hl0u%|KV!VOj+dM|zW=lS%{kgQ=dP+0O zx~ylpE~@2BtDbwr2T_b9uPY5@G3!NbPuVE)$*W(~p0y5GWS?W0_i))2)?3=eW%Zc% zS?fBhM7;#@r<7~UZne(Us26(GTgvXTC`x?AdY5Z?SG%w5QHwn78&(XpdKTehWqm+0 zKeU{%4t~QY?7u^}mGL(CGx%XAT!hiMi#a`zC`->i6g`>i?k!9rcdwjvmKr zj`tlNBWNr%s*SbAcB9is8J{*<&1=mcn13?!taVnS)n{E`ecpP|ddm8-MJK$oaJ}FK z3$33Ah4d{o2s`Mo>JY=*8NR_#H3;r7Xd`%#;hW6KH)*r9!X&(%;Y$o>TeR8RXVpxR zta474*HH@xLIeH41#bMy!@qp|^Fok6_uZr64i{II*CC8DZtCBsdl~uX~MS`nh~m~vy(qnqjT^Ugt)55HhFOjJ%R zZ^4-eakqsvTM)(Cys#Ic3N=`d1%p_s7xp2<^*^0-!w{4sKZX$ZeNcg%ahQ#qg9uev z4s#GcA8YpFXsbj{9oFWBBUrNqhY_kc&gLWMMcb4C@ez$1j6sC8?+WCO4#-qk_#w*6(jDWeoe9zRa&6a*N z``fSLwMzb=t|PNL?oiUVmb1M5Gw@O~@c!AC%&Z8SAiNWO5jKog@3ua|H=qHq;$z+zZITnvHXinIpjI@r7j-?nAH@b4r&he25 zh$|{~B85ql%G(+q8HgjZr@d`!DmA(*dhS>>nG$+IcPbXo)v>*&73A%%Gh!nH_JJhi z+$@6hB{C@kJNk#BkrcEXj6_FSAlrh;rPRt>GD$RWDusgWV{y8ilT0;7SWlfiZT~V?n_fwaRT?>5? zagC_WMw1Uf>qsmW3&&&UM>EcqZgP_ykE2zvlw|Fe=twjXi$HUX8R5kEId#yNK=(?f z&<_WrDWG!0v5_Q%2L>P!9k$PlLL?C-lT7MA!JEYD8;cE48T{-^qB2Y|(w7<^6(l2l zqjqeBe4`C(K4&>fi_2q>L@Qvjcy!saM+eYF681Py!CV{{l8Ek2l6yzH(CZk*9(UI`5(7eM=#<(|#O<9c|rR ztvj~&wd~pj97neA=<4h2?&#RDtE;7%*-bmzJNlY-Y~S40+SJAAn|E|?7ipa>P2Ia% zyLy>u+=Q7JBcWX_jm?dl+FF>=vb||Xb1T+PMBe~L4{kh#5soF~dIQ2BO(L2hhzmDN z*{N_GGI_d~Buu)gU`Rq3wr^U$k^D5~KrA^LPDS>ii*O7=@9bklxTwIJ6XC%Yb}Nyb zrZO^V24QW{FuHbHP*6F7g26tLgcuGl(rYtQP2rJ9G|pKiD)ULI35V~XC|aWFbU{st zMIw~8+hfV7h(?nJ74w_z10!5smXbwg8H{z0X2rTkCkY|hH%wt}6k~Z`I6|QX`!|*h z_s6L>xQ&v8K6^Ae(u@(s9)yy4+tEl~f%D4t7VbfgcwAeSlJ#X7>Cn$|8A6I> zXp+yAlv{|HnK(&cGA&Jn2XNq#dtfoxH0bN6nY1sNh_ntIL~1-0O$wjGfFp+<UqR9CMONyJ`&iRu!pxt52iXfEM;f2*vKFS*myK0`gg_zspO1lxy(t%nK5C8 zk}_$z%&eKFb7v?+B=pJ9lZZy5F^cl>XgEP$j@BVFwvL=mJm&`YXjzQ#yJYQM=5ShGQ$*>RDKE< zy_4rN=uX6N)=9+Eo=q;7MYoETNtUtMwrTYD?c;=`aF^{Ig$Uami^c~8iQbYD!450L z`7}v$5_;NLGX3nL|3M*>x>c4a+rAwqQd-@d5$#Vea8UGIprz5iggp{FpJ#f$3QWbY zRVC46+xuhDCNT|@wvj0eG@~q3HZVLoN;8RgaM$rP#M)*s)|WarPCYS6=|L(`uw>VV z`_WOR#;HvSgjii?BoP};$(cDxHTU(CBS@vhFv|Ey#za|8k}nx|*_&{9HYO6`ap*(k z61W)NA^R1>ZX%lPZlb2T0Nnwn)ynW_dKDcd-)c_J6A9`_#BuaaNr2W#%b)1MXoM6% zxML)LGQxRib;RG#?SQC*%k&!N5gSem#lf(vbq0(fJ@mzxos`H|WR2Qx})79BPmP3^PMS!mH2Nq0#&DIF6h3OUlTlX%+e!+{eXPG(n=iOdL>`wiMj zjN-(Y=!_=Li;=R;<2bd)B8@5R=>9PZl@YP($@QFQcE3S2up?x1BrtRw#8yZ5;$upE z@*5)*T7ju3p(`03?vIam#ZvKTRxr(OjtcEibb2BVzP+)* zu|)Vp$-|@Jk@4vX=&l1}kE%7LQ8-v&OyKtUB!{MX_>o!FC`Y3k9!{hulkve46_w}Xr#gee@gLiEk z`uqBpNh?GXqDpFS7^BbtS0vONKpBi~=0rDM ztY^ta;r&_84vZt=j14l%${L8*jsZ42C>G*q-pGD*$q4lTg>CG{5o|H-NaMs!H*Y)c zZ+Xi+kmCV3KW{@_d4ZSRn5N?e??y37<@jS)Vth+9wVNZHobi&|qT|pwK)WN}jCRr1 z4~6(itvfGFyYnXAkG76r+`~mU@LbOOuT7``>b*H0#!$0`*6^4DnOfLgSa3^pYSfor z#5H9O26$s5;(R;D(#(ERkW!P3JgPp)X*0np?QtF95!^InJTSXo7rwAB79T)wz@>Ed zTThuXvcl-<(|i?K)3@ouE5*D5>-cCxuoB{wsbyqrn7RdRN*2jdypM~H45s!;r@|^X z+ldx*XWV?87p3(w&8;}yi%o<;xg%)?#N8hTC|q=lt>c)qbSs_Qw1=_O_Sgsri6&l( zQtS~PpE2?F^j>_seL$p(MLRn62ydag?2MZZ(>J7W+C{7%7f!&@F>Xip1|# z##_V8gtU$(J~GPkELxXES70k~Z74?!p=gHTaEjflIlcMK2_iJqaouGf$nH{eJ)+AN ztDxElpEHs44qUik_yh4pv!r}-xs;1#B(G~$J1CTmhh!FX_pfQ0cH|Bw`dT*b`{` zIVq8c&Wbt^&>qFP3s>7=nj+=-3U*Zo4WgVaMlBt4 za8jOjHITzblT()wmwj^jUL_qCF^o?MZOFlGtlefGK*@F3t>;k$r;YM(I?y#ov7mTz z!=W{sS8d+Z(%4YbR9Cm6rhZd>OHIS3#`>C7tJbV&T+`T8zjDQzBd}nBSl%u>xM~@` z)-11CE(V`i919Kk+>~QFHdO3^rYM%)7$wu;DJP?hfT%nBLq|B4z)gf~4juiV0h8oJ zI}$C!qq2J@=jCnlmh7f0hmo^`!eMjbZIz5jCy`ijQi=MLN~{#4h&Bk~s0BCr(^TCY zA4{_9WfxevM0PLQC(%w^*X&4i;Nmf}EhGZ9nYvvh9l|Hz_n&|tIRSq_c)PTEx*?Lx z?ALQ>p>0$8ymLk}XX7BaW21D;lFZp%Q}AbJnaVBD9fGJSGF6KQwX<~1!N5u2BH z83YTU*uf=rh%Mnb4xw(``X^?X|EYU(x6&MgSIi)|S_)3yWwZFIT(xjRH8>UzCt42D zm#~u@*pL;)JsPfr>Cj^s!w^oWyZAE&+!L~GC|ahMuo*@>ZZM*WoSjKDB}0XHa9HQ{ zc@zsuFVQj#TC{UCq&meU!Pb;$3vQEfg)kxxbh>OBnKHP>ZH#ieaF(%$ffg;z_82W! zcwvVVi2MMmcCa>){!Tl86zIsO-$rumff0ZeOQAjUs{p4$1o2@QML2@=2&Cv6D^q_; zpdy=th7)Ndtz&VBz1JDOx3JjbHNMlKS z(ziCDVF2i_67{3MO3W?(DzVIcuoi0@Mu@=;Ij6uDl*TzMWWB7|Til_&QkQK}fJ=(YDUC6u4WE zOQ~4v;x5*Gg!{tgyfM~uTK*GCHc4-Yqa<5v{)r@W>UH*`ybb-_y9u&UAT=!)%<5

iat3ibHIG+>lzrI((g5p zWR0o!lv!kfy<9)*Fh8rO;MQ>Y5m^S+q!f-xjceF1geHnRk@W%RK*qPIHROGeAI4Is z&QYRDrnVzJGL-o>ApWwy)X~o#F#-eJ|Kp%IC|zl9no>ry9CbFgFm1E7I5zgO&4*D& zXcoqCUJ2a z;ZjoE3n{ib)uXH*#umm|a#VWx(i3Ps)f(&39;64w6zNI6Q6BS2^erlZVoC?>z!B7i zX;b?X+}+6EjJ2!*r9_Mf5&e?6ZSrlFmPzXZ72VuMG47^~sMB(PX(hsX5Z1yYpRCx$ z`VX=-YFU>gmn%FI%BIH9Y);5e<>ZC3J(xcPr=cazf{y`FXG0Y%pkJiOKfomq@Hhi^ zHflruTI{`6Oe0T$BBJQq=4lU=QaO29Gb)#sPZZTN`W<{i>Y_<)Uakc`iKKY!| zKEp53KzR~0Ug4NhV4Vd1K|6AL)eeU+XpZwBSTGoJd`0WdS^7vijmucv{My0Bh`{#;>PdpYn zDiy`QP&HK3DD*E@J>`0(Qtm;ZdK@U>DK{&%a(|D*(?a0Ew@Wpgn&Dfi8U6;n68sH_tS1D4qPSS827(n1 z#vAnz3K3Y3k_A|-;xBNy@M%>zEK8^BK04h6qU=t+h%o*S%ITL!bh;oUo9A(&fWXo^ zd908`usu#x&Z!#Z2G-zml_Q5#F4v3-4^~{m%GAg<*E=hrLN?3rw{ThuWyFTl15HKh zl=H8jphO2tbRgzc4NKU6y|Yrc{9bAVHHsTksc?a9EZ&A#BlSdiIjSxV%XG0QVVSE^ z_qXEH-(Jo+S~15?e0QVL4!3AF=}Qgh#rN6x4r9Yu1Amkqbc$*q@Ev`SaEoyN(QlfC{-aN!le$cYt3-~*Yp>nkXy+H9#C?3}3U4j$NJkb0T4kXKw zFu4aO9Gp~W75XPis5R7$0Vp=zxVVkzO@=aE@Kag|d=UaTkp7MjiF za^;(b%Vk+4PJM4mpENm-zu1k2E|xguT~Gh#_eySH16tX?-a<1v$;YYh0$45y*JJ~`Y(wtA2tpsZ~~ zwb37D#pr+SNDwW#bEbpvN>7K>alpvzN` z`LsnInb3(seol_cdY1wYaf1~ceC@bM0e|K*-pX&?U0GSTYi4DV?lugs+H*%C`_9qZpS8Xx0B zqdmz)WX~`efw5%PK6~u`p*_2z@n|@cysLaJ%#Hm=`r{Y%a-RFm1mZZ2_f1QE@@v)` zmtvcHa(yRX?++|IJS*Q_RA& z;B^5nmphg{ez%oBk^7C)8qxC2w7#{&QsI0eV*=od41Zn zTW5El{PJ(wx0WrRmtAK%H`VrI=kqtuj=pC6E8BYN#gn^xZUp-4zqFhdIqm1_8bZZ*#A0(WIxl%Yx%zM z_T}fzlfNxwo+0$S?nAPi)k^7 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 6d1fb7f800233408f44bf254322f9966d07be3e7..cdf8259fe657fe41e8cc54ab0155b6efb514f9b4 100644 GIT binary patch literal 28056 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

vN&*T9b4(|i9~ErBY1sNPPa%jUAk2wnD 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 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));