);
-
}
});
-let EditionDetailHistoryIterator = React.createClass({
- propTypes: {
- history: React.PropTypes.array
- },
-
- render() {
- return (
-
- );
- }
-});
-
-let EditionPersonalNote = React.createClass({
- propTypes: {
- edition: React.PropTypes.object,
- currentUser: React.PropTypes.object,
- handleSuccess: React.PropTypes.func
- },
- showNotification(){
- this.props.handleSuccess();
- let notification = new GlobalNotificationModel(getLangText('Private note saved'), 'success');
- GlobalNotificationActions.appendGlobalNotification(notification);
- },
-
- render() {
- if (this.props.currentUser.username && true || false) {
- return (
-
- );
- }
- return null;
- }
-});
-
-let EditionPublicEditionNote = React.createClass({
- propTypes: {
- edition: React.PropTypes.object,
- handleSuccess: React.PropTypes.func
- },
- showNotification(){
- this.props.handleSuccess();
- let notification = new GlobalNotificationModel(getLangText('Public note saved'), 'success');
- GlobalNotificationActions.appendGlobalNotification(notification);
- },
- render() {
- let isEditable = this.props.edition.acl.acl_edit;
- if (isEditable || this.props.edition.public_note){
- return (
-
- );
- }
- return null;
- }
-});
-
let CoaDetails = React.createClass({
propTypes: {
edition: React.PropTypes.object
diff --git a/js/components/ascribe_detail/edition_container.js b/js/components/ascribe_detail/edition_container.js
index 15086434..0f726ae5 100644
--- a/js/components/ascribe_detail/edition_container.js
+++ b/js/components/ascribe_detail/edition_container.js
@@ -9,6 +9,8 @@ import Edition from './edition';
import AppConstants from '../../constants/application_constants';
+
+
/**
* This is the component that implements resource/data specific functionality
*/
@@ -34,6 +36,15 @@ let EditionContainer = React.createClass({
EditionActions.fetchOne(this.props.params.editionId);
},
+ // This is done to update the container when the user clicks on the prev or next
+ // button to update the URL parameter (and therefore to switch pieces)
+ componentWillReceiveProps(nextProps) {
+ if(this.props.params.editionId !== nextProps.params.editionId) {
+ EditionActions.updateEdition({});
+ EditionActions.fetchOne(nextProps.params.editionId);
+ }
+ },
+
componentWillUnmount() {
// Every time we're leaving the edition detail page,
// just reset the edition that is saved in the edition store
@@ -50,7 +61,7 @@ let EditionContainer = React.createClass({
},
render() {
- if('title' in this.state.edition) {
+ if(this.state.edition && this.state.edition.title) {
return (
file.status !== 'deleted' && file.status !== 'canceled');
- if(files.length > 0 && files[0].status === 'upload successful') {
- return true;
- } else {
- return false;
- }
- },
-
render() {
- //return ();
return (
@@ -90,93 +76,23 @@ let FurtherDetails = React.createClass({
editable={this.props.editable}
pieceId={this.props.pieceId}
extraData={this.props.extraData} />
-
+
);
}
});
-let FileUploader = React.createClass({
- propTypes: {
- pieceId: React.PropTypes.number,
- otherData: React.PropTypes.object,
- setIsUploadReady: React.PropTypes.func,
- submitKey: React.PropTypes.func,
- isReadyForFormSubmission: React.PropTypes.func,
- editable: React.PropTypes.bool
- },
- render() {
- // Essentially there a three cases important to the fileuploader
- //
- // 1. there is no other_data => do not show the fileuploader at all
- // 2. there is other_data, but user has no edit rights => show fileuploader but without action buttons
- // 3. both other_data and editable are defined or true => show fileuploade with all action buttons
- if (!this.props.editable && !this.props.otherData){
- return null;
- }
- return (
-
- );
- }
-});
export default FurtherDetails;
diff --git a/js/components/ascribe_detail/further_details_fileuploader.js b/js/components/ascribe_detail/further_details_fileuploader.js
new file mode 100644
index 00000000..9bf0bd5b
--- /dev/null
+++ b/js/components/ascribe_detail/further_details_fileuploader.js
@@ -0,0 +1,97 @@
+'use strict';
+
+import React from 'react';
+
+import Property from './../ascribe_forms/property';
+
+import ReactS3FineUploader from './../ascribe_uploader/react_s3_fine_uploader';
+
+import ApiUrls from '../../constants/api_urls';
+import AppConstants from '../../constants/application_constants';
+
+import { getCookie } from '../../utils/fetch_api_utils';
+
+let FurtherDetailsFileuploader = React.createClass({
+ propTypes: {
+ uploadStarted: React.PropTypes.func,
+ pieceId: React.PropTypes.number,
+ otherData: React.PropTypes.arrayOf(React.PropTypes.object),
+ setIsUploadReady: React.PropTypes.func,
+ submitFile: React.PropTypes.func,
+ isReadyForFormSubmission: React.PropTypes.func,
+ editable: React.PropTypes.bool,
+ multiple: React.PropTypes.bool
+ },
+
+ getDefaultProps() {
+ return {
+ multiple: false
+ };
+ },
+
+ render() {
+ // Essentially there a three cases important to the fileuploader
+ //
+ // 1. there is no other_data => do not show the fileuploader at all (where otherData is now an array)
+ // 2. there is other_data, but user has no edit rights => show fileuploader but without action buttons
+ // 3. both other_data and editable are defined or true => show fileuploader with all action buttons
+ if (!this.props.editable && (!this.props.otherData || this.props.otherData.length === 0)) {
+ return null;
+ }
+
+ let otherDataIds = this.props.otherData ? this.props.otherData.map((data) => data.id).join() : null;
+
+ return (
+
+
+
+ );
+ }
+});
+
+export default FurtherDetailsFileuploader;
\ No newline at end of file
diff --git a/js/components/ascribe_detail/history_iterator.js b/js/components/ascribe_detail/history_iterator.js
new file mode 100644
index 00000000..54d11a5b
--- /dev/null
+++ b/js/components/ascribe_detail/history_iterator.js
@@ -0,0 +1,33 @@
+'use strict';
+
+import React from 'react';
+
+import Form from '../ascribe_forms/form';
+import Property from '../ascribe_forms/property';
+
+let HistoryIterator = React.createClass({
+ propTypes: {
+ history: React.PropTypes.array
+ },
+
+ render() {
+ return (
+
+ );
+ }
+});
+
+export default HistoryIterator;
diff --git a/js/components/ascribe_detail/license_detail.js b/js/components/ascribe_detail/license_detail.js
new file mode 100644
index 00000000..c3cc9f62
--- /dev/null
+++ b/js/components/ascribe_detail/license_detail.js
@@ -0,0 +1,31 @@
+'use strict';
+
+import React from 'react';
+
+import DetailProperty from './detail_property';
+
+/**
+ * This is the component that implements display-specific functionality
+ */
+let LicenseDetail = React.createClass({
+ propTypes: {
+ license: React.PropTypes.object
+ },
+ render () {
+ if (this.props.license.code === 'default') {
+ return null;
+ }
+ return (
+
+ { this.props.license.code.toUpperCase() + ': ' + this.props.license.name}
+
+ }
+ />
+ );
+ }
+});
+
+export default LicenseDetail;
diff --git a/js/components/ascribe_detail/media_container.js b/js/components/ascribe_detail/media_container.js
index 2ff5a55d..6ac2f745 100644
--- a/js/components/ascribe_detail/media_container.js
+++ b/js/components/ascribe_detail/media_container.js
@@ -19,7 +19,33 @@ const EMBED_IFRAME_HEIGHT = {
let MediaContainer = React.createClass({
propTypes: {
- content: React.PropTypes.object
+ content: React.PropTypes.object,
+ refreshObject: React.PropTypes.func
+ },
+
+ getInitialState() {
+ return {timerId: null};
+ },
+
+ componentDidMount() {
+ if (!this.props.content.digital_work) {
+ return;
+ }
+ let isEncoding = this.props.content.digital_work.isEncoding;
+ if (this.props.content.digital_work.mime === 'video' && typeof isEncoding === 'number' && isEncoding !== 100 && !this.state.timerId) {
+ let timerId = window.setInterval(this.props.refreshObject, 10000);
+ this.setState({timerId: timerId});
+ }
+ },
+
+ componentWillUpdate() {
+ if (this.props.content.digital_work.isEncoding === 100) {
+ window.clearInterval(this.state.timerId);
+ }
+ },
+
+ componentWillUnmount() {
+ window.clearInterval(this.state.timerId);
},
render() {
@@ -46,7 +72,7 @@ let MediaContainer = React.createClass({
}
panel={
- {''}
}/>
diff --git a/js/components/ascribe_detail/note.js b/js/components/ascribe_detail/note.js
new file mode 100644
index 00000000..c739b937
--- /dev/null
+++ b/js/components/ascribe_detail/note.js
@@ -0,0 +1,65 @@
+'use strict';
+
+import React from 'react';
+
+import Form from './../ascribe_forms/form';
+import Property from './../ascribe_forms/property';
+import InputTextAreaToggable from './../ascribe_forms/input_textarea_toggable';
+
+import GlobalNotificationModel from '../../models/global_notification_model';
+import GlobalNotificationActions from '../../actions/global_notification_actions';
+
+import { getLangText } from '../../utils/lang_utils';
+
+let Note = React.createClass({
+ propTypes: {
+ url: React.PropTypes.string,
+ id: React.PropTypes.func,
+ label: React.PropTypes.string,
+ currentUser: React.PropTypes.object,
+ defaultValue: React.PropTypes.string,
+ editable: React.PropTypes.bool,
+ show: React.PropTypes.bool,
+ placeholder: React.PropTypes.string,
+ successMessage: React.PropTypes.string
+ },
+
+ getDefaultProps() {
+ return {
+ editable: true,
+ show: true,
+ placeholder: getLangText('Enter a note'),
+ successMessage: getLangText('Note saved')
+ };
+ },
+
+ showNotification(){
+ let notification = new GlobalNotificationModel(this.props.successMessage, 'success');
+ GlobalNotificationActions.appendGlobalNotification(notification);
+ },
+
+ render() {
+ if ((!!this.props.currentUser.username && this.props.editable || !this.props.editable ) && this.props.show) {
+ return (
+
+ );
+ }
+ return null;
+ }
+});
+
+export default Note;
\ No newline at end of file
diff --git a/js/components/ascribe_detail/piece.js b/js/components/ascribe_detail/piece.js
index 3fabb055..ed312f5f 100644
--- a/js/components/ascribe_detail/piece.js
+++ b/js/components/ascribe_detail/piece.js
@@ -1,38 +1,14 @@
'use strict';
import React from 'react';
-import Router from 'react-router';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
-import DetailProperty from './detail_property';
-
-import UserActions from '../../actions/user_actions';
-import UserStore from '../../stores/user_store';
-
-import PieceListActions from '../../actions/piece_list_actions';
-import PieceListStore from '../../stores/piece_list_store';
-
-import EditionListActions from '../../actions/edition_list_actions';
-
import PieceActions from '../../actions/piece_actions';
import MediaContainer from './media_container';
-import EditionDetailProperty from './detail_property';
-
-import AclButtonList from './../ascribe_buttons/acl_button_list';
-import CreateEditionsForm from '../ascribe_forms/create_editions_form';
-import CreateEditionsButton from '../ascribe_buttons/create_editions_button';
-import DeleteButton from '../ascribe_buttons/delete_button';
-
-import GlobalNotificationModel from '../../models/global_notification_model';
-import GlobalNotificationActions from '../../actions/global_notification_actions';
-
-import { getLangText } from '../../utils/lang_utils';
-import { mergeOptions } from '../../utils/general_utils';
-
/**
* This is the component that implements display-specific functionality
@@ -40,97 +16,16 @@ import { mergeOptions } from '../../utils/general_utils';
let Piece = React.createClass({
propTypes: {
piece: React.PropTypes.object,
+ header: React.PropTypes.object,
+ subheader: React.PropTypes.object,
+ buttons: React.PropTypes.object,
loadPiece: React.PropTypes.func,
children: React.PropTypes.object
},
- mixins: [Router.Navigation],
- getInitialState() {
- return mergeOptions(
- UserStore.getState(),
- PieceListStore.getState(),
- {
- showCreateEditionsDialog: false
- }
- );
- },
-
- componentDidMount() {
- UserStore.listen(this.onChange);
- PieceListStore.listen(this.onChange);
- UserActions.fetchCurrentUser();
- },
-
- componentWillUnmount() {
- UserStore.unlisten(this.onChange);
- PieceListStore.unlisten(this.onChange);
- },
-
- onChange(state) {
- this.setState(state);
- },
-
- toggleCreateEditionsDialog() {
- this.setState({
- showCreateEditionsDialog: !this.state.showCreateEditionsDialog
- });
- },
-
- handleEditionCreationSuccess() {
- PieceActions.updateProperty({key: 'num_editions', value: 0});
- PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
- this.state.orderBy, this.state.orderAsc, this.state.filterBy);
- this.toggleCreateEditionsDialog();
- },
-
- handleDeleteSuccess(response) {
- PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
- this.state.orderBy, this.state.orderAsc, this.state.filterBy);
-
- // since we're deleting a piece, we just need to close
- // all editions dialogs and not reload them
- EditionListActions.closeAllEditionLists();
- EditionListActions.clearAllEditionSelections();
-
- let notification = new GlobalNotificationModel(response.notification, 'success');
- GlobalNotificationActions.appendGlobalNotification(notification);
-
- this.transitionTo('pieces');
- },
-
- getCreateEditionsDialog() {
- if(this.props.piece.num_editions < 1 && this.state.showCreateEditionsDialog) {
- return (
-
-
-
-
- );
- } else {
- return ();
- }
- },
-
- handlePollingSuccess(pieceId, numEditions) {
-
- // we need to refresh the num_editions property of the actual piece we're looking at
- PieceActions.updateProperty({
- key: 'num_editions',
- value: numEditions
- });
-
- // as well as its representation in the collection
- // btw.: It's not sufficient to just set num_editions to numEditions, since a single accordion
- // list item also uses the firstEdition property which we can only get from the server in that case.
- // Therefore we need to at least refetch the changed piece from the server or on our case simply all
- PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
- this.state.orderBy, this.state.orderAsc, this.state.filterBy);
-
- let notification = new GlobalNotificationModel('Editions successfully created', 'success', 10000);
- GlobalNotificationActions.appendGlobalNotification(notification);
+ updateObject() {
+ return PieceActions.fetchOne(this.props.piece.id);
},
render() {
@@ -138,38 +33,14 @@ let Piece = React.createClass({
+ {this.props.header}
+ {this.props.subheader}
+ {this.props.buttons}
-
-
-
-
-
- {this.getCreateEditionsDialog()}
{this.props.children}
diff --git a/js/components/ascribe_detail/piece_container.js b/js/components/ascribe_detail/piece_container.js
index 8e3a5750..c2eb1759 100644
--- a/js/components/ascribe_detail/piece_container.js
+++ b/js/components/ascribe_detail/piece_container.js
@@ -1,37 +1,66 @@
'use strict';
import React from 'react';
+import Router from 'react-router';
import PieceActions from '../../actions/piece_actions';
import PieceStore from '../../stores/piece_store';
+import PieceListActions from '../../actions/piece_list_actions';
+import PieceListStore from '../../stores/piece_list_store';
+
+import UserActions from '../../actions/user_actions';
+import UserStore from '../../stores/user_store';
+
+import EditionListActions from '../../actions/edition_list_actions';
+
import Piece from './piece';
import CollapsibleParagraph from './../ascribe_collapsible/collapsible_paragraph';
import FurtherDetails from './further_details';
+import DetailProperty from './detail_property';
+import LicenseDetail from './license_detail';
+import HistoryIterator from './history_iterator';
+
+import AclButtonList from './../ascribe_buttons/acl_button_list';
+import CreateEditionsForm from '../ascribe_forms/create_editions_form';
+import CreateEditionsButton from '../ascribe_buttons/create_editions_button';
+import DeleteButton from '../ascribe_buttons/delete_button';
+
+import ListRequestActions from '../ascribe_forms/list_form_request_actions';
+
+import GlobalNotificationModel from '../../models/global_notification_model';
+import GlobalNotificationActions from '../../actions/global_notification_actions';
+
+import Note from './note';
+
+import ApiUrls from '../../constants/api_urls';
import AppConstants from '../../constants/application_constants';
+import { mergeOptions } from '../../utils/general_utils';
+import { getLangText } from '../../utils/lang_utils';
/**
* This is the component that implements resource/data specific functionality
*/
let PieceContainer = React.createClass({
- getInitialState() {
- return PieceStore.getState();
- },
- onChange(state) {
- this.setState(state);
- if (!state.piece.digital_work) {
- return;
- }
- let isEncoding = state.piece.digital_work.isEncoding;
- if (state.piece.digital_work.mime === 'video' && typeof isEncoding === 'number' && isEncoding !== 100 && !this.state.timerId) {
- let timerId = window.setInterval(() => PieceActions.fetchOne(this.props.params.pieceId), 10000);
- this.setState({timerId: timerId});
- }
+ mixins: [Router.Navigation],
+
+ getInitialState() {
+ return mergeOptions(
+ UserStore.getState(),
+ PieceListStore.getState(),
+ PieceStore.getState(),
+ {
+ showCreateEditionsDialog: false
+ }
+ );
},
componentDidMount() {
+ UserStore.listen(this.onChange);
+ PieceListStore.listen(this.onChange);
+ UserActions.fetchCurrentUser();
PieceStore.listen(this.onChange);
PieceActions.fetchOne(this.props.params.pieceId);
},
@@ -42,26 +71,190 @@ let PieceContainer = React.createClass({
// as it will otherwise display wrong/old data once the user loads
// the piece detail a second time
PieceActions.updatePiece({});
- window.clearInterval(this.state.timerId);
PieceStore.unlisten(this.onChange);
+ UserStore.unlisten(this.onChange);
+ PieceListStore.unlisten(this.onChange);
},
+ onChange(state) {
+ /*
+
+ ATTENTION:
+ THIS IS JUST A TEMPORARY USABILITY FIX THAT ESSENTIALLY REMOVES THE LOAN BUTTON
+ FROM THE PIECE DETAIL PAGE SO THAT USERS DO NOT CONFUSE A PIECE WITH AN EDITION.
+
+ IT SHOULD BE REMOVED AND REPLACED WITH A BETTER SOLUTION ASAP!
+
+ ALSO, WE ENABLED THE LOAN BUTTON FOR IKONOTV TO LET THEM LOAN ON A PIECE LEVEL
+
+ */
+ if(state && state.piece && state.piece.acl && typeof state.piece.acl.acl_loan !== 'undefined') {
+
+ let pieceState = mergeOptions({}, state.piece);
+ pieceState.acl.acl_loan = false;
+
+ this.setState({
+ piece: pieceState
+ });
+
+ } else {
+ this.setState(state);
+ }
+ },
loadPiece() {
PieceActions.fetchOne(this.props.params.pieceId);
},
+
+ toggleCreateEditionsDialog() {
+ this.setState({
+ showCreateEditionsDialog: !this.state.showCreateEditionsDialog
+ });
+ },
+
+ handleEditionCreationSuccess() {
+ PieceActions.updateProperty({key: 'num_editions', value: 0});
+ PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
+ this.state.orderBy, this.state.orderAsc, this.state.filterBy);
+ this.toggleCreateEditionsDialog();
+ },
+
+ handleDeleteSuccess(response) {
+ PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
+ this.state.orderBy, this.state.orderAsc, this.state.filterBy);
+
+ // since we're deleting a piece, we just need to close
+ // all editions dialogs and not reload them
+ EditionListActions.closeAllEditionLists();
+ EditionListActions.clearAllEditionSelections();
+
+ let notification = new GlobalNotificationModel(response.notification, 'success');
+ GlobalNotificationActions.appendGlobalNotification(notification);
+
+ this.transitionTo('pieces');
+ },
+
+ getCreateEditionsDialog() {
+ if(this.state.piece.num_editions < 1 && this.state.showCreateEditionsDialog) {
+ return (
+
+
+
+
+ );
+ } else {
+ return ();
+ }
+ },
+
+ handlePollingSuccess(pieceId, numEditions) {
+
+ // we need to refresh the num_editions property of the actual piece we're looking at
+ PieceActions.updateProperty({
+ key: 'num_editions',
+ value: numEditions
+ });
+
+ // as well as its representation in the collection
+ // btw.: It's not sufficient to just set num_editions to numEditions, since a single accordion
+ // list item also uses the firstEdition property which we can only get from the server in that case.
+ // Therefore we need to at least refetch the changed piece from the server or on our case simply all
+ PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
+ this.state.orderBy, this.state.orderAsc, this.state.filterBy);
+
+ let notification = new GlobalNotificationModel('Editions successfully created', 'success', 10000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
+ },
+
+ getId() {
+ return {'id': this.state.piece.id};
+ },
+
+ getActions() {
+ if (this.state.piece &&
+ this.state.piece.notifications &&
+ this.state.piece.notifications.length > 0) {
+ return (
+ );
+ }
+ else {
+ return (
+
+
+
+
+ );
+ }
+ },
+
render() {
- if('title' in this.state.piece) {
+ if(this.state.piece && this.state.piece.title) {
return (
+ loadPiece={this.loadPiece}
+ header={
+
+
+
+
+ {this.getContracts()}
+
+ {getLangText('Appendix')}
+ {/* We're using disabled on a form here as PropertyCollapsible currently
+ does not support the disabled + overrideForm functionality */}
+
+
+
+ );
+ }
+ return (
+
+
+ {getLangText('No contracts uploaded yet, please go to the ')}
+ {getLangText('settings page')}
+ {getLangText(' and create them.')}
+
+
+ );
+ }
+});
+
+export default ContractAgreementForm;
\ No newline at end of file
diff --git a/js/components/ascribe_forms/form_copyright_association.js b/js/components/ascribe_forms/form_copyright_association.js
new file mode 100644
index 00000000..da14e76d
--- /dev/null
+++ b/js/components/ascribe_forms/form_copyright_association.js
@@ -0,0 +1,80 @@
+'use strict';
+
+import React from 'react';
+
+import GlobalNotificationModel from '../../models/global_notification_model';
+import GlobalNotificationActions from '../../actions/global_notification_actions';
+
+import Form from './form';
+import Property from './property';
+
+import ApiUrls from '../../constants/api_urls';
+import AppConstants from '../../constants/application_constants';
+
+import { getLangText } from '../../utils/lang_utils';
+
+let CopyrightAssociationForm = React.createClass({
+ propTypes: {
+ currentUser: React.PropTypes.object
+ },
+
+ handleSubmitSuccess(){
+ let notification = getLangText('Copyright association updated');
+ notification = new GlobalNotificationModel(notification, 'success', 10000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
+ },
+
+ getProfileFormData(){
+ return {email: this.props.currentUser.email};
+ },
+
+ render() {
+ let selectedState;
+ let selectDefaultValue = ' -- ' + getLangText('select an association') + ' -- ';
+
+ if (this.props.currentUser && this.props.currentUser.profile
+ && this.props.currentUser.profile.copyright_association) {
+ selectedState = AppConstants.copyrightAssociations.indexOf(this.props.currentUser.profile.copyright_association);
+ selectedState = selectedState !== -1 ? AppConstants.copyrightAssociations[selectedState] : selectDefaultValue;
+ }
+
+ if (this.props.currentUser && this.props.currentUser.email){
+ return (
+
+
+
+
+
+
+ );
+ }
+ return null;
+ }
+});
+
+export default CopyrightAssociationForm;
\ No newline at end of file
diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js
new file mode 100644
index 00000000..b19cb050
--- /dev/null
+++ b/js/components/ascribe_forms/form_create_contract.js
@@ -0,0 +1,111 @@
+'use strict';
+
+import React from 'react';
+
+import Form from '../ascribe_forms/form';
+import Property from '../ascribe_forms/property';
+
+import GlobalNotificationModel from '../../models/global_notification_model';
+import GlobalNotificationActions from '../../actions/global_notification_actions';
+
+import ContractListActions from '../../actions/contract_list_actions';
+
+import AppConstants from '../../constants/application_constants';
+import ApiUrls from '../../constants/api_urls';
+
+import InputFineUploader from './input_fineuploader';
+
+import { getLangText } from '../../utils/lang_utils';
+import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
+
+
+let CreateContractForm = React.createClass({
+ propTypes: {
+ isPublic: React.PropTypes.bool,
+
+ // A class of a file the user has to upload
+ // Needs to be defined both in singular as well as in plural
+ fileClassToUpload: React.PropTypes.shape({
+ singular: React.PropTypes.string,
+ plural: React.PropTypes.string
+ })
+ },
+
+ getInitialState() {
+ return {
+ isUploadReady: false,
+ contractName: ''
+ };
+ },
+
+ setIsUploadReady(isReady) {
+ this.setState({
+ isUploadReady: isReady
+ });
+ },
+
+ handleCreateSuccess(response) {
+ ContractListActions.fetchContractList(true);
+ let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
+ this.refs.form.reset();
+ },
+
+ submitFileName(fileName) {
+ this.setState({
+ contractName: fileName
+ });
+
+ this.refs.form.submit();
+ },
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+});
+
+export default CreateContractForm;
\ No newline at end of file
diff --git a/js/components/ascribe_forms/form_delete_edition.js b/js/components/ascribe_forms/form_delete_edition.js
index c05a20bc..9eb721f6 100644
--- a/js/components/ascribe_forms/form_delete_edition.js
+++ b/js/components/ascribe_forms/form_delete_edition.js
@@ -2,33 +2,65 @@
import React from 'react';
-import requests from '../../utils/requests';
+import Form from './form';
+
import ApiUrls from '../../constants/api_urls';
-import FormMixin from '../../mixins/form_mixin';
+import AppConstants from '../../constants/application_constants';
+
import { getLangText } from '../../utils/lang_utils';
+
let EditionDeleteForm = React.createClass({
- mixins: [FormMixin],
+ propTypes: {
+ editions: React.PropTypes.arrayOf(React.PropTypes.object),
- url() {
- return requests.prepareUrl(ApiUrls.edition_delete, {edition_id: this.getBitcoinIds().join()});
- },
- httpVerb(){
- return 'delete';
+ // Propagated by ModalWrapper in most cases
+ handleSuccess: React.PropTypes.func
},
- renderForm () {
+ getBitcoinIds() {
+ return this.props.editions.map(function(edition){
+ return edition.bitcoin_id;
+ });
+ },
+
+ // Since this form can be used for either deleting a single edition or multiple
+ // we need to call getBitcoinIds to get the value of edition_id
+ getFormData() {
+ return {
+ edition_id: this.getBitcoinIds().join(',')
+ };
+ },
+
+ render () {
return (
-
+
+
+
+
+
+ }
+ spinner={
+
+
+
+ }>
{getLangText('Are you sure you would like to permanently delete this edition')}?
{getLangText('This is an irrevocable action%s', '.')}
-
-
-
-
-
+
);
}
});
diff --git a/js/components/ascribe_forms/form_delete_piece.js b/js/components/ascribe_forms/form_delete_piece.js
index 168d9261..552c38c0 100644
--- a/js/components/ascribe_forms/form_delete_piece.js
+++ b/js/components/ascribe_forms/form_delete_piece.js
@@ -2,37 +2,56 @@
import React from 'react';
-import requests from '../../utils/requests';
+import Form from '../ascribe_forms/form';
+
import ApiUrls from '../../constants/api_urls';
-import FormMixin from '../../mixins/form_mixin';
+import AppConstants from '../../constants/application_constants';
+
import { getLangText } from '../../utils/lang_utils';
+
let PieceDeleteForm = React.createClass({
propTypes: {
- pieceId: React.PropTypes.number
+ pieceId: React.PropTypes.number,
+
+ // Propagated by ModalWrapper in most cases
+ handleSuccess: React.PropTypes.func
},
- mixins: [FormMixin],
-
- url() {
- return requests.prepareUrl(ApiUrls.piece, {piece_id: this.props.pieceId});
+ getFormData() {
+ return {
+ piece_id: this.props.pieceId
+ };
},
- httpVerb() {
- return 'delete';
- },
-
- renderForm () {
+ render() {
return (
-
+
+
+
+
+
+ }
+ spinner={
+
+
+
+ }>
{getLangText('Are you sure you would like to permanently delete this piece')}?
{getLangText('This is an irrevocable action%s', '.')}
-
-
-
-
-
+
);
}
});
diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js
index 7aae656a..ef2fbd13 100644
--- a/js/components/ascribe_forms/form_loan.js
+++ b/js/components/ascribe_forms/form_loan.js
@@ -2,6 +2,8 @@
import React from 'react';
+import classnames from 'classnames';
+
import Button from 'react-bootstrap/lib/Button';
import Form from './form';
@@ -10,70 +12,150 @@ import InputTextAreaToggable from './input_textarea_toggable';
import InputDate from './input_date';
import InputCheckbox from './input_checkbox';
-import LoanContractStore from '../../stores/loan_contract_store';
-import LoanContractActions from '../../actions/loan_contract_actions';
+import ContractAgreementListStore from '../../stores/contract_agreement_list_store';
+import ContractAgreementListActions from '../../actions/contract_agreement_list_actions';
import AppConstants from '../../constants/application_constants';
+import { mergeOptions } from '../../utils/general_utils';
import { getLangText } from '../../utils/lang_utils';
let LoanForm = React.createClass({
propTypes: {
+ loanHeading: React.PropTypes.string,
+ email: React.PropTypes.string,
+ gallery: React.PropTypes.string,
+ startdate: React.PropTypes.object,
+ enddate: React.PropTypes.object,
+ showPersonalMessage: React.PropTypes.bool,
+ showEndDate: React.PropTypes.bool,
+ showStartDate: React.PropTypes.bool,
+ showPassword: React.PropTypes.bool,
url: React.PropTypes.string,
id: React.PropTypes.object,
message: React.PropTypes.string,
- onRequestHide: React.PropTypes.func,
+ createPublicContractAgreement: React.PropTypes.bool,
handleSuccess: React.PropTypes.func
},
+ getDefaultProps() {
+ return {
+ loanHeading: '',
+ showPersonalMessage: true,
+ showEndDate: true,
+ showStartDate: true,
+ showPassword: true,
+ createPublicContractAgreement: true
+ };
+ },
+
getInitialState() {
- return LoanContractStore.getState();
+ return ContractAgreementListStore.getState();
},
componentDidMount() {
- LoanContractStore.listen(this.onChange);
- LoanContractActions.flushLoanContract();
+ ContractAgreementListStore.listen(this.onChange);
+ this.getContractAgreementsOrCreatePublic(this.props.email);
+ },
+
+ /**
+ * This method needs to be in form_loan as some whitelabel pages (Cyland) load
+ * the loanee's email async!
+ *
+ * SO LEAVE IT IN!
+ */
+ componentWillReceiveProps(nextProps) {
+ if(nextProps && nextProps.email && this.props.email !== nextProps.email) {
+ this.getContractAgreementsOrCreatePublic(nextProps.email);
+ }
},
componentWillUnmount() {
- LoanContractStore.unlisten(this.onChange);
+ ContractAgreementListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
- getFormData(){
- return this.props.id;
+ getContractAgreementsOrCreatePublic(email){
+ ContractAgreementListActions.flushContractAgreementList.defer();
+ if (email) {
+ // fetch the available contractagreements (pending/accepted)
+ ContractAgreementListActions.fetchAvailableContractAgreementList(email, true);
+ }
},
- handleOnBlur(event) {
- LoanContractActions.fetchLoanContract(event.target.value);
+ getFormData(){
+ return mergeOptions(
+ this.props.id,
+ this.getContractAgreementId()
+ );
+ },
+
+ handleOnChange(event) {
+ // event.target.value is the submitted email of the loanee
+ if(event && event.target && event.target.value && event.target.value.match(/.*@.*\..*/)) {
+ this.getContractAgreementsOrCreatePublic(event.target.value);
+ } else {
+ ContractAgreementListActions.flushContractAgreementList();
+ }
+ },
+
+ getContractAgreementId() {
+ if (this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
+ return {'contract_agreement_id': this.state.contractAgreementList[0].id};
+ }
+ return {};
},
getContractCheckbox() {
- if(this.state.contractKey && this.state.contractUrl) {
+ if(this.state.contractAgreementList && this.state.contractAgreementList.length > 0) {
// we need to define a key on the InputCheckboxes as otherwise
// react is not rerendering them on a store switch and is keeping
// the default value of the component (which is in that case true)
- return (
-
-
-
- {getLangText('I agree to the')}
-
- {getLangText('terms of')} {this.state.contractEmail}
-
-
-
-
- );
+ let contractAgreement = this.state.contractAgreementList[0];
+ let contract = contractAgreement.contract;
+
+ if(contractAgreement.datetime_accepted) {
+ return (
+
+
+ {/* We still need to send the server information that we're accepting */}
+
+
+ );
+ } else {
+ return (
+
+
+
+ {getLangText('I agree to the')}
+
+ {getLangText('terms of ')} {contract.issuer}
+
+
+
+
+ );
+ }
} else {
return (
0) {
+ let appendix = this.state.contractAgreementList[0].appendix;
+ if (appendix && appendix.default) {
+ return (
+
+
+ );
+ }
+ return null;
+ }
+});
+
+export default ListRequestActions;
\ No newline at end of file
diff --git a/js/components/ascribe_forms/property.js b/js/components/ascribe_forms/property.js
index 5a72270c..f3c26935 100644
--- a/js/components/ascribe_forms/property.js
+++ b/js/components/ascribe_forms/property.js
@@ -6,10 +6,22 @@ import ReactAddons from 'react/addons';
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
import Tooltip from 'react-bootstrap/lib/Tooltip';
+import AppConstants from '../../constants/application_constants';
+
+import { mergeOptions } from '../../utils/general_utils';
+
+
let Property = React.createClass({
propTypes: {
hidden: React.PropTypes.bool,
+
editable: React.PropTypes.bool,
+
+ // If we want Form to have a different value for disabled as Property has one for
+ // editable, we need to set overrideForm to true, as it will then override Form's
+ // disabled value for individual Properties
+ overrideForm: React.PropTypes.bool,
+
tooltip: React.PropTypes.element,
label: React.PropTypes.string,
value: React.PropTypes.oneOfType([
@@ -20,8 +32,11 @@ let Property = React.createClass({
handleChange: React.PropTypes.func,
ignoreFocus: React.PropTypes.bool,
className: React.PropTypes.string,
+
onClick: React.PropTypes.func,
onChange: React.PropTypes.func,
+ onBlur: React.PropTypes.func,
+
children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(React.PropTypes.element),
React.PropTypes.element
@@ -55,7 +70,7 @@ let Property = React.createClass({
// In order to set this.state.value from another component
// the state of value should only be set if its not undefined and
// actually references something
- if(typeof childInput.getDOMNode().value !== 'undefined') {
+ if(childInput && typeof childInput.getDOMNode().value !== 'undefined') {
this.setState({
value: childInput.getDOMNode().value
});
@@ -78,21 +93,41 @@ let Property = React.createClass({
},
reset() {
+ let input = this.refs.input;
+
// maybe do reset by reload instead of front end state?
this.setState({value: this.state.initialValue});
- // resets the value of a custom react component input
- this.refs.input.state.value = this.state.initialValue;
+ if(input.state && input.state.value) {
+ // resets the value of a custom react component input
+ input.state.value = this.state.initialValue;
+ }
- // resets the value of a plain HTML5 input
- this.refs.input.getDOMNode().value = this.state.initialValue;
+ // For some reason, if we set the value of a non HTML element (but a custom input),
+ // after a reset, the value will be be propagated to this component.
+ //
+ // Therefore we have to make sure only to reset the initial value
+ // of HTML inputs (which we determine by checking if there 'type' attribute matches
+ // the ones included in AppConstants.possibleInputTypes).
+ let inputDOMNode = input.getDOMNode();
+ if(inputDOMNode.type && typeof inputDOMNode.type === 'string' &&
+ AppConstants.possibleInputTypes.indexOf(inputDOMNode.type.toLowerCase()) > -1) {
+ inputDOMNode.value = this.state.initialValue;
+ }
+ // For some inputs, reseting state.value is not enough to visually reset the
+ // component.
+ //
+ // So if the input actually needs a visual reset, it needs to implement
+ // a dedicated reset method.
+ if(typeof input.reset === 'function') {
+ input.reset();
+ }
},
handleChange(event) {
-
this.props.handleChange(event);
- if ('onChange' in this.props) {
+ if (typeof this.props.onChange === 'function') {
this.props.onChange(event);
}
@@ -108,7 +143,7 @@ let Property = React.createClass({
// if onClick is defined from the outside,
// just call it
- if(this.props.onClick) {
+ if(typeof this.props.onClick === 'function') {
this.props.onClick();
}
@@ -123,7 +158,7 @@ let Property = React.createClass({
isFocused: false
});
- if(this.props.onBlur) {
+ if(typeof this.props.onBlur === 'function') {
this.props.onBlur(event);
}
},
@@ -167,9 +202,10 @@ let Property = React.createClass({
}
},
- renderChildren() {
+ renderChildren(style) {
return ReactAddons.Children.map(this.props.children, (child) => {
return ReactAddons.addons.cloneWithProps(child, {
+ style,
onChange: this.handleChange,
onFocus: this.handleFocus,
onBlur: this.handleBlur,
@@ -180,34 +216,42 @@ let Property = React.createClass({
},
render() {
+ let footer = null;
let tooltip = ;
- if (this.props.tooltip){
+ let style = this.props.style ? mergeOptions({}, this.props.style) : {};
+
+ if(this.props.tooltip){
tooltip = (
{this.props.tooltip}
);
}
- let footer = null;
- if (this.props.footer){
+
+ if(this.props.footer){
footer = (
+ }
+ leftColumnWidth="60%"
+ rightColumnWidth="40%"/>
+ );
+ })}
+
+
+
+
+ );
+ }
+});
+
+export default ContractSettings;
\ No newline at end of file
diff --git a/js/components/ascribe_settings/contract_settings_update_button.js b/js/components/ascribe_settings/contract_settings_update_button.js
new file mode 100644
index 00000000..f2e54c50
--- /dev/null
+++ b/js/components/ascribe_settings/contract_settings_update_button.js
@@ -0,0 +1,98 @@
+'use strict';
+
+import React from 'react';
+
+import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
+import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button';
+
+import AppConstants from '../../constants/application_constants';
+import ApiUrls from '../../constants/api_urls';
+
+import ContractListActions from '../../actions/contract_list_actions';
+
+import GlobalNotificationModel from '../../models/global_notification_model';
+import GlobalNotificationActions from '../../actions/global_notification_actions';
+
+import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
+import { getCookie } from '../../utils/fetch_api_utils';
+import { getLangText } from '../../utils/lang_utils';
+
+
+let ContractSettingsUpdateButton = React.createClass({
+ propTypes: {
+ contract: React.PropTypes.object
+ },
+
+ submitFile(file) {
+ let contract = this.props.contract;
+
+ // override the blob with the key's value
+ contract.blob = file.key;
+
+ // send it to the server
+ ContractListActions
+ .changeContract(contract)
+ .then((res) => {
+
+ // Display feedback to the user
+ let notification = new GlobalNotificationModel(getLangText('Contract %s successfully updated', res.name), 'success', 5000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
+
+ // and refresh the contract list to get the updated contracs
+ return ContractListActions.fetchContractList(true);
+ })
+ .then(() => {
+ // Also, reset the fineuploader component so that the user can again 'update' his contract
+ this.refs.fineuploader.reset();
+ })
+ .catch((err) => {
+ console.logGlobal(err);
+ let notification = new GlobalNotificationModel(getLangText('Contract could not be updated'), 'success', 5000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
+ });
+ },
+
+ render() {
+ return (
+ {/* So that ReactS3FineUploader is not complaining */}}
+ signature={{
+ endpoint: AppConstants.serverUrl + 's3/signature/',
+ customHeaders: {
+ 'X-CSRFToken': getCookie(AppConstants.csrftoken)
+ }
+ }}
+ deleteFile={{
+ enabled: true,
+ method: 'DELETE',
+ endpoint: AppConstants.serverUrl + 's3/delete',
+ customHeaders: {
+ 'X-CSRFToken': getCookie(AppConstants.csrftoken)
+ }
+ }}
+ fileClassToUpload={{
+ singular: getLangText('UPDATE'),
+ plural: getLangText('UPDATE')
+ }}
+ isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
+ submitFile={this.submitFile}
+ />
+ );
+ }
+});
+
+export default ContractSettingsUpdateButton;
\ No newline at end of file
diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js
new file mode 100644
index 00000000..2b9ae2a1
--- /dev/null
+++ b/js/components/ascribe_settings/settings_container.js
@@ -0,0 +1,84 @@
+'use strict';
+
+import React from 'react';
+import Router from 'react-router';
+
+import UserStore from '../../stores/user_store';
+import UserActions from '../../actions/user_actions';
+
+import WhitelabelStore from '../../stores/whitelabel_store';
+import WhitelabelActions from '../../actions/whitelabel_actions';
+
+import AccountSettings from './account_settings';
+import BitcoinWalletSettings from './bitcoin_wallet_settings';
+import APISettings from './api_settings';
+
+import AclProxy from '../acl_proxy';
+
+import { mergeOptions } from '../../utils/general_utils';
+
+
+let SettingsContainer = React.createClass({
+ propTypes: {
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.arrayOf(React.PropTypes.element),
+ React.PropTypes.element])
+ },
+
+ mixins: [Router.Navigation],
+
+ getInitialState() {
+ return mergeOptions(
+ UserStore.getState(),
+ WhitelabelStore.getState()
+ );
+ },
+
+ componentDidMount() {
+ UserStore.listen(this.onChange);
+ WhitelabelStore.listen(this.onChange);
+
+ WhitelabelActions.fetchWhitelabel();
+ UserActions.fetchCurrentUser();
+ },
+
+ componentWillUnmount() {
+ WhitelabelStore.unlisten(this.onChange);
+ UserStore.unlisten(this.onChange);
+ },
+
+ loadUser(){
+ UserActions.fetchCurrentUser();
+ },
+
+ onChange(state) {
+ this.setState(state);
+ },
+
+ render() {
+ if (this.state.currentUser && this.state.currentUser.username) {
+ return (
+
+
+ {this.props.children}
+
+
+
+
+
+
+
+ );
+ }
+ return null;
+ }
+});
+
+export default SettingsContainer;
diff --git a/js/components/ascribe_slides_container/slides_container.js b/js/components/ascribe_slides_container/slides_container.js
index 67286385..53092a38 100644
--- a/js/components/ascribe_slides_container/slides_container.js
+++ b/js/components/ascribe_slides_container/slides_container.js
@@ -4,12 +4,21 @@ import React from 'react';
import Router from 'react-router';
import ReactAddons from 'react/addons';
+import SlidesContainerBreadcrumbs from './slides_container_breadcrumbs';
+
let State = Router.State;
let Navigation = Router.Navigation;
+
let SlidesContainer = React.createClass({
propTypes: {
- children: React.PropTypes.arrayOf(React.PropTypes.element)
+ children: React.PropTypes.arrayOf(React.PropTypes.element),
+ forwardProcess: React.PropTypes.bool.isRequired,
+
+ glyphiconClassNames: React.PropTypes.shape({
+ pending: React.PropTypes.string,
+ complete: React.PropTypes.string
+ })
},
mixins: [State, Navigation],
@@ -18,15 +27,25 @@ let SlidesContainer = React.createClass({
// handle queryParameters
let queryParams = this.getQuery();
let slideNum = -1;
+ let startFrom = -1;
+ // We can actually need to check if slide_num is present as a key in queryParams.
+ // We do not really care about its value though...
if(queryParams && 'slide_num' in queryParams) {
slideNum = parseInt(queryParams.slide_num, 10);
}
// if slide_num is not set, this will be done in componentDidMount
+ // the query param 'start_from' removes all slide children before the respective number
+ // Also, we use the 'in' keyword for the same reason as above in 'slide_num'
+ if(queryParams && 'start_from' in queryParams) {
+ startFrom = parseInt(queryParams.start_from, 10);
+ }
+
return {
+ slideNum,
+ startFrom,
containerWidth: 0,
- slideNum: slideNum,
historyLength: window.history.length
};
},
@@ -34,6 +53,9 @@ let SlidesContainer = React.createClass({
componentDidMount() {
// check if slide_num was defined, and if not then default to 0
let queryParams = this.getQuery();
+
+ // We use 'in' to check if the key is present in the user's browser url bar,
+ // we do not really care about its value at this point
if(!('slide_num' in queryParams)) {
// we're first requiring all the other possible queryParams and then set
@@ -51,9 +73,23 @@ let SlidesContainer = React.createClass({
window.addEventListener('resize', this.handleContainerResize);
},
- componentDidUpdate() {
- // check if slide_num was defined, and if not then default to 0
+ componentWillReceiveProps() {
let queryParams = this.getQuery();
+
+ // also check if start_from was updated
+ // This applies for example when the user tries to submit a already existing piece
+ // (starting from slide 1 for example) and then clicking on + NEW WORK
+ if(queryParams && !('start_from' in queryParams)) {
+ this.setState({
+ startFrom: -1
+ });
+ }
+ },
+
+ componentDidUpdate() {
+ let queryParams = this.getQuery();
+
+ // check if slide_num was defined, and if not then default to 0
this.setSlideNum(queryParams.slide_num);
},
@@ -68,6 +104,12 @@ let SlidesContainer = React.createClass({
});
},
+ // When the start_from parameter is used, this.setSlideNum can not simply be used anymore.
+ nextSlide() {
+ let nextSlide = this.state.slideNum + 1;
+ this.setSlideNum(nextSlide);
+ },
+
// We let every one from the outsite set the page number of the slider,
// though only if the slideNum is actually in the range of our children-list.
setSlideNum(slideNum) {
@@ -84,7 +126,6 @@ let SlidesContainer = React.createClass({
// then we want to "replace" (in this case append) the current url with ?slide_num=0
if(isNaN(slideNum) && this.state.slideNum === -1) {
slideNum = 0;
-
queryParams.slide_num = slideNum;
this.replaceWith(this.getPathname(), null, queryParams);
@@ -98,7 +139,7 @@ let SlidesContainer = React.createClass({
// if slideNum is within the range of slides and none of the previous cases
// where matched, we can actually do transitions
- } else if(slideNum >= 0 || slideNum < React.Children.count(this.props.children)) {
+ } else if(slideNum >= 0 || slideNum < this.customChildrenCount()) {
if(slideNum !== this.state.slideNum - 1) {
// Bootstrapping the component, getInitialState is called once to save
@@ -108,13 +149,17 @@ let SlidesContainer = React.createClass({
// we push a new state on it ONCE (ever).
// Otherwise, we're able to use the browsers history.forward() method
// to keep the stack clean
- if(this.state.historyLength === window.history.length) {
-
+
+ if(this.props.forwardProcess) {
queryParams.slide_num = slideNum;
-
this.transitionTo(this.getPathname(), null, queryParams);
} else {
- window.history.forward();
+ if(this.state.historyLength === window.history.length) {
+ queryParams.slide_num = slideNum;
+ this.transitionTo(this.getPathname(), null, queryParams);
+ } else {
+ window.history.forward();
+ }
}
}
@@ -127,34 +172,108 @@ let SlidesContainer = React.createClass({
}
},
+ // breadcrumbs are defined as attributes of the slides.
+ // To extract them we have to read the DOM element's attributes
+ extractBreadcrumbs() {
+ let breadcrumbs = [];
+
+ ReactAddons.Children.map(this.props.children, (child, i) => {
+ if(child && i >= this.state.startFrom && child.props['data-slide-title']) {
+ breadcrumbs.push(child.props['data-slide-title']);
+ }
+ });
+
+ return breadcrumbs;
+ },
+
+ // If startFrom is defined as a URL parameter, this can manipulate
+ // the number of children that are injected into the DOM.
+ // Therefore React.Children.count does not work anymore and we
+ // need to implement our own method.
+ customChildrenCount() {
+ let count = 0;
+ React.Children.forEach(this.props.children, (child, i) => {
+ if(i >= this.state.startFrom) {
+ count++;
+ }
+ });
+
+ return count;
+ },
+
+ renderBreadcrumbs() {
+ let breadcrumbs = this.extractBreadcrumbs();
+ let numOfChildren = this.customChildrenCount();
+
+ // check if every child/slide has a title,
+ // otherwise do not display the breadcrumbs at all
+ // Also, if there is only one child, do not display the breadcrumbs
+ if(breadcrumbs.length === numOfChildren && breadcrumbs.length > 1 && numOfChildren > 1) {
+ return (
+
+ );
+ } else {
+ return null;
+ }
+ },
+
// Since we need to give the slides a width, we need to call ReactAddons.addons.cloneWithProps
// Also, a key is nice to have!
renderChildren() {
return ReactAddons.Children.map(this.props.children, (child, i) => {
- return ReactAddons.addons.cloneWithProps(child, {
- className: 'ascribe-slide',
- style: {
- width: this.state.containerWidth
- },
- key: i
- });
+
+ // since the default parameter of startFrom is -1, we do not need to check
+ // if its actually present in the url bar, as it will just not match
+ if(child && i >= this.state.startFrom) {
+ return ReactAddons.addons.cloneWithProps(child, {
+ className: 'ascribe-slide',
+ style: {
+ width: this.state.containerWidth
+ },
+ key: i
+ });
+ } else {
+ // Abortions are bad mkay
+ return null;
+ }
+
});
},
render() {
+ let spacing = this.state.containerWidth * this.state.slideNum;
+ let translateXValue = 'translateX(' + (-1) * spacing + 'px)';
+
+ /*
+ According to the react documentation,
+ all browser vendor prefixes need to be upper cases in the beginning except for
+ the Microsoft one *bigfuckingsurprise*
+ https://facebook.github.io/react/tips/inline-styles.html
+ */
+
return (
+ {this.renderBreadcrumbs()}
-
- {this.renderChildren()}
-
+
+ {this.renderChildren()}
+
);
diff --git a/js/components/ascribe_slides_container/slides_container_breadcrumbs.js b/js/components/ascribe_slides_container/slides_container_breadcrumbs.js
new file mode 100644
index 00000000..6d361ca2
--- /dev/null
+++ b/js/components/ascribe_slides_container/slides_container_breadcrumbs.js
@@ -0,0 +1,85 @@
+'use strict';
+
+import React from 'react';
+
+import classnames from 'classnames';
+
+import Col from 'react-bootstrap/lib/Col';
+
+
+// Note:
+//
+// If we ever need generic breadcrumbs component, we should refactor this
+let SlidesContainerBreadcrumbs = React.createClass({
+ propTypes: {
+ breadcrumbs: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
+
+ slideNum: React.PropTypes.number.isRequired,
+ numOfSlides: React.PropTypes.number.isRequired,
+
+ containerWidth: React.PropTypes.number.isRequired,
+
+ glyphiconClassNames: React.PropTypes.shape({
+ pending: React.PropTypes.string,
+ complete: React.PropTypes.string
+ })
+ },
+
+ getDefaultProps() {
+ return {
+ glyphiconClassNames: {
+ pending: 'glyphicon glyphicon-chevron-right',
+ complete: 'glyphicon glyphicon-lock'
+ }
+ };
+ },
+
+ render() {
+ let breadcrumbs = this.props.breadcrumbs;
+ let numSlides = breadcrumbs.length;
+ let columnWidth = Math.floor(12 / numSlides);
+
+ return (
+
+
+
+ {breadcrumbs.map((breadcrumb, i) => {
+
+ // Depending on the progress the user has already made, we display different
+ // glyphicons that can also be specified from the outside
+ let glyphiconClassName;
+
+ if(i >= this.props.slideNum) {
+ glyphiconClassName = this.props.glyphiconClassNames.pending;
+ } else {
+ glyphiconClassName = this.props.glyphiconClassNames.completed;
+ }
+
+ return (
+
);
}
diff --git a/js/components/ascribe_uploader/file_drag_and_drop_dialog.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_dialog.js
similarity index 67%
rename from js/components/ascribe_uploader/file_drag_and_drop_dialog.js
rename to js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_dialog.js
index 306eb6f1..f74eb713 100644
--- a/js/components/ascribe_uploader/file_drag_and_drop_dialog.js
+++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_dialog.js
@@ -3,7 +3,7 @@
import React from 'react';
import Router from 'react-router';
-import { getLangText } from '../../utils/lang_utils';
+import { getLangText } from '../../../utils/lang_utils';
let Link = Router.Link;
@@ -12,7 +12,14 @@ let FileDragAndDropDialog = React.createClass({
hasFiles: React.PropTypes.bool,
multipleFiles: React.PropTypes.bool,
onClick: React.PropTypes.func,
- enableLocalHashing: React.PropTypes.bool
+ enableLocalHashing: React.PropTypes.bool,
+
+ // A class of a file the user has to upload
+ // Needs to be defined both in singular as well as in plural
+ fileClassToUpload: React.PropTypes.shape({
+ singular: React.PropTypes.string,
+ plural: React.PropTypes.string
+ })
},
mixins: [Router.State],
@@ -32,7 +39,7 @@ let FileDragAndDropDialog = React.createClass({
queryParamsUpload.method = 'upload';
return (
-
+
{getLangText('Would you rather')}
-
+
);
} else {
if(this.props.multipleFiles) {
return (
- {getLangText('Click or drag to add files')}
+
+
+ {getLangText('choose %s to upload', this.props.fileClassToUpload.plural)}
+
);
} else {
- let dialog = queryParams.method === 'hash' ? getLangText('choose a file to hash') : getLangText('choose a file to upload');
+ let dialog = queryParams.method === 'hash' ? getLangText('choose a %s to hash', this.props.fileClassToUpload.singular) : getLangText('choose a %s to upload', this.props.fileClassToUpload.singular);
return (
-
{getLangText('Drag a file here')}
+
{getLangText('Drag a %s here', this.props.fileClassToUpload.singular)}
- );
- } else {
- return null;
- }
- }
-});
-
-export default FileDragAndDropPreviewIterator;
\ No newline at end of file
diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js
index d6d2f939..c7a5f9a7 100644
--- a/js/components/ascribe_uploader/react_s3_fine_uploader.js
+++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js
@@ -1,16 +1,13 @@
'use strict';
import React from 'react/addons';
+import fineUploader from 'fineUploader';
import Router from 'react-router';
import Q from 'q';
-import { getCookie } from '../../utils/fetch_api_utils';
-import { getLangText } from '../../utils/lang_utils';
-
import S3Fetcher from '../../fetchers/s3_fetcher';
-import fineUploader from 'fineUploader';
-import FileDragAndDrop from './file_drag_and_drop';
+import FileDragAndDrop from './ascribe_file_drag_and_drop/file_drag_and_drop';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
@@ -18,9 +15,12 @@ import GlobalNotificationActions from '../../actions/global_notification_actions
import AppConstants from '../../constants/application_constants';
import { computeHashOfFile } from '../../utils/file_utils';
+import { displayValidFilesFilter, transformAllowedExtensionsToInputAcceptProp } from './react_s3_fine_uploader_utils';
+import { getCookie } from '../../utils/fetch_api_utils';
+import { getLangText } from '../../utils/lang_utils';
-var ReactS3FineUploader = React.createClass({
+let ReactS3FineUploader = React.createClass({
propTypes: {
keyRoutine: React.PropTypes.shape({
url: React.PropTypes.string,
@@ -37,7 +37,7 @@ var ReactS3FineUploader = React.createClass({
React.PropTypes.number
])
}),
- submitKey: React.PropTypes.func,
+ submitFile: React.PropTypes.func,
autoUpload: React.PropTypes.bool,
debug: React.PropTypes.bool,
objectProperties: React.PropTypes.shape({
@@ -84,7 +84,8 @@ var ReactS3FineUploader = React.createClass({
}),
validation: React.PropTypes.shape({
itemLimit: React.PropTypes.number,
- sizeLimit: React.PropTypes.string
+ sizeLimit: React.PropTypes.string,
+ allowedExtensions: React.PropTypes.arrayOf(React.PropTypes.string)
}),
messages: React.PropTypes.shape({
unsupportedBrowser: React.PropTypes.string
@@ -94,6 +95,7 @@ var ReactS3FineUploader = React.createClass({
retry: React.PropTypes.shape({
enableAuto: React.PropTypes.bool
}),
+ uploadStarted: React.PropTypes.func,
setIsUploadReady: React.PropTypes.func,
isReadyForFormSubmission: React.PropTypes.func,
areAssetsDownloadable: React.PropTypes.bool,
@@ -110,7 +112,22 @@ var ReactS3FineUploader = React.createClass({
enableLocalHashing: React.PropTypes.bool,
// automatically injected by React-Router
- query: React.PropTypes.object
+ query: React.PropTypes.object,
+
+ // A class of a file the user has to upload
+ // Needs to be defined both in singular as well as in plural
+ fileClassToUpload: React.PropTypes.shape({
+ singular: React.PropTypes.string,
+ plural: React.PropTypes.string
+ }),
+
+ // Uploading functionality of react fineuploader is disconnected from its UI
+ // layer, which means that literally every (properly adjusted) react element
+ // can handle the UI handling.
+ fileInputElement: React.PropTypes.oneOfType([
+ React.PropTypes.func,
+ React.PropTypes.element
+ ])
},
mixins: [Router.State],
@@ -124,6 +141,7 @@ var ReactS3FineUploader = React.createClass({
bucket: 'ascribe0'
},
request: {
+ //endpoint: 'https://www.ascribe.io.global.prod.fastly.net',
endpoint: 'https://ascribe0.s3.amazonaws.com',
accessKey: 'AKIAIVCZJ33WSCBQ3QDA'
},
@@ -161,7 +179,12 @@ var ReactS3FineUploader = React.createClass({
return name;
},
multiple: false,
- defaultErrorMessage: getLangText('Unexpected error. Please contact us if this happens repeatedly.')
+ defaultErrorMessage: getLangText('Unexpected error. Please contact us if this happens repeatedly.'),
+ fileClassToUpload: {
+ singular: getLangText('file'),
+ plural: getLangText('files')
+ },
+ fileInputElement: FileDragAndDrop
};
},
@@ -228,13 +251,27 @@ var ReactS3FineUploader = React.createClass({
onDeleteComplete: this.onDeleteComplete,
onSessionRequestComplete: this.onSessionRequestComplete,
onError: this.onError,
- onValidate: this.onValidate,
onUploadChunk: this.onUploadChunk,
onUploadChunkSuccess: this.onUploadChunkSuccess
}
};
},
+ // Resets the whole react fineuploader component to its initial state
+ reset() {
+ // Cancel all currently ongoing uploads
+ this.state.uploader.cancelAll();
+
+ // and reset component in general
+ this.state.uploader.reset();
+
+ // proclaim that upload is not ready
+ this.props.setIsUploadReady(false);
+
+ // reset internal data structures of component
+ this.setState(this.getInitialState());
+ },
+
requestKey(fileId) {
let filename = this.state.uploader.getName(fileId);
let uuid = this.state.uploader.getUuid(fileId);
@@ -297,6 +334,9 @@ var ReactS3FineUploader = React.createClass({
} else if(res.digitalwork) {
file.s3Url = res.digitalwork.url_safe;
file.s3UrlSafe = res.digitalwork.url_safe;
+ } else if(res.contractblob) {
+ file.s3Url = res.contractblob.url_safe;
+ file.s3UrlSafe = res.contractblob.url_safe;
} else {
throw new Error(getLangText('Could not find a url to download.'));
}
@@ -325,11 +365,9 @@ var ReactS3FineUploader = React.createClass({
completed: false
};
- let newState = React.addons.update(this.state, {
- startedChunks: { $set: chunks }
- });
+ let startedChunks = React.addons.update(this.state.startedChunks, { $set: chunks });
- this.setState(newState);
+ this.setState({ startedChunks });
},
onUploadChunkSuccess(id, chunkData, responseJson, xhr) {
@@ -342,75 +380,65 @@ var ReactS3FineUploader = React.createClass({
chunks[chunkKey].responseJson = responseJson;
chunks[chunkKey].xhr = xhr;
- let newState = React.addons.update(this.state, {
- startedChunks: { $set: chunks }
- });
+ let startedChunks = React.addons.update(this.state.startedChunks, { $set: chunks });
- this.setState(newState);
+ this.setState({ startedChunks });
}
},
onComplete(id, name, res, xhr) {
// there has been an issue with the server's connection
- if(xhr.status === 0) {
-
- console.logGlobal(new Error('Complete was called but there wasn\t a success'), false, {
+ if((xhr && xhr.status === 0) || res.error) {
+ console.logGlobal(new Error(res.error || 'Complete was called but there wasn\t a success'), false, {
files: this.state.filesToUpload,
chunks: this.state.chunks
});
+ } else {
+ let files = this.state.filesToUpload;
- return;
- }
+ // Set the state of the completed file to 'upload successful' in order to
+ // remove it from the GUI
+ files[id].status = 'upload successful';
+ files[id].key = this.state.uploader.getKey(id);
- let files = this.state.filesToUpload;
+ let filesToUpload = React.addons.update(this.state.filesToUpload, { $set: files });
+ this.setState({ filesToUpload });
- // Set the state of the completed file to 'upload successful' in order to
- // remove it from the GUI
- files[id].status = 'upload successful';
- files[id].key = this.state.uploader.getKey(id);
-
- let newState = React.addons.update(this.state, {
- filesToUpload: { $set: files }
- });
-
- this.setState(newState);
-
- // Only after the blob has been created server-side, we can make the form submittable.
- this.createBlob(files[id])
- .then(() => {
- // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey
- // are optional, we'll only trigger them when they're actually defined
- if(this.props.submitKey) {
- this.props.submitKey(files[id].key);
- } else {
- console.warn('You didn\'t define submitKey in as a prop in react-s3-fine-uploader');
- }
-
- // for explanation, check comment of if statement above
- if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
- // also, lets check if after the completion of this upload,
- // the form is ready for submission or not
- if(this.props.isReadyForFormSubmission(this.state.filesToUpload)) {
- // if so, set uploadstatus to true
- this.props.setIsUploadReady(true);
+ // Only after the blob has been created server-side, we can make the form submittable.
+ this.createBlob(files[id])
+ .then(() => {
+ // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile
+ // are optional, we'll only trigger them when they're actually defined
+ if(this.props.submitFile) {
+ this.props.submitFile(files[id]);
} else {
- this.props.setIsUploadReady(false);
+ console.warn('You didn\'t define submitFile in as a prop in react-s3-fine-uploader');
}
- } else {
- console.warn('You didn\'t define the functions isReadyForFormSubmission and/or setIsUploadReady in as a prop in react-s3-fine-uploader');
- }
- })
- .catch((err) => {
- console.logGlobal(err, false, {
- files: this.state.filesToUpload,
- chunks: this.state.chunks
+
+ // for explanation, check comment of if statement above
+ if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
+ // also, lets check if after the completion of this upload,
+ // the form is ready for submission or not
+ if(this.props.isReadyForFormSubmission(this.state.filesToUpload)) {
+ // if so, set uploadstatus to true
+ this.props.setIsUploadReady(true);
+ } else {
+ this.props.setIsUploadReady(false);
+ }
+ } else {
+ console.warn('You didn\'t define the functions isReadyForFormSubmission and/or setIsUploadReady in as a prop in react-s3-fine-uploader');
+ }
+ })
+ .catch((err) => {
+ console.logGlobal(err, false, {
+ files: this.state.filesToUpload,
+ chunks: this.state.chunks
+ });
+ let notification = new GlobalNotificationModel(err.message, 'danger', 5000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
});
- let notification = new GlobalNotificationModel(err.message, 'danger', 5000);
- GlobalNotificationActions.appendGlobalNotification(notification);
- });
-
-
+ }
},
onError(id, name, errorReason) {
@@ -420,27 +448,32 @@ var ReactS3FineUploader = React.createClass({
});
this.state.uploader.cancelAll();
- let notification = new GlobalNotificationModel(this.props.defaultErrorMessage, 'danger', 5000);
+ let notification = new GlobalNotificationModel(errorReason || this.props.defaultErrorMessage, 'danger', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
- onValidate(data) {
- if(data.size > this.props.validation.sizeLimit) {
- this.state.uploader.cancelAll();
+ isFileValid(file) {
+ if(file.size > this.props.validation.sizeLimit) {
let fileSizeInMegaBytes = this.props.validation.sizeLimit / 1000000;
- let notification = new GlobalNotificationModel(getLangText('Your file is bigger than %d MB', fileSizeInMegaBytes), 'danger', 5000);
+
+ let notification = new GlobalNotificationModel(getLangText('A file you submitted is bigger than ' + fileSizeInMegaBytes + 'MB.'), 'danger', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
+
+ return false;
+ } else {
+ return true;
}
},
onCancel(id) {
- this.removeFileWithIdFromFilesToUpload(id);
+ // when a upload is canceled, we need to update this components file array
+ this.setStatusOfFile(id, 'canceled');
let notification = new GlobalNotificationModel(getLangText('File upload canceled'), 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
- // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey
+ // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile
// are optional, we'll only trigger them when they're actually defined
if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
if(this.props.isReadyForFormSubmission(this.state.filesToUpload)) {
@@ -452,15 +485,17 @@ var ReactS3FineUploader = React.createClass({
} else {
console.warn('You didn\'t define the functions isReadyForFormSubmission and/or setIsUploadReady in as a prop in react-s3-fine-uploader');
}
+
+ return true;
},
onProgress(id, name, uploadedBytes, totalBytes) {
- let newState = React.addons.update(this.state, {
- filesToUpload: { [id]: {
- progress: { $set: (uploadedBytes / totalBytes) * 100} }
+ let filesToUpload = React.addons.update(this.state.filesToUpload, {
+ [id]: {
+ progress: { $set: (uploadedBytes / totalBytes) * 100}
}
});
- this.setState(newState);
+ this.setState({ filesToUpload });
},
onSessionRequestComplete(response, success) {
@@ -482,8 +517,9 @@ var ReactS3FineUploader = React.createClass({
return file;
});
- let newState = React.addons.update(this.state, {filesToUpload: {$set: updatedFilesToUpload}});
- this.setState(newState);
+ let filesToUpload = React.addons.update(this.state.filesToUpload, {$set: updatedFilesToUpload});
+
+ this.setState({filesToUpload });
} else {
// server has to respond with 204
//let notification = new GlobalNotificationModel('Could not load attached files (Further data)', 'danger', 10000);
@@ -495,16 +531,16 @@ var ReactS3FineUploader = React.createClass({
onDeleteComplete(id, xhr, isError) {
if(isError) {
- let notification = new GlobalNotificationModel(getLangText('Couldn\'t delete file'), 'danger', 10000);
+ this.setStatusOfFile(id, 'online');
+
+ let notification = new GlobalNotificationModel(getLangText('There was an error deleting your file.'), 'danger', 10000);
GlobalNotificationActions.appendGlobalNotification(notification);
} else {
- this.removeFileWithIdFromFilesToUpload(id);
-
let notification = new GlobalNotificationModel(getLangText('File deleted'), 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
}
- // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey
+ // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile
// are optional, we'll only trigger them when they're actually defined
if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
// also, lets check if after the completion of this upload,
@@ -521,7 +557,15 @@ var ReactS3FineUploader = React.createClass({
},
handleDeleteFile(fileId) {
- // In some instances (when the file was already uploaded and is just displayed to the user)
+ // We set the files state to 'deleted' immediately, so that the user is not confused with
+ // the unresponsiveness of the UI
+ //
+ // If there is an error during the deletion, we will just change the status back to 'online'
+ // and display an error message
+ this.setStatusOfFile(fileId, 'deleted');
+
+ // In some instances (when the file was already uploaded and is just displayed to the user
+ // - for example in the contract or additional files dialog)
// fineuploader does not register an id on the file (we do, don't be confused by this!).
// Since you can only delete a file by its id, we have to implement this method ourselves
//
@@ -532,13 +576,11 @@ var ReactS3FineUploader = React.createClass({
if(this.state.filesToUpload[fileId].status !== 'online') {
// delete file from server
this.state.uploader.deleteFile(fileId);
- // this is being continues in onDeleteFile, as
+ // this is being continued in onDeleteFile, as
// fineuploaders deleteFile does not return a correct callback or
// promise
} else {
let fileToDelete = this.state.filesToUpload[fileId];
- fileToDelete.status = 'deleted';
-
S3Fetcher
.deleteFile(fileToDelete.s3Key, fileToDelete.s3Bucket)
.then(() => this.onDeleteComplete(fileToDelete.id, null, false))
@@ -570,10 +612,25 @@ var ReactS3FineUploader = React.createClass({
handleUploadFile(files) {
// If multiple set and user already uploaded its work,
// cancel upload
- if(!this.props.multiple && this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled').length > 0) {
+ if(!this.props.multiple && this.state.filesToUpload.filter(displayValidFilesFilter).length > 0) {
return;
}
+ // validate each submitted file if it fits the file size
+ let validFiles = [];
+ for(let i = 0; i < files.length; i++) {
+ if(this.isFileValid(files[i])) {
+ validFiles.push(files[i]);
+ }
+ }
+ // override standard files list with only valid files
+ files = validFiles;
+
+ // Call this method to signal the outside component that an upload is in progress
+ if(typeof this.props.uploadStarted === 'function' && files.length > 0) {
+ this.props.uploadStarted();
+ }
+
// if multiple is set to false and user drops multiple files into the dropzone,
// take the first one and notify user that only one file can be submitted
if(!this.props.multiple && files.length > 1) {
@@ -684,8 +741,10 @@ var ReactS3FineUploader = React.createClass({
// if we're not hashing the files locally, we're just going to hand them over to fineuploader
// to upload them to the server
} else {
- this.state.uploader.addFiles(files);
- this.synchronizeFileLists(files);
+ if(files.length > 0) {
+ this.state.uploader.addFiles(files);
+ this.synchronizeFileLists(files);
+ }
}
},
@@ -709,6 +768,7 @@ var ReactS3FineUploader = React.createClass({
synchronizeFileLists(files) {
let oldFiles = this.state.filesToUpload;
let oldAndNewFiles = this.state.uploader.getUploads();
+
// Add fineuploader specific information to new files
for(let i = 0; i < oldAndNewFiles.length; i++) {
for(let j = 0; j < files.length; j++) {
@@ -723,6 +783,22 @@ var ReactS3FineUploader = React.createClass({
// and re-add fineuploader specific information for old files as well
for(let i = 0; i < oldAndNewFiles.length; i++) {
for(let j = 0; j < oldFiles.length; j++) {
+
+ // EXCEPTION:
+ //
+ // Files do not necessarily come from the user's hard drive but can also be fetched
+ // from Amazon S3. This is handled in onSessionRequestComplete.
+ //
+ // If the user deletes one of those files, then fineuploader will still keep it in his
+ // files array but with key, progress undefined and size === -1 but
+ // status === 'upload successful'.
+ // This poses a problem as we depend on the amount of files that have
+ // status === 'upload successful', therefore once the file is synced,
+ // we need to tag its status as 'deleted' (which basically happens here)
+ if(oldAndNewFiles[i].size === -1 && (!oldAndNewFiles[i].progress || oldAndNewFiles[i].progress === 0)) {
+ oldAndNewFiles[i].status = 'deleted';
+ }
+
if(oldAndNewFiles[i].originalName === oldFiles[j].name) {
oldAndNewFiles[i].progress = oldFiles[j].progress;
oldAndNewFiles[i].type = oldFiles[j].type;
@@ -733,38 +809,23 @@ var ReactS3FineUploader = React.createClass({
}
// set the new file array
- let newState = React.addons.update(this.state, {
- filesToUpload: { $set: oldAndNewFiles }
- });
- this.setState(newState);
- },
+ let filesToUpload = React.addons.update(this.state.filesToUpload, { $set: oldAndNewFiles });
- removeFileWithIdFromFilesToUpload(fileId) {
- // also, sync files from state with the ones from fineuploader
- let filesToUpload = JSON.parse(JSON.stringify(this.state.filesToUpload));
-
- // splice because I can
- filesToUpload.splice(fileId, 1);
-
- // set state
- let newState = React.addons.update(this.state, {
- filesToUpload: { $set: filesToUpload }
- });
- this.setState(newState);
+ this.setState({ filesToUpload });
},
setStatusOfFile(fileId, status) {
- // also, sync files from state with the ones from fineuploader
- let filesToUpload = JSON.parse(JSON.stringify(this.state.filesToUpload));
+ let changeSet = {};
- // splice because I can
- filesToUpload[fileId].status = status;
+ if(status === 'deleted' || status === 'canceled') {
+ changeSet.progress = { $set: 0 };
+ }
- // set state
- let newState = React.addons.update(this.state, {
- filesToUpload: { $set: filesToUpload }
- });
- this.setState(newState);
+ changeSet.status = { $set: status };
+
+ let filesToUpload = React.addons.update(this.state.filesToUpload, { [fileId]: changeSet });
+
+ this.setState({ filesToUpload });
},
isDropzoneInactive() {
@@ -779,27 +840,48 @@ var ReactS3FineUploader = React.createClass({
},
+ getAllowedExtensions() {
+ let { validation } = this.props;
+
+ if(validation && validation.allowedExtensions && validation.allowedExtensions.length > 0) {
+ return transformAllowedExtensionsToInputAcceptProp(validation.allowedExtensions);
+ } else {
+ return null;
+ }
+ },
+
render() {
- return (
-
-
-
- );
+ let {
+ multiple,
+ areAssetsDownloadable,
+ areAssetsEditable,
+ onInactive,
+ enableLocalHashing,
+ fileClassToUpload,
+ validation,
+ fileInputElement
+ } = this.props;
+
+ // Here we initialize the template that has been either provided from the outside
+ // or the default input that is FileDragAndDrop.
+ return React.createElement(fileInputElement, {
+ onDrop: this.handleUploadFile,
+ filesToUpload: this.state.filesToUpload,
+ handleDeleteFile: this.handleDeleteFile,
+ handleCancelFile: this.handleCancelFile,
+ handlePauseFile: this.handlePauseFile,
+ handleResumeFile: this.handleResumeFile,
+ handleCancelHashing: this.handleCancelHashing,
+ multiple: multiple,
+ areAssetsDownloadable: areAssetsDownloadable,
+ areAssetsEditable: areAssetsEditable,
+ onInactive: onInactive,
+ dropzoneInactive: this.isDropzoneInactive(),
+ hashingProgress: this.state.hashingProgress,
+ enableLocalHashing: enableLocalHashing,
+ fileClassToUpload: fileClassToUpload,
+ allowedExtensions: this.getAllowedExtensions()
+ });
}
});
diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js
new file mode 100644
index 00000000..cd1dbce2
--- /dev/null
+++ b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js
@@ -0,0 +1,73 @@
+'use strict';
+
+export const formSubmissionValidation = {
+ /**
+ * Returns a boolean if there has been at least one file uploaded
+ * successfully without it being deleted or canceled.
+ * @param {array of files} files provided by react fine uploader
+ * @return {boolean}
+ */
+ atLeastOneUploadedFile(files) {
+ files = files.filter((file) => file.status !== 'deleted' && file.status !== 'canceled');
+ if (files.length > 0 && files[0].status === 'upload successful') {
+ return true;
+ } else {
+ return false;
+ }
+ },
+
+ /**
+ * File submission for the form is optional, but if the user decides to submit a file
+ * the form is not ready until there are no more files currently uploading.
+ * @param {array of files} files files provided by react fine uploader
+ * @return {boolean} [description]
+ */
+ fileOptional(files) {
+ let uploadingFiles = files.filter((file) => file.status === 'submitting');
+
+ if (uploadingFiles.length === 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+};
+
+/**
+ * Filter function for filtering all deleted and canceled files
+ * @param {object} file A file from filesToUpload that has status as a prop.
+ * @return {boolean}
+ */
+export function displayValidFilesFilter(file) {
+ return file.status !== 'deleted' && file.status !== 'canceled';
+}
+
+
+/**
+ * Filter function for which files to integrate in the progress process
+ * @param {object} file A file from filesToUpload, that has a status as a prop.
+ * @return {boolean}
+ */
+export function displayValidProgressFilesFilter(file) {
+ return file.status !== 'deleted' && file.status !== 'canceled' && file.status !== 'online';
+}
+
+
+/**
+ * Fineuploader allows to specify the file extensions that are allowed to upload.
+ * For our self defined input, we can reuse those declarations to restrict which files
+ * the user can pick from his hard drive.
+ *
+ * Takes an array of file extensions (['pdf', 'png', ...]) and transforms them into a string
+ * that can be passed into an html5 input via its 'accept' prop.
+ * @param {array} allowedExtensions Array of strings without a dot prefixed
+ * @return {string} Joined string (comma-separated) of the passed-in array
+ */
+export function transformAllowedExtensionsToInputAcceptProp(allowedExtensions) {
+ // add a dot in front of the extension
+ let prefixedAllowedExtensions = allowedExtensions.map((ext) => '.' + ext);
+
+ // generate a comma separated list to add them to the DOM element
+ // See: http://stackoverflow.com/questions/4328947/limit-file-format-when-using-input-type-file
+ return prefixedAllowedExtensions.join(', ');
+}
diff --git a/js/components/ascribe_uploader/vendor/s3.fine-uploader.js b/js/components/ascribe_uploader/vendor/s3.fine-uploader.js
index e0f096df..5b90cf5a 100644
--- a/js/components/ascribe_uploader/vendor/s3.fine-uploader.js
+++ b/js/components/ascribe_uploader/vendor/s3.fine-uploader.js
@@ -3,7 +3,7 @@
*
* Copyright 2015, Widen Enterprises, Inc. info@fineuploader.com
*
-* Version: 5.2.2
+* Version: 5.3.0
*
* Homepage: http://fineuploader.com
*
@@ -894,7 +894,7 @@ var qq = function(element) {
}());
/*global qq */
-qq.version = "5.2.2";
+qq.version = "5.3.0";
/* globals qq */
qq.supportedFeatures = (function() {
@@ -1928,6 +1928,10 @@ qq.status = {
this._endpointStore.set(endpoint, id);
},
+ setForm: function(elementOrId) {
+ this._updateFormSupportAndParams(elementOrId);
+ },
+
setItemLimit: function(newItemLimit) {
this._currentItemLimit = newItemLimit;
},
@@ -1945,16 +1949,11 @@ qq.status = {
},
uploadStoredFiles: function() {
- var idToUpload;
-
if (this._storedIds.length === 0) {
this._itemError("noFilesError");
}
else {
- while (this._storedIds.length) {
- idToUpload = this._storedIds.shift();
- this._uploadFile(idToUpload);
- }
+ this._uploadStoredFiles();
}
}
};
@@ -2038,10 +2037,11 @@ qq.status = {
});
},
- _createStore: function(initialValue, readOnlyValues) {
+ _createStore: function(initialValue, _readOnlyValues_) {
var store = {},
catchall = initialValue,
perIdReadOnlyValues = {},
+ readOnlyValues = _readOnlyValues_,
copy = function(orig) {
if (qq.isObject(orig)) {
return qq.extend({}, orig);
@@ -2095,8 +2095,20 @@ qq.status = {
addReadOnly: function(id, values) {
// Only applicable to Object stores
if (qq.isObject(store)) {
- perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};
- qq.extend(perIdReadOnlyValues[id], values);
+ // If null ID, apply readonly values to all files
+ if (id === null) {
+ if (qq.isFunction(values)) {
+ readOnlyValues = values;
+ }
+ else {
+ readOnlyValues = readOnlyValues || {};
+ qq.extend(readOnlyValues, values);
+ }
+ }
+ else {
+ perIdReadOnlyValues[id] = perIdReadOnlyValues[id] || {};
+ qq.extend(perIdReadOnlyValues[id], values);
+ }
}
},
@@ -2882,7 +2894,7 @@ qq.status = {
_onBeforeManualRetry: function(id) {
var itemLimit = this._currentItemLimit,
fileName;
- console.log(this._handler.isValid(id));
+
if (this._preventRetries[id]) {
this.log("Retries are forbidden for id " + id, "warn");
return false;
@@ -3005,13 +3017,14 @@ qq.status = {
this._onSubmit.apply(this, arguments);
this._uploadData.setStatus(id, qq.status.SUBMITTED);
this._onSubmitted.apply(this, arguments);
- this._options.callbacks.onSubmitted.apply(this, arguments);
if (this._options.autoUpload) {
+ this._options.callbacks.onSubmitted.apply(this, arguments);
this._uploadFile(id);
}
else {
this._storeForLater(id);
+ this._options.callbacks.onSubmitted.apply(this, arguments);
}
},
@@ -3238,6 +3251,23 @@ qq.status = {
}
},
+ _updateFormSupportAndParams: function(formElementOrId) {
+ this._options.form.element = formElementOrId;
+
+ this._formSupport = qq.FormSupport && new qq.FormSupport(
+ this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this)
+ );
+
+ if (this._formSupport && this._formSupport.attachedToForm) {
+ this._paramsStore.addReadOnly(null, this._formSupport.getFormInputsAsObject);
+
+ this._options.autoUpload = this._formSupport.newAutoUpload;
+ if (this._formSupport.newEndpoint) {
+ this.setEndpoint(this._formSupport.newEndpoint);
+ }
+ }
+ },
+
_upload: function(id, params, endpoint) {
var name = this.getName(id);
@@ -3264,6 +3294,25 @@ qq.status = {
}
},
+ _uploadStoredFiles: function() {
+ var idToUpload, stillSubmitting,
+ self = this;
+
+ while (this._storedIds.length) {
+ idToUpload = this._storedIds.shift();
+ this._uploadFile(idToUpload);
+ }
+
+ // If we are still waiting for some files to clear validation, attempt to upload these again in a bit
+ stillSubmitting = this.getUploads({status: qq.status.SUBMITTING}).length;
+ if (stillSubmitting) {
+ qq.log("Still waiting for " + stillSubmitting + " files to clear submit queue. Will re-parse stored IDs array shortly.");
+ setTimeout(function() {
+ self._uploadStoredFiles();
+ }, 1000);
+ }
+ },
+
/**
* Performs some internal validation checks on an item, defined in the `validation` option.
*
@@ -5271,6 +5320,7 @@ qq.XhrUploadHandler = function(spec) {
*/
getResumableFilesData: function() {
var resumableFilesData = [];
+
handler._iterateResumeRecords(function(key, uploadData) {
handler.moveInProgressToRemaining(null, uploadData.chunking.inProgress, uploadData.chunking.remaining);
@@ -5461,7 +5511,7 @@ qq.XhrUploadHandler = function(spec) {
_iterateResumeRecords: function(callback) {
if (resumeEnabled) {
qq.each(localStorage, function(key, item) {
- if (key.indexOf(qq.format("qq{}resume-", namespace)) === 0) {
+ if (key.indexOf(qq.format("qq{}resume", namespace)) === 0) {
var uploadData = JSON.parse(item);
callback(key, uploadData);
}
@@ -5728,7 +5778,9 @@ qq.WindowReceiveMessage = function(o) {
},
getItemByFileId: function(id) {
- return this._templating.getFileContainer(id);
+ if (!this._templating.isHiddenForever(id)) {
+ return this._templating.getFileContainer(id);
+ }
},
reset: function() {
@@ -6238,11 +6290,6 @@ qq.WindowReceiveMessage = function(o) {
dontDisplay = this._handler.isProxied(id) && this._options.scaling.hideScaled,
record;
- // If we don't want this file to appear in the UI, skip all of this UI-related logic.
- if (dontDisplay) {
- return;
- }
-
if (this._options.display.prependFiles) {
if (this._totalFilesInBatch > 1 && this._filesInBatchAddedToUi > 0) {
prependIndex = this._filesInBatchAddedToUi - 1;
@@ -6274,7 +6321,7 @@ qq.WindowReceiveMessage = function(o) {
}
}
- this._templating.addFile(id, this._options.formatFileName(name), prependData);
+ this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);
if (canned) {
this._thumbnailUrls[id] && this._templating.updateThumbnail(id, this._thumbnailUrls[id], true);
@@ -6638,6 +6685,7 @@ qq.Templating = function(spec) {
HIDE_DROPZONE_ATTR = "qq-hide-dropzone",
DROPZPONE_TEXT_ATTR = "qq-drop-area-text",
IN_PROGRESS_CLASS = "qq-in-progress",
+ HIDDEN_FOREVER_CLASS = "qq-hidden-forever",
isCancelDisabled = false,
generatedThumbnails = 0,
thumbnailQueueMonitorRunning = false,
@@ -7273,7 +7321,7 @@ qq.Templating = function(spec) {
isCancelDisabled = true;
},
- addFile: function(id, name, prependInfo) {
+ addFile: function(id, name, prependInfo, hideForever) {
var fileEl = qq.toElement(templateHtml.fileTemplate),
fileNameEl = getTemplateEl(fileEl, selectorClasses.file),
uploaderEl = getTemplateEl(container, selectorClasses.uploader),
@@ -7296,30 +7344,36 @@ qq.Templating = function(spec) {
fileList.appendChild(fileEl);
}
- hide(getProgress(id));
- hide(getSize(id));
- hide(getDelete(id));
- hide(getRetry(id));
- hide(getPause(id));
- hide(getContinue(id));
-
- if (isCancelDisabled) {
- this.hideCancel(id);
+ if (hideForever) {
+ fileEl.style.display = "none";
+ qq(fileEl).addClass(HIDDEN_FOREVER_CLASS);
}
+ else {
+ hide(getProgress(id));
+ hide(getSize(id));
+ hide(getDelete(id));
+ hide(getRetry(id));
+ hide(getPause(id));
+ hide(getContinue(id));
- thumb = getThumbnail(id);
- if (thumb && !thumb.src) {
- cachedWaitingForThumbnailImg.then(function(waitingImg) {
- thumb.src = waitingImg.src;
- if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {
- qq(thumb).css({
- maxHeight: waitingImg.style.maxHeight,
- maxWidth: waitingImg.style.maxWidth
- });
- }
+ if (isCancelDisabled) {
+ this.hideCancel(id);
+ }
- show(thumb);
- });
+ thumb = getThumbnail(id);
+ if (thumb && !thumb.src) {
+ cachedWaitingForThumbnailImg.then(function(waitingImg) {
+ thumb.src = waitingImg.src;
+ if (waitingImg.style.maxHeight && waitingImg.style.maxWidth) {
+ qq(thumb).css({
+ maxHeight: waitingImg.style.maxHeight,
+ maxWidth: waitingImg.style.maxWidth
+ });
+ }
+
+ show(thumb);
+ });
+ }
}
},
@@ -7413,6 +7467,10 @@ qq.Templating = function(spec) {
icon && qq(icon).addClass(options.classes.editable);
},
+ isHiddenForever: function(id) {
+ return qq(getFile(id)).hasClass(HIDDEN_FOREVER_CLASS);
+ },
+
hideEditIcon: function(id) {
var icon = getEditIcon(id);
@@ -7572,13 +7630,17 @@ qq.Templating = function(spec) {
},
generatePreview: function(id, optFileOrBlob) {
- thumbGenerationQueue.push({id: id, optFileOrBlob: optFileOrBlob});
- !thumbnailQueueMonitorRunning && generateNextQueuedPreview();
+ if (!this.isHiddenForever(id)) {
+ thumbGenerationQueue.push({id: id, optFileOrBlob: optFileOrBlob});
+ !thumbnailQueueMonitorRunning && generateNextQueuedPreview();
+ }
},
updateThumbnail: function(id, thumbnailUrl, showWaitingImg) {
- thumbGenerationQueue.push({update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});
- !thumbnailQueueMonitorRunning && generateNextQueuedPreview();
+ if (!this.isHiddenForever(id)) {
+ thumbGenerationQueue.push({update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});
+ !thumbnailQueueMonitorRunning && generateNextQueuedPreview();
+ }
},
hasDialog: function(type) {
@@ -9489,12 +9551,6 @@ qq.s3.XhrUploadHandler = function(spec, proxy) {
result.success,
function failure(reason, xhr) {
- console.logGlobal(reason + 'in chunked.combine', false, {
- uploadId,
- etagMap,
- result
- });
-
result.failure(upload.done(id, xhr).response, xhr);
}
);
@@ -12335,7 +12391,7 @@ qq.Scaler = function(spec, log) {
"use strict";
var self = this,
- includeReference = spec.sendOriginal,
+ includeOriginal = spec.sendOriginal,
orient = spec.orient,
defaultType = spec.defaultType,
defaultQuality = spec.defaultQuality / 100,
@@ -12385,16 +12441,18 @@ qq.Scaler = function(spec, log) {
});
});
- includeReference && records.push({
+ records.push({
uuid: originalFileUuid,
name: originalFileName,
- blob: originalBlob
+ size: originalBlob.size,
+ blob: includeOriginal ? originalBlob : null
});
}
else {
records.push({
uuid: originalFileUuid,
name: originalFileName,
+ size: originalBlob.size,
blob: originalBlob
});
}
@@ -12413,19 +12471,17 @@ qq.Scaler = function(spec, log) {
proxyGroupId = qq.getUniqueId();
qq.each(self.getFileRecords(uuid, name, file), function(idx, record) {
- var relatedBlob = file,
- relatedSize = size,
+ var blobSize = record.size,
id;
if (record.blob instanceof qq.BlobProxy) {
- relatedBlob = record.blob;
- relatedSize = -1;
+ blobSize = -1;
}
id = uploadData.addFile({
uuid: record.uuid,
name: record.name,
- size: relatedSize,
+ size: blobSize,
batchId: batchId,
proxyGroupId: proxyGroupId
});
@@ -12437,10 +12493,13 @@ qq.Scaler = function(spec, log) {
originalId = id;
}
- addFileToHandler(id, relatedBlob);
-
- fileList.push({id: id, file: relatedBlob});
-
+ if (record.blob) {
+ addFileToHandler(id, record.blob);
+ fileList.push({id: id, file: record.blob});
+ }
+ else {
+ uploadData.setStatus(id, qq.status.REJECTED);
+ }
});
// If we are potentially uploading an original file and some scaled versions,
@@ -12453,8 +12512,8 @@ qq.Scaler = function(spec, log) {
qqparentsize: uploadData.retrieve({id: originalId}).size
};
- // Make SURE the UUID for each scaled image is sent with the upload request,
- // to be consistent (since we need to ensure it is sent for the original file as well).
+ // Make sure the UUID for each scaled image is sent with the upload request,
+ // to be consistent (since we may need to ensure it is sent for the original file as well).
params[uuidParamName] = uploadData.retrieve({id: scaledId}).uuid;
uploadData.setParentId(scaledId, originalId);
@@ -14411,4 +14470,4 @@ code.google.com/p/crypto-js/wiki/License
C.HmacSHA1 = Hasher._createHmacHelper(SHA1);
}());
-/*! 2015-06-09 */
+/*! 2015-08-26 */
diff --git a/js/components/ascribe_uploader/vendor/s3.fine-uploader.min.js b/js/components/ascribe_uploader/vendor/s3.fine-uploader.min.js
index ef244d9e..620fcafc 100644
--- a/js/components/ascribe_uploader/vendor/s3.fine-uploader.min.js
+++ b/js/components/ascribe_uploader/vendor/s3.fine-uploader.min.js
@@ -3,7 +3,7 @@
*
* Copyright 2015, Widen Enterprises, Inc. info@fineuploader.com
*
-* Version: 5.2.2
+* Version: 5.3.0
*
* Homepage: http://fineuploader.com
*
@@ -13,10 +13,10 @@
*/
-var qq=function(a){"use strict";return{hide:function(){return a.style.display="none",this},attach:function(b,c){return a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent("on"+b,c),function(){qq(a).detach(b,c)}},detach:function(b,c){return a.removeEventListener?a.removeEventListener(b,c,!1):a.attachEvent&&a.detachEvent("on"+b,c),this},contains:function(b){return b?a===b?!0:a.contains?a.contains(b):!!(8&b.compareDocumentPosition(a)):!1},insertBefore:function(b){return b.parentNode.insertBefore(a,b),this},remove:function(){return a.parentNode.removeChild(a),this},css:function(b){if(null==a.style)throw new qq.Error("Can't apply style to node as it is not on the HTMLElement prototype chain!");return null!=b.opacity&&"string"!=typeof a.style.opacity&&"undefined"!=typeof a.filters&&(b.filter="alpha(opacity="+Math.round(100*b.opacity)+")"),qq.extend(a.style,b),this},hasClass:function(b,c){var d=new RegExp("(^| )"+b+"( |$)");return d.test(a.className)||!(!c||!d.test(a.parentNode.className))},addClass:function(b){return qq(a).hasClass(b)||(a.className+=" "+b),this},removeClass:function(b){var c=new RegExp("(^| )"+b+"( |$)");return a.className=a.className.replace(c," ").replace(/^\s+|\s+$/g,""),this},getByClass:function(b){var c,d=[];return a.querySelectorAll?a.querySelectorAll("."+b):(c=a.getElementsByTagName("*"),qq.each(c,function(a,c){qq(c).hasClass(b)&&d.push(c)}),d)},children:function(){for(var b=[],c=a.firstChild;c;)1===c.nodeType&&b.push(c),c=c.nextSibling;return b},setText:function(b){return a.innerText=b,a.textContent=b,this},clearText:function(){return qq(a).setText("")},hasAttribute:function(b){var c;return a.hasAttribute?a.hasAttribute(b)?null==/^false$/i.exec(a.getAttribute(b)):!1:(c=a[b],void 0===c?!1:null==/^false$/i.exec(c))}}};!function(){"use strict";qq.canvasToBlob=function(a,b,c){return qq.dataUriToBlob(a.toDataURL(b,c))},qq.dataUriToBlob=function(a){var b,c,d,e,f=function(a,b){var c=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,d=c&&new c;return d?(d.append(a),d.getBlob(b)):new Blob([a],{type:b})};return c=a.split(",")[0].indexOf("base64")>=0?atob(a.split(",")[1]):decodeURI(a.split(",")[1]),e=a.split(",")[0].split(":")[1].split(";")[0],b=new ArrayBuffer(c.length),d=new Uint8Array(b),qq.each(c,function(a,b){d[a]=b.charCodeAt(0)}),f(b,e)},qq.log=function(a,b){window.console&&(b&&"info"!==b?window.console[b]?window.console[b](a):window.console.log("<"+b+"> "+a):window.console.log(a))},qq.isObject=function(a){return a&&!a.nodeType&&"[object Object]"===Object.prototype.toString.call(a)},qq.isFunction=function(a){return"function"==typeof a},qq.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)||a&&window.ArrayBuffer&&a.buffer&&a.buffer.constructor===ArrayBuffer},qq.isItemList=function(a){return"[object DataTransferItemList]"===Object.prototype.toString.call(a)},qq.isNodeList=function(a){return"[object NodeList]"===Object.prototype.toString.call(a)||a.item&&a.namedItem},qq.isString=function(a){return"[object String]"===Object.prototype.toString.call(a)},qq.trimStr=function(a){return String.prototype.trim?a.trim():a.replace(/^\s+|\s+$/g,"")},qq.format=function(a){var b=Array.prototype.slice.call(arguments,1),c=a,d=c.indexOf("{}");return qq.each(b,function(a,b){var e=c.substring(0,d),f=c.substring(d+2);return c=e+b+f,d=c.indexOf("{}",d+b.length),0>d?!1:void 0}),c},qq.isFile=function(a){return window.File&&"[object File]"===Object.prototype.toString.call(a)},qq.isFileList=function(a){return window.FileList&&"[object FileList]"===Object.prototype.toString.call(a)},qq.isFileOrInput=function(a){return qq.isFile(a)||qq.isInput(a)},qq.isInput=function(a,b){var c=function(a){var c=a.toLowerCase();return b?"file"!==c:"file"===c};return window.HTMLInputElement&&"[object HTMLInputElement]"===Object.prototype.toString.call(a)&&a.type&&c(a.type)?!0:a.tagName&&"input"===a.tagName.toLowerCase()&&a.type&&c(a.type)?!0:!1},qq.isBlob=function(a){return window.Blob&&"[object Blob]"===Object.prototype.toString.call(a)?!0:void 0},qq.isXhrUploadSupported=function(){var a=document.createElement("input");return a.type="file",void 0!==a.multiple&&"undefined"!=typeof File&&"undefined"!=typeof FormData&&"undefined"!=typeof qq.createXhrInstance().upload},qq.createXhrInstance=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(a){return qq.log("Neither XHR or ActiveX are supported!","error"),null}},qq.isFolderDropSupported=function(a){return a.items&&a.items.length>0&&a.items[0].webkitGetAsEntry},qq.isFileChunkingSupported=function(){return!qq.androidStock()&&qq.isXhrUploadSupported()&&(void 0!==File.prototype.slice||void 0!==File.prototype.webkitSlice||void 0!==File.prototype.mozSlice)},qq.sliceBlob=function(a,b,c){var d=a.slice||a.mozSlice||a.webkitSlice;return d.call(a,b,c)},qq.arrayBufferToHex=function(a){var b="",c=new Uint8Array(a);return qq.each(c,function(a,c){var d=c.toString(16);d.length<2&&(d="0"+d),b+=d}),b},qq.readBlobToHex=function(a,b,c){var d=qq.sliceBlob(a,b,b+c),e=new FileReader,f=new qq.Promise;return e.onload=function(){f.success(qq.arrayBufferToHex(e.result))},e.onerror=f.failure,e.readAsArrayBuffer(d),f},qq.extend=function(a,b,c){return qq.each(b,function(b,d){c&&qq.isObject(d)?(void 0===a[b]&&(a[b]={}),qq.extend(a[b],d,!0)):a[b]=d}),a},qq.override=function(a,b){var c={},d=b(c);return qq.each(d,function(b,d){void 0!==a[b]&&(c[b]=a[b]),a[b]=d}),a},qq.indexOf=function(a,b,c){if(a.indexOf)return a.indexOf(b,c);c=c||0;var d=a.length;for(0>c&&(c+=d);d>c;c+=1)if(a.hasOwnProperty(c)&&a[c]===b)return c;return-1},qq.getUniqueId=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=0|16*Math.random(),c="x"==a?b:8|3&b;return c.toString(16)})},qq.ie=function(){return-1!==navigator.userAgent.indexOf("MSIE")||-1!==navigator.userAgent.indexOf("Trident")},qq.ie7=function(){return-1!==navigator.userAgent.indexOf("MSIE 7")},qq.ie8=function(){return-1!==navigator.userAgent.indexOf("MSIE 8")},qq.ie10=function(){return-1!==navigator.userAgent.indexOf("MSIE 10")},qq.ie11=function(){return qq.ie()&&-1!==navigator.userAgent.indexOf("rv:11")},qq.safari=function(){return void 0!==navigator.vendor&&-1!==navigator.vendor.indexOf("Apple")},qq.chrome=function(){return void 0!==navigator.vendor&&-1!==navigator.vendor.indexOf("Google")},qq.opera=function(){return void 0!==navigator.vendor&&-1!==navigator.vendor.indexOf("Opera")},qq.firefox=function(){return!qq.ie11()&&-1!==navigator.userAgent.indexOf("Mozilla")&&void 0!==navigator.vendor&&""===navigator.vendor},qq.windows=function(){return"Win32"===navigator.platform},qq.android=function(){return-1!==navigator.userAgent.toLowerCase().indexOf("android")},qq.androidStock=function(){return qq.android()&&navigator.userAgent.toLowerCase().indexOf("chrome")<0},qq.ios6=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf(" OS 6_")},qq.ios7=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf(" OS 7_")},qq.ios8=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf(" OS 8_")},qq.ios800=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf(" OS 8_0 ")},qq.ios=function(){return-1!==navigator.userAgent.indexOf("iPad")||-1!==navigator.userAgent.indexOf("iPod")||-1!==navigator.userAgent.indexOf("iPhone")},qq.iosChrome=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf("CriOS")},qq.iosSafari=function(){return qq.ios()&&!qq.iosChrome()&&-1!==navigator.userAgent.indexOf("Safari")},qq.iosSafariWebView=function(){return qq.ios()&&!qq.iosChrome()&&!qq.iosSafari()},qq.preventDefault=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},qq.toElement=function(){var a=document.createElement("div");return function(b){a.innerHTML=b;var c=a.firstChild;return a.removeChild(c),c}}(),qq.each=function(a,b){var c,d;if(a)if(window.Storage&&a.constructor===window.Storage)for(c=0;c0?a.substr(b,a.length-b):void 0},qq.getFilename=function(a){return qq.isInput(a)?a.value.replace(/.*(\/|\\)/,""):qq.isFile(a)&&null!==a.fileName&&void 0!==a.fileName?a.fileName:a.name},qq.DisposeSupport=function(){var a=[];return{dispose:function(){var b;do b=a.shift(),b&&b();while(b)},attach:function(){var a=arguments;this.addDisposer(qq(a[0]).attach.apply(this,Array.prototype.slice.call(arguments,1)))},addDisposer:function(b){a.push(b)}}}}(),function(){"use strict";qq.Error=function(a){this.message="[Fine Uploader "+qq.version+"] "+a},qq.Error.prototype=new Error}(),qq.version="5.2.2",qq.supportedFeatures=function(){"use strict";function a(){var a,b=!0;try{a=document.createElement("input"),a.type="file",qq(a).hide(),a.disabled&&(b=!1)}catch(c){b=!1}return b}function b(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[2][1-9]|Chrome\/[3-9][0-9]/)}function c(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/)}function d(){if(window.XMLHttpRequest){var a=qq.createXhrInstance();return void 0!==a.withCredentials}return!1}function e(){return void 0!==window.XDomainRequest}function f(){return d()?!0:e()}function g(){return void 0!==document.createElement("input").webkitdirectory}function h(){try{return!!window.localStorage}catch(a){return!1}}function i(){var a=document.createElement("span");return("draggable"in a||"ondragstart"in a&&"ondrop"in a)&&!qq.android()&&!qq.ios()}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x;return j=a(),m=j&&qq.isXhrUploadSupported(),k=m&&!qq.androidStock(),l=m&&i(),n=l&&b(),o=m&&qq.isFileChunkingSupported(),p=m&&o&&h(),q=m&&c(),r=j&&(void 0!==window.postMessage||m),t=d(),s=e(),u=f(),v=g(),w=m&&void 0!==window.FileReader,x=function(){return m?!qq.androidStock()&&!qq.iosChrome():!1}(),{ajaxUploading:m,blobUploading:k,canDetermineSize:m,chunking:o,deleteFileCors:u,deleteFileCorsXdr:s,deleteFileCorsXhr:t,dialogElement:!!window.HTMLDialogElement,fileDrop:l,folderDrop:n,folderSelection:v,imagePreviews:w,imageValidation:w,itemSizeValidation:m,pause:o,progressBar:x,resume:p,scaling:w&&k,tiffPreviews:qq.safari(),unlimitedScaledImageSize:!qq.ios(),uploading:j,uploadCors:r,uploadCustomHeaders:m,uploadNonMultipart:m,uploadViaPaste:q}}(),qq.isGenericPromise=function(a){"use strict";return!!(a&&a.then&&qq.isFunction(a.then))},qq.Promise=function(){"use strict";var a,b,c=[],d=[],e=[],f=0;qq.extend(this,{then:function(e,g){return 0===f?(e&&c.push(e),g&&d.push(g)):-1===f?g&&g.apply(null,b):e&&e.apply(null,a),this},done:function(c){return 0===f?e.push(c):c.apply(null,void 0===b?a:b),this},success:function(){return f=1,a=arguments,c.length&&qq.each(c,function(b,c){c.apply(null,a)}),e.length&&qq.each(e,function(b,c){c.apply(null,a)}),this},failure:function(){return f=-1,b=arguments,d.length&&qq.each(d,function(a,c){c.apply(null,b)}),e.length&&qq.each(e,function(a,c){c.apply(null,b)}),this}})},qq.BlobProxy=function(a,b){"use strict";qq.extend(this,{referenceBlob:a,create:function(){return b(a)}})},qq.UploadButton=function(a){"use strict";function b(){var a=document.createElement("input");return a.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME,d),a.setAttribute("title","file input"),e.setMultiple(g.multiple,a),g.folders&&qq.supportedFeatures.folderSelection&&a.setAttribute("webkitdirectory",""),g.acceptFiles&&a.setAttribute("accept",g.acceptFiles),a.setAttribute("type","file"),a.setAttribute("name",g.name),qq(a).css({position:"absolute",right:0,top:0,fontFamily:"Arial",fontSize:qq.ie()&&!qq.ie8()?"3500px":"118px",margin:0,padding:0,cursor:"pointer",opacity:0}),!qq.ie7()&&qq(a).css({height:"100%"}),g.element.appendChild(a),f.attach(a,"change",function(){g.onChange(a)}),f.attach(a,"mouseover",function(){qq(g.element).addClass(g.hoverClass)}),f.attach(a,"mouseout",function(){qq(g.element).removeClass(g.hoverClass)}),f.attach(a,"focus",function(){qq(g.element).addClass(g.focusClass)}),f.attach(a,"blur",function(){qq(g.element).removeClass(g.focusClass)}),a}var c,d,e=this,f=new qq.DisposeSupport,g={element:null,multiple:!1,acceptFiles:null,folders:!1,name:"qqfile",onChange:function(){},ios8BrowserCrashWorkaround:!1,hoverClass:"qq-upload-button-hover",focusClass:"qq-upload-button-focus"};qq.extend(g,a),d=qq.getUniqueId(),qq(g.element).css({position:"relative",overflow:"hidden",direction:"ltr"}),qq.extend(this,{getInput:function(){return c},getButtonId:function(){return d},setMultiple:function(a,b){var c=b||this.getInput();g.ios8BrowserCrashWorkaround&&qq.ios8()&&(qq.iosChrome()||qq.iosSafariWebView())?c.setAttribute("multiple",""):a?c.setAttribute("multiple",""):c.removeAttribute("multiple")},setAcceptFiles:function(a){a!==g.acceptFiles&&c.setAttribute("accept",a)},reset:function(){c.parentNode&&qq(c).remove(),qq(g.element).removeClass(g.focusClass),c=null,c=b()}}),c=b()},qq.UploadButton.BUTTON_ID_ATTR_NAME="qq-button-id",qq.UploadData=function(a){"use strict";function b(a){if(qq.isArray(a)){var b=[];return qq.each(a,function(a,c){b.push(e[c])}),b}return e[a]}function c(a){if(qq.isArray(a)){var b=[];return qq.each(a,function(a,c){b.push(e[f[c]])}),b}return e[f[a]]}function d(a){var b=[],c=[].concat(a);return qq.each(c,function(a,c){var d=g[c];void 0!==d&&qq.each(d,function(a,c){b.push(e[c])})}),b}var e=[],f={},g={},h={},i={};qq.extend(this,{addFile:function(b){var c=b.status||qq.status.SUBMITTING,d=e.push({name:b.name,originalName:b.name,uuid:b.uuid,size:null==b.size?-1:b.size,status:c})-1;return b.batchId&&(e[d].batchId=b.batchId,void 0===i[b.batchId]&&(i[b.batchId]=[]),i[b.batchId].push(d)),b.proxyGroupId&&(e[d].proxyGroupId=b.proxyGroupId,void 0===h[b.proxyGroupId]&&(h[b.proxyGroupId]=[]),h[b.proxyGroupId].push(d)),e[d].id=d,f[b.uuid]=d,void 0===g[c]&&(g[c]=[]),g[c].push(d),a.onStatusChange(d,null,c),d},retrieve:function(a){return qq.isObject(a)&&e.length?void 0!==a.id?b(a.id):void 0!==a.uuid?c(a.uuid):a.status?d(a.status):void 0:qq.extend([],e,!0)},reset:function(){e=[],f={},g={},i={}},setStatus:function(b,c){var d=e[b].status,f=qq.indexOf(g[d],b);g[d].splice(f,1),e[b].status=c,void 0===g[c]&&(g[c]=[]),g[c].push(b),a.onStatusChange(b,d,c)},uuidChanged:function(a,b){var c=e[a].uuid;e[a].uuid=b,f[b]=a,delete f[c]},updateName:function(a,b){e[a].name=b},updateSize:function(a,b){e[a].size=b},setParentId:function(a,b){e[a].parentId=b},getIdsInProxyGroup:function(a){var b=e[a].proxyGroupId;return b?h[b]:[]},getIdsInBatch:function(a){var b=e[a].batchId;return i[b]}})},qq.status={SUBMITTING:"submitting",SUBMITTED:"submitted",REJECTED:"rejected",QUEUED:"queued",CANCELED:"canceled",PAUSED:"paused",UPLOADING:"uploading",UPLOAD_RETRYING:"retrying upload",UPLOAD_SUCCESSFUL:"upload successful",UPLOAD_FAILED:"upload failed",DELETE_FAILED:"delete failed",DELETING:"deleting",DELETED:"deleted"},function(){"use strict";qq.basePublicApi={addBlobs:function(a,b,c){this.addFiles(a,b,c)},addFiles:function(a,b,c){this._maybeHandleIos8SafariWorkaround();var d=0===this._storedIds.length?qq.getUniqueId():this._currentBatchId,e=qq.bind(function(a){this._handleNewFile({blob:a,name:this._options.blobs.defaultName},d,l)},this),f=qq.bind(function(a){this._handleNewFile(a,d,l)},this),g=qq.bind(function(a){var b=qq.canvasToBlob(a);this._handleNewFile({blob:b,name:this._options.blobs.defaultName+".png"},d,l)},this),h=qq.bind(function(a){var b=a.quality&&a.quality/100,c=qq.canvasToBlob(a.canvas,a.type,b);this._handleNewFile({blob:c,name:a.name},d,l)},this),i=qq.bind(function(a){if(qq.isInput(a)&&qq.supportedFeatures.ajaxUploading){var b=Array.prototype.slice.call(a.files),c=this;qq.each(b,function(a,b){c._handleNewFile(b,d,l)})}else this._handleNewFile(a,d,l)},this),j=function(){qq.isFileList(a)&&(a=Array.prototype.slice.call(a)),a=[].concat(a)},k=this,l=[];this._currentBatchId=d,a&&(j(),qq.each(a,function(a,b){qq.isFileOrInput(b)?i(b):qq.isBlob(b)?e(b):qq.isObject(b)?b.blob&&b.name?f(b):b.canvas&&b.name&&h(b):b.tagName&&"canvas"===b.tagName.toLowerCase()?g(b):k.log(b+" is not a valid file container! Ignoring!","warn")}),this.log("Received "+l.length+" files."),this._prepareItemsForUpload(l,b,c))},cancel:function(a){this._handler.cancel(a)},cancelAll:function(){var a=[],b=this;qq.extend(a,this._storedIds),qq.each(a,function(a,c){b.cancel(c)}),this._handler.cancelAll()},clearStoredFiles:function(){this._storedIds=[]},continueUpload:function(a){var b=this._uploadData.retrieve({id:a});return qq.supportedFeatures.pause&&this._options.chunking.enabled?b.status===qq.status.PAUSED?(this.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.",a,this.getName(a))),this._uploadFile(a),!0):(this.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.",a,this.getName(a)),"error"),!1):!1},deleteFile:function(a){return this._onSubmitDelete(a)},doesExist:function(a){return this._handler.isValid(a)},drawThumbnail:function(a,b,c,d){var e,f,g=new qq.Promise;return this._imageGenerator?(e=this._thumbnailUrls[a],f={scale:c>0,maxSize:c>0?c:null},!d&&qq.supportedFeatures.imagePreviews&&(e=this.getFile(a)),null==e?g.failure({container:b,error:"File or URL not found."}):this._imageGenerator.generate(e,b,f).then(function(a){g.success(a)},function(a,b){g.failure({container:a,error:b||"Problem generating thumbnail"})})):g.failure({container:b,error:"Missing image generator module"}),g},getButton:function(a){return this._getButton(this._buttonIdsForFileIds[a])},getEndpoint:function(a){return this._endpointStore.get(a)},getFile:function(a){return this._handler.getFile(a)||null},getInProgress:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED]}).length},getName:function(a){return this._uploadData.retrieve({id:a}).name},getParentId:function(a){var b=this.getUploads({id:a}),c=null;return b&&void 0!==b.parentId&&(c=b.parentId),c},getResumableFilesData:function(){return this._handler.getResumableFilesData()},getSize:function(a){return this._uploadData.retrieve({id:a}).size},getNetUploads:function(){return this._netUploaded},getRemainingAllowedItems:function(){var a=this._currentItemLimit;return a>0?a-this._netUploadedOrQueued:null},getUploads:function(a){return this._uploadData.retrieve(a)},getUuid:function(a){return this._uploadData.retrieve({id:a}).uuid},log:function(a,b){!this._options.debug||b&&"info"!==b?b&&"info"!==b&&qq.log("[Fine Uploader "+qq.version+"] "+a,b):qq.log("[Fine Uploader "+qq.version+"] "+a)},pauseUpload:function(a){var b=this._uploadData.retrieve({id:a});if(!qq.supportedFeatures.pause||!this._options.chunking.enabled)return!1;if(qq.indexOf([qq.status.UPLOADING,qq.status.UPLOAD_RETRYING],b.status)>=0){if(this._handler.pause(a))return this._uploadData.setStatus(a,qq.status.PAUSED),!0;this.log(qq.format("Unable to pause file ID {} ({}).",a,this.getName(a)),"error")}else this.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.",a,this.getName(a)),"error");return!1},reset:function(){this.log("Resetting uploader..."),this._handler.reset(),this._storedIds=[],this._autoRetries=[],this._retryTimeouts=[],this._preventRetries=[],this._thumbnailUrls=[],qq.each(this._buttons,function(a,b){b.reset()}),this._paramsStore.reset(),this._endpointStore.reset(),this._netUploadedOrQueued=0,this._netUploaded=0,this._uploadData.reset(),this._buttonIdsForFileIds=[],this._pasteHandler&&this._pasteHandler.reset(),this._options.session.refreshOnReset&&this._refreshSessionData(),this._succeededSinceLastAllComplete=[],this._failedSinceLastAllComplete=[],this._totalProgress&&this._totalProgress.reset()},retry:function(a){return this._manualRetry(a)},scaleImage:function(a,b){var c=this;return qq.Scaler.prototype.scaleImage(a,b,{log:qq.bind(c.log,c),getFile:qq.bind(c.getFile,c),uploadData:c._uploadData})},setCustomHeaders:function(a,b){this._customHeadersStore.set(a,b)},setDeleteFileCustomHeaders:function(a,b){this._deleteFileCustomHeadersStore.set(a,b)},setDeleteFileEndpoint:function(a,b){this._deleteFileEndpointStore.set(a,b)},setDeleteFileParams:function(a,b){this._deleteFileParamsStore.set(a,b)},setEndpoint:function(a,b){this._endpointStore.set(a,b)},setItemLimit:function(a){this._currentItemLimit=a},setName:function(a,b){this._uploadData.updateName(a,b)},setParams:function(a,b){this._paramsStore.set(a,b)},setUuid:function(a,b){return this._uploadData.uuidChanged(a,b)},uploadStoredFiles:function(){var a;if(0===this._storedIds.length)this._itemError("noFilesError");else for(;this._storedIds.length;)a=this._storedIds.shift(),this._uploadFile(a)}},qq.basePrivateApi={_addCannedFile:function(a){var b=this._uploadData.addFile({uuid:a.uuid,name:a.name,size:a.size,status:qq.status.UPLOAD_SUCCESSFUL});return a.deleteFileEndpoint&&this.setDeleteFileEndpoint(a.deleteFileEndpoint,b),a.deleteFileParams&&this.setDeleteFileParams(a.deleteFileParams,b),a.thumbnailUrl&&(this._thumbnailUrls[b]=a.thumbnailUrl),this._netUploaded++,this._netUploadedOrQueued++,b},_annotateWithButtonId:function(a,b){qq.isFile(a)&&(a.qqButtonId=this._getButtonId(b))},_batchError:function(a){this._options.callbacks.onError(null,null,a,void 0)},_createDeleteHandler:function(){var a=this;return new qq.DeleteFileAjaxRequester({method:this._options.deleteFile.method.toUpperCase(),maxConnections:this._options.maxConnections,uuidParamName:this._options.request.uuidName,customHeaders:this._deleteFileCustomHeadersStore,paramsStore:this._deleteFileParamsStore,endpointStore:this._deleteFileEndpointStore,cors:this._options.cors,log:qq.bind(a.log,a),onDelete:function(b){a._onDelete(b),a._options.callbacks.onDelete(b)},onDeleteComplete:function(b,c,d){a._onDeleteComplete(b,c,d),a._options.callbacks.onDeleteComplete(b,c,d)}})},_createPasteHandler:function(){var a=this;return new qq.PasteSupport({targetElement:this._options.paste.targetElement,callbacks:{log:qq.bind(a.log,a),pasteReceived:function(b){a._handleCheckedCallback({name:"onPasteReceived",callback:qq.bind(a._options.callbacks.onPasteReceived,a,b),onSuccess:qq.bind(a._handlePasteSuccess,a,b),identifier:"pasted image"})}}})},_createStore:function(a,b){var c={},d=a,e={},f=function(a){return qq.isObject(a)?qq.extend({},a):a},g=function(){return qq.isFunction(b)?b():b},h=function(a,c){b&&qq.isObject(c)&&qq.extend(c,g()),e[a]&&qq.extend(c,e[a])};return{set:function(a,b){null==b?(c={},d=f(a)):c[b]=f(a)},get:function(a){var b;return b=null!=a&&c[a]?c[a]:f(d),h(a,b),f(b)},addReadOnly:function(a,b){qq.isObject(c)&&(e[a]=e[a]||{},qq.extend(e[a],b))},remove:function(a){return delete c[a]},reset:function(){c={},e={},d=a}}},_createUploadDataTracker:function(){var a=this;return new qq.UploadData({getName:function(b){return a.getName(b)},getUuid:function(b){return a.getUuid(b)},getSize:function(b){return a.getSize(b)},onStatusChange:function(b,c,d){a._onUploadStatusChange(b,c,d),a._options.callbacks.onStatusChange(b,c,d),a._maybeAllComplete(b,d),a._totalProgress&&setTimeout(function(){a._totalProgress.onStatusChange(b,c,d)},0)}})},_createUploadButton:function(a){function b(){return qq.supportedFeatures.ajaxUploading?d._options.workarounds.iosEmptyVideos&&qq.ios()&&!qq.ios6()&&d._isAllowedExtension(f,".mov")?!1:void 0===a.multiple?d._options.multiple:a.multiple:!1}var c,d=this,e=a.accept||this._options.validation.acceptFiles,f=a.allowedExtensions||this._options.validation.allowedExtensions;return c=new qq.UploadButton({element:a.element,folders:a.folders,name:this._options.request.inputName,multiple:b(),acceptFiles:e,onChange:function(a){d._onInputChange(a)},hoverClass:this._options.classes.buttonHover,focusClass:this._options.classes.buttonFocus,ios8BrowserCrashWorkaround:this._options.workarounds.ios8BrowserCrash}),this._disposeSupport.addDisposer(function(){c.dispose()}),d._buttons.push(c),c},_createUploadHandler:function(a,b){var c=this,d={},e={debug:this._options.debug,maxConnections:this._options.maxConnections,cors:this._options.cors,paramsStore:this._paramsStore,endpointStore:this._endpointStore,chunking:this._options.chunking,resume:this._options.resume,blobs:this._options.blobs,log:qq.bind(c.log,c),preventRetryParam:this._options.retry.preventRetryResponseProperty,onProgress:function(a,b,e,f){0>e||0>f||(d[a]?(d[a].loaded!==e||d[a].total!==f)&&(c._onProgress(a,b,e,f),c._options.callbacks.onProgress(a,b,e,f)):(c._onProgress(a,b,e,f),c._options.callbacks.onProgress(a,b,e,f)),d[a]={loaded:e,total:f})},onComplete:function(a,b,e,f){delete d[a];var g,h=c.getUploads({id:a}).status;h!==qq.status.UPLOAD_SUCCESSFUL&&h!==qq.status.UPLOAD_FAILED&&(g=c._onComplete(a,b,e,f),g instanceof qq.Promise?g.done(function(){c._options.callbacks.onComplete(a,b,e,f)}):c._options.callbacks.onComplete(a,b,e,f))},onCancel:function(a,b,d){var e=new qq.Promise;return c._handleCheckedCallback({name:"onCancel",callback:qq.bind(c._options.callbacks.onCancel,c,a,b),onFailure:e.failure,onSuccess:function(){d.then(function(){c._onCancel(a,b)}),e.success()},identifier:a}),e},onUploadPrep:qq.bind(this._onUploadPrep,this),onUpload:function(a,b){c._onUpload(a,b),c._options.callbacks.onUpload(a,b)},onUploadChunk:function(a,b,d){c._onUploadChunk(a,d),c._options.callbacks.onUploadChunk(a,b,d)},onUploadChunkSuccess:function(){c._options.callbacks.onUploadChunkSuccess.apply(c,arguments)},onResume:function(a,b,d){return c._options.callbacks.onResume(a,b,d)},onAutoRetry:function(){return c._onAutoRetry.apply(c,arguments)},onUuidChanged:function(a,b){c.log("Server requested UUID change from '"+c.getUuid(a)+"' to '"+b+"'"),c.setUuid(a,b)},getName:qq.bind(c.getName,c),getUuid:qq.bind(c.getUuid,c),getSize:qq.bind(c.getSize,c),setSize:qq.bind(c._setSize,c),getDataByUuid:function(a){return c.getUploads({uuid:a})},isQueued:function(a){var b=c.getUploads({id:a}).status;return b===qq.status.QUEUED||b===qq.status.SUBMITTED||b===qq.status.UPLOAD_RETRYING||b===qq.status.PAUSED},getIdsInProxyGroup:c._uploadData.getIdsInProxyGroup,getIdsInBatch:c._uploadData.getIdsInBatch};return qq.each(this._options.request,function(a,b){e[a]=b}),e.customHeaders=this._customHeadersStore,a&&qq.each(a,function(a,b){e[a]=b}),new qq.UploadHandlerController(e,b)},_fileOrBlobRejected:function(a){this._netUploadedOrQueued--,this._uploadData.setStatus(a,qq.status.REJECTED)},_formatSize:function(a){var b=-1;do a/=1e3,b++;while(a>999);return Math.max(a,.1).toFixed(1)+this._options.text.sizeSymbols[b]},_generateExtraButtonSpecs:function(){var a=this;this._extraButtonSpecs={},qq.each(this._options.extraButtons,function(b,c){var d=c.multiple,e=qq.extend({},a._options.validation,!0),f=qq.extend({},c);void 0===d&&(d=a._options.multiple),f.validation&&qq.extend(e,c.validation,!0),qq.extend(f,{multiple:d,validation:e},!0),a._initExtraButton(f)})},_getButton:function(a){var b=this._extraButtonSpecs[a];return b?b.element:a===this._defaultButtonId?this._options.button:void 0},_getButtonId:function(a){var b,c,d=a;if(d instanceof qq.BlobProxy&&(d=d.referenceBlob),d&&!qq.isBlob(d)){if(qq.isFile(d))return d.qqButtonId;if("input"===d.tagName.toLowerCase()&&"file"===d.type.toLowerCase())return d.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);if(b=d.getElementsByTagName("input"),qq.each(b,function(a,b){return"file"===b.getAttribute("type")?(c=b,!1):void 0}),c)return c.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME)}},_getNotFinished:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED,qq.status.SUBMITTING,qq.status.SUBMITTED,qq.status.PAUSED]}).length},_getValidationBase:function(a){var b=this._extraButtonSpecs[a];return b?b.validation:this._options.validation},_getValidationDescriptor:function(a){return a.file instanceof qq.BlobProxy?{name:qq.getFilename(a.file.referenceBlob),size:a.file.referenceBlob.size}:{name:this.getUploads({id:a.id}).name,size:this.getUploads({id:a.id}).size}},_getValidationDescriptors:function(a){var b=this,c=[];return qq.each(a,function(a,d){c.push(b._getValidationDescriptor(d))}),c},_handleCameraAccess:function(){if(this._options.camera.ios&&qq.ios()){var a="image/*;capture=camera",b=this._options.camera.button,c=b?this._getButtonId(b):this._defaultButtonId,d=this._options;c&&c!==this._defaultButtonId&&(d=this._extraButtonSpecs[c]),d.multiple=!1,null===d.validation.acceptFiles?d.validation.acceptFiles=a:d.validation.acceptFiles+=","+a,qq.each(this._buttons,function(a,b){return b.getButtonId()===c?(b.setMultiple(d.multiple),b.setAcceptFiles(d.acceptFiles),!1):void 0})}},_handleCheckedCallback:function(a){var b=this,c=a.callback();return qq.isGenericPromise(c)?(this.log(a.name+" - waiting for "+a.name+" promise to be fulfilled for "+a.identifier),c.then(function(c){b.log(a.name+" promise success for "+a.identifier),a.onSuccess(c)},function(){a.onFailure?(b.log(a.name+" promise failure for "+a.identifier),a.onFailure()):b.log(a.name+" promise failure for "+a.identifier)})):(c!==!1?a.onSuccess(c):a.onFailure?(this.log(a.name+" - return value was 'false' for "+a.identifier+". Invoking failure callback."),a.onFailure()):this.log(a.name+" - return value was 'false' for "+a.identifier+". Will not proceed."),c)},_handleNewFile:function(a,b,c){var d=this,e=qq.getUniqueId(),f=-1,g=qq.getFilename(a),h=a.blob||a,i=this._customNewFileHandler?this._customNewFileHandler:qq.bind(d._handleNewFileGeneric,d);!qq.isInput(h)&&h.size>=0&&(f=h.size),i(h,g,e,f,c,b,this._options.request.uuidName,{uploadData:d._uploadData,paramsStore:d._paramsStore,addFileToHandler:function(a,b){d._handler.add(a,b),d._netUploadedOrQueued++,d._trackButton(a)}})},_handleNewFileGeneric:function(a,b,c,d,e,f){var g=this._uploadData.addFile({uuid:c,name:b,size:d,batchId:f});this._handler.add(g,a),this._trackButton(g),this._netUploadedOrQueued++,e.push({id:g,file:a})},_handlePasteSuccess:function(a,b){var c=a.type.split("/")[1],d=b;null==d&&(d=this._options.paste.defaultName),d+="."+c,this.addFiles({name:d,blob:a})},_initExtraButton:function(a){var b=this._createUploadButton({element:a.element,multiple:a.multiple,accept:a.validation.acceptFiles,folders:a.folders,allowedExtensions:a.validation.allowedExtensions});this._extraButtonSpecs[b.getButtonId()]=a},_initFormSupportAndParams:function(){this._formSupport=qq.FormSupport&&new qq.FormSupport(this._options.form,qq.bind(this.uploadStoredFiles,this),qq.bind(this.log,this)),this._formSupport&&this._formSupport.attachedToForm?(this._paramsStore=this._createStore(this._options.request.params,this._formSupport.getFormInputsAsObject),this._options.autoUpload=this._formSupport.newAutoUpload,this._formSupport.newEndpoint&&(this._options.request.endpoint=this._formSupport.newEndpoint)):this._paramsStore=this._createStore(this._options.request.params)
-},_isDeletePossible:function(){return qq.DeleteFileAjaxRequester&&this._options.deleteFile.enabled?this._options.cors.expected?qq.supportedFeatures.deleteFileCorsXhr?!0:qq.supportedFeatures.deleteFileCorsXdr&&this._options.cors.allowXdr?!0:!1:!0:!1},_isAllowedExtension:function(a,b){var c=!1;return a.length?(qq.each(a,function(a,d){if(qq.isString(d)){var e=new RegExp("\\."+d+"$","i");if(null!=b.match(e))return c=!0,!1}}),c):!0},_itemError:function(a,b,c){function d(a,b){g=g.replace(a,b)}var e,f,g=this._options.messages[a],h=[],i=[].concat(b),j=i[0],k=this._getButtonId(c),l=this._getValidationBase(k);return qq.each(l.allowedExtensions,function(a,b){qq.isString(b)&&h.push(b)}),e=h.join(", ").toLowerCase(),d("{file}",this._options.formatFileName(j)),d("{extensions}",e),d("{sizeLimit}",this._formatSize(l.sizeLimit)),d("{minSizeLimit}",this._formatSize(l.minSizeLimit)),f=g.match(/(\{\w+\})/g),null!==f&&qq.each(f,function(a,b){d(b,i[a])}),this._options.callbacks.onError(null,j,g,void 0),g},_manualRetry:function(a,b){return this._onBeforeManualRetry(a)?(this._netUploadedOrQueued++,this._uploadData.setStatus(a,qq.status.UPLOAD_RETRYING),b?b(a):this._handler.retry(a),!0):void 0},_maybeAllComplete:function(a,b){var c=this,d=this._getNotFinished();b===qq.status.UPLOAD_SUCCESSFUL?this._succeededSinceLastAllComplete.push(a):b===qq.status.UPLOAD_FAILED&&this._failedSinceLastAllComplete.push(a),0===d&&(this._succeededSinceLastAllComplete.length||this._failedSinceLastAllComplete.length)&&setTimeout(function(){c._onAllComplete(c._succeededSinceLastAllComplete,c._failedSinceLastAllComplete)},0)},_maybeHandleIos8SafariWorkaround:function(){var a=this;if(this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari())throw setTimeout(function(){window.alert(a._options.messages.unsupportedBrowserIos8Safari)},0),new qq.Error(this._options.messages.unsupportedBrowserIos8Safari)},_maybeParseAndSendUploadError:function(a,b,c,d){if(!c.success)if(d&&200!==d.status&&!c.error)this._options.callbacks.onError(a,b,"XHR returned response code "+d.status,d);else{var e=c.error?c.error:this._options.text.defaultResponseError;this._options.callbacks.onError(a,b,e,d)}},_maybeProcessNextItemAfterOnValidateCallback:function(a,b,c,d,e){var f=this;if(b.length>c)if(a||!this._options.validation.stopOnFirstInvalidFile)setTimeout(function(){var a=f._getValidationDescriptor(b[c]),g=f._getButtonId(b[c].file),h=f._getButton(g);f._handleCheckedCallback({name:"onValidate",callback:qq.bind(f._options.callbacks.onValidate,f,a,h),onSuccess:qq.bind(f._onValidateCallbackSuccess,f,b,c,d,e),onFailure:qq.bind(f._onValidateCallbackFailure,f,b,c,d,e),identifier:"Item '"+a.name+"', size: "+a.size})},0);else if(!a)for(;c0&&this._netUploadedOrQueued+1>c?(this._itemError("retryFailTooManyItems"),!1):(this.log("Retrying upload for '"+b+"' (id: "+a+")..."),!0)):(this.log("'"+a+"' is not a valid file ID","error"),!1)},_onCancel:function(a){this._netUploadedOrQueued--,clearTimeout(this._retryTimeouts[a]);var b=qq.indexOf(this._storedIds,a);!this._options.autoUpload&&b>=0&&this._storedIds.splice(b,1),this._uploadData.setStatus(a,qq.status.CANCELED)},_onComplete:function(a,b,c,d){return c.success?(c.thumbnailUrl&&(this._thumbnailUrls[a]=c.thumbnailUrl),this._netUploaded++,this._uploadData.setStatus(a,qq.status.UPLOAD_SUCCESSFUL)):(this._netUploadedOrQueued--,this._uploadData.setStatus(a,qq.status.UPLOAD_FAILED),c[this._options.retry.preventRetryResponseProperty]===!0&&(this._preventRetries[a]=!0)),this._maybeParseAndSendUploadError(a,b,c,d),c.success?!0:!1},_onDelete:function(a){this._uploadData.setStatus(a,qq.status.DELETING)},_onDeleteComplete:function(a,b,c){var d=this.getName(a);c?(this._uploadData.setStatus(a,qq.status.DELETE_FAILED),this.log("Delete request for '"+d+"' has failed.","error"),void 0===b.withCredentials?this._options.callbacks.onError(a,d,"Delete request failed",b):this._options.callbacks.onError(a,d,"Delete request failed with response code "+b.status,b)):(this._netUploadedOrQueued--,this._netUploaded--,this._handler.expunge(a),this._uploadData.setStatus(a,qq.status.DELETED),this.log("Delete request for '"+d+"' has succeeded."))},_onInputChange:function(a){var b;if(qq.supportedFeatures.ajaxUploading){for(b=0;b0&&this.addFiles(a);qq.each(this._buttons,function(a,b){b.reset()})},_onProgress:function(a,b,c,d){this._totalProgress&&this._totalProgress.onIndividualProgress(a,c,d)},_onSubmit:function(){},_onSubmitCallbackSuccess:function(a){this._onSubmit.apply(this,arguments),this._uploadData.setStatus(a,qq.status.SUBMITTED),this._onSubmitted.apply(this,arguments),this._options.callbacks.onSubmitted.apply(this,arguments),this._options.autoUpload?this._uploadFile(a):this._storeForLater(a)},_onSubmitDelete:function(a,b,c){var d,e=this.getUuid(a);return b&&(d=qq.bind(b,this,a,e,c)),this._isDeletePossible()?(this._handleCheckedCallback({name:"onSubmitDelete",callback:qq.bind(this._options.callbacks.onSubmitDelete,this,a),onSuccess:d||qq.bind(this._deleteHandler.sendDelete,this,a,e,c),identifier:a}),!0):(this.log("Delete request ignored for ID "+a+", delete feature is disabled or request not possible "+"due to CORS on a user agent that does not support pre-flighting.","warn"),!1)},_onSubmitted:function(){},_onTotalProgress:function(a,b){this._options.callbacks.onTotalProgress(a,b)},_onUploadPrep:function(){},_onUpload:function(a){this._uploadData.setStatus(a,qq.status.UPLOADING)},_onUploadChunk:function(){},_onUploadStatusChange:function(a,b,c){c===qq.status.PAUSED&&clearTimeout(this._retryTimeouts[a])},_onValidateBatchCallbackFailure:function(a){var b=this;qq.each(a,function(a,c){b._fileOrBlobRejected(c.id)})},_onValidateBatchCallbackSuccess:function(a,b,c,d,e){var f,g=this._currentItemLimit,h=this._netUploadedOrQueued;0===g||g>=h?b.length>0?this._handleCheckedCallback({name:"onValidate",callback:qq.bind(this._options.callbacks.onValidate,this,a[0],e),onSuccess:qq.bind(this._onValidateCallbackSuccess,this,b,0,c,d),onFailure:qq.bind(this._onValidateCallbackFailure,this,b,0,c,d),identifier:"Item '"+b[0].file.name+"', size: "+b[0].file.size}):this._itemError("noFilesError"):(this._onValidateBatchCallbackFailure(b),f=this._options.messages.tooManyItemsError.replace(/\{netItems\}/g,h).replace(/\{itemLimit\}/g,g),this._batchError(f))},_onValidateCallbackFailure:function(a,b,c,d){var e=b+1;this._fileOrBlobRejected(a[b].id,a[b].file.name),this._maybeProcessNextItemAfterOnValidateCallback(!1,a,e,c,d)},_onValidateCallbackSuccess:function(a,b,c,d){var e=this,f=b+1,g=this._getValidationDescriptor(a[b]);this._validateFileOrBlobData(a[b],g).then(function(){e._upload(a[b].id,c,d),e._maybeProcessNextItemAfterOnValidateCallback(!0,a,f,c,d)},function(){e._maybeProcessNextItemAfterOnValidateCallback(!1,a,f,c,d)})},_prepareItemsForUpload:function(a,b,c){if(0===a.length)return this._itemError("noFilesError"),void 0;var d=this._getValidationDescriptors(a),e=this._getButtonId(a[0].file),f=this._getButton(e);this._handleCheckedCallback({name:"onValidateBatch",callback:qq.bind(this._options.callbacks.onValidateBatch,this,d,f),onSuccess:qq.bind(this._onValidateBatchCallbackSuccess,this,d,a,b,c,f),onFailure:qq.bind(this._onValidateBatchCallbackFailure,this,a),identifier:"batch validation"})},_preventLeaveInProgress:function(){var a=this;this._disposeSupport.attach(window,"beforeunload",function(b){return a.getInProgress()?(b=b||window.event,b.returnValue=a._options.messages.onLeave,a._options.messages.onLeave):void 0})},_refreshSessionData:function(){var a=this,b=this._options.session;qq.Session&&null!=this._options.session.endpoint&&(this._session||(qq.extend(b,this._options.cors),b.log=qq.bind(this.log,this),b.addFileRecord=qq.bind(this._addCannedFile,this),this._session=new qq.Session(b)),setTimeout(function(){a._session.refresh().then(function(b,c){a._options.callbacks.onSessionRequestComplete(b,!0,c)},function(b,c){a._options.callbacks.onSessionRequestComplete(b,!1,c)})},0))},_setSize:function(a,b){this._uploadData.updateSize(a,b),this._totalProgress&&this._totalProgress.onNewSize(a)},_shouldAutoRetry:function(a){var b=this._uploadData.retrieve({id:a});return!this._preventRetries[a]&&this._options.retry.enableAuto&&b.status!==qq.status.PAUSED&&(void 0===this._autoRetries[a]&&(this._autoRetries[a]=0),this._autoRetries[a]0&&h.sizeLimit&&f>h.sizeLimit?(this._itemError("sizeError",e,d),i.failure()):f>0&&f=0}function c(){var a=!1;return qq.each(a,function(b,c){return qq.indexOf(["Accept","Accept-Language","Content-Language","Content-Type"],c)<0?(a=!0,!1):void 0}),a}function d(a){return w.cors.expected&&void 0===a.withCredentials}function e(){var a;return(window.XMLHttpRequest||window.ActiveXObject)&&(a=qq.createXhrInstance(),void 0===a.withCredentials&&(a=new XDomainRequest)),a}function f(a,b){var c=v[a].xhr;return c||(c=b?b:w.cors.expected?e():qq.createXhrInstance(),v[a].xhr=c),c}function g(a){var b,c=qq.indexOf(u,a),d=w.maxConnections;delete v[a],u.splice(c,1),u.length>=d&&d>c&&(b=u[d-1],j(b))}function h(a,b){var c=f(a),e=w.method,h=b===!0;g(a),h?s(e+" request for "+a+" has failed","error"):d(c)||q(c.status)||(h=!0,s(e+" request for "+a+" has failed - response code "+c.status,"error")),w.onComplete(a,c,h)}function i(a){var b,c=v[a].additionalParams,d=w.mandatedParams;return w.paramsStore.get&&(b=w.paramsStore.get(a)),c&&qq.each(c,function(a,c){b=b||{},b[a]=c}),d&&qq.each(d,function(a,c){b=b||{},b[a]=c}),b}function j(a,b){var c,e=f(a,b),g=w.method,h=i(a),j=v[a].payload;return w.onSend(a),c=k(a,h),d(e)?(e.onload=n(a),e.onerror=o(a)):e.onreadystatechange=l(a),m(a),e.open(g,c,!0),w.cors.expected&&w.cors.sendCredentials&&!d(e)&&(e.withCredentials=!0),p(a),s("Sending "+g+" request for "+a),j?e.send(j):t||!h?e.send():h&&w.contentType&&w.contentType.toLowerCase().indexOf("application/x-www-form-urlencoded")>=0?e.send(qq.obj2url(h,"")):h&&w.contentType&&w.contentType.toLowerCase().indexOf("application/json")>=0?e.send(JSON.stringify(h)):e.send(h),e}function k(a,b){var c=w.endpointStore.get(a),d=v[a].addToPath;return void 0!=d&&(c+="/"+d),t&&b?qq.obj2url(b,c):c}function l(a){return function(){4===f(a).readyState&&h(a)}}function m(a){var b=w.onProgress;b&&(f(a).upload.onprogress=function(c){c.lengthComputable&&b(a,c.loaded,c.total)})}function n(a){return function(){h(a)}}function o(a){return function(){h(a,!0)}}function p(a){var e=f(a),g=w.customHeaders,h=v[a].additionalHeaders||{},i=w.method,j={};d(e)||(w.acceptHeader&&e.setRequestHeader("Accept",w.acceptHeader),w.allowXRequestedWithAndCacheControl&&(w.cors.expected&&b()&&!c(g)||(e.setRequestHeader("X-Requested-With","XMLHttpRequest"),e.setRequestHeader("Cache-Control","no-cache"))),!w.contentType||"POST"!==i&&"PUT"!==i||e.setRequestHeader("Content-Type",w.contentType),qq.extend(j,qq.isFunction(g)?g(a):g),qq.extend(j,h),qq.each(j,function(a,b){e.setRequestHeader(a,b)}))}function q(a){return qq.indexOf(w.successfulResponseCodes[w.method],a)>=0}function r(a,b,c,d,e,f){v[a]={addToPath:c,additionalParams:d,additionalHeaders:e,payload:f};var g=u.push(a);return g<=w.maxConnections?j(a,b):void 0}var s,t,u=[],v={},w={acceptHeader:null,validMethods:["PATCH","POST","PUT"],method:"POST",contentType:"application/x-www-form-urlencoded",maxConnections:3,customHeaders:{},endpointStore:{},paramsStore:{},mandatedParams:{},allowXRequestedWithAndCacheControl:!0,successfulResponseCodes:{DELETE:[200,202,204],PATCH:[200,201,202,203,204],POST:[200,201,202,203,204],PUT:[200,201,202,203,204],GET:[200]},cors:{expected:!1,sendCredentials:!1},log:function(){},onSend:function(){},onComplete:function(){},onProgress:null};if(qq.extend(w,a),s=w.log,qq.indexOf(w.validMethods,w.method)<0)throw new Error("'"+w.method+"' is not a supported method for this type of request!");t="GET"===w.method||"DELETE"===w.method,qq.extend(this,{initTransport:function(a){var b,c,d,e,f;return{withPath:function(a){return b=a,this},withParams:function(a){return c=a,this},withHeaders:function(a){return d=a,this},withPayload:function(a){return e=a,this},withCacheBuster:function(){return f=!0,this},send:function(g){return f&&qq.indexOf(["GET","DELETE"],w.method)>=0&&(c.qqtimestamp=(new Date).getTime()),r(a,g,b,c,d,e)}}},canceled:function(a){g(a)}})},qq.UploadHandler=function(a){"use strict";var b=a.proxy,c={},d=b.onCancel,e=b.getName;qq.extend(this,{add:function(a,b){c[a]=b,c[a].temp={}},cancel:function(a){var b=this,f=new qq.Promise,g=d(a,e(a),f);g.then(function(){b.isValid(a)&&(c[a].canceled=!0,b.expunge(a)),f.success()})},expunge:function(a){delete c[a]},getThirdPartyFileId:function(a){return c[a].key},isValid:function(a){return void 0!==c[a]},reset:function(){c={}},_getFileState:function(a){return c[a]},_setThirdPartyFileId:function(a,b){c[a].key=b},_wasCanceled:function(a){return!!c[a].canceled}})},qq.UploadHandlerController=function(a,b){"use strict";var c,d,e,f=this,g=!1,h=!1,i={paramsStore:{},maxConnections:3,chunking:{enabled:!1,multiple:{enabled:!1}},log:function(){},onProgress:function(){},onComplete:function(){},onCancel:function(){},onUploadPrep:function(){},onUpload:function(){},onUploadChunk:function(){},onUploadChunkSuccess:function(){},onAutoRetry:function(){},onResume:function(){},onUuidChanged:function(){},getName:function(){},setSize:function(){},isQueued:function(){},getIdsInProxyGroup:function(){},getIdsInBatch:function(){}},j={done:function(a,b,c,d){var f=e._getChunkData(a,b);e._getFileState(a).attemptingResume=!1,delete e._getFileState(a).temp.chunkProgress[b],e._getFileState(a).loaded+=f.size,i.onUploadChunkSuccess(a,e._getChunkDataForCallback(f),c,d)},finalize:function(a){var b=i.getSize(a),c=i.getName(a);d("All chunks have been uploaded for "+a+" - finalizing...."),e.finalizeChunks(a).then(function(f,g){d("Finalize successful for "+a);var h=m.normalizeResponse(f,!0);i.onProgress(a,c,b,b),e._maybeDeletePersistedChunkData(a),m.cleanup(a,h,g)},function(b,e){var f=m.normalizeResponse(b,!1);d("Problem finalizing chunks for file ID "+a+" - "+f.error,"error"),f.reset&&j.reset(a),i.onAutoRetry(a,c,f,e)||m.cleanup(a,f,e)})},hasMoreParts:function(a){return!!e._getFileState(a).chunking.remaining.length},nextPart:function(a){var b=e._getFileState(a).chunking.remaining.shift();return b>=e._getTotalChunks(a)&&(b=null),b},reset:function(a){d("Server or callback has ordered chunking effort to be restarted on next attempt for item ID "+a,"error"),e._maybeDeletePersistedChunkData(a),e.reevaluateChunking(a),e._getFileState(a).loaded=0},sendNext:function(a){var b=i.getSize(a),c=i.getName(a),f=j.nextPart(a),g=e._getChunkData(a,f),l=e._getFileState(a).attemptingResume,n=e._getFileState(a).chunking.inProgress||[];null==e._getFileState(a).loaded&&(e._getFileState(a).loaded=0),l&&i.onResume(a,c,g)===!1&&(j.reset(a),f=j.nextPart(a),g=e._getChunkData(a,f),l=!1),null==f&&0===n.length?j.finalize(a):(d("Sending chunked upload request for item "+a+": bytes "+(g.start+1)+"-"+g.end+" of "+b),i.onUploadChunk(a,c,e._getChunkDataForCallback(g)),n.push(f),e._getFileState(a).chunking.inProgress=n,h&&k.open(a,f),h&&k.available()&&e._getFileState(a).chunking.remaining.length&&j.sendNext(a),e.uploadChunk(a,f,l).then(function(b,c){d("Chunked upload request succeeded for "+a+", chunk "+f),e.clearCachedChunk(a,f);var g=e._getFileState(a).chunking.inProgress||[],h=m.normalizeResponse(b,!0),i=qq.indexOf(g,f);d(qq.format("Chunk {} for file {} uploaded successfully.",f,a)),j.done(a,f,h,c),i>=0&&g.splice(i,1),e._maybePersistChunkedState(a),j.hasMoreParts(a)||0!==g.length?j.hasMoreParts(a)&&j.sendNext(a):j.finalize(a)},function(b,g){d("Chunked upload request failed for "+a+", chunk "+f),e.clearCachedChunk(a,f);var l,n=m.normalizeResponse(b,!1);n.reset?j.reset(a):(l=qq.indexOf(e._getFileState(a).chunking.inProgress,f),l>=0&&(e._getFileState(a).chunking.inProgress.splice(l,1),e._getFileState(a).chunking.remaining.unshift(f))),e._getFileState(a).temp.ignoreFailure||(h&&(e._getFileState(a).temp.ignoreFailure=!0,qq.each(e._getXhrs(a),function(a,b){b.abort()}),e.moveInProgressToRemaining(a),k.free(a,!0)),i.onAutoRetry(a,c,n,g)||m.cleanup(a,n,g))}).done(function(){e.clearXhr(a,f)}))}},k={_open:[],_openChunks:{},_waiting:[],available:function(){var a=i.maxConnections,b=0,c=0;return qq.each(k._openChunks,function(a,d){b++,c+=d.length}),a-(k._open.length-b+c)},free:function(a,b){var c,f=!b,g=qq.indexOf(k._waiting,a),h=qq.indexOf(k._open,a);delete k._openChunks[a],m.getProxyOrBlob(a)instanceof qq.BlobProxy&&(d("Generated blob upload has ended for "+a+", disposing generated blob."),delete e._getFileState(a).file),g>=0?k._waiting.splice(g,1):f&&h>=0&&(k._open.splice(h,1),c=k._waiting.shift(),c>=0&&(k._open.push(c),m.start(c)))},getWaitingOrConnected:function(){var a=[];return qq.each(k._openChunks,function(b,c){c&&c.length&&a.push(parseInt(b))}),qq.each(k._open,function(b,c){k._openChunks[c]||a.push(parseInt(c))}),a=a.concat(k._waiting)},isUsingConnection:function(a){return qq.indexOf(k._open,a)>=0},open:function(a,b){return null==b&&k._waiting.push(a),k.available()?(null==b?(k._waiting.pop(),k._open.push(a)):function(){var c=k._openChunks[a]||[];c.push(b),k._openChunks[a]=c}(),!0):!1},reset:function(){k._waiting=[],k._open=[]}},l={send:function(a,b){e._getFileState(a).loaded=0,d("Sending simple upload request for "+a),e.uploadFile(a).then(function(c,e){d("Simple upload request succeeded for "+a);var f=m.normalizeResponse(c,!0),g=i.getSize(a);i.onProgress(a,b,g,g),m.maybeNewUuid(a,f),m.cleanup(a,f,e)},function(c,e){d("Simple upload request failed for "+a);var f=m.normalizeResponse(c,!1);i.onAutoRetry(a,b,f,e)||m.cleanup(a,f,e)})}},m={cancel:function(a){d("Cancelling "+a),i.paramsStore.remove(a),k.free(a)},cleanup:function(a,b,c){var d=i.getName(a);i.onComplete(a,d,b,c),e._getFileState(a)&&e._clearXhrs&&e._clearXhrs(a),k.free(a)},getProxyOrBlob:function(a){return e.getProxy&&e.getProxy(a)||e.getFile&&e.getFile(a)},initHandler:function(){var a=b?qq[b]:qq.traditional,c=qq.supportedFeatures.ajaxUploading?"Xhr":"Form";e=new a[c+"UploadHandler"](i,{getDataByUuid:i.getDataByUuid,getName:i.getName,getSize:i.getSize,getUuid:i.getUuid,log:d,onCancel:i.onCancel,onProgress:i.onProgress,onUuidChanged:i.onUuidChanged}),e._removeExpiredChunkingRecords&&e._removeExpiredChunkingRecords()},isDeferredEligibleForUpload:function(a){return i.isQueued(a)},maybeDefer:function(a,b){return b&&!e.getFile(a)&&b instanceof qq.BlobProxy?(i.onUploadPrep(a),d("Attempting to generate a blob on-demand for "+a),b.create().then(function(b){d("Generated an on-demand blob for "+a),e.updateBlob(a,b),i.setSize(a,b.size),e.reevaluateChunking(a),m.maybeSendDeferredFiles(a)},function(b){var e={};b&&(e.error=b),d(qq.format("Failed to generate blob for ID {}. Error message: {}.",a,b),"error"),i.onComplete(a,i.getName(a),qq.extend(e,c),null),m.maybeSendDeferredFiles(a),k.free(a)}),!1):m.maybeSendDeferredFiles(a)},maybeSendDeferredFiles:function(a){var b=i.getIdsInProxyGroup(a),c=!1;return b&&b.length?(d("Maybe ready to upload proxy group file "+a),qq.each(b,function(b,d){if(m.isDeferredEligibleForUpload(d)&&e.getFile(d))c=d===a,m.now(d);else if(m.isDeferredEligibleForUpload(d))return!1})):(c=!0,m.now(a)),c},maybeNewUuid:function(a,b){void 0!==b.newUuid&&i.onUuidChanged(a,b.newUuid)},normalizeResponse:function(a,b){var c=a;return qq.isObject(a)||(c={},qq.isString(a)&&!b&&(c.error=a)),c.success=b,c},now:function(a){var b=i.getName(a);if(!f.isValid(a))throw new qq.Error(a+" is not a valid file ID to upload!");i.onUpload(a,b),g&&e._shouldChunkThisFile(a)?j.sendNext(a):l.send(a,b)},start:function(a){var b=m.getProxyOrBlob(a);return b?m.maybeDefer(a,b):(m.now(a),!0)}};qq.extend(this,{add:function(){e.add.apply(this,arguments)},upload:function(a){return k.open(a)?m.start(a):!1},retry:function(a){return h&&(e._getFileState(a).temp.ignoreFailure=!1),k.isUsingConnection(a)?m.start(a):f.upload(a)},cancel:function(a){var b=e.cancel(a);qq.isGenericPromise(b)?b.then(function(){m.cancel(a)}):b!==!1&&m.cancel(a)},cancelAll:function(){var a,b=k.getWaitingOrConnected();if(b.length)for(a=b.length-1;a>=0;a--)f.cancel(b[a]);k.reset()},getFile:function(a){return e.getProxy&&e.getProxy(a)?e.getProxy(a).referenceBlob:e.getFile&&e.getFile(a)},isProxied:function(a){return!(!e.getProxy||!e.getProxy(a))},getInput:function(a){return e.getInput?e.getInput(a):void 0},reset:function(){d("Resetting upload handler"),f.cancelAll(),k.reset(),e.reset()},expunge:function(a){return f.isValid(a)?e.expunge(a):void 0},isValid:function(a){return e.isValid(a)},getResumableFilesData:function(){return e.getResumableFilesData?e.getResumableFilesData():[]},getThirdPartyFileId:function(a){return f.isValid(a)?e.getThirdPartyFileId(a):void 0},pause:function(a){return f.isResumable(a)&&e.pause&&f.isValid(a)&&e.pause(a)?(k.free(a),e.moveInProgressToRemaining(a),!0):!1},isResumable:function(a){return!!e.isResumable&&e.isResumable(a)}}),qq.extend(i,a),d=i.log,g=i.chunking.enabled&&qq.supportedFeatures.chunking,h=g&&i.chunking.concurrent.enabled,c=function(){var a={};return a[i.preventRetryParam]=!0,a}(),m.initHandler()},qq.FormUploadHandler=function(a){"use strict";function b(a){delete k[a],m&&(clearTimeout(l[a]),delete l[a],q.stopReceivingMessages(a));var b=document.getElementById(g._getIframeName(a));b&&(b.setAttribute("src","javascript:false;"),qq(b).remove())}function c(a){return a.split("_")[0]}function d(a){var b=qq.toElement("");return b.setAttribute("id",a),b.style.display="none",document.body.appendChild(b),b}function e(a,b){var d=a.id,e=c(d),f=o(e);j[f]=b,k[e]=qq(a).attach("load",function(){g.getInput(e)&&(p("Received iframe load event for CORS upload request (iframe name "+d+")"),l[d]=setTimeout(function(){var a="No valid message received from loaded iframe for iframe name "+d;p(a,"error"),b({error:a})},1e3))}),q.receiveMessage(d,function(a){p("Received the following window message: '"+a+"'");var b,e=(c(d),g._parseJsonResponse(a)),f=e.uuid;f&&j[f]?(p("Handling response for iframe name "+d),clearTimeout(l[d]),delete l[d],g._detachLoadEvent(d),b=j[f],delete j[f],q.stopReceivingMessages(d),b(e)):f||p("'"+a+"' does not contain a UUID - ignoring.")})}var f=a.options,g=this,h=a.proxy,i=qq.getUniqueId(),j={},k={},l={},m=f.isCors,n=f.inputName,o=h.getUuid,p=h.log,q=new qq.WindowReceiveMessage({log:p});qq.extend(this,new qq.UploadHandler(a)),qq.override(this,function(a){return{add:function(b,c){a.add(b,{input:c}),c.setAttribute("name",n),c.parentNode&&qq(c).remove()},expunge:function(c){b(c),a.expunge(c)},isValid:function(b){return a.isValid(b)&&void 0!==g._getFileState(b).input}}}),qq.extend(this,{getInput:function(a){return g._getFileState(a).input},_attachLoadEvent:function(a,b){var c;m?e(a,b):k[a.id]=qq(a).attach("load",function(){if(p("Received response for "+a.id),a.parentNode){try{if(a.contentDocument&&a.contentDocument.body&&"false"==a.contentDocument.body.innerHTML)return}catch(d){p("Error when attempting to access iframe during handling of upload response ("+d.message+")","error"),c={success:!1}}b(c)}})},_createIframe:function(a){var b=g._getIframeName(a);return d(b)},_detachLoadEvent:function(a){void 0!==k[a]&&(k[a](),delete k[a])},_getIframeName:function(a){return a+"_"+i},_initFormForUpload:function(a){var b=a.method,c=a.endpoint,d=a.params,e=a.paramsInBody,f=a.targetName,g=qq.toElement("
"),h=c;return e?qq.obj2Inputs(d,g):h=qq.obj2url(d,c),g.setAttribute("action",h),g.setAttribute("target",f),g.style.display="none",document.body.appendChild(g),g
-},_parseJsonResponse:function(a){var b={};try{b=qq.parseJson(a)}catch(c){p("Error when attempting to parse iframe upload response ("+c.message+")","error")}return b}})},qq.XhrUploadHandler=function(a){"use strict";function b(a){qq.each(c._getXhrs(a),function(b,d){var e=c._getAjaxRequester(a,b);d.onreadystatechange=null,d.upload.onprogress=null,d.abort(),e&&e.canceled&&e.canceled(a)})}var c=this,d=a.options.namespace,e=a.proxy,f=a.options.chunking,g=a.options.resume,h=f&&a.options.chunking.enabled&&qq.supportedFeatures.chunking,i=g&&a.options.resume.enabled&&h&&qq.supportedFeatures.resume,j=e.getName,k=e.getSize,l=e.getUuid,m=e.getEndpoint,n=e.getDataByUuid,o=e.onUuidChanged,p=e.onProgress,q=e.log;qq.extend(this,new qq.UploadHandler(a)),qq.override(this,function(a){return{add:function(b,d){if(qq.isFile(d)||qq.isBlob(d))a.add(b,{file:d});else{if(!(d instanceof qq.BlobProxy))throw new Error("Passed obj is not a File, Blob, or proxy");a.add(b,{proxy:d})}c._initTempState(b),i&&c._maybePrepareForResume(b)},expunge:function(d){b(d),c._maybeDeletePersistedChunkData(d),c._clearXhrs(d),a.expunge(d)}}}),qq.extend(this,{clearCachedChunk:function(a,b){delete c._getFileState(a).temp.cachedChunks[b]},clearXhr:function(a,b){var d=c._getFileState(a).temp;d.xhrs&&delete d.xhrs[b],d.ajaxRequesters&&delete d.ajaxRequesters[b]},finalizeChunks:function(a,b){var d=c._getTotalChunks(a)-1,e=c._getXhr(a,d);return b?(new qq.Promise).success(b(e),e):(new qq.Promise).success({},e)},getFile:function(a){return c.isValid(a)&&c._getFileState(a).file},getProxy:function(a){return c.isValid(a)&&c._getFileState(a).proxy},getResumableFilesData:function(){var a=[];return c._iterateResumeRecords(function(b,d){c.moveInProgressToRemaining(null,d.chunking.inProgress,d.chunking.remaining);var e={name:d.name,remaining:d.chunking.remaining,size:d.size,uuid:d.uuid};d.key&&(e.key=d.key),a.push(e)}),a},isResumable:function(a){return!!f&&c.isValid(a)&&!c._getFileState(a).notResumable},moveInProgressToRemaining:function(a,b,d){var e=b||c._getFileState(a).chunking.inProgress,f=d||c._getFileState(a).chunking.remaining;e&&(e.reverse(),qq.each(e,function(a,b){f.unshift(b)}),e.length=0)},pause:function(a){return c.isValid(a)?(q(qq.format("Aborting XHR upload for {} '{}' due to pause instruction.",a,j(a))),c._getFileState(a).paused=!0,b(a),!0):void 0},reevaluateChunking:function(a){if(f&&c.isValid(a)){var b,d,e=c._getFileState(a);if(delete e.chunking,e.chunking={},b=c._getTotalChunks(a),b>1||f.mandatory){for(e.chunking.enabled=!0,e.chunking.parts=b,e.chunking.remaining=[],d=0;b>d;d++)e.chunking.remaining.push(d);c._initTempState(a)}else e.chunking.enabled=!1}},updateBlob:function(a,b){c.isValid(a)&&(c._getFileState(a).file=b)},_clearXhrs:function(a){var b=c._getFileState(a).temp;qq.each(b.ajaxRequesters,function(a){delete b.ajaxRequesters[a]}),qq.each(b.xhrs,function(a){delete b.xhrs[a]})},_createXhr:function(a,b){return c._registerXhr(a,b,qq.createXhrInstance())},_getAjaxRequester:function(a,b){var d=null==b?-1:b;return c._getFileState(a).temp.ajaxRequesters[d]},_getChunkData:function(a,b){var d=f.partSize,e=k(a),g=c.getFile(a),h=d*b,i=h+d>=e?e:h+d,j=c._getTotalChunks(a),l=this._getFileState(a).temp.cachedChunks,m=l[b]||qq.sliceBlob(g,h,i);return l[b]=m,{part:b,start:h,end:i,count:j,blob:m,size:i-h}},_getChunkDataForCallback:function(a){return{partIndex:a.part,startByte:a.start+1,endByte:a.end,totalParts:a.count}},_getLocalStorageId:function(a){var b="5.0",c=j(a),e=k(a),g=f.partSize,h=m(a);return qq.format("qq{}resume{}-{}-{}-{}-{}",d,b,c,e,g,h)},_getMimeType:function(a){return c.getFile(a).type},_getPersistableData:function(a){return c._getFileState(a).chunking},_getTotalChunks:function(a){if(f){var b=k(a),c=f.partSize;return Math.ceil(b/c)}},_getXhr:function(a,b){var d=null==b?-1:b;return c._getFileState(a).temp.xhrs[d]},_getXhrs:function(a){return c._getFileState(a).temp.xhrs},_iterateResumeRecords:function(a){i&&qq.each(localStorage,function(b,c){if(0===b.indexOf(qq.format("qq{}resume-",d))){var e=JSON.parse(c);a(b,e)}})},_initTempState:function(a){c._getFileState(a).temp={ajaxRequesters:{},chunkProgress:{},xhrs:{},cachedChunks:{}}},_markNotResumable:function(a){c._getFileState(a).notResumable=!0},_maybeDeletePersistedChunkData:function(a){var b;return i&&c.isResumable(a)&&(b=c._getLocalStorageId(a),b&&localStorage.getItem(b))?(localStorage.removeItem(b),!0):!1},_maybePrepareForResume:function(a){var b,d,e=c._getFileState(a);i&&void 0===e.key&&(b=c._getLocalStorageId(a),d=localStorage.getItem(b),d&&(d=JSON.parse(d),n(d.uuid)?c._markNotResumable(a):(q(qq.format("Identified file with ID {} and name of {} as resumable.",a,j(a))),o(a,d.uuid),e.key=d.key,e.chunking=d.chunking,e.loaded=d.loaded,e.attemptingResume=!0,c.moveInProgressToRemaining(a))))},_maybePersistChunkedState:function(a){var b,d,e=c._getFileState(a);if(i&&c.isResumable(a)){b=c._getLocalStorageId(a),d={name:j(a),size:k(a),uuid:l(a),key:e.key,chunking:e.chunking,loaded:e.loaded,lastUpdated:Date.now()};try{localStorage.setItem(b,JSON.stringify(d))}catch(f){q(qq.format("Unable to save resume data for '{}' due to error: '{}'.",a,f.toString()),"warn")}}},_registerProgressHandler:function(a,b,d){var e=c._getXhr(a,b),f=j(a),g={simple:function(b,c){var d=k(a);b===c?p(a,f,d,d):p(a,f,b>=d?d-1:b,d)},chunked:function(e,g){var h=c._getFileState(a).temp.chunkProgress,i=c._getFileState(a).loaded,j=e,l=g,m=k(a),n=j-(l-d),o=i;h[b]=n,qq.each(h,function(a,b){o+=b}),p(a,f,o,m)}};e.upload.onprogress=function(a){if(a.lengthComputable){var b=null==d?"simple":"chunked";g[b](a.loaded,a.total)}}},_registerXhr:function(a,b,d,e){var f=null==b?-1:b,g=c._getFileState(a).temp;return g.xhrs=g.xhrs||{},g.ajaxRequesters=g.ajaxRequesters||{},g.xhrs[f]=d,e&&(g.ajaxRequesters[f]=e),d},_removeExpiredChunkingRecords:function(){var a=g.recordsExpireIn;c._iterateResumeRecords(function(b,c){var d=new Date(c.lastUpdated);d.setDate(d.getDate()+a),d.getTime()<=Date.now()&&(q("Removing expired resume record with key "+b),localStorage.removeItem(b))})},_shouldChunkThisFile:function(a){var b=c._getFileState(a);return b.chunking||c.reevaluateChunking(a),b.chunking.enabled}})},qq.WindowReceiveMessage=function(a){"use strict";var b={log:function(){}},c={};qq.extend(b,a),qq.extend(this,{receiveMessage:function(a,b){var d=function(a){b(a.data)};window.postMessage?c[a]=qq(window).attach("message",d):log("iframe message passing not supported in this browser!","error")},stopReceivingMessages:function(a){if(window.postMessage){var b=c[a];b&&b()}}})},function(){"use strict";qq.uiPublicApi={clearStoredFiles:function(){this._parent.prototype.clearStoredFiles.apply(this,arguments),this._templating.clearFiles()},addExtraDropzone:function(a){this._dnd&&this._dnd.setupExtraDropzone(a)},removeExtraDropzone:function(a){return this._dnd?this._dnd.removeDropzone(a):void 0},getItemByFileId:function(a){return this._templating.getFileContainer(a)},reset:function(){this._parent.prototype.reset.apply(this,arguments),this._templating.reset(),!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton()}).getButtonId()),this._dnd&&(this._dnd.dispose(),this._dnd=this._setupDragAndDrop()),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0,this._setupClickAndEditEventHandlers()},setName:function(a,b){var c=this._options.formatFileName(b);this._parent.prototype.setName.apply(this,arguments),this._templating.updateFilename(a,c)},pauseUpload:function(a){var b=this._parent.prototype.pauseUpload.apply(this,arguments);return b&&this._templating.uploadPaused(a),b},continueUpload:function(a){var b=this._parent.prototype.continueUpload.apply(this,arguments);return b&&this._templating.uploadContinued(a),b},getId:function(a){return this._templating.getFileId(a)},getDropTarget:function(a){var b=this.getFile(a);return b.qqDropTarget}},qq.uiPrivateApi={_getButton:function(a){var b=this._parent.prototype._getButton.apply(this,arguments);return b||a===this._defaultButtonId&&(b=this._templating.getButton()),b},_removeFileItem:function(a){this._templating.removeFile(a)},_setupClickAndEditEventHandlers:function(){this._fileButtonsClickHandler=qq.FileButtonsClickHandler&&this._bindFileButtonsClickEvent(),this._focusinEventSupported=!qq.firefox(),this._isEditFilenameEnabled()&&(this._filenameClickHandler=this._bindFilenameClickEvent(),this._filenameInputFocusInHandler=this._bindFilenameInputFocusInEvent(),this._filenameInputFocusHandler=this._bindFilenameInputFocusEvent())},_setupDragAndDrop:function(){var a=this,b=this._options.dragAndDrop.extraDropzones,c=this._templating,d=c.getDropZone();return d&&b.push(d),new qq.DragAndDrop({dropZoneElements:b,allowMultipleItems:this._options.multiple,classes:{dropActive:this._options.classes.dropActive},callbacks:{processingDroppedFiles:function(){c.showDropProcessing()},processingDroppedFilesComplete:function(b,d){c.hideDropProcessing(),qq.each(b,function(a,b){b.qqDropTarget=d}),b.length&&a.addFiles(b,null,null)},dropError:function(b,c){a._itemError(b,c)},dropLog:function(b,c){a.log(b,c)}}})},_bindFileButtonsClickEvent:function(){var a=this;return new qq.FileButtonsClickHandler({templating:this._templating,log:function(b,c){a.log(b,c)},onDeleteFile:function(b){a.deleteFile(b)},onCancel:function(b){a.cancel(b)},onRetry:function(b){qq(a._templating.getFileContainer(b)).removeClass(a._classes.retryable),a._templating.hideRetry(b),a.retry(b)},onPause:function(b){a.pauseUpload(b)},onContinue:function(b){a.continueUpload(b)},onGetName:function(b){return a.getName(b)}})},_isEditFilenameEnabled:function(){return this._templating.isEditFilenamePossible()&&!this._options.autoUpload&&qq.FilenameClickHandler&&qq.FilenameInputFocusHandler&&qq.FilenameInputFocusHandler},_filenameEditHandler:function(){var a=this,b=this._templating;return{templating:b,log:function(b,c){a.log(b,c)},onGetUploadStatus:function(b){return a.getUploads({id:b}).status},onGetName:function(b){return a.getName(b)},onSetName:function(b,c){a.setName(b,c)},onEditingStatusChange:function(a,c){var d=qq(b.getEditInput(a)),e=qq(b.getFileContainer(a));c?(d.addClass("qq-editing"),b.hideFilename(a),b.hideEditIcon(a)):(d.removeClass("qq-editing"),b.showFilename(a),b.showEditIcon(a)),e.addClass("qq-temp").removeClass("qq-temp")}}},_onUploadStatusChange:function(a,b,c){this._parent.prototype._onUploadStatusChange.apply(this,arguments),this._isEditFilenameEnabled()&&this._templating.getFileContainer(a)&&c!==qq.status.SUBMITTED&&(this._templating.markFilenameEditable(a),this._templating.hideEditIcon(a)),c===qq.status.UPLOAD_RETRYING?(this._templating.setStatusText(a),qq(this._templating.getFileContainer(a)).removeClass(this._classes.retrying)):c===qq.status.UPLOAD_FAILED&&this._templating.hidePause(a)},_bindFilenameInputFocusInEvent:function(){var a=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusInHandler(a)},_bindFilenameInputFocusEvent:function(){var a=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusHandler(a)},_bindFilenameClickEvent:function(){var a=qq.extend({},this._filenameEditHandler());return new qq.FilenameClickHandler(a)},_storeForLater:function(a){this._parent.prototype._storeForLater.apply(this,arguments),this._templating.hideSpinner(a)},_onAllComplete:function(){this._parent.prototype._onAllComplete.apply(this,arguments),this._templating.resetTotalProgress()},_onSubmit:function(a,b){var c=this.getFile(a);c&&c.qqPath&&this._options.dragAndDrop.reportDirectoryPaths&&this._paramsStore.addReadOnly(a,{qqpath:c.qqPath}),this._parent.prototype._onSubmit.apply(this,arguments),this._addToList(a,b)},_onSubmitted:function(a){this._isEditFilenameEnabled()&&(this._templating.markFilenameEditable(a),this._templating.showEditIcon(a),this._focusinEventSupported||this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(a)))},_onProgress:function(a,b,c,d){this._parent.prototype._onProgress.apply(this,arguments),this._templating.updateProgress(a,c,d),100===Math.round(100*(c/d))?(this._templating.hideCancel(a),this._templating.hidePause(a),this._templating.hideProgress(a),this._templating.setStatusText(a,this._options.text.waitingForResponse),this._displayFileSize(a)):this._displayFileSize(a,c,d)},_onTotalProgress:function(a,b){this._parent.prototype._onTotalProgress.apply(this,arguments),this._templating.updateTotalProgress(a,b)},_onComplete:function(a,b,c){function d(b){g&&(f.setStatusText(a),qq(g).removeClass(h._classes.retrying),f.hideProgress(a),h.getUploads({id:a}).status!==qq.status.UPLOAD_FAILED&&f.hideCancel(a),f.hideSpinner(a),b.success?h._markFileAsSuccessful(a):(qq(g).addClass(h._classes.fail),f.showCancel(a),f.isRetryPossible()&&!h._preventRetries[a]&&(qq(g).addClass(h._classes.retryable),f.showRetry(a)),h._controlFailureTextDisplay(a,b)))}var e=this._parent.prototype._onComplete.apply(this,arguments),f=this._templating,g=f.getFileContainer(a),h=this;return e instanceof qq.Promise?e.done(function(a){d(a)}):d(c),e},_markFileAsSuccessful:function(a){var b=this._templating;this._isDeletePossible()&&b.showDeleteButton(a),qq(b.getFileContainer(a)).addClass(this._classes.success),this._maybeUpdateThumbnail(a)},_onUploadPrep:function(a){this._parent.prototype._onUploadPrep.apply(this,arguments),this._templating.showSpinner(a)},_onUpload:function(a){var b=this._parent.prototype._onUpload.apply(this,arguments);return this._templating.showSpinner(a),b},_onUploadChunk:function(a,b){this._parent.prototype._onUploadChunk.apply(this,arguments),b.partIndex>0&&this._handler.isResumable(a)&&this._templating.allowPause(a)},_onCancel:function(a){this._parent.prototype._onCancel.apply(this,arguments),this._removeFileItem(a),0===this._getNotFinished()&&this._templating.resetTotalProgress()},_onBeforeAutoRetry:function(a){var b,c,d;this._parent.prototype._onBeforeAutoRetry.apply(this,arguments),this._showCancelLink(a),this._options.retry.showAutoRetryNote&&(b=this._autoRetries[a],c=this._options.retry.maxAutoAttempts,d=this._options.retry.autoRetryNote.replace(/\{retryNum\}/g,b),d=d.replace(/\{maxAuto\}/g,c),this._templating.setStatusText(a,d),qq(this._templating.getFileContainer(a)).addClass(this._classes.retrying))},_onBeforeManualRetry:function(a){return this._parent.prototype._onBeforeManualRetry.apply(this,arguments)?(this._templating.resetProgress(a),qq(this._templating.getFileContainer(a)).removeClass(this._classes.fail),this._templating.setStatusText(a),this._templating.showSpinner(a),this._showCancelLink(a),!0):(qq(this._templating.getFileContainer(a)).addClass(this._classes.retryable),this._templating.showRetry(a),!1)},_onSubmitDelete:function(a){var b=qq.bind(this._onSubmitDeleteSuccess,this);this._parent.prototype._onSubmitDelete.call(this,a,b)},_onSubmitDeleteSuccess:function(){this._options.deleteFile.forceConfirm?this._showDeleteConfirm.apply(this,arguments):this._sendDeleteRequest.apply(this,arguments)},_onDeleteComplete:function(a,b,c){this._parent.prototype._onDeleteComplete.apply(this,arguments),this._templating.hideSpinner(a),c?(this._templating.setStatusText(a,this._options.deleteFile.deletingFailedText),this._templating.showDeleteButton(a)):this._removeFileItem(a)},_sendDeleteRequest:function(a){this._templating.hideDeleteButton(a),this._templating.showSpinner(a),this._templating.setStatusText(a,this._options.deleteFile.deletingStatusText),this._deleteHandler.sendDelete.apply(this,arguments)},_showDeleteConfirm:function(a){var b,c=this.getName(a),d=this._options.deleteFile.confirmMessage.replace(/\{filename\}/g,c),e=(this.getUuid(a),arguments),f=this;b=this._options.showConfirm(d),qq.isGenericPromise(b)?b.then(function(){f._sendDeleteRequest.apply(f,e)}):b!==!1&&f._sendDeleteRequest.apply(f,e)},_addToList:function(a,b,c){var d,e,f=0,g=this._handler.isProxied(a)&&this._options.scaling.hideScaled;g||(this._options.display.prependFiles&&(this._totalFilesInBatch>1&&this._filesInBatchAddedToUi>0&&(f=this._filesInBatchAddedToUi-1),d={index:f}),c||(this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading&&this._templating.disableCancel(),this._options.multiple||(e=this.getUploads({id:a}),this._handledProxyGroup=this._handledProxyGroup||e.proxyGroupId,e.proxyGroupId===this._handledProxyGroup&&e.proxyGroupId||(this._handler.cancelAll(),this._clearList(),this._handledProxyGroup=null))),this._templating.addFile(a,this._options.formatFileName(b),d),c?this._thumbnailUrls[a]&&this._templating.updateThumbnail(a,this._thumbnailUrls[a],!0):this._templating.generatePreview(a,this.getFile(a)),this._filesInBatchAddedToUi+=1,(c||this._options.display.fileSizeOnSubmit&&qq.supportedFeatures.ajaxUploading)&&this._displayFileSize(a))},_clearList:function(){this._templating.clearFiles(),this.clearStoredFiles()},_displayFileSize:function(a,b,c){var d=this.getSize(a),e=this._formatSize(d);d>=0&&(void 0!==b&&void 0!==c&&(e=this._formatProgress(b,c)),this._templating.updateSize(a,e))},_formatProgress:function(a,b){function c(a,b){d=d.replace(a,b)}var d=this._options.text.formatProgress;return c("{percent}",Math.round(100*(a/b))),c("{total_size}",this._formatSize(b)),d},_controlFailureTextDisplay:function(a,b){var c,d,e;c=this._options.failedUploadTextDisplay.mode,d=this._options.failedUploadTextDisplay.responseProperty,"custom"===c?(e=b[d],e||(e=this._options.text.failUpload),this._templating.setStatusText(a,e),this._options.failedUploadTextDisplay.enableTooltip&&this._showTooltip(a,e)):"default"===c?this._templating.setStatusText(a,this._options.text.failUpload):"none"!==c&&this.log("failedUploadTextDisplay.mode value of '"+c+"' is not valid","warn")},_showTooltip:function(a,b){this._templating.getFileContainer(a).title=b},_showCancelLink:function(a){(!this._options.disableCancelForFormUploads||qq.supportedFeatures.ajaxUploading)&&this._templating.showCancel(a)},_itemError:function(){var a=this._parent.prototype._itemError.apply(this,arguments);this._options.showMessage(a)},_batchError:function(a){this._parent.prototype._batchError.apply(this,arguments),this._options.showMessage(a)},_setupPastePrompt:function(){var a=this;this._options.callbacks.onPasteReceived=function(){var b=a._options.paste.namePromptMessage,c=a._options.paste.defaultName;return a._options.showPrompt(b,c)}},_fileOrBlobRejected:function(){this._totalFilesInBatch-=1,this._parent.prototype._fileOrBlobRejected.apply(this,arguments)},_prepareItemsForUpload:function(a){this._totalFilesInBatch=a.length,this._filesInBatchAddedToUi=0,this._parent.prototype._prepareItemsForUpload.apply(this,arguments)},_maybeUpdateThumbnail:function(a){var b=this._thumbnailUrls[a],c=this.getUploads({id:a}).status;c===qq.status.DELETED||!b&&!this._options.thumbnails.placeholders.waitUntilResponse&&qq.supportedFeatures.imagePreviews||this._templating.updateThumbnail(a,b)},_addCannedFile:function(){var a=this._parent.prototype._addCannedFile.apply(this,arguments);return this._addToList(a,this.getName(a),!0),this._templating.hideSpinner(a),this._templating.hideCancel(a),this._markFileAsSuccessful(a),a},_setSize:function(a,b){this._parent.prototype._setSize.apply(this,arguments),this._templating.updateSize(a,this._formatSize(b))}}}(),qq.FineUploader=function(a,b){"use strict";var c=this;this._parent=b?qq[b].FineUploaderBasic:qq.FineUploaderBasic,this._parent.apply(this,arguments),qq.extend(this._options,{element:null,button:null,listElement:null,dragAndDrop:{extraDropzones:[],reportDirectoryPaths:!1},text:{formatProgress:"{percent}% of {total_size}",failUpload:"Upload failed",waitingForResponse:"Processing...",paused:"Paused"},template:"qq-template",classes:{retrying:"qq-upload-retrying",retryable:"qq-upload-retryable",success:"qq-upload-success",fail:"qq-upload-fail",editable:"qq-editable",hide:"qq-hide",dropActive:"qq-upload-drop-area-active"},failedUploadTextDisplay:{mode:"default",responseProperty:"error",enableTooltip:!0},messages:{tooManyFilesError:"You may only drop one file",unsupportedBrowser:"Unrecoverable error - this browser does not permit file uploading of any kind."},retry:{showAutoRetryNote:!0,autoRetryNote:"Retrying {retryNum}/{maxAuto}..."},deleteFile:{forceConfirm:!1,confirmMessage:"Are you sure you want to delete {filename}?",deletingStatusText:"Deleting...",deletingFailedText:"Delete failed"},display:{fileSizeOnSubmit:!1,prependFiles:!1},paste:{promptForName:!1,namePromptMessage:"Please name this image"},thumbnails:{maxCount:0,placeholders:{waitUntilResponse:!1,notAvailablePath:null,waitingPath:null},timeBetweenThumbs:750},scaling:{hideScaled:!1},showMessage:function(a){return c._templating.hasDialog("alert")?c._templating.showDialog("alert",a):(setTimeout(function(){window.alert(a)},0),void 0)},showConfirm:function(a){return c._templating.hasDialog("confirm")?c._templating.showDialog("confirm",a):window.confirm(a)},showPrompt:function(a,b){return c._templating.hasDialog("prompt")?c._templating.showDialog("prompt",a,b):window.prompt(a,b)}},!0),qq.extend(this._options,a,!0),this._templating=new qq.Templating({log:qq.bind(this.log,this),templateIdOrEl:this._options.template,containerEl:this._options.element,fileContainerEl:this._options.listElement,button:this._options.button,imageGenerator:this._imageGenerator,classes:{hide:this._options.classes.hide,editable:this._options.classes.editable},limits:{maxThumbs:this._options.thumbnails.maxCount,timeBetweenThumbs:this._options.thumbnails.timeBetweenThumbs},placeholders:{waitUntilUpdate:this._options.thumbnails.placeholders.waitUntilResponse,thumbnailNotAvailable:this._options.thumbnails.placeholders.notAvailablePath,waitingForThumbnail:this._options.thumbnails.placeholders.waitingPath},text:this._options.text}),this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari()?this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari):!qq.supportedFeatures.uploading||this._options.cors.expected&&!qq.supportedFeatures.uploadCors?this._templating.renderFailure(this._options.messages.unsupportedBrowser):(this._wrapCallbacks(),this._templating.render(),this._classes=this._options.classes,!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton()}).getButtonId()),this._setupClickAndEditEventHandlers(),qq.DragAndDrop&&qq.supportedFeatures.fileDrop&&(this._dnd=this._setupDragAndDrop()),this._options.paste.targetElement&&this._options.paste.promptForName&&(qq.PasteSupport?this._setupPastePrompt():this.log("Paste support module not found.","error")),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0)},qq.extend(qq.FineUploader.prototype,qq.basePublicApi),qq.extend(qq.FineUploader.prototype,qq.basePrivateApi),qq.extend(qq.FineUploader.prototype,qq.uiPublicApi),qq.extend(qq.FineUploader.prototype,qq.uiPrivateApi),qq.Templating=function(a){"use strict";var b,c,d,e,f,g,h,i,j="qq-file-id",k="qq-file-id-",l="qq-max-size",m="qq-server-scale",n="qq-hide-dropzone",o="qq-drop-area-text",p="qq-in-progress",q=!1,r=0,s=!1,t=[],u=-1,v={log:null,limits:{maxThumbs:0,timeBetweenThumbs:750},templateIdOrEl:"qq-template",containerEl:null,fileContainerEl:null,button:null,imageGenerator:null,classes:{hide:"qq-hide",editable:"qq-editable"},placeholders:{waitUntilUpdate:!1,thumbnailNotAvailable:null,waitingForThumbnail:null},text:{paused:"Paused"}},w={button:"qq-upload-button-selector",alertDialog:"qq-alert-dialog-selector",dialogCancelButton:"qq-cancel-button-selector",confirmDialog:"qq-confirm-dialog-selector",dialogMessage:"qq-dialog-message-selector",dialogOkButton:"qq-ok-button-selector",promptDialog:"qq-prompt-dialog-selector",uploader:"qq-uploader-selector",drop:"qq-upload-drop-area-selector",list:"qq-upload-list-selector",progressBarContainer:"qq-progress-bar-container-selector",progressBar:"qq-progress-bar-selector",totalProgressBarContainer:"qq-total-progress-bar-container-selector",totalProgressBar:"qq-total-progress-bar-selector",file:"qq-upload-file-selector",spinner:"qq-upload-spinner-selector",size:"qq-upload-size-selector",cancel:"qq-upload-cancel-selector",pause:"qq-upload-pause-selector",continueButton:"qq-upload-continue-selector",deleteButton:"qq-upload-delete-selector",retry:"qq-upload-retry-selector",statusText:"qq-upload-status-text-selector",editFilenameInput:"qq-edit-filename-selector",editNameIcon:"qq-edit-filename-icon-selector",dropText:"qq-upload-drop-area-text-selector",dropProcessing:"qq-drop-processing-selector",dropProcessingSpinner:"qq-drop-processing-spinner-selector",thumbnail:"qq-thumbnail-selector"},x={},y=new qq.Promise,z=new qq.Promise,A=function(){var a=v.placeholders.thumbnailNotAvailable,c=v.placeholders.waitingForThumbnail,d={maxSize:u,scale:i};h&&(a?v.imageGenerator.generate(a,new Image,d).then(function(a){y.success(a)},function(){y.failure(),b("Problem loading 'not available' placeholder image at "+a,"error")}):y.failure(),c?v.imageGenerator.generate(c,new Image,d).then(function(a){z.success(a)},function(){z.failure(),b("Problem loading 'waiting for thumbnail' placeholder image at "+c,"error")}):z.failure())},B=function(a){var b=new qq.Promise;return z.then(function(c){U(c,a),a.src?b.success():(a.src=c.src,a.onload=function(){a.onload=null,_(a),b.success()})},function(){T(a),b.success()}),b},C=function(a,c,d){var e=S(a);return b("Generating new thumbnail for "+a),c.qqThumbnailId=a,v.imageGenerator.generate(c,e,d).then(function(){r++,_(e),x[a].success()},function(){x[a].failure(),v.placeholders.waitUntilUpdate||V(a,e)})},D=function(){if(t.length){s=!0;var a=t.shift();a.update?Z(a):Y(a)}else s=!1},E=function(a){return R(K(a),w.cancel)},F=function(a){return R(K(a),w.continueButton)},G=function(a){return R(f,w[a+"Dialog"])},H=function(a){return R(K(a),w.deleteButton)},I=function(){return R(f,w.dropProcessing)},J=function(a){return R(K(a),w.editNameIcon)},K=function(a){return qq(g).getByClass(k+a)[0]},L=function(a){return R(K(a),w.file)},M=function(a){return R(K(a),w.pause)},N=function(a){return null==a?R(f,w.totalProgressBarContainer)||R(f,w.totalProgressBar):R(K(a),w.progressBarContainer)||R(K(a),w.progressBar)},O=function(a){return R(K(a),w.retry)},P=function(a){return R(K(a),w.size)},Q=function(a){return R(K(a),w.spinner)},R=function(a,b){return a&&qq(a).getByClass(b)[0]},S=function(a){return h&&R(K(a),w.thumbnail)},T=function(a){a&&qq(a).addClass(v.classes.hide)},U=function(a,b){var c=a.style.maxWidth,d=a.style.maxHeight;d&&c&&!b.style.maxWidth&&!b.style.maxHeight&&qq(b).css({maxWidth:c,maxHeight:d})},V=function(a,b){var c=x[a]||(new qq.Promise).failure(),d=new qq.Promise;return y.then(function(a){c.then(function(){d.success()},function(){U(a,b),b.onload=function(){b.onload=null,d.success()},b.src=a.src,_(b)})}),d},W=function(){var a,e,f,g,j,k,p,q,r,s,t;if(b("Parsing template"),null==v.templateIdOrEl)throw new Error("You MUST specify either a template element or ID!");if(qq.isString(v.templateIdOrEl)){if(a=document.getElementById(v.templateIdOrEl),null===a)throw new Error(qq.format("Cannot find template script at ID '{}'!",v.templateIdOrEl));e=a.innerHTML}else{if(void 0===v.templateIdOrEl.innerHTML)throw new Error("You have specified an invalid value for the template option! It must be an ID or an Element.");e=v.templateIdOrEl.innerHTML}if(e=qq.trimStr(e),g=document.createElement("div"),g.appendChild(qq.toElement(e)),t=qq(g).getByClass(w.uploader)[0],v.button&&(k=qq(g).getByClass(w.button)[0],k&&qq(k).remove()),qq.DragAndDrop&&qq.supportedFeatures.fileDrop||(r=qq(g).getByClass(w.dropProcessing)[0],r&&qq(r).remove()),p=qq(g).getByClass(w.drop)[0],p&&!qq.DragAndDrop&&(b("DnD module unavailable.","info"),qq(p).remove()),qq.supportedFeatures.fileDrop?qq(t).hasAttribute(o)&&p&&(s=qq(p).getByClass(w.dropText)[0],s&&qq(s).remove()):(t.removeAttribute(o),p&&qq(p).hasAttribute(n)&&qq(p).css({display:"none"})),q=qq(g).getByClass(w.thumbnail)[0],h?q&&(u=parseInt(q.getAttribute(l)),u=u>0?u:null,i=qq(q).hasAttribute(m)):q&&qq(q).remove(),h=h&&q,c=qq(g).getByClass(w.editFilenameInput).length>0,d=qq(g).getByClass(w.retry).length>0,f=qq(g).getByClass(w.list)[0],null==f)throw new Error("Could not find the file list container in the template!");return j=f.innerHTML,f.innerHTML="",g.getElementsByTagName("DIALOG").length&&document.createElement("dialog"),b("Template parsing complete"),{template:qq.trimStr(g.innerHTML),fileTemplate:qq.trimStr(j)}},X=function(a,b){var c=g,d=c.firstChild;b>0&&(d=qq(c).children()[b].nextSibling),c.insertBefore(a,d)},Y=function(a){var b=a.id,c=a.optFileOrBlob,d=c&&c.qqThumbnailId,e=S(b),f={maxSize:u,scale:!0,orient:!0};qq.supportedFeatures.imagePreviews?e?v.limits.maxThumbs&&v.limits.maxThumbs<=r?(V(b,e),D()):B(e).done(function(){x[b]=new qq.Promise,x[b].done(function(){setTimeout(D,v.limits.timeBetweenThumbs)}),null!=d?ab(b,d):C(b,c,f)}):D():e&&(B(e),D())},Z=function(a){var b=a.id,c=a.thumbnailUrl,d=a.showWaitingImg,e=S(b),f={maxSize:u,scale:i};if(e)if(c){if(!(v.limits.maxThumbs&&v.limits.maxThumbs<=r))return d&&B(e),v.imageGenerator.generate(c,e,f).then(function(){_(e),r++,setTimeout(D,v.limits.timeBetweenThumbs)},function(){V(b,e),setTimeout(D,v.limits.timeBetweenThumbs)});V(b,e),D()}else V(b,e),D()},$=function(a,b){var c=N(a),d=null==a?w.totalProgressBar:w.progressBar;c&&!qq(c).hasClass(d)&&(c=qq(c).getByClass(d)[0]),c&&(qq(c).css({width:b+"%"}),c.setAttribute("aria-valuenow",b))},_=function(a){a&&qq(a).removeClass(v.classes.hide)},ab=function(a,c){var d=S(a),e=S(c);b(qq.format("ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.",a,c,c)),x[c].then(function(){r++,x[a].success(),b(qq.format("Now using previously generated thumbnail created for ID {} on ID {}.",c,a)),d.src=e.src,_(d)},function(){x[a].failure(),v.placeholders.waitUntilUpdate||V(a,d)})};qq.extend(v,a),b=v.log,qq.supportedFeatures.imagePreviews||(v.limits.timeBetweenThumbs=0,v.limits.maxThumbs=0),f=v.containerEl,h=void 0!==v.imageGenerator,e=W(),A(),qq.extend(this,{render:function(){b("Rendering template in DOM."),r=0,f.innerHTML=e.template,T(I()),this.hideTotalProgress(),g=v.fileContainerEl||R(f,w.list),b("Template rendering complete")},renderFailure:function(a){var b=qq.toElement(a);f.innerHTML="",f.appendChild(b)},reset:function(){this.render()},clearFiles:function(){g.innerHTML=""},disableCancel:function(){q=!0},addFile:function(a,b,c){var d,h=qq.toElement(e.fileTemplate),i=R(h,w.file),l=R(f,w.uploader);qq(h).addClass(k+a),l.removeAttribute(o),i&&(qq(i).setText(b),i.setAttribute("title",b)),h.setAttribute(j,a),c?X(h,c.index):g.appendChild(h),T(N(a)),T(P(a)),T(H(a)),T(O(a)),T(M(a)),T(F(a)),q&&this.hideCancel(a),d=S(a),d&&!d.src&&z.then(function(a){d.src=a.src,a.style.maxHeight&&a.style.maxWidth&&qq(d).css({maxHeight:a.style.maxHeight,maxWidth:a.style.maxWidth}),_(d)})},removeFile:function(a){qq(K(a)).remove()},getFileId:function(a){var b=a;if(b){for(;null==b.getAttribute(j);)b=b.parentNode;return parseInt(b.getAttribute(j))}},getFileList:function(){return g},markFilenameEditable:function(a){var b=L(a);b&&qq(b).addClass(v.classes.editable)},updateFilename:function(a,b){var c=L(a);c&&(qq(c).setText(b),c.setAttribute("title",b))},hideFilename:function(a){T(L(a))},showFilename:function(a){_(L(a))},isFileName:function(a){return qq(a).hasClass(w.file)},getButton:function(){return v.button||R(f,w.button)},hideDropProcessing:function(){T(I())},showDropProcessing:function(){_(I())},getDropZone:function(){return R(f,w.drop)},isEditFilenamePossible:function(){return c},hideRetry:function(a){T(O(a))},isRetryPossible:function(){return d},showRetry:function(a){_(O(a))},getFileContainer:function(a){return K(a)},showEditIcon:function(a){var b=J(a);b&&qq(b).addClass(v.classes.editable)},hideEditIcon:function(a){var b=J(a);b&&qq(b).removeClass(v.classes.editable)},isEditIcon:function(a){return qq(a).hasClass(w.editNameIcon,!0)},getEditInput:function(a){return R(K(a),w.editFilenameInput)},isEditInput:function(a){return qq(a).hasClass(w.editFilenameInput,!0)},updateProgress:function(a,b,c){var d,e=N(a);e&&c>0&&(d=Math.round(100*(b/c)),100===d?T(e):_(e),$(a,d))
-},updateTotalProgress:function(a,b){this.updateProgress(null,a,b)},hideProgress:function(a){var b=N(a);b&&T(b)},hideTotalProgress:function(){this.hideProgress()},resetProgress:function(a){$(a,0),this.hideTotalProgress(a)},resetTotalProgress:function(){this.resetProgress()},showCancel:function(a){if(!q){var b=E(a);b&&qq(b).removeClass(v.classes.hide)}},hideCancel:function(a){T(E(a))},isCancel:function(a){return qq(a).hasClass(w.cancel,!0)},allowPause:function(a){_(M(a)),T(F(a))},uploadPaused:function(a){this.setStatusText(a,v.text.paused),this.allowContinueButton(a),T(Q(a))},hidePause:function(a){T(M(a))},isPause:function(a){return qq(a).hasClass(w.pause,!0)},isContinueButton:function(a){return qq(a).hasClass(w.continueButton,!0)},allowContinueButton:function(a){_(F(a)),T(M(a))},uploadContinued:function(a){this.setStatusText(a,""),this.allowPause(a),_(Q(a))},showDeleteButton:function(a){_(H(a))},hideDeleteButton:function(a){T(H(a))},isDeleteButton:function(a){return qq(a).hasClass(w.deleteButton,!0)},isRetry:function(a){return qq(a).hasClass(w.retry,!0)},updateSize:function(a,b){var c=P(a);c&&(_(c),qq(c).setText(b))},setStatusText:function(a,b){var c=R(K(a),w.statusText);c&&(null==b?qq(c).clearText():qq(c).setText(b))},hideSpinner:function(a){qq(K(a)).removeClass(p),T(Q(a))},showSpinner:function(a){qq(K(a)).addClass(p),_(Q(a))},generatePreview:function(a,b){t.push({id:a,optFileOrBlob:b}),!s&&D()},updateThumbnail:function(a,b,c){t.push({update:!0,id:a,thumbnailUrl:b,showWaitingImg:c}),!s&&D()},hasDialog:function(a){return qq.supportedFeatures.dialogElement&&!!G(a)},showDialog:function(a,b,c){var d=G(a),e=R(d,w.dialogMessage),f=d.getElementsByTagName("INPUT")[0],g=R(d,w.dialogCancelButton),h=R(d,w.dialogOkButton),i=new qq.Promise,j=function(){g.removeEventListener("click",k),h&&h.removeEventListener("click",l),i.failure()},k=function(){g.removeEventListener("click",k),d.close()},l=function(){d.removeEventListener("close",j),h.removeEventListener("click",l),d.close(),i.success(f&&f.value)};return d.addEventListener("close",j),g.addEventListener("click",k),h&&h.addEventListener("click",l),f&&(f.value=c),e.textContent=b,d.showModal(),i}})},qq.s3=qq.s3||{},qq.s3.util=qq.s3.util||function(){"use strict";return{AWS_PARAM_PREFIX:"x-amz-meta-",SESSION_TOKEN_PARAM_NAME:"x-amz-security-token",REDUCED_REDUNDANCY_PARAM_NAME:"x-amz-storage-class",REDUCED_REDUNDANCY_PARAM_VALUE:"REDUCED_REDUNDANCY",SERVER_SIDE_ENCRYPTION_PARAM_NAME:"x-amz-server-side-encryption",SERVER_SIDE_ENCRYPTION_PARAM_VALUE:"AES256",getBucket:function(a){var b,c=[/^(?:https?:\/\/)?([a-z0-9.\-_]+)\.s3(?:-[a-z0-9\-]+)?\.amazonaws\.com/i,/^(?:https?:\/\/)?s3(?:-[a-z0-9\-]+)?\.amazonaws\.com\/([a-z0-9.\-_]+)/i,/^(?:https?:\/\/)?([a-z0-9.\-_]+)/i];return qq.each(c,function(c,d){var e=d.exec(a);return e?(b=e[1],!1):void 0}),b},getPolicy:function(a){var b={},c=[],d=a.bucket,e=a.key,f=a.acl,g=a.type,h=new Date,i=a.expectedStatus,j=a.sessionToken,k=a.params,l=qq.s3.util.getSuccessRedirectAbsoluteUrl(a.successRedirectUrl),m=a.minFileSize,n=a.maxFileSize,o=a.reducedRedundancy,p=a.serverSideEncryption;return b.expiration=qq.s3.util.getPolicyExpirationDate(h),c.push({acl:f}),c.push({bucket:d}),g&&c.push({"Content-Type":g}),i&&c.push({success_action_status:i.toString()}),l&&c.push({success_action_redirect:l}),o&&(c.push({}),c[c.length-1][qq.s3.util.REDUCED_REDUNDANCY_PARAM_NAME]=qq.s3.util.REDUCED_REDUNDANCY_PARAM_VALUE),j&&(c.push({}),c[c.length-1][qq.s3.util.SESSION_TOKEN_PARAM_NAME]=j),p&&(c.push({}),c[c.length-1][qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_NAME]=qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_VALUE),c.push({key:e}),qq.each(k,function(a,b){var d=qq.s3.util.AWS_PARAM_PREFIX+a,e={};e[d]=encodeURIComponent(b),c.push(e)}),b.conditions=c,qq.s3.util.enforceSizeLimits(b,m,n),b},refreshPolicyCredentials:function(a,b){var c=!1;qq.each(a.conditions,function(a,d){qq.each(d,function(a){a===qq.s3.util.SESSION_TOKEN_PARAM_NAME&&(d[a]=b,c=!0)})}),c||(a.conditions.push({}),a.conditions[a.conditions.length-1][qq.s3.util.SESSION_TOKEN_PARAM_NAME]=b)},generateAwsParams:function(a,b){var c={},d=a.params,e=new qq.Promise,f=qq.s3.util.getPolicy(a),g=a.sessionToken,h=a.type,i=a.key,j=a.accessKey,k=a.acl,l=a.expectedStatus,m=qq.s3.util.getSuccessRedirectAbsoluteUrl(a.successRedirectUrl),n=a.reducedRedundancy,o=a.serverSideEncryption,p=a.log;return c.key=i,c.AWSAccessKeyId=j,h&&(c["Content-Type"]=h),l&&(c.success_action_status=l),m&&(c.success_action_redirect=m),n&&(c[qq.s3.util.REDUCED_REDUNDANCY_PARAM_NAME]=qq.s3.util.REDUCED_REDUNDANCY_PARAM_VALUE),o&&(c[qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_NAME]=qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_VALUE),g&&(c[qq.s3.util.SESSION_TOKEN_PARAM_NAME]=g),c.acl=k,qq.each(d,function(a,b){var d=qq.s3.util.AWS_PARAM_PREFIX+a;c[d]=encodeURIComponent(b)}),b(f).then(function(a,b,d){c.policy=a.policy,c.signature=a.signature,b&&(c.AWSAccessKeyId=b),d&&(c[qq.s3.util.SESSION_TOKEN_PARAM_NAME]=d),e.success(c)},function(a){a=a||"Can't continue further with request to S3 as we did not receive a valid signature and policy from the server.",p("Policy signing failed. "+a,"error"),e.failure(a)}),e},enforceSizeLimits:function(a,b,c){var d=0>b?0:b,e=0>=c?9007199254740992:c;(b>0||c>0)&&a.conditions.push(["content-length-range",d.toString(),e.toString()])},getPolicyExpirationDate:function(a){if(a.setMinutes(a.getMinutes()+5),Date.prototype.toISOString)return a.toISOString();var b=function(a){var b=String(a);return 1===b.length&&(b="0"+b),b};return a.getUTCFullYear()+"-"+b(a.getUTCMonth()+1)+"-"+b(a.getUTCDate())+"T"+b(a.getUTCHours())+":"+b(a.getUTCMinutes())+":"+b(a.getUTCSeconds())+"."+String((a.getUTCMilliseconds()/1e3).toFixed(3)).slice(2,5)+"Z"},parseIframeResponse:function(a){var b=a.contentDocument||a.contentWindow.document,c=b.location.search,d=/bucket=(.+)&key=(.+)&etag=(.+)/.exec(c);return d?{bucket:d[1],key:d[2],etag:d[3].replace(/%22/g,"")}:void 0},getSuccessRedirectAbsoluteUrl:function(a){if(a){var b,c=document.createElement("div");return qq.ie7()?(c.innerHTML="",b=c.firstChild,b.href):(b=document.createElement("a"),b.href=a,b.href=b.href,b.href)}},encodeQueryStringParam:function(a){var b=encodeURIComponent(a);return b=b.replace(/[!'()]/g,escape),b=b.replace(/\*/g,"%2A"),b.replace(/%20/g,"+")}}}(),function(){"use strict";qq.nonTraditionalBasePublicApi={setUploadSuccessParams:function(a,b){this._uploadSuccessParamsStore.set(a,b)},setUploadSuccessEndpoint:function(a,b){this._uploadSuccessEndpointStore.set(a,b)}},qq.nonTraditionalBasePrivateApi={_onComplete:function(a,b,c,d){var e,f,g=c.success?!0:!1,h=this,i=arguments,j=this._uploadSuccessEndpointStore.get(a),k=this._options.uploadSuccess.customHeaders,l=this._options.uploadSuccess.method,m=this._options.cors,n=new qq.Promise,o=this._uploadSuccessParamsStore.get(a),p=this._paramsStore.get(a),q=function(b){delete h._failedSuccessRequestCallbacks[a],qq.extend(c,b),qq.FineUploaderBasic.prototype._onComplete.apply(h,i),n.success(b)},r=function(f){var g=e;qq.extend(c,f),c&&c.reset&&(g=null),g?h._failedSuccessRequestCallbacks[a]=g:delete h._failedSuccessRequestCallbacks[a],h._onAutoRetry(a,b,c,d,g)||(qq.FineUploaderBasic.prototype._onComplete.apply(h,i),n.failure(f))};return g&&j?(f=new qq.UploadSuccessAjaxRequester({endpoint:j,method:l,customHeaders:k,cors:m,log:qq.bind(this.log,this)}),qq.extend(o,h._getEndpointSpecificParams(a,c,d),!0),p&&qq.extend(o,p,!0),e=qq.bind(function(){f.sendSuccessRequest(a,o).then(q,r)},h),e(),n):qq.FineUploaderBasic.prototype._onComplete.apply(this,arguments)},_manualRetry:function(a){var b=this._failedSuccessRequestCallbacks[a];return qq.FineUploaderBasic.prototype._manualRetry.call(this,a,b)}}}(),function(){"use strict";qq.s3.FineUploaderBasic=function(a){var b={request:{accessKey:null},objectProperties:{acl:"private",bucket:qq.bind(function(a){return qq.s3.util.getBucket(this.getEndpoint(a))},this),key:"uuid",reducedRedundancy:!1,serverSideEncryption:!1},credentials:{accessKey:null,secretKey:null,expiration:null,sessionToken:null},signature:{endpoint:null,customHeaders:{}},uploadSuccess:{endpoint:null,method:"POST",params:{},customHeaders:{}},iframeSupport:{localBlankPagePath:null},chunking:{partSize:5242880},cors:{allowXdr:!0},callbacks:{onCredentialsExpired:function(){}}};qq.extend(b,a,!0),this.setCredentials(b.credentials,!0)||(this._currentCredentials.accessKey=b.request.accessKey),this._aclStore=this._createStore(b.objectProperties.acl),qq.FineUploaderBasic.call(this,b),this._uploadSuccessParamsStore=this._createStore(this._options.uploadSuccess.params),this._uploadSuccessEndpointStore=this._createStore(this._options.uploadSuccess.endpoint),this._failedSuccessRequestCallbacks={},this._cannedKeys={},this._cannedBuckets={},this._buckets={}},qq.extend(qq.s3.FineUploaderBasic.prototype,qq.basePublicApi),qq.extend(qq.s3.FineUploaderBasic.prototype,qq.basePrivateApi),qq.extend(qq.s3.FineUploaderBasic.prototype,qq.nonTraditionalBasePublicApi),qq.extend(qq.s3.FineUploaderBasic.prototype,qq.nonTraditionalBasePrivateApi),qq.extend(qq.s3.FineUploaderBasic.prototype,{getBucket:function(a){return null==this._cannedBuckets[a]?this._buckets[a]:this._cannedBuckets[a]},getKey:function(a){return null==this._cannedKeys[a]?this._handler.getThirdPartyFileId(a):this._cannedKeys[a]},reset:function(){qq.FineUploaderBasic.prototype.reset.call(this),this._failedSuccessRequestCallbacks=[],this._buckets={}},setCredentials:function(a,b){if(a&&a.secretKey){if(!a.accessKey)throw new qq.Error("Invalid credentials: no accessKey");if(!a.expiration)throw new qq.Error("Invalid credentials: no expiration");return this._currentCredentials=qq.extend({},a),qq.isString(a.expiration)&&(this._currentCredentials.expiration=new Date(a.expiration)),!0}if(!b)throw new qq.Error("Invalid credentials parameter!");this._currentCredentials={}},setAcl:function(a,b){this._aclStore.set(a,b)},_createUploadHandler:function(){var a=this,b={aclStore:this._aclStore,getBucket:qq.bind(this._determineBucket,this),getKeyName:qq.bind(this._determineKeyName,this),iframeSupport:this._options.iframeSupport,objectProperties:this._options.objectProperties,signature:this._options.signature,validation:{minSizeLimit:this._options.validation.minSizeLimit,maxSizeLimit:this._options.validation.sizeLimit}};return qq.override(this._endpointStore,function(a){return{get:function(b){var c=a.get(b);return c.indexOf("http")<0?"http://"+c:c}}}),qq.override(this._paramsStore,function(a){return{get:function(b){var c=a.get(b),d={};return qq.each(c,function(a,b){d[a.toLowerCase()]=qq.isFunction(b)?b():b}),d}}}),b.signature.credentialsProvider={get:function(){return a._currentCredentials},onExpired:function(){var b=new qq.Promise,c=a._options.callbacks.onCredentialsExpired();return qq.isGenericPromise(c)?c.then(function(c){try{a.setCredentials(c),b.success()}catch(d){a.log("Invalid credentials returned from onCredentialsExpired callback! ("+d.message+")","error"),b.failure("onCredentialsExpired did not return valid credentials.")}},function(c){a.log("onCredentialsExpired callback indicated failure! ("+c+")","error"),b.failure("onCredentialsExpired callback failed.")}):(a.log("onCredentialsExpired callback did not return a promise!","error"),b.failure("Unexpected return value for onCredentialsExpired.")),b}},qq.FineUploaderBasic.prototype._createUploadHandler.call(this,b,"s3")},_determineBucket:function(a){var b=this._options.objectProperties.bucket,c=new qq.Promise,d=this;return qq.isFunction(b)?(b=b(a),qq.isGenericPromise(b)?c=b:c.success(b)):qq.isString(b)&&c.success(b),c.then(function(b){d._buckets[a]=b},function(b){qq.log("Problem determining bucket for ID "+a+" ("+b+")","error")}),c},_determineKeyName:function(a,b){var c=new qq.Promise,d=this._options.objectProperties.key,e=qq.getExtension(b),f=c.failure,g=function(a,b){var d=a;void 0!==b&&(d+="."+b),c.success(d)};switch(d){case"uuid":g(this.getUuid(a),e);break;case"filename":g(b);break;default:qq.isFunction(d)?this._handleKeynameFunction(d,a,g,f):(this.log(d+" is not a valid value for the s3.keyname option!","error"),f())}return c},_handleKeynameFunction:function(a,b,c,d){var e=this,f=function(a){c(a)},g=function(a){e.log(qq.format("Failed to retrieve key name for {}. Reason: {}",b,a||"null"),"error"),d(a)},h=a.call(this,b);qq.isGenericPromise(h)?h.then(f,g):null==h?g():f(h)},_getEndpointSpecificParams:function(a,b,c){var d={key:this.getKey(a),uuid:this.getUuid(a),name:this.getName(a),bucket:this.getBucket(a)};return c&&c.getResponseHeader("ETag")?d.etag=c.getResponseHeader("ETag"):b.etag&&(d.etag=b.etag),d},_onSubmitDelete:function(a,b){var c={key:this.getKey(a),bucket:this.getBucket(a)};return qq.FineUploaderBasic.prototype._onSubmitDelete.call(this,a,b,c)},_addCannedFile:function(a){var b;if(null==a.s3Key)throw new qq.Error("Did not find s3Key property in server session response. This is required!");return b=qq.FineUploaderBasic.prototype._addCannedFile.apply(this,arguments),this._cannedKeys[b]=a.s3Key,this._cannedBuckets[b]=a.s3Bucket,b}})}(),qq.s3.RequestSigner=function(a){"use strict";function b(a,b,c){var d,e,f=b.responseText,g=j[a],h=g.promise;if(delete j[a],f)try{e=qq.parseJson(f)}catch(i){k.log("Error attempting to parse signature response: "+i,"error")}e&&e.invalid?(c=!0,d="Invalid policy document or request headers!"):e?k.expectingPolicy&&!e.policy?(c=!0,d="Response does not include the base64 encoded policy!"):e.signature||(c=!0,d="Response does not include the signature!"):(c=!0,d="Received an empty or invalid response from the server!"),c?(d&&k.log(d,"error"),h.failure(d)):h.success(e)}function c(a,b,c,d,e,f,g){var h,j="POST",k=[],l="";switch(a){case i.REQUEST_TYPE.MULTIPART_ABORT:j="DELETE",h=qq.format("uploadId={}",f);break;case i.REQUEST_TYPE.MULTIPART_INITIATE:h="uploads";break;case i.REQUEST_TYPE.MULTIPART_COMPLETE:h=qq.format("uploadId={}",f);break;case i.REQUEST_TYPE.MULTIPART_UPLOAD:j="PUT",h=qq.format("partNumber={}&uploadId={}",g,f)}return h=c+"?"+h,qq.each(e,function(a){k.push(a)}),k.sort(),qq.each(k,function(a,b){l+=b+":"+e[b]+"\n"}),{toSign:qq.format("{}\n\n{}\n\n{}/{}/{}",j,d||"",l||"\n",b,h),endOfUrl:h}}function d(a,b,c,d){var g;a.signatureConstructor?(d&&(g=a.signatureConstructor.getHeaders(),g[qq.s3.util.SESSION_TOKEN_PARAM_NAME]=d,a.signatureConstructor.withHeaders(g)),f(a.signatureConstructor.getToSign().stringToSign,b)):(d&&qq.s3.util.refreshPolicyCredentials(a,d),e(a,b,c,d))}function e(a,b,c,d){var e=JSON.stringify(a),f=CryptoJS.enc.Utf8.parse(e),g=CryptoJS.enc.Base64.stringify(f),i=CryptoJS.HmacSHA1(g,h.get().secretKey),j=CryptoJS.enc.Base64.stringify(i);b.success({policy:g,signature:j},c,d)}function f(a,b){var c=CryptoJS.enc.Utf8.parse(a),d=CryptoJS.HmacSHA1(c,h.get().secretKey),e=CryptoJS.enc.Base64.stringify(d);b.success({signature:e})}var g,h,i=this,j={},k={expectingPolicy:!1,method:"POST",signatureSpec:{credentialsProvider:{},endpoint:null,customHeaders:{}},maxConnections:3,paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(){}};qq.extend(k,a,!0),h=k.signatureSpec.credentialsProvider,g=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",method:k.method,contentType:"application/json; charset=utf-8",endpointStore:{get:function(){return k.signatureSpec.endpoint}},paramsStore:k.paramsStore,maxConnections:k.maxConnections,customHeaders:k.signatureSpec.customHeaders,log:k.log,onComplete:b,cors:k.cors})),qq.extend(this,{getSignature:function(a,b){var c=b,e=new qq.Promise;return h.get().secretKey&&window.CryptoJS?h.get().expiration.getTime()>Date.now()?d(b,e):h.onExpired().then(function(){d(b,e,h.get().accessKey,h.get().sessionToken)},function(){k.log("Attempt to update expired credentials apparently failed! Unable to sign request. ","error"),e.failure("Unable to sign request - expired credentials.")}):(k.log("Submitting S3 signature request for "+a),c.signatureConstructor&&(c={headers:c.signatureConstructor.getToSign().stringToSign}),g.initTransport(a).withParams(c).send(),j[a]={promise:e}),e},constructStringToSign:function(a,b,d){var e,f,g,i,j={};return{withHeaders:function(a){return j=a,this},withUploadId:function(a){return e=a,this},withContentType:function(a){return f=a,this},withPartNum:function(a){return g=a,this},getToSign:function(){var k=h.get().sessionToken;return j["x-amz-date"]=(new Date).toUTCString(),k&&(j[qq.s3.util.SESSION_TOKEN_PARAM_NAME]=k),i=c(a,b,d,f,j,e,g),{headers:function(){return f&&(j["Content-Type"]=f),j}(),endOfUrl:i.endOfUrl,stringToSign:i.toSign}},getHeaders:function(){return qq.extend({},j)},getEndOfUrl:function(){return i&&i.endOfUrl}}}})},qq.s3.RequestSigner.prototype.REQUEST_TYPE={MULTIPART_INITIATE:"multipart_initiate",MULTIPART_COMPLETE:"multipart_complete",MULTIPART_ABORT:"multipart_abort",MULTIPART_UPLOAD:"multipart_upload"},qq.UploadSuccessAjaxRequester=function(a){"use strict";function b(a,b,c){var f,g=d[a],h=b.responseText,i={success:!0},j={success:!1};delete d[a],e.log(qq.format("Received the following response body to an upload success request for id {}: {}",a,h));try{f=qq.parseJson(h),c||f&&(f.error||f.success===!1)?(e.log("Upload success request was rejected by the server.","error"),g.failure(qq.extend(f,j))):(e.log("Upload success was acknowledged by the server."),g.success(qq.extend(f,i)))}catch(k){c?(e.log(qq.format("Your server indicated failure in its upload success request response for id {}!",a),"error"),g.failure(j)):(e.log("Upload success was acknowledged by the server."),g.success(i))}}var c,d=[],e={method:"POST",endpoint:null,maxConnections:3,customHeaders:{},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(){}};qq.extend(e,a),c=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",method:e.method,endpointStore:{get:function(){return e.endpoint}},paramsStore:e.paramsStore,maxConnections:e.maxConnections,customHeaders:e.customHeaders,log:e.log,onComplete:b,cors:e.cors})),qq.extend(this,{sendSuccessRequest:function(a,b){var f=new qq.Promise;return e.log("Submitting upload success request/notification for "+a),c.initTransport(a).withParams(b).send(),d[a]=f,f}})},qq.s3.InitiateMultipartAjaxRequester=function(a){"use strict";function b(a){var b,c=g.getBucket(a),d={},f=new qq.Promise,h=g.getKey(a);return d["x-amz-acl"]=g.aclStore.get(a),g.reducedRedundancy&&(d[qq.s3.util.REDUCED_REDUNDANCY_PARAM_NAME]=qq.s3.util.REDUCED_REDUNDANCY_PARAM_VALUE),g.serverSideEncryption&&(d[qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_NAME]=qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_VALUE),d[qq.s3.util.AWS_PARAM_PREFIX+g.filenameParam]=encodeURIComponent(g.getName(a)),qq.each(g.paramsStore.get(a),function(a,b){d[qq.s3.util.AWS_PARAM_PREFIX+a]=encodeURIComponent(b)}),b=e.constructStringToSign(e.REQUEST_TYPE.MULTIPART_INITIATE,c,h).withContentType(g.getContentType(a)).withHeaders(d),e.getSignature(a,{signatureConstructor:b}).then(function(a){d=b.getHeaders(),d.Authorization="AWS "+g.signatureSpec.credentialsProvider.get().accessKey+":"+a.signature,f.success(d,b.getEndOfUrl())},f.failure),f}function c(a,b,c){var d,e,h,i,j,k=f[a],l=new DOMParser,m=l.parseFromString(b.responseText,"application/xml");delete f[a],c?(j=b.status,e=m.getElementsByTagName("Message"),e.length>0&&(i=e[0].textContent)):(d=m.getElementsByTagName("UploadId"),d.length>0?h=d[0].textContent:i="Upload ID missing from request"),void 0===h?(i?g.log(qq.format("Specific problem detected initiating multipart upload request for {}: '{}'.",a,i),"error"):g.log(qq.format("Unexplained error with initiate multipart upload request for {}. Status code {}.",a,j),"error"),k.failure("Problem initiating upload request.",b)):(g.log(qq.format("Initiate multipart upload request successful for {}. Upload ID is {}",a,h)),k.success(h,b))}var d,e,f={},g={filenameParam:"qqfilename",method:"POST",endpointStore:null,paramsStore:null,signatureSpec:null,aclStore:null,reducedRedundancy:!1,serverSideEncryption:!1,maxConnections:3,getContentType:function(){},getBucket:function(){},getKey:function(){},getName:function(){},log:function(){}};qq.extend(g,a),e=new qq.s3.RequestSigner({signatureSpec:g.signatureSpec,cors:g.cors,log:g.log}),d=qq.extend(this,new qq.AjaxRequester({method:g.method,contentType:null,endpointStore:g.endpointStore,maxConnections:g.maxConnections,allowXRequestedWithAndCacheControl:!1,log:g.log,onComplete:c,successfulResponseCodes:{POST:[200]}})),qq.extend(this,{send:function(a){var c=new qq.Promise;return b(a).then(function(b,e){g.log("Submitting S3 initiate multipart upload request for "+a),f[a]=c,d.initTransport(a).withPath(e).withHeaders(b).send()},c.failure),c}})},qq.s3.CompleteMultipartAjaxRequester=function(a){"use strict";function b(a,b){var c={},d=new qq.Promise,e=h.getBucket(a),g=f.constructStringToSign(f.REQUEST_TYPE.MULTIPART_COMPLETE,e,h.getKey(a)).withUploadId(b).withContentType("application/xml; charset=UTF-8");return f.getSignature(a,{signatureConstructor:g}).then(function(a){c=g.getHeaders(),c.Authorization="AWS "+h.signatureSpec.credentialsProvider.get().accessKey+":"+a.signature,d.success(c,g.getEndOfUrl())},d.failure),d}function c(a,b,c){var d=g[a],e=new DOMParser,f=h.getBucket(a),i=(h.getKey(a),e.parseFromString(b.responseText,"application/xml")),j=i.getElementsByTagName("Bucket"),k=i.getElementsByTagName("Key");delete g[a],h.log(qq.format("Complete response status {}, body = {}",b.status,b.responseText)),c?h.log(qq.format("Complete Multipart Upload request for {} failed with status {}.",a,b.status),"error"):j.length&&k.length?j[0].textContent!==f&&(c=!0,h.log(qq.format("Wrong bucket in response to Complete Multipart Upload request for {}.",a),"error")):(c=!0,h.log(qq.format("Missing bucket and/or key in response to Complete Multipart Upload request for {}.",a),"error")),c?d.failure("Problem combining the file parts!",b):d.success({},b)}function d(a){var b=document.implementation.createDocument(null,"CompleteMultipartUpload",null);return a.sort(function(a,b){return a.part-b.part}),qq.each(a,function(a,c){var d=c.part,e=c.etag,f=b.createElement("Part"),g=b.createElement("PartNumber"),h=b.createTextNode(d),i=b.createTextNode(e),j=b.createElement("ETag");j.appendChild(i),g.appendChild(h),f.appendChild(g),f.appendChild(j),qq(b).children()[0].appendChild(f)}),(new XMLSerializer).serializeToString(b)}var e,f,g={},h={method:"POST",contentType:"text/xml",endpointStore:null,signatureSpec:null,maxConnections:3,getBucket:function(){},getKey:function(){},log:function(){}};qq.extend(h,a),f=new qq.s3.RequestSigner({signatureSpec:h.signatureSpec,cors:h.cors,log:h.log}),e=qq.extend(this,new qq.AjaxRequester({method:h.method,contentType:"application/xml; charset=UTF-8",endpointStore:h.endpointStore,maxConnections:h.maxConnections,allowXRequestedWithAndCacheControl:!1,log:h.log,onComplete:c,successfulResponseCodes:{POST:[200]}})),qq.extend(this,{send:function(a,c,f){var i=new qq.Promise;return b(a,c).then(function(b,c){var j=d(f);h.log("Submitting S3 complete multipart upload request for "+a),g[a]=i,delete b["Content-Type"],e.initTransport(a).withPath(c).withHeaders(b).withPayload(j).send()},i.failure),i}})},qq.s3.AbortMultipartAjaxRequester=function(a){"use strict";function b(a,b){var c={},d=new qq.Promise,g=(f.endpointStore.get(a),f.getBucket(a)),h=e.constructStringToSign(e.REQUEST_TYPE.MULTIPART_ABORT,g,f.getKey(a)).withUploadId(b);return e.getSignature(a,{signatureConstructor:h}).then(function(a){c=h.getHeaders(),c.Authorization="AWS "+f.signatureSpec.credentialsProvider.get().accessKey+":"+a.signature,d.success(c,h.getEndOfUrl())},d.failure),d}function c(a,b,c){var d,e=new DOMParser,g=e.parseFromString(b.responseText,"application/xml"),h=g.getElementsByTagName("Error");f.log(qq.format("Abort response status {}, body = {}",b.status,b.responseText)),c?f.log(qq.format("Abort Multipart Upload request for {} failed with status {}.",a,b.status),"error"):h.length?(c=!0,d=g.getElementsByTagName("Message")[0].textContent,f.log(qq.format("Failed to Abort Multipart Upload request for {}. Error: {}",a,d),"error")):f.log(qq.format("Abort MPU request succeeded for file ID {}.",a))}var d,e,f={method:"DELETE",endpointStore:null,signatureSpec:null,maxConnections:3,getBucket:function(){},getKey:function(){},log:function(){}};qq.extend(f,a),e=new qq.s3.RequestSigner({signatureSpec:f.signatureSpec,cors:f.cors,log:f.log}),d=qq.extend(this,new qq.AjaxRequester({validMethods:["DELETE"],method:f.method,contentType:null,endpointStore:f.endpointStore,maxConnections:f.maxConnections,allowXRequestedWithAndCacheControl:!1,log:f.log,onComplete:c,successfulResponseCodes:{DELETE:[204]}})),qq.extend(this,{send:function(a,c){b(a,c).then(function(b,c){f.log("Submitting S3 Abort multipart upload request for "+a),d.initTransport(a).withPath(c).withHeaders(b).send()})}})},qq.s3.XhrUploadHandler=function(a,b){"use strict";var c=b.getName,d=b.log,e=200,f=a.getBucket,g=a.getKeyName,h=a.filenameParam,i=a.paramsStore,j=a.endpointStore,k=a.aclStore,l=a.objectProperties.reducedRedundancy,m=a.objectProperties.serverSideEncryption,n=a.validation,o=a.signature,p=this,q=a.signature.credentialsProvider,r={combine:function(a){var b=p._getPersistableData(a).uploadId,c=p._getPersistableData(a).etags,d=new qq.Promise;return s.completeMultipart.send(a,b,c).then(d.success,function(b,c){d.failure(u.done(a,c).response,c)}),d},done:function(a,b,c){var d,e=u.response.parse(a,b);e.success&&(d=b.getResponseHeader("ETag"),p._getPersistableData(a).etags||(p._getPersistableData(a).etags=[]),p._getPersistableData(a).etags.push({part:c+1,etag:d}))},initHeaders:function(b,c){var d={},e=(a.endpointStore.get(b),u.bucket.getName(b)),f=u.key.urlSafe(b),g=new qq.Promise,h=s.restSignature.constructStringToSign(s.restSignature.REQUEST_TYPE.MULTIPART_UPLOAD,e,f).withPartNum(c+1).withUploadId(p._getPersistableData(b).uploadId);return s.restSignature.getSignature(b+"."+c,{signatureConstructor:h}).then(function(a){d=h.getHeaders(),d.Authorization="AWS "+q.get().accessKey+":"+a.signature,g.success(d,h.getEndOfUrl())},g.failure),g},put:function(b,c){var d=p._createXhr(b,c),e=p._getChunkData(b,c),f=a.endpointStore.get(b),g=new qq.Promise;return r.initHeaders(b,c).then(function(a,h){var i=f+"/"+h;p._registerProgressHandler(b,c,e.size),u.track(b,d,c).then(g.success,g.failure),d.open("PUT",i,!0),qq.each(a,function(a,b){d.setRequestHeader(a,b)}),d.send(e.blob)},function(){g.failure({error:"Problem signing the chunk!"},d)}),g},send:function(a,b){var c=new qq.Promise;return r.setup(a).then(function(){r.put(a,b).then(c.success,c.failure)},function(a,b){c.failure({error:a},b)}),c},setup:function(a){var b=new qq.Promise,c=p._getPersistableData(a).uploadId,d=new qq.Promise;return c?c instanceof qq.Promise?c.then(function(a){b.success(a)}):b.success(c):(p._getPersistableData(a).uploadId=d,s.initiateMultipart.send(a).then(function(c){p._getPersistableData(a).uploadId=c,d.success(c),b.success(c)},function(c){p._getPersistableData(a).uploadId=null,b.failure(c),d.failure(c)})),b}},s={abortMultipart:new qq.s3.AbortMultipartAjaxRequester({endpointStore:j,signatureSpec:o,cors:a.cors,log:d,getBucket:function(a){return u.bucket.getName(a)},getKey:function(a){return u.key.urlSafe(a)}}),completeMultipart:new qq.s3.CompleteMultipartAjaxRequester({endpointStore:j,signatureSpec:o,cors:a.cors,log:d,getBucket:function(a){return u.bucket.getName(a)},getKey:function(a){return u.key.urlSafe(a)}}),initiateMultipart:new qq.s3.InitiateMultipartAjaxRequester({filenameParam:h,endpointStore:j,paramsStore:i,signatureSpec:o,aclStore:k,reducedRedundancy:l,serverSideEncryption:m,cors:a.cors,log:d,getContentType:function(a){return p._getMimeType(a)},getBucket:function(a){return u.bucket.getName(a)},getKey:function(a){return u.key.urlSafe(a)},getName:function(a){return c(a)}}),policySignature:new qq.s3.RequestSigner({expectingPolicy:!0,signatureSpec:o,cors:a.cors,log:d}),restSignature:new qq.s3.RequestSigner({signatureSpec:o,cors:a.cors,log:d})},t={initParams:function(a){var b=i.get(a);return b[h]=c(a),qq.s3.util.generateAwsParams({endpoint:j.get(a),params:b,type:p._getMimeType(a),bucket:u.bucket.getName(a),key:p.getThirdPartyFileId(a),accessKey:q.get().accessKey,sessionToken:q.get().sessionToken,acl:k.get(a),expectedStatus:e,minFileSize:n.minSizeLimit,maxFileSize:n.maxSizeLimit,reducedRedundancy:l,serverSideEncryption:m,log:d},qq.bind(s.policySignature.getSignature,this,a))},send:function(a){var b=new qq.Promise,c=p._createXhr(a),e=p.getFile(a);return p._registerProgressHandler(a),u.track(a,c).then(b.success,b.failure),t.setup(a,c,e).then(function(b){d("Sending upload request for "+a),c.send(b)},b.failure),b},setup:function(a,b,c){var d=new FormData,e=j.get(a),f=e,g=new qq.Promise;return t.initParams(a).then(function(a){b.open("POST",f,!0),qq.obj2FormData(a,d),d.append("file",c),g.success(d)},function(a){g.failure({error:a})}),g}},u={bucket:{promise:function(a){var b=new qq.Promise,c=p._getFileState(a).bucket;return c?b.success(c):f(a).then(function(c){p._getFileState(a).bucket=c,b.success(c)},b.failure),b},getName:function(a){return p._getFileState(a).bucket}},done:function(a,b){var c=u.response.parse(a,b),e=c.success!==!0;return e&&u.response.shouldReset(c.code)&&(d("This is an unrecoverable error, we must restart the upload entirely on the next retry attempt.","error"),c.reset=!0),{success:!e,response:c}},key:{promise:function(a){var b=new qq.Promise,d=p.getThirdPartyFileId(a);return null==d?(p._setThirdPartyFileId(a,b),g(a,c(a)).then(function(c){p._setThirdPartyFileId(a,c),b.success(c)},function(c){p._setThirdPartyFileId(a,null),b.failure(c)})):qq.isGenericPromise(d)?d.then(b.success,b.failure):b.success(d),b},urlSafe:function(a){return encodeURIComponent(p.getThirdPartyFileId(a))}},response:{parse:function(a,b){var c,f={};try{d(qq.format("Received response status {} with body: {}",b.status,b.responseText)),b.status===e?f.success=!0:(c=u.response.parseError(b.responseText),c&&(f.error=c.message,f.code=c.code))}catch(g){d("Error when attempting to parse xhr response text ("+g.message+")","error")}return f},parseError:function(a){var b,c,d=new DOMParser,e=d.parseFromString(a,"application/xml"),f=e.getElementsByTagName("Error"),g={};return f.length?(b=e.getElementsByTagName("Code"),c=e.getElementsByTagName("Message"),c.length&&(g.message=c[0].textContent),b.length&&(g.code=b[0].textContent),g):void 0},shouldReset:function(a){return"EntityTooSmall"===a||"InvalidPart"===a||"InvalidPartOrder"===a||"NoSuchUpload"===a}},start:function(a,b){var c=new qq.Promise;return u.key.promise(a).then(function(){u.bucket.promise(a).then(function(){null==b?t.send(a).then(c.success,c.failure):r.send(a,b).then(c.success,c.failure)})},function(a){c.failure({error:a})}),c},track:function(a,b,c){var d=new qq.Promise;return b.onreadystatechange=function(){if(4===b.readyState){var e;null==c?(e=u.done(a,b),d[e.success?"success":"failure"](e.response,b)):(r.done(a,b,c),e=u.done(a,b),d[e.success?"success":"failure"](e.response,b))}},d}};qq.extend(this,{uploadChunk:u.start,uploadFile:u.start}),qq.extend(this,new qq.XhrUploadHandler({options:qq.extend({namespace:"s3"},a),proxy:qq.extend({getEndpoint:a.endpointStore.get},b)})),qq.override(this,function(a){return{expunge:function(b){var c=p._getPersistableData(b)&&p._getPersistableData(b).uploadId,d=p._maybeDeletePersistedChunkData(b);void 0!==c&&d&&s.abortMultipart.send(b,c),a.expunge(b)},finalizeChunks:function(a){return r.combine(a)},_getLocalStorageId:function(b){var c=a._getLocalStorageId(b),d=u.bucket.getName(b);return c+"-"+d}}})},qq.s3.FormUploadHandler=function(a,b){"use strict";function c(b,c){var d,e,f,g=a.endpointStore.get(b),i=qq.s3.util.getBucket(g);try{if(d=c.contentDocument||c.contentWindow.document,e=d.body.innerHTML,f=qq.s3.util.parseIframeResponse(c),f.bucket===i&&f.key===qq.s3.util.encodeQueryStringParam(h.getThirdPartyFileId(b)))return!0;l("Response from AWS included an unexpected bucket or key name.","error")}catch(j){l("Error when attempting to parse form upload response ("+j.message+")","error")}return!1}function d(a){var b=p.get(a);return b[o]=j(a),qq.s3.util.generateAwsParams({endpoint:q.get(a),params:b,bucket:h._getFileState(a).bucket,key:h.getThirdPartyFileId(a),accessKey:x.get().accessKey,sessionToken:x.get().sessionToken,acl:r.get(a),minFileSize:u.minSizeLimit,maxFileSize:u.maxSizeLimit,successRedirectUrl:w,reducedRedundancy:s,serverSideEncryption:t,log:l},qq.bind(y.getSignature,this,a))
-}function e(b,c){var e=new qq.Promise,f="POST",i=a.endpointStore.get(b),k=j(b);return d(b).then(function(a){var b=h._initFormForUpload({method:f,endpoint:i,params:a,paramsInBody:!0,targetName:c.name});e.success(b)},function(a){e.failure(a),g(b,c,k,{error:a})}),e}function f(a){var b=h._createIframe(a),d=h.getInput(a),f=new qq.Promise;return e(a,b).then(function(e){e.appendChild(d),h._attachLoadEvent(b,function(d){l("iframe loaded"),d?d.success===!1&&(l("Amazon likely rejected the upload request","error"),f.failure(d)):(d={},d.success=c(a,b),d.success===!1?(l("A success response was received by Amazon, but it was invalid in some way.","error"),f.failure(d)):(qq.extend(d,qq.s3.util.parseIframeResponse(b)),f.success(d))),g(a,b)}),l("Sending upload request for "+a),e.submit(),qq(e).remove()},f.failure),f}function g(a,b){h._detachLoadEvent(a),b&&qq(b).remove()}var h=this,i=b.onUuidChanged,j=b.getName,k=b.getUuid,l=b.log,m=a.getBucket,n=a.getKeyName,o=a.filenameParam,p=a.paramsStore,q=a.endpointStore,r=a.aclStore,s=a.objectProperties.reducedRedundancy,t=a.objectProperties.serverSideEncryption,u=a.validation,v=a.signature,w=a.iframeSupport.localBlankPagePath,x=a.signature.credentialsProvider,y=new qq.s3.RequestSigner({signatureSpec:v,cors:a.cors,log:l});if(void 0===w)throw new Error("successRedirectEndpoint MUST be defined if you intend to use browsers that do not support the File API!");qq.extend(this,new qq.FormUploadHandler({options:{isCors:!1,inputName:"file"},proxy:{onCancel:a.onCancel,onUuidChanged:i,getName:j,getUuid:k,log:l}})),qq.extend(this,{uploadFile:function(a){var b=j(a),c=new qq.Promise;return h.getThirdPartyFileId(a)?h._getFileState(a).bucket?f(a).then(c.success,c.failure):m(a).then(function(b){h._getFileState(a).bucket=b,f(a).then(c.success,c.failure)}):n(a,b).then(function(b){m(a).then(function(d){h._getFileState(a).bucket=d,h._setThirdPartyFileId(a,b),f(a).then(c.success,c.failure)},function(a){c.failure({error:a})})},function(a){c.failure({error:a})}),c}})},function(){"use strict";qq.s3.FineUploader=function(a){var b={failedUploadTextDisplay:{mode:"custom"}};qq.extend(b,a,!0),qq.FineUploader.call(this,b,"s3"),qq.supportedFeatures.ajaxUploading||void 0!==b.iframeSupport.localBlankPagePath||(this._options.element.innerHTML="
You MUST set the localBlankPagePath property of the iframeSupport option since this browser does not support the File API!
")},qq.extend(qq.s3.FineUploader.prototype,qq.s3.FineUploaderBasic.prototype),qq.extend(qq.s3.FineUploader.prototype,qq.uiPublicApi),qq.extend(qq.s3.FineUploader.prototype,qq.uiPrivateApi)}(),qq.PasteSupport=function(a){"use strict";function b(a){return a.type&&0===a.type.indexOf("image/")}function c(){f=qq(e.targetElement).attach("paste",function(a){var c=a.clipboardData;c&&qq.each(c.items,function(a,c){if(b(c)){var d=c.getAsFile();e.callbacks.pasteReceived(d)}})})}function d(){f&&f()}var e,f;e={targetElement:null,callbacks:{log:function(){},pasteReceived:function(){}}},qq.extend(e,a),c(),qq.extend(this,{reset:function(){d()}})},qq.DragAndDrop=function(a){"use strict";function b(a,b){var c=Array.prototype.slice.call(a);j.callbacks.dropLog("Grabbed "+a.length+" dropped files."),b.dropDisabled(!1),j.callbacks.processingDroppedFilesComplete(c,b.getElement())}function c(a){var b=new qq.Promise;return a.isFile?a.file(function(c){var d=a.name,e=a.fullPath,f=e.indexOf(d);e=e.substr(0,f),"/"===e.charAt(0)&&(e=e.substr(1)),c.qqPath=e,n.push(c),b.success()},function(c){j.callbacks.dropLog("Problem parsing '"+a.fullPath+"'. FileError code "+c.code+".","error"),b.failure()}):a.isDirectory&&d(a).then(function(a){var d=a.length;qq.each(a,function(a,e){c(e).done(function(){d-=1,0===d&&b.success()})}),a.length||b.success()},function(c){j.callbacks.dropLog("Problem parsing '"+a.fullPath+"'. FileError code "+c.code+".","error"),b.failure()}),b}function d(a,b,c,e){var f=e||new qq.Promise,g=b||a.createReader();return g.readEntries(function(b){var e=c?c.concat(b):b;b.length?setTimeout(function(){d(a,g,e,f)},0):f.success(e)},f.failure),f}function e(a,b){var d=[],e=new qq.Promise;return j.callbacks.processingDroppedFiles(),b.dropDisabled(!0),a.files.length>1&&!j.allowMultipleItems?(j.callbacks.processingDroppedFilesComplete([]),j.callbacks.dropError("tooManyFilesError",""),b.dropDisabled(!1),e.failure()):(n=[],qq.isFolderDropSupported(a)?qq.each(a.items,function(a,b){var f=b.webkitGetAsEntry();f&&(f.isFile?n.push(b.getAsFile()):d.push(c(f).done(function(){d.pop(),0===d.length&&e.success()})))}):n=a.files,0===d.length&&e.success()),e}function f(a){var c=new qq.UploadDropZone({HIDE_ZONES_EVENT_NAME:k,element:a,onEnter:function(b){qq(a).addClass(j.classes.dropActive),b.stopPropagation()},onLeaveNotDescendants:function(){qq(a).removeClass(j.classes.dropActive)},onDrop:function(a){e(a.dataTransfer,c).then(function(){b(n,c)},function(){j.callbacks.dropLog("Drop event DataTransfer parsing failed. No files will be uploaded.","error")})}});return o.addDisposer(function(){c.dispose()}),qq(a).hasAttribute(l)&&qq(a).hide(),m.push(c),c}function g(a){var b;return qq.each(a.dataTransfer.types,function(a,c){return"Files"===c?(b=!0,!1):void 0}),b}function h(a){return qq.firefox()?!a.relatedTarget:qq.safari()?a.x<0||a.y<0:0===a.x&&0===a.y}function i(){var a=j.dropZoneElements,b=function(){setTimeout(function(){qq.each(a,function(a,b){qq(b).hasAttribute(l)&&qq(b).hide(),qq(b).removeClass(j.classes.dropActive)})},10)};qq.each(a,function(b,c){var d=f(c);a.length&&qq.supportedFeatures.fileDrop&&o.attach(document,"dragenter",function(b){!d.dropDisabled()&&g(b)&&qq.each(a,function(a,b){b instanceof HTMLElement&&qq(b).hasAttribute(l)&&qq(b).css({display:"block"})})})}),o.attach(document,"dragleave",function(a){h(a)&&b()}),o.attach(qq(document).children()[0],"mouseenter",function(){b()}),o.attach(document,"drop",function(a){a.preventDefault(),b()}),o.attach(document,k,b)}var j,k="qq-hidezones",l="qq-hide-dropzone",m=[],n=[],o=new qq.DisposeSupport;j={dropZoneElements:[],allowMultipleItems:!0,classes:{dropActive:null},callbacks:new qq.DragAndDrop.callbacks},qq.extend(j,a,!0),i(),qq.extend(this,{setupExtraDropzone:function(a){j.dropZoneElements.push(a),f(a)},removeDropzone:function(a){var b,c=j.dropZoneElements;for(b in c)if(c[b]===a)return c.splice(b,1)},dispose:function(){o.dispose(),qq.each(m,function(a,b){b.dispose()})}})},qq.DragAndDrop.callbacks=function(){"use strict";return{processingDroppedFiles:function(){},processingDroppedFilesComplete:function(){},dropError:function(a,b){qq.log("Drag & drop error code '"+a+" with these specifics: '"+b+"'","error")},dropLog:function(a,b){qq.log(a,b)}}},qq.UploadDropZone=function(a){"use strict";function b(){return qq.safari()||qq.firefox()&&qq.windows()}function c(){k||(b?l.attach(document,"dragover",function(a){a.preventDefault()}):l.attach(document,"dragover",function(a){a.dataTransfer&&(a.dataTransfer.dropEffect="none",a.preventDefault())}),k=!0)}function d(a){if(!qq.supportedFeatures.fileDrop)return!1;var b,c=a.dataTransfer,d=qq.safari();return b=qq.ie()&&qq.supportedFeatures.fileDrop?!0:"none"!==c.effectAllowed,c&&b&&(c.files||!d&&c.types.contains&&c.types.contains("Files"))}function e(a){return void 0!==a&&(j=a),j}function f(){function a(){b=document.createEvent("Event"),b.initEvent(h.HIDE_ZONES_EVENT_NAME,!0,!0)}var b;if(window.CustomEvent)try{b=new CustomEvent(h.HIDE_ZONES_EVENT_NAME)}catch(c){a()}else a();document.dispatchEvent(b)}function g(){l.attach(i,"dragover",function(a){if(d(a)){var b=qq.ie()&&qq.supportedFeatures.fileDrop?null:a.dataTransfer.effectAllowed;a.dataTransfer.dropEffect="move"===b||"linkMove"===b?"move":"copy",a.stopPropagation(),a.preventDefault()}}),l.attach(i,"dragenter",function(a){if(!e()){if(!d(a))return;h.onEnter(a)}}),l.attach(i,"dragleave",function(a){if(d(a)){h.onLeave(a);var b=document.elementFromPoint(a.clientX,a.clientY);qq(this).contains(b)||h.onLeaveNotDescendants(a)}}),l.attach(i,"drop",function(a){if(!e()){if(!d(a))return;a.preventDefault(),a.stopPropagation(),h.onDrop(a),f()}})}var h,i,j,k,l=new qq.DisposeSupport;h={element:null,onEnter:function(){},onLeave:function(){},onLeaveNotDescendants:function(){},onDrop:function(){}},qq.extend(h,a),i=h.element,c(),g(),qq.extend(this,{dropDisabled:function(a){return e(a)},dispose:function(){l.dispose()},getElement:function(){return i}})},qq.DeleteFileAjaxRequester=function(a){"use strict";function b(){return"POST"===d.method.toUpperCase()?{_method:"DELETE"}:{}}var c,d={method:"DELETE",uuidParamName:"qquuid",endpointStore:{},maxConnections:3,customHeaders:function(){return{}},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(){},onDelete:function(){},onDeleteComplete:function(){}};qq.extend(d,a),c=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["POST","DELETE"],method:d.method,endpointStore:d.endpointStore,paramsStore:d.paramsStore,mandatedParams:b(),maxConnections:d.maxConnections,customHeaders:function(a){return d.customHeaders.get(a)},log:d.log,onSend:d.onDelete,onComplete:d.onDeleteComplete,cors:d.cors})),qq.extend(this,{sendDelete:function(a,b,e){var f=e||{};d.log("Submitting delete file request for "+a),"DELETE"===d.method?c.initTransport(a).withPath(b).withParams(f).send():(f[d.uuidParamName]=b,c.initTransport(a).withParams(f).send())}})},function(){function a(a){var b,c=a.naturalWidth,d=a.naturalHeight,e=document.createElement("canvas");return c*d>1048576?(e.width=e.height=1,b=e.getContext("2d"),b.drawImage(a,-c+1,0),0===b.getImageData(0,0,1,1).data[3]):!1}function b(a,b,c){var d,e,f,g,h=document.createElement("canvas"),i=0,j=c,k=c;for(h.width=1,h.height=c,d=h.getContext("2d"),d.drawImage(a,0,0),e=d.getImageData(0,0,1,c).data;k>i;)f=e[4*(k-1)+3],0===f?j=k:i=k,k=j+i>>1;return g=k/c,0===g?1:g}function c(a,b,c){var d=document.createElement("canvas"),f=b.mime||"image/jpeg";return e(a,d,b,c),d.toDataURL(f,b.quality||.8)}function d(a){var b=5241e3;if(!qq.ios())throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");return a.origHeight*a.origWidth>b?{newHeight:Math.round(Math.sqrt(b*(a.origHeight/a.origWidth))),newWidth:Math.round(Math.sqrt(b*(a.origWidth/a.origHeight)))}:void 0}function e(c,e,g,h){var i,j=c.naturalWidth,k=c.naturalHeight,l=g.width,m=g.height,n=e.getContext("2d");n.save(),qq.supportedFeatures.unlimitedScaledImageSize||(i=d({origWidth:l,origHeight:m}),i&&(qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",l,m,i.newWidth,i.newHeight),"warn"),l=i.newWidth,m=i.newHeight)),f(e,l,m,g.orientation),qq.ios()?function(){a(c)&&(j/=2,k/=2);var d,e,f,g=1024,i=document.createElement("canvas"),o=h?b(c,j,k):1,p=Math.ceil(g*l/j),q=Math.ceil(g*m/k/o),r=0,s=0;for(i.width=i.height=g,d=i.getContext("2d");k>r;){for(e=0,f=0;j>e;)d.clearRect(0,0,g,g),d.drawImage(c,-e,-r),n.drawImage(i,0,0,g,g,f,s,p,q),e+=g,f+=p;r+=g,s+=q}n.restore(),i=d=null}():n.drawImage(c,0,0,l,m),e.qqImageRendered&&e.qqImageRendered()}function f(a,b,c,d){switch(d){case 5:case 6:case 7:case 8:a.width=c,a.height=b;break;default:a.width=b,a.height=c}var e=a.getContext("2d");switch(d){case 2:e.translate(b,0),e.scale(-1,1);break;case 3:e.translate(b,c),e.rotate(Math.PI);break;case 4:e.translate(0,c),e.scale(1,-1);break;case 5:e.rotate(.5*Math.PI),e.scale(1,-1);break;case 6:e.rotate(.5*Math.PI),e.translate(0,-c);break;case 7:e.rotate(.5*Math.PI),e.translate(b,-c),e.scale(-1,1);break;case 8:e.rotate(-.5*Math.PI),e.translate(-b,0)}}function g(a,b){var c=this;window.Blob&&a instanceof Blob&&function(){var b=new Image,d=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;if(!d)throw Error("No createObjectURL function found to create blob url");b.src=d.createObjectURL(a),c.blob=a,a=b}(),a.naturalWidth||a.naturalHeight||(a.onload=function(){var a=c.imageLoadListeners;a&&(c.imageLoadListeners=null,setTimeout(function(){for(var b=0,c=a.length;c>b;b++)a[b]()},0))},a.onerror=b,this.imageLoadListeners=[]),this.srcImage=a}g.prototype.render=function(a,b){b=b||{};var d,f=this,g=this.srcImage.naturalWidth,h=this.srcImage.naturalHeight,i=b.width,j=b.height,k=b.maxWidth,l=b.maxHeight,m=!this.blob||"image/jpeg"===this.blob.type,n=a.tagName.toLowerCase();return this.imageLoadListeners?(this.imageLoadListeners.push(function(){f.render(a,b)}),void 0):(i&&!j?j=h*i/g<<0:j&&!i?i=g*j/h<<0:(i=g,j=h),k&&i>k&&(i=k,j=h*i/g<<0),l&&j>l&&(j=l,i=g*j/h<<0),d={width:i,height:j},qq.each(b,function(a,b){d[a]=b}),"img"===n?function(){var b=a.src;a.src=c(f.srcImage,d,m),b===a.src&&a.onload()}():"canvas"===n&&e(this.srcImage,a,d,m),"function"==typeof this.onrender&&this.onrender(a),void 0)},qq.MegaPixImage=g}(),qq.ImageGenerator=function(a){"use strict";function b(a){return"img"===a.tagName.toLowerCase()}function c(a){return"canvas"===a.tagName.toLowerCase()}function d(){return void 0!==(new Image).crossOrigin}function e(){var a=document.createElement("canvas");return a.getContext&&a.getContext("2d")}function f(a){var b=a.split("/"),c=b[b.length-1],d=qq.getExtension(c);switch(d=d&&d.toLowerCase()){case"jpeg":case"jpg":return"image/jpeg";case"png":return"image/png";case"bmp":return"image/bmp";case"gif":return"image/gif";case"tiff":case"tif":return"image/tiff"}}function g(a){var b,c,d,e=document.createElement("a");return e.href=a,b=e.protocol,d=e.port,c=e.hostname,b.toLowerCase()!==window.location.protocol.toLowerCase()?!0:c.toLowerCase()!==window.location.hostname.toLowerCase()?!0:d===window.location.port||qq.ie()?!1:!0}function h(b,c){b.onload=function(){b.onload=null,b.onerror=null,c.success(b)},b.onerror=function(){b.onload=null,b.onerror=null,a("Problem drawing thumbnail!","error"),c.failure(b,"Problem drawing thumbnail!")}}function i(a,b){a.qqImageRendered=function(){b.success(a)}}function j(d,e){var f=b(d)||c(d);return b(d)?h(d,e):c(d)?i(d,e):(e.failure(d),a(qq.format("Element container of type {} is not supported!",d.tagName),"error")),f}function k(b,c,d){var e=new qq.Promise,f=new qq.Identify(b,a),g=d.maxSize,h=null==d.orient?!0:d.orient,i=function(){c.onerror=null,c.onload=null,a("Could not render preview, file may be too large!","error"),e.failure(c,"Browser cannot render image!")};return f.isPreviewable().then(function(d){var f={parse:function(){return(new qq.Promise).success()}},k=h?new qq.Exif(b,a):f,l=new qq.MegaPixImage(b,i);j(c,e)&&k.parse().then(function(a){var b=a&&a.Orientation;l.render(c,{maxWidth:g,maxHeight:g,orientation:b,mime:d})},function(b){a(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.",b)),l.render(c,{maxWidth:g,maxHeight:g,mime:d})})},function(){a("Not previewable"),e.failure(c,"Not previewable")}),e}function l(a,b,c,d){var e=new Image,h=new qq.Promise;j(e,h),g(a)&&(e.crossOrigin="anonymous"),e.src=a,h.then(function(){j(b,c);var g=new qq.MegaPixImage(e);g.render(b,{maxWidth:d,maxHeight:d,mime:f(a)})},c.failure)}function m(a,b,c,d){j(b,c),qq(b).css({maxWidth:d+"px",maxHeight:d+"px"}),b.src=a}function n(a,f,h){var i=new qq.Promise,k=h.scale,n=k?h.maxSize:null;return k&&b(f)?e()?g(a)&&!d()?m(a,f,i,n):l(a,f,i,n):m(a,f,i,n):c(f)?l(a,f,i,n):j(f,i)&&(f.src=a),i}qq.extend(this,{generate:function(b,c,d){return qq.isString(b)?(a("Attempting to update thumbnail based on server response."),n(b,c,d||{})):(a("Attempting to draw client-side image preview."),k(b,c,d||{}))}})},qq.Exif=function(a,b){"use strict";function c(a){for(var b=0,c=0;a.length>0;)b+=parseInt(a.substring(0,2),16)*Math.pow(2,c),a=a.substring(2,a.length),c+=8;return b}function d(b,c){var e=b,f=c;return void 0===e&&(e=2,f=new qq.Promise),qq.readBlobToHex(a,e,4).then(function(a){var b,c=/^ffe([0-9])/.exec(a);c?"1"!==c[1]?(b=parseInt(a.slice(4,8),16),d(e+b+2,f)):f.success(e):f.failure("No EXIF header to be found!")}),f}function e(){var b=new qq.Promise;return qq.readBlobToHex(a,0,6).then(function(a){0!==a.indexOf("ffd8")?b.failure("Not a valid JPEG!"):d().then(function(a){b.success(a)},function(a){b.failure(a)})}),b}function f(b){var c=new qq.Promise;return qq.readBlobToHex(a,b+10,2).then(function(a){c.success("4949"===a)}),c}function g(b,d){var e=new qq.Promise;return qq.readBlobToHex(a,b+18,2).then(function(a){return d?e.success(c(a)):(e.success(parseInt(a,16)),void 0)}),e}function h(b,c){var d=b+20,e=12*c;return qq.readBlobToHex(a,d,e)}function i(a){for(var b=[],c=0;c+24<=a.length;)b.push(a.slice(c,c+24)),c+=24;return b}function j(a,b){var d=16,e=qq.extend([],k),f={};return qq.each(b,function(b,g){var h,i,j,k=g.slice(0,4),m=a?c(k):parseInt(k,16),n=e.indexOf(m);return n>=0&&(i=l[m].name,j=l[m].bytes,h=g.slice(d,d+2*j),f[i]=a?c(h):parseInt(h,16),e.splice(n,1)),0===e.length?!1:void 0}),f}var k=[274],l={274:{name:"Orientation",bytes:2}};qq.extend(this,{parse:function(){var c=new qq.Promise,d=function(a){b(qq.format("EXIF header parse failed: '{}' ",a)),c.failure(a)};return e().then(function(e){b(qq.format("Moving forward with EXIF header parsing for '{}'",void 0===a.name?"blob":a.name)),f(e).then(function(a){b(qq.format("EXIF Byte order is {} endian",a?"little":"big")),g(e,a).then(function(f){b(qq.format("Found {} APP1 directory entries",f)),h(e,f).then(function(d){var e=i(d),f=j(a,e);b("Successfully parsed some EXIF tags"),c.success(f)},d)},d)},d)},d),c}})},qq.Identify=function(a,b){"use strict";function c(a,b){var c=!1,d=[].concat(a);return qq.each(d,function(a,d){return 0===b.indexOf(d)?(c=!0,!1):void 0}),c}qq.extend(this,{isPreviewable:function(){var d=this,e=new qq.Promise,f=!1,g=void 0===a.name?"blob":a.name;return b(qq.format("Attempting to determine if {} can be rendered in this browser",g)),b("First pass: check type attribute of blob object."),this.isPreviewableSync()?(b("Second pass: check for magic bytes in file header."),qq.readBlobToHex(a,0,4).then(function(a){qq.each(d.PREVIEWABLE_MIME_TYPES,function(b,d){return c(d,a)?(("image/tiff"!==b||qq.supportedFeatures.tiffPreviews)&&(f=!0,e.success(b)),!1):void 0}),b(qq.format("'{}' is {} able to be rendered in this browser",g,f?"":"NOT")),f||e.failure()},function(){b("Error reading file w/ name '"+g+"'. Not able to be rendered in this browser."),e.failure()})):e.failure(),e},isPreviewableSync:function(){var c=a.type,d=qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES),c)>=0,e=!1,f=void 0===a.name?"blob":a.name;return d&&(e="image/tiff"===c?qq.supportedFeatures.tiffPreviews:!0),!e&&b(f+" is not previewable in this browser per the blob's type attr"),e}})},qq.Identify.prototype.PREVIEWABLE_MIME_TYPES={"image/jpeg":"ffd8ff","image/gif":"474946","image/png":"89504e","image/bmp":"424d","image/tiff":["49492a00","4d4d002a"]},qq.ImageValidation=function(a,b){"use strict";function c(a){var b=!1;return qq.each(a,function(a,c){return c>0?(b=!0,!1):void 0}),b}function d(){var c=new qq.Promise;return new qq.Identify(a,b).isPreviewable().then(function(){var d=new Image,e=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;e?(d.onerror=function(){b("Cannot determine dimensions for image. May be too large.","error"),c.failure()},d.onload=function(){c.success({width:this.width,height:this.height})},d.src=e.createObjectURL(a)):(b("No createObjectURL function available to generate image URL!","error"),c.failure())},c.failure),c}function e(a,b){var c;return qq.each(a,function(a,d){if(d>0){var e=/(max|min)(Width|Height)/.exec(a),f=e[2].charAt(0).toLowerCase()+e[2].slice(1),g=b[f];switch(e[1]){case"min":if(d>g)return c=a,!1;break;case"max":if(g>d)return c=a,!1}}}),c}this.validate=function(a){var f=new qq.Promise;return b("Attempting to validate image."),c(a)?d().then(function(b){var c=e(a,b);c?f.failure(c):f.success()},f.success):f.success(),f}},qq.Session=function(a){"use strict";function b(a){return qq.isArray(a)?!0:(d.log("Session response is not an array.","error"),void 0)}function c(a,c,e,f){var g=!1;c=c&&b(a),c&&qq.each(a,function(a,b){if(null==b.uuid)g=!0,d.log(qq.format("Session response item {} did not include a valid UUID - ignoring.",a),"error");else if(null==b.name)g=!0,d.log(qq.format("Session response item {} did not include a valid name - ignoring.",a),"error");else try{return d.addFileRecord(b),!0}catch(c){g=!0,d.log(c.message,"error")}return!1}),f[c&&!g?"success":"failure"](a,e)}var d={endpoint:null,params:{},customHeaders:{},cors:{},addFileRecord:function(){},log:function(){}};qq.extend(d,a,!0),this.refresh=function(){var a=new qq.Promise,b=function(b,d,e){c(b,d,e,a)},e=qq.extend({},d),f=new qq.SessionAjaxRequester(qq.extend(e,{onComplete:b}));return f.queryServer(),a}},qq.SessionAjaxRequester=function(a){"use strict";function b(a,b,c){var e=null;if(null!=b.responseText)try{e=qq.parseJson(b.responseText)}catch(f){d.log("Problem parsing session response: "+f.message,"error"),c=!0}d.onComplete(e,!c,b)}var c,d={endpoint:null,customHeaders:{},params:{},cors:{expected:!1,sendCredentials:!1},onComplete:function(){},log:function(){}};qq.extend(d,a),c=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["GET"],method:"GET",endpointStore:{get:function(){return d.endpoint}},customHeaders:d.customHeaders,log:d.log,onComplete:b,cors:d.cors})),qq.extend(this,{queryServer:function(){var a=qq.extend({},d.params);d.log("Session query request."),c.initTransport("sessionRefresh").withParams(a).withCacheBuster().send()}})},qq.FormSupport=function(a,b,c){"use strict";function d(a){a.getAttribute("action")&&(h.newEndpoint=a.getAttribute("action"))}function e(a,b){return!a.checkValidity||a.checkValidity()?!0:(c("Form did not pass validation checks - will not upload.","error"),b(),void 0)}function f(a){var c=a.submit;qq(a).attach("submit",function(d){d=d||window.event,d.preventDefault?d.preventDefault():d.returnValue=!1,e(a,c)&&b()}),a.submit=function(){e(a,c)&&b()}}function g(a){return a&&(qq.isString(a)&&(a=document.getElementById(a)),a&&(c("Attaching to form element."),d(a),i&&f(a))),a}var h=this,i=a.interceptSubmit,j=a.element,k=a.autoUpload;qq.extend(this,{newEndpoint:null,newAutoUpload:k,attachedToForm:!1,getFormInputsAsObject:function(){return null==j?null:h._form2Obj(j)}}),j=g(j),this.attachedToForm=!!j},qq.extend(qq.FormSupport.prototype,{_form2Obj:function(a){"use strict";var b={},c=function(a){var b=["button","image","reset","submit"];return qq.indexOf(b,a.toLowerCase())<0},d=function(a){return qq.indexOf(["checkbox","radio"],a.toLowerCase())>=0},e=function(a){return d(a.type)&&!a.checked?!0:a.disabled&&"hidden"!==a.type.toLowerCase()},f=function(a){var b=null;return qq.each(qq(a).children(),function(a,c){return"option"===c.tagName.toLowerCase()&&c.selected?(b=c.value,!1):void 0}),b};return qq.each(a.elements,function(a,d){if(!qq.isInput(d,!0)&&"textarea"!==d.tagName.toLowerCase()||!c(d.type)||e(d)){if("select"===d.tagName.toLowerCase()&&!e(d)){var g=f(d);null!==g&&(b[d.name]=g)}}else b[d.name]=d.value}),b}}),qq.Scaler=function(a,b){"use strict";var c=a.sendOriginal,d=a.orient,e=a.defaultType,f=a.defaultQuality/100,g=a.failureText,h=a.includeExif,i=this._getSortedSizes(a.sizes);qq.extend(this,{enabled:qq.supportedFeatures.scaling&&i.length>0,getFileRecords:function(a,j,k){var l=this,m=[],n=k.blob?k.blob:k,o=new qq.Identify(n,b);return o.isPreviewableSync()?(qq.each(i,function(a,c){var i=l._determineOutputType({defaultType:e,requestedType:c.type,refType:n.type});m.push({uuid:qq.getUniqueId(),name:l._getName(j,{name:c.name,type:i,refType:n.type}),blob:new qq.BlobProxy(n,qq.bind(l._generateScaledImage,l,{maxSize:c.maxSize,orient:d,type:i,quality:f,failedText:g,includeExif:h,log:b}))})}),c&&m.push({uuid:a,name:j,blob:n})):m.push({uuid:a,name:j,blob:n}),m},handleNewFile:function(a,b,c,d,e,f,g,h){var i=this,j=(a.qqButtonId||a.blob&&a.blob.qqButtonId,[]),k=null,l=h.addFileToHandler,m=h.uploadData,n=h.paramsStore,o=qq.getUniqueId();qq.each(i.getFileRecords(c,b,a),function(b,c){var g,h=a,i=d;c.blob instanceof qq.BlobProxy&&(h=c.blob,i=-1),g=m.addFile({uuid:c.uuid,name:c.name,size:i,batchId:f,proxyGroupId:o}),c.blob instanceof qq.BlobProxy?j.push(g):k=g,l(g,h),e.push({id:g,file:h})}),null!==k&&(qq.each(j,function(a,b){var c={qqparentuuid:m.retrieve({id:k}).uuid,qqparentsize:m.retrieve({id:k}).size};c[g]=m.retrieve({id:b}).uuid,m.setParentId(b,k),n.addReadOnly(b,c)}),j.length&&function(){var a={};a[g]=m.retrieve({id:k}).uuid,n.addReadOnly(k,a)}())}})},qq.extend(qq.Scaler.prototype,{scaleImage:function(a,b,c){"use strict";if(!qq.supportedFeatures.scaling)throw new qq.Error("Scaling is not supported in this browser!");var d=new qq.Promise,e=c.log,f=c.getFile(a),g=c.uploadData.retrieve({id:a}),h=g&&g.name,i=g&&g.uuid,j={sendOriginal:!1,orient:b.orient,defaultType:b.type||null,defaultQuality:b.quality,failedToScaleText:"Unable to scale",sizes:[{name:"",maxSize:b.maxSize}]},k=new qq.Scaler(j,e);return qq.Scaler&&qq.supportedFeatures.imagePreviews&&f?qq.bind(function(){var b=k.getFileRecords(i,h,f)[0];b&&b.blob instanceof qq.BlobProxy?b.blob.create().then(d.success,d.failure):(e(a+" is not a scalable image!","error"),d.failure())},this)():(d.failure(),e("Could not generate requested scaled image for "+a+". "+"Scaling is either not possible in this browser, or the file could not be located.","error")),d},_determineOutputType:function(a){"use strict";var b=a.requestedType,c=a.defaultType,d=a.refType;return c||b?b?qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES),b)>=0?"image/tiff"===b?qq.supportedFeatures.tiffPreviews?b:c:b:c:c:"image/jpeg"!==d?"image/png":d},_getName:function(a,b){"use strict";var c=a.lastIndexOf("."),d=b.type||"image/png",e=b.refType,f="",g=qq.getExtension(a),h="";return b.name&&b.name.trim().length&&(h=" ("+b.name+")"),c>=0?(f=a.substr(0,c),e!==d&&(g=d.split("/")[1]),f+=h+"."+g):f=a+h,f},_getSortedSizes:function(a){"use strict";return a=qq.extend([],a),a.sort(function(a,b){return a.maxSize>b.maxSize?1:a.maxSize=0?atob(a.split(",")[1]):decodeURI(a.split(",")[1]),c=a.split(",")[0].split(":")[1].split(";")[0],d=new ArrayBuffer(b.length),e=new Uint8Array(d),qq.each(b,function(a,b){e[a]=b.charCodeAt(0)}),this._createBlob(d,c)},_createBlob:function(a,b){"use strict";var c=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,d=c&&new c;return d?(d.append(a),d.getBlob(b)):new Blob([a],{type:b})}});var ExifRestorer=function(){var a={};return a.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",a.encode64=function(a){var b,c,d,e,f,g="",h="",i="",j=0;do b=a[j++],c=a[j++],h=a[j++],d=b>>2,e=(3&b)<<4|c>>4,f=(15&c)<<2|h>>6,i=63&h,isNaN(c)?f=i=64:isNaN(h)&&(i=64),g=g+this.KEY_STR.charAt(d)+this.KEY_STR.charAt(e)+this.KEY_STR.charAt(f)+this.KEY_STR.charAt(i),b=c=h="",d=e=f=i="";while(ja.length)break}return c},a.decode64=function(a){var b,c,d,e,f,g="",h="",i=0,j=[],k=/[^A-Za-z0-9\+\/\=]/g;if(k.exec(a))throw new Error("There were invalid base64 characters in the input text. Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='");a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do d=this.KEY_STR.indexOf(a.charAt(i++)),e=this.KEY_STR.indexOf(a.charAt(i++)),f=this.KEY_STR.indexOf(a.charAt(i++)),h=this.KEY_STR.indexOf(a.charAt(i++)),b=d<<2|e>>4,c=(15&e)<<4|f>>2,g=(3&f)<<6|h,j.push(b),64!=f&&j.push(c),64!=h&&j.push(g),b=c=g="",d=e=f=h="";while(i=0?(c=!1,!1):void 0}),c},j=function(a){m(a,-1,-1),delete c[a]},k=function(a,b,c){(0===b.length||i(b,c))&&(h(e,e),this.reset())},l=function(a){var d=b(a);d>0&&(m(a,0,d),c[a]={loaded:0,total:d})},m=function(a,b,f){var g=c[a]?c[a].loaded:0,i=c[a]?c[a].total:0;-1===b&&-1===f?(d-=g,e-=i):(b&&(d+=b-g),f&&(e+=f-i)),h(d,e)};qq.extend(this,{onAllComplete:k,onStatusChange:function(a,b,c){c===qq.status.CANCELED||c===qq.status.REJECTED?j(a):c===qq.status.SUBMITTING&&l(a)},onIndividualProgress:function(a,b,d){m(a,b,d),c[a]={loaded:b,total:d}},onNewSize:function(a){l(a)},reset:function(){c={},d=0,e=0}})},qq.UiEventHandler=function(a,b){"use strict";function c(a){d.attach(a,e.eventType,function(a){a=a||window.event;var b=a.target||a.srcElement;e.onHandled(b,a)})}var d=new qq.DisposeSupport,e={eventType:"click",attachTo:null,onHandled:function(){}};qq.extend(this,{addHandler:function(a){c(a)},dispose:function(){d.dispose()}}),qq.extend(b,{getFileIdFromItem:function(a){return a.qqFileId},getDisposeSupport:function(){return d}}),qq.extend(e,a),e.attachTo&&c(e.attachTo)},qq.FileButtonsClickHandler=function(a){"use strict";function b(a,b){qq.each(e,function(c,e){var f,g=c.charAt(0).toUpperCase()+c.slice(1);return d.templating["is"+g](a)?(f=d.templating.getFileId(a),qq.preventDefault(b),d.log(qq.format("Detected valid file button click event on file '{}', ID: {}.",d.onGetName(f),f)),e(f),!1):void 0})}var c={},d={templating:null,log:function(){},onDeleteFile:function(){},onCancel:function(){},onRetry:function(){},onPause:function(){},onContinue:function(){},onGetName:function(){}},e={cancel:function(a){d.onCancel(a)},retry:function(a){d.onRetry(a)},deleteButton:function(a){d.onDeleteFile(a)},pause:function(a){d.onPause(a)},continueButton:function(a){d.onContinue(a)}};qq.extend(d,a),d.eventType="click",d.onHandled=b,d.attachTo=d.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(d,c))},qq.FilenameClickHandler=function(a){"use strict";function b(a,b){if(d.templating.isFileName(a)||d.templating.isEditIcon(a)){var e=d.templating.getFileId(a),f=d.onGetUploadStatus(e);f===qq.status.SUBMITTED&&(d.log(qq.format("Detected valid filename click event on file '{}', ID: {}.",d.onGetName(e),e)),qq.preventDefault(b),c.handleFilenameEdit(e,a,!0))}}var c={},d={templating:null,log:function(){},classes:{file:"qq-upload-file",editNameIcon:"qq-edit-filename-icon"},onGetUploadStatus:function(){},onGetName:function(){}};qq.extend(d,a),d.eventType="click",d.onHandled=b,qq.extend(this,new qq.FilenameEditHandler(d,c))
-},qq.FilenameInputFocusInHandler=function(a,b){"use strict";function c(a){if(d.templating.isEditInput(a)){var c=d.templating.getFileId(a),e=d.onGetUploadStatus(c);e===qq.status.SUBMITTED&&(d.log(qq.format("Detected valid filename input focus event on file '{}', ID: {}.",d.onGetName(c),c)),b.handleFilenameEdit(c,a))}}var d={templating:null,onGetUploadStatus:function(){},log:function(){}};b||(b={}),d.eventType="focusin",d.onHandled=c,qq.extend(d,a),qq.extend(this,new qq.FilenameEditHandler(d,b))},qq.FilenameInputFocusHandler=function(a){"use strict";a.eventType="focus",a.attachTo=null,qq.extend(this,new qq.FilenameInputFocusInHandler(a,{}))},qq.FilenameEditHandler=function(a,b){"use strict";function c(a){var b=h.onGetName(a),c=b.lastIndexOf(".");return c>0&&(b=b.substr(0,c)),b}function d(a){var b=h.onGetName(a);return qq.getExtension(b)}function e(a,b){var c,e=a.value;void 0!==e&&qq.trimStr(e).length>0&&(c=d(b),void 0!==c&&(e=e+"."+c),h.onSetName(b,e)),h.onEditingStatusChange(b,!1)}function f(a,c){b.getDisposeSupport().attach(a,"blur",function(){e(a,c)})}function g(a,c){b.getDisposeSupport().attach(a,"keyup",function(b){var d=b.keyCode||b.which;13===d&&e(a,c)})}var h={templating:null,log:function(){},onGetUploadStatus:function(){},onGetName:function(){},onSetName:function(){},onEditingStatusChange:function(){}};qq.extend(h,a),h.attachTo=h.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(h,b)),qq.extend(b,{handleFilenameEdit:function(a,b,d){var e=h.templating.getEditInput(a);h.onEditingStatusChange(a,!0),e.value=c(a),d&&e.focus(),f(e,a),g(e,a)}})};var CryptoJS=CryptoJS||function(a,b){var c={},d=c.lib={},e=d.Base=function(){function a(){}return{extend:function(b){a.prototype=this;var c=new a;return b&&c.mixIn(b),c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)}),c.init.prototype=c,c.$super=this,c},create:function(){var a=this.extend();return a.init.apply(a,arguments),a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),f=d.WordArray=e.extend({init:function(a,c){a=this.words=a||[],this.sigBytes=c!=b?c:4*a.length},toString:function(a){return(a||h).stringify(this)},concat:function(a){var b=this.words,c=a.words,d=this.sigBytes,e=a.sigBytes;if(this.clamp(),d%4)for(var f=0;e>f;f++){var g=255&c[f>>>2]>>>24-8*(f%4);b[d+f>>>2]|=g<<24-8*((d+f)%4)}else if(c.length>65535)for(var f=0;e>f;f+=4)b[d+f>>>2]=c[f>>>2];else b.push.apply(b,c);return this.sigBytes+=e,this},clamp:function(){var b=this.words,c=this.sigBytes;b[c>>>2]&=4294967295<<32-8*(c%4),b.length=a.ceil(c/4)},clone:function(){var a=e.clone.call(this);return a.words=this.words.slice(0),a},random:function(b){for(var c=[],d=0;b>d;d+=4)c.push(0|4294967296*a.random());return new f.init(c,b)}}),g=c.enc={},h=g.Hex={stringify:function(a){for(var b=a.words,c=a.sigBytes,d=[],e=0;c>e;e++){var f=255&b[e>>>2]>>>24-8*(e%4);d.push((f>>>4).toString(16)),d.push((15&f).toString(16))}return d.join("")},parse:function(a){for(var b=a.length,c=[],d=0;b>d;d+=2)c[d>>>3]|=parseInt(a.substr(d,2),16)<<24-4*(d%8);return new f.init(c,b/2)}},i=g.Latin1={stringify:function(a){for(var b=a.words,c=a.sigBytes,d=[],e=0;c>e;e++){var f=255&b[e>>>2]>>>24-8*(e%4);d.push(String.fromCharCode(f))}return d.join("")},parse:function(a){for(var b=a.length,c=[],d=0;b>d;d++)c[d>>>2]|=(255&a.charCodeAt(d))<<24-8*(d%4);return new f.init(c,b)}},j=g.Utf8={stringify:function(a){try{return decodeURIComponent(escape(i.stringify(a)))}catch(b){throw new Error("Malformed UTF-8 data")}},parse:function(a){return i.parse(unescape(encodeURIComponent(a)))}},k=d.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new f.init,this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=j.parse(a)),this._data.concat(a),this._nDataBytes+=a.sigBytes},_process:function(b){var c=this._data,d=c.words,e=c.sigBytes,g=this.blockSize,h=4*g,i=e/h;i=b?a.ceil(i):a.max((0|i)-this._minBufferSize,0);var j=i*g,k=a.min(4*j,e);if(j){for(var l=0;j>l;l+=g)this._doProcessBlock(d,l);var m=d.splice(0,j);c.sigBytes-=k}return new f.init(m,k)},clone:function(){var a=e.clone.call(this);return a._data=this._data.clone(),a},_minBufferSize:0});d.Hasher=k.extend({cfg:e.extend(),init:function(a){this.cfg=this.cfg.extend(a),this.reset()},reset:function(){k.reset.call(this),this._doReset()},update:function(a){return this._append(a),this._process(),this},finalize:function(a){a&&this._append(a);var b=this._doFinalize();return b},blockSize:16,_createHelper:function(a){return function(b,c){return new a.init(c).finalize(b)}},_createHmacHelper:function(a){return function(b,c){return new l.HMAC.init(a,c).finalize(b)}}});var l=c.algo={};return c}(Math);!function(){var a=CryptoJS,b=a.lib,c=b.WordArray,d=a.enc;d.Base64={stringify:function(a){var b=a.words,c=a.sigBytes,d=this._map;a.clamp();for(var e=[],f=0;c>f;f+=3)for(var g=255&b[f>>>2]>>>24-8*(f%4),h=255&b[f+1>>>2]>>>24-8*((f+1)%4),i=255&b[f+2>>>2]>>>24-8*((f+2)%4),j=g<<16|h<<8|i,k=0;4>k&&c>f+.75*k;k++)e.push(d.charAt(63&j>>>6*(3-k)));var l=d.charAt(64);if(l)for(;e.length%4;)e.push(l);return e.join("")},parse:function(a){var b=a.length,d=this._map,e=d.charAt(64);if(e){var f=a.indexOf(e);-1!=f&&(b=f)}for(var g=[],h=0,i=0;b>i;i++)if(i%4){var j=d.indexOf(a.charAt(i-1))<<2*(i%4),k=d.indexOf(a.charAt(i))>>>6-2*(i%4);g[h>>>2]|=(j|k)<<24-8*(h%4),h++}return c.create(g,h)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}(),function(){var a=CryptoJS,b=a.lib,c=b.Base,d=a.enc,e=d.Utf8,f=a.algo;f.HMAC=c.extend({init:function(a,b){a=this._hasher=new a.init,"string"==typeof b&&(b=e.parse(b));var c=a.blockSize,d=4*c;b.sigBytes>d&&(b=a.finalize(b)),b.clamp();for(var f=this._oKey=b.clone(),g=this._iKey=b.clone(),h=f.words,i=g.words,j=0;c>j;j++)h[j]^=1549556828,i[j]^=909522486;f.sigBytes=g.sigBytes=d,this.reset()},reset:function(){var a=this._hasher;a.reset(),a.update(this._iKey)},update:function(a){return this._hasher.update(a),this},finalize:function(a){var b=this._hasher,c=b.finalize(a);b.reset();var d=b.finalize(this._oKey.clone().concat(c));return d}})}(),function(){var a=CryptoJS,b=a.lib,c=b.WordArray,d=b.Hasher,e=a.algo,f=[],g=e.SHA1=d.extend({_doReset:function(){this._hash=new c.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(a,b){for(var c=this._hash.words,d=c[0],e=c[1],g=c[2],h=c[3],i=c[4],j=0;80>j;j++){if(16>j)f[j]=0|a[b+j];else{var k=f[j-3]^f[j-8]^f[j-14]^f[j-16];f[j]=k<<1|k>>>31}var l=(d<<5|d>>>27)+i+f[j];l+=20>j?(e&g|~e&h)+1518500249:40>j?(e^g^h)+1859775393:60>j?(e&g|e&h|g&h)-1894007588:(e^g^h)-899497514,i=h,h=g,g=e<<30|e>>>2,e=d,d=l}c[0]=0|c[0]+d,c[1]=0|c[1]+e,c[2]=0|c[2]+g,c[3]=0|c[3]+h,c[4]=0|c[4]+i},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,d=8*a.sigBytes;return b[d>>>5]|=128<<24-d%32,b[(d+64>>>9<<4)+14]=Math.floor(c/4294967296),b[(d+64>>>9<<4)+15]=c,a.sigBytes=4*b.length,this._process(),this._hash},clone:function(){var a=d.clone.call(this);return a._hash=this._hash.clone(),a}});a.SHA1=d._createHelper(g),a.HmacSHA1=d._createHmacHelper(g)}();
-/*! 2015-06-09 */
+var qq=function(a){"use strict";return{hide:function(){return a.style.display="none",this},attach:function(b,c){return a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent("on"+b,c),function(){qq(a).detach(b,c)}},detach:function(b,c){return a.removeEventListener?a.removeEventListener(b,c,!1):a.attachEvent&&a.detachEvent("on"+b,c),this},contains:function(b){return b?a===b?!0:a.contains?a.contains(b):!!(8&b.compareDocumentPosition(a)):!1},insertBefore:function(b){return b.parentNode.insertBefore(a,b),this},remove:function(){return a.parentNode.removeChild(a),this},css:function(b){if(null==a.style)throw new qq.Error("Can't apply style to node as it is not on the HTMLElement prototype chain!");return null!=b.opacity&&"string"!=typeof a.style.opacity&&"undefined"!=typeof a.filters&&(b.filter="alpha(opacity="+Math.round(100*b.opacity)+")"),qq.extend(a.style,b),this},hasClass:function(b,c){var d=new RegExp("(^| )"+b+"( |$)");return d.test(a.className)||!(!c||!d.test(a.parentNode.className))},addClass:function(b){return qq(a).hasClass(b)||(a.className+=" "+b),this},removeClass:function(b){var c=new RegExp("(^| )"+b+"( |$)");return a.className=a.className.replace(c," ").replace(/^\s+|\s+$/g,""),this},getByClass:function(b){var c,d=[];return a.querySelectorAll?a.querySelectorAll("."+b):(c=a.getElementsByTagName("*"),qq.each(c,function(a,c){qq(c).hasClass(b)&&d.push(c)}),d)},children:function(){for(var b=[],c=a.firstChild;c;)1===c.nodeType&&b.push(c),c=c.nextSibling;return b},setText:function(b){return a.innerText=b,a.textContent=b,this},clearText:function(){return qq(a).setText("")},hasAttribute:function(b){var c;return a.hasAttribute?a.hasAttribute(b)?null==/^false$/i.exec(a.getAttribute(b)):!1:(c=a[b],void 0===c?!1:null==/^false$/i.exec(c))}}};!function(){"use strict";qq.canvasToBlob=function(a,b,c){return qq.dataUriToBlob(a.toDataURL(b,c))},qq.dataUriToBlob=function(a){var b,c,d,e,f=function(a,b){var c=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,d=c&&new c;return d?(d.append(a),d.getBlob(b)):new Blob([a],{type:b})};return c=a.split(",")[0].indexOf("base64")>=0?atob(a.split(",")[1]):decodeURI(a.split(",")[1]),e=a.split(",")[0].split(":")[1].split(";")[0],b=new ArrayBuffer(c.length),d=new Uint8Array(b),qq.each(c,function(a,b){d[a]=b.charCodeAt(0)}),f(b,e)},qq.log=function(a,b){window.console&&(b&&"info"!==b?window.console[b]?window.console[b](a):window.console.log("<"+b+"> "+a):window.console.log(a))},qq.isObject=function(a){return a&&!a.nodeType&&"[object Object]"===Object.prototype.toString.call(a)},qq.isFunction=function(a){return"function"==typeof a},qq.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)||a&&window.ArrayBuffer&&a.buffer&&a.buffer.constructor===ArrayBuffer},qq.isItemList=function(a){return"[object DataTransferItemList]"===Object.prototype.toString.call(a)},qq.isNodeList=function(a){return"[object NodeList]"===Object.prototype.toString.call(a)||a.item&&a.namedItem},qq.isString=function(a){return"[object String]"===Object.prototype.toString.call(a)},qq.trimStr=function(a){return String.prototype.trim?a.trim():a.replace(/^\s+|\s+$/g,"")},qq.format=function(a){var b=Array.prototype.slice.call(arguments,1),c=a,d=c.indexOf("{}");return qq.each(b,function(a,b){var e=c.substring(0,d),f=c.substring(d+2);return c=e+b+f,d=c.indexOf("{}",d+b.length),0>d?!1:void 0}),c},qq.isFile=function(a){return window.File&&"[object File]"===Object.prototype.toString.call(a)},qq.isFileList=function(a){return window.FileList&&"[object FileList]"===Object.prototype.toString.call(a)},qq.isFileOrInput=function(a){return qq.isFile(a)||qq.isInput(a)},qq.isInput=function(a,b){var c=function(a){var c=a.toLowerCase();return b?"file"!==c:"file"===c};return window.HTMLInputElement&&"[object HTMLInputElement]"===Object.prototype.toString.call(a)&&a.type&&c(a.type)?!0:a.tagName&&"input"===a.tagName.toLowerCase()&&a.type&&c(a.type)?!0:!1},qq.isBlob=function(a){return window.Blob&&"[object Blob]"===Object.prototype.toString.call(a)?!0:void 0},qq.isXhrUploadSupported=function(){var a=document.createElement("input");return a.type="file",void 0!==a.multiple&&"undefined"!=typeof File&&"undefined"!=typeof FormData&&"undefined"!=typeof qq.createXhrInstance().upload},qq.createXhrInstance=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(a){return qq.log("Neither XHR or ActiveX are supported!","error"),null}},qq.isFolderDropSupported=function(a){return a.items&&a.items.length>0&&a.items[0].webkitGetAsEntry},qq.isFileChunkingSupported=function(){return!qq.androidStock()&&qq.isXhrUploadSupported()&&(void 0!==File.prototype.slice||void 0!==File.prototype.webkitSlice||void 0!==File.prototype.mozSlice)},qq.sliceBlob=function(a,b,c){var d=a.slice||a.mozSlice||a.webkitSlice;return d.call(a,b,c)},qq.arrayBufferToHex=function(a){var b="",c=new Uint8Array(a);return qq.each(c,function(a,c){var d=c.toString(16);d.length<2&&(d="0"+d),b+=d}),b},qq.readBlobToHex=function(a,b,c){var d=qq.sliceBlob(a,b,b+c),e=new FileReader,f=new qq.Promise;return e.onload=function(){f.success(qq.arrayBufferToHex(e.result))},e.onerror=f.failure,e.readAsArrayBuffer(d),f},qq.extend=function(a,b,c){return qq.each(b,function(b,d){c&&qq.isObject(d)?(void 0===a[b]&&(a[b]={}),qq.extend(a[b],d,!0)):a[b]=d}),a},qq.override=function(a,b){var c={},d=b(c);return qq.each(d,function(b,d){void 0!==a[b]&&(c[b]=a[b]),a[b]=d}),a},qq.indexOf=function(a,b,c){if(a.indexOf)return a.indexOf(b,c);c=c||0;var d=a.length;for(0>c&&(c+=d);d>c;c+=1)if(a.hasOwnProperty(c)&&a[c]===b)return c;return-1},qq.getUniqueId=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=0|16*Math.random(),c="x"==a?b:8|3&b;return c.toString(16)})},qq.ie=function(){return-1!==navigator.userAgent.indexOf("MSIE")||-1!==navigator.userAgent.indexOf("Trident")},qq.ie7=function(){return-1!==navigator.userAgent.indexOf("MSIE 7")},qq.ie8=function(){return-1!==navigator.userAgent.indexOf("MSIE 8")},qq.ie10=function(){return-1!==navigator.userAgent.indexOf("MSIE 10")},qq.ie11=function(){return qq.ie()&&-1!==navigator.userAgent.indexOf("rv:11")},qq.safari=function(){return void 0!==navigator.vendor&&-1!==navigator.vendor.indexOf("Apple")},qq.chrome=function(){return void 0!==navigator.vendor&&-1!==navigator.vendor.indexOf("Google")},qq.opera=function(){return void 0!==navigator.vendor&&-1!==navigator.vendor.indexOf("Opera")},qq.firefox=function(){return!qq.ie11()&&-1!==navigator.userAgent.indexOf("Mozilla")&&void 0!==navigator.vendor&&""===navigator.vendor},qq.windows=function(){return"Win32"===navigator.platform},qq.android=function(){return-1!==navigator.userAgent.toLowerCase().indexOf("android")},qq.androidStock=function(){return qq.android()&&navigator.userAgent.toLowerCase().indexOf("chrome")<0},qq.ios6=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf(" OS 6_")},qq.ios7=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf(" OS 7_")},qq.ios8=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf(" OS 8_")},qq.ios800=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf(" OS 8_0 ")},qq.ios=function(){return-1!==navigator.userAgent.indexOf("iPad")||-1!==navigator.userAgent.indexOf("iPod")||-1!==navigator.userAgent.indexOf("iPhone")},qq.iosChrome=function(){return qq.ios()&&-1!==navigator.userAgent.indexOf("CriOS")},qq.iosSafari=function(){return qq.ios()&&!qq.iosChrome()&&-1!==navigator.userAgent.indexOf("Safari")},qq.iosSafariWebView=function(){return qq.ios()&&!qq.iosChrome()&&!qq.iosSafari()},qq.preventDefault=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},qq.toElement=function(){var a=document.createElement("div");return function(b){a.innerHTML=b;var c=a.firstChild;return a.removeChild(c),c}}(),qq.each=function(a,b){var c,d;if(a)if(window.Storage&&a.constructor===window.Storage)for(c=0;c0?a.substr(b,a.length-b):void 0},qq.getFilename=function(a){return qq.isInput(a)?a.value.replace(/.*(\/|\\)/,""):qq.isFile(a)&&null!==a.fileName&&void 0!==a.fileName?a.fileName:a.name},qq.DisposeSupport=function(){var a=[];return{dispose:function(){var b;do b=a.shift(),b&&b();while(b)},attach:function(){var a=arguments;this.addDisposer(qq(a[0]).attach.apply(this,Array.prototype.slice.call(arguments,1)))},addDisposer:function(b){a.push(b)}}}}(),function(){"use strict";qq.Error=function(a){this.message="[Fine Uploader "+qq.version+"] "+a},qq.Error.prototype=new Error}(),qq.version="5.3.0",qq.supportedFeatures=function(){"use strict";function a(){var a,b=!0;try{a=document.createElement("input"),a.type="file",qq(a).hide(),a.disabled&&(b=!1)}catch(c){b=!1}return b}function b(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[2][1-9]|Chrome\/[3-9][0-9]/)}function c(){return(qq.chrome()||qq.opera())&&void 0!==navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/)}function d(){if(window.XMLHttpRequest){var a=qq.createXhrInstance();return void 0!==a.withCredentials}return!1}function e(){return void 0!==window.XDomainRequest}function f(){return d()?!0:e()}function g(){return void 0!==document.createElement("input").webkitdirectory}function h(){try{return!!window.localStorage}catch(a){return!1}}function i(){var a=document.createElement("span");return("draggable"in a||"ondragstart"in a&&"ondrop"in a)&&!qq.android()&&!qq.ios()}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x;return j=a(),m=j&&qq.isXhrUploadSupported(),k=m&&!qq.androidStock(),l=m&&i(),n=l&&b(),o=m&&qq.isFileChunkingSupported(),p=m&&o&&h(),q=m&&c(),r=j&&(void 0!==window.postMessage||m),t=d(),s=e(),u=f(),v=g(),w=m&&void 0!==window.FileReader,x=function(){return m?!qq.androidStock()&&!qq.iosChrome():!1}(),{ajaxUploading:m,blobUploading:k,canDetermineSize:m,chunking:o,deleteFileCors:u,deleteFileCorsXdr:s,deleteFileCorsXhr:t,dialogElement:!!window.HTMLDialogElement,fileDrop:l,folderDrop:n,folderSelection:v,imagePreviews:w,imageValidation:w,itemSizeValidation:m,pause:o,progressBar:x,resume:p,scaling:w&&k,tiffPreviews:qq.safari(),unlimitedScaledImageSize:!qq.ios(),uploading:j,uploadCors:r,uploadCustomHeaders:m,uploadNonMultipart:m,uploadViaPaste:q}}(),qq.isGenericPromise=function(a){"use strict";return!!(a&&a.then&&qq.isFunction(a.then))},qq.Promise=function(){"use strict";var a,b,c=[],d=[],e=[],f=0;qq.extend(this,{then:function(e,g){return 0===f?(e&&c.push(e),g&&d.push(g)):-1===f?g&&g.apply(null,b):e&&e.apply(null,a),this},done:function(c){return 0===f?e.push(c):c.apply(null,void 0===b?a:b),this},success:function(){return f=1,a=arguments,c.length&&qq.each(c,function(b,c){c.apply(null,a)}),e.length&&qq.each(e,function(b,c){c.apply(null,a)}),this},failure:function(){return f=-1,b=arguments,d.length&&qq.each(d,function(a,c){c.apply(null,b)}),e.length&&qq.each(e,function(a,c){c.apply(null,b)}),this}})},qq.BlobProxy=function(a,b){"use strict";qq.extend(this,{referenceBlob:a,create:function(){return b(a)}})},qq.UploadButton=function(a){"use strict";function b(){var a=document.createElement("input");return a.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME,d),a.setAttribute("title","file input"),e.setMultiple(g.multiple,a),g.folders&&qq.supportedFeatures.folderSelection&&a.setAttribute("webkitdirectory",""),g.acceptFiles&&a.setAttribute("accept",g.acceptFiles),a.setAttribute("type","file"),a.setAttribute("name",g.name),qq(a).css({position:"absolute",right:0,top:0,fontFamily:"Arial",fontSize:qq.ie()&&!qq.ie8()?"3500px":"118px",margin:0,padding:0,cursor:"pointer",opacity:0}),!qq.ie7()&&qq(a).css({height:"100%"}),g.element.appendChild(a),f.attach(a,"change",function(){g.onChange(a)}),f.attach(a,"mouseover",function(){qq(g.element).addClass(g.hoverClass)}),f.attach(a,"mouseout",function(){qq(g.element).removeClass(g.hoverClass)}),f.attach(a,"focus",function(){qq(g.element).addClass(g.focusClass)}),f.attach(a,"blur",function(){qq(g.element).removeClass(g.focusClass)}),a}var c,d,e=this,f=new qq.DisposeSupport,g={element:null,multiple:!1,acceptFiles:null,folders:!1,name:"qqfile",onChange:function(){},ios8BrowserCrashWorkaround:!1,hoverClass:"qq-upload-button-hover",focusClass:"qq-upload-button-focus"};qq.extend(g,a),d=qq.getUniqueId(),qq(g.element).css({position:"relative",overflow:"hidden",direction:"ltr"}),qq.extend(this,{getInput:function(){return c},getButtonId:function(){return d},setMultiple:function(a,b){var c=b||this.getInput();g.ios8BrowserCrashWorkaround&&qq.ios8()&&(qq.iosChrome()||qq.iosSafariWebView())?c.setAttribute("multiple",""):a?c.setAttribute("multiple",""):c.removeAttribute("multiple")},setAcceptFiles:function(a){a!==g.acceptFiles&&c.setAttribute("accept",a)},reset:function(){c.parentNode&&qq(c).remove(),qq(g.element).removeClass(g.focusClass),c=null,c=b()}}),c=b()},qq.UploadButton.BUTTON_ID_ATTR_NAME="qq-button-id",qq.UploadData=function(a){"use strict";function b(a){if(qq.isArray(a)){var b=[];return qq.each(a,function(a,c){b.push(e[c])}),b}return e[a]}function c(a){if(qq.isArray(a)){var b=[];return qq.each(a,function(a,c){b.push(e[f[c]])}),b}return e[f[a]]}function d(a){var b=[],c=[].concat(a);return qq.each(c,function(a,c){var d=g[c];void 0!==d&&qq.each(d,function(a,c){b.push(e[c])})}),b}var e=[],f={},g={},h={},i={};qq.extend(this,{addFile:function(b){var c=b.status||qq.status.SUBMITTING,d=e.push({name:b.name,originalName:b.name,uuid:b.uuid,size:null==b.size?-1:b.size,status:c})-1;return b.batchId&&(e[d].batchId=b.batchId,void 0===i[b.batchId]&&(i[b.batchId]=[]),i[b.batchId].push(d)),b.proxyGroupId&&(e[d].proxyGroupId=b.proxyGroupId,void 0===h[b.proxyGroupId]&&(h[b.proxyGroupId]=[]),h[b.proxyGroupId].push(d)),e[d].id=d,f[b.uuid]=d,void 0===g[c]&&(g[c]=[]),g[c].push(d),a.onStatusChange(d,null,c),d},retrieve:function(a){return qq.isObject(a)&&e.length?void 0!==a.id?b(a.id):void 0!==a.uuid?c(a.uuid):a.status?d(a.status):void 0:qq.extend([],e,!0)},reset:function(){e=[],f={},g={},i={}},setStatus:function(b,c){var d=e[b].status,f=qq.indexOf(g[d],b);g[d].splice(f,1),e[b].status=c,void 0===g[c]&&(g[c]=[]),g[c].push(b),a.onStatusChange(b,d,c)},uuidChanged:function(a,b){var c=e[a].uuid;e[a].uuid=b,f[b]=a,delete f[c]},updateName:function(a,b){e[a].name=b},updateSize:function(a,b){e[a].size=b},setParentId:function(a,b){e[a].parentId=b},getIdsInProxyGroup:function(a){var b=e[a].proxyGroupId;return b?h[b]:[]},getIdsInBatch:function(a){var b=e[a].batchId;return i[b]}})},qq.status={SUBMITTING:"submitting",SUBMITTED:"submitted",REJECTED:"rejected",QUEUED:"queued",CANCELED:"canceled",PAUSED:"paused",UPLOADING:"uploading",UPLOAD_RETRYING:"retrying upload",UPLOAD_SUCCESSFUL:"upload successful",UPLOAD_FAILED:"upload failed",DELETE_FAILED:"delete failed",DELETING:"deleting",DELETED:"deleted"},function(){"use strict";qq.basePublicApi={addBlobs:function(a,b,c){this.addFiles(a,b,c)},addFiles:function(a,b,c){this._maybeHandleIos8SafariWorkaround();var d=0===this._storedIds.length?qq.getUniqueId():this._currentBatchId,e=qq.bind(function(a){this._handleNewFile({blob:a,name:this._options.blobs.defaultName},d,l)},this),f=qq.bind(function(a){this._handleNewFile(a,d,l)},this),g=qq.bind(function(a){var b=qq.canvasToBlob(a);this._handleNewFile({blob:b,name:this._options.blobs.defaultName+".png"},d,l)},this),h=qq.bind(function(a){var b=a.quality&&a.quality/100,c=qq.canvasToBlob(a.canvas,a.type,b);this._handleNewFile({blob:c,name:a.name},d,l)},this),i=qq.bind(function(a){if(qq.isInput(a)&&qq.supportedFeatures.ajaxUploading){var b=Array.prototype.slice.call(a.files),c=this;qq.each(b,function(a,b){c._handleNewFile(b,d,l)})}else this._handleNewFile(a,d,l)},this),j=function(){qq.isFileList(a)&&(a=Array.prototype.slice.call(a)),a=[].concat(a)},k=this,l=[];this._currentBatchId=d,a&&(j(),qq.each(a,function(a,b){qq.isFileOrInput(b)?i(b):qq.isBlob(b)?e(b):qq.isObject(b)?b.blob&&b.name?f(b):b.canvas&&b.name&&h(b):b.tagName&&"canvas"===b.tagName.toLowerCase()?g(b):k.log(b+" is not a valid file container! Ignoring!","warn")}),this.log("Received "+l.length+" files."),this._prepareItemsForUpload(l,b,c))},cancel:function(a){this._handler.cancel(a)},cancelAll:function(){var a=[],b=this;qq.extend(a,this._storedIds),qq.each(a,function(a,c){b.cancel(c)}),this._handler.cancelAll()},clearStoredFiles:function(){this._storedIds=[]},continueUpload:function(a){var b=this._uploadData.retrieve({id:a});return qq.supportedFeatures.pause&&this._options.chunking.enabled?b.status===qq.status.PAUSED?(this.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.",a,this.getName(a))),this._uploadFile(a),!0):(this.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.",a,this.getName(a)),"error"),!1):!1},deleteFile:function(a){return this._onSubmitDelete(a)},doesExist:function(a){return this._handler.isValid(a)},drawThumbnail:function(a,b,c,d){var e,f,g=new qq.Promise;return this._imageGenerator?(e=this._thumbnailUrls[a],f={scale:c>0,maxSize:c>0?c:null},!d&&qq.supportedFeatures.imagePreviews&&(e=this.getFile(a)),null==e?g.failure({container:b,error:"File or URL not found."}):this._imageGenerator.generate(e,b,f).then(function(a){g.success(a)},function(a,b){g.failure({container:a,error:b||"Problem generating thumbnail"})})):g.failure({container:b,error:"Missing image generator module"}),g},getButton:function(a){return this._getButton(this._buttonIdsForFileIds[a])},getEndpoint:function(a){return this._endpointStore.get(a)},getFile:function(a){return this._handler.getFile(a)||null},getInProgress:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED]}).length},getName:function(a){return this._uploadData.retrieve({id:a}).name},getParentId:function(a){var b=this.getUploads({id:a}),c=null;return b&&void 0!==b.parentId&&(c=b.parentId),c},getResumableFilesData:function(){return this._handler.getResumableFilesData()},getSize:function(a){return this._uploadData.retrieve({id:a}).size},getNetUploads:function(){return this._netUploaded},getRemainingAllowedItems:function(){var a=this._currentItemLimit;return a>0?a-this._netUploadedOrQueued:null},getUploads:function(a){return this._uploadData.retrieve(a)},getUuid:function(a){return this._uploadData.retrieve({id:a}).uuid},log:function(a,b){!this._options.debug||b&&"info"!==b?b&&"info"!==b&&qq.log("[Fine Uploader "+qq.version+"] "+a,b):qq.log("[Fine Uploader "+qq.version+"] "+a)},pauseUpload:function(a){var b=this._uploadData.retrieve({id:a});if(!qq.supportedFeatures.pause||!this._options.chunking.enabled)return!1;if(qq.indexOf([qq.status.UPLOADING,qq.status.UPLOAD_RETRYING],b.status)>=0){if(this._handler.pause(a))return this._uploadData.setStatus(a,qq.status.PAUSED),!0;this.log(qq.format("Unable to pause file ID {} ({}).",a,this.getName(a)),"error")}else this.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.",a,this.getName(a)),"error");return!1},reset:function(){this.log("Resetting uploader..."),this._handler.reset(),this._storedIds=[],this._autoRetries=[],this._retryTimeouts=[],this._preventRetries=[],this._thumbnailUrls=[],qq.each(this._buttons,function(a,b){b.reset()}),this._paramsStore.reset(),this._endpointStore.reset(),this._netUploadedOrQueued=0,this._netUploaded=0,this._uploadData.reset(),this._buttonIdsForFileIds=[],this._pasteHandler&&this._pasteHandler.reset(),this._options.session.refreshOnReset&&this._refreshSessionData(),this._succeededSinceLastAllComplete=[],this._failedSinceLastAllComplete=[],this._totalProgress&&this._totalProgress.reset()},retry:function(a){return this._manualRetry(a)},scaleImage:function(a,b){var c=this;return qq.Scaler.prototype.scaleImage(a,b,{log:qq.bind(c.log,c),getFile:qq.bind(c.getFile,c),uploadData:c._uploadData})},setCustomHeaders:function(a,b){this._customHeadersStore.set(a,b)},setDeleteFileCustomHeaders:function(a,b){this._deleteFileCustomHeadersStore.set(a,b)},setDeleteFileEndpoint:function(a,b){this._deleteFileEndpointStore.set(a,b)},setDeleteFileParams:function(a,b){this._deleteFileParamsStore.set(a,b)},setEndpoint:function(a,b){this._endpointStore.set(a,b)},setForm:function(a){this._updateFormSupportAndParams(a)},setItemLimit:function(a){this._currentItemLimit=a},setName:function(a,b){this._uploadData.updateName(a,b)},setParams:function(a,b){this._paramsStore.set(a,b)},setUuid:function(a,b){return this._uploadData.uuidChanged(a,b)},uploadStoredFiles:function(){0===this._storedIds.length?this._itemError("noFilesError"):this._uploadStoredFiles()}},qq.basePrivateApi={_addCannedFile:function(a){var b=this._uploadData.addFile({uuid:a.uuid,name:a.name,size:a.size,status:qq.status.UPLOAD_SUCCESSFUL});return a.deleteFileEndpoint&&this.setDeleteFileEndpoint(a.deleteFileEndpoint,b),a.deleteFileParams&&this.setDeleteFileParams(a.deleteFileParams,b),a.thumbnailUrl&&(this._thumbnailUrls[b]=a.thumbnailUrl),this._netUploaded++,this._netUploadedOrQueued++,b},_annotateWithButtonId:function(a,b){qq.isFile(a)&&(a.qqButtonId=this._getButtonId(b))},_batchError:function(a){this._options.callbacks.onError(null,null,a,void 0)},_createDeleteHandler:function(){var a=this;return new qq.DeleteFileAjaxRequester({method:this._options.deleteFile.method.toUpperCase(),maxConnections:this._options.maxConnections,uuidParamName:this._options.request.uuidName,customHeaders:this._deleteFileCustomHeadersStore,paramsStore:this._deleteFileParamsStore,endpointStore:this._deleteFileEndpointStore,cors:this._options.cors,log:qq.bind(a.log,a),onDelete:function(b){a._onDelete(b),a._options.callbacks.onDelete(b)},onDeleteComplete:function(b,c,d){a._onDeleteComplete(b,c,d),a._options.callbacks.onDeleteComplete(b,c,d)}})},_createPasteHandler:function(){var a=this;return new qq.PasteSupport({targetElement:this._options.paste.targetElement,callbacks:{log:qq.bind(a.log,a),pasteReceived:function(b){a._handleCheckedCallback({name:"onPasteReceived",callback:qq.bind(a._options.callbacks.onPasteReceived,a,b),onSuccess:qq.bind(a._handlePasteSuccess,a,b),identifier:"pasted image"})}}})},_createStore:function(a,b){var c={},d=a,e={},f=b,g=function(a){return qq.isObject(a)?qq.extend({},a):a},h=function(){return qq.isFunction(f)?f():f},i=function(a,b){f&&qq.isObject(b)&&qq.extend(b,h()),e[a]&&qq.extend(b,e[a])};return{set:function(a,b){null==b?(c={},d=g(a)):c[b]=g(a)},get:function(a){var b;return b=null!=a&&c[a]?c[a]:g(d),i(a,b),g(b)},addReadOnly:function(a,b){qq.isObject(c)&&(null===a?qq.isFunction(b)?f=b:(f=f||{},qq.extend(f,b)):(e[a]=e[a]||{},qq.extend(e[a],b)))},remove:function(a){return delete c[a]},reset:function(){c={},e={},d=a}}},_createUploadDataTracker:function(){var a=this;return new qq.UploadData({getName:function(b){return a.getName(b)},getUuid:function(b){return a.getUuid(b)},getSize:function(b){return a.getSize(b)},onStatusChange:function(b,c,d){a._onUploadStatusChange(b,c,d),a._options.callbacks.onStatusChange(b,c,d),a._maybeAllComplete(b,d),a._totalProgress&&setTimeout(function(){a._totalProgress.onStatusChange(b,c,d)},0)}})},_createUploadButton:function(a){function b(){return qq.supportedFeatures.ajaxUploading?d._options.workarounds.iosEmptyVideos&&qq.ios()&&!qq.ios6()&&d._isAllowedExtension(f,".mov")?!1:void 0===a.multiple?d._options.multiple:a.multiple:!1}var c,d=this,e=a.accept||this._options.validation.acceptFiles,f=a.allowedExtensions||this._options.validation.allowedExtensions;return c=new qq.UploadButton({element:a.element,folders:a.folders,name:this._options.request.inputName,multiple:b(),acceptFiles:e,onChange:function(a){d._onInputChange(a)},hoverClass:this._options.classes.buttonHover,focusClass:this._options.classes.buttonFocus,ios8BrowserCrashWorkaround:this._options.workarounds.ios8BrowserCrash}),this._disposeSupport.addDisposer(function(){c.dispose()}),d._buttons.push(c),c},_createUploadHandler:function(a,b){var c=this,d={},e={debug:this._options.debug,maxConnections:this._options.maxConnections,cors:this._options.cors,paramsStore:this._paramsStore,endpointStore:this._endpointStore,chunking:this._options.chunking,resume:this._options.resume,blobs:this._options.blobs,log:qq.bind(c.log,c),preventRetryParam:this._options.retry.preventRetryResponseProperty,onProgress:function(a,b,e,f){0>e||0>f||(d[a]?(d[a].loaded!==e||d[a].total!==f)&&(c._onProgress(a,b,e,f),c._options.callbacks.onProgress(a,b,e,f)):(c._onProgress(a,b,e,f),c._options.callbacks.onProgress(a,b,e,f)),d[a]={loaded:e,total:f})},onComplete:function(a,b,e,f){delete d[a];var g,h=c.getUploads({id:a}).status;h!==qq.status.UPLOAD_SUCCESSFUL&&h!==qq.status.UPLOAD_FAILED&&(g=c._onComplete(a,b,e,f),g instanceof qq.Promise?g.done(function(){c._options.callbacks.onComplete(a,b,e,f)}):c._options.callbacks.onComplete(a,b,e,f))},onCancel:function(a,b,d){var e=new qq.Promise;return c._handleCheckedCallback({name:"onCancel",callback:qq.bind(c._options.callbacks.onCancel,c,a,b),onFailure:e.failure,onSuccess:function(){d.then(function(){c._onCancel(a,b)}),e.success()},identifier:a}),e},onUploadPrep:qq.bind(this._onUploadPrep,this),onUpload:function(a,b){c._onUpload(a,b),c._options.callbacks.onUpload(a,b)},onUploadChunk:function(a,b,d){c._onUploadChunk(a,d),c._options.callbacks.onUploadChunk(a,b,d)},onUploadChunkSuccess:function(){c._options.callbacks.onUploadChunkSuccess.apply(c,arguments)},onResume:function(a,b,d){return c._options.callbacks.onResume(a,b,d)},onAutoRetry:function(){return c._onAutoRetry.apply(c,arguments)},onUuidChanged:function(a,b){c.log("Server requested UUID change from '"+c.getUuid(a)+"' to '"+b+"'"),c.setUuid(a,b)},getName:qq.bind(c.getName,c),getUuid:qq.bind(c.getUuid,c),getSize:qq.bind(c.getSize,c),setSize:qq.bind(c._setSize,c),getDataByUuid:function(a){return c.getUploads({uuid:a})},isQueued:function(a){var b=c.getUploads({id:a}).status;return b===qq.status.QUEUED||b===qq.status.SUBMITTED||b===qq.status.UPLOAD_RETRYING||b===qq.status.PAUSED},getIdsInProxyGroup:c._uploadData.getIdsInProxyGroup,getIdsInBatch:c._uploadData.getIdsInBatch};return qq.each(this._options.request,function(a,b){e[a]=b}),e.customHeaders=this._customHeadersStore,a&&qq.each(a,function(a,b){e[a]=b}),new qq.UploadHandlerController(e,b)},_fileOrBlobRejected:function(a){this._netUploadedOrQueued--,this._uploadData.setStatus(a,qq.status.REJECTED)},_formatSize:function(a){var b=-1;do a/=1e3,b++;while(a>999);return Math.max(a,.1).toFixed(1)+this._options.text.sizeSymbols[b]},_generateExtraButtonSpecs:function(){var a=this;this._extraButtonSpecs={},qq.each(this._options.extraButtons,function(b,c){var d=c.multiple,e=qq.extend({},a._options.validation,!0),f=qq.extend({},c);void 0===d&&(d=a._options.multiple),f.validation&&qq.extend(e,c.validation,!0),qq.extend(f,{multiple:d,validation:e},!0),a._initExtraButton(f)})},_getButton:function(a){var b=this._extraButtonSpecs[a];return b?b.element:a===this._defaultButtonId?this._options.button:void 0},_getButtonId:function(a){var b,c,d=a;if(d instanceof qq.BlobProxy&&(d=d.referenceBlob),d&&!qq.isBlob(d)){if(qq.isFile(d))return d.qqButtonId;if("input"===d.tagName.toLowerCase()&&"file"===d.type.toLowerCase())return d.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME);if(b=d.getElementsByTagName("input"),qq.each(b,function(a,b){return"file"===b.getAttribute("type")?(c=b,!1):void 0}),c)return c.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME)}},_getNotFinished:function(){return this._uploadData.retrieve({status:[qq.status.UPLOADING,qq.status.UPLOAD_RETRYING,qq.status.QUEUED,qq.status.SUBMITTING,qq.status.SUBMITTED,qq.status.PAUSED]}).length},_getValidationBase:function(a){var b=this._extraButtonSpecs[a];return b?b.validation:this._options.validation},_getValidationDescriptor:function(a){return a.file instanceof qq.BlobProxy?{name:qq.getFilename(a.file.referenceBlob),size:a.file.referenceBlob.size}:{name:this.getUploads({id:a.id}).name,size:this.getUploads({id:a.id}).size}},_getValidationDescriptors:function(a){var b=this,c=[];return qq.each(a,function(a,d){c.push(b._getValidationDescriptor(d))}),c},_handleCameraAccess:function(){if(this._options.camera.ios&&qq.ios()){var a="image/*;capture=camera",b=this._options.camera.button,c=b?this._getButtonId(b):this._defaultButtonId,d=this._options;c&&c!==this._defaultButtonId&&(d=this._extraButtonSpecs[c]),d.multiple=!1,null===d.validation.acceptFiles?d.validation.acceptFiles=a:d.validation.acceptFiles+=","+a,qq.each(this._buttons,function(a,b){return b.getButtonId()===c?(b.setMultiple(d.multiple),b.setAcceptFiles(d.acceptFiles),!1):void 0})}},_handleCheckedCallback:function(a){var b=this,c=a.callback();return qq.isGenericPromise(c)?(this.log(a.name+" - waiting for "+a.name+" promise to be fulfilled for "+a.identifier),c.then(function(c){b.log(a.name+" promise success for "+a.identifier),a.onSuccess(c)},function(){a.onFailure?(b.log(a.name+" promise failure for "+a.identifier),a.onFailure()):b.log(a.name+" promise failure for "+a.identifier)})):(c!==!1?a.onSuccess(c):a.onFailure?(this.log(a.name+" - return value was 'false' for "+a.identifier+". Invoking failure callback."),a.onFailure()):this.log(a.name+" - return value was 'false' for "+a.identifier+". Will not proceed."),c)},_handleNewFile:function(a,b,c){var d=this,e=qq.getUniqueId(),f=-1,g=qq.getFilename(a),h=a.blob||a,i=this._customNewFileHandler?this._customNewFileHandler:qq.bind(d._handleNewFileGeneric,d);!qq.isInput(h)&&h.size>=0&&(f=h.size),i(h,g,e,f,c,b,this._options.request.uuidName,{uploadData:d._uploadData,paramsStore:d._paramsStore,addFileToHandler:function(a,b){d._handler.add(a,b),d._netUploadedOrQueued++,d._trackButton(a)}})},_handleNewFileGeneric:function(a,b,c,d,e,f){var g=this._uploadData.addFile({uuid:c,name:b,size:d,batchId:f});this._handler.add(g,a),this._trackButton(g),this._netUploadedOrQueued++,e.push({id:g,file:a})},_handlePasteSuccess:function(a,b){var c=a.type.split("/")[1],d=b;null==d&&(d=this._options.paste.defaultName),d+="."+c,this.addFiles({name:d,blob:a})},_initExtraButton:function(a){var b=this._createUploadButton({element:a.element,multiple:a.multiple,accept:a.validation.acceptFiles,folders:a.folders,allowedExtensions:a.validation.allowedExtensions});this._extraButtonSpecs[b.getButtonId()]=a},_initFormSupportAndParams:function(){this._formSupport=qq.FormSupport&&new qq.FormSupport(this._options.form,qq.bind(this.uploadStoredFiles,this),qq.bind(this.log,this)),this._formSupport&&this._formSupport.attachedToForm?(this._paramsStore=this._createStore(this._options.request.params,this._formSupport.getFormInputsAsObject),this._options.autoUpload=this._formSupport.newAutoUpload,this._formSupport.newEndpoint&&(this._options.request.endpoint=this._formSupport.newEndpoint)):this._paramsStore=this._createStore(this._options.request.params)
+},_isDeletePossible:function(){return qq.DeleteFileAjaxRequester&&this._options.deleteFile.enabled?this._options.cors.expected?qq.supportedFeatures.deleteFileCorsXhr?!0:qq.supportedFeatures.deleteFileCorsXdr&&this._options.cors.allowXdr?!0:!1:!0:!1},_isAllowedExtension:function(a,b){var c=!1;return a.length?(qq.each(a,function(a,d){if(qq.isString(d)){var e=new RegExp("\\."+d+"$","i");if(null!=b.match(e))return c=!0,!1}}),c):!0},_itemError:function(a,b,c){function d(a,b){g=g.replace(a,b)}var e,f,g=this._options.messages[a],h=[],i=[].concat(b),j=i[0],k=this._getButtonId(c),l=this._getValidationBase(k);return qq.each(l.allowedExtensions,function(a,b){qq.isString(b)&&h.push(b)}),e=h.join(", ").toLowerCase(),d("{file}",this._options.formatFileName(j)),d("{extensions}",e),d("{sizeLimit}",this._formatSize(l.sizeLimit)),d("{minSizeLimit}",this._formatSize(l.minSizeLimit)),f=g.match(/(\{\w+\})/g),null!==f&&qq.each(f,function(a,b){d(b,i[a])}),this._options.callbacks.onError(null,j,g,void 0),g},_manualRetry:function(a,b){return this._onBeforeManualRetry(a)?(this._netUploadedOrQueued++,this._uploadData.setStatus(a,qq.status.UPLOAD_RETRYING),b?b(a):this._handler.retry(a),!0):void 0},_maybeAllComplete:function(a,b){var c=this,d=this._getNotFinished();b===qq.status.UPLOAD_SUCCESSFUL?this._succeededSinceLastAllComplete.push(a):b===qq.status.UPLOAD_FAILED&&this._failedSinceLastAllComplete.push(a),0===d&&(this._succeededSinceLastAllComplete.length||this._failedSinceLastAllComplete.length)&&setTimeout(function(){c._onAllComplete(c._succeededSinceLastAllComplete,c._failedSinceLastAllComplete)},0)},_maybeHandleIos8SafariWorkaround:function(){var a=this;if(this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari())throw setTimeout(function(){window.alert(a._options.messages.unsupportedBrowserIos8Safari)},0),new qq.Error(this._options.messages.unsupportedBrowserIos8Safari)},_maybeParseAndSendUploadError:function(a,b,c,d){if(!c.success)if(d&&200!==d.status&&!c.error)this._options.callbacks.onError(a,b,"XHR returned response code "+d.status,d);else{var e=c.error?c.error:this._options.text.defaultResponseError;this._options.callbacks.onError(a,b,e,d)}},_maybeProcessNextItemAfterOnValidateCallback:function(a,b,c,d,e){var f=this;if(b.length>c)if(a||!this._options.validation.stopOnFirstInvalidFile)setTimeout(function(){var a=f._getValidationDescriptor(b[c]),g=f._getButtonId(b[c].file),h=f._getButton(g);f._handleCheckedCallback({name:"onValidate",callback:qq.bind(f._options.callbacks.onValidate,f,a,h),onSuccess:qq.bind(f._onValidateCallbackSuccess,f,b,c,d,e),onFailure:qq.bind(f._onValidateCallbackFailure,f,b,c,d,e),identifier:"Item '"+a.name+"', size: "+a.size})},0);else if(!a)for(;c0&&this._netUploadedOrQueued+1>c?(this._itemError("retryFailTooManyItems"),!1):(this.log("Retrying upload for '"+b+"' (id: "+a+")..."),!0)):(this.log("'"+a+"' is not a valid file ID","error"),!1)},_onCancel:function(a){this._netUploadedOrQueued--,clearTimeout(this._retryTimeouts[a]);var b=qq.indexOf(this._storedIds,a);!this._options.autoUpload&&b>=0&&this._storedIds.splice(b,1),this._uploadData.setStatus(a,qq.status.CANCELED)},_onComplete:function(a,b,c,d){return c.success?(c.thumbnailUrl&&(this._thumbnailUrls[a]=c.thumbnailUrl),this._netUploaded++,this._uploadData.setStatus(a,qq.status.UPLOAD_SUCCESSFUL)):(this._netUploadedOrQueued--,this._uploadData.setStatus(a,qq.status.UPLOAD_FAILED),c[this._options.retry.preventRetryResponseProperty]===!0&&(this._preventRetries[a]=!0)),this._maybeParseAndSendUploadError(a,b,c,d),c.success?!0:!1},_onDelete:function(a){this._uploadData.setStatus(a,qq.status.DELETING)},_onDeleteComplete:function(a,b,c){var d=this.getName(a);c?(this._uploadData.setStatus(a,qq.status.DELETE_FAILED),this.log("Delete request for '"+d+"' has failed.","error"),void 0===b.withCredentials?this._options.callbacks.onError(a,d,"Delete request failed",b):this._options.callbacks.onError(a,d,"Delete request failed with response code "+b.status,b)):(this._netUploadedOrQueued--,this._netUploaded--,this._handler.expunge(a),this._uploadData.setStatus(a,qq.status.DELETED),this.log("Delete request for '"+d+"' has succeeded."))},_onInputChange:function(a){var b;if(qq.supportedFeatures.ajaxUploading){for(b=0;b0&&this.addFiles(a);qq.each(this._buttons,function(a,b){b.reset()})},_onProgress:function(a,b,c,d){this._totalProgress&&this._totalProgress.onIndividualProgress(a,c,d)},_onSubmit:function(){},_onSubmitCallbackSuccess:function(a){this._onSubmit.apply(this,arguments),this._uploadData.setStatus(a,qq.status.SUBMITTED),this._onSubmitted.apply(this,arguments),this._options.autoUpload?(this._options.callbacks.onSubmitted.apply(this,arguments),this._uploadFile(a)):(this._storeForLater(a),this._options.callbacks.onSubmitted.apply(this,arguments))},_onSubmitDelete:function(a,b,c){var d,e=this.getUuid(a);return b&&(d=qq.bind(b,this,a,e,c)),this._isDeletePossible()?(this._handleCheckedCallback({name:"onSubmitDelete",callback:qq.bind(this._options.callbacks.onSubmitDelete,this,a),onSuccess:d||qq.bind(this._deleteHandler.sendDelete,this,a,e,c),identifier:a}),!0):(this.log("Delete request ignored for ID "+a+", delete feature is disabled or request not possible "+"due to CORS on a user agent that does not support pre-flighting.","warn"),!1)},_onSubmitted:function(){},_onTotalProgress:function(a,b){this._options.callbacks.onTotalProgress(a,b)},_onUploadPrep:function(){},_onUpload:function(a){this._uploadData.setStatus(a,qq.status.UPLOADING)},_onUploadChunk:function(){},_onUploadStatusChange:function(a,b,c){c===qq.status.PAUSED&&clearTimeout(this._retryTimeouts[a])},_onValidateBatchCallbackFailure:function(a){var b=this;qq.each(a,function(a,c){b._fileOrBlobRejected(c.id)})},_onValidateBatchCallbackSuccess:function(a,b,c,d,e){var f,g=this._currentItemLimit,h=this._netUploadedOrQueued;0===g||g>=h?b.length>0?this._handleCheckedCallback({name:"onValidate",callback:qq.bind(this._options.callbacks.onValidate,this,a[0],e),onSuccess:qq.bind(this._onValidateCallbackSuccess,this,b,0,c,d),onFailure:qq.bind(this._onValidateCallbackFailure,this,b,0,c,d),identifier:"Item '"+b[0].file.name+"', size: "+b[0].file.size}):this._itemError("noFilesError"):(this._onValidateBatchCallbackFailure(b),f=this._options.messages.tooManyItemsError.replace(/\{netItems\}/g,h).replace(/\{itemLimit\}/g,g),this._batchError(f))},_onValidateCallbackFailure:function(a,b,c,d){var e=b+1;this._fileOrBlobRejected(a[b].id,a[b].file.name),this._maybeProcessNextItemAfterOnValidateCallback(!1,a,e,c,d)},_onValidateCallbackSuccess:function(a,b,c,d){var e=this,f=b+1,g=this._getValidationDescriptor(a[b]);this._validateFileOrBlobData(a[b],g).then(function(){e._upload(a[b].id,c,d),e._maybeProcessNextItemAfterOnValidateCallback(!0,a,f,c,d)},function(){e._maybeProcessNextItemAfterOnValidateCallback(!1,a,f,c,d)})},_prepareItemsForUpload:function(a,b,c){if(0===a.length)return this._itemError("noFilesError"),void 0;var d=this._getValidationDescriptors(a),e=this._getButtonId(a[0].file),f=this._getButton(e);this._handleCheckedCallback({name:"onValidateBatch",callback:qq.bind(this._options.callbacks.onValidateBatch,this,d,f),onSuccess:qq.bind(this._onValidateBatchCallbackSuccess,this,d,a,b,c,f),onFailure:qq.bind(this._onValidateBatchCallbackFailure,this,a),identifier:"batch validation"})},_preventLeaveInProgress:function(){var a=this;this._disposeSupport.attach(window,"beforeunload",function(b){return a.getInProgress()?(b=b||window.event,b.returnValue=a._options.messages.onLeave,a._options.messages.onLeave):void 0})},_refreshSessionData:function(){var a=this,b=this._options.session;qq.Session&&null!=this._options.session.endpoint&&(this._session||(qq.extend(b,this._options.cors),b.log=qq.bind(this.log,this),b.addFileRecord=qq.bind(this._addCannedFile,this),this._session=new qq.Session(b)),setTimeout(function(){a._session.refresh().then(function(b,c){a._options.callbacks.onSessionRequestComplete(b,!0,c)},function(b,c){a._options.callbacks.onSessionRequestComplete(b,!1,c)})},0))},_setSize:function(a,b){this._uploadData.updateSize(a,b),this._totalProgress&&this._totalProgress.onNewSize(a)},_shouldAutoRetry:function(a){var b=this._uploadData.retrieve({id:a});return!this._preventRetries[a]&&this._options.retry.enableAuto&&b.status!==qq.status.PAUSED&&(void 0===this._autoRetries[a]&&(this._autoRetries[a]=0),this._autoRetries[a]0&&h.sizeLimit&&f>h.sizeLimit?(this._itemError("sizeError",e,d),i.failure()):f>0&&f=0}function c(){var a=!1;return qq.each(a,function(b,c){return qq.indexOf(["Accept","Accept-Language","Content-Language","Content-Type"],c)<0?(a=!0,!1):void 0}),a}function d(a){return w.cors.expected&&void 0===a.withCredentials}function e(){var a;return(window.XMLHttpRequest||window.ActiveXObject)&&(a=qq.createXhrInstance(),void 0===a.withCredentials&&(a=new XDomainRequest)),a}function f(a,b){var c=v[a].xhr;return c||(c=b?b:w.cors.expected?e():qq.createXhrInstance(),v[a].xhr=c),c}function g(a){var b,c=qq.indexOf(u,a),d=w.maxConnections;delete v[a],u.splice(c,1),u.length>=d&&d>c&&(b=u[d-1],j(b))}function h(a,b){var c=f(a),e=w.method,h=b===!0;g(a),h?s(e+" request for "+a+" has failed","error"):d(c)||q(c.status)||(h=!0,s(e+" request for "+a+" has failed - response code "+c.status,"error")),w.onComplete(a,c,h)}function i(a){var b,c=v[a].additionalParams,d=w.mandatedParams;return w.paramsStore.get&&(b=w.paramsStore.get(a)),c&&qq.each(c,function(a,c){b=b||{},b[a]=c}),d&&qq.each(d,function(a,c){b=b||{},b[a]=c}),b}function j(a,b){var c,e=f(a,b),g=w.method,h=i(a),j=v[a].payload;return w.onSend(a),c=k(a,h),d(e)?(e.onload=n(a),e.onerror=o(a)):e.onreadystatechange=l(a),m(a),e.open(g,c,!0),w.cors.expected&&w.cors.sendCredentials&&!d(e)&&(e.withCredentials=!0),p(a),s("Sending "+g+" request for "+a),j?e.send(j):t||!h?e.send():h&&w.contentType&&w.contentType.toLowerCase().indexOf("application/x-www-form-urlencoded")>=0?e.send(qq.obj2url(h,"")):h&&w.contentType&&w.contentType.toLowerCase().indexOf("application/json")>=0?e.send(JSON.stringify(h)):e.send(h),e}function k(a,b){var c=w.endpointStore.get(a),d=v[a].addToPath;return void 0!=d&&(c+="/"+d),t&&b?qq.obj2url(b,c):c}function l(a){return function(){4===f(a).readyState&&h(a)}}function m(a){var b=w.onProgress;b&&(f(a).upload.onprogress=function(c){c.lengthComputable&&b(a,c.loaded,c.total)})}function n(a){return function(){h(a)}}function o(a){return function(){h(a,!0)}}function p(a){var e=f(a),g=w.customHeaders,h=v[a].additionalHeaders||{},i=w.method,j={};d(e)||(w.acceptHeader&&e.setRequestHeader("Accept",w.acceptHeader),w.allowXRequestedWithAndCacheControl&&(w.cors.expected&&b()&&!c(g)||(e.setRequestHeader("X-Requested-With","XMLHttpRequest"),e.setRequestHeader("Cache-Control","no-cache"))),!w.contentType||"POST"!==i&&"PUT"!==i||e.setRequestHeader("Content-Type",w.contentType),qq.extend(j,qq.isFunction(g)?g(a):g),qq.extend(j,h),qq.each(j,function(a,b){e.setRequestHeader(a,b)}))}function q(a){return qq.indexOf(w.successfulResponseCodes[w.method],a)>=0}function r(a,b,c,d,e,f){v[a]={addToPath:c,additionalParams:d,additionalHeaders:e,payload:f};var g=u.push(a);return g<=w.maxConnections?j(a,b):void 0}var s,t,u=[],v={},w={acceptHeader:null,validMethods:["PATCH","POST","PUT"],method:"POST",contentType:"application/x-www-form-urlencoded",maxConnections:3,customHeaders:{},endpointStore:{},paramsStore:{},mandatedParams:{},allowXRequestedWithAndCacheControl:!0,successfulResponseCodes:{DELETE:[200,202,204],PATCH:[200,201,202,203,204],POST:[200,201,202,203,204],PUT:[200,201,202,203,204],GET:[200]},cors:{expected:!1,sendCredentials:!1},log:function(){},onSend:function(){},onComplete:function(){},onProgress:null};if(qq.extend(w,a),s=w.log,qq.indexOf(w.validMethods,w.method)<0)throw new Error("'"+w.method+"' is not a supported method for this type of request!");t="GET"===w.method||"DELETE"===w.method,qq.extend(this,{initTransport:function(a){var b,c,d,e,f;return{withPath:function(a){return b=a,this},withParams:function(a){return c=a,this},withHeaders:function(a){return d=a,this},withPayload:function(a){return e=a,this},withCacheBuster:function(){return f=!0,this},send:function(g){return f&&qq.indexOf(["GET","DELETE"],w.method)>=0&&(c.qqtimestamp=(new Date).getTime()),r(a,g,b,c,d,e)}}},canceled:function(a){g(a)}})},qq.UploadHandler=function(a){"use strict";var b=a.proxy,c={},d=b.onCancel,e=b.getName;qq.extend(this,{add:function(a,b){c[a]=b,c[a].temp={}},cancel:function(a){var b=this,f=new qq.Promise,g=d(a,e(a),f);g.then(function(){b.isValid(a)&&(c[a].canceled=!0,b.expunge(a)),f.success()})},expunge:function(a){delete c[a]},getThirdPartyFileId:function(a){return c[a].key},isValid:function(a){return void 0!==c[a]},reset:function(){c={}},_getFileState:function(a){return c[a]},_setThirdPartyFileId:function(a,b){c[a].key=b},_wasCanceled:function(a){return!!c[a].canceled}})},qq.UploadHandlerController=function(a,b){"use strict";var c,d,e,f=this,g=!1,h=!1,i={paramsStore:{},maxConnections:3,chunking:{enabled:!1,multiple:{enabled:!1}},log:function(){},onProgress:function(){},onComplete:function(){},onCancel:function(){},onUploadPrep:function(){},onUpload:function(){},onUploadChunk:function(){},onUploadChunkSuccess:function(){},onAutoRetry:function(){},onResume:function(){},onUuidChanged:function(){},getName:function(){},setSize:function(){},isQueued:function(){},getIdsInProxyGroup:function(){},getIdsInBatch:function(){}},j={done:function(a,b,c,d){var f=e._getChunkData(a,b);e._getFileState(a).attemptingResume=!1,delete e._getFileState(a).temp.chunkProgress[b],e._getFileState(a).loaded+=f.size,i.onUploadChunkSuccess(a,e._getChunkDataForCallback(f),c,d)},finalize:function(a){var b=i.getSize(a),c=i.getName(a);d("All chunks have been uploaded for "+a+" - finalizing...."),e.finalizeChunks(a).then(function(f,g){d("Finalize successful for "+a);var h=m.normalizeResponse(f,!0);i.onProgress(a,c,b,b),e._maybeDeletePersistedChunkData(a),m.cleanup(a,h,g)},function(b,e){var f=m.normalizeResponse(b,!1);d("Problem finalizing chunks for file ID "+a+" - "+f.error,"error"),f.reset&&j.reset(a),i.onAutoRetry(a,c,f,e)||m.cleanup(a,f,e)})},hasMoreParts:function(a){return!!e._getFileState(a).chunking.remaining.length},nextPart:function(a){var b=e._getFileState(a).chunking.remaining.shift();return b>=e._getTotalChunks(a)&&(b=null),b},reset:function(a){d("Server or callback has ordered chunking effort to be restarted on next attempt for item ID "+a,"error"),e._maybeDeletePersistedChunkData(a),e.reevaluateChunking(a),e._getFileState(a).loaded=0},sendNext:function(a){var b=i.getSize(a),c=i.getName(a),f=j.nextPart(a),g=e._getChunkData(a,f),l=e._getFileState(a).attemptingResume,n=e._getFileState(a).chunking.inProgress||[];null==e._getFileState(a).loaded&&(e._getFileState(a).loaded=0),l&&i.onResume(a,c,g)===!1&&(j.reset(a),f=j.nextPart(a),g=e._getChunkData(a,f),l=!1),null==f&&0===n.length?j.finalize(a):(d("Sending chunked upload request for item "+a+": bytes "+(g.start+1)+"-"+g.end+" of "+b),i.onUploadChunk(a,c,e._getChunkDataForCallback(g)),n.push(f),e._getFileState(a).chunking.inProgress=n,h&&k.open(a,f),h&&k.available()&&e._getFileState(a).chunking.remaining.length&&j.sendNext(a),e.uploadChunk(a,f,l).then(function(b,c){d("Chunked upload request succeeded for "+a+", chunk "+f),e.clearCachedChunk(a,f);var g=e._getFileState(a).chunking.inProgress||[],h=m.normalizeResponse(b,!0),i=qq.indexOf(g,f);d(qq.format("Chunk {} for file {} uploaded successfully.",f,a)),j.done(a,f,h,c),i>=0&&g.splice(i,1),e._maybePersistChunkedState(a),j.hasMoreParts(a)||0!==g.length?j.hasMoreParts(a)&&j.sendNext(a):j.finalize(a)},function(b,g){d("Chunked upload request failed for "+a+", chunk "+f),e.clearCachedChunk(a,f);var l,n=m.normalizeResponse(b,!1);n.reset?j.reset(a):(l=qq.indexOf(e._getFileState(a).chunking.inProgress,f),l>=0&&(e._getFileState(a).chunking.inProgress.splice(l,1),e._getFileState(a).chunking.remaining.unshift(f))),e._getFileState(a).temp.ignoreFailure||(h&&(e._getFileState(a).temp.ignoreFailure=!0,qq.each(e._getXhrs(a),function(a,b){b.abort()}),e.moveInProgressToRemaining(a),k.free(a,!0)),i.onAutoRetry(a,c,n,g)||m.cleanup(a,n,g))}).done(function(){e.clearXhr(a,f)}))}},k={_open:[],_openChunks:{},_waiting:[],available:function(){var a=i.maxConnections,b=0,c=0;return qq.each(k._openChunks,function(a,d){b++,c+=d.length}),a-(k._open.length-b+c)},free:function(a,b){var c,f=!b,g=qq.indexOf(k._waiting,a),h=qq.indexOf(k._open,a);delete k._openChunks[a],m.getProxyOrBlob(a)instanceof qq.BlobProxy&&(d("Generated blob upload has ended for "+a+", disposing generated blob."),delete e._getFileState(a).file),g>=0?k._waiting.splice(g,1):f&&h>=0&&(k._open.splice(h,1),c=k._waiting.shift(),c>=0&&(k._open.push(c),m.start(c)))},getWaitingOrConnected:function(){var a=[];return qq.each(k._openChunks,function(b,c){c&&c.length&&a.push(parseInt(b))}),qq.each(k._open,function(b,c){k._openChunks[c]||a.push(parseInt(c))}),a=a.concat(k._waiting)},isUsingConnection:function(a){return qq.indexOf(k._open,a)>=0},open:function(a,b){return null==b&&k._waiting.push(a),k.available()?(null==b?(k._waiting.pop(),k._open.push(a)):function(){var c=k._openChunks[a]||[];c.push(b),k._openChunks[a]=c}(),!0):!1},reset:function(){k._waiting=[],k._open=[]}},l={send:function(a,b){e._getFileState(a).loaded=0,d("Sending simple upload request for "+a),e.uploadFile(a).then(function(c,e){d("Simple upload request succeeded for "+a);var f=m.normalizeResponse(c,!0),g=i.getSize(a);i.onProgress(a,b,g,g),m.maybeNewUuid(a,f),m.cleanup(a,f,e)},function(c,e){d("Simple upload request failed for "+a);var f=m.normalizeResponse(c,!1);i.onAutoRetry(a,b,f,e)||m.cleanup(a,f,e)})}},m={cancel:function(a){d("Cancelling "+a),i.paramsStore.remove(a),k.free(a)},cleanup:function(a,b,c){var d=i.getName(a);i.onComplete(a,d,b,c),e._getFileState(a)&&e._clearXhrs&&e._clearXhrs(a),k.free(a)},getProxyOrBlob:function(a){return e.getProxy&&e.getProxy(a)||e.getFile&&e.getFile(a)},initHandler:function(){var a=b?qq[b]:qq.traditional,c=qq.supportedFeatures.ajaxUploading?"Xhr":"Form";e=new a[c+"UploadHandler"](i,{getDataByUuid:i.getDataByUuid,getName:i.getName,getSize:i.getSize,getUuid:i.getUuid,log:d,onCancel:i.onCancel,onProgress:i.onProgress,onUuidChanged:i.onUuidChanged}),e._removeExpiredChunkingRecords&&e._removeExpiredChunkingRecords()},isDeferredEligibleForUpload:function(a){return i.isQueued(a)},maybeDefer:function(a,b){return b&&!e.getFile(a)&&b instanceof qq.BlobProxy?(i.onUploadPrep(a),d("Attempting to generate a blob on-demand for "+a),b.create().then(function(b){d("Generated an on-demand blob for "+a),e.updateBlob(a,b),i.setSize(a,b.size),e.reevaluateChunking(a),m.maybeSendDeferredFiles(a)},function(b){var e={};b&&(e.error=b),d(qq.format("Failed to generate blob for ID {}. Error message: {}.",a,b),"error"),i.onComplete(a,i.getName(a),qq.extend(e,c),null),m.maybeSendDeferredFiles(a),k.free(a)}),!1):m.maybeSendDeferredFiles(a)},maybeSendDeferredFiles:function(a){var b=i.getIdsInProxyGroup(a),c=!1;return b&&b.length?(d("Maybe ready to upload proxy group file "+a),qq.each(b,function(b,d){if(m.isDeferredEligibleForUpload(d)&&e.getFile(d))c=d===a,m.now(d);else if(m.isDeferredEligibleForUpload(d))return!1})):(c=!0,m.now(a)),c},maybeNewUuid:function(a,b){void 0!==b.newUuid&&i.onUuidChanged(a,b.newUuid)},normalizeResponse:function(a,b){var c=a;return qq.isObject(a)||(c={},qq.isString(a)&&!b&&(c.error=a)),c.success=b,c},now:function(a){var b=i.getName(a);if(!f.isValid(a))throw new qq.Error(a+" is not a valid file ID to upload!");i.onUpload(a,b),g&&e._shouldChunkThisFile(a)?j.sendNext(a):l.send(a,b)},start:function(a){var b=m.getProxyOrBlob(a);return b?m.maybeDefer(a,b):(m.now(a),!0)}};qq.extend(this,{add:function(){e.add.apply(this,arguments)},upload:function(a){return k.open(a)?m.start(a):!1},retry:function(a){return h&&(e._getFileState(a).temp.ignoreFailure=!1),k.isUsingConnection(a)?m.start(a):f.upload(a)},cancel:function(a){var b=e.cancel(a);qq.isGenericPromise(b)?b.then(function(){m.cancel(a)}):b!==!1&&m.cancel(a)},cancelAll:function(){var a,b=k.getWaitingOrConnected();if(b.length)for(a=b.length-1;a>=0;a--)f.cancel(b[a]);k.reset()},getFile:function(a){return e.getProxy&&e.getProxy(a)?e.getProxy(a).referenceBlob:e.getFile&&e.getFile(a)},isProxied:function(a){return!(!e.getProxy||!e.getProxy(a))},getInput:function(a){return e.getInput?e.getInput(a):void 0},reset:function(){d("Resetting upload handler"),f.cancelAll(),k.reset(),e.reset()},expunge:function(a){return f.isValid(a)?e.expunge(a):void 0},isValid:function(a){return e.isValid(a)},getResumableFilesData:function(){return e.getResumableFilesData?e.getResumableFilesData():[]},getThirdPartyFileId:function(a){return f.isValid(a)?e.getThirdPartyFileId(a):void 0},pause:function(a){return f.isResumable(a)&&e.pause&&f.isValid(a)&&e.pause(a)?(k.free(a),e.moveInProgressToRemaining(a),!0):!1},isResumable:function(a){return!!e.isResumable&&e.isResumable(a)}}),qq.extend(i,a),d=i.log,g=i.chunking.enabled&&qq.supportedFeatures.chunking,h=g&&i.chunking.concurrent.enabled,c=function(){var a={};return a[i.preventRetryParam]=!0,a}(),m.initHandler()},qq.FormUploadHandler=function(a){"use strict";function b(a){delete k[a],m&&(clearTimeout(l[a]),delete l[a],q.stopReceivingMessages(a));var b=document.getElementById(g._getIframeName(a));b&&(b.setAttribute("src","javascript:false;"),qq(b).remove())}function c(a){return a.split("_")[0]}function d(a){var b=qq.toElement("");return b.setAttribute("id",a),b.style.display="none",document.body.appendChild(b),b}function e(a,b){var d=a.id,e=c(d),f=o(e);j[f]=b,k[e]=qq(a).attach("load",function(){g.getInput(e)&&(p("Received iframe load event for CORS upload request (iframe name "+d+")"),l[d]=setTimeout(function(){var a="No valid message received from loaded iframe for iframe name "+d;p(a,"error"),b({error:a})},1e3))}),q.receiveMessage(d,function(a){p("Received the following window message: '"+a+"'");var b,e=(c(d),g._parseJsonResponse(a)),f=e.uuid;f&&j[f]?(p("Handling response for iframe name "+d),clearTimeout(l[d]),delete l[d],g._detachLoadEvent(d),b=j[f],delete j[f],q.stopReceivingMessages(d),b(e)):f||p("'"+a+"' does not contain a UUID - ignoring.")})}var f=a.options,g=this,h=a.proxy,i=qq.getUniqueId(),j={},k={},l={},m=f.isCors,n=f.inputName,o=h.getUuid,p=h.log,q=new qq.WindowReceiveMessage({log:p});qq.extend(this,new qq.UploadHandler(a)),qq.override(this,function(a){return{add:function(b,c){a.add(b,{input:c}),c.setAttribute("name",n),c.parentNode&&qq(c).remove()},expunge:function(c){b(c),a.expunge(c)},isValid:function(b){return a.isValid(b)&&void 0!==g._getFileState(b).input}}}),qq.extend(this,{getInput:function(a){return g._getFileState(a).input
+},_attachLoadEvent:function(a,b){var c;m?e(a,b):k[a.id]=qq(a).attach("load",function(){if(p("Received response for "+a.id),a.parentNode){try{if(a.contentDocument&&a.contentDocument.body&&"false"==a.contentDocument.body.innerHTML)return}catch(d){p("Error when attempting to access iframe during handling of upload response ("+d.message+")","error"),c={success:!1}}b(c)}})},_createIframe:function(a){var b=g._getIframeName(a);return d(b)},_detachLoadEvent:function(a){void 0!==k[a]&&(k[a](),delete k[a])},_getIframeName:function(a){return a+"_"+i},_initFormForUpload:function(a){var b=a.method,c=a.endpoint,d=a.params,e=a.paramsInBody,f=a.targetName,g=qq.toElement("
"),h=c;return e?qq.obj2Inputs(d,g):h=qq.obj2url(d,c),g.setAttribute("action",h),g.setAttribute("target",f),g.style.display="none",document.body.appendChild(g),g},_parseJsonResponse:function(a){var b={};try{b=qq.parseJson(a)}catch(c){p("Error when attempting to parse iframe upload response ("+c.message+")","error")}return b}})},qq.XhrUploadHandler=function(a){"use strict";function b(a){qq.each(c._getXhrs(a),function(b,d){var e=c._getAjaxRequester(a,b);d.onreadystatechange=null,d.upload.onprogress=null,d.abort(),e&&e.canceled&&e.canceled(a)})}var c=this,d=a.options.namespace,e=a.proxy,f=a.options.chunking,g=a.options.resume,h=f&&a.options.chunking.enabled&&qq.supportedFeatures.chunking,i=g&&a.options.resume.enabled&&h&&qq.supportedFeatures.resume,j=e.getName,k=e.getSize,l=e.getUuid,m=e.getEndpoint,n=e.getDataByUuid,o=e.onUuidChanged,p=e.onProgress,q=e.log;qq.extend(this,new qq.UploadHandler(a)),qq.override(this,function(a){return{add:function(b,d){if(qq.isFile(d)||qq.isBlob(d))a.add(b,{file:d});else{if(!(d instanceof qq.BlobProxy))throw new Error("Passed obj is not a File, Blob, or proxy");a.add(b,{proxy:d})}c._initTempState(b),i&&c._maybePrepareForResume(b)},expunge:function(d){b(d),c._maybeDeletePersistedChunkData(d),c._clearXhrs(d),a.expunge(d)}}}),qq.extend(this,{clearCachedChunk:function(a,b){delete c._getFileState(a).temp.cachedChunks[b]},clearXhr:function(a,b){var d=c._getFileState(a).temp;d.xhrs&&delete d.xhrs[b],d.ajaxRequesters&&delete d.ajaxRequesters[b]},finalizeChunks:function(a,b){var d=c._getTotalChunks(a)-1,e=c._getXhr(a,d);return b?(new qq.Promise).success(b(e),e):(new qq.Promise).success({},e)},getFile:function(a){return c.isValid(a)&&c._getFileState(a).file},getProxy:function(a){return c.isValid(a)&&c._getFileState(a).proxy},getResumableFilesData:function(){var a=[];return c._iterateResumeRecords(function(b,d){c.moveInProgressToRemaining(null,d.chunking.inProgress,d.chunking.remaining);var e={name:d.name,remaining:d.chunking.remaining,size:d.size,uuid:d.uuid};d.key&&(e.key=d.key),a.push(e)}),a},isResumable:function(a){return!!f&&c.isValid(a)&&!c._getFileState(a).notResumable},moveInProgressToRemaining:function(a,b,d){var e=b||c._getFileState(a).chunking.inProgress,f=d||c._getFileState(a).chunking.remaining;e&&(e.reverse(),qq.each(e,function(a,b){f.unshift(b)}),e.length=0)},pause:function(a){return c.isValid(a)?(q(qq.format("Aborting XHR upload for {} '{}' due to pause instruction.",a,j(a))),c._getFileState(a).paused=!0,b(a),!0):void 0},reevaluateChunking:function(a){if(f&&c.isValid(a)){var b,d,e=c._getFileState(a);if(delete e.chunking,e.chunking={},b=c._getTotalChunks(a),b>1||f.mandatory){for(e.chunking.enabled=!0,e.chunking.parts=b,e.chunking.remaining=[],d=0;b>d;d++)e.chunking.remaining.push(d);c._initTempState(a)}else e.chunking.enabled=!1}},updateBlob:function(a,b){c.isValid(a)&&(c._getFileState(a).file=b)},_clearXhrs:function(a){var b=c._getFileState(a).temp;qq.each(b.ajaxRequesters,function(a){delete b.ajaxRequesters[a]}),qq.each(b.xhrs,function(a){delete b.xhrs[a]})},_createXhr:function(a,b){return c._registerXhr(a,b,qq.createXhrInstance())},_getAjaxRequester:function(a,b){var d=null==b?-1:b;return c._getFileState(a).temp.ajaxRequesters[d]},_getChunkData:function(a,b){var d=f.partSize,e=k(a),g=c.getFile(a),h=d*b,i=h+d>=e?e:h+d,j=c._getTotalChunks(a),l=this._getFileState(a).temp.cachedChunks,m=l[b]||qq.sliceBlob(g,h,i);return l[b]=m,{part:b,start:h,end:i,count:j,blob:m,size:i-h}},_getChunkDataForCallback:function(a){return{partIndex:a.part,startByte:a.start+1,endByte:a.end,totalParts:a.count}},_getLocalStorageId:function(a){var b="5.0",c=j(a),e=k(a),g=f.partSize,h=m(a);return qq.format("qq{}resume{}-{}-{}-{}-{}",d,b,c,e,g,h)},_getMimeType:function(a){return c.getFile(a).type},_getPersistableData:function(a){return c._getFileState(a).chunking},_getTotalChunks:function(a){if(f){var b=k(a),c=f.partSize;return Math.ceil(b/c)}},_getXhr:function(a,b){var d=null==b?-1:b;return c._getFileState(a).temp.xhrs[d]},_getXhrs:function(a){return c._getFileState(a).temp.xhrs},_iterateResumeRecords:function(a){i&&qq.each(localStorage,function(b,c){if(0===b.indexOf(qq.format("qq{}resume",d))){var e=JSON.parse(c);a(b,e)}})},_initTempState:function(a){c._getFileState(a).temp={ajaxRequesters:{},chunkProgress:{},xhrs:{},cachedChunks:{}}},_markNotResumable:function(a){c._getFileState(a).notResumable=!0},_maybeDeletePersistedChunkData:function(a){var b;return i&&c.isResumable(a)&&(b=c._getLocalStorageId(a),b&&localStorage.getItem(b))?(localStorage.removeItem(b),!0):!1},_maybePrepareForResume:function(a){var b,d,e=c._getFileState(a);i&&void 0===e.key&&(b=c._getLocalStorageId(a),d=localStorage.getItem(b),d&&(d=JSON.parse(d),n(d.uuid)?c._markNotResumable(a):(q(qq.format("Identified file with ID {} and name of {} as resumable.",a,j(a))),o(a,d.uuid),e.key=d.key,e.chunking=d.chunking,e.loaded=d.loaded,e.attemptingResume=!0,c.moveInProgressToRemaining(a))))},_maybePersistChunkedState:function(a){var b,d,e=c._getFileState(a);if(i&&c.isResumable(a)){b=c._getLocalStorageId(a),d={name:j(a),size:k(a),uuid:l(a),key:e.key,chunking:e.chunking,loaded:e.loaded,lastUpdated:Date.now()};try{localStorage.setItem(b,JSON.stringify(d))}catch(f){q(qq.format("Unable to save resume data for '{}' due to error: '{}'.",a,f.toString()),"warn")}}},_registerProgressHandler:function(a,b,d){var e=c._getXhr(a,b),f=j(a),g={simple:function(b,c){var d=k(a);b===c?p(a,f,d,d):p(a,f,b>=d?d-1:b,d)},chunked:function(e,g){var h=c._getFileState(a).temp.chunkProgress,i=c._getFileState(a).loaded,j=e,l=g,m=k(a),n=j-(l-d),o=i;h[b]=n,qq.each(h,function(a,b){o+=b}),p(a,f,o,m)}};e.upload.onprogress=function(a){if(a.lengthComputable){var b=null==d?"simple":"chunked";g[b](a.loaded,a.total)}}},_registerXhr:function(a,b,d,e){var f=null==b?-1:b,g=c._getFileState(a).temp;return g.xhrs=g.xhrs||{},g.ajaxRequesters=g.ajaxRequesters||{},g.xhrs[f]=d,e&&(g.ajaxRequesters[f]=e),d},_removeExpiredChunkingRecords:function(){var a=g.recordsExpireIn;c._iterateResumeRecords(function(b,c){var d=new Date(c.lastUpdated);d.setDate(d.getDate()+a),d.getTime()<=Date.now()&&(q("Removing expired resume record with key "+b),localStorage.removeItem(b))})},_shouldChunkThisFile:function(a){var b=c._getFileState(a);return b.chunking||c.reevaluateChunking(a),b.chunking.enabled}})},qq.WindowReceiveMessage=function(a){"use strict";var b={log:function(){}},c={};qq.extend(b,a),qq.extend(this,{receiveMessage:function(a,b){var d=function(a){b(a.data)};window.postMessage?c[a]=qq(window).attach("message",d):log("iframe message passing not supported in this browser!","error")},stopReceivingMessages:function(a){if(window.postMessage){var b=c[a];b&&b()}}})},function(){"use strict";qq.uiPublicApi={clearStoredFiles:function(){this._parent.prototype.clearStoredFiles.apply(this,arguments),this._templating.clearFiles()},addExtraDropzone:function(a){this._dnd&&this._dnd.setupExtraDropzone(a)},removeExtraDropzone:function(a){return this._dnd?this._dnd.removeDropzone(a):void 0},getItemByFileId:function(a){return this._templating.isHiddenForever(a)?void 0:this._templating.getFileContainer(a)},reset:function(){this._parent.prototype.reset.apply(this,arguments),this._templating.reset(),!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton()}).getButtonId()),this._dnd&&(this._dnd.dispose(),this._dnd=this._setupDragAndDrop()),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0,this._setupClickAndEditEventHandlers()},setName:function(a,b){var c=this._options.formatFileName(b);this._parent.prototype.setName.apply(this,arguments),this._templating.updateFilename(a,c)},pauseUpload:function(a){var b=this._parent.prototype.pauseUpload.apply(this,arguments);return b&&this._templating.uploadPaused(a),b},continueUpload:function(a){var b=this._parent.prototype.continueUpload.apply(this,arguments);return b&&this._templating.uploadContinued(a),b},getId:function(a){return this._templating.getFileId(a)},getDropTarget:function(a){var b=this.getFile(a);return b.qqDropTarget}},qq.uiPrivateApi={_getButton:function(a){var b=this._parent.prototype._getButton.apply(this,arguments);return b||a===this._defaultButtonId&&(b=this._templating.getButton()),b},_removeFileItem:function(a){this._templating.removeFile(a)},_setupClickAndEditEventHandlers:function(){this._fileButtonsClickHandler=qq.FileButtonsClickHandler&&this._bindFileButtonsClickEvent(),this._focusinEventSupported=!qq.firefox(),this._isEditFilenameEnabled()&&(this._filenameClickHandler=this._bindFilenameClickEvent(),this._filenameInputFocusInHandler=this._bindFilenameInputFocusInEvent(),this._filenameInputFocusHandler=this._bindFilenameInputFocusEvent())},_setupDragAndDrop:function(){var a=this,b=this._options.dragAndDrop.extraDropzones,c=this._templating,d=c.getDropZone();return d&&b.push(d),new qq.DragAndDrop({dropZoneElements:b,allowMultipleItems:this._options.multiple,classes:{dropActive:this._options.classes.dropActive},callbacks:{processingDroppedFiles:function(){c.showDropProcessing()},processingDroppedFilesComplete:function(b,d){c.hideDropProcessing(),qq.each(b,function(a,b){b.qqDropTarget=d}),b.length&&a.addFiles(b,null,null)},dropError:function(b,c){a._itemError(b,c)},dropLog:function(b,c){a.log(b,c)}}})},_bindFileButtonsClickEvent:function(){var a=this;return new qq.FileButtonsClickHandler({templating:this._templating,log:function(b,c){a.log(b,c)},onDeleteFile:function(b){a.deleteFile(b)},onCancel:function(b){a.cancel(b)},onRetry:function(b){qq(a._templating.getFileContainer(b)).removeClass(a._classes.retryable),a._templating.hideRetry(b),a.retry(b)},onPause:function(b){a.pauseUpload(b)},onContinue:function(b){a.continueUpload(b)},onGetName:function(b){return a.getName(b)}})},_isEditFilenameEnabled:function(){return this._templating.isEditFilenamePossible()&&!this._options.autoUpload&&qq.FilenameClickHandler&&qq.FilenameInputFocusHandler&&qq.FilenameInputFocusHandler},_filenameEditHandler:function(){var a=this,b=this._templating;return{templating:b,log:function(b,c){a.log(b,c)},onGetUploadStatus:function(b){return a.getUploads({id:b}).status},onGetName:function(b){return a.getName(b)},onSetName:function(b,c){a.setName(b,c)},onEditingStatusChange:function(a,c){var d=qq(b.getEditInput(a)),e=qq(b.getFileContainer(a));c?(d.addClass("qq-editing"),b.hideFilename(a),b.hideEditIcon(a)):(d.removeClass("qq-editing"),b.showFilename(a),b.showEditIcon(a)),e.addClass("qq-temp").removeClass("qq-temp")}}},_onUploadStatusChange:function(a,b,c){this._parent.prototype._onUploadStatusChange.apply(this,arguments),this._isEditFilenameEnabled()&&this._templating.getFileContainer(a)&&c!==qq.status.SUBMITTED&&(this._templating.markFilenameEditable(a),this._templating.hideEditIcon(a)),c===qq.status.UPLOAD_RETRYING?(this._templating.setStatusText(a),qq(this._templating.getFileContainer(a)).removeClass(this._classes.retrying)):c===qq.status.UPLOAD_FAILED&&this._templating.hidePause(a)},_bindFilenameInputFocusInEvent:function(){var a=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusInHandler(a)},_bindFilenameInputFocusEvent:function(){var a=qq.extend({},this._filenameEditHandler());return new qq.FilenameInputFocusHandler(a)},_bindFilenameClickEvent:function(){var a=qq.extend({},this._filenameEditHandler());return new qq.FilenameClickHandler(a)},_storeForLater:function(a){this._parent.prototype._storeForLater.apply(this,arguments),this._templating.hideSpinner(a)},_onAllComplete:function(){this._parent.prototype._onAllComplete.apply(this,arguments),this._templating.resetTotalProgress()},_onSubmit:function(a,b){var c=this.getFile(a);c&&c.qqPath&&this._options.dragAndDrop.reportDirectoryPaths&&this._paramsStore.addReadOnly(a,{qqpath:c.qqPath}),this._parent.prototype._onSubmit.apply(this,arguments),this._addToList(a,b)},_onSubmitted:function(a){this._isEditFilenameEnabled()&&(this._templating.markFilenameEditable(a),this._templating.showEditIcon(a),this._focusinEventSupported||this._filenameInputFocusHandler.addHandler(this._templating.getEditInput(a)))},_onProgress:function(a,b,c,d){this._parent.prototype._onProgress.apply(this,arguments),this._templating.updateProgress(a,c,d),100===Math.round(100*(c/d))?(this._templating.hideCancel(a),this._templating.hidePause(a),this._templating.hideProgress(a),this._templating.setStatusText(a,this._options.text.waitingForResponse),this._displayFileSize(a)):this._displayFileSize(a,c,d)},_onTotalProgress:function(a,b){this._parent.prototype._onTotalProgress.apply(this,arguments),this._templating.updateTotalProgress(a,b)},_onComplete:function(a,b,c){function d(b){g&&(f.setStatusText(a),qq(g).removeClass(h._classes.retrying),f.hideProgress(a),h.getUploads({id:a}).status!==qq.status.UPLOAD_FAILED&&f.hideCancel(a),f.hideSpinner(a),b.success?h._markFileAsSuccessful(a):(qq(g).addClass(h._classes.fail),f.showCancel(a),f.isRetryPossible()&&!h._preventRetries[a]&&(qq(g).addClass(h._classes.retryable),f.showRetry(a)),h._controlFailureTextDisplay(a,b)))}var e=this._parent.prototype._onComplete.apply(this,arguments),f=this._templating,g=f.getFileContainer(a),h=this;return e instanceof qq.Promise?e.done(function(a){d(a)}):d(c),e},_markFileAsSuccessful:function(a){var b=this._templating;this._isDeletePossible()&&b.showDeleteButton(a),qq(b.getFileContainer(a)).addClass(this._classes.success),this._maybeUpdateThumbnail(a)},_onUploadPrep:function(a){this._parent.prototype._onUploadPrep.apply(this,arguments),this._templating.showSpinner(a)},_onUpload:function(a){var b=this._parent.prototype._onUpload.apply(this,arguments);return this._templating.showSpinner(a),b},_onUploadChunk:function(a,b){this._parent.prototype._onUploadChunk.apply(this,arguments),b.partIndex>0&&this._handler.isResumable(a)&&this._templating.allowPause(a)},_onCancel:function(a){this._parent.prototype._onCancel.apply(this,arguments),this._removeFileItem(a),0===this._getNotFinished()&&this._templating.resetTotalProgress()},_onBeforeAutoRetry:function(a){var b,c,d;this._parent.prototype._onBeforeAutoRetry.apply(this,arguments),this._showCancelLink(a),this._options.retry.showAutoRetryNote&&(b=this._autoRetries[a],c=this._options.retry.maxAutoAttempts,d=this._options.retry.autoRetryNote.replace(/\{retryNum\}/g,b),d=d.replace(/\{maxAuto\}/g,c),this._templating.setStatusText(a,d),qq(this._templating.getFileContainer(a)).addClass(this._classes.retrying))},_onBeforeManualRetry:function(a){return this._parent.prototype._onBeforeManualRetry.apply(this,arguments)?(this._templating.resetProgress(a),qq(this._templating.getFileContainer(a)).removeClass(this._classes.fail),this._templating.setStatusText(a),this._templating.showSpinner(a),this._showCancelLink(a),!0):(qq(this._templating.getFileContainer(a)).addClass(this._classes.retryable),this._templating.showRetry(a),!1)},_onSubmitDelete:function(a){var b=qq.bind(this._onSubmitDeleteSuccess,this);this._parent.prototype._onSubmitDelete.call(this,a,b)},_onSubmitDeleteSuccess:function(){this._options.deleteFile.forceConfirm?this._showDeleteConfirm.apply(this,arguments):this._sendDeleteRequest.apply(this,arguments)},_onDeleteComplete:function(a,b,c){this._parent.prototype._onDeleteComplete.apply(this,arguments),this._templating.hideSpinner(a),c?(this._templating.setStatusText(a,this._options.deleteFile.deletingFailedText),this._templating.showDeleteButton(a)):this._removeFileItem(a)},_sendDeleteRequest:function(a){this._templating.hideDeleteButton(a),this._templating.showSpinner(a),this._templating.setStatusText(a,this._options.deleteFile.deletingStatusText),this._deleteHandler.sendDelete.apply(this,arguments)},_showDeleteConfirm:function(a){var b,c=this.getName(a),d=this._options.deleteFile.confirmMessage.replace(/\{filename\}/g,c),e=(this.getUuid(a),arguments),f=this;b=this._options.showConfirm(d),qq.isGenericPromise(b)?b.then(function(){f._sendDeleteRequest.apply(f,e)}):b!==!1&&f._sendDeleteRequest.apply(f,e)},_addToList:function(a,b,c){var d,e,f=0,g=this._handler.isProxied(a)&&this._options.scaling.hideScaled;this._options.display.prependFiles&&(this._totalFilesInBatch>1&&this._filesInBatchAddedToUi>0&&(f=this._filesInBatchAddedToUi-1),d={index:f}),c||(this._options.disableCancelForFormUploads&&!qq.supportedFeatures.ajaxUploading&&this._templating.disableCancel(),this._options.multiple||(e=this.getUploads({id:a}),this._handledProxyGroup=this._handledProxyGroup||e.proxyGroupId,e.proxyGroupId===this._handledProxyGroup&&e.proxyGroupId||(this._handler.cancelAll(),this._clearList(),this._handledProxyGroup=null))),this._templating.addFile(a,this._options.formatFileName(b),d,g),c?this._thumbnailUrls[a]&&this._templating.updateThumbnail(a,this._thumbnailUrls[a],!0):this._templating.generatePreview(a,this.getFile(a)),this._filesInBatchAddedToUi+=1,(c||this._options.display.fileSizeOnSubmit&&qq.supportedFeatures.ajaxUploading)&&this._displayFileSize(a)},_clearList:function(){this._templating.clearFiles(),this.clearStoredFiles()},_displayFileSize:function(a,b,c){var d=this.getSize(a),e=this._formatSize(d);d>=0&&(void 0!==b&&void 0!==c&&(e=this._formatProgress(b,c)),this._templating.updateSize(a,e))},_formatProgress:function(a,b){function c(a,b){d=d.replace(a,b)}var d=this._options.text.formatProgress;return c("{percent}",Math.round(100*(a/b))),c("{total_size}",this._formatSize(b)),d},_controlFailureTextDisplay:function(a,b){var c,d,e;c=this._options.failedUploadTextDisplay.mode,d=this._options.failedUploadTextDisplay.responseProperty,"custom"===c?(e=b[d],e||(e=this._options.text.failUpload),this._templating.setStatusText(a,e),this._options.failedUploadTextDisplay.enableTooltip&&this._showTooltip(a,e)):"default"===c?this._templating.setStatusText(a,this._options.text.failUpload):"none"!==c&&this.log("failedUploadTextDisplay.mode value of '"+c+"' is not valid","warn")},_showTooltip:function(a,b){this._templating.getFileContainer(a).title=b},_showCancelLink:function(a){(!this._options.disableCancelForFormUploads||qq.supportedFeatures.ajaxUploading)&&this._templating.showCancel(a)},_itemError:function(){var a=this._parent.prototype._itemError.apply(this,arguments);this._options.showMessage(a)},_batchError:function(a){this._parent.prototype._batchError.apply(this,arguments),this._options.showMessage(a)},_setupPastePrompt:function(){var a=this;this._options.callbacks.onPasteReceived=function(){var b=a._options.paste.namePromptMessage,c=a._options.paste.defaultName;return a._options.showPrompt(b,c)}},_fileOrBlobRejected:function(){this._totalFilesInBatch-=1,this._parent.prototype._fileOrBlobRejected.apply(this,arguments)},_prepareItemsForUpload:function(a){this._totalFilesInBatch=a.length,this._filesInBatchAddedToUi=0,this._parent.prototype._prepareItemsForUpload.apply(this,arguments)},_maybeUpdateThumbnail:function(a){var b=this._thumbnailUrls[a],c=this.getUploads({id:a}).status;c===qq.status.DELETED||!b&&!this._options.thumbnails.placeholders.waitUntilResponse&&qq.supportedFeatures.imagePreviews||this._templating.updateThumbnail(a,b)},_addCannedFile:function(){var a=this._parent.prototype._addCannedFile.apply(this,arguments);return this._addToList(a,this.getName(a),!0),this._templating.hideSpinner(a),this._templating.hideCancel(a),this._markFileAsSuccessful(a),a},_setSize:function(a,b){this._parent.prototype._setSize.apply(this,arguments),this._templating.updateSize(a,this._formatSize(b))}}}(),qq.FineUploader=function(a,b){"use strict";var c=this;this._parent=b?qq[b].FineUploaderBasic:qq.FineUploaderBasic,this._parent.apply(this,arguments),qq.extend(this._options,{element:null,button:null,listElement:null,dragAndDrop:{extraDropzones:[],reportDirectoryPaths:!1},text:{formatProgress:"{percent}% of {total_size}",failUpload:"Upload failed",waitingForResponse:"Processing...",paused:"Paused"},template:"qq-template",classes:{retrying:"qq-upload-retrying",retryable:"qq-upload-retryable",success:"qq-upload-success",fail:"qq-upload-fail",editable:"qq-editable",hide:"qq-hide",dropActive:"qq-upload-drop-area-active"},failedUploadTextDisplay:{mode:"default",responseProperty:"error",enableTooltip:!0},messages:{tooManyFilesError:"You may only drop one file",unsupportedBrowser:"Unrecoverable error - this browser does not permit file uploading of any kind."},retry:{showAutoRetryNote:!0,autoRetryNote:"Retrying {retryNum}/{maxAuto}..."},deleteFile:{forceConfirm:!1,confirmMessage:"Are you sure you want to delete {filename}?",deletingStatusText:"Deleting...",deletingFailedText:"Delete failed"},display:{fileSizeOnSubmit:!1,prependFiles:!1},paste:{promptForName:!1,namePromptMessage:"Please name this image"},thumbnails:{maxCount:0,placeholders:{waitUntilResponse:!1,notAvailablePath:null,waitingPath:null},timeBetweenThumbs:750},scaling:{hideScaled:!1},showMessage:function(a){return c._templating.hasDialog("alert")?c._templating.showDialog("alert",a):(setTimeout(function(){window.alert(a)},0),void 0)},showConfirm:function(a){return c._templating.hasDialog("confirm")?c._templating.showDialog("confirm",a):window.confirm(a)},showPrompt:function(a,b){return c._templating.hasDialog("prompt")?c._templating.showDialog("prompt",a,b):window.prompt(a,b)}},!0),qq.extend(this._options,a,!0),this._templating=new qq.Templating({log:qq.bind(this.log,this),templateIdOrEl:this._options.template,containerEl:this._options.element,fileContainerEl:this._options.listElement,button:this._options.button,imageGenerator:this._imageGenerator,classes:{hide:this._options.classes.hide,editable:this._options.classes.editable},limits:{maxThumbs:this._options.thumbnails.maxCount,timeBetweenThumbs:this._options.thumbnails.timeBetweenThumbs},placeholders:{waitUntilUpdate:this._options.thumbnails.placeholders.waitUntilResponse,thumbnailNotAvailable:this._options.thumbnails.placeholders.notAvailablePath,waitingForThumbnail:this._options.thumbnails.placeholders.waitingPath},text:this._options.text}),this._options.workarounds.ios8SafariUploads&&qq.ios800()&&qq.iosSafari()?this._templating.renderFailure(this._options.messages.unsupportedBrowserIos8Safari):!qq.supportedFeatures.uploading||this._options.cors.expected&&!qq.supportedFeatures.uploadCors?this._templating.renderFailure(this._options.messages.unsupportedBrowser):(this._wrapCallbacks(),this._templating.render(),this._classes=this._options.classes,!this._options.button&&this._templating.getButton()&&(this._defaultButtonId=this._createUploadButton({element:this._templating.getButton()}).getButtonId()),this._setupClickAndEditEventHandlers(),qq.DragAndDrop&&qq.supportedFeatures.fileDrop&&(this._dnd=this._setupDragAndDrop()),this._options.paste.targetElement&&this._options.paste.promptForName&&(qq.PasteSupport?this._setupPastePrompt():this.log("Paste support module not found.","error")),this._totalFilesInBatch=0,this._filesInBatchAddedToUi=0)},qq.extend(qq.FineUploader.prototype,qq.basePublicApi),qq.extend(qq.FineUploader.prototype,qq.basePrivateApi),qq.extend(qq.FineUploader.prototype,qq.uiPublicApi),qq.extend(qq.FineUploader.prototype,qq.uiPrivateApi),qq.Templating=function(a){"use strict";var b,c,d,e,f,g,h,i,j="qq-file-id",k="qq-file-id-",l="qq-max-size",m="qq-server-scale",n="qq-hide-dropzone",o="qq-drop-area-text",p="qq-in-progress",q="qq-hidden-forever",r=!1,s=0,t=!1,u=[],v=-1,w={log:null,limits:{maxThumbs:0,timeBetweenThumbs:750},templateIdOrEl:"qq-template",containerEl:null,fileContainerEl:null,button:null,imageGenerator:null,classes:{hide:"qq-hide",editable:"qq-editable"},placeholders:{waitUntilUpdate:!1,thumbnailNotAvailable:null,waitingForThumbnail:null},text:{paused:"Paused"}},x={button:"qq-upload-button-selector",alertDialog:"qq-alert-dialog-selector",dialogCancelButton:"qq-cancel-button-selector",confirmDialog:"qq-confirm-dialog-selector",dialogMessage:"qq-dialog-message-selector",dialogOkButton:"qq-ok-button-selector",promptDialog:"qq-prompt-dialog-selector",uploader:"qq-uploader-selector",drop:"qq-upload-drop-area-selector",list:"qq-upload-list-selector",progressBarContainer:"qq-progress-bar-container-selector",progressBar:"qq-progress-bar-selector",totalProgressBarContainer:"qq-total-progress-bar-container-selector",totalProgressBar:"qq-total-progress-bar-selector",file:"qq-upload-file-selector",spinner:"qq-upload-spinner-selector",size:"qq-upload-size-selector",cancel:"qq-upload-cancel-selector",pause:"qq-upload-pause-selector",continueButton:"qq-upload-continue-selector",deleteButton:"qq-upload-delete-selector",retry:"qq-upload-retry-selector",statusText:"qq-upload-status-text-selector",editFilenameInput:"qq-edit-filename-selector",editNameIcon:"qq-edit-filename-icon-selector",dropText:"qq-upload-drop-area-text-selector",dropProcessing:"qq-drop-processing-selector",dropProcessingSpinner:"qq-drop-processing-spinner-selector",thumbnail:"qq-thumbnail-selector"},y={},z=new qq.Promise,A=new qq.Promise,B=function(){var a=w.placeholders.thumbnailNotAvailable,c=w.placeholders.waitingForThumbnail,d={maxSize:v,scale:i};h&&(a?w.imageGenerator.generate(a,new Image,d).then(function(a){z.success(a)},function(){z.failure(),b("Problem loading 'not available' placeholder image at "+a,"error")}):z.failure(),c?w.imageGenerator.generate(c,new Image,d).then(function(a){A.success(a)},function(){A.failure(),b("Problem loading 'waiting for thumbnail' placeholder image at "+c,"error")}):A.failure())},C=function(a){var b=new qq.Promise;return A.then(function(c){V(c,a),a.src?b.success():(a.src=c.src,a.onload=function(){a.onload=null,ab(a),b.success()})},function(){U(a),b.success()}),b},D=function(a,c,d){var e=T(a);return b("Generating new thumbnail for "+a),c.qqThumbnailId=a,w.imageGenerator.generate(c,e,d).then(function(){s++,ab(e),y[a].success()},function(){y[a].failure(),w.placeholders.waitUntilUpdate||W(a,e)})},E=function(){if(u.length){t=!0;var a=u.shift();a.update?$(a):Z(a)}else t=!1},F=function(a){return S(L(a),x.cancel)},G=function(a){return S(L(a),x.continueButton)},H=function(a){return S(f,x[a+"Dialog"])},I=function(a){return S(L(a),x.deleteButton)},J=function(){return S(f,x.dropProcessing)},K=function(a){return S(L(a),x.editNameIcon)},L=function(a){return qq(g).getByClass(k+a)[0]},M=function(a){return S(L(a),x.file)},N=function(a){return S(L(a),x.pause)},O=function(a){return null==a?S(f,x.totalProgressBarContainer)||S(f,x.totalProgressBar):S(L(a),x.progressBarContainer)||S(L(a),x.progressBar)},P=function(a){return S(L(a),x.retry)},Q=function(a){return S(L(a),x.size)},R=function(a){return S(L(a),x.spinner)},S=function(a,b){return a&&qq(a).getByClass(b)[0]},T=function(a){return h&&S(L(a),x.thumbnail)},U=function(a){a&&qq(a).addClass(w.classes.hide)},V=function(a,b){var c=a.style.maxWidth,d=a.style.maxHeight;d&&c&&!b.style.maxWidth&&!b.style.maxHeight&&qq(b).css({maxWidth:c,maxHeight:d})},W=function(a,b){var c=y[a]||(new qq.Promise).failure(),d=new qq.Promise;return z.then(function(a){c.then(function(){d.success()},function(){V(a,b),b.onload=function(){b.onload=null,d.success()},b.src=a.src,ab(b)})}),d},X=function(){var a,e,f,g,j,k,p,q,r,s,t;if(b("Parsing template"),null==w.templateIdOrEl)throw new Error("You MUST specify either a template element or ID!");if(qq.isString(w.templateIdOrEl)){if(a=document.getElementById(w.templateIdOrEl),null===a)throw new Error(qq.format("Cannot find template script at ID '{}'!",w.templateIdOrEl));e=a.innerHTML}else{if(void 0===w.templateIdOrEl.innerHTML)throw new Error("You have specified an invalid value for the template option! It must be an ID or an Element.");e=w.templateIdOrEl.innerHTML}if(e=qq.trimStr(e),g=document.createElement("div"),g.appendChild(qq.toElement(e)),t=qq(g).getByClass(x.uploader)[0],w.button&&(k=qq(g).getByClass(x.button)[0],k&&qq(k).remove()),qq.DragAndDrop&&qq.supportedFeatures.fileDrop||(r=qq(g).getByClass(x.dropProcessing)[0],r&&qq(r).remove()),p=qq(g).getByClass(x.drop)[0],p&&!qq.DragAndDrop&&(b("DnD module unavailable.","info"),qq(p).remove()),qq.supportedFeatures.fileDrop?qq(t).hasAttribute(o)&&p&&(s=qq(p).getByClass(x.dropText)[0],s&&qq(s).remove()):(t.removeAttribute(o),p&&qq(p).hasAttribute(n)&&qq(p).css({display:"none"})),q=qq(g).getByClass(x.thumbnail)[0],h?q&&(v=parseInt(q.getAttribute(l)),v=v>0?v:null,i=qq(q).hasAttribute(m)):q&&qq(q).remove(),h=h&&q,c=qq(g).getByClass(x.editFilenameInput).length>0,d=qq(g).getByClass(x.retry).length>0,f=qq(g).getByClass(x.list)[0],null==f)throw new Error("Could not find the file list container in the template!");return j=f.innerHTML,f.innerHTML="",g.getElementsByTagName("DIALOG").length&&document.createElement("dialog"),b("Template parsing complete"),{template:qq.trimStr(g.innerHTML),fileTemplate:qq.trimStr(j)}},Y=function(a,b){var c=g,d=c.firstChild;b>0&&(d=qq(c).children()[b].nextSibling),c.insertBefore(a,d)},Z=function(a){var b=a.id,c=a.optFileOrBlob,d=c&&c.qqThumbnailId,e=T(b),f={maxSize:v,scale:!0,orient:!0};qq.supportedFeatures.imagePreviews?e?w.limits.maxThumbs&&w.limits.maxThumbs<=s?(W(b,e),E()):C(e).done(function(){y[b]=new qq.Promise,y[b].done(function(){setTimeout(E,w.limits.timeBetweenThumbs)}),null!=d?bb(b,d):D(b,c,f)}):E():e&&(C(e),E())},$=function(a){var b=a.id,c=a.thumbnailUrl,d=a.showWaitingImg,e=T(b),f={maxSize:v,scale:i};if(e)if(c){if(!(w.limits.maxThumbs&&w.limits.maxThumbs<=s))return d&&C(e),w.imageGenerator.generate(c,e,f).then(function(){ab(e),s++,setTimeout(E,w.limits.timeBetweenThumbs)},function(){W(b,e),setTimeout(E,w.limits.timeBetweenThumbs)});W(b,e),E()}else W(b,e),E()},_=function(a,b){var c=O(a),d=null==a?x.totalProgressBar:x.progressBar;c&&!qq(c).hasClass(d)&&(c=qq(c).getByClass(d)[0]),c&&(qq(c).css({width:b+"%"}),c.setAttribute("aria-valuenow",b))},ab=function(a){a&&qq(a).removeClass(w.classes.hide)},bb=function(a,c){var d=T(a),e=T(c);b(qq.format("ID {} is the same file as ID {}. Will use generated thumbnail from ID {} instead.",a,c,c)),y[c].then(function(){s++,y[a].success(),b(qq.format("Now using previously generated thumbnail created for ID {} on ID {}.",c,a)),d.src=e.src,ab(d)},function(){y[a].failure(),w.placeholders.waitUntilUpdate||W(a,d)})};qq.extend(w,a),b=w.log,qq.supportedFeatures.imagePreviews||(w.limits.timeBetweenThumbs=0,w.limits.maxThumbs=0),f=w.containerEl,h=void 0!==w.imageGenerator,e=X(),B(),qq.extend(this,{render:function(){b("Rendering template in DOM."),s=0,f.innerHTML=e.template,U(J()),this.hideTotalProgress(),g=w.fileContainerEl||S(f,x.list),b("Template rendering complete")},renderFailure:function(a){var b=qq.toElement(a);f.innerHTML="",f.appendChild(b)},reset:function(){this.render()},clearFiles:function(){g.innerHTML=""},disableCancel:function(){r=!0},addFile:function(a,b,c,d){var h,i=qq.toElement(e.fileTemplate),l=S(i,x.file),m=S(f,x.uploader);qq(i).addClass(k+a),m.removeAttribute(o),l&&(qq(l).setText(b),l.setAttribute("title",b)),i.setAttribute(j,a),c?Y(i,c.index):g.appendChild(i),d?(i.style.display="none",qq(i).addClass(q)):(U(O(a)),U(Q(a)),U(I(a)),U(P(a)),U(N(a)),U(G(a)),r&&this.hideCancel(a),h=T(a),h&&!h.src&&A.then(function(a){h.src=a.src,a.style.maxHeight&&a.style.maxWidth&&qq(h).css({maxHeight:a.style.maxHeight,maxWidth:a.style.maxWidth}),ab(h)}))},removeFile:function(a){qq(L(a)).remove()},getFileId:function(a){var b=a;if(b){for(;null==b.getAttribute(j);)b=b.parentNode;return parseInt(b.getAttribute(j))}},getFileList:function(){return g},markFilenameEditable:function(a){var b=M(a);b&&qq(b).addClass(w.classes.editable)
+},updateFilename:function(a,b){var c=M(a);c&&(qq(c).setText(b),c.setAttribute("title",b))},hideFilename:function(a){U(M(a))},showFilename:function(a){ab(M(a))},isFileName:function(a){return qq(a).hasClass(x.file)},getButton:function(){return w.button||S(f,x.button)},hideDropProcessing:function(){U(J())},showDropProcessing:function(){ab(J())},getDropZone:function(){return S(f,x.drop)},isEditFilenamePossible:function(){return c},hideRetry:function(a){U(P(a))},isRetryPossible:function(){return d},showRetry:function(a){ab(P(a))},getFileContainer:function(a){return L(a)},showEditIcon:function(a){var b=K(a);b&&qq(b).addClass(w.classes.editable)},isHiddenForever:function(a){return qq(L(a)).hasClass(q)},hideEditIcon:function(a){var b=K(a);b&&qq(b).removeClass(w.classes.editable)},isEditIcon:function(a){return qq(a).hasClass(x.editNameIcon,!0)},getEditInput:function(a){return S(L(a),x.editFilenameInput)},isEditInput:function(a){return qq(a).hasClass(x.editFilenameInput,!0)},updateProgress:function(a,b,c){var d,e=O(a);e&&c>0&&(d=Math.round(100*(b/c)),100===d?U(e):ab(e),_(a,d))},updateTotalProgress:function(a,b){this.updateProgress(null,a,b)},hideProgress:function(a){var b=O(a);b&&U(b)},hideTotalProgress:function(){this.hideProgress()},resetProgress:function(a){_(a,0),this.hideTotalProgress(a)},resetTotalProgress:function(){this.resetProgress()},showCancel:function(a){if(!r){var b=F(a);b&&qq(b).removeClass(w.classes.hide)}},hideCancel:function(a){U(F(a))},isCancel:function(a){return qq(a).hasClass(x.cancel,!0)},allowPause:function(a){ab(N(a)),U(G(a))},uploadPaused:function(a){this.setStatusText(a,w.text.paused),this.allowContinueButton(a),U(R(a))},hidePause:function(a){U(N(a))},isPause:function(a){return qq(a).hasClass(x.pause,!0)},isContinueButton:function(a){return qq(a).hasClass(x.continueButton,!0)},allowContinueButton:function(a){ab(G(a)),U(N(a))},uploadContinued:function(a){this.setStatusText(a,""),this.allowPause(a),ab(R(a))},showDeleteButton:function(a){ab(I(a))},hideDeleteButton:function(a){U(I(a))},isDeleteButton:function(a){return qq(a).hasClass(x.deleteButton,!0)},isRetry:function(a){return qq(a).hasClass(x.retry,!0)},updateSize:function(a,b){var c=Q(a);c&&(ab(c),qq(c).setText(b))},setStatusText:function(a,b){var c=S(L(a),x.statusText);c&&(null==b?qq(c).clearText():qq(c).setText(b))},hideSpinner:function(a){qq(L(a)).removeClass(p),U(R(a))},showSpinner:function(a){qq(L(a)).addClass(p),ab(R(a))},generatePreview:function(a,b){this.isHiddenForever(a)||(u.push({id:a,optFileOrBlob:b}),!t&&E())},updateThumbnail:function(a,b,c){this.isHiddenForever(a)||(u.push({update:!0,id:a,thumbnailUrl:b,showWaitingImg:c}),!t&&E())},hasDialog:function(a){return qq.supportedFeatures.dialogElement&&!!H(a)},showDialog:function(a,b,c){var d=H(a),e=S(d,x.dialogMessage),f=d.getElementsByTagName("INPUT")[0],g=S(d,x.dialogCancelButton),h=S(d,x.dialogOkButton),i=new qq.Promise,j=function(){g.removeEventListener("click",k),h&&h.removeEventListener("click",l),i.failure()},k=function(){g.removeEventListener("click",k),d.close()},l=function(){d.removeEventListener("close",j),h.removeEventListener("click",l),d.close(),i.success(f&&f.value)};return d.addEventListener("close",j),g.addEventListener("click",k),h&&h.addEventListener("click",l),f&&(f.value=c),e.textContent=b,d.showModal(),i}})},qq.s3=qq.s3||{},qq.s3.util=qq.s3.util||function(){"use strict";return{AWS_PARAM_PREFIX:"x-amz-meta-",SESSION_TOKEN_PARAM_NAME:"x-amz-security-token",REDUCED_REDUNDANCY_PARAM_NAME:"x-amz-storage-class",REDUCED_REDUNDANCY_PARAM_VALUE:"REDUCED_REDUNDANCY",SERVER_SIDE_ENCRYPTION_PARAM_NAME:"x-amz-server-side-encryption",SERVER_SIDE_ENCRYPTION_PARAM_VALUE:"AES256",getBucket:function(a){var b,c=[/^(?:https?:\/\/)?([a-z0-9.\-_]+)\.s3(?:-[a-z0-9\-]+)?\.amazonaws\.com/i,/^(?:https?:\/\/)?s3(?:-[a-z0-9\-]+)?\.amazonaws\.com\/([a-z0-9.\-_]+)/i,/^(?:https?:\/\/)?([a-z0-9.\-_]+)/i];return qq.each(c,function(c,d){var e=d.exec(a);return e?(b=e[1],!1):void 0}),b},getPolicy:function(a){var b={},c=[],d=a.bucket,e=a.key,f=a.acl,g=a.type,h=new Date,i=a.expectedStatus,j=a.sessionToken,k=a.params,l=qq.s3.util.getSuccessRedirectAbsoluteUrl(a.successRedirectUrl),m=a.minFileSize,n=a.maxFileSize,o=a.reducedRedundancy,p=a.serverSideEncryption;return b.expiration=qq.s3.util.getPolicyExpirationDate(h),c.push({acl:f}),c.push({bucket:d}),g&&c.push({"Content-Type":g}),i&&c.push({success_action_status:i.toString()}),l&&c.push({success_action_redirect:l}),o&&(c.push({}),c[c.length-1][qq.s3.util.REDUCED_REDUNDANCY_PARAM_NAME]=qq.s3.util.REDUCED_REDUNDANCY_PARAM_VALUE),j&&(c.push({}),c[c.length-1][qq.s3.util.SESSION_TOKEN_PARAM_NAME]=j),p&&(c.push({}),c[c.length-1][qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_NAME]=qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_VALUE),c.push({key:e}),qq.each(k,function(a,b){var d=qq.s3.util.AWS_PARAM_PREFIX+a,e={};e[d]=encodeURIComponent(b),c.push(e)}),b.conditions=c,qq.s3.util.enforceSizeLimits(b,m,n),b},refreshPolicyCredentials:function(a,b){var c=!1;qq.each(a.conditions,function(a,d){qq.each(d,function(a){a===qq.s3.util.SESSION_TOKEN_PARAM_NAME&&(d[a]=b,c=!0)})}),c||(a.conditions.push({}),a.conditions[a.conditions.length-1][qq.s3.util.SESSION_TOKEN_PARAM_NAME]=b)},generateAwsParams:function(a,b){var c={},d=a.params,e=new qq.Promise,f=qq.s3.util.getPolicy(a),g=a.sessionToken,h=a.type,i=a.key,j=a.accessKey,k=a.acl,l=a.expectedStatus,m=qq.s3.util.getSuccessRedirectAbsoluteUrl(a.successRedirectUrl),n=a.reducedRedundancy,o=a.serverSideEncryption,p=a.log;return c.key=i,c.AWSAccessKeyId=j,h&&(c["Content-Type"]=h),l&&(c.success_action_status=l),m&&(c.success_action_redirect=m),n&&(c[qq.s3.util.REDUCED_REDUNDANCY_PARAM_NAME]=qq.s3.util.REDUCED_REDUNDANCY_PARAM_VALUE),o&&(c[qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_NAME]=qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_VALUE),g&&(c[qq.s3.util.SESSION_TOKEN_PARAM_NAME]=g),c.acl=k,qq.each(d,function(a,b){var d=qq.s3.util.AWS_PARAM_PREFIX+a;c[d]=encodeURIComponent(b)}),b(f).then(function(a,b,d){c.policy=a.policy,c.signature=a.signature,b&&(c.AWSAccessKeyId=b),d&&(c[qq.s3.util.SESSION_TOKEN_PARAM_NAME]=d),e.success(c)},function(a){a=a||"Can't continue further with request to S3 as we did not receive a valid signature and policy from the server.",p("Policy signing failed. "+a,"error"),e.failure(a)}),e},enforceSizeLimits:function(a,b,c){var d=0>b?0:b,e=0>=c?9007199254740992:c;(b>0||c>0)&&a.conditions.push(["content-length-range",d.toString(),e.toString()])},getPolicyExpirationDate:function(a){if(a.setMinutes(a.getMinutes()+5),Date.prototype.toISOString)return a.toISOString();var b=function(a){var b=String(a);return 1===b.length&&(b="0"+b),b};return a.getUTCFullYear()+"-"+b(a.getUTCMonth()+1)+"-"+b(a.getUTCDate())+"T"+b(a.getUTCHours())+":"+b(a.getUTCMinutes())+":"+b(a.getUTCSeconds())+"."+String((a.getUTCMilliseconds()/1e3).toFixed(3)).slice(2,5)+"Z"},parseIframeResponse:function(a){var b=a.contentDocument||a.contentWindow.document,c=b.location.search,d=/bucket=(.+)&key=(.+)&etag=(.+)/.exec(c);return d?{bucket:d[1],key:d[2],etag:d[3].replace(/%22/g,"")}:void 0},getSuccessRedirectAbsoluteUrl:function(a){if(a){var b,c=document.createElement("div");return qq.ie7()?(c.innerHTML="",b=c.firstChild,b.href):(b=document.createElement("a"),b.href=a,b.href=b.href,b.href)}},encodeQueryStringParam:function(a){var b=encodeURIComponent(a);return b=b.replace(/[!'()]/g,escape),b=b.replace(/\*/g,"%2A"),b.replace(/%20/g,"+")}}}(),function(){"use strict";qq.nonTraditionalBasePublicApi={setUploadSuccessParams:function(a,b){this._uploadSuccessParamsStore.set(a,b)},setUploadSuccessEndpoint:function(a,b){this._uploadSuccessEndpointStore.set(a,b)}},qq.nonTraditionalBasePrivateApi={_onComplete:function(a,b,c,d){var e,f,g=c.success?!0:!1,h=this,i=arguments,j=this._uploadSuccessEndpointStore.get(a),k=this._options.uploadSuccess.customHeaders,l=this._options.uploadSuccess.method,m=this._options.cors,n=new qq.Promise,o=this._uploadSuccessParamsStore.get(a),p=this._paramsStore.get(a),q=function(b){delete h._failedSuccessRequestCallbacks[a],qq.extend(c,b),qq.FineUploaderBasic.prototype._onComplete.apply(h,i),n.success(b)},r=function(f){var g=e;qq.extend(c,f),c&&c.reset&&(g=null),g?h._failedSuccessRequestCallbacks[a]=g:delete h._failedSuccessRequestCallbacks[a],h._onAutoRetry(a,b,c,d,g)||(qq.FineUploaderBasic.prototype._onComplete.apply(h,i),n.failure(f))};return g&&j?(f=new qq.UploadSuccessAjaxRequester({endpoint:j,method:l,customHeaders:k,cors:m,log:qq.bind(this.log,this)}),qq.extend(o,h._getEndpointSpecificParams(a,c,d),!0),p&&qq.extend(o,p,!0),e=qq.bind(function(){f.sendSuccessRequest(a,o).then(q,r)},h),e(),n):qq.FineUploaderBasic.prototype._onComplete.apply(this,arguments)},_manualRetry:function(a){var b=this._failedSuccessRequestCallbacks[a];return qq.FineUploaderBasic.prototype._manualRetry.call(this,a,b)}}}(),function(){"use strict";qq.s3.FineUploaderBasic=function(a){var b={request:{accessKey:null},objectProperties:{acl:"private",bucket:qq.bind(function(a){return qq.s3.util.getBucket(this.getEndpoint(a))},this),key:"uuid",reducedRedundancy:!1,serverSideEncryption:!1},credentials:{accessKey:null,secretKey:null,expiration:null,sessionToken:null},signature:{endpoint:null,customHeaders:{}},uploadSuccess:{endpoint:null,method:"POST",params:{},customHeaders:{}},iframeSupport:{localBlankPagePath:null},chunking:{partSize:5242880},cors:{allowXdr:!0},callbacks:{onCredentialsExpired:function(){}}};qq.extend(b,a,!0),this.setCredentials(b.credentials,!0)||(this._currentCredentials.accessKey=b.request.accessKey),this._aclStore=this._createStore(b.objectProperties.acl),qq.FineUploaderBasic.call(this,b),this._uploadSuccessParamsStore=this._createStore(this._options.uploadSuccess.params),this._uploadSuccessEndpointStore=this._createStore(this._options.uploadSuccess.endpoint),this._failedSuccessRequestCallbacks={},this._cannedKeys={},this._cannedBuckets={},this._buckets={}},qq.extend(qq.s3.FineUploaderBasic.prototype,qq.basePublicApi),qq.extend(qq.s3.FineUploaderBasic.prototype,qq.basePrivateApi),qq.extend(qq.s3.FineUploaderBasic.prototype,qq.nonTraditionalBasePublicApi),qq.extend(qq.s3.FineUploaderBasic.prototype,qq.nonTraditionalBasePrivateApi),qq.extend(qq.s3.FineUploaderBasic.prototype,{getBucket:function(a){return null==this._cannedBuckets[a]?this._buckets[a]:this._cannedBuckets[a]},getKey:function(a){return null==this._cannedKeys[a]?this._handler.getThirdPartyFileId(a):this._cannedKeys[a]},reset:function(){qq.FineUploaderBasic.prototype.reset.call(this),this._failedSuccessRequestCallbacks=[],this._buckets={}},setCredentials:function(a,b){if(a&&a.secretKey){if(!a.accessKey)throw new qq.Error("Invalid credentials: no accessKey");if(!a.expiration)throw new qq.Error("Invalid credentials: no expiration");return this._currentCredentials=qq.extend({},a),qq.isString(a.expiration)&&(this._currentCredentials.expiration=new Date(a.expiration)),!0}if(!b)throw new qq.Error("Invalid credentials parameter!");this._currentCredentials={}},setAcl:function(a,b){this._aclStore.set(a,b)},_createUploadHandler:function(){var a=this,b={aclStore:this._aclStore,getBucket:qq.bind(this._determineBucket,this),getKeyName:qq.bind(this._determineKeyName,this),iframeSupport:this._options.iframeSupport,objectProperties:this._options.objectProperties,signature:this._options.signature,validation:{minSizeLimit:this._options.validation.minSizeLimit,maxSizeLimit:this._options.validation.sizeLimit}};return qq.override(this._endpointStore,function(a){return{get:function(b){var c=a.get(b);return c.indexOf("http")<0?"http://"+c:c}}}),qq.override(this._paramsStore,function(a){return{get:function(b){var c=a.get(b),d={};return qq.each(c,function(a,b){d[a.toLowerCase()]=qq.isFunction(b)?b():b}),d}}}),b.signature.credentialsProvider={get:function(){return a._currentCredentials},onExpired:function(){var b=new qq.Promise,c=a._options.callbacks.onCredentialsExpired();return qq.isGenericPromise(c)?c.then(function(c){try{a.setCredentials(c),b.success()}catch(d){a.log("Invalid credentials returned from onCredentialsExpired callback! ("+d.message+")","error"),b.failure("onCredentialsExpired did not return valid credentials.")}},function(c){a.log("onCredentialsExpired callback indicated failure! ("+c+")","error"),b.failure("onCredentialsExpired callback failed.")}):(a.log("onCredentialsExpired callback did not return a promise!","error"),b.failure("Unexpected return value for onCredentialsExpired.")),b}},qq.FineUploaderBasic.prototype._createUploadHandler.call(this,b,"s3")},_determineBucket:function(a){var b=this._options.objectProperties.bucket,c=new qq.Promise,d=this;return qq.isFunction(b)?(b=b(a),qq.isGenericPromise(b)?c=b:c.success(b)):qq.isString(b)&&c.success(b),c.then(function(b){d._buckets[a]=b},function(b){qq.log("Problem determining bucket for ID "+a+" ("+b+")","error")}),c},_determineKeyName:function(a,b){var c=new qq.Promise,d=this._options.objectProperties.key,e=qq.getExtension(b),f=c.failure,g=function(a,b){var d=a;void 0!==b&&(d+="."+b),c.success(d)};switch(d){case"uuid":g(this.getUuid(a),e);break;case"filename":g(b);break;default:qq.isFunction(d)?this._handleKeynameFunction(d,a,g,f):(this.log(d+" is not a valid value for the s3.keyname option!","error"),f())}return c},_handleKeynameFunction:function(a,b,c,d){var e=this,f=function(a){c(a)},g=function(a){e.log(qq.format("Failed to retrieve key name for {}. Reason: {}",b,a||"null"),"error"),d(a)},h=a.call(this,b);qq.isGenericPromise(h)?h.then(f,g):null==h?g():f(h)},_getEndpointSpecificParams:function(a,b,c){var d={key:this.getKey(a),uuid:this.getUuid(a),name:this.getName(a),bucket:this.getBucket(a)};return c&&c.getResponseHeader("ETag")?d.etag=c.getResponseHeader("ETag"):b.etag&&(d.etag=b.etag),d},_onSubmitDelete:function(a,b){var c={key:this.getKey(a),bucket:this.getBucket(a)};return qq.FineUploaderBasic.prototype._onSubmitDelete.call(this,a,b,c)},_addCannedFile:function(a){var b;if(null==a.s3Key)throw new qq.Error("Did not find s3Key property in server session response. This is required!");return b=qq.FineUploaderBasic.prototype._addCannedFile.apply(this,arguments),this._cannedKeys[b]=a.s3Key,this._cannedBuckets[b]=a.s3Bucket,b}})}(),qq.s3.RequestSigner=function(a){"use strict";function b(a,b,c){var d,e,f=b.responseText,g=j[a],h=g.promise;if(delete j[a],f)try{e=qq.parseJson(f)}catch(i){k.log("Error attempting to parse signature response: "+i,"error")}e&&e.invalid?(c=!0,d="Invalid policy document or request headers!"):e?k.expectingPolicy&&!e.policy?(c=!0,d="Response does not include the base64 encoded policy!"):e.signature||(c=!0,d="Response does not include the signature!"):(c=!0,d="Received an empty or invalid response from the server!"),c?(d&&k.log(d,"error"),h.failure(d)):h.success(e)}function c(a,b,c,d,e,f,g){var h,j="POST",k=[],l="";switch(a){case i.REQUEST_TYPE.MULTIPART_ABORT:j="DELETE",h=qq.format("uploadId={}",f);break;case i.REQUEST_TYPE.MULTIPART_INITIATE:h="uploads";break;case i.REQUEST_TYPE.MULTIPART_COMPLETE:h=qq.format("uploadId={}",f);break;case i.REQUEST_TYPE.MULTIPART_UPLOAD:j="PUT",h=qq.format("partNumber={}&uploadId={}",g,f)}return h=c+"?"+h,qq.each(e,function(a){k.push(a)}),k.sort(),qq.each(k,function(a,b){l+=b+":"+e[b]+"\n"}),{toSign:qq.format("{}\n\n{}\n\n{}/{}/{}",j,d||"",l||"\n",b,h),endOfUrl:h}}function d(a,b,c,d){var g;a.signatureConstructor?(d&&(g=a.signatureConstructor.getHeaders(),g[qq.s3.util.SESSION_TOKEN_PARAM_NAME]=d,a.signatureConstructor.withHeaders(g)),f(a.signatureConstructor.getToSign().stringToSign,b)):(d&&qq.s3.util.refreshPolicyCredentials(a,d),e(a,b,c,d))}function e(a,b,c,d){var e=JSON.stringify(a),f=CryptoJS.enc.Utf8.parse(e),g=CryptoJS.enc.Base64.stringify(f),i=CryptoJS.HmacSHA1(g,h.get().secretKey),j=CryptoJS.enc.Base64.stringify(i);b.success({policy:g,signature:j},c,d)}function f(a,b){var c=CryptoJS.enc.Utf8.parse(a),d=CryptoJS.HmacSHA1(c,h.get().secretKey),e=CryptoJS.enc.Base64.stringify(d);b.success({signature:e})}var g,h,i=this,j={},k={expectingPolicy:!1,method:"POST",signatureSpec:{credentialsProvider:{},endpoint:null,customHeaders:{}},maxConnections:3,paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(){}};qq.extend(k,a,!0),h=k.signatureSpec.credentialsProvider,g=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",method:k.method,contentType:"application/json; charset=utf-8",endpointStore:{get:function(){return k.signatureSpec.endpoint}},paramsStore:k.paramsStore,maxConnections:k.maxConnections,customHeaders:k.signatureSpec.customHeaders,log:k.log,onComplete:b,cors:k.cors})),qq.extend(this,{getSignature:function(a,b){var c=b,e=new qq.Promise;return h.get().secretKey&&window.CryptoJS?h.get().expiration.getTime()>Date.now()?d(b,e):h.onExpired().then(function(){d(b,e,h.get().accessKey,h.get().sessionToken)},function(){k.log("Attempt to update expired credentials apparently failed! Unable to sign request. ","error"),e.failure("Unable to sign request - expired credentials.")}):(k.log("Submitting S3 signature request for "+a),c.signatureConstructor&&(c={headers:c.signatureConstructor.getToSign().stringToSign}),g.initTransport(a).withParams(c).send(),j[a]={promise:e}),e},constructStringToSign:function(a,b,d){var e,f,g,i,j={};return{withHeaders:function(a){return j=a,this},withUploadId:function(a){return e=a,this},withContentType:function(a){return f=a,this},withPartNum:function(a){return g=a,this},getToSign:function(){var k=h.get().sessionToken;return j["x-amz-date"]=(new Date).toUTCString(),k&&(j[qq.s3.util.SESSION_TOKEN_PARAM_NAME]=k),i=c(a,b,d,f,j,e,g),{headers:function(){return f&&(j["Content-Type"]=f),j}(),endOfUrl:i.endOfUrl,stringToSign:i.toSign}},getHeaders:function(){return qq.extend({},j)},getEndOfUrl:function(){return i&&i.endOfUrl}}}})},qq.s3.RequestSigner.prototype.REQUEST_TYPE={MULTIPART_INITIATE:"multipart_initiate",MULTIPART_COMPLETE:"multipart_complete",MULTIPART_ABORT:"multipart_abort",MULTIPART_UPLOAD:"multipart_upload"},qq.UploadSuccessAjaxRequester=function(a){"use strict";function b(a,b,c){var f,g=d[a],h=b.responseText,i={success:!0},j={success:!1};delete d[a],e.log(qq.format("Received the following response body to an upload success request for id {}: {}",a,h));try{f=qq.parseJson(h),c||f&&(f.error||f.success===!1)?(e.log("Upload success request was rejected by the server.","error"),g.failure(qq.extend(f,j))):(e.log("Upload success was acknowledged by the server."),g.success(qq.extend(f,i)))}catch(k){c?(e.log(qq.format("Your server indicated failure in its upload success request response for id {}!",a),"error"),g.failure(j)):(e.log("Upload success was acknowledged by the server."),g.success(i))}}var c,d=[],e={method:"POST",endpoint:null,maxConnections:3,customHeaders:{},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(){}};qq.extend(e,a),c=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",method:e.method,endpointStore:{get:function(){return e.endpoint}},paramsStore:e.paramsStore,maxConnections:e.maxConnections,customHeaders:e.customHeaders,log:e.log,onComplete:b,cors:e.cors})),qq.extend(this,{sendSuccessRequest:function(a,b){var f=new qq.Promise;return e.log("Submitting upload success request/notification for "+a),c.initTransport(a).withParams(b).send(),d[a]=f,f}})},qq.s3.InitiateMultipartAjaxRequester=function(a){"use strict";function b(a){var b,c=g.getBucket(a),d={},f=new qq.Promise,h=g.getKey(a);return d["x-amz-acl"]=g.aclStore.get(a),g.reducedRedundancy&&(d[qq.s3.util.REDUCED_REDUNDANCY_PARAM_NAME]=qq.s3.util.REDUCED_REDUNDANCY_PARAM_VALUE),g.serverSideEncryption&&(d[qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_NAME]=qq.s3.util.SERVER_SIDE_ENCRYPTION_PARAM_VALUE),d[qq.s3.util.AWS_PARAM_PREFIX+g.filenameParam]=encodeURIComponent(g.getName(a)),qq.each(g.paramsStore.get(a),function(a,b){d[qq.s3.util.AWS_PARAM_PREFIX+a]=encodeURIComponent(b)}),b=e.constructStringToSign(e.REQUEST_TYPE.MULTIPART_INITIATE,c,h).withContentType(g.getContentType(a)).withHeaders(d),e.getSignature(a,{signatureConstructor:b}).then(function(a){d=b.getHeaders(),d.Authorization="AWS "+g.signatureSpec.credentialsProvider.get().accessKey+":"+a.signature,f.success(d,b.getEndOfUrl())},f.failure),f}function c(a,b,c){var d,e,h,i,j,k=f[a],l=new DOMParser,m=l.parseFromString(b.responseText,"application/xml");delete f[a],c?(j=b.status,e=m.getElementsByTagName("Message"),e.length>0&&(i=e[0].textContent)):(d=m.getElementsByTagName("UploadId"),d.length>0?h=d[0].textContent:i="Upload ID missing from request"),void 0===h?(i?g.log(qq.format("Specific problem detected initiating multipart upload request for {}: '{}'.",a,i),"error"):g.log(qq.format("Unexplained error with initiate multipart upload request for {}. Status code {}.",a,j),"error"),k.failure("Problem initiating upload request.",b)):(g.log(qq.format("Initiate multipart upload request successful for {}. Upload ID is {}",a,h)),k.success(h,b))}var d,e,f={},g={filenameParam:"qqfilename",method:"POST",endpointStore:null,paramsStore:null,signatureSpec:null,aclStore:null,reducedRedundancy:!1,serverSideEncryption:!1,maxConnections:3,getContentType:function(){},getBucket:function(){},getKey:function(){},getName:function(){},log:function(){}};qq.extend(g,a),e=new qq.s3.RequestSigner({signatureSpec:g.signatureSpec,cors:g.cors,log:g.log}),d=qq.extend(this,new qq.AjaxRequester({method:g.method,contentType:null,endpointStore:g.endpointStore,maxConnections:g.maxConnections,allowXRequestedWithAndCacheControl:!1,log:g.log,onComplete:c,successfulResponseCodes:{POST:[200]}})),qq.extend(this,{send:function(a){var c=new qq.Promise;return b(a).then(function(b,e){g.log("Submitting S3 initiate multipart upload request for "+a),f[a]=c,d.initTransport(a).withPath(e).withHeaders(b).send()},c.failure),c}})},qq.s3.CompleteMultipartAjaxRequester=function(a){"use strict";function b(a,b){var c={},d=new qq.Promise,e=h.getBucket(a),g=f.constructStringToSign(f.REQUEST_TYPE.MULTIPART_COMPLETE,e,h.getKey(a)).withUploadId(b).withContentType("application/xml; charset=UTF-8");return f.getSignature(a,{signatureConstructor:g}).then(function(a){c=g.getHeaders(),c.Authorization="AWS "+h.signatureSpec.credentialsProvider.get().accessKey+":"+a.signature,d.success(c,g.getEndOfUrl())},d.failure),d}function c(a,b,c){var d=g[a],e=new DOMParser,f=h.getBucket(a),i=(h.getKey(a),e.parseFromString(b.responseText,"application/xml")),j=i.getElementsByTagName("Bucket"),k=i.getElementsByTagName("Key");delete g[a],h.log(qq.format("Complete response status {}, body = {}",b.status,b.responseText)),c?h.log(qq.format("Complete Multipart Upload request for {} failed with status {}.",a,b.status),"error"):j.length&&k.length?j[0].textContent!==f&&(c=!0,h.log(qq.format("Wrong bucket in response to Complete Multipart Upload request for {}.",a),"error")):(c=!0,h.log(qq.format("Missing bucket and/or key in response to Complete Multipart Upload request for {}.",a),"error")),c?d.failure("Problem combining the file parts!",b):d.success({},b)}function d(a){var b=document.implementation.createDocument(null,"CompleteMultipartUpload",null);return a.sort(function(a,b){return a.part-b.part}),qq.each(a,function(a,c){var d=c.part,e=c.etag,f=b.createElement("Part"),g=b.createElement("PartNumber"),h=b.createTextNode(d),i=b.createTextNode(e),j=b.createElement("ETag");j.appendChild(i),g.appendChild(h),f.appendChild(g),f.appendChild(j),qq(b).children()[0].appendChild(f)}),(new XMLSerializer).serializeToString(b)}var e,f,g={},h={method:"POST",contentType:"text/xml",endpointStore:null,signatureSpec:null,maxConnections:3,getBucket:function(){},getKey:function(){},log:function(){}};qq.extend(h,a),f=new qq.s3.RequestSigner({signatureSpec:h.signatureSpec,cors:h.cors,log:h.log}),e=qq.extend(this,new qq.AjaxRequester({method:h.method,contentType:"application/xml; charset=UTF-8",endpointStore:h.endpointStore,maxConnections:h.maxConnections,allowXRequestedWithAndCacheControl:!1,log:h.log,onComplete:c,successfulResponseCodes:{POST:[200]}})),qq.extend(this,{send:function(a,c,f){var i=new qq.Promise;return b(a,c).then(function(b,c){var j=d(f);h.log("Submitting S3 complete multipart upload request for "+a),g[a]=i,delete b["Content-Type"],e.initTransport(a).withPath(c).withHeaders(b).withPayload(j).send()},i.failure),i}})},qq.s3.AbortMultipartAjaxRequester=function(a){"use strict";function b(a,b){var c={},d=new qq.Promise,g=(f.endpointStore.get(a),f.getBucket(a)),h=e.constructStringToSign(e.REQUEST_TYPE.MULTIPART_ABORT,g,f.getKey(a)).withUploadId(b);return e.getSignature(a,{signatureConstructor:h}).then(function(a){c=h.getHeaders(),c.Authorization="AWS "+f.signatureSpec.credentialsProvider.get().accessKey+":"+a.signature,d.success(c,h.getEndOfUrl())},d.failure),d}function c(a,b,c){var d,e=new DOMParser,g=e.parseFromString(b.responseText,"application/xml"),h=g.getElementsByTagName("Error");f.log(qq.format("Abort response status {}, body = {}",b.status,b.responseText)),c?f.log(qq.format("Abort Multipart Upload request for {} failed with status {}.",a,b.status),"error"):h.length?(c=!0,d=g.getElementsByTagName("Message")[0].textContent,f.log(qq.format("Failed to Abort Multipart Upload request for {}. Error: {}",a,d),"error")):f.log(qq.format("Abort MPU request succeeded for file ID {}.",a))}var d,e,f={method:"DELETE",endpointStore:null,signatureSpec:null,maxConnections:3,getBucket:function(){},getKey:function(){},log:function(){}};qq.extend(f,a),e=new qq.s3.RequestSigner({signatureSpec:f.signatureSpec,cors:f.cors,log:f.log}),d=qq.extend(this,new qq.AjaxRequester({validMethods:["DELETE"],method:f.method,contentType:null,endpointStore:f.endpointStore,maxConnections:f.maxConnections,allowXRequestedWithAndCacheControl:!1,log:f.log,onComplete:c,successfulResponseCodes:{DELETE:[204]}})),qq.extend(this,{send:function(a,c){b(a,c).then(function(b,c){f.log("Submitting S3 Abort multipart upload request for "+a),d.initTransport(a).withPath(c).withHeaders(b).send()})}})},qq.s3.XhrUploadHandler=function(a,b){"use strict";var c=b.getName,d=b.log,e=200,f=a.getBucket,g=a.getKeyName,h=a.filenameParam,i=a.paramsStore,j=a.endpointStore,k=a.aclStore,l=a.objectProperties.reducedRedundancy,m=a.objectProperties.serverSideEncryption,n=a.validation,o=a.signature,p=this,q=a.signature.credentialsProvider,r={combine:function(a){var b=p._getPersistableData(a).uploadId,c=p._getPersistableData(a).etags,d=new qq.Promise;return s.completeMultipart.send(a,b,c).then(d.success,function(b,c){d.failure(u.done(a,c).response,c)}),d},done:function(a,b,c){var d,e=u.response.parse(a,b);e.success&&(d=b.getResponseHeader("ETag"),p._getPersistableData(a).etags||(p._getPersistableData(a).etags=[]),p._getPersistableData(a).etags.push({part:c+1,etag:d}))},initHeaders:function(b,c){var d={},e=(a.endpointStore.get(b),u.bucket.getName(b)),f=u.key.urlSafe(b),g=new qq.Promise,h=s.restSignature.constructStringToSign(s.restSignature.REQUEST_TYPE.MULTIPART_UPLOAD,e,f).withPartNum(c+1).withUploadId(p._getPersistableData(b).uploadId);return s.restSignature.getSignature(b+"."+c,{signatureConstructor:h}).then(function(a){d=h.getHeaders(),d.Authorization="AWS "+q.get().accessKey+":"+a.signature,g.success(d,h.getEndOfUrl())},g.failure),g},put:function(b,c){var d=p._createXhr(b,c),e=p._getChunkData(b,c),f=a.endpointStore.get(b),g=new qq.Promise;return r.initHeaders(b,c).then(function(a,h){var i=f+"/"+h;p._registerProgressHandler(b,c,e.size),u.track(b,d,c).then(g.success,g.failure),d.open("PUT",i,!0),qq.each(a,function(a,b){d.setRequestHeader(a,b)}),d.send(e.blob)},function(){g.failure({error:"Problem signing the chunk!"},d)}),g},send:function(a,b){var c=new qq.Promise;return r.setup(a).then(function(){r.put(a,b).then(c.success,c.failure)},function(a,b){c.failure({error:a},b)}),c},setup:function(a){var b=new qq.Promise,c=p._getPersistableData(a).uploadId,d=new qq.Promise;return c?c instanceof qq.Promise?c.then(function(a){b.success(a)}):b.success(c):(p._getPersistableData(a).uploadId=d,s.initiateMultipart.send(a).then(function(c){p._getPersistableData(a).uploadId=c,d.success(c),b.success(c)},function(c){p._getPersistableData(a).uploadId=null,b.failure(c),d.failure(c)})),b}},s={abortMultipart:new qq.s3.AbortMultipartAjaxRequester({endpointStore:j,signatureSpec:o,cors:a.cors,log:d,getBucket:function(a){return u.bucket.getName(a)},getKey:function(a){return u.key.urlSafe(a)}}),completeMultipart:new qq.s3.CompleteMultipartAjaxRequester({endpointStore:j,signatureSpec:o,cors:a.cors,log:d,getBucket:function(a){return u.bucket.getName(a)},getKey:function(a){return u.key.urlSafe(a)}}),initiateMultipart:new qq.s3.InitiateMultipartAjaxRequester({filenameParam:h,endpointStore:j,paramsStore:i,signatureSpec:o,aclStore:k,reducedRedundancy:l,serverSideEncryption:m,cors:a.cors,log:d,getContentType:function(a){return p._getMimeType(a)},getBucket:function(a){return u.bucket.getName(a)},getKey:function(a){return u.key.urlSafe(a)},getName:function(a){return c(a)}}),policySignature:new qq.s3.RequestSigner({expectingPolicy:!0,signatureSpec:o,cors:a.cors,log:d}),restSignature:new qq.s3.RequestSigner({signatureSpec:o,cors:a.cors,log:d})},t={initParams:function(a){var b=i.get(a);return b[h]=c(a),qq.s3.util.generateAwsParams({endpoint:j.get(a),params:b,type:p._getMimeType(a),bucket:u.bucket.getName(a),key:p.getThirdPartyFileId(a),accessKey:q.get().accessKey,sessionToken:q.get().sessionToken,acl:k.get(a),expectedStatus:e,minFileSize:n.minSizeLimit,maxFileSize:n.maxSizeLimit,reducedRedundancy:l,serverSideEncryption:m,log:d},qq.bind(s.policySignature.getSignature,this,a))},send:function(a){var b=new qq.Promise,c=p._createXhr(a),e=p.getFile(a);return p._registerProgressHandler(a),u.track(a,c).then(b.success,b.failure),t.setup(a,c,e).then(function(b){d("Sending upload request for "+a),c.send(b)},b.failure),b},setup:function(a,b,c){var d=new FormData,e=j.get(a),f=e,g=new qq.Promise;return t.initParams(a).then(function(a){b.open("POST",f,!0),qq.obj2FormData(a,d),d.append("file",c),g.success(d)},function(a){g.failure({error:a})}),g}},u={bucket:{promise:function(a){var b=new qq.Promise,c=p._getFileState(a).bucket;return c?b.success(c):f(a).then(function(c){p._getFileState(a).bucket=c,b.success(c)},b.failure),b},getName:function(a){return p._getFileState(a).bucket}},done:function(a,b){var c=u.response.parse(a,b),e=c.success!==!0;return e&&u.response.shouldReset(c.code)&&(d("This is an unrecoverable error, we must restart the upload entirely on the next retry attempt.","error"),c.reset=!0),{success:!e,response:c}},key:{promise:function(a){var b=new qq.Promise,d=p.getThirdPartyFileId(a);return null==d?(p._setThirdPartyFileId(a,b),g(a,c(a)).then(function(c){p._setThirdPartyFileId(a,c),b.success(c)},function(c){p._setThirdPartyFileId(a,null),b.failure(c)})):qq.isGenericPromise(d)?d.then(b.success,b.failure):b.success(d),b},urlSafe:function(a){return encodeURIComponent(p.getThirdPartyFileId(a))}},response:{parse:function(a,b){var c,f={};try{d(qq.format("Received response status {} with body: {}",b.status,b.responseText)),b.status===e?f.success=!0:(c=u.response.parseError(b.responseText),c&&(f.error=c.message,f.code=c.code))}catch(g){d("Error when attempting to parse xhr response text ("+g.message+")","error")}return f},parseError:function(a){var b,c,d=new DOMParser,e=d.parseFromString(a,"application/xml"),f=e.getElementsByTagName("Error"),g={};return f.length?(b=e.getElementsByTagName("Code"),c=e.getElementsByTagName("Message"),c.length&&(g.message=c[0].textContent),b.length&&(g.code=b[0].textContent),g):void 0},shouldReset:function(a){return"EntityTooSmall"===a||"InvalidPart"===a||"InvalidPartOrder"===a||"NoSuchUpload"===a}},start:function(a,b){var c=new qq.Promise;return u.key.promise(a).then(function(){u.bucket.promise(a).then(function(){null==b?t.send(a).then(c.success,c.failure):r.send(a,b).then(c.success,c.failure)})},function(a){c.failure({error:a})}),c},track:function(a,b,c){var d=new qq.Promise;return b.onreadystatechange=function(){if(4===b.readyState){var e;null==c?(e=u.done(a,b),d[e.success?"success":"failure"](e.response,b)):(r.done(a,b,c),e=u.done(a,b),d[e.success?"success":"failure"](e.response,b))
+}},d}};qq.extend(this,{uploadChunk:u.start,uploadFile:u.start}),qq.extend(this,new qq.XhrUploadHandler({options:qq.extend({namespace:"s3"},a),proxy:qq.extend({getEndpoint:a.endpointStore.get},b)})),qq.override(this,function(a){return{expunge:function(b){var c=p._getPersistableData(b)&&p._getPersistableData(b).uploadId,d=p._maybeDeletePersistedChunkData(b);void 0!==c&&d&&s.abortMultipart.send(b,c),a.expunge(b)},finalizeChunks:function(a){return r.combine(a)},_getLocalStorageId:function(b){var c=a._getLocalStorageId(b),d=u.bucket.getName(b);return c+"-"+d}}})},qq.s3.FormUploadHandler=function(a,b){"use strict";function c(b,c){var d,e,f,g=a.endpointStore.get(b),i=qq.s3.util.getBucket(g);try{if(d=c.contentDocument||c.contentWindow.document,e=d.body.innerHTML,f=qq.s3.util.parseIframeResponse(c),f.bucket===i&&f.key===qq.s3.util.encodeQueryStringParam(h.getThirdPartyFileId(b)))return!0;l("Response from AWS included an unexpected bucket or key name.","error")}catch(j){l("Error when attempting to parse form upload response ("+j.message+")","error")}return!1}function d(a){var b=p.get(a);return b[o]=j(a),qq.s3.util.generateAwsParams({endpoint:q.get(a),params:b,bucket:h._getFileState(a).bucket,key:h.getThirdPartyFileId(a),accessKey:x.get().accessKey,sessionToken:x.get().sessionToken,acl:r.get(a),minFileSize:u.minSizeLimit,maxFileSize:u.maxSizeLimit,successRedirectUrl:w,reducedRedundancy:s,serverSideEncryption:t,log:l},qq.bind(y.getSignature,this,a))}function e(b,c){var e=new qq.Promise,f="POST",i=a.endpointStore.get(b),k=j(b);return d(b).then(function(a){var b=h._initFormForUpload({method:f,endpoint:i,params:a,paramsInBody:!0,targetName:c.name});e.success(b)},function(a){e.failure(a),g(b,c,k,{error:a})}),e}function f(a){var b=h._createIframe(a),d=h.getInput(a),f=new qq.Promise;return e(a,b).then(function(e){e.appendChild(d),h._attachLoadEvent(b,function(d){l("iframe loaded"),d?d.success===!1&&(l("Amazon likely rejected the upload request","error"),f.failure(d)):(d={},d.success=c(a,b),d.success===!1?(l("A success response was received by Amazon, but it was invalid in some way.","error"),f.failure(d)):(qq.extend(d,qq.s3.util.parseIframeResponse(b)),f.success(d))),g(a,b)}),l("Sending upload request for "+a),e.submit(),qq(e).remove()},f.failure),f}function g(a,b){h._detachLoadEvent(a),b&&qq(b).remove()}var h=this,i=b.onUuidChanged,j=b.getName,k=b.getUuid,l=b.log,m=a.getBucket,n=a.getKeyName,o=a.filenameParam,p=a.paramsStore,q=a.endpointStore,r=a.aclStore,s=a.objectProperties.reducedRedundancy,t=a.objectProperties.serverSideEncryption,u=a.validation,v=a.signature,w=a.iframeSupport.localBlankPagePath,x=a.signature.credentialsProvider,y=new qq.s3.RequestSigner({signatureSpec:v,cors:a.cors,log:l});if(void 0===w)throw new Error("successRedirectEndpoint MUST be defined if you intend to use browsers that do not support the File API!");qq.extend(this,new qq.FormUploadHandler({options:{isCors:!1,inputName:"file"},proxy:{onCancel:a.onCancel,onUuidChanged:i,getName:j,getUuid:k,log:l}})),qq.extend(this,{uploadFile:function(a){var b=j(a),c=new qq.Promise;return h.getThirdPartyFileId(a)?h._getFileState(a).bucket?f(a).then(c.success,c.failure):m(a).then(function(b){h._getFileState(a).bucket=b,f(a).then(c.success,c.failure)}):n(a,b).then(function(b){m(a).then(function(d){h._getFileState(a).bucket=d,h._setThirdPartyFileId(a,b),f(a).then(c.success,c.failure)},function(a){c.failure({error:a})})},function(a){c.failure({error:a})}),c}})},function(){"use strict";qq.s3.FineUploader=function(a){var b={failedUploadTextDisplay:{mode:"custom"}};qq.extend(b,a,!0),qq.FineUploader.call(this,b,"s3"),qq.supportedFeatures.ajaxUploading||void 0!==b.iframeSupport.localBlankPagePath||(this._options.element.innerHTML="
You MUST set the localBlankPagePath property of the iframeSupport option since this browser does not support the File API!
")},qq.extend(qq.s3.FineUploader.prototype,qq.s3.FineUploaderBasic.prototype),qq.extend(qq.s3.FineUploader.prototype,qq.uiPublicApi),qq.extend(qq.s3.FineUploader.prototype,qq.uiPrivateApi)}(),qq.PasteSupport=function(a){"use strict";function b(a){return a.type&&0===a.type.indexOf("image/")}function c(){f=qq(e.targetElement).attach("paste",function(a){var c=a.clipboardData;c&&qq.each(c.items,function(a,c){if(b(c)){var d=c.getAsFile();e.callbacks.pasteReceived(d)}})})}function d(){f&&f()}var e,f;e={targetElement:null,callbacks:{log:function(){},pasteReceived:function(){}}},qq.extend(e,a),c(),qq.extend(this,{reset:function(){d()}})},qq.DragAndDrop=function(a){"use strict";function b(a,b){var c=Array.prototype.slice.call(a);j.callbacks.dropLog("Grabbed "+a.length+" dropped files."),b.dropDisabled(!1),j.callbacks.processingDroppedFilesComplete(c,b.getElement())}function c(a){var b=new qq.Promise;return a.isFile?a.file(function(c){var d=a.name,e=a.fullPath,f=e.indexOf(d);e=e.substr(0,f),"/"===e.charAt(0)&&(e=e.substr(1)),c.qqPath=e,n.push(c),b.success()},function(c){j.callbacks.dropLog("Problem parsing '"+a.fullPath+"'. FileError code "+c.code+".","error"),b.failure()}):a.isDirectory&&d(a).then(function(a){var d=a.length;qq.each(a,function(a,e){c(e).done(function(){d-=1,0===d&&b.success()})}),a.length||b.success()},function(c){j.callbacks.dropLog("Problem parsing '"+a.fullPath+"'. FileError code "+c.code+".","error"),b.failure()}),b}function d(a,b,c,e){var f=e||new qq.Promise,g=b||a.createReader();return g.readEntries(function(b){var e=c?c.concat(b):b;b.length?setTimeout(function(){d(a,g,e,f)},0):f.success(e)},f.failure),f}function e(a,b){var d=[],e=new qq.Promise;return j.callbacks.processingDroppedFiles(),b.dropDisabled(!0),a.files.length>1&&!j.allowMultipleItems?(j.callbacks.processingDroppedFilesComplete([]),j.callbacks.dropError("tooManyFilesError",""),b.dropDisabled(!1),e.failure()):(n=[],qq.isFolderDropSupported(a)?qq.each(a.items,function(a,b){var f=b.webkitGetAsEntry();f&&(f.isFile?n.push(b.getAsFile()):d.push(c(f).done(function(){d.pop(),0===d.length&&e.success()})))}):n=a.files,0===d.length&&e.success()),e}function f(a){var c=new qq.UploadDropZone({HIDE_ZONES_EVENT_NAME:k,element:a,onEnter:function(b){qq(a).addClass(j.classes.dropActive),b.stopPropagation()},onLeaveNotDescendants:function(){qq(a).removeClass(j.classes.dropActive)},onDrop:function(a){e(a.dataTransfer,c).then(function(){b(n,c)},function(){j.callbacks.dropLog("Drop event DataTransfer parsing failed. No files will be uploaded.","error")})}});return o.addDisposer(function(){c.dispose()}),qq(a).hasAttribute(l)&&qq(a).hide(),m.push(c),c}function g(a){var b;return qq.each(a.dataTransfer.types,function(a,c){return"Files"===c?(b=!0,!1):void 0}),b}function h(a){return qq.firefox()?!a.relatedTarget:qq.safari()?a.x<0||a.y<0:0===a.x&&0===a.y}function i(){var a=j.dropZoneElements,b=function(){setTimeout(function(){qq.each(a,function(a,b){qq(b).hasAttribute(l)&&qq(b).hide(),qq(b).removeClass(j.classes.dropActive)})},10)};qq.each(a,function(b,c){var d=f(c);a.length&&qq.supportedFeatures.fileDrop&&o.attach(document,"dragenter",function(b){!d.dropDisabled()&&g(b)&&qq.each(a,function(a,b){b instanceof HTMLElement&&qq(b).hasAttribute(l)&&qq(b).css({display:"block"})})})}),o.attach(document,"dragleave",function(a){h(a)&&b()}),o.attach(qq(document).children()[0],"mouseenter",function(){b()}),o.attach(document,"drop",function(a){a.preventDefault(),b()}),o.attach(document,k,b)}var j,k="qq-hidezones",l="qq-hide-dropzone",m=[],n=[],o=new qq.DisposeSupport;j={dropZoneElements:[],allowMultipleItems:!0,classes:{dropActive:null},callbacks:new qq.DragAndDrop.callbacks},qq.extend(j,a,!0),i(),qq.extend(this,{setupExtraDropzone:function(a){j.dropZoneElements.push(a),f(a)},removeDropzone:function(a){var b,c=j.dropZoneElements;for(b in c)if(c[b]===a)return c.splice(b,1)},dispose:function(){o.dispose(),qq.each(m,function(a,b){b.dispose()})}})},qq.DragAndDrop.callbacks=function(){"use strict";return{processingDroppedFiles:function(){},processingDroppedFilesComplete:function(){},dropError:function(a,b){qq.log("Drag & drop error code '"+a+" with these specifics: '"+b+"'","error")},dropLog:function(a,b){qq.log(a,b)}}},qq.UploadDropZone=function(a){"use strict";function b(){return qq.safari()||qq.firefox()&&qq.windows()}function c(){k||(b?l.attach(document,"dragover",function(a){a.preventDefault()}):l.attach(document,"dragover",function(a){a.dataTransfer&&(a.dataTransfer.dropEffect="none",a.preventDefault())}),k=!0)}function d(a){if(!qq.supportedFeatures.fileDrop)return!1;var b,c=a.dataTransfer,d=qq.safari();return b=qq.ie()&&qq.supportedFeatures.fileDrop?!0:"none"!==c.effectAllowed,c&&b&&(c.files||!d&&c.types.contains&&c.types.contains("Files"))}function e(a){return void 0!==a&&(j=a),j}function f(){function a(){b=document.createEvent("Event"),b.initEvent(h.HIDE_ZONES_EVENT_NAME,!0,!0)}var b;if(window.CustomEvent)try{b=new CustomEvent(h.HIDE_ZONES_EVENT_NAME)}catch(c){a()}else a();document.dispatchEvent(b)}function g(){l.attach(i,"dragover",function(a){if(d(a)){var b=qq.ie()&&qq.supportedFeatures.fileDrop?null:a.dataTransfer.effectAllowed;a.dataTransfer.dropEffect="move"===b||"linkMove"===b?"move":"copy",a.stopPropagation(),a.preventDefault()}}),l.attach(i,"dragenter",function(a){if(!e()){if(!d(a))return;h.onEnter(a)}}),l.attach(i,"dragleave",function(a){if(d(a)){h.onLeave(a);var b=document.elementFromPoint(a.clientX,a.clientY);qq(this).contains(b)||h.onLeaveNotDescendants(a)}}),l.attach(i,"drop",function(a){if(!e()){if(!d(a))return;a.preventDefault(),a.stopPropagation(),h.onDrop(a),f()}})}var h,i,j,k,l=new qq.DisposeSupport;h={element:null,onEnter:function(){},onLeave:function(){},onLeaveNotDescendants:function(){},onDrop:function(){}},qq.extend(h,a),i=h.element,c(),g(),qq.extend(this,{dropDisabled:function(a){return e(a)},dispose:function(){l.dispose()},getElement:function(){return i}})},qq.DeleteFileAjaxRequester=function(a){"use strict";function b(){return"POST"===d.method.toUpperCase()?{_method:"DELETE"}:{}}var c,d={method:"DELETE",uuidParamName:"qquuid",endpointStore:{},maxConnections:3,customHeaders:function(){return{}},paramsStore:{},cors:{expected:!1,sendCredentials:!1},log:function(){},onDelete:function(){},onDeleteComplete:function(){}};qq.extend(d,a),c=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["POST","DELETE"],method:d.method,endpointStore:d.endpointStore,paramsStore:d.paramsStore,mandatedParams:b(),maxConnections:d.maxConnections,customHeaders:function(a){return d.customHeaders.get(a)},log:d.log,onSend:d.onDelete,onComplete:d.onDeleteComplete,cors:d.cors})),qq.extend(this,{sendDelete:function(a,b,e){var f=e||{};d.log("Submitting delete file request for "+a),"DELETE"===d.method?c.initTransport(a).withPath(b).withParams(f).send():(f[d.uuidParamName]=b,c.initTransport(a).withParams(f).send())}})},function(){function a(a){var b,c=a.naturalWidth,d=a.naturalHeight,e=document.createElement("canvas");return c*d>1048576?(e.width=e.height=1,b=e.getContext("2d"),b.drawImage(a,-c+1,0),0===b.getImageData(0,0,1,1).data[3]):!1}function b(a,b,c){var d,e,f,g,h=document.createElement("canvas"),i=0,j=c,k=c;for(h.width=1,h.height=c,d=h.getContext("2d"),d.drawImage(a,0,0),e=d.getImageData(0,0,1,c).data;k>i;)f=e[4*(k-1)+3],0===f?j=k:i=k,k=j+i>>1;return g=k/c,0===g?1:g}function c(a,b,c){var d=document.createElement("canvas"),f=b.mime||"image/jpeg";return e(a,d,b,c),d.toDataURL(f,b.quality||.8)}function d(a){var b=5241e3;if(!qq.ios())throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");return a.origHeight*a.origWidth>b?{newHeight:Math.round(Math.sqrt(b*(a.origHeight/a.origWidth))),newWidth:Math.round(Math.sqrt(b*(a.origWidth/a.origHeight)))}:void 0}function e(c,e,g,h){var i,j=c.naturalWidth,k=c.naturalHeight,l=g.width,m=g.height,n=e.getContext("2d");n.save(),qq.supportedFeatures.unlimitedScaledImageSize||(i=d({origWidth:l,origHeight:m}),i&&(qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",l,m,i.newWidth,i.newHeight),"warn"),l=i.newWidth,m=i.newHeight)),f(e,l,m,g.orientation),qq.ios()?function(){a(c)&&(j/=2,k/=2);var d,e,f,g=1024,i=document.createElement("canvas"),o=h?b(c,j,k):1,p=Math.ceil(g*l/j),q=Math.ceil(g*m/k/o),r=0,s=0;for(i.width=i.height=g,d=i.getContext("2d");k>r;){for(e=0,f=0;j>e;)d.clearRect(0,0,g,g),d.drawImage(c,-e,-r),n.drawImage(i,0,0,g,g,f,s,p,q),e+=g,f+=p;r+=g,s+=q}n.restore(),i=d=null}():n.drawImage(c,0,0,l,m),e.qqImageRendered&&e.qqImageRendered()}function f(a,b,c,d){switch(d){case 5:case 6:case 7:case 8:a.width=c,a.height=b;break;default:a.width=b,a.height=c}var e=a.getContext("2d");switch(d){case 2:e.translate(b,0),e.scale(-1,1);break;case 3:e.translate(b,c),e.rotate(Math.PI);break;case 4:e.translate(0,c),e.scale(1,-1);break;case 5:e.rotate(.5*Math.PI),e.scale(1,-1);break;case 6:e.rotate(.5*Math.PI),e.translate(0,-c);break;case 7:e.rotate(.5*Math.PI),e.translate(b,-c),e.scale(-1,1);break;case 8:e.rotate(-.5*Math.PI),e.translate(-b,0)}}function g(a,b){var c=this;window.Blob&&a instanceof Blob&&function(){var b=new Image,d=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;if(!d)throw Error("No createObjectURL function found to create blob url");b.src=d.createObjectURL(a),c.blob=a,a=b}(),a.naturalWidth||a.naturalHeight||(a.onload=function(){var a=c.imageLoadListeners;a&&(c.imageLoadListeners=null,setTimeout(function(){for(var b=0,c=a.length;c>b;b++)a[b]()},0))},a.onerror=b,this.imageLoadListeners=[]),this.srcImage=a}g.prototype.render=function(a,b){b=b||{};var d,f=this,g=this.srcImage.naturalWidth,h=this.srcImage.naturalHeight,i=b.width,j=b.height,k=b.maxWidth,l=b.maxHeight,m=!this.blob||"image/jpeg"===this.blob.type,n=a.tagName.toLowerCase();return this.imageLoadListeners?(this.imageLoadListeners.push(function(){f.render(a,b)}),void 0):(i&&!j?j=h*i/g<<0:j&&!i?i=g*j/h<<0:(i=g,j=h),k&&i>k&&(i=k,j=h*i/g<<0),l&&j>l&&(j=l,i=g*j/h<<0),d={width:i,height:j},qq.each(b,function(a,b){d[a]=b}),"img"===n?function(){var b=a.src;a.src=c(f.srcImage,d,m),b===a.src&&a.onload()}():"canvas"===n&&e(this.srcImage,a,d,m),"function"==typeof this.onrender&&this.onrender(a),void 0)},qq.MegaPixImage=g}(),qq.ImageGenerator=function(a){"use strict";function b(a){return"img"===a.tagName.toLowerCase()}function c(a){return"canvas"===a.tagName.toLowerCase()}function d(){return void 0!==(new Image).crossOrigin}function e(){var a=document.createElement("canvas");return a.getContext&&a.getContext("2d")}function f(a){var b=a.split("/"),c=b[b.length-1],d=qq.getExtension(c);switch(d=d&&d.toLowerCase()){case"jpeg":case"jpg":return"image/jpeg";case"png":return"image/png";case"bmp":return"image/bmp";case"gif":return"image/gif";case"tiff":case"tif":return"image/tiff"}}function g(a){var b,c,d,e=document.createElement("a");return e.href=a,b=e.protocol,d=e.port,c=e.hostname,b.toLowerCase()!==window.location.protocol.toLowerCase()?!0:c.toLowerCase()!==window.location.hostname.toLowerCase()?!0:d===window.location.port||qq.ie()?!1:!0}function h(b,c){b.onload=function(){b.onload=null,b.onerror=null,c.success(b)},b.onerror=function(){b.onload=null,b.onerror=null,a("Problem drawing thumbnail!","error"),c.failure(b,"Problem drawing thumbnail!")}}function i(a,b){a.qqImageRendered=function(){b.success(a)}}function j(d,e){var f=b(d)||c(d);return b(d)?h(d,e):c(d)?i(d,e):(e.failure(d),a(qq.format("Element container of type {} is not supported!",d.tagName),"error")),f}function k(b,c,d){var e=new qq.Promise,f=new qq.Identify(b,a),g=d.maxSize,h=null==d.orient?!0:d.orient,i=function(){c.onerror=null,c.onload=null,a("Could not render preview, file may be too large!","error"),e.failure(c,"Browser cannot render image!")};return f.isPreviewable().then(function(d){var f={parse:function(){return(new qq.Promise).success()}},k=h?new qq.Exif(b,a):f,l=new qq.MegaPixImage(b,i);j(c,e)&&k.parse().then(function(a){var b=a&&a.Orientation;l.render(c,{maxWidth:g,maxHeight:g,orientation:b,mime:d})},function(b){a(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.",b)),l.render(c,{maxWidth:g,maxHeight:g,mime:d})})},function(){a("Not previewable"),e.failure(c,"Not previewable")}),e}function l(a,b,c,d){var e=new Image,h=new qq.Promise;j(e,h),g(a)&&(e.crossOrigin="anonymous"),e.src=a,h.then(function(){j(b,c);var g=new qq.MegaPixImage(e);g.render(b,{maxWidth:d,maxHeight:d,mime:f(a)})},c.failure)}function m(a,b,c,d){j(b,c),qq(b).css({maxWidth:d+"px",maxHeight:d+"px"}),b.src=a}function n(a,f,h){var i=new qq.Promise,k=h.scale,n=k?h.maxSize:null;return k&&b(f)?e()?g(a)&&!d()?m(a,f,i,n):l(a,f,i,n):m(a,f,i,n):c(f)?l(a,f,i,n):j(f,i)&&(f.src=a),i}qq.extend(this,{generate:function(b,c,d){return qq.isString(b)?(a("Attempting to update thumbnail based on server response."),n(b,c,d||{})):(a("Attempting to draw client-side image preview."),k(b,c,d||{}))}})},qq.Exif=function(a,b){"use strict";function c(a){for(var b=0,c=0;a.length>0;)b+=parseInt(a.substring(0,2),16)*Math.pow(2,c),a=a.substring(2,a.length),c+=8;return b}function d(b,c){var e=b,f=c;return void 0===e&&(e=2,f=new qq.Promise),qq.readBlobToHex(a,e,4).then(function(a){var b,c=/^ffe([0-9])/.exec(a);c?"1"!==c[1]?(b=parseInt(a.slice(4,8),16),d(e+b+2,f)):f.success(e):f.failure("No EXIF header to be found!")}),f}function e(){var b=new qq.Promise;return qq.readBlobToHex(a,0,6).then(function(a){0!==a.indexOf("ffd8")?b.failure("Not a valid JPEG!"):d().then(function(a){b.success(a)},function(a){b.failure(a)})}),b}function f(b){var c=new qq.Promise;return qq.readBlobToHex(a,b+10,2).then(function(a){c.success("4949"===a)}),c}function g(b,d){var e=new qq.Promise;return qq.readBlobToHex(a,b+18,2).then(function(a){return d?e.success(c(a)):(e.success(parseInt(a,16)),void 0)}),e}function h(b,c){var d=b+20,e=12*c;return qq.readBlobToHex(a,d,e)}function i(a){for(var b=[],c=0;c+24<=a.length;)b.push(a.slice(c,c+24)),c+=24;return b}function j(a,b){var d=16,e=qq.extend([],k),f={};return qq.each(b,function(b,g){var h,i,j,k=g.slice(0,4),m=a?c(k):parseInt(k,16),n=e.indexOf(m);return n>=0&&(i=l[m].name,j=l[m].bytes,h=g.slice(d,d+2*j),f[i]=a?c(h):parseInt(h,16),e.splice(n,1)),0===e.length?!1:void 0}),f}var k=[274],l={274:{name:"Orientation",bytes:2}};qq.extend(this,{parse:function(){var c=new qq.Promise,d=function(a){b(qq.format("EXIF header parse failed: '{}' ",a)),c.failure(a)};return e().then(function(e){b(qq.format("Moving forward with EXIF header parsing for '{}'",void 0===a.name?"blob":a.name)),f(e).then(function(a){b(qq.format("EXIF Byte order is {} endian",a?"little":"big")),g(e,a).then(function(f){b(qq.format("Found {} APP1 directory entries",f)),h(e,f).then(function(d){var e=i(d),f=j(a,e);b("Successfully parsed some EXIF tags"),c.success(f)},d)},d)},d)},d),c}})},qq.Identify=function(a,b){"use strict";function c(a,b){var c=!1,d=[].concat(a);return qq.each(d,function(a,d){return 0===b.indexOf(d)?(c=!0,!1):void 0}),c}qq.extend(this,{isPreviewable:function(){var d=this,e=new qq.Promise,f=!1,g=void 0===a.name?"blob":a.name;return b(qq.format("Attempting to determine if {} can be rendered in this browser",g)),b("First pass: check type attribute of blob object."),this.isPreviewableSync()?(b("Second pass: check for magic bytes in file header."),qq.readBlobToHex(a,0,4).then(function(a){qq.each(d.PREVIEWABLE_MIME_TYPES,function(b,d){return c(d,a)?(("image/tiff"!==b||qq.supportedFeatures.tiffPreviews)&&(f=!0,e.success(b)),!1):void 0}),b(qq.format("'{}' is {} able to be rendered in this browser",g,f?"":"NOT")),f||e.failure()},function(){b("Error reading file w/ name '"+g+"'. Not able to be rendered in this browser."),e.failure()})):e.failure(),e},isPreviewableSync:function(){var c=a.type,d=qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES),c)>=0,e=!1,f=void 0===a.name?"blob":a.name;return d&&(e="image/tiff"===c?qq.supportedFeatures.tiffPreviews:!0),!e&&b(f+" is not previewable in this browser per the blob's type attr"),e}})},qq.Identify.prototype.PREVIEWABLE_MIME_TYPES={"image/jpeg":"ffd8ff","image/gif":"474946","image/png":"89504e","image/bmp":"424d","image/tiff":["49492a00","4d4d002a"]},qq.ImageValidation=function(a,b){"use strict";function c(a){var b=!1;return qq.each(a,function(a,c){return c>0?(b=!0,!1):void 0}),b}function d(){var c=new qq.Promise;return new qq.Identify(a,b).isPreviewable().then(function(){var d=new Image,e=window.URL&&window.URL.createObjectURL?window.URL:window.webkitURL&&window.webkitURL.createObjectURL?window.webkitURL:null;e?(d.onerror=function(){b("Cannot determine dimensions for image. May be too large.","error"),c.failure()},d.onload=function(){c.success({width:this.width,height:this.height})},d.src=e.createObjectURL(a)):(b("No createObjectURL function available to generate image URL!","error"),c.failure())},c.failure),c}function e(a,b){var c;return qq.each(a,function(a,d){if(d>0){var e=/(max|min)(Width|Height)/.exec(a),f=e[2].charAt(0).toLowerCase()+e[2].slice(1),g=b[f];switch(e[1]){case"min":if(d>g)return c=a,!1;break;case"max":if(g>d)return c=a,!1}}}),c}this.validate=function(a){var f=new qq.Promise;return b("Attempting to validate image."),c(a)?d().then(function(b){var c=e(a,b);c?f.failure(c):f.success()},f.success):f.success(),f}},qq.Session=function(a){"use strict";function b(a){return qq.isArray(a)?!0:(d.log("Session response is not an array.","error"),void 0)}function c(a,c,e,f){var g=!1;c=c&&b(a),c&&qq.each(a,function(a,b){if(null==b.uuid)g=!0,d.log(qq.format("Session response item {} did not include a valid UUID - ignoring.",a),"error");else if(null==b.name)g=!0,d.log(qq.format("Session response item {} did not include a valid name - ignoring.",a),"error");else try{return d.addFileRecord(b),!0}catch(c){g=!0,d.log(c.message,"error")}return!1}),f[c&&!g?"success":"failure"](a,e)}var d={endpoint:null,params:{},customHeaders:{},cors:{},addFileRecord:function(){},log:function(){}};qq.extend(d,a,!0),this.refresh=function(){var a=new qq.Promise,b=function(b,d,e){c(b,d,e,a)},e=qq.extend({},d),f=new qq.SessionAjaxRequester(qq.extend(e,{onComplete:b}));return f.queryServer(),a}},qq.SessionAjaxRequester=function(a){"use strict";function b(a,b,c){var e=null;if(null!=b.responseText)try{e=qq.parseJson(b.responseText)}catch(f){d.log("Problem parsing session response: "+f.message,"error"),c=!0}d.onComplete(e,!c,b)}var c,d={endpoint:null,customHeaders:{},params:{},cors:{expected:!1,sendCredentials:!1},onComplete:function(){},log:function(){}};qq.extend(d,a),c=qq.extend(this,new qq.AjaxRequester({acceptHeader:"application/json",validMethods:["GET"],method:"GET",endpointStore:{get:function(){return d.endpoint}},customHeaders:d.customHeaders,log:d.log,onComplete:b,cors:d.cors})),qq.extend(this,{queryServer:function(){var a=qq.extend({},d.params);d.log("Session query request."),c.initTransport("sessionRefresh").withParams(a).withCacheBuster().send()}})},qq.FormSupport=function(a,b,c){"use strict";function d(a){a.getAttribute("action")&&(h.newEndpoint=a.getAttribute("action"))}function e(a,b){return!a.checkValidity||a.checkValidity()?!0:(c("Form did not pass validation checks - will not upload.","error"),b(),void 0)}function f(a){var c=a.submit;qq(a).attach("submit",function(d){d=d||window.event,d.preventDefault?d.preventDefault():d.returnValue=!1,e(a,c)&&b()}),a.submit=function(){e(a,c)&&b()}}function g(a){return a&&(qq.isString(a)&&(a=document.getElementById(a)),a&&(c("Attaching to form element."),d(a),i&&f(a))),a}var h=this,i=a.interceptSubmit,j=a.element,k=a.autoUpload;qq.extend(this,{newEndpoint:null,newAutoUpload:k,attachedToForm:!1,getFormInputsAsObject:function(){return null==j?null:h._form2Obj(j)}}),j=g(j),this.attachedToForm=!!j},qq.extend(qq.FormSupport.prototype,{_form2Obj:function(a){"use strict";var b={},c=function(a){var b=["button","image","reset","submit"];return qq.indexOf(b,a.toLowerCase())<0},d=function(a){return qq.indexOf(["checkbox","radio"],a.toLowerCase())>=0},e=function(a){return d(a.type)&&!a.checked?!0:a.disabled&&"hidden"!==a.type.toLowerCase()},f=function(a){var b=null;return qq.each(qq(a).children(),function(a,c){return"option"===c.tagName.toLowerCase()&&c.selected?(b=c.value,!1):void 0}),b};return qq.each(a.elements,function(a,d){if(!qq.isInput(d,!0)&&"textarea"!==d.tagName.toLowerCase()||!c(d.type)||e(d)){if("select"===d.tagName.toLowerCase()&&!e(d)){var g=f(d);null!==g&&(b[d.name]=g)}}else b[d.name]=d.value}),b}}),qq.Scaler=function(a,b){"use strict";var c=a.sendOriginal,d=a.orient,e=a.defaultType,f=a.defaultQuality/100,g=a.failureText,h=a.includeExif,i=this._getSortedSizes(a.sizes);qq.extend(this,{enabled:qq.supportedFeatures.scaling&&i.length>0,getFileRecords:function(a,j,k){var l=this,m=[],n=k.blob?k.blob:k,o=new qq.Identify(n,b);return o.isPreviewableSync()?(qq.each(i,function(a,c){var i=l._determineOutputType({defaultType:e,requestedType:c.type,refType:n.type});m.push({uuid:qq.getUniqueId(),name:l._getName(j,{name:c.name,type:i,refType:n.type}),blob:new qq.BlobProxy(n,qq.bind(l._generateScaledImage,l,{maxSize:c.maxSize,orient:d,type:i,quality:f,failedText:g,includeExif:h,log:b}))})}),m.push({uuid:a,name:j,size:n.size,blob:c?n:null})):m.push({uuid:a,name:j,size:n.size,blob:n}),m},handleNewFile:function(a,b,c,d,e,f,g,h){var i=this,j=(a.qqButtonId||a.blob&&a.blob.qqButtonId,[]),k=null,l=h.addFileToHandler,m=h.uploadData,n=h.paramsStore,o=qq.getUniqueId();qq.each(i.getFileRecords(c,b,a),function(a,b){var c,d=b.size;b.blob instanceof qq.BlobProxy&&(d=-1),c=m.addFile({uuid:b.uuid,name:b.name,size:d,batchId:f,proxyGroupId:o}),b.blob instanceof qq.BlobProxy?j.push(c):k=c,b.blob?(l(c,b.blob),e.push({id:c,file:b.blob})):m.setStatus(c,qq.status.REJECTED)}),null!==k&&(qq.each(j,function(a,b){var c={qqparentuuid:m.retrieve({id:k}).uuid,qqparentsize:m.retrieve({id:k}).size};c[g]=m.retrieve({id:b}).uuid,m.setParentId(b,k),n.addReadOnly(b,c)}),j.length&&function(){var a={};a[g]=m.retrieve({id:k}).uuid,n.addReadOnly(k,a)}())}})},qq.extend(qq.Scaler.prototype,{scaleImage:function(a,b,c){"use strict";if(!qq.supportedFeatures.scaling)throw new qq.Error("Scaling is not supported in this browser!");var d=new qq.Promise,e=c.log,f=c.getFile(a),g=c.uploadData.retrieve({id:a}),h=g&&g.name,i=g&&g.uuid,j={sendOriginal:!1,orient:b.orient,defaultType:b.type||null,defaultQuality:b.quality,failedToScaleText:"Unable to scale",sizes:[{name:"",maxSize:b.maxSize}]},k=new qq.Scaler(j,e);return qq.Scaler&&qq.supportedFeatures.imagePreviews&&f?qq.bind(function(){var b=k.getFileRecords(i,h,f)[0];b&&b.blob instanceof qq.BlobProxy?b.blob.create().then(d.success,d.failure):(e(a+" is not a scalable image!","error"),d.failure())},this)():(d.failure(),e("Could not generate requested scaled image for "+a+". "+"Scaling is either not possible in this browser, or the file could not be located.","error")),d},_determineOutputType:function(a){"use strict";var b=a.requestedType,c=a.defaultType,d=a.refType;return c||b?b?qq.indexOf(Object.keys(qq.Identify.prototype.PREVIEWABLE_MIME_TYPES),b)>=0?"image/tiff"===b?qq.supportedFeatures.tiffPreviews?b:c:b:c:c:"image/jpeg"!==d?"image/png":d},_getName:function(a,b){"use strict";var c=a.lastIndexOf("."),d=b.type||"image/png",e=b.refType,f="",g=qq.getExtension(a),h="";return b.name&&b.name.trim().length&&(h=" ("+b.name+")"),c>=0?(f=a.substr(0,c),e!==d&&(g=d.split("/")[1]),f+=h+"."+g):f=a+h,f},_getSortedSizes:function(a){"use strict";return a=qq.extend([],a),a.sort(function(a,b){return a.maxSize>b.maxSize?1:a.maxSize=0?atob(a.split(",")[1]):decodeURI(a.split(",")[1]),c=a.split(",")[0].split(":")[1].split(";")[0],d=new ArrayBuffer(b.length),e=new Uint8Array(d),qq.each(b,function(a,b){e[a]=b.charCodeAt(0)}),this._createBlob(d,c)},_createBlob:function(a,b){"use strict";var c=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,d=c&&new c;return d?(d.append(a),d.getBlob(b)):new Blob([a],{type:b})}});var ExifRestorer=function(){var a={};return a.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",a.encode64=function(a){var b,c,d,e,f,g="",h="",i="",j=0;do b=a[j++],c=a[j++],h=a[j++],d=b>>2,e=(3&b)<<4|c>>4,f=(15&c)<<2|h>>6,i=63&h,isNaN(c)?f=i=64:isNaN(h)&&(i=64),g=g+this.KEY_STR.charAt(d)+this.KEY_STR.charAt(e)+this.KEY_STR.charAt(f)+this.KEY_STR.charAt(i),b=c=h="",d=e=f=i="";while(ja.length)break}return c},a.decode64=function(a){var b,c,d,e,f,g="",h="",i=0,j=[],k=/[^A-Za-z0-9\+\/\=]/g;if(k.exec(a))throw new Error("There were invalid base64 characters in the input text. Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='");a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do d=this.KEY_STR.indexOf(a.charAt(i++)),e=this.KEY_STR.indexOf(a.charAt(i++)),f=this.KEY_STR.indexOf(a.charAt(i++)),h=this.KEY_STR.indexOf(a.charAt(i++)),b=d<<2|e>>4,c=(15&e)<<4|f>>2,g=(3&f)<<6|h,j.push(b),64!=f&&j.push(c),64!=h&&j.push(g),b=c=g="",d=e=f=h="";while(i=0?(c=!1,!1):void 0}),c},j=function(a){m(a,-1,-1),delete c[a]},k=function(a,b,c){(0===b.length||i(b,c))&&(h(e,e),this.reset())},l=function(a){var d=b(a);d>0&&(m(a,0,d),c[a]={loaded:0,total:d})},m=function(a,b,f){var g=c[a]?c[a].loaded:0,i=c[a]?c[a].total:0;-1===b&&-1===f?(d-=g,e-=i):(b&&(d+=b-g),f&&(e+=f-i)),h(d,e)};qq.extend(this,{onAllComplete:k,onStatusChange:function(a,b,c){c===qq.status.CANCELED||c===qq.status.REJECTED?j(a):c===qq.status.SUBMITTING&&l(a)},onIndividualProgress:function(a,b,d){m(a,b,d),c[a]={loaded:b,total:d}},onNewSize:function(a){l(a)},reset:function(){c={},d=0,e=0}})},qq.UiEventHandler=function(a,b){"use strict";function c(a){d.attach(a,e.eventType,function(a){a=a||window.event;var b=a.target||a.srcElement;e.onHandled(b,a)})}var d=new qq.DisposeSupport,e={eventType:"click",attachTo:null,onHandled:function(){}};qq.extend(this,{addHandler:function(a){c(a)},dispose:function(){d.dispose()}}),qq.extend(b,{getFileIdFromItem:function(a){return a.qqFileId
+},getDisposeSupport:function(){return d}}),qq.extend(e,a),e.attachTo&&c(e.attachTo)},qq.FileButtonsClickHandler=function(a){"use strict";function b(a,b){qq.each(e,function(c,e){var f,g=c.charAt(0).toUpperCase()+c.slice(1);return d.templating["is"+g](a)?(f=d.templating.getFileId(a),qq.preventDefault(b),d.log(qq.format("Detected valid file button click event on file '{}', ID: {}.",d.onGetName(f),f)),e(f),!1):void 0})}var c={},d={templating:null,log:function(){},onDeleteFile:function(){},onCancel:function(){},onRetry:function(){},onPause:function(){},onContinue:function(){},onGetName:function(){}},e={cancel:function(a){d.onCancel(a)},retry:function(a){d.onRetry(a)},deleteButton:function(a){d.onDeleteFile(a)},pause:function(a){d.onPause(a)},continueButton:function(a){d.onContinue(a)}};qq.extend(d,a),d.eventType="click",d.onHandled=b,d.attachTo=d.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(d,c))},qq.FilenameClickHandler=function(a){"use strict";function b(a,b){if(d.templating.isFileName(a)||d.templating.isEditIcon(a)){var e=d.templating.getFileId(a),f=d.onGetUploadStatus(e);f===qq.status.SUBMITTED&&(d.log(qq.format("Detected valid filename click event on file '{}', ID: {}.",d.onGetName(e),e)),qq.preventDefault(b),c.handleFilenameEdit(e,a,!0))}}var c={},d={templating:null,log:function(){},classes:{file:"qq-upload-file",editNameIcon:"qq-edit-filename-icon"},onGetUploadStatus:function(){},onGetName:function(){}};qq.extend(d,a),d.eventType="click",d.onHandled=b,qq.extend(this,new qq.FilenameEditHandler(d,c))},qq.FilenameInputFocusInHandler=function(a,b){"use strict";function c(a){if(d.templating.isEditInput(a)){var c=d.templating.getFileId(a),e=d.onGetUploadStatus(c);e===qq.status.SUBMITTED&&(d.log(qq.format("Detected valid filename input focus event on file '{}', ID: {}.",d.onGetName(c),c)),b.handleFilenameEdit(c,a))}}var d={templating:null,onGetUploadStatus:function(){},log:function(){}};b||(b={}),d.eventType="focusin",d.onHandled=c,qq.extend(d,a),qq.extend(this,new qq.FilenameEditHandler(d,b))},qq.FilenameInputFocusHandler=function(a){"use strict";a.eventType="focus",a.attachTo=null,qq.extend(this,new qq.FilenameInputFocusInHandler(a,{}))},qq.FilenameEditHandler=function(a,b){"use strict";function c(a){var b=h.onGetName(a),c=b.lastIndexOf(".");return c>0&&(b=b.substr(0,c)),b}function d(a){var b=h.onGetName(a);return qq.getExtension(b)}function e(a,b){var c,e=a.value;void 0!==e&&qq.trimStr(e).length>0&&(c=d(b),void 0!==c&&(e=e+"."+c),h.onSetName(b,e)),h.onEditingStatusChange(b,!1)}function f(a,c){b.getDisposeSupport().attach(a,"blur",function(){e(a,c)})}function g(a,c){b.getDisposeSupport().attach(a,"keyup",function(b){var d=b.keyCode||b.which;13===d&&e(a,c)})}var h={templating:null,log:function(){},onGetUploadStatus:function(){},onGetName:function(){},onSetName:function(){},onEditingStatusChange:function(){}};qq.extend(h,a),h.attachTo=h.templating.getFileList(),qq.extend(this,new qq.UiEventHandler(h,b)),qq.extend(b,{handleFilenameEdit:function(a,b,d){var e=h.templating.getEditInput(a);h.onEditingStatusChange(a,!0),e.value=c(a),d&&e.focus(),f(e,a),g(e,a)}})};var CryptoJS=CryptoJS||function(a,b){var c={},d=c.lib={},e=d.Base=function(){function a(){}return{extend:function(b){a.prototype=this;var c=new a;return b&&c.mixIn(b),c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)}),c.init.prototype=c,c.$super=this,c},create:function(){var a=this.extend();return a.init.apply(a,arguments),a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),f=d.WordArray=e.extend({init:function(a,c){a=this.words=a||[],this.sigBytes=c!=b?c:4*a.length},toString:function(a){return(a||h).stringify(this)},concat:function(a){var b=this.words,c=a.words,d=this.sigBytes,e=a.sigBytes;if(this.clamp(),d%4)for(var f=0;e>f;f++){var g=255&c[f>>>2]>>>24-8*(f%4);b[d+f>>>2]|=g<<24-8*((d+f)%4)}else if(c.length>65535)for(var f=0;e>f;f+=4)b[d+f>>>2]=c[f>>>2];else b.push.apply(b,c);return this.sigBytes+=e,this},clamp:function(){var b=this.words,c=this.sigBytes;b[c>>>2]&=4294967295<<32-8*(c%4),b.length=a.ceil(c/4)},clone:function(){var a=e.clone.call(this);return a.words=this.words.slice(0),a},random:function(b){for(var c=[],d=0;b>d;d+=4)c.push(0|4294967296*a.random());return new f.init(c,b)}}),g=c.enc={},h=g.Hex={stringify:function(a){for(var b=a.words,c=a.sigBytes,d=[],e=0;c>e;e++){var f=255&b[e>>>2]>>>24-8*(e%4);d.push((f>>>4).toString(16)),d.push((15&f).toString(16))}return d.join("")},parse:function(a){for(var b=a.length,c=[],d=0;b>d;d+=2)c[d>>>3]|=parseInt(a.substr(d,2),16)<<24-4*(d%8);return new f.init(c,b/2)}},i=g.Latin1={stringify:function(a){for(var b=a.words,c=a.sigBytes,d=[],e=0;c>e;e++){var f=255&b[e>>>2]>>>24-8*(e%4);d.push(String.fromCharCode(f))}return d.join("")},parse:function(a){for(var b=a.length,c=[],d=0;b>d;d++)c[d>>>2]|=(255&a.charCodeAt(d))<<24-8*(d%4);return new f.init(c,b)}},j=g.Utf8={stringify:function(a){try{return decodeURIComponent(escape(i.stringify(a)))}catch(b){throw new Error("Malformed UTF-8 data")}},parse:function(a){return i.parse(unescape(encodeURIComponent(a)))}},k=d.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new f.init,this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=j.parse(a)),this._data.concat(a),this._nDataBytes+=a.sigBytes},_process:function(b){var c=this._data,d=c.words,e=c.sigBytes,g=this.blockSize,h=4*g,i=e/h;i=b?a.ceil(i):a.max((0|i)-this._minBufferSize,0);var j=i*g,k=a.min(4*j,e);if(j){for(var l=0;j>l;l+=g)this._doProcessBlock(d,l);var m=d.splice(0,j);c.sigBytes-=k}return new f.init(m,k)},clone:function(){var a=e.clone.call(this);return a._data=this._data.clone(),a},_minBufferSize:0});d.Hasher=k.extend({cfg:e.extend(),init:function(a){this.cfg=this.cfg.extend(a),this.reset()},reset:function(){k.reset.call(this),this._doReset()},update:function(a){return this._append(a),this._process(),this},finalize:function(a){a&&this._append(a);var b=this._doFinalize();return b},blockSize:16,_createHelper:function(a){return function(b,c){return new a.init(c).finalize(b)}},_createHmacHelper:function(a){return function(b,c){return new l.HMAC.init(a,c).finalize(b)}}});var l=c.algo={};return c}(Math);!function(){var a=CryptoJS,b=a.lib,c=b.WordArray,d=a.enc;d.Base64={stringify:function(a){var b=a.words,c=a.sigBytes,d=this._map;a.clamp();for(var e=[],f=0;c>f;f+=3)for(var g=255&b[f>>>2]>>>24-8*(f%4),h=255&b[f+1>>>2]>>>24-8*((f+1)%4),i=255&b[f+2>>>2]>>>24-8*((f+2)%4),j=g<<16|h<<8|i,k=0;4>k&&c>f+.75*k;k++)e.push(d.charAt(63&j>>>6*(3-k)));var l=d.charAt(64);if(l)for(;e.length%4;)e.push(l);return e.join("")},parse:function(a){var b=a.length,d=this._map,e=d.charAt(64);if(e){var f=a.indexOf(e);-1!=f&&(b=f)}for(var g=[],h=0,i=0;b>i;i++)if(i%4){var j=d.indexOf(a.charAt(i-1))<<2*(i%4),k=d.indexOf(a.charAt(i))>>>6-2*(i%4);g[h>>>2]|=(j|k)<<24-8*(h%4),h++}return c.create(g,h)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}(),function(){var a=CryptoJS,b=a.lib,c=b.Base,d=a.enc,e=d.Utf8,f=a.algo;f.HMAC=c.extend({init:function(a,b){a=this._hasher=new a.init,"string"==typeof b&&(b=e.parse(b));var c=a.blockSize,d=4*c;b.sigBytes>d&&(b=a.finalize(b)),b.clamp();for(var f=this._oKey=b.clone(),g=this._iKey=b.clone(),h=f.words,i=g.words,j=0;c>j;j++)h[j]^=1549556828,i[j]^=909522486;f.sigBytes=g.sigBytes=d,this.reset()},reset:function(){var a=this._hasher;a.reset(),a.update(this._iKey)},update:function(a){return this._hasher.update(a),this},finalize:function(a){var b=this._hasher,c=b.finalize(a);b.reset();var d=b.finalize(this._oKey.clone().concat(c));return d}})}(),function(){var a=CryptoJS,b=a.lib,c=b.WordArray,d=b.Hasher,e=a.algo,f=[],g=e.SHA1=d.extend({_doReset:function(){this._hash=new c.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(a,b){for(var c=this._hash.words,d=c[0],e=c[1],g=c[2],h=c[3],i=c[4],j=0;80>j;j++){if(16>j)f[j]=0|a[b+j];else{var k=f[j-3]^f[j-8]^f[j-14]^f[j-16];f[j]=k<<1|k>>>31}var l=(d<<5|d>>>27)+i+f[j];l+=20>j?(e&g|~e&h)+1518500249:40>j?(e^g^h)+1859775393:60>j?(e&g|e&h|g&h)-1894007588:(e^g^h)-899497514,i=h,h=g,g=e<<30|e>>>2,e=d,d=l}c[0]=0|c[0]+d,c[1]=0|c[1]+e,c[2]=0|c[2]+g,c[3]=0|c[3]+h,c[4]=0|c[4]+i},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,d=8*a.sigBytes;return b[d>>>5]|=128<<24-d%32,b[(d+64>>>9<<4)+14]=Math.floor(c/4294967296),b[(d+64>>>9<<4)+15]=c,a.sigBytes=4*b.length,this._process(),this._hash},clone:function(){var a=d.clone.call(this);return a._hash=this._hash.clone(),a}});a.SHA1=d._createHelper(g),a.HmacSHA1=d._createHmacHelper(g)}();
+/*! 2015-08-26 */
diff --git a/js/components/coa_verify_container.js b/js/components/coa_verify_container.js
index 8c2f2e77..d65fdb83 100644
--- a/js/components/coa_verify_container.js
+++ b/js/components/coa_verify_container.js
@@ -10,7 +10,7 @@ import Form from './ascribe_forms/form';
import Property from './ascribe_forms/property';
import InputTextAreaToggable from './ascribe_forms/input_textarea_toggable';
-import apiUrls from '../constants/api_urls';
+import ApiUrls from '../constants/api_urls';
import { getLangText } from '../utils/lang_utils';
@@ -59,7 +59,7 @@ let CoaVerifyForm = React.createClass({
return (
+
+ );
},
+
onChange(state) {
this.setState(state);
@@ -88,22 +99,61 @@ let Header = React.createClass({
}
},
+ onMenuItemClick() {
+ /*
+ This is a hack to make the dropdown close after clicking on an item
+ The function just need to be defined
+
+ from https://github.com/react-bootstrap/react-bootstrap/issues/368:
+
+ @jvillasante - Have you tried to use onSelect with the DropdownButton?
+ I don't have a working example that is exactly like yours,
+ but I just noticed that the Dropdown closes when I've attached an event handler to OnSelect:
+
+
+
+ onSelected: function(e) {
+ // doesn't need to have functionality (necessarily) ... just wired up
+ }
+ Internally, a call to DropdownButton.setDropDownState(false) is made which will hide the dropdown menu.
+ So, you should be able to call that directly on the DropdownButton instance as well if needed.
+
+ NOW, THAT DIDN'T WORK - the onSelect routine isnt triggered in all cases
+ Hence, we do this manually
+ */
+ this.refs.dropdownbutton.setDropdownState(false);
+ },
+
render() {
- let account = null;
- let signup = null;
- let collection = null;
- let addNewWork = null;
+ let account;
+ let signup;
+ let navRoutesLinks;
if (this.state.currentUser.username){
account = (
-
- {getLangText('Account Settings')}
+
+
+ {getLangText('Account Settings')}
+
+
+
+ {getLangText('Contract Settings')}
+
+ {getLangText('Log out')}
-
+
);
-
- collection = {getLangText('COLLECTION')};
- addNewWork = this.props.showAddWork ? + {getLangText('NEW WORK')} : null;
+ navRoutesLinks = ;
}
else {
account = {getLangText('LOGIN')};
@@ -124,11 +174,11 @@ let Header = React.createClass({
+
+ {navRoutesLinks}
diff --git a/js/components/header_notification.js b/js/components/header_notification.js
new file mode 100644
index 00000000..67252af8
--- /dev/null
+++ b/js/components/header_notification.js
@@ -0,0 +1,218 @@
+'use strict';
+
+import React from 'react';
+import Router from 'react-router';
+import DropdownButton from 'react-bootstrap/lib/DropdownButton';
+import Glyphicon from 'react-bootstrap/lib/Glyphicon';
+import MenuItem from 'react-bootstrap/lib/MenuItem';
+
+import Nav from 'react-bootstrap/lib/Nav';
+
+import NotificationActions from '../actions/notification_actions';
+import NotificationStore from '../stores/notification_store';
+
+import { mergeOptions } from '../utils/general_utils';
+import { getLangText } from '../utils/lang_utils';
+
+let Link = Router.Link;
+
+
+let HeaderNotifications = React.createClass({
+
+ getInitialState() {
+ return mergeOptions(
+ NotificationStore.getState()
+ );
+ },
+
+ componentDidMount() {
+ NotificationStore.listen(this.onChange);
+ NotificationActions.fetchPieceListNotifications();
+ NotificationActions.fetchEditionListNotifications();
+ },
+
+ componentWillUnmount() {
+ NotificationStore.unlisten(this.onChange);
+ },
+
+ onChange(state) {
+ this.setState(state);
+ },
+
+ onMenuItemClick(event) {
+ /*
+ This is a hack to make the dropdown close after clicking on an item
+ The function just need to be defined
+
+ from https://github.com/react-bootstrap/react-bootstrap/issues/368:
+
+ @jvillasante - Have you tried to use onSelect with the DropdownButton?
+ I don't have a working example that is exactly like yours,
+ but I just noticed that the Dropdown closes when I've attached an event handler to OnSelect:
+
+
+
+ onSelected: function(e) {
+ // doesn't need to have functionality (necessarily) ... just wired up
+ }
+ Internally, a call to DropdownButton.setDropDownState(false) is made which will hide the dropdown menu.
+ So, you should be able to call that directly on the DropdownButton instance as well if needed.
+
+ NOW, THAT DIDN'T WORK - the onSelect routine isnt triggered in all cases
+ Hence, we do this manually
+ */
+ this.refs.dropdownbutton.setDropdownState(false);
+ },
+
+ getPieceNotifications(){
+ if (this.state.pieceListNotifications && this.state.pieceListNotifications.length > 0) {
+ return (
+
- This modal is controlled by our custom trigger component.
-
-
-
-
-
- );
- }
-});
-
-export default LoginModalHandler;
\ No newline at end of file
diff --git a/js/components/logout_container.js b/js/components/logout_container.js
index 096fa490..c7769867 100644
--- a/js/components/logout_container.js
+++ b/js/components/logout_container.js
@@ -19,7 +19,7 @@ let LogoutContainer = React.createClass({
Alt.flush();
// kill intercom (with fire)
window.Intercom('shutdown');
- this.transitionTo(baseUrl);
+ this.replaceWith(baseUrl);
})
.catch((err) => {
console.logGlobal(err);
diff --git a/js/components/nav_routes_links.js b/js/components/nav_routes_links.js
new file mode 100644
index 00000000..d3342cb8
--- /dev/null
+++ b/js/components/nav_routes_links.js
@@ -0,0 +1,97 @@
+'use strict';
+
+import React from 'react';
+
+import Nav from 'react-bootstrap/lib/Nav';
+
+import NavRoutesLinksLink from './nav_routes_links_link';
+
+import AclProxy from './acl_proxy';
+
+import { sanitizeList } from '../utils/general_utils';
+
+
+let NavRoutesLinks = React.createClass({
+ propTypes: {
+ routes: React.PropTypes.element,
+ userAcl: React.PropTypes.object
+ },
+
+ /**
+ * This method generales a bunch of react-bootstrap specific links
+ * from the routes we defined in one of the specific routes.js file
+ *
+ * We can define a headerTitle as well as a aclName and according to that the
+ * link will be created for a specific user
+ * @param {ReactElement} node Starts at the very top of a routes files root
+ * @param {object} userAcl ACL object we use throughout the whole app
+ * @param {number} i Depth of the route in comparison to the root
+ * @return {Array} Array of ReactElements that can be displayed to the user
+ */
+ extractLinksFromRoutes(node, userAcl, i) {
+ if(!node) {
+ return;
+ }
+
+ let links = node.props.children.map((child, j) => {
+ let childrenFn = null;
+ let { aclName, headerTitle, name, children } = child.props;
+
+ // If the node has children that could be rendered, then we want
+ // to execute this function again with the child as the root
+ //
+ // Otherwise we'll just pass childrenFn as false
+ if(child.props.children && child.props.children.length > 0) {
+ childrenFn = this.extractLinksFromRoutes(child, userAcl, i++);
+ }
+
+ // We validate if the user has set the title correctly,
+ // otherwise we're not going to render his route
+ if(headerTitle && typeof headerTitle === 'string') {
+ // if there is an aclName present on the route definition,
+ // we evaluate it against the user's acl
+ if(aclName && typeof aclName !== 'undefined') {
+ return (
+
+
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ } else {
+ return null;
+ }
+
+ });
+
+ // remove all nulls from the list of generated links
+ return sanitizeList(links);
+ },
+
+ render() {
+ let {routes, userAcl} = this.props;
+
+ return (
+
+ );
+ }
+});
+
+export default NavRoutesLinks;
\ No newline at end of file
diff --git a/js/components/nav_routes_links_link.js b/js/components/nav_routes_links_link.js
new file mode 100644
index 00000000..15aff405
--- /dev/null
+++ b/js/components/nav_routes_links_link.js
@@ -0,0 +1,51 @@
+'use strict';
+
+import React from 'react';
+
+import DropdownButton from 'react-bootstrap/lib/DropdownButton';
+import MenuItemLink from 'react-router-bootstrap/lib/MenuItemLink';
+import NavItemLink from 'react-router-bootstrap/lib/NavItemLink';
+
+let NavRoutesLinksLink = React.createClass({
+ propTypes: {
+ headerTitle: React.PropTypes.string,
+ routeName: React.PropTypes.string,
+
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.arrayOf(React.PropTypes.element),
+ React.PropTypes.element
+ ]),
+
+ depth: React.PropTypes.number
+ },
+
+ render() {
+ let { children, headerTitle, depth, routeName } = this.props;
+
+ // if the route has children, we're returning a DropdownButton that will get filled
+ // with MenuItemLinks
+ if(children) {
+ return (
+
+ {children}
+
+ );
+ } else {
+ if(depth === 1) {
+ // if the node's child is actually a node of level one (a child of a node), we're
+ // returning a DropdownButton matching MenuItemLink
+ return (
+ {headerTitle}
+ );
+ } else if(depth === 0) {
+ return (
+ {headerTitle}
+ );
+ } else {
+ return null;
+ }
+ }
+ }
+});
+
+export default NavRoutesLinksLink;
\ No newline at end of file
diff --git a/js/components/password_reset_container.js b/js/components/password_reset_container.js
index 20851632..ae581fdf 100644
--- a/js/components/password_reset_container.js
+++ b/js/components/password_reset_container.js
@@ -5,8 +5,7 @@ import Router from 'react-router';
import Form from './ascribe_forms/form';
import Property from './ascribe_forms/property';
-import FormPropertyHeader from './ascribe_forms/form_property_header';
-import apiUrls from '../constants/api_urls';
+import ApiUrls from '../constants/api_urls';
import GlobalNotificationModel from '../models/global_notification_model';
import GlobalNotificationActions from '../actions/global_notification_actions';
@@ -15,12 +14,15 @@ import { getLangText } from '../utils/lang_utils';
let PasswordResetContainer = React.createClass({
mixins: [Router.Navigation],
+
getInitialState() {
return {isRequested: false};
},
- handleRequestSuccess(email){
+
+ handleRequestSuccess(email) {
this.setState({isRequested: email});
},
+
render() {
if (this.props.query.email && this.props.query.token) {
return (
@@ -57,17 +59,23 @@ let PasswordResetContainer = React.createClass({
});
let PasswordRequestResetForm = React.createClass({
+ propTypes: {
+ handleRequestSuccess: React.PropTypes.func
+ },
+
handleSuccess() {
let notificationText = getLangText('If your email address exists in our database, you will receive a password recovery link in a few minutes.');
let notification = new GlobalNotificationModel(notificationText, 'success', 50000);
GlobalNotificationActions.appendGlobalNotification(notification);
this.props.handleRequestSuccess(this.refs.form.refs.email.state.value);
},
+
render() {
return (
{getLangText('Reset the password for')} {this.props.email}
-
+
diff --git a/js/components/piece_list.js b/js/components/piece_list.js
index 1792b17a..35dcaba0 100644
--- a/js/components/piece_list.js
+++ b/js/components/piece_list.js
@@ -6,49 +6,82 @@ import Router from 'react-router';
import PieceListStore from '../stores/piece_list_store';
import PieceListActions from '../actions/piece_list_actions';
+import EditionListStore from '../stores/edition_list_store';
+import EditionListActions from '../actions/edition_list_actions';
+
import AccordionList from './ascribe_accordion_list/accordion_list';
-import AccordionListItem from './ascribe_accordion_list/accordion_list_item';
+import AccordionListItemWallet from './ascribe_accordion_list/accordion_list_item_wallet';
import AccordionListItemTableEditions from './ascribe_accordion_list/accordion_list_item_table_editions';
import Pagination from './ascribe_pagination/pagination';
+import PieceListFilterDisplay from './piece_list_filter_display';
+
import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_modal';
import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
import AppConstants from '../constants/application_constants';
+import { mergeOptions } from '../utils/general_utils';
+import { getLangText } from '../utils/lang_utils';
+
let PieceList = React.createClass({
propTypes: {
+ accordionListItemType: React.PropTypes.func,
redirectTo: React.PropTypes.string,
- customSubmitButton: React.PropTypes.element
+ customSubmitButton: React.PropTypes.element,
+ filterParams: React.PropTypes.array,
+ orderParams: React.PropTypes.array,
+ orderBy: React.PropTypes.string
},
mixins: [Router.Navigation, Router.State],
+ getDefaultProps() {
+ return {
+ accordionListItemType: AccordionListItemWallet,
+ orderParams: ['artist_name', 'title'],
+ filterParams: [{
+ label: getLangText('Show works I can'),
+ items: [
+ 'acl_transfer',
+ 'acl_consign',
+ 'acl_create_editions'
+ ]
+ }]
+ };
+ },
getInitialState() {
- return PieceListStore.getState();
+ return mergeOptions(
+ PieceListStore.getState(),
+ EditionListStore.getState()
+ );
},
componentDidMount() {
let page = this.getQuery().page || 1;
+
PieceListStore.listen(this.onChange);
- if (this.state.pieceList.length === 0){
+ EditionListStore.listen(this.onChange);
+
+ let orderBy = this.props.orderBy ? this.props.orderBy : this.state.orderBy;
+ if (this.state.pieceList.length === 0 || this.state.page !== page){
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search,
- this.state.orderBy, this.state.orderAsc, this.state.filterBy)
- .then(PieceListActions.fetchPieceRequestActions());
+ orderBy, this.state.orderAsc, this.state.filterBy);
}
},
componentDidUpdate() {
- if (this.props.redirectTo && this.state.pieceListCount === 0) {
+ if (this.props.redirectTo && this.state.unfilteredPieceListCount === 0) {
// FIXME: hack to redirect out of the dispatch cycle
- window.setTimeout(() => this.transitionTo(this.props.redirectTo), 0);
+ window.setTimeout(() => this.transitionTo(this.props.redirectTo, this.getQuery()));
}
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
+ EditionListStore.unlisten(this.onChange);
},
onChange(state) {
@@ -56,13 +89,14 @@ let PieceList = React.createClass({
},
paginationGoToPage(page) {
- // if the users clicks a pager of the pagination,
- // the site should go to the top
- document.body.scrollTop = document.documentElement.scrollTop = 0;
-
- return () => PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search,
- this.state.orderBy, this.state.orderAsc,
- this.state.filterBy);
+ return () => {
+ // if the users clicks a pager of the pagination,
+ // the site should go to the top
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
+ PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search,
+ this.state.orderBy, this.state.orderAsc,
+ this.state.filterBy);
+ };
},
getPagination() {
@@ -85,32 +119,56 @@ let PieceList = React.createClass({
this.transitionTo(this.getPathname(), {page: 1});
},
- applyFilterBy(filterBy) {
+ applyFilterBy(filterBy){
+ // first we need to apply the filter on the piece list
PieceListActions.fetchPieceList(1, this.state.pageSize, this.state.search,
- this.state.orderBy, this.state.orderAsc, filterBy);
+ this.state.orderBy, this.state.orderAsc, filterBy)
+ .then(() => {
+ // but also, we need to filter all the open edition lists
+ this.state.pieceList
+ .forEach((piece) => {
+ // but only if they're actually open
+ if(this.state.isEditionListOpenForPieceId[piece.id].show) {
+ EditionListActions.refreshEditionList({
+ pieceId: piece.id,
+ filterBy
+ });
+ }
+
+ });
+ });
+
// we have to redirect the user always to page one as it could be that there is no page two
// for filtered pieces
this.transitionTo(this.getPathname(), {page: 1});
},
- accordionChangeOrder(orderBy, orderAsc) {
+ applyOrderBy(orderBy) {
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
- orderBy, orderAsc, this.state.filterBy);
+ orderBy, this.state.orderAsc, this.state.filterBy);
},
render() {
let loadingElement = ();
-
+ let AccordionListItemType = this.props.accordionListItemType;
+
return (
+ orderBy={this.state.orderBy}
+ applyFilterBy={this.applyFilterBy}
+ applyOrderBy={this.applyOrderBy}>
{this.props.customSubmitButton}
+
{this.state.pieceList.map((piece, i) => {
return (
-
-
+
);
})}
diff --git a/js/components/piece_list_filter_display.js b/js/components/piece_list_filter_display.js
new file mode 100644
index 00000000..6ca5207a
--- /dev/null
+++ b/js/components/piece_list_filter_display.js
@@ -0,0 +1,118 @@
+'use strict';
+
+import React from 'react';
+
+
+let PieceListFilterDisplay = React.createClass({
+ propTypes: {
+ filterBy: React.PropTypes.object,
+ filterParams: React.PropTypes.arrayOf(
+ React.PropTypes.shape({
+ label: React.PropTypes.string,
+ items: React.PropTypes.arrayOf(
+ React.PropTypes.oneOfType([
+ React.PropTypes.string,
+ React.PropTypes.shape({
+ key: React.PropTypes.string,
+ label: React.PropTypes.string
+ })
+ ])
+ )
+ })
+ )
+ },
+
+ /**
+ * Takes the above described filterParams prop,
+ * assigns it it's true filterBy value that is derived from the filterBy prop
+ * and also - if there wasn't already one defined - generates a label
+ * @return {object}
+ */
+ transformFilterParamsItemsToBools() {
+ let { filterParams, filterBy } = this.props;
+
+ return filterParams.map((filterParam) => {
+ return {
+ label: filterParam.label,
+ items: filterParam.items.map((item) => {
+ if(typeof item !== 'string' && typeof item.key === 'string' && typeof item.label === 'string') {
+ return {
+ key: item.key,
+ label: item.label,
+ value: filterBy[item.key] || false
+ };
+ } else {
+ return {
+ key: item,
+ label: item.split('acl_')[1].replace(/_/g, ' '),
+ value: filterBy[item] || false
+ };
+ }
+ })
+ };
+ });
+ },
+
+ /**
+ * Takes the list of filters generated in transformFilterParamsItemsToBools and
+ * transforms them into human readable text.
+ * @param {Object} filtersWithLabel An object of the shape {key: , label: , value: }
+ * @return {string} A human readable string
+ */
+ getFilterText(filtersWithLabel) {
+ let filterTextList = filtersWithLabel
+ // Iterate over all provided filterLabels and generate a list
+ // of human readable strings
+ .map((filterWithLabel) => {
+ let activeFilterWithLabel = filterWithLabel
+ .items
+ // If the filter is active (which it is when its value is true),
+ // we're going to include it's label into a list,
+ // otherwise we'll just return nothing
+ .map((filter) => {
+ if(filter.value) {
+ return filter.label;
+ }
+ })
+ // if nothing is returned, that index is 'undefined'.
+ // As we only want active filter, we filter out all falsy values e.g. undefined
+ .filter((filterName) => !!filterName)
+ // and join the result to a string
+ .join(', ');
+
+ // If this actually didn't generate an empty string,
+ // we take the label and concat it to the result.
+ if(activeFilterWithLabel) {
+ return filterWithLabel.label + ': ' + activeFilterWithLabel;
+ }
+ })
+ // filter out strings that are undefined, as their filter's were not activated
+ .filter((filterText) => !!filterText)
+ // if there are multiple sentences, capitalize the first one and lowercase the others
+ .map((filterText, i) => i === 0 ? filterText.charAt(0).toUpperCase() + filterText.substr(1) : filterText.charAt(0).toLowerCase() + filterText.substr(1))
+ .join(' and ');
+
+ return filterTextList;
+ },
+
+ render() {
+ let { filterBy } = this.props;
+ let filtersWithLabel = this.transformFilterParamsItemsToBools();
+
+ // do not show the FilterDisplay if there are no filters applied
+ if(filterBy && Object.keys(filterBy).length === 0) {
+ return null;
+ } else {
+ return (
+
+
+ {this.getFilterText(filtersWithLabel)}
+
+
+
+ );
+ }
+ }
+});
+
+export default PieceListFilterDisplay;
\ No newline at end of file
diff --git a/js/components/react_flow_type/react_flow_type.js b/js/components/react_flow_type/react_flow_type.js
deleted file mode 100644
index 063eaf1c..00000000
--- a/js/components/react_flow_type/react_flow_type.js
+++ /dev/null
@@ -1,92 +0,0 @@
-'use strict';
-/**
- * This component is essentially a port of https://github.com/simplefocus/FlowType.JS
- * to Reactjs in order to not being forced to use jQuery
- *
- * Author: Tim Daubenschütz
- *
- * Thanks to the guys at Simple Focus http://simplefocus.com/
- */
-
-import React from 'react';
-import ReactAddons from 'react/addons';
-
-let FlowType = React.createClass({
- propTypes: {
-
- // standard FlowTypes.JS options
- maximum: React.PropTypes.number,
- minimum: React.PropTypes.number,
- maxFont: React.PropTypes.number,
- minFont: React.PropTypes.number,
- fontRatio: React.PropTypes.number,
-
- // react specific options
- children: React.PropTypes.element.isRequired // only supporting one child element at once right now
- },
-
- getDefaultProps() {
- return {
- maximum: 9999,
- minimum: 1,
- maxFont: 9999,
- minFont: 1,
- fontRatio: 35
- };
- },
-
- getInitialState() {
- return {
- // 32 because that's the default font display size
- // doesn't really matter though
- fontSize: 0
- };
- },
-
- componentDidMount() {
- // Make changes upon resize, calculate changes and rerender
- this.handleResize();
- window.addEventListener('resize', this.handleResize);
- },
-
- componentWillUnmount() {
- // stop listening to window once the component was unmounted
- window.removeEventListener('resize', this.handleResize);
- },
-
- handleResize() {
- let elemWidth = this.refs.flowTypeElement.getDOMNode().offsetWidth;
- let width = elemWidth > this.props.maximum ? this.props.maximum : elemWidth < this.props.minimum ? this.props.minimum : elemWidth;
- let fontBase = width / this.props.fontRatio;
- let fontSize = fontBase > this.props.maxFont ? this.props.maxFont : fontBase < this.props.minFont ? this.props.minFont : fontBase;
-
- this.setState({ fontSize });
- },
-
- // The child the user passes to this component needs to have it's
- // style.fontSize property to be updated
- renderChildren() {
- return ReactAddons.Children.map(this.props.children, (child) => {
- return ReactAddons.addons.cloneWithProps(child, {
- ref: 'flowTypeFontElement',
-
- });
- });
- },
-
- render() {
- return (
-
- {this.props.children}
-
- );
- }
-});
-
-export default FlowType;
\ No newline at end of file
diff --git a/js/components/register_piece.js b/js/components/register_piece.js
index f46ab99c..1a09e64f 100644
--- a/js/components/register_piece.js
+++ b/js/components/register_piece.js
@@ -1,14 +1,11 @@
'use strict';
import React from 'react';
-
import Router from 'react-router';
+
import Col from 'react-bootstrap/lib/Col';
import Row from 'react-bootstrap/lib/Row';
-import LicenseActions from '../actions/license_actions';
-import LicenseStore from '../stores/license_store';
-
import WhitelabelActions from '../actions/whitelabel_actions';
import WhitelabelStore from '../stores/whitelabel_store';
@@ -20,10 +17,8 @@ import UserStore from '../stores/user_store';
import GlobalNotificationModel from '../models/global_notification_model';
import GlobalNotificationActions from '../actions/global_notification_actions';
-import Property from './ascribe_forms/property';
import PropertyCollapsible from './ascribe_forms/property_collapsible';
import RegisterPieceForm from './ascribe_forms/form_register_piece';
-//import FormPropertyHeader from './ascribe_forms/form_property_header';
import LoginContainer from './login_container';
import SlidesContainer from './ascribe_slides_container/slides_container';
@@ -40,7 +35,9 @@ let RegisterPiece = React.createClass( {
submitMessage: React.PropTypes.string,
children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(React.PropTypes.element),
- React.PropTypes.element])
+ React.PropTypes.element,
+ React.PropTypes.string
+ ])
},
mixins: [Router.Navigation],
@@ -53,7 +50,6 @@ let RegisterPiece = React.createClass( {
getInitialState(){
return mergeOptions(
- LicenseStore.getState(),
UserStore.getState(),
WhitelabelStore.getState(),
PieceListStore.getState(),
@@ -64,16 +60,13 @@ let RegisterPiece = React.createClass( {
},
componentDidMount() {
- LicenseActions.fetchLicense();
WhitelabelActions.fetchWhitelabel();
- LicenseStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
UserStore.listen(this.onChange);
WhitelabelStore.listen(this.onChange);
},
componentWillUnmount() {
- LicenseStore.unlisten(this.onChange);
PieceListStore.unlisten(this.onChange);
UserStore.unlisten(this.onChange);
WhitelabelStore.unlisten(this.onChange);
@@ -108,37 +101,6 @@ let RegisterPiece = React.createClass( {
this.transitionTo('piece', {pieceId: response.piece.id});
},
- onLicenseChange(event){
- //console.log(this.state.licenses[event.target.selectedIndex].url);
- this.setState({selectedLicense: event.target.selectedIndex});
- },
- getLicenses() {
- if (this.state.licenses && this.state.licenses.length > 1) {
- return (
- {getLangText('Learn more')}
- }>
-
- );
- }
- return null;
- },
-
getSpecifyEditions() {
if(this.state.whitelabel && this.state.whitelabel.acl_create_editions || Object.keys(this.state.whitelabel).length === 0) {
return (
@@ -155,7 +117,8 @@ let RegisterPiece = React.createClass( {
}
},
- changeSlide() {
+ // basically redirects to the second slide (index: 1), when the user is not logged in
+ onLoggedOut() {
// only transition to the login store, if user is not logged in
// ergo the currentUser object is not properly defined
if(this.state.currentUser && !this.state.currentUser.email) {
@@ -163,11 +126,6 @@ let RegisterPiece = React.createClass( {
}
},
- // basically redirects to the second slide (index: 1), when the user is not logged in
- onLoggedOut() {
- this.refs.slidesContainer.setSlideNum(1);
- },
-
onLogin() {
// once the currentUser object from UserStore is defined (eventually the user was transitioned
// to the login form via the slider and successfully logged in), we can direct him back to the
@@ -179,10 +137,12 @@ let RegisterPiece = React.createClass( {
render() {
return (
-
+
-
- );
- }
- return null;
- }
-});
-
-export default PieceContainer;
diff --git a/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js b/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js
new file mode 100644
index 00000000..73cfa83a
--- /dev/null
+++ b/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js
@@ -0,0 +1,442 @@
+'use strict';
+
+import React from 'react';
+import Router from 'react-router';
+import Moment from 'moment';
+
+import StarRating from 'react-star-rating';
+
+import PieceActions from '../../../../../actions/piece_actions';
+import PieceStore from '../../../../../stores/piece_store';
+
+import PieceListStore from '../../../../../stores/piece_list_store';
+import PieceListActions from '../../../../../actions/piece_list_actions';
+
+import PrizeRatingActions from '../../actions/prize_rating_actions';
+import PrizeRatingStore from '../../stores/prize_rating_store';
+
+import UserStore from '../../../../../stores/user_store';
+
+import Piece from '../../../../../components/ascribe_detail/piece';
+import Note from '../../../../../components/ascribe_detail/note';
+
+import AppConstants from '../../../../../constants/application_constants';
+
+import Form from '../../../../../components/ascribe_forms/form';
+import Property from '../../../../../components/ascribe_forms/property';
+import InputTextAreaToggable from '../../../../../components/ascribe_forms/input_textarea_toggable';
+import CollapsibleParagraph from '../../../../../components/ascribe_collapsible/collapsible_paragraph';
+
+import InputCheckbox from '../../../../ascribe_forms/input_checkbox';
+import LoanForm from '../../../../ascribe_forms/form_loan';
+import ListRequestActions from '../../../../ascribe_forms/list_form_request_actions';
+import ModalWrapper from '../../../../ascribe_modal/modal_wrapper';
+
+import GlobalNotificationModel from '../../../../../models/global_notification_model';
+import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
+
+import DetailProperty from '../../../../ascribe_detail/detail_property';
+
+import ApiUrls from '../../../../../constants/api_urls';
+import { mergeOptions } from '../../../../../utils/general_utils';
+import { getLangText } from '../../../../../utils/lang_utils';
+
+let Link = Router.Link;
+
+/**
+ * This is the component that implements resource/data specific functionality
+ */
+let PieceContainer = React.createClass({
+ getInitialState() {
+ return mergeOptions(
+ PieceStore.getState(),
+ UserStore.getState()
+ );
+ },
+
+ componentDidMount() {
+ PieceStore.listen(this.onChange);
+ PieceActions.fetchOne(this.props.params.pieceId);
+ UserStore.listen(this.onChange);
+ },
+
+ // This is done to update the container when the user clicks on the prev or next
+ // button to update the URL parameter (and therefore to switch pieces)
+ componentWillReceiveProps(nextProps) {
+ if(this.props.params.pieceId !== nextProps.params.pieceId) {
+ PieceActions.updatePiece({});
+ PieceActions.fetchOne(nextProps.params.pieceId);
+ }
+ },
+
+ componentWillUnmount() {
+ // Every time we're leaving the piece detail page,
+ // just reset the piece that is saved in the piece store
+ // as it will otherwise display wrong/old data once the user loads
+ // the piece detail a second time
+ PieceActions.updatePiece({});
+ PieceStore.unlisten(this.onChange);
+ UserStore.unlisten(this.onChange);
+ },
+
+
+ onChange(state) {
+ this.setState(state);
+ },
+
+ loadPiece() {
+ PieceActions.fetchOne(this.props.params.pieceId);
+ },
+
+ getActions() {
+ if (this.state.piece &&
+ this.state.piece.notifications &&
+ this.state.piece.notifications.length > 0) {
+ return (
+ );
+ }
+ },
+
+ render() {
+ if(this.state.piece && this.state.piece.title) {
+ /*
+
+ This really needs a refactor!
+
+ - Tim
+
+ */
+ // Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
+ let artistName = ((this.state.currentUser.is_jury && !this.state.currentUser.is_judge) ||
+ (this.state.currentUser.is_judge && !this.state.piece.selected )) ?
+ : this.state.piece.artist_name;
+
+ // Only show the artist email if you are a judge and the piece is shortlisted
+ let artistEmail = (this.state.currentUser.is_judge && this.state.piece.selected ) ?
+ : null;
+
+ return (
+
+
+
+
+ );
+ }
+});
+
+export default CylandPieceList;
diff --git a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js
new file mode 100644
index 00000000..84713bd9
--- /dev/null
+++ b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js
@@ -0,0 +1,231 @@
+'use strict';
+
+import React from 'react';
+import Router from 'react-router';
+
+import Moment from 'moment';
+
+import Col from 'react-bootstrap/lib/Col';
+import Row from 'react-bootstrap/lib/Row';
+
+import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
+
+import WhitelabelActions from '../../../../../actions/whitelabel_actions';
+import WhitelabelStore from '../../../../../stores/whitelabel_store';
+
+import PieceListStore from '../../../../../stores/piece_list_store';
+import PieceListActions from '../../../../../actions/piece_list_actions';
+
+import UserStore from '../../../../../stores/user_store';
+import UserActions from '../../../../../actions/user_actions';
+
+import PieceStore from '../../../../../stores/piece_store';
+import PieceActions from '../../../../../actions/piece_actions';
+
+import GlobalNotificationModel from '../../../../../models/global_notification_model';
+import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
+
+import CylandAdditionalDataForm from './ascribe_forms/cyland_additional_data_form';
+
+import LoanForm from '../../../../ascribe_forms/form_loan';
+
+import SlidesContainer from '../../../../ascribe_slides_container/slides_container';
+
+import ApiUrls from '../../../../../constants/api_urls';
+
+import { getLangText } from '../../../../../utils/lang_utils';
+import { mergeOptions } from '../../../../../utils/general_utils';
+import { getAclFormMessage } from '../../../../../utils/form_utils';
+
+
+let CylandRegisterPiece = React.createClass({
+
+ mixins: [Router.Navigation, Router.State],
+
+ getInitialState(){
+ return mergeOptions(
+ UserStore.getState(),
+ PieceListStore.getState(),
+ PieceStore.getState(),
+ WhitelabelStore.getState(),
+ {
+ selectedLicense: 0,
+ isFineUploaderActive: false,
+ step: 0
+ });
+ },
+
+ componentDidMount() {
+ PieceListStore.listen(this.onChange);
+ UserStore.listen(this.onChange);
+ PieceStore.listen(this.onChange);
+ WhitelabelStore.listen(this.onChange);
+ UserActions.fetchCurrentUser();
+ WhitelabelActions.fetchWhitelabel();
+
+ let queryParams = this.getQuery();
+
+ // Since every step of this register process is atomic,
+ // we may need to enter the process at step 1 or 2.
+ // If this is the case, we'll need the piece number to complete submission.
+ // It is encoded in the URL as a queryParam and we're checking for it here.
+ //
+ // We're using 'in' here as we want to know if 'piece_id' is present in the url,
+ // we don't care about the value.
+ if(queryParams && 'piece_id' in queryParams) {
+ PieceActions.fetchOne(queryParams.piece_id);
+ }
+ },
+
+ componentWillUnmount() {
+ PieceListStore.unlisten(this.onChange);
+ UserStore.unlisten(this.onChange);
+ PieceStore.unlisten(this.onChange);
+ WhitelabelStore.unlisten(this.onChange);
+ },
+
+ onChange(state) {
+ this.setState(state);
+
+ if(this.state.currentUser && this.state.currentUser.email) {
+ // we should also make the fineuploader component editable again
+ this.setState({
+ isFineUploaderActive: true
+ });
+ }
+ },
+
+ handleRegisterSuccess(response){
+
+ this.refreshPieceList();
+
+ // also start loading the piece for the next step
+ if(response && response.piece) {
+ PieceActions.updatePiece(response.piece);
+ }
+
+ this.incrementStep();
+
+ this.refs.slidesContainer.nextSlide();
+ },
+
+ handleAdditionalDataSuccess() {
+
+ // We need to refetch the piece again after submitting the additional data
+ // since we want it's otherData to be displayed when the user choses to click
+ // on the browsers back button.
+ PieceActions.fetchOne(this.state.piece.id);
+
+ this.refreshPieceList();
+
+ this.incrementStep();
+
+ this.refs.slidesContainer.nextSlide();
+ },
+
+ handleLoanSuccess(response) {
+ let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
+
+ this.refreshPieceList();
+
+ PieceActions.fetchOne(this.state.piece.id);
+ this.transitionTo('piece', {pieceId: this.state.piece.id});
+ },
+
+ // We need to increase the step to lock the forms that are already filled out
+ incrementStep() {
+ // also increase step
+ let newStep = this.state.step + 1;
+ this.setState({
+ step: newStep
+ });
+ },
+
+ refreshPieceList() {
+ PieceListActions.fetchPieceList(
+ this.state.page,
+ this.state.pageSize,
+ this.state.searchTerm,
+ this.state.orderBy,
+ this.state.orderAsc,
+ this.state.filterBy
+ );
+ },
+
+ changeSlide() {
+ // only transition to the login store, if user is not logged in
+ // ergo the currentUser object is not properly defined
+ if(this.state.currentUser && !this.state.currentUser.email) {
+ this.onLoggedOut();
+ }
+ },
+
+ // basically redirects to the second slide (index: 1), when the user is not logged in
+ onLoggedOut() {
+ this.transitionTo('login');
+ },
+
+ render() {
+
+ let today = new Moment();
+ let datetimeWhenWeAllWillBeFlyingCoolHoverboardsAndDinosaursWillLiveAgain = new Moment();
+ datetimeWhenWeAllWillBeFlyingCoolHoverboardsAndDinosaursWillLiveAgain.add(1000, 'years');
+
+ return (
+
+
+ As an entirely digital broadcasting and licensing company we’re always keen to properly handle the content that artists, museums, and archives consign to us. The main concern with art online is the risk it will be misused. Thanks to our partnership with ascribe.io, we can address that issue in a way that is faster and more efficient for our users.
+ Using ascribe means we can do away with paper contracts and replace them with an online-only version. Partnering with ascribe also means we can encrypt digital work once it is uploaded. This revolutionary service will allow you to keep track of your works and share without worry.
+
+
+
+
+ NEW SUBSCRIPTION SERVICE
+
+
+ IkonoTV has developed an app that provides playlists on demand—soon to be available on all online devices and SmartTVs. We can now offer the possibility of a share in revenue to compensate for the artist’s work.
+
+
+
+
+ THE RAPID GROWTH OF IkonoTV
+
+
+ In October 2014, our first app was installed on Amazon Fire TV. During the first month it was downloaded 200 times, and jumped to 5,000 by the second month. Today, we’re well over the 285,000 mark, making us the number one app in our category in the US, Canada, UK and Germany.
+
+
+
+
+ FULL TRANSPARENCY
+
+
+ We expect a similar success with each SmartTV brand. For us, this marks the beginning of a new way to offer hassle-free licensing to visual artists—and we’re very proud to be an integral part of this virtual market. In the future, should we plan anything not directly mentioned in the contract, we will always make sure to secure the artist’s approval first. ikonoTV was developed to serve art and artists, and for this reason it’s of the utmost importance to us to respect this relationship. Thanks to you, we now look forward to our next big step.
+
+ );
+ }
+});
+
+export default IkonotvPieceList;
diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js
new file mode 100644
index 00000000..38078747
--- /dev/null
+++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js
@@ -0,0 +1,271 @@
+'use strict';
+
+import React from 'react';
+import Moment from 'moment';
+import Router from 'react-router';
+
+import Col from 'react-bootstrap/lib/Col';
+import Row from 'react-bootstrap/lib/Row';
+
+import PieceListStore from '../../../../../stores/piece_list_store';
+import PieceListActions from '../../../../../actions/piece_list_actions';
+
+import UserStore from '../../../../../stores/user_store';
+import UserActions from '../../../../../actions/user_actions';
+
+import PieceStore from '../../../../../stores/piece_store';
+import PieceActions from '../../../../../actions/piece_actions';
+
+import GlobalNotificationModel from '../../../../../models/global_notification_model';
+import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
+
+import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
+import LoanForm from '../../../../ascribe_forms/form_loan';
+
+import IkonotvArtistDetailsForm from './ascribe_forms/ikonotv_artist_details_form';
+import IkonotvArtworkDetailsForm from './ascribe_forms/ikonotv_artwork_details_form';
+
+import SlidesContainer from '../../../../ascribe_slides_container/slides_container';
+
+import ApiUrls from '../../../../../constants/api_urls';
+
+import { mergeOptions } from '../../../../../utils/general_utils';
+import { getLangText } from '../../../../../utils/lang_utils';
+
+let IkonotvRegisterPiece = React.createClass({
+
+ propTypes: {
+ handleSuccess: React.PropTypes.func,
+ piece: React.PropTypes.object.isRequired
+ },
+
+ mixins: [Router.Navigation, Router.State],
+
+ getInitialState(){
+ return mergeOptions(
+ UserStore.getState(),
+ PieceListStore.getState(),
+ PieceStore.getState(),
+ {
+ step: 0
+ });
+ },
+
+ componentDidMount() {
+ PieceListStore.listen(this.onChange);
+ UserStore.listen(this.onChange);
+ PieceStore.listen(this.onChange);
+ UserActions.fetchCurrentUser();
+
+ // Before we load the new piece, we reset the piece store to delete old data that we do
+ // not want to display to the user.
+ PieceActions.updatePiece({});
+
+ let queryParams = this.getQuery();
+
+ // Since every step of this register process is atomic,
+ // we may need to enter the process at step 1 or 2.
+ // If this is the case, we'll need the piece number to complete submission.
+ // It is encoded in the URL as a queryParam and we're checking for it here.
+ //
+ // We're using 'in' here as we want to know if 'piece_id' is present in the url,
+ // we don't care about the value.
+ if (queryParams && 'piece_id' in queryParams) {
+ PieceActions.fetchOne(queryParams.piece_id);
+ }
+ },
+
+ componentWillUnmount() {
+ PieceListStore.unlisten(this.onChange);
+ UserStore.unlisten(this.onChange);
+ PieceStore.unlisten(this.onChange);
+ },
+
+ onChange(state) {
+ this.setState(state);
+
+ if(this.state.currentUser && this.state.currentUser.email) {
+ // we should also make the fineuploader component editable again
+ this.setState({
+ isFineUploaderActive: true
+ });
+ }
+ },
+
+
+ handleRegisterSuccess(response){
+
+ this.refreshPieceList();
+
+ // also start loading the piece for the next step
+ if(response && response.piece) {
+ PieceActions.updatePiece(response.piece);
+ }
+ if (!this.canSubmit()) {
+ this.transitionTo('pieces');
+ }
+ else {
+ this.incrementStep();
+ this.refs.slidesContainer.nextSlide();
+ }
+
+ },
+
+ handleAdditionalDataSuccess() {
+
+ // We need to refetch the piece again after submitting the additional data
+ // since we want it's otherData to be displayed when the user choses to click
+ // on the browsers back button.
+ PieceActions.fetchOne(this.state.piece.id);
+
+ this.refreshPieceList();
+
+ this.incrementStep();
+
+ this.refs.slidesContainer.nextSlide();
+ },
+
+ handleLoanSuccess(response) {
+ let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
+ GlobalNotificationActions.appendGlobalNotification(notification);
+
+ this.refreshPieceList();
+
+ PieceActions.fetchOne(this.state.piece.id);
+ this.transitionTo('piece', {pieceId: this.state.piece.id});
+ },
+
+ // We need to increase the step to lock the forms that are already filled out
+ incrementStep() {
+ // also increase step
+ let newStep = this.state.step + 1;
+ this.setState({
+ step: newStep
+ });
+ },
+
+ refreshPieceList() {
+ PieceListActions.fetchPieceList(
+ this.state.page,
+ this.state.pageSize,
+ this.state.searchTerm,
+ this.state.orderBy,
+ this.state.orderAsc,
+ this.state.filterBy
+ );
+ },
+
+ changeSlide() {
+ // only transition to the login store, if user is not logged in
+ // ergo the currentUser object is not properly defined
+ if(this.state.currentUser && !this.state.currentUser.email) {
+ this.onLoggedOut();
+ }
+ },
+
+ // basically redirects to the second slide (index: 1), when the user is not logged in
+ onLoggedOut() {
+ this.transitionTo('login');
+ },
+
+ canSubmit() {
+ let currentUser = this.state.currentUser;
+ return currentUser && currentUser.acl && currentUser.acl.acl_wallet_submit;
+ },
+
+ getSlideArtistDetails() {
+ if (this.canSubmit()) {
+ return (
+