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' || $('
").append( jQuery.parseHTML( responseText ) ).find( selector ) :
-
- // Otherwise use the full result
- responseText );
-
- }).complete( callback && function( jqXHR, status ) {
- self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
- });
- }
-
- return this;
- };
-
- })();
- (function(){
-// Install script dataType
- jQuery.ajaxSetup({
- accepts: {
- script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
- },
- contents: {
- script: /(?:java|ecma)script/
- },
- converters: {
- "text script": function( text ) {
- jQuery.globalEval( text );
- return text;
- }
- }
- });
-
-// Handle cache's special case and global
- jQuery.ajaxPrefilter( "script", function( s ) {
- if ( s.cache === undefined ) {
- s.cache = false;
- }
- if ( s.crossDomain ) {
- s.type = "GET";
- s.global = false;
- }
- });
-
-// Bind script tag hack transport
- jQuery.ajaxTransport( "script", function(s) {
-
- // This transport only deals with cross domain requests
- if ( s.crossDomain ) {
-
- var script,
- head = document.head || jQuery("head")[0] || document.documentElement;
-
- return {
-
- send: function( _, callback ) {
-
- script = document.createElement("script");
-
- script.async = true;
-
- if ( s.scriptCharset ) {
- script.charset = s.scriptCharset;
- }
-
- script.src = s.url;
-
- // Attach handlers for all browsers
- script.onload = script.onreadystatechange = function( _, isAbort ) {
-
- if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
-
- // Handle memory leak in IE
- script.onload = script.onreadystatechange = null;
-
- // Remove the script
- if ( script.parentNode ) {
- script.parentNode.removeChild( script );
- }
-
- // Dereference the script
- script = null;
-
- // Callback if not abort
- if ( !isAbort ) {
- callback( 200, "success" );
- }
- }
- };
-
- // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
- // Use native DOM manipulation to avoid our domManip AJAX trickery
- head.insertBefore( script, head.firstChild );
- },
-
- abort: function() {
- if ( script ) {
- script.onload( undefined, true );
- }
- }
- };
- }
- });
- })();
- (function(){
- var support = jQuery.support;
-// Create the request object
-// (This is still attached to ajaxSettings for backward compatibility)
- jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
- // Support: IE6+
- function() {
-
- // XHR cannot access local files, always use ActiveX for that case
- return !this.isLocal &&
-
- // Support: IE7-8
- // oldIE XHR does not support non-RFC2616 methods (#13240)
- // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
- // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
- // Although this check for six methods instead of eight
- // since IE also does not support "trace" and "connect"
- /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
-
- createStandardXHR() || createActiveXHR();
- } :
- // For all other browsers, use the standard XMLHttpRequest object
- createStandardXHR;
-
- var xhrId = 0,
- xhrCallbacks = {},
- xhrSupported = jQuery.ajaxSettings.xhr();
-
-// Support: IE<10
-// Open requests must be manually aborted on unload (#5280)
- if ( window.ActiveXObject ) {
- jQuery( window ).on( "unload", function() {
- for ( var key in xhrCallbacks ) {
- xhrCallbacks[ key ]( undefined, true );
- }
- });
- }
-
-// Determine support properties
- support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
- xhrSupported = support.ajax = !!xhrSupported;
-
-// Create transport if the browser can provide an xhr
- if ( xhrSupported ) {
-
- jQuery.ajaxTransport(function( options ) {
- // Cross domain only allowed if supported through XMLHttpRequest
- if ( !options.crossDomain || support.cors ) {
-
- var callback;
-
- return {
- send: function( headers, complete ) {
- var i,
- xhr = options.xhr(),
- id = ++xhrId;
-
- // Open the socket
- xhr.open( options.type, options.url, options.async, options.username, options.password );
-
- // Apply custom fields if provided
- if ( options.xhrFields ) {
- for ( i in options.xhrFields ) {
- xhr[ i ] = options.xhrFields[ i ];
- }
- }
-
- // Override mime type if needed
- if ( options.mimeType && xhr.overrideMimeType ) {
- xhr.overrideMimeType( options.mimeType );
- }
-
- // X-Requested-With header
- // For cross-domain requests, seeing as conditions for a preflight are
- // akin to a jigsaw puzzle, we simply never set it to be sure.
- // (it can always be set on a per-request basis or even using ajaxSetup)
- // For same-domain requests, won't change header if already provided.
- if ( !options.crossDomain && !headers["X-Requested-With"] ) {
- headers["X-Requested-With"] = "XMLHttpRequest";
- }
-
- // Set headers
- for ( i in headers ) {
- // Support: IE<9
- // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
- // request header to a null-value.
- //
- // To keep consistent with other XHR implementations, cast the value
- // to string and ignore `undefined`.
- if ( headers[ i ] !== undefined ) {
- xhr.setRequestHeader( i, headers[ i ] + "" );
- }
- }
-
- // Do send the request
- // This may raise an exception which is actually
- // handled in jQuery.ajax (so no try/catch here)
- xhr.send( ( options.hasContent && options.data ) || null );
-
- // Listener
- callback = function( _, isAbort ) {
- var status, statusText, responses;
-
- // Was never called and is aborted or complete
- if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
- // Clean up
- delete xhrCallbacks[ id ];
- callback = undefined;
- xhr.onreadystatechange = jQuery.noop;
-
- // Abort manually if needed
- if ( isAbort ) {
- if ( xhr.readyState !== 4 ) {
- xhr.abort();
- }
- } else {
- responses = {};
- status = xhr.status;
-
- // Support: IE<10
- // Accessing binary-data responseText throws an exception
- // (#11426)
- if ( typeof xhr.responseText === "string" ) {
- responses.text = xhr.responseText;
- }
-
- // Firefox throws an exception when accessing
- // statusText for faulty cross-domain requests
- try {
- statusText = xhr.statusText;
- } catch( e ) {
- // We normalize with Webkit giving an empty statusText
- statusText = "";
- }
-
- // Filter status for non standard behaviors
-
- // If the request is local and we have data: assume a success
- // (success with no data won't get notified, that's the best we
- // can do given current implementations)
- if ( !status && options.isLocal && !options.crossDomain ) {
- status = responses.text ? 200 : 404;
- // IE - #1450: sometimes returns 1223 when it should be 204
- } else if ( status === 1223 ) {
- status = 204;
- }
- }
- }
-
- // Call complete if needed
- if ( responses ) {
- complete( status, statusText, responses, xhr.getAllResponseHeaders() );
- }
- };
-
- if ( !options.async ) {
- // if we're in sync mode we fire the callback
- callback();
- } else if ( xhr.readyState === 4 ) {
- // (IE6 & IE7) if it's in cache and has been
- // retrieved directly we need to fire the callback
- setTimeout( callback );
- } else {
- // Add to the list of active xhr callbacks
- xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
- }
- },
-
- abort: function() {
- if ( callback ) {
- callback( undefined, true );
- }
- }
- };
- }
- });
- }
-
-// Functions to create xhrs
- function createStandardXHR() {
- try {
- return new window.XMLHttpRequest();
- } catch( e ) {}
- }
-
- function createActiveXHR() {
- try {
- return new window.ActiveXObject( "Microsoft.XMLHTTP" );
- } catch( e ) {}
- }
- })();
- webshims.isReady('jajax', true);
-})();
diff --git a/public/webshims/shims/jme/controls.css b/public/webshims/shims/jme/controls.css
index e7a02e5a..10ece81e 100644
--- a/public/webshims/shims/jme/controls.css
+++ b/public/webshims/shims/jme/controls.css
@@ -1,5 +1,5 @@
/* thx to http://icomoon.io */
-.mediaplayer[data-state="waiting"] > .jme-media-overlay, .mediaplayer .fullscreen, .mediaplayer .fullscreen.state-exitfullscreen, .mediaplayer .mediaconfigmenu, .mediaplayer.initial-state > .jme-media-overlay, .mediaplayer button.play-pause, .mediaplayer button.play-pause.state-playing, .mediaplayer .mute-unmute, .mediaplayer[data-volume="medium"] .mute-unmute, .mediaplayer[data-volume="low"] .mute-unmute, .mediaplayer[data-volume="no"] .mute-unmute, .mediaplayer .state-unmute.mute-unmute, .mediaplayer .captions, .mediaplayer .subtitle-menu button[aria-checked="true"], .mediaplayer .subtitle-menu button, .mediaplayer .playlist-next, .mediaplayer .playlist-prev, .mediaplayer .chapters, .mediaplayer.ended-state > .jme-media-overlay {
+.mediaplayer[data-state="waiting"] > div.jme-media-overlay, .mediaplayer .fullscreen, .mediaplayer .fullscreen.state-exitfullscreen, .mediaplayer .mediaconfigmenu, .mediaplayer.initial-state > .jme-media-overlay, .mediaplayer button.play-pause, .mediaplayer button.play-pause.state-playing, .mediaplayer .mute-unmute, .mediaplayer[data-volume="medium"] .mute-unmute, .mediaplayer[data-volume="low"] .mute-unmute, .mediaplayer[data-volume="no"] .mute-unmute, .mediaplayer .state-unmute.mute-unmute, .mediaplayer .captions, .mediaplayer .subtitle-menu button[aria-checked="true"], .mediaplayer .subtitle-menu button, .mediaplayer .playlist-next, .mediaplayer .playlist-prev, .mediaplayer .chapters, .mediaplayer.ended-state > .jme-media-overlay {
font-family: 'jme';
speak: none;
font-style: normal;
@@ -13,7 +13,7 @@
-moz-osx-font-smoothing: grayscale;
}
-.mediaplayer[data-state="waiting"] > .jme-media-overlay:before {
+.mediaplayer[data-state="waiting"] > div.jme-media-overlay:before {
content: "\e612";
}
@@ -300,10 +300,10 @@
.mediaplayer[data-state="waiting"] {
cursor: default;
}
-.mediaplayer[data-state="waiting"] > .jme-media-overlay {
+.mediaplayer[data-state="waiting"] > div.jme-media-overlay {
background-position: 4px 4px;
}
-.mediaplayer[data-state="waiting"] > .jme-media-overlay:before {
+.mediaplayer[data-state="waiting"] > div.jme-media-overlay:before {
-webkit-animation-name: jmespin;
-webkit-animation-iteration-count: infinite;
-webkit-animation-duration: 1100ms;
diff --git a/public/webshims/shims/jme/controls.scss b/public/webshims/shims/jme/controls.scss
index e9744c7d..6cf683af 100644
--- a/public/webshims/shims/jme/controls.scss
+++ b/public/webshims/shims/jme/controls.scss
@@ -4,6 +4,7 @@
font-family: 'jme';
src: url('jme.eot');
}
+
@font-face {
font-family: 'jme';
src: url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AAA5sAAoAAAAADiQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAACq0AAAqt29xKpU9TLzIAAAukAAAAYAAAAGAIIvzPY21hcAAADAQAAABMAAAATBpVzHBnYXNwAAAMUAAAAAgAAAAIAAAAEGhlYWQAAAxYAAAANgAAADb/1ko1aGhlYQAADJAAAAAkAAAAJAQCAh9obXR4AAAMtAAAAHgAAAB4NSAB521heHAAAA0sAAAABgAAAAYAHlAAbmFtZQAADTQAAAEVAAABFQcRlmFwb3N0AAAOTAAAACAAAAAgAAMAAAEABAQAAQEBBGptZQABAgABADr4HAL4GwP4GAQeCgAZU/+Lix4KABlT/4uLDAeLa/i0+HQFHQAAAQAPHQAAAQURHQAAAAkdAAAKpBIAHwEBBAcJCw4TGB0iJywxNjtARUpPVFleY2htcnd8gYaLkGptZWptZXUwdTF1MjB1RTYwMHVFNjAxdUU2MDJ1RTYwM3VFNjA0dUU2MDV1RTYwNnVFNjA3dUU2MDh1RTYwOXVFNjBBdUU2MEJ1RTYwQ3VFNjBEdUU2MEV1RTYwRnVFNjEwdUU2MTF1RTYxMnVFNjEzdUU2MTR1RTYxNXVFNjE2dUU2MTd1RTYxOHVFNjE5AAACAYkAHAAeAgABAAQABwAKAA0BJAGCAZ8BuwHiAgoCngLwA1EDvgPMA+oEsAU6BZEFuQYFBoAHcwe1B/sIaQikCMgJJQlf/JQO/JQO/JQO+5QO+IL4ABX7f7sFiYuJi4mLCPt/WwWDioWEi4MIi/uyBYuDkYWTiQj3f1wFjYqNi42MCPd/ugWTjZGRi5MIi/eyBYuThZKDjAj7o/twFXtncnlpi1KLZbqLz4vQsbnEi6yLpXqbaYyIi4iKiIqIiYiIighvfwWFiISOiJGHlIOVfot2i3xyi2eLZ5pyoIuai5KajZGNj42NjoyOjY+LjokIp38FjoqNiYyIjYeLiImICPd/ixV6Z3J5aYtTi2W6i8+L0LG5w4uti6R6m2mNiIuIioiJiImIiIoIcH8FhIiEjoiRh5SDlX6Ldot9cotni2eZcqCLmouSmo6RjI+NjY+Mjo2Oi4+JCKZ/BY6KjomMiIyHi4iKiAgO+En4KRVduUuoRIv7AosuRmYqCMd0BabU0r/di8CLu3auaAhDQ/dUi4v3VEBABftJ/AkVVotboGiuCNPT+1SLi/tU1tYFuV3LbtKL9wKL6NCw7AhPogVwQkRXOYsIDvgU+DQVi/wUS4uL90T7NPs0i/f09zT7NIv3RAUO9xSrFYv4FMuLi/tE9zT3NIv79Ps09zSL+0QFDvh1+FUVi/tLRdI2NmG14OBE0QVF+7sVNzbRRftLi4v3S9FF4N8FDvd491gVi/tLRdE2N2G13+BF0QX4SPdnFTc20UX7S4uL90vRReDfBQ74lPdEFYvrQpcFiJSHlIeUCLbHR89PYAWCj4KPgo4If9Qri39CBYKIgoeChwhPtkdHtk8Fh4KHgoiCCEJ/iyvVfwWOgo6Cj4MIYE7PR8i2BZOHlIiUiAiXQeuLl9UFlI6UjpOPCMhgz89gyAWPk46UjpQI1ZcF+5R7FWiLbqiLrouuqKiui66LqG6LaItobm5oiwgOi/h0FfcUi4v7FPsUiwX3VOsV99SLi0v71IsF+1QrFfcUi4v7FPsUiwX3VOsV99SLi0v71IsF+1QrFfcUi4v7FPsUiwX3VOsV99SLi0v71IsFDveU+HQV+yGL+wf7B4v7IYv7IfcH+wf3IYv3IYv3B/cHi/chi/ch+wf3B/shiwiL/GQV+weLLuiL9weL9wfo6PcHi/cHi+gui/sHi/sHLi77B4sIS/fUFfdU+wT7VPsEBQ73lPh0Ffshi/sH+weL+yGL+yH3B/sH9yGL9yGL9wf3B4v3IYv3IfsH9wf7IYsIi/xkFfsHiy7oi/cHi/cH6Oj3B4v3B4voLov7B4v7By4u+weLCCv3xBXLi4v7VEuLBfcU91QVy4uL+1RLiwUOyfhdFfgY+338GPt9BQ6i+F0V91aLi/xm+1aLBfek+GYV91aLi/xm+1aLBQ6r+FGeFYWLhY2GkIKUi5uUlLe3o8WLyYvJc8Vft4KUi5uUlJSUm4uUgsBWqEWLQItAbkVWVgiGhoWJhYsINrgVhYuEjoePgZWLmpWUzM2L9UrNgZSLmpWVlJSai5WCtGKhVYtRi1F1VWJihoeFiIWLCDa4FYSLhY6HkIGUi5qVlLO0i81jtIGUi5qVlJSVmouUgcdQiytPUIeGhYiFiwhB9+AVmJiVhot5CIv8MgWLeYGHfpcI+w33DTuLi/dU24v3DfcNBQ73/MsVhYuEjoePgZWLmpWUzM2L9UrNgZSLmpWVlJSai5WCtGKhVYtRi1F1VWJihoeFiIWLCDa4FYSLhY6HkIGUi5qVlLO0i81jtIGUi5qVlJSVmouUgcdQiytPUIeGhYiFiwhB9+AVmJiVhot5CIv8MgWLeYGHfpcI+w33DTuLi/dU24v3DfcNBQ73p/cBFYSLhY6HkIGUi5qVlLO0i81jtIGUi5qVlJSVmouUgcdQiytPUIeGhYiFiwhB9+AVmJiVhot5CIv8MgWLeYGHfpcI+w33DTuLi/dU24v3DfcNBQ73XfhNFZiYlYaLeQiL/DIFi3mBh36XCPsN9w07i4v3VNuL9w33DQUO9134TRWYmJWGi3kIi/wyBYt5gYd+lwj7DfcNO4uL91Tbi/cN9w0F96v7oxWLYWGLVcFVVWGLi7XBwVXBi7W1i8FVwcG1i4thVVUFDvhE9xQVdIt3gnx8CPtr9gWMj4uQi4+Lj4uQio8I92v2BZp8n4Kii7eLr6+Lt4u3Z69fi1+LZ2eLX4uHi4aMhwj7ayAFfJp3lHSLX4tnZ4tfi1+vZ7eLoouflJqaCPdrIAWKh4uGi4eLX69nt4u3i6+vi7eLt2evX4sIDviU93QViqyErX6pfap4pnOic6JvnW2XbJdqkWuKa4pqhG5+bX5xeXR0dXN6cH9ugG2Fa4xsCIxskWuYb5hunXGhdqF2pnqngKiAqoWpjKmMqZGnl6eYpJyfoaCgm6WWppGckJ2NnAiMi4uLjIudi5mai5yLjIuMi4wIi4sFWDYVf3B6c3d3dnhye3CBcYBuhm+Mb4xvkXGWcZd0m3ifeJ98o4GlgaSGp4ymjKaRppakCJajmqKfnZ6eopmklaOUppCliqWKpYajgKKAoXydeZx4mXWUc5R0kHGKcgiLiwWLiouKi4qLe5d9nIqHeYZ6hHsIDvhU+HQV/FSLi/yU+JSLi/hUS8sF+1RLFcuLi/sUS4uL9xQF91T8FBX8FIuL+BSri4v7NPe0i4v3NLCLpnCL+/kFDvh/+CQVQ5U7kTiLOIs7hUOBflWDUItMi0yTUJhV04Hbhd6L3ovbkdOVmMGTxovKi8qDxn7BCPu/+6QVi/dU9zQr+zQrBQ73VMsV99SLi0v71IsFi/eUFffUi4tL+9SLBYv3lBX31IuLS/vUiwUr6xWL+xRri4vra4uLqwWr+5sVi3LLi4trK4uL1Mupi6RLi4ur64uLQgWL+wsVi/s0K4uLq8uLi6tLi4ury4uLq0uLi6sFDov4dBWL/JT4lIuL+JT8lIsF+HT8dBX8VIuL+FT4VIuL/FQFK/gEFfs0+zQr60tL9zT7NPd093RLywUOi/h0FYv8lPiUi4v4lPyUiwX4dPx0FfxUi4v4VPhUi4v8VAUO9930FSL1i/chy4uL+wfiNQX7C/fdFfshi/sH+weL+yGL+yH3B/sH9yGL9yGL9wf3B4v3IYv3IfsH9wf7IYsIi/xUFSGLNeGL9Yv14eH1i/WL4TWLIYshNTUhiwgOy/d0FfcU9xRLi/sU+xT3FPsUy4sF91T3lBVLi/cU+xT7FPsUy4v3FPcUBfuE91QVO/wUu4vb+BQFDviUFPiUFYsMCgAAAAADAgABkAAFAAABTAFmAAAARwFMAWYAAAD1ABkAhAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAEAAAOYZAeD/4P/gAeAAIAAAAAEAAAAAAAAAAAAAACAAAAAAAAIAAAADAAAAFAADAAEAAAAUAAQAOAAAAAoACAACAAIAAQAg5hn//f//AAAAAAAg5gD//f//AAH/4xoEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAQAAAnhtIV8PPPUACwIAAAAAAM9LhLwAAAAAz0uEvAAA/+ACIAHgAAAACAACAAAAAAAAAAEAAAHg/+AAAAIgAAAAAAIgAAEAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAQAAAAIAAAQCAAAAAgAAoAIAAIACAAAfAgAAHwIAAAACAAAAAgAAAAIAAAACAAA+AgAAFwIgAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAABACAAAAAgAAAAIAACACAAAAAgAAAAIAAAACAAAAAABQAAAeAAAAAAAOAK4AAQAAAAAAAQAGAAAAAQAAAAAAAgAOACsAAQAAAAAAAwAGABwAAQAAAAAABAAGADkAAQAAAAAABQAWAAYAAQAAAAAABgADACIAAQAAAAAACgAoAD8AAwABBAkAAQAGAAAAAwABBAkAAgAOACsAAwABBAkAAwAGABwAAwABBAkABAAGADkAAwABBAkABQAWAAYAAwABBAkABgAGACUAAwABBAkACgAoAD8AagBtAGUAVgBlAHIAcwBpAG8AbgAgADEALgAwAGoAbQBlam1lAGoAbQBlAFIAZQBnAHUAbABhAHIAagBtAGUARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('woff'),
@@ -235,7 +236,7 @@ $browser-context: 16; // Default
&[data-state="waiting"] {
cursor: default;
- > .jme-media-overlay {
+ > div.jme-media-overlay {
@extend %icon-spinner;
background-position: 4px 4px;
diff --git a/public/webshims/shims/jme/mediacontrols.js b/public/webshims/shims/jme/mediacontrols.js
index cd4b3663..30573d0e 100644
--- a/public/webshims/shims/jme/mediacontrols.js
+++ b/public/webshims/shims/jme/mediacontrols.js
@@ -52,7 +52,8 @@ webshims.register('mediacontrols', function($, webshims, window){
})();
var ios = /iP(hone|od|ad)/i.test(navigator.platform);
var ios6 = ios && parseInt(((navigator.appVersion).match(/OS (\d+)_\d+/) || ['','8'])[1], 10) < 7;
- var hasYtBug = (!window.Modernizr || !Modernizr.videoautoplay) && (ios || /android/i.test(navigator.userAgent));
+ var modern = window.Modernizr;
+ var hasYtBug = (!modern || !modern.videoautoplay) && (ios || /android/i.test(navigator.userAgent));
var loadLazy = function(){
if(!loadLazy.loaded){
loadLazy.loaded = true;
@@ -173,7 +174,8 @@ webshims.register('mediacontrols', function($, webshims, window){
if(!e){
e.type = 'playing';
}
- if(isInitial && (!isYt || !hasYtBug || e.type == 'playing' || data.media.prop('readyState') > 1)){
+
+ if(isInitial && (!isYt || !hasYtBug || e.type == 'playing' || data.media.prop('readyState') || data.media.prop('networkState'))){
isInitial = false;
data.player.removeClass('initial-state');
}
diff --git a/public/webshims/shims/mediacapture-picker.js b/public/webshims/shims/mediacapture-picker.js
new file mode 100644
index 00000000..4e540b49
--- /dev/null
+++ b/public/webshims/shims/mediacapture-picker.js
@@ -0,0 +1,42 @@
+webshim.register('mediacapture-picker', function($, webshim, window, document, undefined, featureOptions){
+ "use strict";
+
+ function PhotoShooter($dom){
+ this.$dom = $dom;
+ this._createDom();
+ this.requestMedia();
+ }
+
+ PhotoShooter.prototype = {
+ _createDom: function(){
+ this.$dom.html('
' +
+ '
' +
+ '
')
+ ;
+ },
+ requestMedia: function(){
+ var that = this;
+
+
+ navigator.getUserMedia(
+ {video: {minWidth: 200, audio: false}},
+ function(stream){
+ that.stream = stream;
+ $('video', that.$dom).prop('src', URL.createObjectURL(stream));
+ },
+ function(){
+
+ }
+ );
+ $('video', that.$dom).removeClass('ws-usermedia');
+
+ }
+ };
+
+ webshim.mediacapture.showContent = function($fileinput, $button, popover){
+ var stream = new PhotoShooter(popover.contentElement);
+ };
+});
diff --git a/public/webshims/shims/mediacapture.js b/public/webshims/shims/mediacapture.js
new file mode 100644
index 00000000..a41bef6e
--- /dev/null
+++ b/public/webshims/shims/mediacapture.js
@@ -0,0 +1,159 @@
+webshim.register('mediacapture', function($, webshim, window, document, undefined, featureOptions){
+ "use strict";
+ var hasCamera = -1;
+ var checkCameras = $.noop;
+ var sel = 'input[type="file"].ws-filereader, input[type="file"].ws-capture';
+ var cameraListPromise = $.Deferred();
+
+ //
+
+ (function(){
+ var tmp;
+
+ var hasNativeUserMedia = !!(navigator.getUserMedia && !navigator.wsGetUserMedia);
+ var hasFlash = swfmini.hasFlashPlayerVersion('11.3');
+ var writeToStorage = function(){
+ try{
+ sessionStorage.setItem('wsCameras', JSON.stringify(hasCamera));
+ } catch (e){}
+ };
+ var reject = function(){
+ hasCamera = 0;
+ writeToStorage();
+ cameraListPromise.reject(hasCamera);
+ };
+ var resolve = function(){
+ writeToStorage();
+ cameraListPromise.resolve(hasCamera);
+ };
+ try {
+ tmp = JSON.parse(sessionStorage.getItem('wsCameras'));
+ if(tmp == null){
+ hasCamera = -1;
+ }
+ } catch(e){}
+
+ if(hasCamera === 0 || (hasCamera == -1 && !hasNativeUserMedia && !hasFlash)){
+ reject();
+ } else if(hasFlash){
+ checkCameras = function(){
+ var mediaOptions = webshim.cfg.mediaelement;
+ var playerSwfPath = mediaOptions.playerPath || (webshim.cfg.basePath + "swf/" + (mediaOptions.playerName || 'JarisFLVPlayer.swf'));
+ var id = 'wscameralistdetection';
+ var vars = {
+ controltype: '1',
+ jsapi: '1',
+ source: '',
+ id: id,
+ evtId: id
+ };
+ var attrs = {
+ id: id,
+ name: id
+ };
+ var params = {
+ allowscriptaccess: 'always',
+ allowNetworking: 'all'
+ };
+ var $dom = $('
')
+ .css({position: 'absolute', left: -999, width: 5, height: 5, overflow: 'hidden'})
+ .appendTo('body')
+ ;
+
+ webshim.mediaelement.jarisEvent = webshim.mediaelement.jarisEvent || {};
+ webshim.mediaelement.jarisEvent[id] = function(jaris){
+ hasCamera = jaris.cameras;
+ $dom.remove();
+ if(hasCamera){
+ resolve();
+ } else {
+ reject();
+ }
+ };
+
+
+ checkCameras = $.noop;
+ swfmini.embedSWF(playerSwfPath, id, "100%", "100%", "11.3", false, vars, params, attrs);
+ };
+
+ } else {
+ hasCamera = -1;
+ resolve();
+ }
+ })();
+ var loadPicker = function(){
+ webshim.ready('WINDOWLOAD', function(){
+ webshim.loader.loadList(['mediacapture-picker']);
+ });
+ loadPicker = $.noop;
+ };
+
+
+ var _createPhotoPicker = function(){
+ if($(this).is('[capture].ws-filereader, .ws-capture') && webshim.implement(this, 'capture')){
+ var $wrapper, $customFile;
+ var $fileinput = $(this);
+ var $button = $('
');
+ var popover = webshim.objectCreate(webshim.wsPopover, {}, $.extend({prepareFor: $button}));
+ popover.element.addClass('capture-popover input-picker');
+
+ if($fileinput.is('.ws-custom-file > *')){
+ $customFile = $fileinput.closest('.ws-custom-file');
+ $wrapper = $('
').insertAfter($customFile);
+ $wrapper.append($button).append($customFile);
+ } else {
+ $fileinput.before($button);
+ }
+ popover.element.insertAfter($button);
+
+ $button.on('click', function(){
+ webshim.mediacapture.showContent($fileinput, $button, popover);
+ popover.show();
+ });
+ loadPicker();
+ }
+ };
+ var createPhotoPicker = function (){
+ var elem = this;
+ checkCameras();
+
+ cameraListPromise.done(function(){
+ _createPhotoPicker.call(elem);
+ });
+ };
+
+ webshim.mediacapture = {
+ showContent: function($fileinput, $button, popover){
+ webshim.loader.loadList(['mediacapture-picker']);
+ webshim.ready('mediacapture-picker', function(){
+ webshim.mediacapture.showContent($fileinput, $button, popover);
+ });
+ }
+ };
+ webshim.defineNodeNamesBooleanProperty('input', 'capture');
+
+ if(hasCamera){
+
+ cameraListPromise.done(function(){
+ createPhotoPicker = _createPhotoPicker;
+ webshim.loader.addModule('mediacapture-picker', {
+ noAutoCallback: true,
+ css: 'styles/forms-picker.css',
+ options: featureOptions
+ });
+
+ });
+
+ webshim.addReady(function(context, insertedElement){
+ $(sel, context).add(insertedElement.filter(sel))
+ .filter('[accept*="image"], :not([accept]), [accept=""]')
+ .each(createPhotoPicker)
+ ;
+ });
+
+ webshim.ready('WINDOWLOAD', checkCameras);
+ }
+ if(document.readyState == 'complete'){
+ webshim.isReady('WINDOWLOAD', true);
+ }
+});
diff --git a/public/webshims/shims/mediaelement-core.js b/public/webshims/shims/mediaelement-core.js
index 2cd8b91f..1655a844 100644
--- a/public/webshims/shims/mediaelement-core.js
+++ b/public/webshims/shims/mediaelement-core.js
@@ -58,9 +58,16 @@
})();
}
+ if(window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype){
+ CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){
+ cb.call(this, this);
+ };
+ }
+
webshims.register('mediaelement-core', function($, webshims, window, document, undefined, options){
var hasSwf = swfmini.hasFlashPlayerVersion('11.3');
var mediaelement = webshims.mediaelement;
+ var allowYtLoading = false;
mediaelement.parseRtmp = function(data){
var src = data.src.split('://');
@@ -156,7 +163,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
return function(){
if(loaded || !hasYt){return;}
loaded = true;
- webshims.loader.loadScript("https://www.youtube.com/player_api");
+ if(allowYtLoading){
+ webshims.loader.loadScript("https://www.youtube.com/player_api");
+ }
$(function(){
webshims._polyfill(["mediaelement-yt"]);
});
@@ -342,6 +351,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
}
});
if(!requested && hasYt && !mediaelement.createSWF){
+ allowYtLoading = true;
loadYt();
}
};
@@ -506,6 +516,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
.add(insertedElement.filter('video, audio'))
.each(function(){
if(!mediaelement.canNativePlaySrces(this)){
+ allowYtLoading = true;
loadThird();
handleMedia = true;
return false;
@@ -528,6 +539,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
mediaelement.loadDebugger();
});
}
+
//set native implementation ready, before swf api is retested
if(hasNative){
webshims.isReady('mediaelement-core', true);
diff --git a/public/webshims/shims/mediaelement-jaris.js b/public/webshims/shims/mediaelement-jaris.js
index b326b11b..be5e4514 100644
--- a/public/webshims/shims/mediaelement-jaris.js
+++ b/public/webshims/shims/mediaelement-jaris.js
@@ -124,12 +124,13 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document,
};
- mediaelement.jarisEvent = {};
+ mediaelement.jarisEvent = mediaelement.jarisEvent || {};
var localConnectionTimer;
var onEvent = {
onPlayPause: function(jaris, data, override){
var playing, type;
var idled = data.paused || data.ended;
+
if(override == null){
try {
playing = data.api.api_get("isPlaying");
@@ -143,12 +144,15 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document,
type = data.paused ? 'pause' : 'play';
data._ppFlag = true;
trigger(data._elem, type);
+
+ }
+ if(!data.paused || playing == idled || playing == null){
if(data.readyState < 3){
setReadyState(3, data);
}
- if(!data.paused){
- trigger(data._elem, 'playing');
- }
+ }
+ if(!data.paused){
+ trigger(data._elem, 'playing');
}
},
onSeek: function(jaris, data){
@@ -900,11 +904,11 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document,
options.changeSWF(vars, elem, canPlaySrc, data, 'embed');
clearTimeout(data.flashBlock);
- swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "9.0.115", false, vars, params, attrs, function(swfData){
+ swfmini.embedSWF(playerSwfPath, elemId, "100%", "100%", "11.3", false, vars, params, attrs, function(swfData){
if(swfData.success){
var fBlocker = function(){
- if((!swfData.ref.parentNode && box[0].parentNode) || swfData.ref.style.display == "none"){
- box.addClass('flashblocker-assumed');
+ if((!swfData.ref.parentNode) || swfData.ref.style.display == "none"){
+
$(elem).trigger('flashblocker');
webshims.warn("flashblocker assumed");
}
@@ -1138,8 +1142,19 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document,
webshim.error('canvas.drawImage feature is needed. In IE8 flashvanvas pro can be used');
}
+ CanvasRenderingContext2D.prototype.wsImageComplete = function(cb){
+ if(this._wsIsLoading){
+ if(!this._wsLoadingCbs){
+ this._wsLoadingCbs = [];
+ }
+ this._wsLoadingCbs.push(cb);
+ } else {
+ cb.call(this, this);
+ }
+ };
+
CanvasRenderingContext2D.prototype.drawImage = function(elem){
- var data, img, args, imgData;
+ var data, img, args, imgData, hadCachedImg;
var context = this;
if(isVideo[elem.nodeName] && (data = webshims.data(elem, 'mediaelement')) && data.isActive == 'third' && data.api.api_image){
@@ -1157,18 +1172,39 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document,
}
args = slice.call(arguments, 1);
- img = new Image();
+
+ if(options.canvasSync && data.canvasImg){
+ args.unshift(data.canvasImg);
+ _drawImage.apply(context, args);
+ args = slice.call(arguments, 1);
+ hadCachedImg = true;
+ }
+
+ img = document.createElement('img');
//todo find a performant sync way
img.onload = function(){
args.unshift(this);
- _drawImage.apply(context, args);
img.onload = null;
+
+ if(options.canvasSync){
+ data.canvasImg = img;
+ if(hadCachedImg && options.noDoubbleDraw){
+ return;
+ }
+ }
+ _drawImage.apply(context, args);
+ context._wsIsLoading = false;
+ if(context._wsLoadingCbs && context._wsLoadingCbs.length){
+ while(context._wsLoadingCbs.length){
+ context._wsLoadingCbs.shift().call(context, context);
+ }
+ }
};
img.src = 'data:image/jpeg;base64,'+imgData;
-
- if(img.complete){
+ this._wsIsLoading = true;
+ if(img.complete && img.onload){
img.onload();
}
return;
diff --git a/public/webshims/shims/mediaelement-yt.js b/public/webshims/shims/mediaelement-yt.js
index c308279f..56396387 100644
--- a/public/webshims/shims/mediaelement-yt.js
+++ b/public/webshims/shims/mediaelement-yt.js
@@ -2,13 +2,21 @@ webshims.register('mediaelement-yt', function($, webshims, window, document, und
"use strict";
var mediaelement = webshims.mediaelement;
var ytAPI = $.Deferred();
+var loadYTAPI = function(){
+ if(!window.YT){
+ webshims.loader.loadScript("https://www.youtube.com/player_api");
+ }
+ loadYTAPI = $.noop;
+};
+var modern = window.Modernizr;
+var assumeYTBug = (!modern || !modern.videoautoplay) && /iP(hone|od|ad)|android/i.test(navigator.userAgent);
window.onYouTubePlayerAPIReady = function() {
ytAPI.resolve();
+ loadYTAPI = $.noop;
};
if(window.YT && YT.Player){
window.onYouTubePlayerAPIReady();
}
-
var getProps = {
paused: true,
ended: false,
@@ -45,7 +53,6 @@ var getSetProps = {
volume: 1,
muted: false
};
-var getSetPropKeys = Object.keys(getSetProps);
var playerStateObj = $.extend({
isActive: 'html5',
@@ -193,7 +200,6 @@ var getComputedDimension = (function(){
var setElementDimension = function(data){
var dims;
- var elem = data._elem;
var box = data.shadowElem;
if(data.isActive == 'third'){
if(data && data._ytAPI && data._ytAPI.getPlaybackQuality){
@@ -439,9 +445,9 @@ var addYtAPI = function(mediaElm, elemId, data, ytParams){
var currentTime = data._ytAPI.getCurrentTime();
if(data.currentTime != currentTime){
data.currentTime = currentTime;
- $(mediaElm).trigger('timeupdate');
+ $.event.trigger('timeupdate', null, mediaElm, true);
}
- }, 350);
+ }, 270);
};
data._metatrys = 0;
@@ -569,7 +575,9 @@ mediaelement.createSWF = function(mediaElem, src, data){
var ytParams = getYtParams(src.src);
var hasControls = $.prop(mediaElem, 'controls');
var attrStyle = {};
-
+
+ loadYTAPI();
+
if((attrStyle.height = $.attr(mediaElem, 'height') || '') || (attrStyle.width = $.attr(mediaElem, 'width') || '')){
$(mediaElem).css(attrStyle);
webshims.warn("width or height content attributes used. Webshims prefers the usage of CSS (computed styles or inline styles) to detect size of a video/audio. It's really more powerfull.");
@@ -739,8 +747,12 @@ mediaelement.createSWF = function(mediaElem, src, data){
var data = getYtDataFromElem(this);
if(data){
if(data._ytAPI && data._ytAPI[ytName]){
- data._ytAPI[ytName]();
- handlePlayPauseState(name, data);
+ if(assumeYTBug && !data.readyState && !data.networkState && data._ppFlag === undefined){
+ webshims.warn('youtube video play needs to be directly activated by user, if you use a video overlay set pointer-events to none.');
+ } else {
+ data._ytAPI[ytName]();
+ handlePlayPauseState(name, data);
+ }
}
} else {
return mediaSup[name].prop._supvalue.apply(this, arguments);
diff --git a/public/webshims/shims/combos/26.js b/public/webshims/shims/moxie/js/moxie-html4.js
similarity index 76%
rename from public/webshims/shims/combos/26.js
rename to public/webshims/shims/moxie/js/moxie-html4.js
index 5d2bf15d..a2edc2d3 100644
--- a/public/webshims/shims/combos/26.js
+++ b/public/webshims/shims/moxie/js/moxie-html4.js
@@ -5131,436 +5131,6 @@ define("moxie/xhr/XMLHttpRequest", [
return XMLHttpRequest;
});
-// Included from: src/javascript/runtime/flash/Runtime.js
-
-/**
- * Runtime.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/*global ActiveXObject:true */
-
-/**
-Defines constructor for Flash runtime.
-
-@class moxie/runtime/flash/Runtime
-@private
-*/
-define("moxie/runtime/flash/Runtime", [
- "moxie/core/utils/Basic",
- "moxie/core/utils/Env",
- "moxie/core/utils/Dom",
- "moxie/core/Exceptions",
- "moxie/runtime/Runtime"
-], function(Basic, Env, Dom, x, Runtime) {
-
- var type = 'flash', extensions = {};
-
- /**
- Get the version of the Flash Player
-
- @method getShimVersion
- @private
- @return {Number} Flash Player version
- */
- function getShimVersion() {
- var version;
-
- try {
- version = navigator.plugins['Shockwave Flash'];
- version = version.description;
- } catch (e1) {
- try {
- version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
- } catch (e2) {
- version = '0.0';
- }
- }
- version = version.match(/\d+/g);
- return parseFloat(version[0] + '.' + version[1]);
- }
-
- /**
- Constructor for the Flash Runtime
-
- @class FlashRuntime
- @extends Runtime
- */
- function FlashRuntime(options) {
- var I = this, initTimer;
-
- options = Basic.extend({ swf_url: Env.swf_url }, options);
-
- Runtime.call(this, options, type, {
- access_binary: function(value) {
- return value && I.mode === 'browser';
- },
- access_image_binary: function(value) {
- return value && I.mode === 'browser';
- },
- display_media: Runtime.capTrue,
- do_cors: Runtime.capTrue,
- drag_and_drop: false,
- report_upload_progress: function() {
- return I.mode === 'client';
- },
- resize_image: Runtime.capTrue,
- return_response_headers: false,
- return_response_type: function(responseType) {
- if (responseType === 'json' && !!window.JSON) {
- return true;
- }
- return !Basic.arrayDiff(responseType, ['', 'text', 'document']) || I.mode === 'browser';
- },
- return_status_code: function(code) {
- return I.mode === 'browser' || !Basic.arrayDiff(code, [200, 404]);
- },
- select_file: Runtime.capTrue,
- select_multiple: Runtime.capTrue,
- send_binary_string: function(value) {
- return value && I.mode === 'browser';
- },
- send_browser_cookies: function(value) {
- return value && I.mode === 'browser';
- },
- send_custom_headers: function(value) {
- return value && I.mode === 'browser';
- },
- send_multipart: Runtime.capTrue,
- slice_blob: function(value) {
- return value && I.mode === 'browser';
- },
- stream_upload: function(value) {
- return value && I.mode === 'browser';
- },
- summon_file_dialog: false,
- upload_filesize: function(size) {
- return Basic.parseSizeStr(size) <= 2097152 || I.mode === 'client';
- },
- use_http_method: function(methods) {
- return !Basic.arrayDiff(methods, ['GET', 'POST']);
- }
- }, {
- // capabilities that require specific mode
- access_binary: function(value) {
- return value ? 'browser' : 'client';
- },
- access_image_binary: function(value) {
- return value ? 'browser' : 'client';
- },
- report_upload_progress: function(value) {
- return value ? 'browser' : 'client';
- },
- return_response_type: function(responseType) {
- return Basic.arrayDiff(responseType, ['', 'text', 'json', 'document']) ? 'browser' : ['client', 'browser'];
- },
- return_status_code: function(code) {
- return Basic.arrayDiff(code, [200, 404]) ? 'browser' : ['client', 'browser'];
- },
- send_binary_string: function(value) {
- return value ? 'browser' : 'client';
- },
- send_browser_cookies: function(value) {
- return value ? 'browser' : 'client';
- },
- send_custom_headers: function(value) {
- return value ? 'browser' : 'client';
- },
- stream_upload: function(value) {
- return value ? 'client' : 'browser';
- },
- upload_filesize: function(size) {
- return Basic.parseSizeStr(size) >= 2097152 ? 'client' : 'browser';
- }
- }, 'client');
-
-
- // minimal requirement for Flash Player version
- if (getShimVersion() < 10) {
- this.mode = false; // with falsy mode, runtime won't operable, no matter what the mode was before
- }
-
-
- Basic.extend(this, {
-
- getShim: function() {
- return Dom.get(this.uid);
- },
-
- shimExec: function(component, action) {
- var args = [].slice.call(arguments, 2);
- return I.getShim().exec(this.uid, component, action, args);
- },
-
- init: function() {
- var html, el, container;
-
- container = this.getShimContainer();
-
- // if not the minimal height, shims are not initialized in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)
- Basic.extend(container.style, {
- position: 'absolute',
- top: '-8px',
- left: '-8px',
- width: '9px',
- height: '9px',
- overflow: 'hidden'
- });
-
- // insert flash object
- html = '
';
-
- if (Env.browser === 'IE') {
- el = document.createElement('div');
- container.appendChild(el);
- el.outerHTML = html;
- el = container = null; // just in case
- } else {
- container.innerHTML = html;
- }
-
- // Init is dispatched by the shim
- initTimer = setTimeout(function() {
- if (I && !I.initialized) { // runtime might be already destroyed by this moment
- I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
- }
- }, 5000);
- },
-
- destroy: (function(destroy) { // extend default destroy method
- return function() {
- destroy.call(I);
- clearTimeout(initTimer); // initialization check might be still onwait
- options = initTimer = destroy = I = null;
- };
- }(this.destroy))
-
- }, extensions);
- }
-
- Runtime.addConstructor(type, FlashRuntime);
-
- return extensions;
-});
-
-// Included from: src/javascript/runtime/flash/file/Blob.js
-
-/**
- * Blob.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/flash/file/Blob
-@private
-*/
-define("moxie/runtime/flash/file/Blob", [
- "moxie/runtime/flash/Runtime",
- "moxie/file/Blob"
-], function(extensions, Blob) {
-
- var FlashBlob = {
- slice: function(blob, start, end, type) {
- var self = this.getRuntime();
-
- if (start < 0) {
- start = Math.max(blob.size + start, 0);
- } else if (start > 0) {
- start = Math.min(start, blob.size);
- }
-
- if (end < 0) {
- end = Math.max(blob.size + end, 0);
- } else if (end > 0) {
- end = Math.min(end, blob.size);
- }
-
- blob = self.shimExec.call(this, 'Blob', 'slice', start, end, type || '');
-
- if (blob) {
- blob = new Blob(self.uid, blob);
- }
- return blob;
- }
- };
-
- return (extensions.Blob = FlashBlob);
-});
-
-// Included from: src/javascript/runtime/flash/file/FileInput.js
-
-/**
- * FileInput.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/flash/file/FileInput
-@private
-*/
-define("moxie/runtime/flash/file/FileInput", [
- "moxie/runtime/flash/Runtime"
-], function(extensions) {
-
- var FileInput = {
- init: function(options) {
- this.getRuntime().shimExec.call(this, 'FileInput', 'init', {
- name: options.name,
- accept: options.accept,
- multiple: options.multiple
- });
- this.trigger('ready');
- }
- };
-
- return (extensions.FileInput = FileInput);
-});
-
-// Included from: src/javascript/runtime/flash/file/FileReader.js
-
-/**
- * FileReader.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/flash/file/FileReader
-@private
-*/
-define("moxie/runtime/flash/file/FileReader", [
- "moxie/runtime/flash/Runtime",
- "moxie/core/utils/Encode"
-], function(extensions, Encode) {
-
- var _result = '';
-
- function _formatData(data, op) {
- switch (op) {
- case 'readAsText':
- return Encode.atob(data, 'utf8');
- case 'readAsBinaryString':
- return Encode.atob(data);
- case 'readAsDataURL':
- return data;
- }
- return null;
- }
-
- var FileReader = {
- read: function(op, blob) {
- var target = this, self = target.getRuntime();
-
- // special prefix for DataURL read mode
- if (op === 'readAsDataURL') {
- _result = 'data:' + (blob.type || '') + ';base64,';
- }
-
- target.bind('Progress', function(e, data) {
- if (data) {
- _result += _formatData(data, op);
- }
- });
-
- return self.shimExec.call(this, 'FileReader', 'readAsBase64', blob.uid);
- },
-
- getResult: function() {
- return _result;
- },
-
- destroy: function() {
- _result = null;
- }
- };
-
- return (extensions.FileReader = FileReader);
-});
-
-// Included from: src/javascript/runtime/flash/file/FileReaderSync.js
-
-/**
- * FileReaderSync.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/flash/file/FileReaderSync
-@private
-*/
-define("moxie/runtime/flash/file/FileReaderSync", [
- "moxie/runtime/flash/Runtime",
- "moxie/core/utils/Encode"
-], function(extensions, Encode) {
-
- function _formatData(data, op) {
- switch (op) {
- case 'readAsText':
- return Encode.atob(data, 'utf8');
- case 'readAsBinaryString':
- return Encode.atob(data);
- case 'readAsDataURL':
- return data;
- }
- return null;
- }
-
- var FileReaderSync = {
- read: function(op, blob) {
- var result, self = this.getRuntime();
-
- result = self.shimExec.call(this, 'FileReaderSync', 'readAsBase64', blob.uid);
- if (!result) {
- return null; // or throw ex
- }
-
- // special prefix for DataURL read mode
- if (op === 'readAsDataURL') {
- result = 'data:' + (blob.type || '') + ';base64,' + result;
- }
-
- return _formatData(result, op, blob.type);
- }
- };
-
- return (extensions.FileReaderSync = FileReaderSync);
-});
-
// Included from: src/javascript/runtime/Transporter.js
/**
@@ -5698,10 +5268,10 @@ define("moxie/runtime/Transporter", [
return Transporter;
});
-// Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js
+// Included from: src/javascript/image/Image.js
/**
- * XMLHttpRequest.js
+ * Image.js
*
* Copyright 2013, Moxiecode Systems AB
* Released under GPL License.
@@ -5710,141 +5280,598 @@ define("moxie/runtime/Transporter", [
* Contributing: http://www.plupload.com/contributing
*/
-/**
-@class moxie/runtime/flash/xhr/XMLHttpRequest
-@private
-*/
-define("moxie/runtime/flash/xhr/XMLHttpRequest", [
- "moxie/runtime/flash/Runtime",
+define("moxie/image/Image", [
"moxie/core/utils/Basic",
+ "moxie/core/utils/Dom",
+ "moxie/core/Exceptions",
+ "moxie/file/FileReaderSync",
+ "moxie/xhr/XMLHttpRequest",
+ "moxie/runtime/Runtime",
+ "moxie/runtime/RuntimeClient",
+ "moxie/runtime/Transporter",
+ "moxie/core/utils/Env",
+ "moxie/core/EventTarget",
"moxie/file/Blob",
"moxie/file/File",
- "moxie/file/FileReaderSync",
- "moxie/xhr/FormData",
- "moxie/runtime/Transporter"
-], function(extensions, Basic, Blob, File, FileReaderSync, FormData, Transporter) {
-
- var XMLHttpRequest = {
+ "moxie/core/utils/Encode"
+], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) {
+ /**
+ Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data.
- send: function(meta, data) {
- var target = this, self = target.getRuntime();
+ @class Image
+ @constructor
+ @extends EventTarget
+ */
+ var dispatches = [
+ 'progress',
- function send() {
- meta.transport = self.mode;
- self.shimExec.call(target, 'XMLHttpRequest', 'send', meta, data);
- }
+ /**
+ Dispatched when loading is complete.
+ @event load
+ @param {Object} event
+ */
+ 'load',
- function appendBlob(name, blob) {
- self.shimExec.call(target, 'XMLHttpRequest', 'appendBlob', name, blob.uid);
- data = null;
- send();
- }
+ 'error',
+ /**
+ Dispatched when resize operation is complete.
+
+ @event resize
+ @param {Object} event
+ */
+ 'resize',
- function attachBlob(blob, cb) {
- var tr = new Transporter();
+ /**
+ Dispatched when visual representation of the image is successfully embedded
+ into the corresponsing container.
- tr.bind("TransportingComplete", function() {
- cb(this.result);
- });
+ @event embedded
+ @param {Object} event
+ */
+ 'embedded'
+ ];
- tr.transport(blob.getSource(), blob.type, {
- ruid: self.uid
- });
- }
+ function Image() {
+ RuntimeClient.call(this);
- // copy over the headers if any
- if (!Basic.isEmptyObj(meta.headers)) {
- Basic.each(meta.headers, function(value, header) {
- self.shimExec.call(target, 'XMLHttpRequest', 'setRequestHeader', header, value.toString()); // Silverlight doesn't accept integers into the arguments of type object
- });
- }
+ Basic.extend(this, {
+ /**
+ Unique id of the component
- // transfer over multipart params and blob itself
- if (data instanceof FormData) {
- var blobField;
- data.each(function(value, name) {
- if (value instanceof Blob) {
- blobField = name;
- } else {
- self.shimExec.call(target, 'XMLHttpRequest', 'append', name, value);
- }
- });
+ @property uid
+ @type {String}
+ */
+ uid: Basic.guid('uid_'),
- if (!data.hasBlob()) {
- data = null;
- send();
+ /**
+ Unique id of the connected runtime, if any.
+
+ @property ruid
+ @type {String}
+ */
+ ruid: null,
+
+ /**
+ Name of the file, that was used to create an image, if available. If not equals to empty string.
+
+ @property name
+ @type {String}
+ @default ""
+ */
+ name: "",
+
+ /**
+ Size of the image in bytes. Actual value is set only after image is preloaded.
+
+ @property size
+ @type {Number}
+ @default 0
+ */
+ size: 0,
+
+ /**
+ Width of the image. Actual value is set only after image is preloaded.
+
+ @property width
+ @type {Number}
+ @default 0
+ */
+ width: 0,
+
+ /**
+ Height of the image. Actual value is set only after image is preloaded.
+
+ @property height
+ @type {Number}
+ @default 0
+ */
+ height: 0,
+
+ /**
+ Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded.
+
+ @property type
+ @type {String}
+ @default ""
+ */
+ type: "",
+
+ /**
+ Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded.
+
+ @property meta
+ @type {Object}
+ @default {}
+ */
+ meta: {},
+
+ /**
+ Alias for load method, that takes another mOxie.Image object as a source (see load).
+
+ @method clone
+ @param {Image} src Source for the image
+ @param {Boolean} [exact=false] Whether to activate in-depth clone mode
+ */
+ clone: function() {
+ this.load.apply(this, arguments);
+ },
+
+ /**
+ Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File,
+ native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL,
+ Image will be downloaded from remote destination and loaded in memory.
+
+ @example
+ var img = new mOxie.Image();
+ img.onload = function() {
+ var blob = img.getAsBlob();
+
+ var formData = new mOxie.FormData();
+ formData.append('file', blob);
+
+ var xhr = new mOxie.XMLHttpRequest();
+ xhr.onload = function() {
+ // upload complete
+ };
+ xhr.open('post', 'upload.php');
+ xhr.send(formData);
+ };
+ img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg)
+
+
+ @method load
+ @param {Image|Blob|File|String} src Source for the image
+ @param {Boolean|Object} [mixed]
+ */
+ load: function() {
+ // this is here because to bind properly we need an uid first, which is created above
+ this.bind('Load Resize', function() {
+ _updateInfo.call(this);
+ }, 999);
+
+ this.convertEventPropsToHandlers(dispatches);
+
+ _load.apply(this, arguments);
+ },
+
+ /**
+ Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions.
+
+ @method downsize
+ @param {Number} width Resulting width
+ @param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
+ @param {Boolean} [crop=false] Whether to crop the image to exact dimensions
+ @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
+ */
+ downsize: function(opts) {
+ var defaults = {
+ width: this.width,
+ height: this.height,
+ crop: false,
+ preserveHeaders: true
+ };
+
+ if (typeof(opts) === 'object') {
+ opts = Basic.extend(defaults, opts);
} else {
- var blob = data.getBlob();
- if (blob.isDetached()) {
- attachBlob(blob, function(attachedBlob) {
- blob.destroy();
- appendBlob(blobField, attachedBlob);
- });
- } else {
- appendBlob(blobField, blob);
- }
- }
- } else if (data instanceof Blob) {
- if (data.isDetached()) {
- attachBlob(data, function(attachedBlob) {
- data.destroy();
- data = attachedBlob.uid;
- send();
+ opts = Basic.extend(defaults, {
+ width: arguments[0],
+ height: arguments[1],
+ crop: arguments[2],
+ preserveHeaders: arguments[3]
});
- } else {
- data = data.uid;
- send();
- }
- } else {
- send();
- }
- },
-
- getResponse: function(responseType) {
- var frs, blob, self = this.getRuntime();
-
- blob = self.shimExec.call(this, 'XMLHttpRequest', 'getResponseAsBlob');
-
- if (blob) {
- blob = new File(self.uid, blob);
-
- if ('blob' === responseType) {
- return blob;
}
- try {
- frs = new FileReaderSync();
-
- if (!!~Basic.inArray(responseType, ["", "text"])) {
- return frs.readAsText(blob);
- } else if ('json' === responseType && !!window.JSON) {
- return JSON.parse(frs.readAsText(blob));
+ try {
+ if (!this.size) { // only preloaded image objects can be used as source
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
}
- } finally {
- blob.destroy();
+
+ // no way to reliably intercept the crash due to high resolution, so we simply avoid it
+ if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
+ throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
+ }
+
+ this.getRuntime().exec.call(this, 'Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders);
+ } catch(ex) {
+ // for now simply trigger error event
+ this.trigger('error', ex.code);
}
+ },
+
+ /**
+ Alias for downsize(width, height, true). (see downsize)
+
+ @method crop
+ @param {Number} width Resulting width
+ @param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
+ @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
+ */
+ crop: function(width, height, preserveHeaders) {
+ this.downsize(width, height, true, preserveHeaders);
+ },
+
+ getAsCanvas: function() {
+ if (!Env.can('create_canvas')) {
+ throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+ }
+
+ var runtime = this.connectRuntime(this.ruid);
+ return runtime.exec.call(this, 'Image', 'getAsCanvas');
+ },
+
+ /**
+ Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws
+ DOMException.INVALID_STATE_ERR).
+
+ @method getAsBlob
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+ @return {Blob} Image as Blob
+ */
+ getAsBlob: function(type, quality) {
+ if (!this.size) {
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+
+ if (!type) {
+ type = 'image/jpeg';
+ }
+
+ if (type === 'image/jpeg' && !quality) {
+ quality = 90;
+ }
+
+ return this.getRuntime().exec.call(this, 'Image', 'getAsBlob', type, quality);
+ },
+
+ /**
+ Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws
+ DOMException.INVALID_STATE_ERR).
+
+ @method getAsDataURL
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+ @return {String} Image as dataURL string
+ */
+ getAsDataURL: function(type, quality) {
+ if (!this.size) {
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+ return this.getRuntime().exec.call(this, 'Image', 'getAsDataURL', type, quality);
+ },
+
+ /**
+ Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws
+ DOMException.INVALID_STATE_ERR).
+
+ @method getAsBinaryString
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+ @return {String} Image as binary string
+ */
+ getAsBinaryString: function(type, quality) {
+ var dataUrl = this.getAsDataURL(type, quality);
+ return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7));
+ },
+
+ /**
+ Embeds a visual representation of the image into the specified node. Depending on the runtime,
+ it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare,
+ can be used in legacy browsers that do not have canvas or proper dataURI support).
+
+ @method embed
+ @param {DOMElement} el DOM element to insert the image object into
+ @param {Object} [options]
+ @param {Number} [options.width] The width of an embed (defaults to the image width)
+ @param {Number} [options.height] The height of an embed (defaults to the image height)
+ @param {String} [type="image/jpeg"] Mime type
+ @param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg
+ @param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions
+ */
+ embed: function(el) {
+ var self = this
+ , imgCopy
+ , type, quality, crop
+ , options = arguments[1] || {}
+ , width = this.width
+ , height = this.height
+ , runtime // this has to be outside of all the closures to contain proper runtime
+ ;
+
+ function onResize() {
+ // if possible, embed a canvas element directly
+ if (Env.can('create_canvas')) {
+ var canvas = imgCopy.getAsCanvas();
+ if (canvas) {
+ el.appendChild(canvas);
+ canvas = null;
+ imgCopy.destroy();
+ self.trigger('embedded');
+ return;
+ }
+ }
+
+ var dataUrl = imgCopy.getAsDataURL(type, quality);
+ if (!dataUrl) {
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+ }
+
+ if (Env.can('use_data_uri_of', dataUrl.length)) {
+ el.innerHTML = '
';
+ imgCopy.destroy();
+ self.trigger('embedded');
+ } else {
+ var tr = new Transporter();
+
+ tr.bind("TransportingComplete", function() {
+ runtime = self.connectRuntime(this.result.ruid);
+
+ self.bind("Embedded", function() {
+ // position and size properly
+ Basic.extend(runtime.getShimContainer().style, {
+ //position: 'relative',
+ top: '0px',
+ left: '0px',
+ width: imgCopy.width + 'px',
+ height: imgCopy.height + 'px'
+ });
+
+ // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's
+ // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and
+ // sometimes 8 and they do not have this problem, we can comment this for now
+ /*tr.bind("RuntimeInit", function(e, runtime) {
+ tr.destroy();
+ runtime.destroy();
+ onResize.call(self); // re-feed our image data
+ });*/
+
+ runtime = null;
+ }, 999);
+
+ runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height);
+ imgCopy.destroy();
+ });
+
+ tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, Basic.extend({}, options, {
+ required_caps: {
+ display_media: true
+ },
+ runtime_order: 'flash,silverlight',
+ container: el
+ }));
+ }
+ }
+
+ try {
+ if (!(el = Dom.get(el))) {
+ throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR);
+ }
+
+ if (!this.size) { // only preloaded image objects can be used as source
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+
+ if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
+ throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
+ }
+
+ type = options.type || this.type || 'image/jpeg';
+ quality = options.quality || 90;
+ crop = Basic.typeOf(options.crop) !== 'undefined' ? options.crop : false;
+
+ // figure out dimensions for the thumb
+ if (options.width) {
+ width = options.width;
+ height = options.height || width;
+ } else {
+ // if container element has measurable dimensions, use them
+ var dimensions = Dom.getSize(el);
+ if (dimensions.w && dimensions.h) { // both should be > 0
+ width = dimensions.w;
+ height = dimensions.h;
+ }
+ }
+
+ imgCopy = new Image();
+
+ imgCopy.bind("Resize", function() {
+ onResize.call(self);
+ });
+
+ imgCopy.bind("Load", function() {
+ imgCopy.downsize(width, height, crop, false);
+ });
+
+ imgCopy.clone(this, false);
+
+ return imgCopy;
+ } catch(ex) {
+ // for now simply trigger error event
+ this.trigger('error', ex.code);
+ }
+ },
+
+ /**
+ Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object.
+
+ @method destroy
+ */
+ destroy: function() {
+ if (this.ruid) {
+ this.getRuntime().exec.call(this, 'Image', 'destroy');
+ this.disconnectRuntime();
+ }
+ this.unbindAll();
}
- return null;
- },
+ });
- abort: function(upload_complete_flag) {
- var self = this.getRuntime();
- self.shimExec.call(this, 'XMLHttpRequest', 'abort');
+ function _updateInfo(info) {
+ if (!info) {
+ info = this.getRuntime().exec.call(this, 'Image', 'getInfo');
+ }
- this.dispatchEvent('readystatechange');
- // this.dispatchEvent('progress');
- this.dispatchEvent('abort');
+ this.size = info.size;
+ this.width = info.width;
+ this.height = info.height;
+ this.type = info.type;
+ this.meta = info.meta;
- //if (!upload_complete_flag) {
- // this.dispatchEvent('uploadprogress');
- //}
+ // update file name, only if empty
+ if (this.name === '') {
+ this.name = info.name;
+ }
}
- };
+
- return (extensions.XMLHttpRequest = XMLHttpRequest);
+ function _load(src) {
+ var srcType = Basic.typeOf(src);
+
+ try {
+ // if source is Image
+ if (src instanceof Image) {
+ if (!src.size) { // only preloaded image objects can be used as source
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+ _loadFromImage.apply(this, arguments);
+ }
+ // if source is o.Blob/o.File
+ else if (src instanceof Blob) {
+ if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) {
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+ }
+ _loadFromBlob.apply(this, arguments);
+ }
+ // if native blob/file
+ else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) {
+ _load.call(this, new File(null, src), arguments[1]);
+ }
+ // if String
+ else if (srcType === 'string') {
+ // if dataUrl String
+ if (/^data:[^;]*;base64,/.test(src)) {
+ _load.call(this, new Blob(null, { data: src }), arguments[1]);
+ }
+ // else assume Url, either relative or absolute
+ else {
+ _loadFromUrl.apply(this, arguments);
+ }
+ }
+ // if source seems to be an img node
+ else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') {
+ _load.call(this, src.src, arguments[1]);
+ }
+ else {
+ throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR);
+ }
+ } catch(ex) {
+ // for now simply trigger error event
+ this.trigger('error', ex.code);
+ }
+ }
+
+
+ function _loadFromImage(img, exact) {
+ var runtime = this.connectRuntime(img.ruid);
+ this.ruid = runtime.uid;
+ runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact));
+ }
+
+
+ function _loadFromBlob(blob, options) {
+ var self = this;
+
+ self.name = blob.name || '';
+
+ function exec(runtime) {
+ self.ruid = runtime.uid;
+ runtime.exec.call(self, 'Image', 'loadFromBlob', blob);
+ }
+
+ if (blob.isDetached()) {
+ this.bind('RuntimeInit', function(e, runtime) {
+ exec(runtime);
+ });
+
+ // convert to object representation
+ if (options && typeof(options.required_caps) === 'string') {
+ options.required_caps = Runtime.parseCaps(options.required_caps);
+ }
+
+ this.connectRuntime(Basic.extend({
+ required_caps: {
+ access_image_binary: true,
+ resize_image: true
+ }
+ }, options));
+ } else {
+ exec(this.connectRuntime(blob.ruid));
+ }
+ }
+
+
+ function _loadFromUrl(url, options) {
+ var self = this, xhr;
+
+ xhr = new XMLHttpRequest();
+
+ xhr.open('get', url);
+ xhr.responseType = 'blob';
+
+ xhr.onprogress = function(e) {
+ self.trigger(e);
+ };
+
+ xhr.onload = function() {
+ _loadFromBlob.call(self, xhr.response, true);
+ };
+
+ xhr.onerror = function(e) {
+ self.trigger(e);
+ };
+
+ xhr.onloadend = function() {
+ xhr.destroy();
+ };
+
+ xhr.bind('RuntimeError', function(e, err) {
+ self.trigger('RuntimeError', err);
+ });
+
+ xhr.send(null, options);
+ }
+ }
+
+ // virtual world will crash on you if image has a resolution higher than this:
+ Image.MAX_RESIZE_WIDTH = 6500;
+ Image.MAX_RESIZE_HEIGHT = 6500;
+
+ Image.prototype = EventTarget.instance;
+
+ return Image;
});
// Included from: src/javascript/runtime/html4/Runtime.js
@@ -6836,10 +6863,10 @@ define("moxie/runtime/html4/xhr/XMLHttpRequest", [
return (extensions.XMLHttpRequest = XMLHttpRequest);
});
-// Included from: src/javascript/runtime/silverlight/Runtime.js
+// Included from: src/javascript/runtime/html5/utils/BinaryReader.js
/**
- * RunTime.js
+ * BinaryReader.js
*
* Copyright 2013, Moxiecode Systems AB
* Released under GPL License.
@@ -6848,207 +6875,1630 @@ define("moxie/runtime/html4/xhr/XMLHttpRequest", [
* Contributing: http://www.plupload.com/contributing
*/
-/*global ActiveXObject:true */
-
/**
-Defines constructor for Silverlight runtime.
-
-@class moxie/runtime/silverlight/Runtime
+@class moxie/runtime/html5/utils/BinaryReader
@private
*/
-define("moxie/runtime/silverlight/Runtime", [
- "moxie/core/utils/Basic",
- "moxie/core/utils/Env",
- "moxie/core/utils/Dom",
- "moxie/core/Exceptions",
- "moxie/runtime/Runtime"
-], function(Basic, Env, Dom, x, Runtime) {
-
- var type = "silverlight", extensions = {};
+define("moxie/runtime/html5/utils/BinaryReader", [], function() {
+ return function() {
+ var II = false, bin;
- function isInstalled(version) {
- var isVersionSupported = false, control = null, actualVer,
- actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0;
+ // Private functions
+ function read(idx, size) {
+ var mv = II ? 0 : -8 * (size - 1), sum = 0, i;
- try {
- try {
- control = new ActiveXObject('AgControl.AgControl');
+ for (i = 0; i < size; i++) {
+ sum |= (bin.charCodeAt(idx + i) << Math.abs(mv + i*8));
+ }
- if (control.IsVersionSupported(version)) {
- isVersionSupported = true;
+ return sum;
+ }
+
+ function putstr(segment, idx, length) {
+ length = arguments.length === 3 ? length : bin.length - idx - 1;
+ bin = bin.substr(0, idx) + segment + bin.substr(length + idx);
+ }
+
+ function write(idx, num, size) {
+ var str = '', mv = II ? 0 : -8 * (size - 1), i;
+
+ for (i = 0; i < size; i++) {
+ str += String.fromCharCode((num >> Math.abs(mv + i*8)) & 255);
+ }
+
+ putstr(str, idx, size);
+ }
+
+ // Public functions
+ return {
+ II: function(order) {
+ if (order === undefined) {
+ return II;
+ } else {
+ II = order;
+ }
+ },
+
+ init: function(binData) {
+ II = false;
+ bin = binData;
+ },
+
+ SEGMENT: function(idx, length, segment) {
+ switch (arguments.length) {
+ case 1:
+ return bin.substr(idx, bin.length - idx - 1);
+ case 2:
+ return bin.substr(idx, length);
+ case 3:
+ putstr(segment, idx, length);
+ break;
+ default: return bin;
+ }
+ },
+
+ BYTE: function(idx) {
+ return read(idx, 1);
+ },
+
+ SHORT: function(idx) {
+ return read(idx, 2);
+ },
+
+ LONG: function(idx, num) {
+ if (num === undefined) {
+ return read(idx, 4);
+ } else {
+ write(idx, num, 4);
+ }
+ },
+
+ SLONG: function(idx) { // 2's complement notation
+ var num = read(idx, 4);
+
+ return (num > 2147483647 ? num - 4294967296 : num);
+ },
+
+ STRING: function(idx, size) {
+ var str = '';
+
+ for (size += idx; idx < size; idx++) {
+ str += String.fromCharCode(read(idx, 1));
}
- control = null;
- } catch (e) {
- var plugin = navigator.plugins["Silverlight Plug-In"];
+ return str;
+ }
+ };
+ };
+});
- if (plugin) {
- actualVer = plugin.description;
+// Included from: src/javascript/runtime/html5/image/JPEGHeaders.js
- if (actualVer === "1.0.30226.2") {
- actualVer = "2.0.30226.2";
+/**
+ * JPEGHeaders.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/JPEGHeaders
+@private
+*/
+define("moxie/runtime/html5/image/JPEGHeaders", [
+ "moxie/runtime/html5/utils/BinaryReader"
+], function(BinaryReader) {
+
+ return function JPEGHeaders(data) {
+ var headers = [], read, idx, marker, length = 0;
+
+ read = new BinaryReader();
+ read.init(data);
+
+ // Check if data is jpeg
+ if (read.SHORT(0) !== 0xFFD8) {
+ return;
+ }
+
+ idx = 2;
+
+ while (idx <= data.length) {
+ marker = read.SHORT(idx);
+
+ // omit RST (restart) markers
+ if (marker >= 0xFFD0 && marker <= 0xFFD7) {
+ idx += 2;
+ continue;
+ }
+
+ // no headers allowed after SOS marker
+ if (marker === 0xFFDA || marker === 0xFFD9) {
+ break;
+ }
+
+ length = read.SHORT(idx + 2) + 2;
+
+ // APPn marker detected
+ if (marker >= 0xFFE1 && marker <= 0xFFEF) {
+ headers.push({
+ hex: marker,
+ name: 'APP' + (marker & 0x000F),
+ start: idx,
+ length: length,
+ segment: read.SEGMENT(idx, length)
+ });
+ }
+
+ idx += length;
+ }
+
+ read.init(null); // free memory
+
+ return {
+ headers: headers,
+
+ restore: function(data) {
+ var max, i;
+
+ read.init(data);
+
+ idx = read.SHORT(2) == 0xFFE0 ? 4 + read.SHORT(4) : 2;
+
+ for (i = 0, max = headers.length; i < max; i++) {
+ read.SEGMENT(idx, 0, headers[i].segment);
+ idx += headers[i].length;
+ }
+
+ data = read.SEGMENT();
+ read.init(null);
+ return data;
+ },
+
+ strip: function(data) {
+ var headers, jpegHeaders, i;
+
+ jpegHeaders = new JPEGHeaders(data);
+ headers = jpegHeaders.headers;
+ jpegHeaders.purge();
+
+ read.init(data);
+
+ i = headers.length;
+ while (i--) {
+ read.SEGMENT(headers[i].start, headers[i].length, '');
+ }
+
+ data = read.SEGMENT();
+ read.init(null);
+ return data;
+ },
+
+ get: function(name) {
+ var array = [];
+
+ for (var i = 0, max = headers.length; i < max; i++) {
+ if (headers[i].name === name.toUpperCase()) {
+ array.push(headers[i].segment);
}
+ }
+ return array;
+ },
- actualVerArray = actualVer.split(".");
+ set: function(name, segment) {
+ var array = [], i, ii, max;
- while (actualVerArray.length > 3) {
- actualVerArray.pop();
+ if (typeof(segment) === 'string') {
+ array.push(segment);
+ } else {
+ array = segment;
+ }
+
+ for (i = ii = 0, max = headers.length; i < max; i++) {
+ if (headers[i].name === name.toUpperCase()) {
+ headers[i].segment = array[ii];
+ headers[i].length = array[ii].length;
+ ii++;
}
-
- while ( actualVerArray.length < 4) {
- actualVerArray.push(0);
+ if (ii >= array.length) {
+ break;
}
+ }
+ },
- reqVerArray = version.split(".");
+ purge: function() {
+ headers = [];
+ read.init(null);
+ read = null;
+ }
+ };
+ };
+});
- while (reqVerArray.length > 4) {
- reqVerArray.pop();
- }
+// Included from: src/javascript/runtime/html5/image/ExifParser.js
- do {
- requiredVersionPart = parseInt(reqVerArray[index], 10);
- actualVersionPart = parseInt(actualVerArray[index], 10);
- index++;
- } while (index < reqVerArray.length && requiredVersionPart === actualVersionPart);
+/**
+ * ExifParser.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
- if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) {
- isVersionSupported = true;
+/**
+@class moxie/runtime/html5/image/ExifParser
+@private
+*/
+define("moxie/runtime/html5/image/ExifParser", [
+ "moxie/core/utils/Basic",
+ "moxie/runtime/html5/utils/BinaryReader"
+], function(Basic, BinaryReader) {
+
+ return function ExifParser() {
+ // Private ExifParser fields
+ var data, tags, Tiff, offsets = {}, tagDescs;
+
+ data = new BinaryReader();
+
+ tags = {
+ tiff : {
+ /*
+ The image orientation viewed in terms of rows and columns.
+
+ 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
+ 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
+ 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
+ 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
+ 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
+ 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
+ 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
+ 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
+ */
+ 0x0112: 'Orientation',
+ 0x010E: 'ImageDescription',
+ 0x010F: 'Make',
+ 0x0110: 'Model',
+ 0x0131: 'Software',
+ 0x8769: 'ExifIFDPointer',
+ 0x8825: 'GPSInfoIFDPointer'
+ },
+ exif : {
+ 0x9000: 'ExifVersion',
+ 0xA001: 'ColorSpace',
+ 0xA002: 'PixelXDimension',
+ 0xA003: 'PixelYDimension',
+ 0x9003: 'DateTimeOriginal',
+ 0x829A: 'ExposureTime',
+ 0x829D: 'FNumber',
+ 0x8827: 'ISOSpeedRatings',
+ 0x9201: 'ShutterSpeedValue',
+ 0x9202: 'ApertureValue' ,
+ 0x9207: 'MeteringMode',
+ 0x9208: 'LightSource',
+ 0x9209: 'Flash',
+ 0x920A: 'FocalLength',
+ 0xA402: 'ExposureMode',
+ 0xA403: 'WhiteBalance',
+ 0xA406: 'SceneCaptureType',
+ 0xA404: 'DigitalZoomRatio',
+ 0xA408: 'Contrast',
+ 0xA409: 'Saturation',
+ 0xA40A: 'Sharpness'
+ },
+ gps : {
+ 0x0000: 'GPSVersionID',
+ 0x0001: 'GPSLatitudeRef',
+ 0x0002: 'GPSLatitude',
+ 0x0003: 'GPSLongitudeRef',
+ 0x0004: 'GPSLongitude'
+ }
+ };
+
+ tagDescs = {
+ 'ColorSpace': {
+ 1: 'sRGB',
+ 0: 'Uncalibrated'
+ },
+
+ 'MeteringMode': {
+ 0: 'Unknown',
+ 1: 'Average',
+ 2: 'CenterWeightedAverage',
+ 3: 'Spot',
+ 4: 'MultiSpot',
+ 5: 'Pattern',
+ 6: 'Partial',
+ 255: 'Other'
+ },
+
+ 'LightSource': {
+ 1: 'Daylight',
+ 2: 'Fliorescent',
+ 3: 'Tungsten',
+ 4: 'Flash',
+ 9: 'Fine weather',
+ 10: 'Cloudy weather',
+ 11: 'Shade',
+ 12: 'Daylight fluorescent (D 5700 - 7100K)',
+ 13: 'Day white fluorescent (N 4600 -5400K)',
+ 14: 'Cool white fluorescent (W 3900 - 4500K)',
+ 15: 'White fluorescent (WW 3200 - 3700K)',
+ 17: 'Standard light A',
+ 18: 'Standard light B',
+ 19: 'Standard light C',
+ 20: 'D55',
+ 21: 'D65',
+ 22: 'D75',
+ 23: 'D50',
+ 24: 'ISO studio tungsten',
+ 255: 'Other'
+ },
+
+ 'Flash': {
+ 0x0000: 'Flash did not fire.',
+ 0x0001: 'Flash fired.',
+ 0x0005: 'Strobe return light not detected.',
+ 0x0007: 'Strobe return light detected.',
+ 0x0009: 'Flash fired, compulsory flash mode',
+ 0x000D: 'Flash fired, compulsory flash mode, return light not detected',
+ 0x000F: 'Flash fired, compulsory flash mode, return light detected',
+ 0x0010: 'Flash did not fire, compulsory flash mode',
+ 0x0018: 'Flash did not fire, auto mode',
+ 0x0019: 'Flash fired, auto mode',
+ 0x001D: 'Flash fired, auto mode, return light not detected',
+ 0x001F: 'Flash fired, auto mode, return light detected',
+ 0x0020: 'No flash function',
+ 0x0041: 'Flash fired, red-eye reduction mode',
+ 0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
+ 0x0047: 'Flash fired, red-eye reduction mode, return light detected',
+ 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
+ 0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
+ 0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
+ 0x0059: 'Flash fired, auto mode, red-eye reduction mode',
+ 0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
+ 0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
+ },
+
+ 'ExposureMode': {
+ 0: 'Auto exposure',
+ 1: 'Manual exposure',
+ 2: 'Auto bracket'
+ },
+
+ 'WhiteBalance': {
+ 0: 'Auto white balance',
+ 1: 'Manual white balance'
+ },
+
+ 'SceneCaptureType': {
+ 0: 'Standard',
+ 1: 'Landscape',
+ 2: 'Portrait',
+ 3: 'Night scene'
+ },
+
+ 'Contrast': {
+ 0: 'Normal',
+ 1: 'Soft',
+ 2: 'Hard'
+ },
+
+ 'Saturation': {
+ 0: 'Normal',
+ 1: 'Low saturation',
+ 2: 'High saturation'
+ },
+
+ 'Sharpness': {
+ 0: 'Normal',
+ 1: 'Soft',
+ 2: 'Hard'
+ },
+
+ // GPS related
+ 'GPSLatitudeRef': {
+ N: 'North latitude',
+ S: 'South latitude'
+ },
+
+ 'GPSLongitudeRef': {
+ E: 'East longitude',
+ W: 'West longitude'
+ }
+ };
+
+ function extractTags(IFD_offset, tags2extract) {
+ var length = data.SHORT(IFD_offset), i, ii,
+ tag, type, count, tagOffset, offset, value, values = [], hash = {};
+
+ for (i = 0; i < length; i++) {
+ // Set binary reader pointer to beginning of the next tag
+ offset = tagOffset = IFD_offset + 12 * i + 2;
+
+ tag = tags2extract[data.SHORT(offset)];
+
+ if (tag === undefined) {
+ continue; // Not the tag we requested
+ }
+
+ type = data.SHORT(offset+=2);
+ count = data.LONG(offset+=2);
+
+ offset += 4;
+ values = [];
+
+ switch (type) {
+ case 1: // BYTE
+ case 7: // UNDEFINED
+ if (count > 4) {
+ offset = data.LONG(offset) + offsets.tiffHeader;
+ }
+
+ for (ii = 0; ii < count; ii++) {
+ values[ii] = data.BYTE(offset + ii);
+ }
+
+ break;
+
+ case 2: // STRING
+ if (count > 4) {
+ offset = data.LONG(offset) + offsets.tiffHeader;
+ }
+
+ hash[tag] = data.STRING(offset, count - 1);
+
+ continue;
+
+ case 3: // SHORT
+ if (count > 2) {
+ offset = data.LONG(offset) + offsets.tiffHeader;
+ }
+
+ for (ii = 0; ii < count; ii++) {
+ values[ii] = data.SHORT(offset + ii*2);
+ }
+
+ break;
+
+ case 4: // LONG
+ if (count > 1) {
+ offset = data.LONG(offset) + offsets.tiffHeader;
+ }
+
+ for (ii = 0; ii < count; ii++) {
+ values[ii] = data.LONG(offset + ii*4);
+ }
+
+ break;
+
+ case 5: // RATIONAL
+ offset = data.LONG(offset) + offsets.tiffHeader;
+
+ for (ii = 0; ii < count; ii++) {
+ values[ii] = data.LONG(offset + ii*4) / data.LONG(offset + ii*4 + 4);
+ }
+
+ break;
+
+ case 9: // SLONG
+ offset = data.LONG(offset) + offsets.tiffHeader;
+
+ for (ii = 0; ii < count; ii++) {
+ values[ii] = data.SLONG(offset + ii*4);
+ }
+
+ break;
+
+ case 10: // SRATIONAL
+ offset = data.LONG(offset) + offsets.tiffHeader;
+
+ for (ii = 0; ii < count; ii++) {
+ values[ii] = data.SLONG(offset + ii*4) / data.SLONG(offset + ii*4 + 4);
+ }
+
+ break;
+
+ default:
+ continue;
+ }
+
+ value = (count == 1 ? values[0] : values);
+
+ if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') {
+ hash[tag] = tagDescs[tag][value];
+ } else {
+ hash[tag] = value;
+ }
+ }
+
+ return hash;
+ }
+
+ function getIFDOffsets() {
+ var idx = offsets.tiffHeader;
+
+ // Set read order of multi-byte data
+ data.II(data.SHORT(idx) == 0x4949);
+
+ // Check if always present bytes are indeed present
+ if (data.SHORT(idx+=2) !== 0x002A) {
+ return false;
+ }
+
+ offsets.IFD0 = offsets.tiffHeader + data.LONG(idx += 2);
+ Tiff = extractTags(offsets.IFD0, tags.tiff);
+
+ if ('ExifIFDPointer' in Tiff) {
+ offsets.exifIFD = offsets.tiffHeader + Tiff.ExifIFDPointer;
+ delete Tiff.ExifIFDPointer;
+ }
+
+ if ('GPSInfoIFDPointer' in Tiff) {
+ offsets.gpsIFD = offsets.tiffHeader + Tiff.GPSInfoIFDPointer;
+ delete Tiff.GPSInfoIFDPointer;
+ }
+ return true;
+ }
+
+ // At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported
+ function setTag(ifd, tag, value) {
+ var offset, length, tagOffset, valueOffset = 0;
+
+ // If tag name passed translate into hex key
+ if (typeof(tag) === 'string') {
+ var tmpTags = tags[ifd.toLowerCase()];
+ for (var hex in tmpTags) {
+ if (tmpTags[hex] === tag) {
+ tag = hex;
+ break;
}
}
}
- } catch (e2) {
- isVersionSupported = false;
+ offset = offsets[ifd.toLowerCase() + 'IFD'];
+ length = data.SHORT(offset);
+
+ for (var i = 0; i < length; i++) {
+ tagOffset = offset + 12 * i + 2;
+
+ if (data.SHORT(tagOffset) == tag) {
+ valueOffset = tagOffset + 8;
+ break;
+ }
+ }
+
+ if (!valueOffset) {
+ return false;
+ }
+
+ data.LONG(valueOffset, value);
+ return true;
}
- return isVersionSupported;
+
+ // Public functions
+ return {
+ init: function(segment) {
+ // Reset internal data
+ offsets = {
+ tiffHeader: 10
+ };
+
+ if (segment === undefined || !segment.length) {
+ return false;
+ }
+
+ data.init(segment);
+
+ // Check if that's APP1 and that it has EXIF
+ if (data.SHORT(0) === 0xFFE1 && data.STRING(4, 5).toUpperCase() === "EXIF\0") {
+ return getIFDOffsets();
+ }
+ return false;
+ },
+
+ TIFF: function() {
+ return Tiff;
+ },
+
+ EXIF: function() {
+ var Exif;
+
+ // Populate EXIF hash
+ Exif = extractTags(offsets.exifIFD, tags.exif);
+
+ // Fix formatting of some tags
+ if (Exif.ExifVersion && Basic.typeOf(Exif.ExifVersion) === 'array') {
+ for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) {
+ exifVersion += String.fromCharCode(Exif.ExifVersion[i]);
+ }
+ Exif.ExifVersion = exifVersion;
+ }
+
+ return Exif;
+ },
+
+ GPS: function() {
+ var GPS;
+
+ GPS = extractTags(offsets.gpsIFD, tags.gps);
+
+ // iOS devices (and probably some others) do not put in GPSVersionID tag (why?..)
+ if (GPS.GPSVersionID && Basic.typeOf(GPS.GPSVersionID) === 'array') {
+ GPS.GPSVersionID = GPS.GPSVersionID.join('.');
+ }
+
+ return GPS;
+ },
+
+ setExif: function(tag, value) {
+ // Right now only setting of width/height is possible
+ if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') {return false;}
+
+ return setTag('exif', tag, value);
+ },
+
+
+ getBinary: function() {
+ return data.SEGMENT();
+ },
+
+ purge: function() {
+ data.init(null);
+ data = Tiff = null;
+ offsets = {};
+ }
+ };
+ };
+});
+
+// Included from: src/javascript/runtime/html5/image/JPEG.js
+
+/**
+ * JPEG.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/JPEG
+@private
+*/
+define("moxie/runtime/html5/image/JPEG", [
+ "moxie/core/utils/Basic",
+ "moxie/core/Exceptions",
+ "moxie/runtime/html5/image/JPEGHeaders",
+ "moxie/runtime/html5/utils/BinaryReader",
+ "moxie/runtime/html5/image/ExifParser"
+], function(Basic, x, JPEGHeaders, BinaryReader, ExifParser) {
+
+ function JPEG(binstr) {
+ var _binstr, _br, _hm, _ep, _info, hasExif;
+
+ function _getDimensions() {
+ var idx = 0, marker, length;
+
+ // examine all through the end, since some images might have very large APP segments
+ while (idx <= _binstr.length) {
+ marker = _br.SHORT(idx += 2);
+
+ if (marker >= 0xFFC0 && marker <= 0xFFC3) { // SOFn
+ idx += 5; // marker (2 bytes) + length (2 bytes) + Sample precision (1 byte)
+ return {
+ height: _br.SHORT(idx),
+ width: _br.SHORT(idx += 2)
+ };
+ }
+ length = _br.SHORT(idx += 2);
+ idx += length - 2;
+ }
+ return null;
+ }
+
+ _binstr = binstr;
+
+ _br = new BinaryReader();
+ _br.init(_binstr);
+
+ // check if it is jpeg
+ if (_br.SHORT(0) !== 0xFFD8) {
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+ }
+
+ // backup headers
+ _hm = new JPEGHeaders(binstr);
+
+ // extract exif info
+ _ep = new ExifParser();
+ hasExif = !!_ep.init(_hm.get('app1')[0]);
+
+ // get dimensions
+ _info = _getDimensions.call(this);
+
+ Basic.extend(this, {
+ type: 'image/jpeg',
+
+ size: _binstr.length,
+
+ width: _info && _info.width || 0,
+
+ height: _info && _info.height || 0,
+
+ setExif: function(tag, value) {
+ if (!hasExif) {
+ return false; // or throw an exception
+ }
+
+ if (Basic.typeOf(tag) === 'object') {
+ Basic.each(tag, function(value, tag) {
+ _ep.setExif(tag, value);
+ });
+ } else {
+ _ep.setExif(tag, value);
+ }
+
+ // update internal headers
+ _hm.set('app1', _ep.getBinary());
+ },
+
+ writeHeaders: function() {
+ if (!arguments.length) {
+ // if no arguments passed, update headers internally
+ return (_binstr = _hm.restore(_binstr));
+ }
+ return _hm.restore(arguments[0]);
+ },
+
+ stripHeaders: function(binstr) {
+ return _hm.strip(binstr);
+ },
+
+ purge: function() {
+ _purge.call(this);
+ }
+ });
+
+ if (hasExif) {
+ this.meta = {
+ tiff: _ep.TIFF(),
+ exif: _ep.EXIF(),
+ gps: _ep.GPS()
+ };
+ }
+
+ function _purge() {
+ if (!_ep || !_hm || !_br) {
+ return; // ignore any repeating purge requests
+ }
+ _ep.purge();
+ _hm.purge();
+ _br.init(null);
+ _binstr = _info = _hm = _ep = _br = null;
+ }
+ }
+
+ return JPEG;
+});
+
+// Included from: src/javascript/runtime/html5/image/PNG.js
+
+/**
+ * PNG.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/PNG
+@private
+*/
+define("moxie/runtime/html5/image/PNG", [
+ "moxie/core/Exceptions",
+ "moxie/core/utils/Basic",
+ "moxie/runtime/html5/utils/BinaryReader"
+], function(x, Basic, BinaryReader) {
+
+ function PNG(binstr) {
+ var _binstr, _br, _hm, _ep, _info;
+
+ _binstr = binstr;
+
+ _br = new BinaryReader();
+ _br.init(_binstr);
+
+ // check if it's png
+ (function() {
+ var idx = 0, i = 0
+ , signature = [0x8950, 0x4E47, 0x0D0A, 0x1A0A]
+ ;
+
+ for (i = 0; i < signature.length; i++, idx += 2) {
+ if (signature[i] != _br.SHORT(idx)) {
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+ }
+ }
+ }());
+
+ function _getDimensions() {
+ var chunk, idx;
+
+ chunk = _getChunkAt.call(this, 8);
+
+ if (chunk.type == 'IHDR') {
+ idx = chunk.start;
+ return {
+ width: _br.LONG(idx),
+ height: _br.LONG(idx += 4)
+ };
+ }
+ return null;
+ }
+
+ function _purge() {
+ if (!_br) {
+ return; // ignore any repeating purge requests
+ }
+ _br.init(null);
+ _binstr = _info = _hm = _ep = _br = null;
+ }
+
+ _info = _getDimensions.call(this);
+
+ Basic.extend(this, {
+ type: 'image/png',
+
+ size: _binstr.length,
+
+ width: _info.width,
+
+ height: _info.height,
+
+ purge: function() {
+ _purge.call(this);
+ }
+ });
+
+ // for PNG we can safely trigger purge automatically, as we do not keep any data for later
+ _purge.call(this);
+
+ function _getChunkAt(idx) {
+ var length, type, start, CRC;
+
+ length = _br.LONG(idx);
+ type = _br.STRING(idx += 4, 4);
+ start = idx += 4;
+ CRC = _br.LONG(idx + length);
+
+ return {
+ length: length,
+ type: type,
+ start: start,
+ CRC: CRC
+ };
+ }
+ }
+
+ return PNG;
+});
+
+// Included from: src/javascript/runtime/html5/image/ImageInfo.js
+
+/**
+ * ImageInfo.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/ImageInfo
+@private
+*/
+define("moxie/runtime/html5/image/ImageInfo", [
+ "moxie/core/utils/Basic",
+ "moxie/core/Exceptions",
+ "moxie/runtime/html5/image/JPEG",
+ "moxie/runtime/html5/image/PNG"
+], function(Basic, x, JPEG, PNG) {
+ /**
+ Optional image investigation tool for HTML5 runtime. Provides the following features:
+ - ability to distinguish image type (JPEG or PNG) by signature
+ - ability to extract image width/height directly from it's internals, without preloading in memory (fast)
+ - ability to extract APP headers from JPEGs (Exif, GPS, etc)
+ - ability to replace width/height tags in extracted JPEG headers
+ - ability to restore APP headers, that were for example stripped during image manipulation
+
+ @class ImageInfo
+ @constructor
+ @param {String} binstr Image source as binary string
+ */
+ return function(binstr) {
+ var _cs = [JPEG, PNG], _img;
+
+ // figure out the format, throw: ImageError.WRONG_FORMAT if not supported
+ _img = (function() {
+ for (var i = 0; i < _cs.length; i++) {
+ try {
+ return new _cs[i](binstr);
+ } catch (ex) {
+ // console.info(ex);
+ }
+ }
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+ }());
+
+ Basic.extend(this, {
+ /**
+ Image Mime Type extracted from it's depths
+
+ @property type
+ @type {String}
+ @default ''
+ */
+ type: '',
+
+ /**
+ Image size in bytes
+
+ @property size
+ @type {Number}
+ @default 0
+ */
+ size: 0,
+
+ /**
+ Image width extracted from image source
+
+ @property width
+ @type {Number}
+ @default 0
+ */
+ width: 0,
+
+ /**
+ Image height extracted from image source
+
+ @property height
+ @type {Number}
+ @default 0
+ */
+ height: 0,
+
+ /**
+ Sets Exif tag. Currently applicable only for width and height tags. Obviously works only with JPEGs.
+
+ @method setExif
+ @param {String} tag Tag to set
+ @param {Mixed} value Value to assign to the tag
+ */
+ setExif: function() {},
+
+ /**
+ Restores headers to the source.
+
+ @method writeHeaders
+ @param {String} data Image source as binary string
+ @return {String} Updated binary string
+ */
+ writeHeaders: function(data) {
+ return data;
+ },
+
+ /**
+ Strip all headers from the source.
+
+ @method stripHeaders
+ @param {String} data Image source as binary string
+ @return {String} Updated binary string
+ */
+ stripHeaders: function(data) {
+ return data;
+ },
+
+ /**
+ Dispose resources.
+
+ @method purge
+ */
+ purge: function() {}
+ });
+
+ Basic.extend(this, _img);
+
+ this.purge = function() {
+ _img.purge();
+ _img = null;
+ };
+ };
+});
+
+// Included from: src/javascript/runtime/html5/image/MegaPixel.js
+
+/**
+(The MIT License)
+
+Copyright (c) 2012 Shinichi Tomita
;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+ * Mega pixel image rendering library for iOS6 Safari
+ *
+ * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel),
+ * which causes unexpected subsampling when drawing it in canvas.
+ * By using this library, you can safely render the image with proper stretching.
+ *
+ * Copyright (c) 2012 Shinichi Tomita
+ * Released under the MIT license
+ */
+
+/**
+@class moxie/runtime/html5/image/MegaPixel
+@private
+*/
+define("moxie/runtime/html5/image/MegaPixel", [], function() {
+
+ /**
+ * Rendering image element (with resizing) into the canvas element
+ */
+ function renderImageToCanvas(img, canvas, options) {
+ var iw = img.naturalWidth, ih = img.naturalHeight;
+ var width = options.width, height = options.height;
+ var x = options.x || 0, y = options.y || 0;
+ var ctx = canvas.getContext('2d');
+ if (detectSubsampling(img)) {
+ iw /= 2;
+ ih /= 2;
+ }
+ var d = 1024; // size of tiling canvas
+ var tmpCanvas = document.createElement('canvas');
+ tmpCanvas.width = tmpCanvas.height = d;
+ var tmpCtx = tmpCanvas.getContext('2d');
+ var vertSquashRatio = detectVerticalSquash(img, iw, ih);
+ var sy = 0;
+ while (sy < ih) {
+ var sh = sy + d > ih ? ih - sy : d;
+ var sx = 0;
+ while (sx < iw) {
+ var sw = sx + d > iw ? iw - sx : d;
+ tmpCtx.clearRect(0, 0, d, d);
+ tmpCtx.drawImage(img, -sx, -sy);
+ var dx = (sx * width / iw + x) << 0;
+ var dw = Math.ceil(sw * width / iw);
+ var dy = (sy * height / ih / vertSquashRatio + y) << 0;
+ var dh = Math.ceil(sh * height / ih / vertSquashRatio);
+ ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh);
+ sx += d;
+ }
+ sy += d;
+ }
+ tmpCanvas = tmpCtx = null;
}
/**
- Constructor for the Silverlight Runtime
+ * Detect subsampling in loaded image.
+ * In iOS, larger images than 2M pixels may be subsampled in rendering.
+ */
+ function detectSubsampling(img) {
+ var iw = img.naturalWidth, ih = img.naturalHeight;
+ if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image
+ var canvas = document.createElement('canvas');
+ canvas.width = canvas.height = 1;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, -iw + 1, 0);
+ // subsampled image becomes half smaller in rendering size.
+ // check alpha channel value to confirm image is covering edge pixel or not.
+ // if alpha value is 0 image is not covering, hence subsampled.
+ return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
+ } else {
+ return false;
+ }
+ }
- @class SilverlightRuntime
- @extends Runtime
- */
- function SilverlightRuntime(options) {
- var I = this, initTimer;
- options = Basic.extend({ xap_url: Env.xap_url }, options);
+ /**
+ * Detecting vertical squash in loaded image.
+ * Fixes a bug which squash image vertically while drawing into canvas for some images.
+ */
+ function detectVerticalSquash(img, iw, ih) {
+ var canvas = document.createElement('canvas');
+ canvas.width = 1;
+ canvas.height = ih;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0);
+ var data = ctx.getImageData(0, 0, 1, ih).data;
+ // search image edge pixel position in case it is squashed vertically.
+ var sy = 0;
+ var ey = ih;
+ var py = ih;
+ while (py > sy) {
+ var alpha = data[(py - 1) * 4 + 3];
+ if (alpha === 0) {
+ ey = py;
+ } else {
+ sy = py;
+ }
+ py = (ey + sy) >> 1;
+ }
+ canvas = null;
+ var ratio = (py / ih);
+ return (ratio === 0) ? 1 : ratio;
+ }
- Runtime.call(this, options, type, {
- access_binary: Runtime.capTrue,
- access_image_binary: Runtime.capTrue,
- display_media: Runtime.capTrue,
- do_cors: Runtime.capTrue,
- drag_and_drop: false,
- report_upload_progress: Runtime.capTrue,
- resize_image: Runtime.capTrue,
- return_response_headers: function(value) {
- return value && I.mode === 'client';
- },
- return_response_type: function(responseType) {
- if (responseType !== 'json') {
- return true;
+ return {
+ isSubsampled: detectSubsampling,
+ renderTo: renderImageToCanvas
+ };
+});
+
+// Included from: src/javascript/runtime/html5/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/Image
+@private
+*/
+define("moxie/runtime/html5/image/Image", [
+ "moxie/runtime/html5/Runtime",
+ "moxie/core/utils/Basic",
+ "moxie/core/Exceptions",
+ "moxie/core/utils/Encode",
+ "moxie/file/File",
+ "moxie/runtime/html5/image/ImageInfo",
+ "moxie/runtime/html5/image/MegaPixel",
+ "moxie/core/utils/Mime",
+ "moxie/core/utils/Env"
+], function(extensions, Basic, x, Encode, File, ImageInfo, MegaPixel, Mime, Env) {
+
+ function HTML5Image() {
+ var me = this
+ , _img, _imgInfo, _canvas, _binStr, _blob
+ , _modified = false // is set true whenever image is modified
+ , _preserveHeaders = true
+ ;
+
+ Basic.extend(this, {
+ loadFromBlob: function(blob) {
+ var comp = this, I = comp.getRuntime()
+ , asBinary = arguments.length > 1 ? arguments[1] : true
+ ;
+
+ if (!I.can('access_binary')) {
+ throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+ }
+
+ _blob = blob;
+
+ if (blob.isDetached()) {
+ _binStr = blob.getSource();
+ _preload.call(this, _binStr);
+ return;
} else {
- return !!window.JSON;
+ _readAsDataUrl.call(this, blob.getSource(), function(dataUrl) {
+ if (asBinary) {
+ _binStr = _toBinary(dataUrl);
+ }
+ _preload.call(comp, dataUrl);
+ });
}
},
- return_status_code: function(code) {
- return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]);
+
+ loadFromImage: function(img, exact) {
+ this.meta = img.meta;
+
+ _blob = new File(null, {
+ name: img.name,
+ size: img.size,
+ type: img.type
+ });
+
+ _preload.call(this, exact ? (_binStr = img.getAsBinaryString()) : img.getAsDataURL());
},
- select_file: Runtime.capTrue,
- select_multiple: Runtime.capTrue,
- send_binary_string: Runtime.capTrue,
- send_browser_cookies: function(value) {
- return value && I.mode === 'browser';
+
+ getInfo: function() {
+ var I = this.getRuntime(), info;
+
+ if (!_imgInfo && _binStr && I.can('access_image_binary')) {
+ _imgInfo = new ImageInfo(_binStr);
+ }
+
+ info = {
+ width: _getImg().width || 0,
+ height: _getImg().height || 0,
+ type: _blob.type || Mime.getFileMime(_blob.name),
+ size: _binStr && _binStr.length || _blob.size || 0,
+ name: _blob.name || '',
+ meta: _imgInfo && _imgInfo.meta || this.meta || {}
+ };
+
+ return info;
},
- send_custom_headers: function(value) {
- return value && I.mode === 'client';
+
+ downsize: function() {
+ _downsize.apply(this, arguments);
},
- send_multipart: Runtime.capTrue,
- slice_blob: Runtime.capTrue,
- stream_upload: true,
- summon_file_dialog: false,
- upload_filesize: Runtime.capTrue,
- use_http_method: function(methods) {
- return I.mode === 'client' || !Basic.arrayDiff(methods, ['GET', 'POST']);
- }
- }, {
- // capabilities that require specific mode
- return_response_headers: function(value) {
- return value ? 'client' : 'browser';
+
+ getAsCanvas: function() {
+ if (_canvas) {
+ _canvas.id = this.uid + '_canvas';
+ }
+ return _canvas;
},
- return_status_code: function(code) {
- return Basic.arrayDiff(code, [200, 404]) ? 'client' : ['client', 'browser'];
+
+ getAsBlob: function(type, quality) {
+ if (type !== this.type) {
+ // if different mime type requested prepare image for conversion
+ _downsize.call(this, this.width, this.height, false);
+ }
+ return new File(null, {
+ name: _blob.name || '',
+ type: type,
+ data: me.getAsBinaryString.call(this, type, quality)
+ });
},
- send_browser_cookies: function(value) {
- return value ? 'browser' : 'client';
+
+ getAsDataURL: function(type) {
+ var quality = arguments[1] || 90;
+
+ // if image has not been modified, return the source right away
+ if (!_modified) {
+ return _img.src;
+ }
+
+ if ('image/jpeg' !== type) {
+ return _canvas.toDataURL('image/png');
+ } else {
+ try {
+ // older Geckos used to result in an exception on quality argument
+ return _canvas.toDataURL('image/jpeg', quality/100);
+ } catch (ex) {
+ return _canvas.toDataURL('image/jpeg');
+ }
+ }
},
- send_custom_headers: function(value) {
- return value ? 'client' : 'browser';
+
+ getAsBinaryString: function(type, quality) {
+ // if image has not been modified, return the source right away
+ if (!_modified) {
+ // if image was not loaded from binary string
+ if (!_binStr) {
+ _binStr = _toBinary(me.getAsDataURL(type, quality));
+ }
+ return _binStr;
+ }
+
+ if ('image/jpeg' !== type) {
+ _binStr = _toBinary(me.getAsDataURL(type, quality));
+ } else {
+ var dataUrl;
+
+ // if jpeg
+ if (!quality) {
+ quality = 90;
+ }
+
+ try {
+ // older Geckos used to result in an exception on quality argument
+ dataUrl = _canvas.toDataURL('image/jpeg', quality/100);
+ } catch (ex) {
+ dataUrl = _canvas.toDataURL('image/jpeg');
+ }
+
+ _binStr = _toBinary(dataUrl);
+
+ if (_imgInfo) {
+ _binStr = _imgInfo.stripHeaders(_binStr);
+
+ if (_preserveHeaders) {
+ // update dimensions info in exif
+ if (_imgInfo.meta && _imgInfo.meta.exif) {
+ _imgInfo.setExif({
+ PixelXDimension: this.width,
+ PixelYDimension: this.height
+ });
+ }
+
+ // re-inject the headers
+ _binStr = _imgInfo.writeHeaders(_binStr);
+ }
+
+ // will be re-created from fresh on next getInfo call
+ _imgInfo.purge();
+ _imgInfo = null;
+ }
+ }
+
+ _modified = false;
+
+ return _binStr;
},
- use_http_method: function(methods) {
- return Basic.arrayDiff(methods, ['GET', 'POST']) ? 'client' : ['client', 'browser'];
+
+ destroy: function() {
+ me = null;
+ _purge.call(this);
+ this.getRuntime().getShim().removeInstance(this.uid);
}
});
- // minimal requirement
- if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') {
- this.mode = false;
+ function _getImg() {
+ if (!_canvas && !_img) {
+ throw new x.ImageError(x.DOMException.INVALID_STATE_ERR);
+ }
+ return _canvas || _img;
}
- Basic.extend(this, {
- getShim: function() {
- return Dom.get(this.uid).content.Moxie;
- },
+ function _toBinary(str) {
+ return Encode.atob(str.substring(str.indexOf('base64,') + 7));
+ }
- shimExec: function(component, action) {
- var args = [].slice.call(arguments, 2);
- return I.getShim().exec(this.uid, component, action, args);
- },
- init : function() {
- var container;
+ function _toDataUrl(str, type) {
+ return 'data:' + (type || '') + ';base64,' + Encode.btoa(str);
+ }
- container = this.getShimContainer();
- container.innerHTML = '';
+ function _preload(str) {
+ var comp = this;
- // Init is dispatched by the shim
- initTimer = setTimeout(function() {
- if (I && !I.initialized) { // runtime might be already destroyed by this moment
- I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
- }
- }, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac)
- },
+ _img = new Image();
+ _img.onerror = function() {
+ _purge.call(this);
+ comp.trigger('error', x.ImageError.WRONG_FORMAT);
+ };
+ _img.onload = function() {
+ comp.trigger('load');
+ };
- destroy: (function(destroy) { // extend default destroy method
- return function() {
- destroy.call(I);
- clearTimeout(initTimer); // initialization check might be still onwait
- options = initTimer = destroy = I = null;
+ _img.src = /^data:[^;]*;base64,/.test(str) ? str : _toDataUrl(str, _blob.type);
+ }
+
+
+ function _readAsDataUrl(file, callback) {
+ var comp = this, fr;
+
+ // use FileReader if it's available
+ if (window.FileReader) {
+ fr = new FileReader();
+ fr.onload = function() {
+ callback(this.result);
};
- }(this.destroy))
+ fr.onerror = function() {
+ comp.trigger('error', x.ImageError.WRONG_FORMAT);
+ };
+ fr.readAsDataURL(file);
+ } else {
+ return callback(file.getAsDataURL());
+ }
+ }
- }, extensions);
+ function _downsize(width, height, crop, preserveHeaders) {
+ var self = this
+ , scale
+ , mathFn
+ , x = 0
+ , y = 0
+ , img
+ , destWidth
+ , destHeight
+ , orientation
+ ;
+
+ _preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString())
+
+ // take into account orientation tag
+ orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1;
+
+ if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation
+ // swap dimensions
+ var tmp = width;
+ width = height;
+ height = tmp;
+ }
+
+ img = _getImg();
+
+ // unify dimensions
+ if (!crop) {
+ scale = Math.min(width/img.width, height/img.height);
+ } else {
+ // one of the dimensions may exceed the actual image dimensions - we need to take the smallest value
+ width = Math.min(width, img.width);
+ height = Math.min(height, img.height);
+
+ scale = Math.max(width/img.width, height/img.height);
+ }
+
+ // we only downsize here
+ if (scale > 1 && !crop && preserveHeaders) {
+ this.trigger('Resize');
+ return;
+ }
+
+ // prepare canvas if necessary
+ if (!_canvas) {
+ _canvas = document.createElement("canvas");
+ }
+
+ // calculate dimensions of proportionally resized image
+ destWidth = Math.round(img.width * scale);
+ destHeight = Math.round(img.height * scale);
+
+ // scale image and canvas
+ if (crop) {
+ _canvas.width = width;
+ _canvas.height = height;
+
+ // if dimensions of the resulting image still larger than canvas, center it
+ if (destWidth > width) {
+ x = Math.round((destWidth - width) / 2);
+ }
+
+ if (destHeight > height) {
+ y = Math.round((destHeight - height) / 2);
+ }
+ } else {
+ _canvas.width = destWidth;
+ _canvas.height = destHeight;
+ }
+
+ // rotate if required, according to orientation tag
+ if (!_preserveHeaders) {
+ _rotateToOrientaion(_canvas.width, _canvas.height, orientation);
+ }
+
+ _drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight);
+
+ this.width = _canvas.width;
+ this.height = _canvas.height;
+
+ _modified = true;
+ self.trigger('Resize');
+ }
+
+
+ function _drawToCanvas(img, canvas, x, y, w, h) {
+ if (Env.OS === 'iOS') {
+ // avoid squish bug in iOS6
+ MegaPixel.renderTo(img, canvas, { width: w, height: h, x: x, y: y });
+ } else {
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, x, y, w, h);
+ }
+ }
+
+
+ /**
+ * Transform canvas coordination according to specified frame size and orientation
+ * Orientation value is from EXIF tag
+ * @author Shinichi Tomita
+ */
+ function _rotateToOrientaion(width, height, orientation) {
+ switch (orientation) {
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ _canvas.width = height;
+ _canvas.height = width;
+ break;
+ default:
+ _canvas.width = width;
+ _canvas.height = height;
+ }
+
+ /**
+ 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
+ 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
+ 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
+ 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
+ 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
+ 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
+ 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
+ 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
+ */
+
+ var ctx = _canvas.getContext('2d');
+ switch (orientation) {
+ case 2:
+ // horizontal flip
+ ctx.translate(width, 0);
+ ctx.scale(-1, 1);
+ break;
+ case 3:
+ // 180 rotate left
+ ctx.translate(width, height);
+ ctx.rotate(Math.PI);
+ break;
+ case 4:
+ // vertical flip
+ ctx.translate(0, height);
+ ctx.scale(1, -1);
+ break;
+ case 5:
+ // vertical flip + 90 rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.scale(1, -1);
+ break;
+ case 6:
+ // 90 rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.translate(0, -height);
+ break;
+ case 7:
+ // horizontal flip + 90 rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.translate(width, -height);
+ ctx.scale(-1, 1);
+ break;
+ case 8:
+ // 90 rotate left
+ ctx.rotate(-0.5 * Math.PI);
+ ctx.translate(-width, 0);
+ break;
+ }
+ }
+
+
+ function _purge() {
+ if (_imgInfo) {
+ _imgInfo.purge();
+ _imgInfo = null;
+ }
+ _binStr = _img = _canvas = _blob = null;
+ _modified = false;
+ }
}
- Runtime.addConstructor(type, SilverlightRuntime);
-
- return extensions;
+ return (extensions.Image = HTML5Image);
});
-// Included from: src/javascript/runtime/silverlight/file/Blob.js
+// Included from: src/javascript/runtime/html4/image/Image.js
/**
- * Blob.js
+ * Image.js
*
* Copyright 2013, Moxiecode Systems AB
* Released under GPL License.
@@ -7058,129 +8508,17 @@ define("moxie/runtime/silverlight/Runtime", [
*/
/**
-@class moxie/runtime/silverlight/file/Blob
+@class moxie/runtime/html4/image/Image
@private
*/
-define("moxie/runtime/silverlight/file/Blob", [
- "moxie/runtime/silverlight/Runtime",
- "moxie/core/utils/Basic",
- "moxie/runtime/flash/file/Blob"
-], function(extensions, Basic, Blob) {
- return (extensions.Blob = Basic.extend({}, Blob));
+define("moxie/runtime/html4/image/Image", [
+ "moxie/runtime/html4/Runtime",
+ "moxie/runtime/html5/image/Image"
+], function(extensions, Image) {
+ return (extensions.Image = Image);
});
-// Included from: src/javascript/runtime/silverlight/file/FileInput.js
-
-/**
- * FileInput.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/file/FileInput
-@private
-*/
-define("moxie/runtime/silverlight/file/FileInput", [
- "moxie/runtime/silverlight/Runtime"
-], function(extensions) {
-
- var FileInput = {
- init: function(options) {
-
- function toFilters(accept) {
- var filter = '';
- for (var i = 0; i < accept.length; i++) {
- filter += (filter !== '' ? '|' : '') + accept[i].title + " | *." + accept[i].extensions.replace(/,/g, ';*.');
- }
- return filter;
- }
-
- this.getRuntime().shimExec.call(this, 'FileInput', 'init', toFilters(options.accept), options.name, options.multiple);
- this.trigger('ready');
- }
- };
-
- return (extensions.FileInput = FileInput);
-});
-
-// Included from: src/javascript/runtime/silverlight/file/FileReader.js
-
-/**
- * FileReader.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/file/FileReader
-@private
-*/
-define("moxie/runtime/silverlight/file/FileReader", [
- "moxie/runtime/silverlight/Runtime",
- "moxie/core/utils/Basic",
- "moxie/runtime/flash/file/FileReader"
-], function(extensions, Basic, FileReader) {
- return (extensions.FileReader = Basic.extend({}, FileReader));
-});
-
-// Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js
-
-/**
- * FileReaderSync.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/file/FileReaderSync
-@private
-*/
-define("moxie/runtime/silverlight/file/FileReaderSync", [
- "moxie/runtime/silverlight/Runtime",
- "moxie/core/utils/Basic",
- "moxie/runtime/flash/file/FileReaderSync"
-], function(extensions, Basic, FileReaderSync) {
- return (extensions.FileReaderSync = Basic.extend({}, FileReaderSync));
-});
-
-// Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js
-
-/**
- * XMLHttpRequest.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/xhr/XMLHttpRequest
-@private
-*/
-define("moxie/runtime/silverlight/xhr/XMLHttpRequest", [
- "moxie/runtime/silverlight/Runtime",
- "moxie/core/utils/Basic",
- "moxie/runtime/flash/xhr/XMLHttpRequest"
-], function(extensions, Basic, XMLHttpRequest) {
- return (extensions.XMLHttpRequest = Basic.extend({}, XMLHttpRequest));
-});
-
-expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/core/utils/Events"]);
+expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"]);
})(this);/**
* o.js
*
@@ -7231,477 +8569,3 @@ Globally exposed namespace with the most frequently used public classes and hand
}
return o;
})(this);
-;webshim.register('filereader', function($, webshim, window, document, undefined, featureOptions){
- "use strict";
- var mOxie, moxie, hasXDomain;
- var FormData = $.noop;
- var sel = 'input[type="file"].ws-filereader';
- var loadMoxie = function (){
- webshim.loader.loadList(['moxie']);
- };
- var _createFilePicker = function(){
- var $input, picker, $parent, onReset;
- var input = this;
-
- if(webshim.implement(input, 'filepicker')){
-
- input = this;
- $input = $(this);
- $parent = $input.parent();
- onReset = function(){
- if(!input.value){
- $input.prop('value', '');
- }
- };
-
- $input.attr('tabindex', '-1').on('mousedown.filereaderwaiting click.filereaderwaiting', false);
- $parent.addClass('ws-loading');
- picker = new mOxie.FileInput({
- browse_button: this,
- accept: $.prop(this, 'accept'),
- multiple: $.prop(this, 'multiple')
- });
-
- $input.jProp('form').on('reset', function(){
- setTimeout(onReset);
- });
- picker.onready = function(){
- $input.off('.fileraderwaiting');
- $parent.removeClass('ws-waiting');
- };
-
- picker.onchange = function(e){
- webshim.data(input, 'fileList', e.target.files);
- $input.trigger('change');
- };
- picker.onmouseenter = function(){
- $input.trigger('mouseover');
- $parent.addClass('ws-mouseenter');
- };
- picker.onmouseleave = function(){
- $input.trigger('mouseout');
- $parent.removeClass('ws-mouseenter');
- };
- picker.onmousedown = function(){
- $input.trigger('mousedown');
- $parent.addClass('ws-active');
- };
- picker.onmouseup = function(){
- $input.trigger('mouseup');
- $parent.removeClass('ws-active');
- };
-
- webshim.data(input, 'filePicker', picker);
-
- webshim.ready('WINDOWLOAD', function(){
- var lastWidth;
- $input.onWSOff('updateshadowdom', function(){
- var curWitdth = input.offsetWidth;
- if(curWitdth && lastWidth != curWitdth){
- lastWidth = curWitdth;
- picker.refresh();
- }
- });
- });
-
- webshim.addShadowDom();
-
- picker.init();
- if(input.disabled){
- picker.disable(true);
- }
- }
- };
- var getFileNames = function(file){
- return file.name;
- };
- var createFilePicker = function(){
- var elem = this;
- loadMoxie();
- $(elem)
- .on('mousedown.filereaderwaiting click.filereaderwaiting', false)
- .parent()
- .addClass('ws-loading')
- ;
- webshim.ready('moxie', function(){
- createFilePicker.call(elem);
- });
- };
- var noxhr = /^(?:script|jsonp)$/i;
- var notReadyYet = function(){
- loadMoxie();
- webshim.error('filereader/formdata not ready yet. please wait for moxie to load `webshim.ready("moxie", callbackFn);`` or wait for the first change event on input[type="file"].ws-filereader.')
- };
- var inputValueDesc = webshim.defineNodeNameProperty('input', 'value', {
- prop: {
- get: function(){
- var fileList = webshim.data(this, 'fileList');
-
- if(fileList && fileList.map){
- return fileList.map(getFileNames).join(', ');
- }
-
- return inputValueDesc.prop._supget.call(this);
- }
- }
- }
- );
- var shimMoxiePath = webshim.cfg.basePath+'moxie/';
- var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf/moxie.xap on your server an configure filereader options: "swfpath"/"xappath"';
- var testMoxie = function(options){
- return (options.wsType == 'moxie' || (options.data && options.data instanceof mOxie.FormData) || (options.crossDomain && $.support.cors !== false && hasXDomain != 'no' && !noxhr.test(options.dataType || '')));
- };
- var createMoxieTransport = function (options){
-
- if(testMoxie(options)){
- var ajax;
- webshim.info('moxie transfer used for $.ajax');
- if(hasXDomain == 'no'){
- webshim.error(crossXMLMessage);
- }
- return {
- send: function( headers, completeCallback ) {
-
- var proressEvent = function(obj, name){
- if(options[name]){
- var called = false;
- ajax.addEventListener('load', function(e){
- if(!called){
- options[name]({type: 'progress', lengthComputable: true, total: 1, loaded: 1});
- } else if(called.lengthComputable && called.total > called.loaded){
- options[name]({type: 'progress', lengthComputable: true, total: called.total, loaded: called.total});
- }
- });
- obj.addEventListener('progress', function(e){
- called = e;
- options[name](e);
- });
- }
- };
- ajax = new moxie.xhr.XMLHttpRequest();
-
- ajax.open(options.type, options.url, options.async, options.username, options.password);
-
- proressEvent(ajax.upload, featureOptions.uploadprogress);
- proressEvent(ajax.upload, featureOptions.progress);
-
- ajax.addEventListener('load', function(e){
- var responses = {
- text: ajax.responseText,
- xml: ajax.responseXML
- };
- completeCallback(ajax.status, ajax.statusText, responses, ajax.getAllResponseHeaders());
- });
-
- if(options.xhrFields && options.xhrFields.withCredentials){
- ajax.withCredentials = true;
- }
-
- if(options.timeout){
- ajax.timeout = options.timeout;
- }
-
- $.each(headers, function(name, value){
- ajax.setRequestHeader(name, value);
- });
-
-
- ajax.send(options.data);
-
- },
- abort: function() {
- if(ajax){
- ajax.abort();
- }
- }
- };
- }
- };
- var transports = {
- //based on script: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest
- xdomain: (function(){
- var httpRegEx = /^https?:\/\//i;
- var getOrPostRegEx = /^get|post$/i;
- var sameSchemeRegEx = new RegExp('^'+location.protocol, 'i');
- return function(options, userOptions, jqXHR) {
-
- // Only continue if the request is: asynchronous, uses GET or POST method, has HTTP or HTTPS protocol, and has the same scheme as the calling page
- if (!options.crossDomain || options.username || (options.xhrFields && options.xhrFields.withCredentials) || !options.async || !getOrPostRegEx.test(options.type) || !httpRegEx.test(options.url) || !sameSchemeRegEx.test(options.url) || (options.data && options.data instanceof mOxie.FormData) || noxhr.test(options.dataType || '')) {
- return;
- }
-
- var xdr = null;
- webshim.info('xdomain transport used.');
-
- return {
- send: function(headers, complete) {
- var postData = '';
- var userType = (userOptions.dataType || '').toLowerCase();
-
- xdr = new XDomainRequest();
- if (/^\d+$/.test(userOptions.timeout)) {
- xdr.timeout = userOptions.timeout;
- }
-
- xdr.ontimeout = function() {
- complete(500, 'timeout');
- };
-
- xdr.onload = function() {
- var allResponseHeaders = 'Content-Length: ' + xdr.responseText.length + '\r\nContent-Type: ' + xdr.contentType;
- var status = {
- code: xdr.status || 200,
- message: xdr.statusText || 'OK'
- };
- var responses = {
- text: xdr.responseText,
- xml: xdr.responseXML
- };
- try {
- if (userType === 'html' || /text\/html/i.test(xdr.contentType)) {
- responses.html = xdr.responseText;
- } else if (userType === 'json' || (userType !== 'text' && /\/json/i.test(xdr.contentType))) {
- try {
- responses.json = $.parseJSON(xdr.responseText);
- } catch(e) {
-
- }
- } else if (userType === 'xml' && !xdr.responseXML) {
- var doc;
- try {
- doc = new ActiveXObject('Microsoft.XMLDOM');
- doc.async = false;
- doc.loadXML(xdr.responseText);
- } catch(e) {
-
- }
-
- responses.xml = doc;
- }
- } catch(parseMessage) {}
- complete(status.code, status.message, responses, allResponseHeaders);
- };
-
- // set an empty handler for 'onprogress' so requests don't get aborted
- xdr.onprogress = function(){};
- xdr.onerror = function() {
- complete(500, 'error', {
- text: xdr.responseText
- });
- };
-
- if (userOptions.data) {
- postData = ($.type(userOptions.data) === 'string') ? userOptions.data : $.param(userOptions.data);
- }
- xdr.open(options.type, options.url);
- xdr.send(postData);
- },
- abort: function() {
- if (xdr) {
- xdr.abort();
- }
- }
- };
- };
- })(),
- moxie: function (options, originalOptions, jqXHR){
- if(testMoxie(options)){
- loadMoxie(options);
- var ajax;
-
- var tmpTransport = {
- send: function( headers, completeCallback ) {
- ajax = true;
- webshim.ready('moxie', function(){
- if(ajax){
- ajax = createMoxieTransport(options, originalOptions, jqXHR);
- tmpTransport.send = ajax.send;
- tmpTransport.abort = ajax.abort;
- ajax.send(headers, completeCallback);
- }
- });
- },
- abort: function() {
- ajax = false;
- }
- };
- return tmpTransport;
- }
- }
- };
-
- if(!featureOptions.progress){
- featureOptions.progress = 'onprogress';
- }
-
- if(!featureOptions.uploadprogress){
- featureOptions.uploadprogress = 'onuploadprogress';
- }
-
- if(!featureOptions.swfpath){
- featureOptions.swfpath = shimMoxiePath+'flash/Moxie.min.swf';
- }
- if(!featureOptions.xappath){
- featureOptions.xappath = shimMoxiePath+'silverlight/Moxie.min.xap';
- }
-
- if($.support.cors !== false || !window.XDomainRequest){
- delete transports.xdomain;
- }
-
-
- $.ajaxTransport("+*", function( options, originalOptions, jqXHR ) {
- var ajax, type;
-
- if(options.wsType || transports[transports]){
- ajax = transports[transports](options, originalOptions, jqXHR);
- }
- if(!ajax){
- for(type in transports){
- ajax = transports[type](options, originalOptions, jqXHR);
- if(ajax){break;}
- }
- }
- return ajax;
- });
-
- webshim.defineNodeNameProperty('input', 'files', {
- prop: {
- writeable: false,
- get: function(){
- if(this.type != 'file'){return null;}
- if(!$(this).hasClass('ws-filereader')){
- webshim.info("please add the 'ws-filereader' class to your input[type='file'] to implement files-property");
- }
- return webshim.data(this, 'fileList') || [];
- }
- }
- }
- );
-
- webshim.reflectProperties(['input'], ['accept']);
-
- if($('').prop('multiple') == null){
- webshim.defineNodeNamesBooleanProperty(['input'], ['multiple']);
- }
-
- webshim.onNodeNamesPropertyModify('input', 'disabled', function(value, boolVal, type){
- var picker = webshim.data(this, 'filePicker');
- if(picker){
- picker.disable(boolVal);
- }
- });
-
- webshim.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){
- if(value === '' && this.type == 'file' && $(this).hasClass('ws-filereader')){
- webshim.data(this, 'fileList', []);
- }
- });
-
-
- window.FileReader = notReadyYet;
- window.FormData = notReadyYet;
- webshim.ready('moxie', function(){
- var wsMimes = 'application/xml,xml';
- moxie = window.moxie;
- mOxie = window.mOxie;
-
- mOxie.Env.swf_url = featureOptions.swfpath;
- mOxie.Env.xap_url = featureOptions.xappath;
-
- window.FileReader = mOxie.FileReader;
-
- window.FormData = function(form){
- var appendData, i, len, files, fileI, fileLen, inputName;
- var moxieData = new mOxie.FormData();
- if(form && $.nodeName(form, 'form')){
- appendData = $(form).serializeArray();
- for(i = 0; i < appendData.length; i++){
- if(Array.isArray(appendData[i].value)){
- appendData[i].value.forEach(function(val){
- moxieData.append(appendData[i].name, val);
- });
- } else {
- moxieData.append(appendData[i].name, appendData[i].value);
- }
- }
-
- appendData = form.querySelectorAll('input[type="file"][name]');
-
- for(i = 0, len = appendData.length; i < appendData.length; i++){
- inputName = appendData[i].name;
- if(inputName && !$(appendData[i]).is(':disabled')){
- files = $.prop(appendData[i], 'files') || [];
- if(files.length){
- if(files.length > 1 || (moxieData.hasBlob && moxieData.hasBlob())){
- webshim.error('FormData shim can only handle one file per ajax. Use multiple ajax request. One per file.');
- }
- for(fileI = 0, fileLen = files.length; fileI < fileLen; fileI++){
- moxieData.append(inputName, files[fileI]);
- }
- }
- }
- }
- }
-
- return moxieData;
- };
- FormData = window.FormData;
-
- createFilePicker = _createFilePicker;
- transports.moxie = createMoxieTransport;
-
- featureOptions.mimeTypes = (featureOptions.mimeTypes) ? wsMimes+','+featureOptions.mimeTypes : wsMimes;
- try {
- mOxie.Mime.addMimeType(featureOptions.mimeTypes);
- } catch(e){
- webshim.warn('mimetype to moxie error: '+e);
- }
-
- });
-
- webshim.addReady(function(context, contextElem){
- $(context.querySelectorAll(sel)).add(contextElem.filter(sel)).each(createFilePicker);
- });
- webshim.ready('WINDOWLOAD', loadMoxie);
-
- if(webshim.cfg.debug !== false && featureOptions.swfpath.indexOf((location.protocol+'//'+location.hostname)) && featureOptions.swfpath.indexOf(('https://'+location.hostname))){
- webshim.ready('WINDOWLOAD', function(){
-
- var printMessage = function(){
- if(hasXDomain == 'no'){
- webshim.error(crossXMLMessage);
- }
- };
-
- try {
- hasXDomain = sessionStorage.getItem('wsXdomain.xml');
- } catch(e){}
- printMessage();
- if(hasXDomain == null){
- try {
- $.ajax({
- url: 'crossdomain.xml',
- type: 'HEAD',
- dataType: 'xml',
- success: function(){
- hasXDomain = 'yes';
- },
- error: function(){
- hasXDomain = 'no';
- },
- complete: function(){
- try {
- sessionStorage.setItem('wsXdomain.xml', hasXDomain);
- } catch(e){}
- printMessage();
- }
- });
- } catch(e){}
- }
- });
- }
- if(document.readyState == 'complete'){
- webshims.isReady('WINDOWLOAD', true);
- }
-});
diff --git a/public/webshims/shims/moxie/js/moxie.js b/public/webshims/shims/moxie/js/moxie-swf.js
similarity index 81%
rename from public/webshims/shims/moxie/js/moxie.js
rename to public/webshims/shims/moxie/js/moxie-swf.js
index 500fb2cd..d5fd8281 100644
--- a/public/webshims/shims/moxie/js/moxie.js
+++ b/public/webshims/shims/moxie/js/moxie-swf.js
@@ -5131,6 +5131,749 @@ define("moxie/xhr/XMLHttpRequest", [
return XMLHttpRequest;
});
+// Included from: src/javascript/runtime/Transporter.js
+
+/**
+ * Transporter.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/runtime/Transporter", [
+ "moxie/core/utils/Basic",
+ "moxie/core/utils/Encode",
+ "moxie/runtime/RuntimeClient",
+ "moxie/core/EventTarget"
+], function(Basic, Encode, RuntimeClient, EventTarget) {
+ function Transporter() {
+ var mod, _runtime, _data, _size, _pos, _chunk_size;
+
+ RuntimeClient.call(this);
+
+ Basic.extend(this, {
+ uid: Basic.guid('uid_'),
+
+ state: Transporter.IDLE,
+
+ result: null,
+
+ transport: function(data, type, options) {
+ var self = this;
+
+ options = Basic.extend({
+ chunk_size: 204798
+ }, options);
+
+ // should divide by three, base64 requires this
+ if ((mod = options.chunk_size % 3)) {
+ options.chunk_size += 3 - mod;
+ }
+
+ _chunk_size = options.chunk_size;
+
+ _reset.call(this);
+ _data = data;
+ _size = data.length;
+
+ if (Basic.typeOf(options) === 'string' || options.ruid) {
+ _run.call(self, type, this.connectRuntime(options));
+ } else {
+ // we require this to run only once
+ var cb = function(e, runtime) {
+ self.unbind("RuntimeInit", cb);
+ _run.call(self, type, runtime);
+ };
+ this.bind("RuntimeInit", cb);
+ this.connectRuntime(options);
+ }
+ },
+
+ abort: function() {
+ var self = this;
+
+ self.state = Transporter.IDLE;
+ if (_runtime) {
+ _runtime.exec.call(self, 'Transporter', 'clear');
+ self.trigger("TransportingAborted");
+ }
+
+ _reset.call(self);
+ },
+
+
+ destroy: function() {
+ this.unbindAll();
+ _runtime = null;
+ this.disconnectRuntime();
+ _reset.call(this);
+ }
+ });
+
+ function _reset() {
+ _size = _pos = 0;
+ _data = this.result = null;
+ }
+
+ function _run(type, runtime) {
+ var self = this;
+
+ _runtime = runtime;
+
+ //self.unbind("RuntimeInit");
+
+ self.bind("TransportingProgress", function(e) {
+ _pos = e.loaded;
+
+ if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) {
+ _transport.call(self);
+ }
+ }, 999);
+
+ self.bind("TransportingComplete", function() {
+ _pos = _size;
+ self.state = Transporter.DONE;
+ _data = null; // clean a bit
+ self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || '');
+ }, 999);
+
+ self.state = Transporter.BUSY;
+ self.trigger("TransportingStarted");
+ _transport.call(self);
+ }
+
+ function _transport() {
+ var self = this,
+ chunk,
+ bytesLeft = _size - _pos;
+
+ if (_chunk_size > bytesLeft) {
+ _chunk_size = bytesLeft;
+ }
+
+ chunk = Encode.btoa(_data.substr(_pos, _chunk_size));
+ _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size);
+ }
+ }
+
+ Transporter.IDLE = 0;
+ Transporter.BUSY = 1;
+ Transporter.DONE = 2;
+
+ Transporter.prototype = EventTarget.instance;
+
+ return Transporter;
+});
+
+// Included from: src/javascript/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/image/Image", [
+ "moxie/core/utils/Basic",
+ "moxie/core/utils/Dom",
+ "moxie/core/Exceptions",
+ "moxie/file/FileReaderSync",
+ "moxie/xhr/XMLHttpRequest",
+ "moxie/runtime/Runtime",
+ "moxie/runtime/RuntimeClient",
+ "moxie/runtime/Transporter",
+ "moxie/core/utils/Env",
+ "moxie/core/EventTarget",
+ "moxie/file/Blob",
+ "moxie/file/File",
+ "moxie/core/utils/Encode"
+], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) {
+ /**
+ Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data.
+
+ @class Image
+ @constructor
+ @extends EventTarget
+ */
+ var dispatches = [
+ 'progress',
+
+ /**
+ Dispatched when loading is complete.
+
+ @event load
+ @param {Object} event
+ */
+ 'load',
+
+ 'error',
+
+ /**
+ Dispatched when resize operation is complete.
+
+ @event resize
+ @param {Object} event
+ */
+ 'resize',
+
+ /**
+ Dispatched when visual representation of the image is successfully embedded
+ into the corresponsing container.
+
+ @event embedded
+ @param {Object} event
+ */
+ 'embedded'
+ ];
+
+ function Image() {
+ RuntimeClient.call(this);
+
+ Basic.extend(this, {
+ /**
+ Unique id of the component
+
+ @property uid
+ @type {String}
+ */
+ uid: Basic.guid('uid_'),
+
+ /**
+ Unique id of the connected runtime, if any.
+
+ @property ruid
+ @type {String}
+ */
+ ruid: null,
+
+ /**
+ Name of the file, that was used to create an image, if available. If not equals to empty string.
+
+ @property name
+ @type {String}
+ @default ""
+ */
+ name: "",
+
+ /**
+ Size of the image in bytes. Actual value is set only after image is preloaded.
+
+ @property size
+ @type {Number}
+ @default 0
+ */
+ size: 0,
+
+ /**
+ Width of the image. Actual value is set only after image is preloaded.
+
+ @property width
+ @type {Number}
+ @default 0
+ */
+ width: 0,
+
+ /**
+ Height of the image. Actual value is set only after image is preloaded.
+
+ @property height
+ @type {Number}
+ @default 0
+ */
+ height: 0,
+
+ /**
+ Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded.
+
+ @property type
+ @type {String}
+ @default ""
+ */
+ type: "",
+
+ /**
+ Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded.
+
+ @property meta
+ @type {Object}
+ @default {}
+ */
+ meta: {},
+
+ /**
+ Alias for load method, that takes another mOxie.Image object as a source (see load).
+
+ @method clone
+ @param {Image} src Source for the image
+ @param {Boolean} [exact=false] Whether to activate in-depth clone mode
+ */
+ clone: function() {
+ this.load.apply(this, arguments);
+ },
+
+ /**
+ Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File,
+ native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL,
+ Image will be downloaded from remote destination and loaded in memory.
+
+ @example
+ var img = new mOxie.Image();
+ img.onload = function() {
+ var blob = img.getAsBlob();
+
+ var formData = new mOxie.FormData();
+ formData.append('file', blob);
+
+ var xhr = new mOxie.XMLHttpRequest();
+ xhr.onload = function() {
+ // upload complete
+ };
+ xhr.open('post', 'upload.php');
+ xhr.send(formData);
+ };
+ img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg)
+
+
+ @method load
+ @param {Image|Blob|File|String} src Source for the image
+ @param {Boolean|Object} [mixed]
+ */
+ load: function() {
+ // this is here because to bind properly we need an uid first, which is created above
+ this.bind('Load Resize', function() {
+ _updateInfo.call(this);
+ }, 999);
+
+ this.convertEventPropsToHandlers(dispatches);
+
+ _load.apply(this, arguments);
+ },
+
+ /**
+ Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions.
+
+ @method downsize
+ @param {Number} width Resulting width
+ @param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
+ @param {Boolean} [crop=false] Whether to crop the image to exact dimensions
+ @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
+ */
+ downsize: function(opts) {
+ var defaults = {
+ width: this.width,
+ height: this.height,
+ crop: false,
+ preserveHeaders: true
+ };
+
+ if (typeof(opts) === 'object') {
+ opts = Basic.extend(defaults, opts);
+ } else {
+ opts = Basic.extend(defaults, {
+ width: arguments[0],
+ height: arguments[1],
+ crop: arguments[2],
+ preserveHeaders: arguments[3]
+ });
+ }
+
+ try {
+ if (!this.size) { // only preloaded image objects can be used as source
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+
+ // no way to reliably intercept the crash due to high resolution, so we simply avoid it
+ if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
+ throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
+ }
+
+ this.getRuntime().exec.call(this, 'Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders);
+ } catch(ex) {
+ // for now simply trigger error event
+ this.trigger('error', ex.code);
+ }
+ },
+
+ /**
+ Alias for downsize(width, height, true). (see downsize)
+
+ @method crop
+ @param {Number} width Resulting width
+ @param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
+ @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
+ */
+ crop: function(width, height, preserveHeaders) {
+ this.downsize(width, height, true, preserveHeaders);
+ },
+
+ getAsCanvas: function() {
+ if (!Env.can('create_canvas')) {
+ throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+ }
+
+ var runtime = this.connectRuntime(this.ruid);
+ return runtime.exec.call(this, 'Image', 'getAsCanvas');
+ },
+
+ /**
+ Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws
+ DOMException.INVALID_STATE_ERR).
+
+ @method getAsBlob
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+ @return {Blob} Image as Blob
+ */
+ getAsBlob: function(type, quality) {
+ if (!this.size) {
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+
+ if (!type) {
+ type = 'image/jpeg';
+ }
+
+ if (type === 'image/jpeg' && !quality) {
+ quality = 90;
+ }
+
+ return this.getRuntime().exec.call(this, 'Image', 'getAsBlob', type, quality);
+ },
+
+ /**
+ Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws
+ DOMException.INVALID_STATE_ERR).
+
+ @method getAsDataURL
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+ @return {String} Image as dataURL string
+ */
+ getAsDataURL: function(type, quality) {
+ if (!this.size) {
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+ return this.getRuntime().exec.call(this, 'Image', 'getAsDataURL', type, quality);
+ },
+
+ /**
+ Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws
+ DOMException.INVALID_STATE_ERR).
+
+ @method getAsBinaryString
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+ @return {String} Image as binary string
+ */
+ getAsBinaryString: function(type, quality) {
+ var dataUrl = this.getAsDataURL(type, quality);
+ return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7));
+ },
+
+ /**
+ Embeds a visual representation of the image into the specified node. Depending on the runtime,
+ it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare,
+ can be used in legacy browsers that do not have canvas or proper dataURI support).
+
+ @method embed
+ @param {DOMElement} el DOM element to insert the image object into
+ @param {Object} [options]
+ @param {Number} [options.width] The width of an embed (defaults to the image width)
+ @param {Number} [options.height] The height of an embed (defaults to the image height)
+ @param {String} [type="image/jpeg"] Mime type
+ @param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg
+ @param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions
+ */
+ embed: function(el) {
+ var self = this
+ , imgCopy
+ , type, quality, crop
+ , options = arguments[1] || {}
+ , width = this.width
+ , height = this.height
+ , runtime // this has to be outside of all the closures to contain proper runtime
+ ;
+
+ function onResize() {
+ // if possible, embed a canvas element directly
+ if (Env.can('create_canvas')) {
+ var canvas = imgCopy.getAsCanvas();
+ if (canvas) {
+ el.appendChild(canvas);
+ canvas = null;
+ imgCopy.destroy();
+ self.trigger('embedded');
+ return;
+ }
+ }
+
+ var dataUrl = imgCopy.getAsDataURL(type, quality);
+ if (!dataUrl) {
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+ }
+
+ if (Env.can('use_data_uri_of', dataUrl.length)) {
+ el.innerHTML = '';
+ imgCopy.destroy();
+ self.trigger('embedded');
+ } else {
+ var tr = new Transporter();
+
+ tr.bind("TransportingComplete", function() {
+ runtime = self.connectRuntime(this.result.ruid);
+
+ self.bind("Embedded", function() {
+ // position and size properly
+ Basic.extend(runtime.getShimContainer().style, {
+ //position: 'relative',
+ top: '0px',
+ left: '0px',
+ width: imgCopy.width + 'px',
+ height: imgCopy.height + 'px'
+ });
+
+ // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's
+ // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and
+ // sometimes 8 and they do not have this problem, we can comment this for now
+ /*tr.bind("RuntimeInit", function(e, runtime) {
+ tr.destroy();
+ runtime.destroy();
+ onResize.call(self); // re-feed our image data
+ });*/
+
+ runtime = null;
+ }, 999);
+
+ runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height);
+ imgCopy.destroy();
+ });
+
+ tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, Basic.extend({}, options, {
+ required_caps: {
+ display_media: true
+ },
+ runtime_order: 'flash,silverlight',
+ container: el
+ }));
+ }
+ }
+
+ try {
+ if (!(el = Dom.get(el))) {
+ throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR);
+ }
+
+ if (!this.size) { // only preloaded image objects can be used as source
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+
+ if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
+ throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
+ }
+
+ type = options.type || this.type || 'image/jpeg';
+ quality = options.quality || 90;
+ crop = Basic.typeOf(options.crop) !== 'undefined' ? options.crop : false;
+
+ // figure out dimensions for the thumb
+ if (options.width) {
+ width = options.width;
+ height = options.height || width;
+ } else {
+ // if container element has measurable dimensions, use them
+ var dimensions = Dom.getSize(el);
+ if (dimensions.w && dimensions.h) { // both should be > 0
+ width = dimensions.w;
+ height = dimensions.h;
+ }
+ }
+
+ imgCopy = new Image();
+
+ imgCopy.bind("Resize", function() {
+ onResize.call(self);
+ });
+
+ imgCopy.bind("Load", function() {
+ imgCopy.downsize(width, height, crop, false);
+ });
+
+ imgCopy.clone(this, false);
+
+ return imgCopy;
+ } catch(ex) {
+ // for now simply trigger error event
+ this.trigger('error', ex.code);
+ }
+ },
+
+ /**
+ Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object.
+
+ @method destroy
+ */
+ destroy: function() {
+ if (this.ruid) {
+ this.getRuntime().exec.call(this, 'Image', 'destroy');
+ this.disconnectRuntime();
+ }
+ this.unbindAll();
+ }
+ });
+
+
+ function _updateInfo(info) {
+ if (!info) {
+ info = this.getRuntime().exec.call(this, 'Image', 'getInfo');
+ }
+
+ this.size = info.size;
+ this.width = info.width;
+ this.height = info.height;
+ this.type = info.type;
+ this.meta = info.meta;
+
+ // update file name, only if empty
+ if (this.name === '') {
+ this.name = info.name;
+ }
+ }
+
+
+ function _load(src) {
+ var srcType = Basic.typeOf(src);
+
+ try {
+ // if source is Image
+ if (src instanceof Image) {
+ if (!src.size) { // only preloaded image objects can be used as source
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+ }
+ _loadFromImage.apply(this, arguments);
+ }
+ // if source is o.Blob/o.File
+ else if (src instanceof Blob) {
+ if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) {
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+ }
+ _loadFromBlob.apply(this, arguments);
+ }
+ // if native blob/file
+ else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) {
+ _load.call(this, new File(null, src), arguments[1]);
+ }
+ // if String
+ else if (srcType === 'string') {
+ // if dataUrl String
+ if (/^data:[^;]*;base64,/.test(src)) {
+ _load.call(this, new Blob(null, { data: src }), arguments[1]);
+ }
+ // else assume Url, either relative or absolute
+ else {
+ _loadFromUrl.apply(this, arguments);
+ }
+ }
+ // if source seems to be an img node
+ else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') {
+ _load.call(this, src.src, arguments[1]);
+ }
+ else {
+ throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR);
+ }
+ } catch(ex) {
+ // for now simply trigger error event
+ this.trigger('error', ex.code);
+ }
+ }
+
+
+ function _loadFromImage(img, exact) {
+ var runtime = this.connectRuntime(img.ruid);
+ this.ruid = runtime.uid;
+ runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact));
+ }
+
+
+ function _loadFromBlob(blob, options) {
+ var self = this;
+
+ self.name = blob.name || '';
+
+ function exec(runtime) {
+ self.ruid = runtime.uid;
+ runtime.exec.call(self, 'Image', 'loadFromBlob', blob);
+ }
+
+ if (blob.isDetached()) {
+ this.bind('RuntimeInit', function(e, runtime) {
+ exec(runtime);
+ });
+
+ // convert to object representation
+ if (options && typeof(options.required_caps) === 'string') {
+ options.required_caps = Runtime.parseCaps(options.required_caps);
+ }
+
+ this.connectRuntime(Basic.extend({
+ required_caps: {
+ access_image_binary: true,
+ resize_image: true
+ }
+ }, options));
+ } else {
+ exec(this.connectRuntime(blob.ruid));
+ }
+ }
+
+
+ function _loadFromUrl(url, options) {
+ var self = this, xhr;
+
+ xhr = new XMLHttpRequest();
+
+ xhr.open('get', url);
+ xhr.responseType = 'blob';
+
+ xhr.onprogress = function(e) {
+ self.trigger(e);
+ };
+
+ xhr.onload = function() {
+ _loadFromBlob.call(self, xhr.response, true);
+ };
+
+ xhr.onerror = function(e) {
+ self.trigger(e);
+ };
+
+ xhr.onloadend = function() {
+ xhr.destroy();
+ };
+
+ xhr.bind('RuntimeError', function(e, err) {
+ self.trigger('RuntimeError', err);
+ });
+
+ xhr.send(null, options);
+ }
+ }
+
+ // virtual world will crash on you if image has a resolution higher than this:
+ Image.MAX_RESIZE_WIDTH = 6500;
+ Image.MAX_RESIZE_HEIGHT = 6500;
+
+ Image.prototype = EventTarget.instance;
+
+ return Image;
+});
+
// Included from: src/javascript/runtime/flash/Runtime.js
/**
@@ -5561,143 +6304,6 @@ define("moxie/runtime/flash/file/FileReaderSync", [
return (extensions.FileReaderSync = FileReaderSync);
});
-// Included from: src/javascript/runtime/Transporter.js
-
-/**
- * Transporter.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-define("moxie/runtime/Transporter", [
- "moxie/core/utils/Basic",
- "moxie/core/utils/Encode",
- "moxie/runtime/RuntimeClient",
- "moxie/core/EventTarget"
-], function(Basic, Encode, RuntimeClient, EventTarget) {
- function Transporter() {
- var mod, _runtime, _data, _size, _pos, _chunk_size;
-
- RuntimeClient.call(this);
-
- Basic.extend(this, {
- uid: Basic.guid('uid_'),
-
- state: Transporter.IDLE,
-
- result: null,
-
- transport: function(data, type, options) {
- var self = this;
-
- options = Basic.extend({
- chunk_size: 204798
- }, options);
-
- // should divide by three, base64 requires this
- if ((mod = options.chunk_size % 3)) {
- options.chunk_size += 3 - mod;
- }
-
- _chunk_size = options.chunk_size;
-
- _reset.call(this);
- _data = data;
- _size = data.length;
-
- if (Basic.typeOf(options) === 'string' || options.ruid) {
- _run.call(self, type, this.connectRuntime(options));
- } else {
- // we require this to run only once
- var cb = function(e, runtime) {
- self.unbind("RuntimeInit", cb);
- _run.call(self, type, runtime);
- };
- this.bind("RuntimeInit", cb);
- this.connectRuntime(options);
- }
- },
-
- abort: function() {
- var self = this;
-
- self.state = Transporter.IDLE;
- if (_runtime) {
- _runtime.exec.call(self, 'Transporter', 'clear');
- self.trigger("TransportingAborted");
- }
-
- _reset.call(self);
- },
-
-
- destroy: function() {
- this.unbindAll();
- _runtime = null;
- this.disconnectRuntime();
- _reset.call(this);
- }
- });
-
- function _reset() {
- _size = _pos = 0;
- _data = this.result = null;
- }
-
- function _run(type, runtime) {
- var self = this;
-
- _runtime = runtime;
-
- //self.unbind("RuntimeInit");
-
- self.bind("TransportingProgress", function(e) {
- _pos = e.loaded;
-
- if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) {
- _transport.call(self);
- }
- }, 999);
-
- self.bind("TransportingComplete", function() {
- _pos = _size;
- self.state = Transporter.DONE;
- _data = null; // clean a bit
- self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || '');
- }, 999);
-
- self.state = Transporter.BUSY;
- self.trigger("TransportingStarted");
- _transport.call(self);
- }
-
- function _transport() {
- var self = this,
- chunk,
- bytesLeft = _size - _pos;
-
- if (_chunk_size > bytesLeft) {
- _chunk_size = bytesLeft;
- }
-
- chunk = Encode.btoa(_data.substr(_pos, _chunk_size));
- _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size);
- }
- }
-
- Transporter.IDLE = 0;
- Transporter.BUSY = 1;
- Transporter.DONE = 2;
-
- Transporter.prototype = EventTarget.instance;
-
- return Transporter;
-});
-
// Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js
/**
@@ -5847,10 +6453,10 @@ define("moxie/runtime/flash/xhr/XMLHttpRequest", [
return (extensions.XMLHttpRequest = XMLHttpRequest);
});
-// Included from: src/javascript/runtime/html4/Runtime.js
+// Included from: src/javascript/runtime/flash/runtime/Transporter.js
/**
- * Runtime.js
+ * Transporter.js
*
* Copyright 2013, Moxiecode Systems AB
* Released under GPL License.
@@ -5859,273 +6465,34 @@ define("moxie/runtime/flash/xhr/XMLHttpRequest", [
* Contributing: http://www.plupload.com/contributing
*/
-/*global File:true */
-
/**
-Defines constructor for HTML4 runtime.
-
-@class moxie/runtime/html4/Runtime
+@class moxie/runtime/flash/runtime/Transporter
@private
*/
-define("moxie/runtime/html4/Runtime", [
- "moxie/core/utils/Basic",
- "moxie/core/Exceptions",
- "moxie/runtime/Runtime",
- "moxie/core/utils/Env"
-], function(Basic, x, Runtime, Env) {
-
- var type = 'html4', extensions = {};
+define("moxie/runtime/flash/runtime/Transporter", [
+ "moxie/runtime/flash/Runtime",
+ "moxie/file/Blob"
+], function(extensions, Blob) {
- function Html4Runtime(options) {
- var I = this
- , Test = Runtime.capTest
- , True = Runtime.capTrue
- ;
-
- Runtime.call(this, options, type, {
- access_binary: Test(window.FileReader || window.File && File.getAsDataURL),
- access_image_binary: false,
- display_media: Test(extensions.Image && (Env.can('create_canvas') || Env.can('use_data_uri_over32kb'))),
- do_cors: false,
- drag_and_drop: false,
- filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest
- return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10);
- }()),
- resize_image: function() {
- return extensions.Image && I.can('access_binary') && Env.can('create_canvas');
- },
- report_upload_progress: false,
- return_response_headers: false,
- return_response_type: function(responseType) {
- if (responseType === 'json' && !!window.JSON) {
- return true;
- }
- return !!~Basic.inArray(responseType, ['text', 'document', '']);
- },
- return_status_code: function(code) {
- return !Basic.arrayDiff(code, [200, 404]);
- },
- select_file: function() {
- return Env.can('use_fileinput');
- },
- select_multiple: false,
- send_binary_string: false,
- send_custom_headers: false,
- send_multipart: true,
- slice_blob: false,
- stream_upload: function() {
- return I.can('select_file');
- },
- summon_file_dialog: Test(function() { // yeah... some dirty sniffing here...
- return (Env.browser === 'Firefox' && Env.version >= 4) ||
- (Env.browser === 'Opera' && Env.version >= 12) ||
- !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']);
- }()),
- upload_filesize: True,
- use_http_method: function(methods) {
- return !Basic.arrayDiff(methods, ['GET', 'POST']);
- }
- });
-
-
- Basic.extend(this, {
- init : function() {
- this.trigger("Init");
- },
-
- destroy: (function(destroy) { // extend default destroy method
- return function() {
- destroy.call(I);
- destroy = I = null;
- };
- }(this.destroy))
- });
-
- Basic.extend(this.getShim(), extensions);
- }
-
- Runtime.addConstructor(type, Html4Runtime);
-
- return extensions;
-});
-
-// Included from: src/javascript/core/utils/Events.js
-
-/**
- * Events.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-define('moxie/core/utils/Events', [
- 'moxie/core/utils/Basic'
-], function(Basic) {
- var eventhash = {}, uid = 'moxie_' + Basic.guid();
-
- // IE W3C like event funcs
- function preventDefault() {
- this.returnValue = false;
- }
-
- function stopPropagation() {
- this.cancelBubble = true;
- }
-
- /**
- Adds an event handler to the specified object and store reference to the handler
- in objects internal Plupload registry (@see removeEvent).
-
- @method addEvent
- @for Utils
- @static
- @param {Object} obj DOM element like object to add handler to.
- @param {String} name Name to add event listener to.
- @param {Function} callback Function to call when event occurs.
- @param {String} [key] that might be used to add specifity to the event record.
- */
- var addEvent = function(obj, name, callback, key) {
- var func, events;
-
- name = name.toLowerCase();
-
- // Add event listener
- if (obj.addEventListener) {
- func = callback;
-
- obj.addEventListener(name, func, false);
- } else if (obj.attachEvent) {
- func = function() {
- var evt = window.event;
-
- if (!evt.target) {
- evt.target = evt.srcElement;
- }
-
- evt.preventDefault = preventDefault;
- evt.stopPropagation = stopPropagation;
-
- callback(evt);
- };
-
- obj.attachEvent('on' + name, func);
- }
-
- // Log event handler to objects internal mOxie registry
- if (!obj[uid]) {
- obj[uid] = Basic.guid();
- }
-
- if (!eventhash.hasOwnProperty(obj[uid])) {
- eventhash[obj[uid]] = {};
- }
-
- events = eventhash[obj[uid]];
-
- if (!events.hasOwnProperty(name)) {
- events[name] = [];
- }
-
- events[name].push({
- func: func,
- orig: callback, // store original callback for IE
- key: key
- });
- };
-
-
- /**
- Remove event handler from the specified object. If third argument (callback)
- is not specified remove all events with the specified name.
-
- @method removeEvent
- @static
- @param {Object} obj DOM element to remove event listener(s) from.
- @param {String} name Name of event listener to remove.
- @param {Function|String} [callback] might be a callback or unique key to match.
- */
- var removeEvent = function(obj, name, callback) {
- var type, undef;
-
- name = name.toLowerCase();
-
- if (obj[uid] && eventhash[obj[uid]] && eventhash[obj[uid]][name]) {
- type = eventhash[obj[uid]][name];
- } else {
- return;
- }
-
- for (var i = type.length - 1; i >= 0; i--) {
- // undefined or not, key should match
- if (type[i].orig === callback || type[i].key === callback) {
- if (obj.removeEventListener) {
- obj.removeEventListener(name, type[i].func, false);
- } else if (obj.detachEvent) {
- obj.detachEvent('on'+name, type[i].func);
- }
-
- type[i].orig = null;
- type[i].func = null;
- type.splice(i, 1);
-
- // If callback was passed we are done here, otherwise proceed
- if (callback !== undef) {
- break;
- }
- }
- }
-
- // If event array got empty, remove it
- if (!type.length) {
- delete eventhash[obj[uid]][name];
- }
-
- // If mOxie registry has become empty, remove it
- if (Basic.isEmptyObj(eventhash[obj[uid]])) {
- delete eventhash[obj[uid]];
-
- // IE doesn't let you remove DOM object property with - delete
- try {
- delete obj[uid];
- } catch(e) {
- obj[uid] = undef;
+ var Transporter = {
+ getAsBlob: function(type) {
+ var self = this.getRuntime()
+ , blob = self.shimExec.call(this, 'Transporter', 'getAsBlob', type)
+ ;
+ if (blob) {
+ return new Blob(self.uid, blob);
}
+ return null;
}
};
-
-
- /**
- Remove all kind of events from the specified object
-
- @method removeAllEvents
- @static
- @param {Object} obj DOM element to remove event listeners from.
- @param {String} [key] unique key to match, when removing events.
- */
- var removeAllEvents = function(obj, key) {
- if (!obj || !obj[uid]) {
- return;
- }
-
- Basic.each(eventhash[obj[uid]], function(events, name) {
- removeEvent(obj, name, key);
- });
- };
- return {
- addEvent: addEvent,
- removeEvent: removeEvent,
- removeAllEvents: removeAllEvents
- };
+ return (extensions.Transporter = Transporter);
});
-// Included from: src/javascript/runtime/html4/file/FileInput.js
+// Included from: src/javascript/runtime/flash/image/Image.js
/**
- * FileInput.js
+ * Image.js
*
* Copyright 2013, Moxiecode Systems AB
* Released under GPL License.
@@ -6135,1052 +6502,69 @@ define('moxie/core/utils/Events', [
*/
/**
-@class moxie/runtime/html4/file/FileInput
+@class moxie/runtime/flash/image/Image
@private
*/
-define("moxie/runtime/html4/file/FileInput", [
- "moxie/runtime/html4/Runtime",
+define("moxie/runtime/flash/image/Image", [
+ "moxie/runtime/flash/Runtime",
"moxie/core/utils/Basic",
- "moxie/core/utils/Dom",
- "moxie/core/utils/Events",
- "moxie/core/utils/Mime",
- "moxie/core/utils/Env"
-], function(extensions, Basic, Dom, Events, Mime, Env) {
-
- function FileInput() {
- var _uid, _files = [], _mimes = [], _options;
-
- function addInput() {
- var comp = this, I = comp.getRuntime(), shimContainer, browseButton, currForm, form, input, uid;
-
- uid = Basic.guid('uid_');
-
- shimContainer = I.getShimContainer(); // we get new ref everytime to avoid memory leaks in IE
-
- if (_uid) { // move previous form out of the view
- currForm = Dom.get(_uid + '_form');
- if (currForm) {
- Basic.extend(currForm.style, { top: '100%' });
- }
- }
-
- // build form in DOM, since innerHTML version not able to submit file for some reason
- form = document.createElement('form');
- form.setAttribute('id', uid + '_form');
- form.setAttribute('method', 'post');
- form.setAttribute('enctype', 'multipart/form-data');
- form.setAttribute('encoding', 'multipart/form-data');
-
- Basic.extend(form.style, {
- overflow: 'hidden',
- position: 'absolute',
- top: 0,
- left: 0,
- width: '100%',
- height: '100%'
- });
-
- input = document.createElement('input');
- input.setAttribute('id', uid);
- input.setAttribute('type', 'file');
- input.setAttribute('name', _options.name || 'Filedata');
- input.setAttribute('accept', _mimes.join(','));
-
- Basic.extend(input.style, {
- fontSize: '999px',
- opacity: 0
- });
-
- form.appendChild(input);
- shimContainer.appendChild(form);
-
- // prepare file input to be placed underneath the browse_button element
- Basic.extend(input.style, {
- position: 'absolute',
- top: 0,
- left: 0,
- width: '100%',
- height: '100%'
- });
-
- if (Env.browser === 'IE' && Env.version < 10) {
- Basic.extend(input.style, {
- filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)"
- });
- }
-
- input.onchange = function() { // there should be only one handler for this
- var file;
-
- if (!this.value) {
- return;
- }
-
- if (this.files) {
- file = this.files[0];
- } else {
- file = {
- name: this.value
- };
- }
-
- _files = [file];
-
- this.onchange = function() {}; // clear event handler
- addInput.call(comp);
-
- // after file is initialized as o.File, we need to update form and input ids
- comp.bind('change', function onChange() {
- var input = Dom.get(uid), form = Dom.get(uid + '_form'), file;
-
- comp.unbind('change', onChange);
-
- if (comp.files.length && input && form) {
- file = comp.files[0];
-
- input.setAttribute('id', file.uid);
- form.setAttribute('id', file.uid + '_form');
-
- // set upload target
- form.setAttribute('target', file.uid + '_iframe');
- }
- input = form = null;
- }, 998);
-
- input = form = null;
- comp.trigger('change');
- };
-
-
- // route click event to the input
- if (I.can('summon_file_dialog')) {
- browseButton = Dom.get(_options.browse_button);
- Events.removeEvent(browseButton, 'click', comp.uid);
- Events.addEvent(browseButton, 'click', function(e) {
- if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
- input.click();
- }
- e.preventDefault();
- }, comp.uid);
- }
-
- _uid = uid;
-
- shimContainer = currForm = browseButton = null;
- }
-
- Basic.extend(this, {
- init: function(options) {
- var comp = this, I = comp.getRuntime(), shimContainer;
-
- // figure out accept string
- _options = options;
- _mimes = options.accept.mimes || Mime.extList2mimes(options.accept, I.can('filter_by_extension'));
-
- shimContainer = I.getShimContainer();
-
- (function() {
- var browseButton, zIndex, top;
-
- browseButton = Dom.get(options.browse_button);
-
- // Route click event to the input[type=file] element for browsers that support such behavior
- if (I.can('summon_file_dialog')) {
- if (Dom.getStyle(browseButton, 'position') === 'static') {
- browseButton.style.position = 'relative';
- }
-
- zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;
-
- browseButton.style.zIndex = zIndex;
- shimContainer.style.zIndex = zIndex - 1;
- }
-
- /* Since we have to place input[type=file] on top of the browse_button for some browsers,
- browse_button loses interactivity, so we restore it here */
- top = I.can('summon_file_dialog') ? browseButton : shimContainer;
-
- Events.addEvent(top, 'mouseover', function() {
- comp.trigger('mouseenter');
- }, comp.uid);
-
- Events.addEvent(top, 'mouseout', function() {
- comp.trigger('mouseleave');
- }, comp.uid);
-
- Events.addEvent(top, 'mousedown', function() {
- comp.trigger('mousedown');
- }, comp.uid);
-
- Events.addEvent(Dom.get(options.container), 'mouseup', function() {
- comp.trigger('mouseup');
- }, comp.uid);
-
- browseButton = null;
- }());
-
- addInput.call(this);
-
- shimContainer = null;
-
- // trigger ready event asynchronously
- comp.trigger({
- type: 'ready',
- async: true
- });
- },
-
- getFiles: function() {
- return _files;
- },
-
- disable: function(state) {
- var input;
-
- if ((input = Dom.get(_uid))) {
- input.disabled = !!state;
- }
- },
-
- destroy: function() {
- var I = this.getRuntime()
- , shim = I.getShim()
- , shimContainer = I.getShimContainer()
- ;
-
- Events.removeAllEvents(shimContainer, this.uid);
- Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
- Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid);
-
- if (shimContainer) {
- shimContainer.innerHTML = '';
- }
-
- shim.removeInstance(this.uid);
-
- _uid = _files = _mimes = _options = shimContainer = shim = null;
- }
- });
- }
-
- return (extensions.FileInput = FileInput);
-});
-
-// Included from: src/javascript/runtime/html5/Runtime.js
-
-/**
- * Runtime.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/*global File:true */
-
-/**
-Defines constructor for HTML5 runtime.
-
-@class moxie/runtime/html5/Runtime
-@private
-*/
-define("moxie/runtime/html5/Runtime", [
- "moxie/core/utils/Basic",
- "moxie/core/Exceptions",
- "moxie/runtime/Runtime",
- "moxie/core/utils/Env"
-], function(Basic, x, Runtime, Env) {
-
- var type = "html5", extensions = {};
-
- function Html5Runtime(options) {
- var I = this
- , Test = Runtime.capTest
- , True = Runtime.capTrue
- ;
-
- var caps = Basic.extend({
- access_binary: Test(window.FileReader || window.File && window.File.getAsDataURL),
- access_image_binary: function() {
- return I.can('access_binary') && !!extensions.Image;
- },
- display_media: Test(Env.can('create_canvas') || Env.can('use_data_uri_over32kb')),
- do_cors: Test(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()),
- drag_and_drop: Test(function() {
- // this comes directly from Modernizr: http://www.modernizr.com/
- var div = document.createElement('div');
- // IE has support for drag and drop since version 5, but doesn't support dropping files from desktop
- return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && (Env.browser !== 'IE' || Env.version > 9);
- }()),
- filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest
- return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10);
- }()),
- return_response_headers: True,
- return_response_type: function(responseType) {
- if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported
- return true;
- }
- return Env.can('return_response_type', responseType);
- },
- return_status_code: True,
- report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload),
- resize_image: function() {
- return I.can('access_binary') && Env.can('create_canvas');
- },
- select_file: function() {
- return Env.can('use_fileinput') && window.File;
- },
- select_folder: function() {
- return I.can('select_file') && Env.browser === 'Chrome' && Env.version >= 21;
- },
- select_multiple: function() {
- // it is buggy on Safari Windows and iOS
- return I.can('select_file') &&
- !(Env.browser === 'Safari' && Env.os === 'Windows') &&
- !(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.4", '<'));
- },
- send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))),
- send_custom_headers: Test(window.XMLHttpRequest),
- send_multipart: function() {
- return !!(window.XMLHttpRequest && new XMLHttpRequest().upload && window.FormData) || I.can('send_binary_string');
- },
- slice_blob: Test(window.File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice)),
- stream_upload: function(){
- return I.can('slice_blob') && I.can('send_multipart');
- },
- summon_file_dialog: Test(function() { // yeah... some dirty sniffing here...
- return (Env.browser === 'Firefox' && Env.version >= 4) ||
- (Env.browser === 'Opera' && Env.version >= 12) ||
- (Env.browser === 'IE' && Env.version >= 10) ||
- !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']);
- }()),
- upload_filesize: True
- },
- arguments[2]
- );
-
- Runtime.call(this, options, (arguments[1] || type), caps);
-
-
- Basic.extend(this, {
-
- init : function() {
- this.trigger("Init");
- },
-
- destroy: (function(destroy) { // extend default destroy method
- return function() {
- destroy.call(I);
- destroy = I = null;
- };
- }(this.destroy))
- });
-
- Basic.extend(this.getShim(), extensions);
- }
-
- Runtime.addConstructor(type, Html5Runtime);
-
- return extensions;
-});
-
-// Included from: src/javascript/runtime/html5/file/FileReader.js
-
-/**
- * FileReader.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/html5/file/FileReader
-@private
-*/
-define("moxie/runtime/html5/file/FileReader", [
- "moxie/runtime/html5/Runtime",
- "moxie/core/utils/Encode",
- "moxie/core/utils/Basic"
-], function(extensions, Encode, Basic) {
-
- function FileReader() {
- var _fr, _convertToBinary = false;
-
- Basic.extend(this, {
-
- read: function(op, blob) {
- var target = this;
-
- _fr = new window.FileReader();
-
- _fr.addEventListener('progress', function(e) {
- target.trigger(e);
- });
-
- _fr.addEventListener('load', function(e) {
- target.trigger(e);
- });
-
- _fr.addEventListener('error', function(e) {
- target.trigger(e, _fr.error);
- });
-
- _fr.addEventListener('loadend', function() {
- _fr = null;
- });
-
- if (Basic.typeOf(_fr[op]) === 'function') {
- _convertToBinary = false;
- _fr[op](blob.getSource());
- } else if (op === 'readAsBinaryString') { // readAsBinaryString is depricated in general and never existed in IE10+
- _convertToBinary = true;
- _fr.readAsDataURL(blob.getSource());
- }
- },
-
- getResult: function() {
- return _fr && _fr.result ? (_convertToBinary ? _toBinary(_fr.result) : _fr.result) : null;
- },
-
- abort: function() {
- if (_fr) {
- _fr.abort();
- }
- },
-
- destroy: function() {
- _fr = null;
- }
- });
-
- function _toBinary(str) {
- return Encode.atob(str.substring(str.indexOf('base64,') + 7));
- }
- }
-
- return (extensions.FileReader = FileReader);
-});
-
-// Included from: src/javascript/runtime/html4/file/FileReader.js
-
-/**
- * FileReader.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/html4/file/FileReader
-@private
-*/
-define("moxie/runtime/html4/file/FileReader", [
- "moxie/runtime/html4/Runtime",
- "moxie/runtime/html5/file/FileReader"
-], function(extensions, FileReader) {
- return (extensions.FileReader = FileReader);
-});
-
-// Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js
-
-/**
- * XMLHttpRequest.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/html4/xhr/XMLHttpRequest
-@private
-*/
-define("moxie/runtime/html4/xhr/XMLHttpRequest", [
- "moxie/runtime/html4/Runtime",
- "moxie/core/utils/Basic",
- "moxie/core/utils/Dom",
- "moxie/core/utils/Url",
- "moxie/core/Exceptions",
- "moxie/core/utils/Events",
+ "moxie/runtime/Transporter",
"moxie/file/Blob",
- "moxie/xhr/FormData"
-], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) {
+ "moxie/file/FileReaderSync"
+], function(extensions, Basic, Transporter, Blob, FileReaderSync) {
- function XMLHttpRequest() {
- var _status, _response, _iframe;
+ var Image = {
+ loadFromBlob: function(blob) {
+ var comp = this, self = comp.getRuntime();
- function cleanup(cb) {
- var target = this, uid, form, inputs, i, hasFile = false;
-
- if (!_iframe) {
- return;
+ function exec(srcBlob) {
+ self.shimExec.call(comp, 'Image', 'loadFromBlob', srcBlob.uid);
+ comp = self = null;
}
- uid = _iframe.id.replace(/_iframe$/, '');
-
- form = Dom.get(uid + '_form');
- if (form) {
- inputs = form.getElementsByTagName('input');
- i = inputs.length;
-
- while (i--) {
- switch (inputs[i].getAttribute('type')) {
- case 'hidden':
- inputs[i].parentNode.removeChild(inputs[i]);
- break;
- case 'file':
- hasFile = true; // flag the case for later
- break;
- }
- }
- inputs = [];
-
- if (!hasFile) { // we need to keep the form for sake of possible retries
- form.parentNode.removeChild(form);
- }
- form = null;
- }
-
- // without timeout, request is marked as canceled (in console)
- setTimeout(function() {
- Events.removeEvent(_iframe, 'load', target.uid);
- if (_iframe.parentNode) { // #382
- _iframe.parentNode.removeChild(_iframe);
- }
-
- // check if shim container has any other children, if - not, remove it as well
- var shimContainer = target.getRuntime().getShimContainer();
- if (!shimContainer.children.length) {
- shimContainer.parentNode.removeChild(shimContainer);
- }
-
- shimContainer = _iframe = null;
- cb();
- }, 1);
- }
-
- Basic.extend(this, {
- send: function(meta, data) {
- var target = this, I = target.getRuntime(), uid, form, input, blob;
-
- _status = _response = null;
-
- function createIframe() {
- var container = I.getShimContainer() || document.body
- , temp = document.createElement('div')
- ;
-
- // IE 6 won't be able to set the name using setAttribute or iframe.name
- temp.innerHTML = '';
- _iframe = temp.firstChild;
- container.appendChild(_iframe);
-
- /* _iframe.onreadystatechange = function() {
- console.info(_iframe.readyState);
- };*/
-
- Events.addEvent(_iframe, 'load', function() { // _iframe.onload doesn't work in IE lte 8
- var el;
-
- try {
- el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document;
-
- // try to detect some standard error pages
- if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error
- _status = el.title.replace(/^(\d+).*$/, '$1');
- } else {
- _status = 200;
- // get result
- _response = Basic.trim(el.body.innerHTML);
-
- // we need to fire these at least once
- target.trigger({
- type: 'progress',
- loaded: _response.length,
- total: _response.length
- });
-
- if (blob) { // if we were uploading a file
- target.trigger({
- type: 'uploadprogress',
- loaded: blob.size || 1025,
- total: blob.size || 1025
- });
- }
- }
- } catch (ex) {
- if (Url.hasSameOrigin(meta.url)) {
- // if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm
- // which obviously results to cross domain error (wtf?)
- _status = 404;
- } else {
- cleanup.call(target, function() {
- target.trigger('error');
- });
- return;
- }
- }
-
- cleanup.call(target, function() {
- target.trigger('load');
- });
- }, target.uid);
- } // end createIframe
-
- // prepare data to be sent and convert if required
- if (data instanceof FormData && data.hasBlob()) {
- blob = data.getBlob();
- uid = blob.uid;
- input = Dom.get(uid);
- form = Dom.get(uid + '_form');
- if (!form) {
- throw new x.DOMException(x.DOMException.NOT_FOUND_ERR);
- }
- } else {
- uid = Basic.guid('uid_');
-
- form = document.createElement('form');
- form.setAttribute('id', uid + '_form');
- form.setAttribute('method', meta.method);
- form.setAttribute('enctype', 'multipart/form-data');
- form.setAttribute('encoding', 'multipart/form-data');
- form.setAttribute('target', uid + '_iframe');
-
- I.getShimContainer().appendChild(form);
- }
-
- if (data instanceof FormData) {
- data.each(function(value, name) {
- if (value instanceof Blob) {
- if (input) {
- input.setAttribute('name', name);
- }
- } else {
- var hidden = document.createElement('input');
-
- Basic.extend(hidden, {
- type : 'hidden',
- name : name,
- value : value
- });
-
- // make sure that input[type="file"], if it's there, comes last
- if (input) {
- form.insertBefore(hidden, input);
- } else {
- form.appendChild(hidden);
- }
- }
- });
- }
-
- // set destination url
- form.setAttribute("action", meta.url);
-
- createIframe();
- form.submit();
- target.trigger('loadstart');
- },
-
- getStatus: function() {
- return _status;
- },
-
- getResponse: function(responseType) {
- if ('json' === responseType) {
- // strip off ..
tags that might be enclosing the response
- if (Basic.typeOf(_response) === 'string' && !!window.JSON) {
- try {
- return JSON.parse(_response.replace(/^\s*]*>/, '').replace(/<\/pre>\s*$/, ''));
- } catch (ex) {
- return null;
- }
- }
- } else if ('document' === responseType) {
-
- }
- return _response;
- },
-
- abort: function() {
- var target = this;
-
- if (_iframe && _iframe.contentWindow) {
- if (_iframe.contentWindow.stop) { // FireFox/Safari/Chrome
- _iframe.contentWindow.stop();
- } else if (_iframe.contentWindow.document.execCommand) { // IE
- _iframe.contentWindow.document.execCommand('Stop');
- } else {
- _iframe.src = "about:blank";
- }
- }
-
- cleanup.call(this, function() {
- // target.dispatchEvent('readystatechange');
- target.dispatchEvent('abort');
+ if (blob.isDetached()) { // binary string
+ var tr = new Transporter();
+ tr.bind("TransportingComplete", function() {
+ exec(tr.result.getSource());
});
+ tr.transport(blob.getSource(), blob.type, { ruid: self.uid });
+ } else {
+ exec(blob.getSource());
}
- });
- }
+ },
- return (extensions.XMLHttpRequest = XMLHttpRequest);
-});
+ loadFromImage: function(img) {
+ var self = this.getRuntime();
+ return self.shimExec.call(this, 'Image', 'loadFromImage', img.uid);
+ },
-// Included from: src/javascript/runtime/silverlight/Runtime.js
-
-/**
- * RunTime.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/*global ActiveXObject:true */
-
-/**
-Defines constructor for Silverlight runtime.
-
-@class moxie/runtime/silverlight/Runtime
-@private
-*/
-define("moxie/runtime/silverlight/Runtime", [
- "moxie/core/utils/Basic",
- "moxie/core/utils/Env",
- "moxie/core/utils/Dom",
- "moxie/core/Exceptions",
- "moxie/runtime/Runtime"
-], function(Basic, Env, Dom, x, Runtime) {
-
- var type = "silverlight", extensions = {};
-
- function isInstalled(version) {
- var isVersionSupported = false, control = null, actualVer,
- actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0;
-
- try {
- try {
- control = new ActiveXObject('AgControl.AgControl');
-
- if (control.IsVersionSupported(version)) {
- isVersionSupported = true;
- }
-
- control = null;
- } catch (e) {
- var plugin = navigator.plugins["Silverlight Plug-In"];
-
- if (plugin) {
- actualVer = plugin.description;
-
- if (actualVer === "1.0.30226.2") {
- actualVer = "2.0.30226.2";
- }
-
- actualVerArray = actualVer.split(".");
-
- while (actualVerArray.length > 3) {
- actualVerArray.pop();
- }
-
- while ( actualVerArray.length < 4) {
- actualVerArray.push(0);
- }
-
- reqVerArray = version.split(".");
-
- while (reqVerArray.length > 4) {
- reqVerArray.pop();
- }
-
- do {
- requiredVersionPart = parseInt(reqVerArray[index], 10);
- actualVersionPart = parseInt(actualVerArray[index], 10);
- index++;
- } while (index < reqVerArray.length && requiredVersionPart === actualVersionPart);
-
- if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) {
- isVersionSupported = true;
- }
- }
+ getAsBlob: function(type, quality) {
+ var self = this.getRuntime()
+ , blob = self.shimExec.call(this, 'Image', 'getAsBlob', type, quality)
+ ;
+ if (blob) {
+ return new Blob(self.uid, blob);
}
- } catch (e2) {
- isVersionSupported = false;
- }
+ return null;
+ },
- return isVersionSupported;
- }
-
- /**
- Constructor for the Silverlight Runtime
-
- @class SilverlightRuntime
- @extends Runtime
- */
- function SilverlightRuntime(options) {
- var I = this, initTimer;
-
- options = Basic.extend({ xap_url: Env.xap_url }, options);
-
- Runtime.call(this, options, type, {
- access_binary: Runtime.capTrue,
- access_image_binary: Runtime.capTrue,
- display_media: Runtime.capTrue,
- do_cors: Runtime.capTrue,
- drag_and_drop: false,
- report_upload_progress: Runtime.capTrue,
- resize_image: Runtime.capTrue,
- return_response_headers: function(value) {
- return value && I.mode === 'client';
- },
- return_response_type: function(responseType) {
- if (responseType !== 'json') {
- return true;
- } else {
- return !!window.JSON;
- }
- },
- return_status_code: function(code) {
- return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]);
- },
- select_file: Runtime.capTrue,
- select_multiple: Runtime.capTrue,
- send_binary_string: Runtime.capTrue,
- send_browser_cookies: function(value) {
- return value && I.mode === 'browser';
- },
- send_custom_headers: function(value) {
- return value && I.mode === 'client';
- },
- send_multipart: Runtime.capTrue,
- slice_blob: Runtime.capTrue,
- stream_upload: true,
- summon_file_dialog: false,
- upload_filesize: Runtime.capTrue,
- use_http_method: function(methods) {
- return I.mode === 'client' || !Basic.arrayDiff(methods, ['GET', 'POST']);
+ getAsDataURL: function() {
+ var self = this.getRuntime()
+ , blob = self.Image.getAsBlob.apply(this, arguments)
+ , frs
+ ;
+ if (!blob) {
+ return null;
}
- }, {
- // capabilities that require specific mode
- return_response_headers: function(value) {
- return value ? 'client' : 'browser';
- },
- return_status_code: function(code) {
- return Basic.arrayDiff(code, [200, 404]) ? 'client' : ['client', 'browser'];
- },
- send_browser_cookies: function(value) {
- return value ? 'browser' : 'client';
- },
- send_custom_headers: function(value) {
- return value ? 'client' : 'browser';
- },
- use_http_method: function(methods) {
- return Basic.arrayDiff(methods, ['GET', 'POST']) ? 'client' : ['client', 'browser'];
- }
- });
-
-
- // minimal requirement
- if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') {
- this.mode = false;
- }
-
-
- Basic.extend(this, {
- getShim: function() {
- return Dom.get(this.uid).content.Moxie;
- },
-
- shimExec: function(component, action) {
- var args = [].slice.call(arguments, 2);
- return I.getShim().exec(this.uid, component, action, args);
- },
-
- init : function() {
- var container;
-
- container = this.getShimContainer();
-
- container.innerHTML = '';
-
- // Init is dispatched by the shim
- initTimer = setTimeout(function() {
- if (I && !I.initialized) { // runtime might be already destroyed by this moment
- I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
- }
- }, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac)
- },
-
- destroy: (function(destroy) { // extend default destroy method
- return function() {
- destroy.call(I);
- clearTimeout(initTimer); // initialization check might be still onwait
- options = initTimer = destroy = I = null;
- };
- }(this.destroy))
-
- }, extensions);
- }
-
- Runtime.addConstructor(type, SilverlightRuntime);
-
- return extensions;
-});
-
-// Included from: src/javascript/runtime/silverlight/file/Blob.js
-
-/**
- * Blob.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/file/Blob
-@private
-*/
-define("moxie/runtime/silverlight/file/Blob", [
- "moxie/runtime/silverlight/Runtime",
- "moxie/core/utils/Basic",
- "moxie/runtime/flash/file/Blob"
-], function(extensions, Basic, Blob) {
- return (extensions.Blob = Basic.extend({}, Blob));
-});
-
-// Included from: src/javascript/runtime/silverlight/file/FileInput.js
-
-/**
- * FileInput.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/file/FileInput
-@private
-*/
-define("moxie/runtime/silverlight/file/FileInput", [
- "moxie/runtime/silverlight/Runtime"
-], function(extensions) {
-
- var FileInput = {
- init: function(options) {
-
- function toFilters(accept) {
- var filter = '';
- for (var i = 0; i < accept.length; i++) {
- filter += (filter !== '' ? '|' : '') + accept[i].title + " | *." + accept[i].extensions.replace(/,/g, ';*.');
- }
- return filter;
- }
-
- this.getRuntime().shimExec.call(this, 'FileInput', 'init', toFilters(options.accept), options.name, options.multiple);
- this.trigger('ready');
+ frs = new FileReaderSync();
+ return frs.readAsDataURL(blob);
}
};
- return (extensions.FileInput = FileInput);
+ return (extensions.Image = Image);
});
-// Included from: src/javascript/runtime/silverlight/file/FileReader.js
-
-/**
- * FileReader.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/file/FileReader
-@private
-*/
-define("moxie/runtime/silverlight/file/FileReader", [
- "moxie/runtime/silverlight/Runtime",
- "moxie/core/utils/Basic",
- "moxie/runtime/flash/file/FileReader"
-], function(extensions, Basic, FileReader) {
- return (extensions.FileReader = Basic.extend({}, FileReader));
-});
-
-// Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js
-
-/**
- * FileReaderSync.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/file/FileReaderSync
-@private
-*/
-define("moxie/runtime/silverlight/file/FileReaderSync", [
- "moxie/runtime/silverlight/Runtime",
- "moxie/core/utils/Basic",
- "moxie/runtime/flash/file/FileReaderSync"
-], function(extensions, Basic, FileReaderSync) {
- return (extensions.FileReaderSync = Basic.extend({}, FileReaderSync));
-});
-
-// Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js
-
-/**
- * XMLHttpRequest.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- */
-
-/**
-@class moxie/runtime/silverlight/xhr/XMLHttpRequest
-@private
-*/
-define("moxie/runtime/silverlight/xhr/XMLHttpRequest", [
- "moxie/runtime/silverlight/Runtime",
- "moxie/core/utils/Basic",
- "moxie/runtime/flash/xhr/XMLHttpRequest"
-], function(extensions, Basic, XMLHttpRequest) {
- return (extensions.XMLHttpRequest = Basic.extend({}, XMLHttpRequest));
-});
-
-expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/core/utils/Events"]);
+expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image"]);
})(this);/**
* o.js
*
diff --git a/public/webshims/shims/moxie/silverlight/Moxie.cdn.xap b/public/webshims/shims/moxie/silverlight/Moxie.cdn.xap
deleted file mode 100644
index f0d499f9..00000000
Binary files a/public/webshims/shims/moxie/silverlight/Moxie.cdn.xap and /dev/null differ
diff --git a/public/webshims/shims/moxie/silverlight/Moxie.min.xap b/public/webshims/shims/moxie/silverlight/Moxie.min.xap
deleted file mode 100644
index 40b12c2b..00000000
Binary files a/public/webshims/shims/moxie/silverlight/Moxie.min.xap and /dev/null differ
diff --git a/public/webshims/shims/sticky.js b/public/webshims/shims/sticky.js
new file mode 100644
index 00000000..881b3c30
--- /dev/null
+++ b/public/webshims/shims/sticky.js
@@ -0,0 +1,585 @@
+webshim.register('sticky', function($, webshim, window, document, undefined, featureOptions){
+
+ "use strict";
+
+ var uid = 0;
+ var stickys = 0;
+ var $window = $(window);
+
+ function getCssValue(property, value, noPrefixes) {
+ var prop = property + ':',
+ el = document.createElement('test'),
+ mStyle = el.style;
+
+ if (!noPrefixes) {
+ mStyle.cssText = prop + [ '-webkit-', '-moz-', '-ms-', '-o-', '' ].join(value + ';' + prop) + value + ';';
+ } else {
+ mStyle.cssText = prop + value;
+ }
+
+ return mStyle[ property ];
+ }
+
+ function getPos() {
+ return {
+ top: $.css(this, 'top'),
+ bottom: $.css(this, 'bottom')
+ };
+ }
+
+ var getWinScroll = (function () {
+ var docElem;
+ var prop = 'pageYOffset';
+
+ return (prop in window) ?
+ function () {
+ return window[ prop ];
+ } :
+ ((docElem = document.documentElement), function () {
+ return docElem.scrollTop;
+ })
+ ;
+ })();
+ var isTouch = 'ontouchstart' in window || window.matchMedia('(max-device-width: 721px)').matches;
+ var support = {
+ fixed: getCssValue('position', 'fixed', true),
+ sticky: getCssValue('position', 'sticky')
+ };
+
+ var stickyMixin = {
+ getPosition: function () {
+
+ if(!this.isSticky){
+ this.position = {
+ top: this.$el.css('top'),
+ bottom: this.$el.css('bottom')
+ };
+
+ if (((
+ (this.position.top != 'auto' && this.position.bottom != 'auto') ||
+ this.position.top == 'auto' && this.position.bottom == 'auto')) && this.$el.css('position') == 'static') {
+ this.position = $.swap(this.$el[0], {position: 'absolute'}, getPos);
+ }
+
+ if (this.position.top !== 'auto') {
+ this.ankered = 'top';
+ } else if (this.position.bottom !== 'auto') {
+ this.ankered = 'bottom';
+ }
+
+ if(this.ankered == 'top'){
+ this.position.top = parseFloat(this.position.top, 10) || 0;
+ } else if(this.ankered == 'bottom'){
+ this.position.bottom = parseFloat(this.position.bottom, 10) || 0;
+ }
+
+ }
+ },
+ update: function (full) {
+ if (!this.disabled && this.$el[0].offsetWidth) {
+ if (full) {
+ if(this.isSticky){
+ this.removeSticky();
+ }
+ this.getPosition();
+ }
+ this.updateDimension();
+ }
+ },
+ setTdWidth: function(){
+ if(this.isTable){
+ this.$el.find('td, th').each(this._setInlineWidth);
+ }
+ },
+ _setInlineWidth: function(){
+ $.data(this, 'inlineWidth', this.style.width);
+ $(this).innerWidth($(this).innerWidth());
+ },
+ _restoreInlineWidth: function(){
+ this.style.width = $.data(this, 'inlineWidth') || '';
+ $.removeData(this, 'inlineWidth');
+ },
+ removeSticky: function(){
+ this.$el.removeClass('ws-sticky-on');
+ this.$el.css(this.stickyData.inline);
+ this.$placeholder.detach();
+ this.isSticky = false;
+
+ if(this.isTable){
+ this.$el.find('td, th').each(this._restoreInlineWidth);
+ }
+ },
+ commonAddEvents: function(){
+ var enableDisable;
+ var that = this;
+ var update = function() {
+ that.update();
+ };
+
+ var stickyMedia = this.$el.data('stickymedia');
+ var media = window.matchMedia && stickyMedia ? matchMedia(stickyMedia) : false;
+ $window.one('load', update);
+ $(document).on('updateshadowdom' + this.evtid, update);
+
+
+ this.$el.on('updatesticky'+ this.evtid, function(e){
+ that.update(true);
+ e.stopPropagation();
+ });
+
+ this.$el.on('disablesticky'+ this.evtid, function(e){
+ that.disable(true);
+ e.stopPropagation();
+ });
+
+ this.$el.on('enablesticky'+ this.evtid, function(e){
+ that.disable(false);
+ e.stopPropagation();
+ });
+
+ this.$el.on('remove'+ this.evtid+' destroysticky'+ this.evtid, function(e) {
+
+ $window.off(that.evtid);
+ $(document).off(that.evtid);
+ that.$el.off(that.evtid);
+ that.$parent.off(that.evtid);
+ that.$el.removeData('wsSticky').removeClass('ws-sticky');
+ if (that.$placeholder) {
+ that.$el.removeClass('ws-sticky-on');
+ that.$placeholder.remove();
+ }
+ stickys--;
+ e.stopPropagation();
+ });
+
+ if(media && media.addListener){
+ enableDisable = function(){
+ that.disable(!media.matches);
+ };
+ media.addListener(enableDisable);
+ enableDisable();
+ }
+ },
+ disable: function(disable){
+ if(!arguments.length){
+ return this.disabled;
+ }
+ if(this.disabled != disable){
+ this.disabled = !!disable;
+ if(this.disabled){
+ if(this.isSticky){
+ this.removeSticky();
+ }
+ } else {
+ this.update(true);
+ }
+ }
+ },
+ setSticky: function(){
+
+ if (!this.$placeholder) {
+ this.$placeholder = this.isTable ? $(this.$el[0].cloneNode(true)) : $(document.createElement(this.$el[0].nodeName || 'div'));
+ this.$placeholder.addClass('ws-fixedsticky-placeholder').removeClass('ws-sticky');
+ }
+
+ this.setTdWidth();
+
+ this.$placeholder
+ .insertAfter(this.$el)
+ .outerHeight(this.stickyData.outerHeight, true)
+ .outerWidth(this.stickyData.outerWidth)
+ ;
+
+ this.isSticky = true;
+ this.$el.addClass('ws-sticky-on');
+
+ if(!this.isTable){
+ if( this.stickyData.width != this.$el.width()){
+ this.$el.width(this.stickyData.width);
+ }
+ }
+ },
+ getCommonStickyData: function(){
+ var marginTop = (parseFloat(this.$el.css('marginTop'), 10) || 0);
+
+ this.stickyData.scrollTop = this.stickyData.top - marginTop;
+
+ this.stickyData.outerHeight = this.$el.outerHeight(true);
+
+ this.stickyData.bottom = this.stickyData.top + this.stickyData.outerHeight - marginTop;
+
+ this.stickyData.width = this.$el.width();
+ this.stickyData.outerWidth = this.$el.outerWidth();
+
+ this.stickyData.marginLeft = parseFloat(this.$el.css('marginLeft'), 10) || 0;
+ this.stickyData.offsetLeft = this.$el[0].offsetLeft;
+
+ this.stickyData.inline.width = this.elStyle.width;
+ this.stickyData.inline.marginLeft = this.elStyle.marginLeft;
+
+ if(this.ankered == 'top'){
+ this.stickyData.inline.top = this.elStyle.top;
+ } else if(this.ankered == 'bottom'){
+ this.stickyData.inline.bottom = this.elStyle.bottom;
+ }
+ },
+ getCommonParentData: function(){
+ this.parentData.paddingTop = (parseFloat(this.$parent.css('paddingTop'), 10) || 0);
+
+ this.parentData.offsetTop = this.$parent.offset().top;
+ this.parentData.top = this.parentData.offsetTop + (parseFloat(this.$parent.css('borderTopWidth'), 10) || 0) + this.parentData.paddingTop;
+
+ this.parentData.height = this.$parent.height();
+ this.parentData.bottom = this.parentData.top + this.parentData.height;
+ }
+ };
+
+ if(isTouch && featureOptions.touchStrategy == 'disable'){return;}
+
+
+ function Sticky(dom) {
+
+ uid++;
+ stickys++;
+
+ this.evtid = '.wsstickyid' + uid;
+ this.$el = $(dom).data('wsSticky', this);
+ this.isTable = this.$el.is('thead, tbody, tfoot');
+ this.$parent = this.$el.parent();
+ this.elStyle = dom.style;
+
+
+ this.ankered = '';
+ this.isSticky = false;
+ this.$placeholder = null;
+
+ this.stickyData = {inline: {}};
+ this.parentData = {};
+
+ this.getParentData = this.getCommonParentData;
+
+
+ this.addEvents();
+ this.update(true);
+ }
+
+ $.extend(Sticky.prototype, stickyMixin, {
+ addEvents: function () {
+ var that = this;
+
+ this.commonAddEvents();
+
+ $window
+ .on('scroll' + this.evtid, function () {
+ if (!that.disabled && that.ankered && that.$el[0].offsetWidth) {
+ that.updatePos();
+ }
+ })
+ ;
+ },
+
+ getStickyData: function(){
+ this.stickyData.top = this.$el.offset().top;
+
+ this.getCommonStickyData();
+ },
+
+ updateDimension: function(fromPos){
+ if(this.isSticky){
+ this.removeSticky();
+ }
+ this.getParentData();
+ this.getStickyData();
+
+ if (this.ankered == 'bottom') {
+ this.viewportBottomAnker = $window.height() - this.position.bottom;
+ }
+
+ if(!fromPos && this.ankered){
+ this.updatePos(true);
+ }
+ },
+ updatePos: function(fromDimension){
+ var offset, shouldSticky, shouldMoveWith;
+ var scroll = getWinScroll();
+
+ if (this.ankered == 'top') {
+ offset = scroll + this.position.top;
+ if(this.stickyData.scrollTop < offset && scroll - 9 <= this.parentData.bottom){
+ shouldMoveWith = ((offset + this.stickyData.outerHeight) - this.parentData.bottom) * -1;
+
+ shouldSticky = true;
+ }
+ } else if (this.ankered == 'bottom') {
+ offset = scroll + this.viewportBottomAnker;
+
+ if(this.stickyData.bottom > offset &&
+ offset + 9 >= this.parentData.top){
+ shouldSticky = true;
+
+ shouldMoveWith = offset - this.parentData.top - this.stickyData.outerHeight;
+ }
+ }
+
+ if (shouldSticky) {
+ if (!this.isSticky) {
+
+ //updateDimension before layout trashing
+ if(!fromDimension){
+ this.updateDimension(true);
+ }
+
+ this.setSticky();
+ }
+
+
+ if(shouldMoveWith < 0){
+ if(this.ankered == 'top'){
+ this.elStyle.top = this.position.top + shouldMoveWith +'px';
+ } else if(this.ankered == 'bottom'){
+ this.elStyle.bottom = this.position.bottom + shouldMoveWith +'px';
+ }
+ }
+ } else if (this.isSticky) {
+ this.removeSticky();
+ }
+ }
+ });
+
+
+ function StickyParent(dom) {
+
+ uid++;
+ stickys++;
+
+ this.evtid = '.wsstickyid' + uid;
+ this.$el = $(dom).data('wsSticky', this);
+ this.isTable = this.$el.is('thead, tbody, tfoot');
+ this.$parent = this.$el.parent();
+ this.elStyle = dom.style;
+
+
+ this.ankered = '';
+ this.isSticky = false;
+ this.$placeholder = null;
+
+ this.stickyData = {inline: {}};
+ this.parentData = {};
+
+ if(this.$parent.css('position') == 'static'){
+ this.$parent.css('position', 'relative');
+ }
+
+ this.updatePos2 = this.updatePos2.bind(this);
+
+ this.addEvents();
+ this.update(true);
+
+ }
+
+ $.extend(StickyParent.prototype, stickyMixin, {
+ addEvents: function () {
+ var that = this;
+
+ this.commonAddEvents();
+
+ this.$parent
+ .on('scroll' + this.evtid, function () {
+ if (that.ankered && that.$el[0].offsetWidth) {
+ that.updatePos();
+ }
+ })
+ ;
+ },
+ getStickyData: function(){
+ this.stickyData.top = this.$el[0].offsetTop;
+
+ this.getCommonStickyData();
+ },
+ getParentData: function(){
+ this.getCommonParentData();
+
+ this.parentData.offsetBottom = this.parentData.top + this.$parent.outerHeight();
+ },
+ updateDimension: function(fromPos){
+ var add;
+ if(this.isSticky){
+ this.removeSticky();
+ }
+ this.getParentData();
+ this.getStickyData();
+
+ this.viewport = $window.height();
+
+ if(this.ankered == 'top'){
+ add = Math.abs(this.position.top) + 9;
+ } else if(this.ankered == 'bottom') {
+ add = Math.abs(this.position.bottom) + 9;
+ this.viewportBottomAnker = this.viewport - this.parentData.bottom;
+ this.compareBottom = this.stickyData.bottom + this.position.bottom;
+
+ this.addBottom = (this.parentData.bottom - this.parentData.paddingTop) - this.viewport;
+ }
+
+ this.viewPortMax = this.parentData.offsetBottom + add + 10;
+ this.viewPortMin = this.parentData.offsetTop - add - this.viewport;
+
+ if(!fromPos){
+ this.updatePos(true);
+ }
+ },
+ updatePos: function(fromDimension){
+ var offset, shouldSticky;
+ var scroll = this.$parent[0].scrollTop;
+
+ if (this.ankered == 'top') {
+ offset = scroll + this.position.top ;
+ if(this.stickyData.scrollTop - this.parentData.paddingTop < offset){
+ shouldSticky = true;
+ }
+ } else if (this.ankered == 'bottom') {
+ if(scroll + this.parentData.height < this.compareBottom){
+ shouldSticky = true;
+ }
+ }
+
+ if (shouldSticky) {
+ if (!this.isSticky) {
+
+ //updateDimension before layout trashing
+ if(!fromDimension){
+ this.updateDimension(true);
+ }
+
+ this.setSticky();
+
+ $window
+ .off('scroll' + this.evtid, this.updatePos2)
+ .on('scroll' + this.evtid, this.updatePos2)
+ ;
+ this.updatePos2(true);
+ }
+ } else if (this.isSticky) {
+ this.removeSticky();
+ $window.off('scroll' + this.evtid, this.updatePos2);
+ }
+ },
+ updatePos2: function(init){
+ var scrollTop = getWinScroll();
+
+ if(init === true || (this.viewPortMax > scrollTop && scrollTop > this.viewPortMin)){
+
+ if(this.ankered == 'top'){
+ if(init === true || (this.viewPortMax > scrollTop && scrollTop > this.viewPortMin)){
+ this.elStyle.top = this.position.top + this.parentData.top - scrollTop +'px';
+ }
+ } else if(this.ankered == 'bottom'){
+ this.elStyle.bottom = this.position.bottom + (scrollTop - this.addBottom) +'px';
+ }
+ }
+ }
+ });
+
+ var loadDomSupport = function(){
+ loadDomSupport = $.noop;
+ webshim.ready('WINDOWLOAD', function(){
+ webshim.loader.loadList(['dom-extend']);
+ webshim.ready('dom-extend', function(){
+ webshim.addShadowDom();
+ });
+ });
+ };
+
+ var addSticky = function(){
+ var stickyData = $.data(this, 'wsSticky');
+ if(!stickyData){
+ var $parent = $(this).parent();
+ $(this).addClass('ws-sticky');
+ if(($parent.css('overflowY') || $parent.css('overflow') || 'visible') == 'visible'){
+ new Sticky(this);
+ } else {
+ //webshim.warn('currently not supported');
+ new StickyParent(this);
+ }
+ loadDomSupport();
+ } else if(stickyData.disable) {
+ stickyData.disable(false);
+ }
+ };
+
+ if (!support.sticky && support.fixed) {
+ var selectors = {};
+ var createUpdateDomSearch = function(media, sels){
+ var i, created, elems;
+
+ var updated = [];
+
+ if(!selectors[media]){
+ selectors[media] = {sels: {}, string: '',
+ fn: function(context, insertedElement){
+ var elems = $(selectors[media].string, context).add(insertedElement.filter(selectors[media].string));
+ if(media){
+ elems.data('stickymedia', media);
+ }
+ elems.each(addSticky);
+ }
+ };
+ created = true;
+ }
+
+ for(i = 0; i < sels.length; i++){
+ if(!selectors[media].sels[sels[i]]){
+ selectors[media].sels[sels[i]] = true;
+ updated.push(sels[i]);
+ }
+ }
+
+ if(!created && !updated.length){return;}
+
+ selectors[media].string = Object.keys(selectors[media].sels).join(', ');
+
+ if(created){
+ $(function(){
+ webshim.addReady(selectors[media].fn);
+ });
+ } else if($.isReady){
+ elems = $(updated.join(', '));
+ if(media){
+ elems.data('stickymedia', media);
+ }
+ elems.each(addSticky);
+ }
+ };
+ createUpdateDomSearch('', ['.ws-sticky']);
+
+ $(function(){
+ $(document).on('wssticky', function(e){
+ addSticky.call(e.target);
+ });
+ });
+
+
+ if(featureOptions.parseCSS){
+ if(window.Polyfill && Polyfill.prototype && Polyfill.prototype.doMatched){
+ var onEnableRule = function(rule){
+ var curSelectors = rule.getSelectors().split(/\,\s*/g);
+ var media = (!rule._rule.media || !rule._rule.media.length) ? '' : rule.getMedia();
+ createUpdateDomSearch(media || '', curSelectors);
+ };
+
+ Polyfill({declarations:["position:sticky"]})
+ .doMatched(function(rules){
+ rules.each(onEnableRule);
+ })
+ ;
+
+ } else {
+ webshim.warn('Polyfill for CSS polyfilling made easy has to be included');
+ }
+ }
+ }
+
+ if(document.readyState == 'complete'){
+ webshim.isReady('WINDOWLOAD', true);
+ }
+});
diff --git a/public/webshims/shims/styles/forms-picker.css b/public/webshims/shims/styles/forms-picker.css
index 8783940d..f7b99ae9 100644
--- a/public/webshims/shims/styles/forms-picker.css
+++ b/public/webshims/shims/styles/forms-picker.css
@@ -439,3 +439,23 @@ SASS:
}
/* helper classes to hide show/hide specific picker features */
+.capture-popover .ws-po-box {
+ padding-left: 0.30769em;
+ padding-right: 0.30769em;
+}
+
+.ws-videocapture-view {
+ position: relative;
+ height: 0;
+ width: 100%;
+ padding-bottom: 70%;
+}
+.ws-videocapture-view .ws-video-overlay,
+.ws-videocapture-view video,
+.ws-videocapture-view .polyfill-video {
+ position: absolute !important;
+ top: 0;
+ left: 0;
+ width: 100% !important;
+ height: 100% !important;
+}
diff --git a/public/webshims/shims/styles/scss/forms-picker.scss b/public/webshims/shims/styles/scss/forms-picker.scss
index 7ff1d465..a80f4519 100644
--- a/public/webshims/shims/styles/scss/forms-picker.scss
+++ b/public/webshims/shims/styles/scss/forms-picker.scss
@@ -474,3 +474,26 @@ $button-bgcolor: #f5f5f5;
@extend %#{$class};
}
}
+
+.capture-popover .ws-po-box {
+ padding-left: em(4);
+ padding-right: em(4);
+}
+
+.ws-videocapture-view {
+ position: relative;
+ height: 0;
+ width: 100%;
+ padding-bottom: 70%;
+
+ .ws-video-overlay,
+ video,
+ .polyfill-video {
+ position: absolute !important;
+ top: 0;
+ left: 0;
+ width: 100% !important;
+ height: 100% !important;
+ }
+}
+
diff --git a/public/webshims/shims/styles/scss/shim.scss b/public/webshims/shims/styles/scss/shim.scss
index 60879d69..c7e97f63 100644
--- a/public/webshims/shims/styles/scss/shim.scss
+++ b/public/webshims/shims/styles/scss/shim.scss
@@ -602,7 +602,8 @@ summary.summary-has-focus {
outline-offset: -1px;
}
-.ws-custom-file {
+.ws-custom-file,
+.ws-capture-file {
position: relative;
overflow: hidden;
@@ -632,7 +633,9 @@ summary.summary-has-focus {
margin-right: 0.4em;
float: left;
}
+}
+.ws-custom-file {
.ws-file-value {
display: block;
overflow: hidden;
@@ -640,39 +643,6 @@ summary.summary-has-focus {
text-overflow: ellipsis;
}
- &:hover > button,
- &.ws-mouseenter > button,
- > input[type="file"]:focus ~ button {
- background: #fff;
- border-color: #999;
- background: #eee linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1));
- }
-
-
- &:hover > .ws-file-value,
- &.ws-mouseenter > .ws-file-value,
- > input[type="file"]:focus ~ .ws-file-value {
- border-color: #999;
- }
-
- &.ws-active > button,
- > input[type="file"]:active ~ button {
- border-color: #000;
- }
-
-
- &.ws-active > .ws-file-value,
- > input[type="file"]:active ~ .ws-file-value {
- border-color: #000;
- }
-
- > input[type="file"][disabled] ~ .ws-file-value,
- > input[type="file"][disabled] ~ button {
- border-color: #bbb;
- background: #eee;
- color: #999;
- }
-
> input[type="file"],
.ws-coverfile {
position: absolute;
@@ -717,4 +687,74 @@ summary.summary-has-focus {
> .moxie-shim {
z-index: 20;
}
+
+ &:hover > button,
+ &.ws-mouseenter > button,
+ > input[type="file"]:focus ~ button {
+ background: #fff;
+ border-color: #999;
+ background: #eee linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1));
+ }
+
+
+ &:hover > .ws-file-value,
+ &.ws-mouseenter > .ws-file-value,
+ > input[type="file"]:focus ~ .ws-file-value {
+ border-color: #999;
+ }
+
+ &.ws-active > button,
+ > input[type="file"]:active ~ button {
+ border-color: #000;
+ }
+
+
+ &.ws-active > .ws-file-value,
+ > input[type="file"]:active ~ .ws-file-value {
+ border-color: #000;
+ }
+
+ > input[type="file"][disabled] ~ .ws-file-value,
+ > input[type="file"][disabled] ~ button {
+ border-color: #bbb;
+ background: #eee;
+ color: #999;
+ }
+}
+
+.ws-sticky {
+ top: auto;
+ left: auto !important;
+ right: auto !important;
+ bottom: auto;
+ position: static;
+ position: -webkit-sticky;
+ position: -moz-sticky;
+ position: -ms-sticky;
+ position: -o-sticky;
+ position: sticky;
+ float: none !important;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+thead.ws-sticky,
+tbody.ws-sticky,
+tfoot.ws-sticky {
+ margin-left: -0.8px;
+ margin-right: -1px;
+}
+
+.ws-sticky.ws-sticky-on {
+ position: fixed !important;
+}
+
+.ws-fixedsticky-placeholder {
+ position: static !important;
+ visibility: hidden !important;
+ padding: 0;
+ border: none;
+ margin: 0;
+ left: -999px;
+ zoom: 1;
}
diff --git a/public/webshims/shims/styles/shim-ext.css b/public/webshims/shims/styles/shim-ext.css
index faada291..a4d94aec 100644
--- a/public/webshims/shims/styles/shim-ext.css
+++ b/public/webshims/shims/styles/shim-ext.css
@@ -5,7 +5,8 @@
top: -999999px;
}
-.ws-po-box button, .ws-custom-file > button {
+.ws-po-box button, .ws-custom-file > button,
+.ws-capture-file > button {
display: inline-block;
overflow: visible;
position: relative;
@@ -21,11 +22,13 @@
line-height: inherit;
touch-action: none;
}
-.ws-po-box button::-moz-focus-inner, .ws-custom-file > button::-moz-focus-inner {
+.ws-po-box button::-moz-focus-inner, .ws-custom-file > button::-moz-focus-inner,
+.ws-capture-file > button::-moz-focus-inner {
border: 0;
padding: 0;
}
-.ws-po-box button[disabled], .ws-custom-file > button[disabled] {
+.ws-po-box button[disabled], .ws-custom-file > button[disabled],
+.ws-capture-file > button[disabled] {
cursor: default;
color: #888;
}
@@ -587,17 +590,22 @@ summary.summary-has-focus {
outline-offset: -1px;
}
-.ws-custom-file {
+.ws-custom-file,
+.ws-capture-file {
position: relative;
overflow: hidden;
}
.ws-custom-file > button,
-.ws-custom-file > input {
+.ws-custom-file > input,
+.ws-capture-file > button,
+.ws-capture-file > input {
box-sizing: border-box;
cursor: pointer;
}
.ws-custom-file > button,
-.ws-custom-file > .ws-file-value {
+.ws-custom-file > .ws-file-value,
+.ws-capture-file > button,
+.ws-capture-file > .ws-file-value {
position: relative;
z-index: 0;
display: inline-block;
@@ -607,40 +615,18 @@ summary.summary-has-focus {
color: #333;
transition: 400ms all;
}
-.ws-custom-file > button {
+.ws-custom-file > button,
+.ws-capture-file > button {
margin-right: 0.4em;
float: left;
}
+
.ws-custom-file .ws-file-value {
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
-.ws-custom-file:hover > button, .ws-custom-file.ws-mouseenter > button,
-.ws-custom-file > input[type="file"]:focus ~ button {
- background: #fff;
- border-color: #999;
- background: #eeeeee linear-gradient(transparent, rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1));
-}
-.ws-custom-file:hover > .ws-file-value, .ws-custom-file.ws-mouseenter > .ws-file-value,
-.ws-custom-file > input[type="file"]:focus ~ .ws-file-value {
- border-color: #999;
-}
-.ws-custom-file.ws-active > button,
-.ws-custom-file > input[type="file"]:active ~ button {
- border-color: #000;
-}
-.ws-custom-file.ws-active > .ws-file-value,
-.ws-custom-file > input[type="file"]:active ~ .ws-file-value {
- border-color: #000;
-}
-.ws-custom-file > input[type="file"][disabled] ~ .ws-file-value,
-.ws-custom-file > input[type="file"][disabled] ~ button {
- border-color: #bbb;
- background: #eee;
- color: #999;
-}
.ws-custom-file > input[type="file"],
.ws-custom-file .ws-coverfile {
position: absolute;
@@ -680,6 +666,67 @@ summary.summary-has-focus {
.ws-custom-file > .moxie-shim {
z-index: 20;
}
+.ws-custom-file:hover > button, .ws-custom-file.ws-mouseenter > button,
+.ws-custom-file > input[type="file"]:focus ~ button {
+ background: #fff;
+ border-color: #999;
+ background: #eeeeee linear-gradient(transparent, rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1));
+}
+.ws-custom-file:hover > .ws-file-value, .ws-custom-file.ws-mouseenter > .ws-file-value,
+.ws-custom-file > input[type="file"]:focus ~ .ws-file-value {
+ border-color: #999;
+}
+.ws-custom-file.ws-active > button,
+.ws-custom-file > input[type="file"]:active ~ button {
+ border-color: #000;
+}
+.ws-custom-file.ws-active > .ws-file-value,
+.ws-custom-file > input[type="file"]:active ~ .ws-file-value {
+ border-color: #000;
+}
+.ws-custom-file > input[type="file"][disabled] ~ .ws-file-value,
+.ws-custom-file > input[type="file"][disabled] ~ button {
+ border-color: #bbb;
+ background: #eee;
+ color: #999;
+}
+
+.ws-sticky {
+ top: auto;
+ left: auto !important;
+ right: auto !important;
+ bottom: auto;
+ position: static;
+ position: -webkit-sticky;
+ position: -moz-sticky;
+ position: -ms-sticky;
+ position: -o-sticky;
+ position: sticky;
+ float: none !important;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+thead.ws-sticky,
+tbody.ws-sticky,
+tfoot.ws-sticky {
+ margin-left: -0.8px;
+ margin-right: -1px;
+}
+
+.ws-sticky.ws-sticky-on {
+ position: fixed !important;
+}
+
+.ws-fixedsticky-placeholder {
+ position: static !important;
+ visibility: hidden !important;
+ padding: 0;
+ border: none;
+ margin: 0;
+ left: -999px;
+ zoom: 1;
+}
/* style picker api */
/* how to use:
diff --git a/public/webshims/shims/styles/shim.css b/public/webshims/shims/styles/shim.css
index ae1a9b09..5765edb8 100644
--- a/public/webshims/shims/styles/shim.css
+++ b/public/webshims/shims/styles/shim.css
@@ -5,7 +5,8 @@
top: -999999px;
}
-.ws-po-box button, .ws-custom-file > button {
+.ws-po-box button, .ws-custom-file > button,
+.ws-capture-file > button {
display: inline-block;
overflow: visible;
position: relative;
@@ -21,11 +22,13 @@
line-height: inherit;
touch-action: none;
}
-.ws-po-box button::-moz-focus-inner, .ws-custom-file > button::-moz-focus-inner {
+.ws-po-box button::-moz-focus-inner, .ws-custom-file > button::-moz-focus-inner,
+.ws-capture-file > button::-moz-focus-inner {
border: 0;
padding: 0;
}
-.ws-po-box button[disabled], .ws-custom-file > button[disabled] {
+.ws-po-box button[disabled], .ws-custom-file > button[disabled],
+.ws-capture-file > button[disabled] {
cursor: default;
color: #888;
}
@@ -587,17 +590,22 @@ summary.summary-has-focus {
outline-offset: -1px;
}
-.ws-custom-file {
+.ws-custom-file,
+.ws-capture-file {
position: relative;
overflow: hidden;
}
.ws-custom-file > button,
-.ws-custom-file > input {
+.ws-custom-file > input,
+.ws-capture-file > button,
+.ws-capture-file > input {
box-sizing: border-box;
cursor: pointer;
}
.ws-custom-file > button,
-.ws-custom-file > .ws-file-value {
+.ws-custom-file > .ws-file-value,
+.ws-capture-file > button,
+.ws-capture-file > .ws-file-value {
position: relative;
z-index: 0;
display: inline-block;
@@ -607,40 +615,18 @@ summary.summary-has-focus {
color: #333;
transition: 400ms all;
}
-.ws-custom-file > button {
+.ws-custom-file > button,
+.ws-capture-file > button {
margin-right: 0.4em;
float: left;
}
+
.ws-custom-file .ws-file-value {
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
-.ws-custom-file:hover > button, .ws-custom-file.ws-mouseenter > button,
-.ws-custom-file > input[type="file"]:focus ~ button {
- background: #fff;
- border-color: #999;
- background: #eeeeee linear-gradient(transparent, rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1));
-}
-.ws-custom-file:hover > .ws-file-value, .ws-custom-file.ws-mouseenter > .ws-file-value,
-.ws-custom-file > input[type="file"]:focus ~ .ws-file-value {
- border-color: #999;
-}
-.ws-custom-file.ws-active > button,
-.ws-custom-file > input[type="file"]:active ~ button {
- border-color: #000;
-}
-.ws-custom-file.ws-active > .ws-file-value,
-.ws-custom-file > input[type="file"]:active ~ .ws-file-value {
- border-color: #000;
-}
-.ws-custom-file > input[type="file"][disabled] ~ .ws-file-value,
-.ws-custom-file > input[type="file"][disabled] ~ button {
- border-color: #bbb;
- background: #eee;
- color: #999;
-}
.ws-custom-file > input[type="file"],
.ws-custom-file .ws-coverfile {
position: absolute;
@@ -680,3 +666,64 @@ summary.summary-has-focus {
.ws-custom-file > .moxie-shim {
z-index: 20;
}
+.ws-custom-file:hover > button, .ws-custom-file.ws-mouseenter > button,
+.ws-custom-file > input[type="file"]:focus ~ button {
+ background: #fff;
+ border-color: #999;
+ background: #eeeeee linear-gradient(transparent, rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.1));
+}
+.ws-custom-file:hover > .ws-file-value, .ws-custom-file.ws-mouseenter > .ws-file-value,
+.ws-custom-file > input[type="file"]:focus ~ .ws-file-value {
+ border-color: #999;
+}
+.ws-custom-file.ws-active > button,
+.ws-custom-file > input[type="file"]:active ~ button {
+ border-color: #000;
+}
+.ws-custom-file.ws-active > .ws-file-value,
+.ws-custom-file > input[type="file"]:active ~ .ws-file-value {
+ border-color: #000;
+}
+.ws-custom-file > input[type="file"][disabled] ~ .ws-file-value,
+.ws-custom-file > input[type="file"][disabled] ~ button {
+ border-color: #bbb;
+ background: #eee;
+ color: #999;
+}
+
+.ws-sticky {
+ top: auto;
+ left: auto !important;
+ right: auto !important;
+ bottom: auto;
+ position: static;
+ position: -webkit-sticky;
+ position: -moz-sticky;
+ position: -ms-sticky;
+ position: -o-sticky;
+ position: sticky;
+ float: none !important;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+thead.ws-sticky,
+tbody.ws-sticky,
+tfoot.ws-sticky {
+ margin-left: -0.8px;
+ margin-right: -1px;
+}
+
+.ws-sticky.ws-sticky-on {
+ position: fixed !important;
+}
+
+.ws-fixedsticky-placeholder {
+ position: static !important;
+ visibility: hidden !important;
+ padding: 0;
+ border: none;
+ margin: 0;
+ left: -999px;
+ zoom: 1;
+}
diff --git a/public/webshims/shims/swf/JarisFLVPlayer.swf b/public/webshims/shims/swf/JarisFLVPlayer.swf
index 6d1fb7f8..cdf8259f 100644
Binary files a/public/webshims/shims/swf/JarisFLVPlayer.swf and b/public/webshims/shims/swf/JarisFLVPlayer.swf differ
diff --git a/public/webshims/shims/track-ui.js b/public/webshims/shims/track-ui.js
index e18dcb6b..983fefb2 100644
--- a/public/webshims/shims/track-ui.js
+++ b/public/webshims/shims/track-ui.js
@@ -48,7 +48,10 @@ webshims.register('track-ui', function($, webshims, window, document, undefined)
var usesNativeTrack = function(){
return !options.override && support.texttrackapi;
};
-
+ var requestAnimationFrame = window.cancelAnimationFrame && window.requestAnimationFrame || function(fn){
+ setTimeout(fn, 17);
+ };
+ var cancelAnimationFrame = window.cancelAnimationFrame || window.clearTimeout;
var trackDisplay = {
update: function(baseData, media){
if(!baseData.activeCues.length){
@@ -169,20 +172,42 @@ webshims.register('track-ui', function($, webshims, window, document, undefined)
return $.extend([], cueListProto);
};
}
+
+ function triggerCueEvent(cue, type, baseData, media, trackIndex){
+ var trackElem, compareTrack;
+ var cueChange = $.Event('cuechange');
+ if(!baseData.trackElements){
+ baseData.trackElements = media[0].getElementsByTagName('track');
+ }
+
+ trackElem = baseData.trackElements[trackIndex];
+
+ if(trackElem){
+ compareTrack = (webshims.data(trackElem, 'trackData') || {track: $.prop(trackElem, 'track')}).track;
+ if(compareTrack != cue.track){
+ trackElem = null;
+ }
+ }
+ $.event.trigger(cueChange, null, cue.track, true);
+
+ if(trackElem){
+ $.event.trigger(cueChange, null, trackElem, true);
+ }
+
+ $.event.trigger(type, null, cue, true);
+ }
- mediaelement.getActiveCue = function(track, media, time, baseData){
+ mediaelement.getActiveCue = function(track, media, time, baseData, trackIndex){
if(!track._lastFoundCue){
track._lastFoundCue = {index: 0, time: 0};
}
- if(support.texttrackapi && !options.override && !track._shimActiveCues){
+ if(!track._shimActiveCues && support.texttrackapi && !options.override){
track._shimActiveCues = mediaelement.createCueList();
}
var i = 0;
- var len;
- var cue;
-
+ var len, cue, delay;
for(; i < track.shimActiveCues.length; i++){
cue = track.shimActiveCues[i];
if(cue.startTime > time || cue.endTime < time){
@@ -191,10 +216,20 @@ webshims.register('track-ui', function($, webshims, window, document, undefined)
if(cue.pauseOnExit){
$(media).pause();
}
- $(track).triggerHandler('cuechange');
- $(cue).triggerHandler('exit');
- } else if(track.mode == 'showing' && showTracks[track.kind] && $.inArray(cue, baseData.activeCues) == -1){
- baseData.activeCues.push(cue);
+
+
+ triggerCueEvent(cue, 'exit', baseData, media, trackIndex);
+
+
+ } else {
+ delay = cue.endTime - time;
+ if(baseData.nextUpdateDelay > delay){
+ baseData.nextUpdateDelay = delay;
+ baseData.nextEvent = cue.endTime;
+ }
+ if(track.mode == 'showing' && showTracks[track.kind] && $.inArray(cue, baseData.activeCues) == -1){
+ baseData.activeCues.push(cue);
+ }
}
}
@@ -210,20 +245,182 @@ webshims.register('track-ui', function($, webshims, window, document, undefined)
if(track.mode == 'showing' && showTracks[track.kind]){
baseData.activeCues.push(cue);
}
- $(track).triggerHandler('cuechange');
- $(cue).triggerHandler('enter');
-
+
+ triggerCueEvent(cue, 'enter', baseData, media, trackIndex);
+
track._lastFoundCue.time = time;
track._lastFoundCue.index = i;
-
+
+ delay = cue.endTime - time;
+ if(baseData.nextUpdateDelay > delay){
+ baseData.nextUpdateDelay = delay;
+ baseData.nextEvent = cue.endTime;
+ }
}
if(cue.startTime > time){
+ delay = cue.startTime - time;
+ if(baseData.nextUpdateDelay > delay){
+ baseData.nextUpdateDelay = delay;
+ baseData.nextEvent = cue.startTime;
+ }
break;
}
}
};
-
+ var filterTrackImplementation = function(){
+ return webshims.implement(this, 'trackui');
+ };
+ var implementTrackUi = function(){
+ var baseData, trackList, updateTimer, updateTimer2, lastDelay, lastTime, invalidTracksTimer;
+ var treshHold = 0.27;
+ var elem = $(this);
+ var recheckI = 0;
+ var recheckId;
+ var reCheck = function(){
+ recheckI++;
+
+ //if recheckI is over 5 video might be paused, stalled or waiting,
+ //in this case abort and wait for the next play, playing or timeupdate event
+ if(recheckI < 9){
+ if(elem.prop('currentTime') > baseData.nextEvent){
+ recheckI = undefined;
+ getDisplayCues();
+ } else {
+ recheckId = requestAnimationFrame(reCheck);
+ }
+ } else {
+ recheckI = undefined;
+ }
+ };
+ var getDisplayCues = function(e){
+ var track, time;
+ if(!trackList || !baseData){
+ trackList = elem.prop('textTracks');
+ baseData = webshims.data(elem[0], 'mediaelementBase') || webshims.data(elem[0], 'mediaelementBase', {});
+
+ if(!baseData.displayedActiveCues){
+ baseData.displayedActiveCues = [];
+ }
+ }
+
+ if (!trackList){return;}
+ time = elem.prop('currentTime');
+
+ if(!time && time !== 0){return;}
+
+ if(baseData.nextEvent && e && e.type == 'timeupdate' && time >= lastTime && baseData.nextEvent - time > treshHold && time - lastTime < 9){
+ return;
+ }
+
+ lastTime = time;
+ lastDelay = baseData.nextUpdateDelay;
+ baseData.nextUpdateDelay = Number.MAX_VALUE;
+ baseData.activeCues = [];
+ for(var i = 0, len = trackList.length; i < len; i++){
+ track = trackList[i];
+ if(track.mode != 'disabled' && track.cues && track.cues.length){
+ mediaelement.getActiveCue(track, elem, time, baseData, i);
+ }
+ }
+ trackDisplay.update(baseData, elem);
+
+ clearTimeout(updateTimer);
+
+ if(baseData.nextUpdateDelay <= treshHold && (e || lastDelay != baseData.nextUpdateDelay) && baseData.nextUpdateDelay > 0){
+
+ lastDelay = baseData.nextUpdateDelay;
+
+ clearTimeout(updateTimer2);
+
+ if(recheckId){
+ cancelAnimationFrame(recheckId);
+ }
+ recheckI = 0;
+ updateTimer2 = setTimeout(reCheck, (baseData.nextUpdateDelay * 1000) + 9);
+ } else if(baseData.nextUpdateDelay >= Number.MAX_VALUE){
+ baseData.nextEvent = time + 2;
+ }
+ };
+ var invalidateTrackElems = function(){
+ if(baseData && baseData.trackElements){
+ delete baseData.trackElements;
+ }
+ };
+ var onUpdatCues = function(e){
+ if(baseData && e && (e.type == 'addtrack' || e.type == 'removetrack')){
+ clearTimeout(invalidTracksTimer);
+ invalidTracksTimer = setTimeout(invalidateTrackElems, 39);
+ }
+ clearTimeout(updateTimer);
+ updateTimer = setTimeout(getDisplayCues, 40);
+ };
+ var addTrackView = function(){
+ if(!trackList) {
+ if(baseData && 'blockTrackListUpdate' in baseData){
+ baseData.blockTrackListUpdate = true;
+ }
+ trackList = elem.prop('textTracks');
+ if(baseData && baseData.blockTrackListUpdate){
+ baseData.blockTrackListUpdate = false;
+ }
+ }
+ //as soon as change on trackList is implemented in all browsers we do not need to have 'updatetrackdisplay' anymore
+ $( [trackList] )
+ .off('.trackview')
+ .on('change.trackview addtrack.trackview removetrack.trackview', onUpdatCues)
+ ;
+ elem
+ .off('.trackview')
+ .on('emptied.trackview', invalidateTrackElems)
+ .on('play.trackview playing.trackview updatetrackdisplay.trackview seeked.trackview', onUpdatCues)
+ .on('timeupdate.trackview', getDisplayCues)
+ ;
+ };
+
+ elem.on('remove', function(e){
+ if(!e.originalEvent && baseData && baseData.trackDisplay){
+ setTimeout(function(){
+ baseData.trackDisplay.remove();
+ }, 4);
+ }
+ });
+
+ if(!usesNativeTrack()){
+ addTrackView();
+ } else {
+
+ if(elem.hasClass('nonnative-api-active')){
+ addTrackView();
+ }
+ elem
+ .on('mediaelementapichange trackapichange', function(){
+
+ if(!usesNativeTrack() || elem.hasClass('nonnative-api-active')){
+ addTrackView();
+ } else {
+ clearTimeout(updateTimer);
+ clearTimeout(updateTimer2);
+ if(recheckId){
+ cancelAnimationFrame(recheckId);
+ }
+
+ trackList = elem.prop('textTracks');
+ baseData = webshims.data(elem[0], 'mediaelementBase') || webshims.data(elem[0], 'mediaelementBase', {});
+ $.each(trackList, function(i, track){
+ if(track._shimActiveCues){
+ delete track._shimActiveCues;
+ }
+ });
+ $( [trackList] ).off('.trackview');
+ trackDisplay.hide(baseData);
+ elem.off('.trackview');
+ }
+ })
+ ;
+ }
+ };
+
if(usesNativeTrack()){
(function(){
var block;
@@ -265,102 +462,8 @@ webshims.register('track-ui', function($, webshims, window, document, undefined)
webshims.addReady(function(context, insertedElement){
$('video, audio', context)
.add(insertedElement.filter('video, audio'))
- .filter(function(){
- return webshims.implement(this, 'trackui');
- })
- .each(function(){
- var baseData, trackList, updateTimer, updateTimer2;
-
- var elem = $(this);
- var getDisplayCues = function(e){
- var track;
- var time;
-
- if(!trackList || !baseData){
- trackList = elem.prop('textTracks');
- baseData = webshims.data(elem[0], 'mediaelementBase') || webshims.data(elem[0], 'mediaelementBase', {});
- if(!baseData.displayedActiveCues){
- baseData.displayedActiveCues = [];
- }
- }
-
- if (!trackList){return;}
- time = elem.prop('currentTime');
-
- if(!time && time !== 0){return;}
- baseData.activeCues = [];
- for(var i = 0, len = trackList.length; i < len; i++){
- track = trackList[i];
- if(track.mode != 'disabled' && track.cues && track.cues.length){
- mediaelement.getActiveCue(track, elem, time, baseData);
- }
- }
-
- trackDisplay.update(baseData, elem);
-
- };
- var onUpdate = function(e){
- clearTimeout(updateTimer);
- if(e){
- if(e.type == 'timeupdate'){
- getDisplayCues();
- }
- updateTimer2 = setTimeout(onUpdate, 90);
- } else {
- updateTimer = setTimeout(getDisplayCues, 9);
- }
- };
- var addTrackView = function(){
- if(!trackList) {
- trackList = elem.prop('textTracks');
- }
- //as soon as change on trackList is implemented in all browsers we do not need to have 'updatetrackdisplay' anymore
- $( [trackList] ).on('change', onUpdate);
- elem
- .off('.trackview')
- .on('play.trackview timeupdate.trackview updatetrackdisplay.trackview', onUpdate)
- ;
- };
-
- elem.on('remove', function(e){
- if(!e.originalEvent && baseData && baseData.trackDisplay){
- setTimeout(function(){
- baseData.trackDisplay.remove();
- }, 4);
- }
- });
-
- if(!usesNativeTrack()){
- addTrackView();
- } else {
-
- if(elem.hasClass('nonnative-api-active')){
- addTrackView();
- }
- elem
- .on('mediaelementapichange trackapichange', function(){
-
- if(!usesNativeTrack() || elem.hasClass('nonnative-api-active')){
- addTrackView();
- } else {
- clearTimeout(updateTimer);
- clearTimeout(updateTimer2);
-
- trackList = elem.prop('textTracks');
- baseData = webshims.data(elem[0], 'mediaelementBase') || webshims.data(elem[0], 'mediaelementBase', {});
-
- $.each(trackList, function(i, track){
- if(track._shimActiveCues){
- delete track._shimActiveCues;
- }
- });
- trackDisplay.hide(baseData);
- elem.off('.trackview');
- }
- })
- ;
- }
- })
+ .filter(filterTrackImplementation)
+ .each(implementTrackUi)
;
});
});
diff --git a/public/webshims/shims/track.js b/public/webshims/shims/track.js
index 5bed9760..a982affd 100644
--- a/public/webshims/shims/track.js
+++ b/public/webshims/shims/track.js
@@ -66,8 +66,12 @@ webshims.register('track', function($, webshims, window, document, undefined){
var lastCue = this.cues[this.cues.length-1];
if(lastCue && lastCue.startTime > cue.startTime){
webshims.error("cue startTime higher than previous cue's startTime");
+ return;
}
}
+ if(cue.startTime >= cue.endTime ){
+ webshim.error('startTime >= endTime of cue: '+ cue.text);
+ }
if(cue.track && cue.track.removeCue){
cue.track.removeCue(cue);
}
@@ -159,6 +163,7 @@ webshims.register('track', function($, webshims, window, document, undefined){
for(i = 0, len = added.length; i < len; i++){
$([trackList]).triggerHandler($.Event({type: 'addtrack', track: added[i]}));
}
+ //todo: remove
if(baseData.scriptedTextTracks || removed.length){
$(this).triggerHandler('updatetrackdisplay');
}
@@ -175,7 +180,7 @@ webshims.register('track', function($, webshims, window, document, undefined){
setTimeout(function(){
$(track).closest('audio, video').triggerHandler('updatetrackdisplay');
trackData.isTriggering = false;
- }, 1);
+ }, 9);
}
};
var isDefaultTrack = (function(){
@@ -368,15 +373,10 @@ webshims.register('track', function($, webshims, window, document, undefined){
error: error
});
};
- if($.ajax && $.ajaxSettings.xhr){
- if(isDisabled){
- setTimeout(createAjax, loadingTracks * 2);
- } else {
- createAjax();
- }
+ if(isDisabled){
+ setTimeout(createAjax, loadingTracks * 2);
} else {
- webshims.ready('jajax', createAjax);
- webshims.loader.loadList(['jajax']);
+ createAjax();
}
} catch(er){
error();
diff --git a/public/webshims/shims/usermedia-core.js b/public/webshims/shims/usermedia-core.js
index 22ab9137..da54c3bc 100644
--- a/public/webshims/shims/usermedia-core.js
+++ b/public/webshims/shims/usermedia-core.js
@@ -5,6 +5,7 @@ webshim.register('usermedia-core', function($, webshim, window, document, undefi
var addUnPrefixed = function(){
navigator.getUserMedia = navigator[webshim.prefixed('getUserMedia', navigator)];
};
+
if(srcObjectName != 'srcObject'){
var hasURL = !!(window.URL && URL.createObjectURL);
webshim.defineNodeNamesProperty(['audio', 'video'], 'srcObject', {
@@ -23,6 +24,32 @@ webshim.register('usermedia-core', function($, webshim, window, document, undefi
});
}
+ (function(){
+ var streams = {};
+ var _nativeCreateObjectURL = URL.createObjectURL;
+ var _nativeRevokeObjectURL = URL.revokeObjectURL;
+
+ URL.createObjectURL = function(stream){
+
+ var url = stream;
+ if(_nativeCreateObjectURL && !stream._wsStreamId){
+ url = _nativeCreateObjectURL.apply(this, arguments);
+ } else if(stream._wsStreamId) {
+ url = stream._wsStreamId;
+ streams[url] = stream;
+ }
+ return url;
+ };
+
+ URL.revokeObjectURL = function(url){
+ if(streams[url]){
+ delete streams[url];
+ } else if (_nativeRevokeObjectURL){
+ return _nativeRevokeObjectURL.apply(this, arguments);
+ }
+ };
+ })();
+
webshim.ready(webshim.modules["usermedia-shim"].loaded ? 'usermedia-api' : 'usermedia-shim', addUnPrefixed);
});
diff --git a/public/webshims/shims/usermedia-shim.js b/public/webshims/shims/usermedia-shim.js
index 3cabe13c..9ceb6a2a 100644
--- a/public/webshims/shims/usermedia-shim.js
+++ b/public/webshims/shims/usermedia-shim.js
@@ -1,18 +1,15 @@
webshim.register('usermedia-shim', function($, webshim, window, document, undefined, options){
"use strict";
var addMediaAPI;
- var streamUrlPrefix = 'webshimstream';
var id = 0;
- var streams = {};
var streamCb = {};
var hasSwf = swfmini.hasFlashPlayerVersion('11.3');
- var mediaOptions = webshim.cfg.mediaelement;
var mediaelement = webshim.mediaelement;
var flashEvents = {
- NOT_SUPPORTED_ERROR: 1,
- PERMISSION_DENIED: 1,
+ NotSupportedError: 1,
+ PermissionDeniedError: 1,
//not implemented yet
- MANDATORY_UNSATISFIED_ERROR: 1,
+ ConstraintNotSatisfiedError: 1,
onUserSuccess: 1
};
var noSource = function(){
@@ -51,6 +48,13 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi
};
addMediaAPI();
+ /*
+ { width: 650 },
+ { width: { min: 650 }},
+ { frameRate: 60 },
+ { width: { max: 800 }},
+ { facingMode: "user" }
+ */
mediaelement.createSWF(media, {srcProp: src, streamrequest: true, type: 'jarisplayer/stream'});
}
@@ -73,6 +77,8 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi
function LocalMediaStream(data, api, id){
+ data._cTNow = Date.now();
+ data._cTID = false;
webshim.defineProperties(this, {
_swf: {
value: api,
@@ -92,20 +98,34 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi
LocalMediaStream.prototype = {
- currentTime: 0,
stop: function(){
+ if(this._data._cTID){
+ clearInterval(this._data._cTID);
+ }
mediaelement.queueSwfMethod(this._data._elem, 'api_detach', [], this._data);
- },
- getAudioTracks: $.noop,
- getVideoTracks: $.noop
+ this._data.ended = true;
+ $(this._data._elem).trigger('ended');
+ }
};
webshim.usermedia = {
attach: function(elem, canPlaySrc, data){
+ var $media;
if(data._usermedia == canPlaySrc.srcProp){
mediaelement.queueSwfMethod(data._elem, 'api_attach', [], data);
- $(data._elem).trigger('loadstart');
+ $media = $(data._elem).trigger('loadstart');
+ data._cTID = setInterval(function(){
+ if(data.ended){
+ clearInterval(data._cTID);
+ } else if(!data.paused){
+ data.currentTime = (Date.now() - data._cTNow) / 1000;
+ $media.triggerHandler('timeupdate');
+ }
+ }, 250);
+ if(!data.paused){
+ mediaelement.queueSwfMethod(data._elem, 'api_play', [], data);
+ }
} else {
webshim.error('something went wrong');
}
@@ -120,30 +140,7 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi
}
};
- URL._nativeCreateObjectURL = URL.createObjectURL;
- URL._nativeRevokeObjectURL = URL.revokeObjectURL;
- URL.createObjectURL = function(stream){
-
- var url = '';
- if(URL._nativeCreateObjectURL && !stream._wsStreamId){
- url = URL._nativeCreateObjectURL(stream);
- } else if(stream._wsStreamId) {
- url = stream._wsStreamId;
- streams[url] = stream;
- }
- return url;
- };
-
- URL.revokeObjectURL = function(url){
- if(streams[url]){
- delete streams[url];
- }
- if(URL._nativeRevokeObjectURL){
- return URL._nativeRevokeObjectURL(url);
- }
- };
- webshim.usermediastreams = streams;
addMediaAPI = function(){
if(!webshim.mediaelement.createSWF){return;}
@@ -161,10 +158,10 @@ webshim.register('usermedia-shim', function($, webshim, window, document, undefi
streamCb[data._usermedia].fail({name: jaris.type});
};
$.extend(mediaelement.onEvent, {
- NOT_SUPPORTED_ERROR: fail,
- PERMISSION_DENIED: fail,
+ NotSupportedError: fail,
+ PermissionDeniedError: fail,
//not implemented yet
- MANDATORY_UNSATISFIED_ERROR: fail,
+ ConstraintNotSatisfiedError: fail,
onUserSuccess: function(jaris, data){
revert(data);
streamCb[data._usermedia].success(new LocalMediaStream(data, data.api, data._usermedia));