diff --git a/ansible/ubuntu/vagrant_playbook.yml b/ansible/ubuntu/vagrant_playbook.yml index dd25b2e0c..44b1a6ef0 100755 --- a/ansible/ubuntu/vagrant_playbook.yml +++ b/ansible/ubuntu/vagrant_playbook.yml @@ -199,7 +199,7 @@ - { regexp: '^DB_PASSWORD=', line: 'DB_PASSWORD=vagrant' } - { regexp: '^APP_URL=', line: "APP_URL=http://{{ fqdn }}" } - { regexp: '^APP_ENV=', line: "APP_ENV=development" } - - { regexp: '^APP_DEBUG=', line: "APP_ENV=true" } + - { regexp: '^APP_DEBUG=', line: "APP_DEBUG=true" } - name: Generate application key shell: "php {{ app_path }}/artisan key:generate --force" - name: Artisan Migrate diff --git a/app/Http/Controllers/Api/ComponentsController.php b/app/Http/Controllers/Api/ComponentsController.php index d7af18b21..cef8506d7 100644 --- a/app/Http/Controllers/Api/ComponentsController.php +++ b/app/Http/Controllers/Api/ComponentsController.php @@ -8,6 +8,9 @@ use App\Http\Transformers\ComponentsTransformer; use App\Models\Company; use App\Models\Component; use Illuminate\Http\Request; +use App\Events\CheckoutableCheckedIn; +use App\Events\ComponentCheckedIn; +use App\Models\Asset; class ComponentsController extends Controller { @@ -172,4 +175,119 @@ class ComponentsController extends Controller $assets = $assets->skip($offset)->take($limit)->get(); return (new ComponentsTransformer)->transformCheckedoutComponents($assets, $total); } + + + /** + * Validate and checkout the component. + * + * @author [A. Gianotto] [] + * t + * @since [v5.1.8] + * @param Request $request + * @param int $componentId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function checkout(Request $request, $componentId) + { + // Check if the component exists + if (is_null($component = Component::find($componentId))) { + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.does_not_exist'))); + } + + $this->authorize('checkout', $component); + + + if ($component->numRemaining() > $request->get('assigned_qty')) { + + if (!$asset = Asset::find($request->input('assigned_to'))) { + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist'))); + } + + // Update the accessory data + $component->assigned_to = $request->input('assigned_to'); + + $component->assets()->attach($component->id, [ + 'component_id' => $component->id, + 'created_at' => \Carbon::now(), + 'assigned_qty' => $request->get('assigned_qty'), + 'user_id' => \Auth::id(), + 'asset_id' => $request->get('assigned_to') + ]); + + $component->logCheckout($request->input('note'), $asset); + + return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkout.success'))); + } + + return response()->json(Helper::formatStandardApiResponse('error', null, 'Not enough components remaining: '.$component->numRemaining().' remaining, '.$request->get('assigned_qty').' requested.')); + } + + /** + * Validate and store checkin data. + * + * @author [A. Gianotto] [] + * @since [v5.1.8] + * @param Request $request + * @param $component_asset_id + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function checkin(Request $request, $component_asset_id) + { + if ($component_assets = \DB::table('components_assets')->find($component_asset_id)) { + + if (is_null($component = Component::find($component_assets->component_id))) { + + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.not_found'))); + } + + $this->authorize('checkin', $component); + + $max_to_checkin = $component_assets->assigned_qty; + + if ($max_to_checkin > 1) { + + $validator = \Validator::make($request->all(), [ + "checkin_qty" => "required|numeric|between:1,$max_to_checkin" + ]); + + if ($validator->fails()) { + return response()->json(Helper::formatStandardApiResponse('error', null, 'Checkin quantity must be between 1 and '.$max_to_checkin)); + } + } + + + // Validation passed, so let's figure out what we have to do here. + $qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty', 1)); + + // We have to modify the record to reflect the new qty that's + // actually checked out. + $component_assets->assigned_qty = $qty_remaining_in_checkout; + + \Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id); + + \DB::table('components_assets')->where('id', + $component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]); + + // If the checked-in qty is exactly the same as the assigned_qty, + // we can simply delete the associated components_assets record + if ($qty_remaining_in_checkout == 0) { + \DB::table('components_assets')->where('id', '=', $component_asset_id)->delete(); + } + + + $asset = Asset::find($component_assets->asset_id); + + event(new CheckoutableCheckedIn($component, $asset, \Auth::user(), $request->input('note'), \Carbon::now())); + + return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkin.success'))); + + } + + return response()->json(Helper::formatStandardApiResponse('error', null, 'No matching checkouts for that component join record')); + + + } + } diff --git a/public/js/build/app.js b/public/js/build/app.js index 128d7a003..6ce1b4d45 100644 --- a/public/js/build/app.js +++ b/public/js/build/app.js @@ -1,57070 +1,2 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = "/"; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 0); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./node_modules/admin-lte/build/less/AdminLTE.less": -/*!*********************************************************!*\ - !*** ./node_modules/admin-lte/build/less/AdminLTE.less ***! - \*********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/alert.vue?vue&type=script&lang=js&": -/*!***********************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/alert.vue?vue&type=script&lang=js& ***! - \***********************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - /* - * The component's data. - */ - props: ['alertType', 'title'], - computed: { - alertClassName: function alertClassName() { - return 'alert-' + this.alertType; - } - }, - methods: { - hideEvent: function hideEvent() { - this.$emit('hide'); - } - } -}); - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/forms/asset-models/fieldset-default-values.vue?vue&type=script&lang=js&": -/*!************************************************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/forms/asset-models/fieldset-default-values.vue?vue&type=script&lang=js& ***! - \************************************************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - props: ['fieldsetId', 'modelId', 'previousInput'], - data: function data() { - return { - identifiers: { - fieldset: null, - model: null - }, - elements: { - fieldset: null, - field: null - }, - fields: null, - show: false, - error: false - }; - }, - - /** - * Initialise the component (Vue 1.x). - */ - ready: function ready() { - this.init(); - }, - - /** - * Initialise the component (Vue 2.x). - */ - mounted: function mounted() { - this.init(); - }, - methods: { - /** - * Grabs the toggle field and connected fieldset and if present, - * set up the rest of the component. Scope lookups to the component - * only so we're not traversing and/or manipulating the whole DOM - */ - init: function init() { - this.defaultValues = JSON.parse(this.previousInput); - this.identifiers.fieldset = this.fieldsetId; - this.identifiers.model = this.modelId; // This has to be jQuery because a lot of native functions/events - // do not work with select2 - - this.elements.fieldset = $('.js-fieldset-field'); - this.elements.field = document.querySelector('.js-default-values-toggler'); - - if (this.elements.fieldset && this.elements.field) { - this.addListeners(); - this.getFields(); - } - }, - - /** - * Adds event listeners for: - * - Toggle field changing - * - Fieldset field changing - * - * Using jQuery event hooks for the select2 fieldset field as - * select2 does not emit DOM events... - */ - addListeners: function addListeners() { - var _this = this; - - this.elements.field.addEventListener('change', function (e) { - return _this.updateShow(); - }); - this.elements.fieldset.on('change', function (e) { - return _this.updateFields(); - }); - }, - - /** - * Call the CustomFieldsetsController::fields() endpoint to grab - * the fields we can set default values for - */ - getFields: function getFields() { - var _this2 = this; - - if (!this.identifiers.fieldset) { - return this.fields = []; - } - - this.$http.get(this.getUrl()).then(function (response) { - return response.json(); - }).then(function (data) { - return _this2.checkResponseForError(data); - }).then(function (data) { - return _this2.fields = data.rows; - }).then(function () { - return _this2.determineIfShouldShow(); - }); - }, - getValue: function getValue(field) { - if (field.default_value) { - return field.default_value; - } - - return this.defaultValues != null ? this.defaultValues[field.id.toString()] : ''; - }, - - /** - * Generates the API URL depending on what information is available - * - * @return Router - */ - getUrl: function getUrl() { - if (this.identifiers.model) { - return route('api.fieldsets.fields-with-default-value', { - fieldset: this.identifiers.fieldset, - model: this.identifiers.model - }); - } - - return route('api.fieldsets.fields', { - fieldset: this.identifiers.fieldset - }); - }, - - /** - * Sets error state and shows error if request was not marked - * successful - */ - checkResponseForError: function checkResponseForError(data) { - this.error = data.status == 'error'; - return data; - }, - - /** - * Checks whether the toggler is checked and shows the default - * values field dependent on that - */ - updateShow: function updateShow() { - if (this.identifiers.fieldset && this.elements.field) { - this.show = this.elements.field.checked; - } - }, - - /** - * checks the 'add default values' checkbox if it is already checked - * OR this.show is already set to true OR if any fields already have - * a default value. - */ - determineIfShouldShow: function determineIfShouldShow() { - this.elements.field.checked = this.elements.field.checked || this.show || this.fields.reduce(function (accumulator, currentValue) { - return accumulator || currentValue.default_value; - }, false); - this.updateShow(); - }, - updateFields: function updateFields() { - this.identifiers.fieldset = this.elements.fieldset[0].value ? parseInt(this.elements.fieldset[0].value) : false; - this.getFields(); - } - } -}); - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/importer/importer-errors.vue?vue&type=script&lang=js&": -/*!******************************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/importer/importer-errors.vue?vue&type=script&lang=js& ***! - \******************************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - /* - * The component's data. - */ - props: ['errors'] -}); - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/importer/importer-file.vue?vue&type=script&lang=js&": -/*!****************************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/importer/importer-file.vue?vue&type=script&lang=js& ***! - \****************************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - props: ['file', 'customFields'], - data: function data() { - return { - activeFile: this.file, - processDetail: false, - statusText: null, - statusType: null, - options: { - importType: this.file.import_type, - update: false, - importTypes: [{ - id: 'asset', - text: 'Assets' - }, { - id: 'accessory', - text: 'Accessories' - }, { - id: 'consumable', - text: 'Consumables' - }, { - id: 'component', - text: 'Components' - }, { - id: 'license', - text: 'Licenses' - }, { - id: 'user', - text: 'Users' - }], - statusText: null - }, - columnOptions: { - general: [{ - id: 'category', - text: 'Category' - }, { - id: 'company', - text: 'Company' - }, { - id: 'email', - text: 'Email' - }, { - id: 'item_name', - text: 'Item Name' - }, { - id: 'location', - text: 'Location' - }, { - id: 'maintained', - text: 'Maintained' - }, { - id: 'manufacturer', - text: 'Manufacturer' - }, { - id: 'notes', - text: 'Notes' - }, { - id: 'order_number', - text: 'Order Number' - }, { - id: 'purchase_cost', - text: 'Purchase Cost' - }, { - id: 'purchase_date', - text: 'Purchase Date' - }, { - id: 'quantity', - text: 'Quantity' - }, { - id: 'requestable', - text: 'Requestable' - }, { - id: 'serial', - text: 'Serial Number' - }, { - id: 'supplier', - text: 'Supplier' - }, { - id: 'username', - text: 'Username' - }, { - id: 'department', - text: 'Department' - }], - assets: [{ - id: 'asset_tag', - text: 'Asset Tag' - }, { - id: 'asset_model', - text: 'Model Name' - }, { - id: 'checkout_class', - text: 'Checkout Type' - }, { - id: 'checkout_location', - text: 'Checkout Location' - }, { - id: 'image', - text: 'Image Filename' - }, { - id: 'model_number', - text: 'Model Number' - }, { - id: 'full_name', - text: 'Full Name' - }, { - id: 'status', - text: 'Status' - }, { - id: 'warranty_months', - text: 'Warranty Months' - }], - consumables: [{ - id: 'item_no', - text: "Item Number" - }, { - id: 'model_number', - text: "Model Number" - }], - licenses: [{ - id: 'asset_tag', - text: 'Assigned To Asset' - }, { - id: 'expiration_date', - text: 'Expiration Date' - }, { - id: 'full_name', - text: 'Full Name' - }, { - id: 'license_email', - text: 'Licensed To Email' - }, { - id: 'license_name', - text: 'Licensed To Name' - }, { - id: 'purchase_order', - text: 'Purchase Order' - }, { - id: 'reassignable', - text: 'Reassignable' - }, { - id: 'seats', - text: 'Seats' - }], - users: [{ - id: 'employee_num', - text: 'Employee Number' - }, { - id: 'first_name', - text: 'First Name' - }, { - id: 'jobtitle', - text: 'Job Title' - }, { - id: 'last_name', - text: 'Last Name' - }, { - id: 'phone_number', - text: 'Phone Number' - }, { - id: 'manager_first_name', - text: 'Manager First Name' - }, { - id: 'manager_last_name', - text: 'Manager Last Name' - }, { - id: 'department', - text: 'Department' - }, { - id: 'activated', - text: 'Activated' - }, { - id: 'address', - text: 'Address' - }, { - id: 'city', - text: 'City' - }, { - id: 'state', - text: 'State' - }, { - id: 'country', - text: 'Country' - }], - customFields: this.customFields - }, - columnMappings: this.file.field_map || {}, - activeColumn: null - }; - }, - created: function created() { - window.eventHub.$on('showDetails', this.toggleExtendedDisplay); - this.populateSelect2ActiveItems(); - }, - computed: { - columns: function columns() { - // function to sort objects by their display text. - function sorter(a, b) { - if (a.text < b.text) return -1; - if (a.text > b.text) return 1; - return 0; - } - - switch (this.options.importType) { - case 'asset': - return this.columnOptions.general.concat(this.columnOptions.assets).concat(this.columnOptions.customFields).sort(sorter); - - case 'consumable': - return this.columnOptions.general.concat(this.columnOptions.consumables).sort(sorter); - - case 'license': - return this.columnOptions.general.concat(this.columnOptions.licenses).sort(sorter); - - case 'user': - return this.columnOptions.general.concat(this.columnOptions.users).sort(sorter); - } - - return this.columnOptions.general; - }, - alertClass: function alertClass() { - if (this.statusType == 'success') { - return 'alert-success'; - } - - if (this.statusType == 'error') { - return 'alert-danger'; - } - - return 'alert-info'; - } - }, - watch: { - columns: function columns() { - this.populateSelect2ActiveItems(); - } - }, - methods: { - postSave: function postSave() { - var _this = this; - - console.log('saving'); - console.log(this.options.importType); - - if (!this.options.importType) { - this.statusType = 'error'; - this.statusText = "An import type is required... "; - return; - } - - this.statusType = 'pending'; - this.statusText = "Processing..."; - this.$http.post(route('api.imports.importFile', this.file.id), { - 'import-update': this.options.update, - 'send-welcome': this.options.send_welcome, - 'import-type': this.options.importType, - 'run-backup': this.options.run_backup, - 'column-mappings': this.columnMappings - }).then(function (_ref) { - var body = _ref.body; - // Success - _this.statusType = "success"; - _this.statusText = "Success... Redirecting."; - window.location.href = body.messages.redirect_url; - }, function (_ref2) { - var body = _ref2.body; - - // Failure - if (body.status == 'import-errors') { - window.eventHub.$emit('importErrors', body.messages); - _this.statusType = 'error'; - _this.statusText = "Error"; - } else { - _this.$emit('alert', { - message: body.messages, - type: "danger", - visible: true - }); - } - - _this.displayImportModal = false; - }); - }, - populateSelect2ActiveItems: function populateSelect2ActiveItems() { - if (this.file.field_map == null) { - // Begin by populating the active selection in dropdowns with blank values. - for (var i = 0; i < this.file.header_row.length; i++) { - this.$set(this.columnMappings, this.file.header_row[i], null); - } // Then, for any values that have a likely match, we make that active. - - - for (var j = 0; j < this.columns.length; j++) { - var column = this.columns[j]; - var lower = this.file.header_row.map(function (value) { - return value.toLowerCase(); - }); - var index = lower.indexOf(column.text.toLowerCase()); - - if (index != -1) { - this.$set(this.columnMappings, this.file.header_row[index], column.id); - } - } - } - }, - toggleExtendedDisplay: function toggleExtendedDisplay(fileId) { - if (fileId == this.file.id) { - this.processDetail = !this.processDetail; - } - }, - updateModel: function updateModel(header, value) { - this.columnMappings[header] = value; - } - }, - components: { - select2: __webpack_require__(/*! ../select2.vue */ "./resources/assets/js/components/select2.vue") - } -}); - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/importer/importer.vue?vue&type=script&lang=js&": -/*!***********************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/importer/importer.vue?vue&type=script&lang=js& ***! - \***********************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -__webpack_require__(/*! blueimp-file-upload */ "./node_modules/blueimp-file-upload/js/jquery.fileupload.js"); - -/* harmony default export */ __webpack_exports__["default"] = ({ - /* - * The component's data. - */ - data: function data() { - return { - files: [], - displayImportModal: false, - activeFile: null, - alert: { - type: null, - message: null, - visible: false - }, - importErrors: null, - progress: { - currentClass: "progress-bar-warning", - currentPercent: "0", - statusText: '', - visible: false - }, - customFields: [] - }; - }, - mounted: function mounted() { - window.eventHub.$on('importErrors', this.updateImportErrors); - this.fetchFiles(); - this.fetchCustomFields(); - var vm = this; - $('#fileupload').fileupload({ - dataType: 'json', - done: function done(e, data) { - vm.progress.currentClass = "progress-bar-success"; - vm.progress.statusText = "Success!"; - vm.files = data.result.files.concat(vm.files); - console.log(data.result.header_row); - }, - add: function add(e, data) { - data.headers = { - "X-Requested-With": 'XMLHttpRequest', - "X-CSRF-TOKEN": Laravel.csrfToken - }; - data.process().done(function () { - data.submit(); - }); - vm.progress.visible = true; - }, - progress: function progress(e, data) { - var progress = parseInt((data.loaded / data.total * 100, 10)); - vm.progress.currentPercent = progress; - vm.progress.statusText = progress + '% Complete'; - }, - fail: function fail(e, data) { - vm.progress.currentClass = "progress-bar-danger"; // Display any errors returned from the $.ajax() - - vm.progress.statusText = data.jqXHR.responseJSON.messages; - } - }); - }, - methods: { - fetchFiles: function fetchFiles() { - var _this = this; - - this.$http.get(route('api.imports.index')).then(function (_ref) { - var data = _ref.data; - return _this.files = data; - }, // Success - //Fail - function (response) { - _this.alert.type = "danger"; - _this.alert.visible = true; - _this.alert.message = "Something went wrong fetching files..."; - }); - }, - fetchCustomFields: function fetchCustomFields() { - var _this2 = this; - - this.$http.get(route('api.customfields.index')).then(function (_ref2) { - var data = _ref2.data; - data = data.rows; - data.forEach(function (item) { - _this2.customFields.push({ - 'id': item.db_column_name, - 'text': item.name - }); - }); - }); - }, - deleteFile: function deleteFile(file, key) { - var _this3 = this; - - this.$http["delete"](route('api.imports.destroy', file.id)).then( // Success, remove file from array. - function (response) { - _this3.files.splice(key, 1); - - _this3.alert.type = response.body.status; // A failed delete can still cause a 200 status code. - - _this3.alert.visible = true; - _this3.alert.message = response.body.messages; - }, function (response) { - // Fail - // this.files.splice(key, 1); - _this3.alert.type = "error"; - _this3.alert.visible = true; - _this3.alert.message = response.body.messages; - }); - }, - toggleEvent: function toggleEvent(fileId) { - window.eventHub.$emit('showDetails', fileId); - }, - updateAlert: function updateAlert(alert) { - this.alert = alert; - }, - updateImportErrors: function updateImportErrors(errors) { - this.importErrors = errors; - } - }, - computed: { - progressWidth: function progressWidth() { - return "width: " + this.progress.currentPercent * 10 + '%'; - } - }, - components: { - alert: __webpack_require__(/*! ../alert.vue */ "./resources/assets/js/components/alert.vue"), - errors: __webpack_require__(/*! ./importer-errors.vue */ "./resources/assets/js/components/importer/importer-errors.vue"), - importFile: __webpack_require__(/*! ./importer-file.vue */ "./resources/assets/js/components/importer/importer-file.vue") - } -}); - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js&": -/*!********************************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js& ***! - \********************************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - props: ['clientsUrl', 'tokensUrl'], - - /* - * The component's data. - */ - data: function data() { - return { - tokens: [] - }; - }, - - /** - * Prepare the component (Vue 1.x). - */ - ready: function ready() { - this.prepareComponent(); - }, - - /** - * Prepare the component (Vue 2.x). - */ - mounted: function mounted() { - this.prepareComponent(); - }, - methods: { - /** - * Prepare the component (Vue 2.x). - */ - prepareComponent: function prepareComponent() { - this.getTokens(); - }, - - /** - * Get all of the authorized tokens for the user. - */ - getTokens: function getTokens() { - var _this = this; - - this.$http.get(this.tokensUrl).then(function (response) { - _this.tokens = response.data; - }); - }, - - /** - * Revoke the given token. - */ - revoke: function revoke(token) { - var _this2 = this; - - this.$http["delete"](this.tokensUrl + '/' + token.id).then(function (response) { - _this2.getTokens(); - }); - } - } -}); - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/passport/Clients.vue?vue&type=script&lang=js&": -/*!**********************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/passport/Clients.vue?vue&type=script&lang=js& ***! - \**********************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } - -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - /* - * The component's data. - */ - props: ['clientsUrl'], - data: function data() { - return { - clients: [], - createForm: { - errors: [], - name: '', - redirect: '' - }, - editForm: { - errors: [], - name: '', - redirect: '' - } - }; - }, - - /** - * Prepare the component (Vue 1.x). - */ - ready: function ready() { - this.prepareComponent(); - }, - - /** - * Prepare the component (Vue 2.x). - */ - mounted: function mounted() { - this.prepareComponent(); - }, - methods: { - /** - * Prepare the component. - */ - prepareComponent: function prepareComponent() { - this.getClients(); - $('#modal-create-client').on('shown.bs.modal', function () { - $('#create-client-name').focus(); - }); - $('#modal-edit-client').on('shown.bs.modal', function () { - $('#edit-client-name').focus(); - }); - }, - - /** - * Get all of the OAuth clients for the user. - */ - getClients: function getClients() { - var _this = this; - - this.$http.get(this.clientsUrl).then(function (response) { - _this.clients = response.data; - }); - }, - - /** - * Show the form for creating new clients. - */ - showCreateClientForm: function showCreateClientForm() { - $('#modal-create-client').modal('show'); - }, - - /** - * Create a new OAuth client for the user. - */ - store: function store() { - this.persistClient('post', this.clientsUrl, this.createForm, '#modal-create-client'); - }, - - /** - * Edit the given client. - */ - edit: function edit(client) { - this.editForm.id = client.id; - this.editForm.name = client.name; - this.editForm.redirect = client.redirect; - $('#modal-edit-client').modal('show'); - }, - - /** - * Update the client being edited. - */ - update: function update() { - this.persistClient('put', this.clientsUrl + '/' + this.editForm.id, this.editForm, '#modal-edit-client'); - }, - - /** - * Persist the client to storage using the given form. - */ - persistClient: function persistClient(method, uri, form, modal) { - var _this2 = this; - - console.log('persisting'); - form.errors = []; - console.log('method: ' + method); - this.$http[method](uri, form).then(function (response) { - _this2.getClients(); - - form.name = ''; - form.redirect = ''; - form.errors = []; - $(modal).modal('hide'); - })["catch"](function (response) { - if (_typeof(response.data) === 'object') { - form.errors = _.flatten(_.toArray(response.data)); - } else { - form.errors = ['Something went wrong. Please try again.']; - } - }); - }, - - /** - * Destroy the given client. - */ - destroy: function destroy(client) { - var _this3 = this; - - this.$http["delete"](this.clientsUrl + '/' + client.id).then(function (response) { - _this3.getClients(); - }); - } - } -}); - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js&": -/*!***********************************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js& ***! - \***********************************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } - -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - props: ['tokenUrl', 'scopesUrl'], - - /* - * The component's data. - */ - data: function data() { - return { - accessToken: null, - tokens: [], - scopes: [], - form: { - name: '', - scopes: [], - errors: [] - } - }; - }, - - /** - * Prepare the component (Vue 1.x). - */ - ready: function ready() { - this.prepareComponent(); - }, - - /** - * Prepare the component (Vue 2.x). - */ - mounted: function mounted() { - this.prepareComponent(); - }, - methods: { - /** - * Prepare the component. - */ - prepareComponent: function prepareComponent() { - this.getTokens(); - this.getScopes(); - $('#modal-create-token').on('shown.bs.modal', function () { - $('#create-token-name').focus(); - }); - }, - - /** - * Get all of the personal access tokens for the user. - */ - getTokens: function getTokens() { - var _this = this; - - this.$http.get(this.tokenUrl).then(function (response) { - _this.tokens = response.data; - }); - }, - - /** - * Get all of the available scopes. - */ - getScopes: function getScopes() { - var _this2 = this; - - this.$http.get(this.scopesUrl).then(function (response) { - _this2.scopes = response.data; - }); - }, - - /** - * Show the form for creating new tokens. - */ - showCreateTokenForm: function showCreateTokenForm() { - $('#modal-create-token').modal('show'); - }, - - /** - * Create a new personal access token. - */ - store: function store() { - var _this3 = this; - - this.accessToken = null; - this.form.errors = []; - this.$http.post(this.tokenUrl, this.form).then(function (response) { - _this3.form.name = ''; - _this3.form.scopes = []; - _this3.form.errors = []; - - _this3.tokens.push(response.data.token); - - _this3.showAccessToken(response.data.accessToken); - })["catch"](function (response) { - if (_typeof(response.data) === 'object') { - _this3.form.errors = _.flatten(_.toArray(response.data)); - } else { - console.dir(_this3.form); - _this3.form.errors = ['Something went wrong. Please try again.']; - } - }); - }, - - /** - * Toggle the given scope in the list of assigned scopes. - */ - toggleScope: function toggleScope(scope) { - if (this.scopeIsAssigned(scope)) { - this.form.scopes = _.reject(this.form.scopes, function (s) { - return s == scope; - }); - } else { - this.form.scopes.push(scope); - } - }, - - /** - * Determine if the given scope has been assigned to the token. - */ - scopeIsAssigned: function scopeIsAssigned(scope) { - return _.indexOf(this.form.scopes, scope) >= 0; - }, - - /** - * Show the given access token to the user. - */ - showAccessToken: function showAccessToken(accessToken) { - $('#modal-create-token').modal('hide'); - this.accessToken = accessToken; - $('#modal-access-token').modal('show'); - }, - - /** - * Revoke the given token. - */ - revoke: function revoke(token) { - var _this4 = this; - - this.$http["delete"](this.tokenUrl + '/' + token.id).then(function (response) { - _this4.getTokens(); - }); - } - } -}); - -/***/ }), - -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/assets/js/components/select2.vue?vue&type=script&lang=js&": -/*!*************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/select2.vue?vue&type=script&lang=js& ***! - \*************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -// -// -// -// -// -__webpack_require__(/*! select2 */ "./node_modules/select2/dist/js/select2.js"); - -/* harmony default export */ __webpack_exports__["default"] = ({ - /* - * The component's data. - */ - props: ['options', 'value'], - mounted: function mounted() { - var vm = this; - $(this.$el).select2({ - data: this.options - }).on('change', function () { - vm.$emit('input', this.value); - }).val(this.value).trigger('change'); - }, - watch: { - value: function value(_value) { - $(this.$el).val(_value); - }, - options: function options(_options) { - var vm = this; - $(this.$el).select2('destroy').empty().select2({ - data: _options - }).on('change', function () { - vm.$emit('input', this.value); - }).val(this.value).trigger('change'); - }, - destroyed: function destroyed() { - $(this.$el).off().select2('destroy'); - } - } -}); - -/***/ }), - -/***/ "./node_modules/blueimp-file-upload/js/jquery.fileupload.js": -/*!******************************************************************!*\ - !*** ./node_modules/blueimp-file-upload/js/jquery.fileupload.js ***! - \******************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* - * jQuery File Upload Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, document, location, Blob, FormData */ - -;(function (factory) { - 'use strict'; - if (true) { - // Register as an anonymous AMD module: - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ - __webpack_require__(/*! jquery */ "./node_modules/jquery/dist/jquery.js"), - __webpack_require__(/*! jquery-ui/ui/widget */ "./node_modules/jquery-ui/ui/widget.js") - ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else {} -}(function ($) { - 'use strict'; - - // Detect file input support, based on - // http://viljamis.com/blog/2012/file-upload-support-on-mobile/ - $.support.fileInput = !(new RegExp( - // Handle devices which give false positives for the feature detection: - '(Android (1\\.[0156]|2\\.[01]))' + - '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' + - '|(w(eb)?OSBrowser)|(webOS)' + - '|(Kindle/(1\\.0|2\\.[05]|3\\.0))' - ).test(window.navigator.userAgent) || - // Feature detection for all other devices: - $('').prop('disabled')); - - // The FileReader API is not actually used, but works as feature detection, - // as some Safari versions (5?) support XHR file uploads via the FormData API, - // but not non-multipart XHR file uploads. - // window.XMLHttpRequestUpload is not available on IE10, so we check for - // window.ProgressEvent instead to detect XHR2 file upload capability: - $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader); - $.support.xhrFormDataFileUpload = !!window.FormData; - - // Detect support for Blob slicing (required for chunked uploads): - $.support.blobSlice = window.Blob && (Blob.prototype.slice || - Blob.prototype.webkitSlice || Blob.prototype.mozSlice); - - // Helper function to create drag handlers for dragover/dragenter/dragleave: - function getDragHandler(type) { - var isDragOver = type === 'dragover'; - return function (e) { - e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; - var dataTransfer = e.dataTransfer; - if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 && - this._trigger( - type, - $.Event(type, {delegatedEvent: e}) - ) !== false) { - e.preventDefault(); - if (isDragOver) { - dataTransfer.dropEffect = 'copy'; - } - } - }; - } - - // The fileupload widget listens for change events on file input fields defined - // via fileInput setting and paste or drop events of the given dropZone. - // In addition to the default jQuery Widget methods, the fileupload widget - // exposes the "add" and "send" methods, to add or directly send files using - // the fileupload API. - // By default, files added via file input selection, paste, drag & drop or - // "add" method are uploaded immediately, but it is possible to override - // the "add" callback option to queue file uploads. - $.widget('blueimp.fileupload', { - - options: { - // The drop target element(s), by the default the complete document. - // Set to null to disable drag & drop support: - dropZone: $(document), - // The paste target element(s), by the default undefined. - // Set to a DOM node or jQuery object to enable file pasting: - pasteZone: undefined, - // The file input field(s), that are listened to for change events. - // If undefined, it is set to the file input fields inside - // of the widget element on plugin initialization. - // Set to null to disable the change listener. - fileInput: undefined, - // By default, the file input field is replaced with a clone after - // each input field change event. This is required for iframe transport - // queues and allows change events to be fired for the same file - // selection, but can be disabled by setting the following option to false: - replaceFileInput: true, - // The parameter name for the file form data (the request argument name). - // If undefined or empty, the name property of the file input field is - // used, or "files[]" if the file input name property is also empty, - // can be a string or an array of strings: - paramName: undefined, - // By default, each file of a selection is uploaded using an individual - // request for XHR type uploads. Set to false to upload file - // selections in one request each: - singleFileUploads: true, - // To limit the number of files uploaded with one XHR request, - // set the following option to an integer greater than 0: - limitMultiFileUploads: undefined, - // The following option limits the number of files uploaded with one - // XHR request to keep the request size under or equal to the defined - // limit in bytes: - limitMultiFileUploadSize: undefined, - // Multipart file uploads add a number of bytes to each uploaded file, - // therefore the following option adds an overhead for each file used - // in the limitMultiFileUploadSize configuration: - limitMultiFileUploadSizeOverhead: 512, - // Set the following option to true to issue all file upload requests - // in a sequential order: - sequentialUploads: false, - // To limit the number of concurrent uploads, - // set the following option to an integer greater than 0: - limitConcurrentUploads: undefined, - // Set the following option to true to force iframe transport uploads: - forceIframeTransport: false, - // Set the following option to the location of a redirect url on the - // origin server, for cross-domain iframe transport uploads: - redirect: undefined, - // The parameter name for the redirect url, sent as part of the form - // data and set to 'redirect' if this option is empty: - redirectParamName: undefined, - // Set the following option to the location of a postMessage window, - // to enable postMessage transport uploads: - postMessage: undefined, - // By default, XHR file uploads are sent as multipart/form-data. - // The iframe transport is always using multipart/form-data. - // Set to false to enable non-multipart XHR uploads: - multipart: true, - // To upload large files in smaller chunks, set the following option - // to a preferred maximum chunk size. If set to 0, null or undefined, - // or the browser does not support the required Blob API, files will - // be uploaded as a whole. - maxChunkSize: undefined, - // When a non-multipart upload or a chunked multipart upload has been - // aborted, this option can be used to resume the upload by setting - // it to the size of the already uploaded bytes. This option is most - // useful when modifying the options object inside of the "add" or - // "send" callbacks, as the options are cloned for each file upload. - uploadedBytes: undefined, - // By default, failed (abort or error) file uploads are removed from the - // global progress calculation. Set the following option to false to - // prevent recalculating the global progress data: - recalculateProgress: true, - // Interval in milliseconds to calculate and trigger progress events: - progressInterval: 100, - // Interval in milliseconds to calculate progress bitrate: - bitrateInterval: 500, - // By default, uploads are started automatically when adding files: - autoUpload: true, - // By default, duplicate file names are expected to be handled on - // the server-side. If this is not possible (e.g. when uploading - // files directly to Amazon S3), the following option can be set to - // an empty object or an object mapping existing filenames, e.g.: - // { "image.jpg": true, "image (1).jpg": true } - // If it is set, all files will be uploaded with unique filenames, - // adding increasing number suffixes if necessary, e.g.: - // "image (2).jpg" - uniqueFilenames: undefined, - - // Error and info messages: - messages: { - uploadedBytes: 'Uploaded bytes exceed file size' - }, - - // Translation function, gets the message key to be translated - // and an object with context specific data as arguments: - i18n: function (message, context) { - message = this.messages[message] || message.toString(); - if (context) { - $.each(context, function (key, value) { - message = message.replace('{' + key + '}', value); - }); - } - return message; - }, - - // Additional form data to be sent along with the file uploads can be set - // using this option, which accepts an array of objects with name and - // value properties, a function returning such an array, a FormData - // object (for XHR file uploads), or a simple object. - // The form of the first fileInput is given as parameter to the function: - formData: function (form) { - return form.serializeArray(); - }, - - // The add callback is invoked as soon as files are added to the fileupload - // widget (via file input selection, drag & drop, paste or add API call). - // If the singleFileUploads option is enabled, this callback will be - // called once for each file in the selection for XHR file uploads, else - // once for each file selection. - // - // The upload starts when the submit method is invoked on the data parameter. - // The data object contains a files property holding the added files - // and allows you to override plugin options as well as define ajax settings. - // - // Listeners for this callback can also be bound the following way: - // .bind('fileuploadadd', func); - // - // data.submit() returns a Promise object and allows to attach additional - // handlers using jQuery's Deferred callbacks: - // data.submit().done(func).fail(func).always(func); - add: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - if (data.autoUpload || (data.autoUpload !== false && - $(this).fileupload('option', 'autoUpload'))) { - data.process().done(function () { - data.submit(); - }); - } - }, - - // Other callbacks: - - // Callback for the submit event of each file upload: - // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); - - // Callback for the start of each file upload request: - // send: function (e, data) {}, // .bind('fileuploadsend', func); - - // Callback for successful uploads: - // done: function (e, data) {}, // .bind('fileuploaddone', func); - - // Callback for failed (abort or error) uploads: - // fail: function (e, data) {}, // .bind('fileuploadfail', func); - - // Callback for completed (success, abort or error) requests: - // always: function (e, data) {}, // .bind('fileuploadalways', func); - - // Callback for upload progress events: - // progress: function (e, data) {}, // .bind('fileuploadprogress', func); - - // Callback for global upload progress events: - // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); - - // Callback for uploads start, equivalent to the global ajaxStart event: - // start: function (e) {}, // .bind('fileuploadstart', func); - - // Callback for uploads stop, equivalent to the global ajaxStop event: - // stop: function (e) {}, // .bind('fileuploadstop', func); - - // Callback for change events of the fileInput(s): - // change: function (e, data) {}, // .bind('fileuploadchange', func); - - // Callback for paste events to the pasteZone(s): - // paste: function (e, data) {}, // .bind('fileuploadpaste', func); - - // Callback for drop events of the dropZone(s): - // drop: function (e, data) {}, // .bind('fileuploaddrop', func); - - // Callback for dragover events of the dropZone(s): - // dragover: function (e) {}, // .bind('fileuploaddragover', func); - - // Callback before the start of each chunk upload request (before form data initialization): - // chunkbeforesend: function (e, data) {}, // .bind('fileuploadchunkbeforesend', func); - - // Callback for the start of each chunk upload request: - // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func); - - // Callback for successful chunk uploads: - // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func); - - // Callback for failed (abort or error) chunk uploads: - // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func); - - // Callback for completed (success, abort or error) chunk upload requests: - // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func); - - // The plugin options are used as settings object for the ajax calls. - // The following are jQuery ajax settings required for the file uploads: - processData: false, - contentType: false, - cache: false, - timeout: 0 - }, - - // A list of options that require reinitializing event listeners and/or - // special initialization code: - _specialOptions: [ - 'fileInput', - 'dropZone', - 'pasteZone', - 'multipart', - 'forceIframeTransport' - ], - - _blobSlice: $.support.blobSlice && function () { - var slice = this.slice || this.webkitSlice || this.mozSlice; - return slice.apply(this, arguments); - }, - - _BitrateTimer: function () { - this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); - this.loaded = 0; - this.bitrate = 0; - this.getBitrate = function (now, loaded, interval) { - var timeDiff = now - this.timestamp; - if (!this.bitrate || !interval || timeDiff > interval) { - this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; - this.loaded = loaded; - this.timestamp = now; - } - return this.bitrate; - }; - }, - - _isXHRUpload: function (options) { - return !options.forceIframeTransport && - ((!options.multipart && $.support.xhrFileUpload) || - $.support.xhrFormDataFileUpload); - }, - - _getFormData: function (options) { - var formData; - if ($.type(options.formData) === 'function') { - return options.formData(options.form); - } - if ($.isArray(options.formData)) { - return options.formData; - } - if ($.type(options.formData) === 'object') { - formData = []; - $.each(options.formData, function (name, value) { - formData.push({name: name, value: value}); - }); - return formData; - } - return []; - }, - - _getTotal: function (files) { - var total = 0; - $.each(files, function (index, file) { - total += file.size || 1; - }); - return total; - }, - - _initProgressObject: function (obj) { - var progress = { - loaded: 0, - total: 0, - bitrate: 0 - }; - if (obj._progress) { - $.extend(obj._progress, progress); - } else { - obj._progress = progress; - } - }, - - _initResponseObject: function (obj) { - var prop; - if (obj._response) { - for (prop in obj._response) { - if (obj._response.hasOwnProperty(prop)) { - delete obj._response[prop]; - } - } - } else { - obj._response = {}; - } - }, - - _onProgress: function (e, data) { - if (e.lengthComputable) { - var now = ((Date.now) ? Date.now() : (new Date()).getTime()), - loaded; - if (data._time && data.progressInterval && - (now - data._time < data.progressInterval) && - e.loaded !== e.total) { - return; - } - data._time = now; - loaded = Math.floor( - e.loaded / e.total * (data.chunkSize || data._progress.total) - ) + (data.uploadedBytes || 0); - // Add the difference from the previously loaded state - // to the global loaded counter: - this._progress.loaded += (loaded - data._progress.loaded); - this._progress.bitrate = this._bitrateTimer.getBitrate( - now, - this._progress.loaded, - data.bitrateInterval - ); - data._progress.loaded = data.loaded = loaded; - data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate( - now, - loaded, - data.bitrateInterval - ); - // Trigger a custom progress event with a total data property set - // to the file size(s) of the current upload and a loaded data - // property calculated accordingly: - this._trigger( - 'progress', - $.Event('progress', {delegatedEvent: e}), - data - ); - // Trigger a global progress event for all current file uploads, - // including ajax calls queued for sequential file uploads: - this._trigger( - 'progressall', - $.Event('progressall', {delegatedEvent: e}), - this._progress - ); - } - }, - - _initProgressListener: function (options) { - var that = this, - xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); - // Accesss to the native XHR object is required to add event listeners - // for the upload progress event: - if (xhr.upload) { - $(xhr.upload).bind('progress', function (e) { - var oe = e.originalEvent; - // Make sure the progress event properties get copied over: - e.lengthComputable = oe.lengthComputable; - e.loaded = oe.loaded; - e.total = oe.total; - that._onProgress(e, options); - }); - options.xhr = function () { - return xhr; - }; - } - }, - - _deinitProgressListener: function (options) { - var xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); - if (xhr.upload) { - $(xhr.upload).unbind('progress'); - } - }, - - _isInstanceOf: function (type, obj) { - // Cross-frame instanceof check - return Object.prototype.toString.call(obj) === '[object ' + type + ']'; - }, - - _getUniqueFilename: function (name, map) { - name = String(name); - if (map[name]) { - name = name.replace( - /(?: \(([\d]+)\))?(\.[^.]+)?$/, - function (_, p1, p2) { - var index = p1 ? Number(p1) + 1 : 1; - var ext = p2 || ''; - return ' (' + index + ')' + ext; - } - ); - return this._getUniqueFilename(name, map); - } - map[name] = true; - return name; - }, - - _initXHRData: function (options) { - var that = this, - formData, - file = options.files[0], - // Ignore non-multipart setting if not supported: - multipart = options.multipart || !$.support.xhrFileUpload, - paramName = $.type(options.paramName) === 'array' ? - options.paramName[0] : options.paramName; - options.headers = $.extend({}, options.headers); - if (options.contentRange) { - options.headers['Content-Range'] = options.contentRange; - } - if (!multipart || options.blob || !this._isInstanceOf('File', file)) { - options.headers['Content-Disposition'] = 'attachment; filename="' + - encodeURI(file.uploadName || file.name) + '"'; - } - if (!multipart) { - options.contentType = file.type || 'application/octet-stream'; - options.data = options.blob || file; - } else if ($.support.xhrFormDataFileUpload) { - if (options.postMessage) { - // window.postMessage does not allow sending FormData - // objects, so we just add the File/Blob objects to - // the formData array and let the postMessage window - // create the FormData object out of this array: - formData = this._getFormData(options); - if (options.blob) { - formData.push({ - name: paramName, - value: options.blob - }); - } else { - $.each(options.files, function (index, file) { - formData.push({ - name: ($.type(options.paramName) === 'array' && - options.paramName[index]) || paramName, - value: file - }); - }); - } - } else { - if (that._isInstanceOf('FormData', options.formData)) { - formData = options.formData; - } else { - formData = new FormData(); - $.each(this._getFormData(options), function (index, field) { - formData.append(field.name, field.value); - }); - } - if (options.blob) { - formData.append( - paramName, - options.blob, - file.uploadName || file.name - ); - } else { - $.each(options.files, function (index, file) { - // This check allows the tests to run with - // dummy objects: - if (that._isInstanceOf('File', file) || - that._isInstanceOf('Blob', file)) { - var fileName = file.uploadName || file.name; - if (options.uniqueFilenames) { - fileName = that._getUniqueFilename( - fileName, - options.uniqueFilenames - ); - } - formData.append( - ($.type(options.paramName) === 'array' && - options.paramName[index]) || paramName, - file, - fileName - ); - } - }); - } - } - options.data = formData; - } - // Blob reference is not needed anymore, free memory: - options.blob = null; - }, - - _initIframeSettings: function (options) { - var targetHost = $('').prop('href', options.url).prop('host'); - // Setting the dataType to iframe enables the iframe transport: - options.dataType = 'iframe ' + (options.dataType || ''); - // The iframe transport accepts a serialized array as form data: - options.formData = this._getFormData(options); - // Add redirect url to form data on cross-domain uploads: - if (options.redirect && targetHost && targetHost !== location.host) { - options.formData.push({ - name: options.redirectParamName || 'redirect', - value: options.redirect - }); - } - }, - - _initDataSettings: function (options) { - if (this._isXHRUpload(options)) { - if (!this._chunkedUpload(options, true)) { - if (!options.data) { - this._initXHRData(options); - } - this._initProgressListener(options); - } - if (options.postMessage) { - // Setting the dataType to postmessage enables the - // postMessage transport: - options.dataType = 'postmessage ' + (options.dataType || ''); - } - } else { - this._initIframeSettings(options); - } - }, - - _getParamName: function (options) { - var fileInput = $(options.fileInput), - paramName = options.paramName; - if (!paramName) { - paramName = []; - fileInput.each(function () { - var input = $(this), - name = input.prop('name') || 'files[]', - i = (input.prop('files') || [1]).length; - while (i) { - paramName.push(name); - i -= 1; - } - }); - if (!paramName.length) { - paramName = [fileInput.prop('name') || 'files[]']; - } - } else if (!$.isArray(paramName)) { - paramName = [paramName]; - } - return paramName; - }, - - _initFormSettings: function (options) { - // Retrieve missing options from the input field and the - // associated form, if available: - if (!options.form || !options.form.length) { - options.form = $(options.fileInput.prop('form')); - // If the given file input doesn't have an associated form, - // use the default widget file input's form: - if (!options.form.length) { - options.form = $(this.options.fileInput.prop('form')); - } - } - options.paramName = this._getParamName(options); - if (!options.url) { - options.url = options.form.prop('action') || location.href; - } - // The HTTP request method must be "POST" or "PUT": - options.type = (options.type || - ($.type(options.form.prop('method')) === 'string' && - options.form.prop('method')) || '' - ).toUpperCase(); - if (options.type !== 'POST' && options.type !== 'PUT' && - options.type !== 'PATCH') { - options.type = 'POST'; - } - if (!options.formAcceptCharset) { - options.formAcceptCharset = options.form.attr('accept-charset'); - } - }, - - _getAJAXSettings: function (data) { - var options = $.extend({}, this.options, data); - this._initFormSettings(options); - this._initDataSettings(options); - return options; - }, - - // jQuery 1.6 doesn't provide .state(), - // while jQuery 1.8+ removed .isRejected() and .isResolved(): - _getDeferredState: function (deferred) { - if (deferred.state) { - return deferred.state(); - } - if (deferred.isResolved()) { - return 'resolved'; - } - if (deferred.isRejected()) { - return 'rejected'; - } - return 'pending'; - }, - - // Maps jqXHR callbacks to the equivalent - // methods of the given Promise object: - _enhancePromise: function (promise) { - promise.success = promise.done; - promise.error = promise.fail; - promise.complete = promise.always; - return promise; - }, - - // Creates and returns a Promise object enhanced with - // the jqXHR methods abort, success, error and complete: - _getXHRPromise: function (resolveOrReject, context, args) { - var dfd = $.Deferred(), - promise = dfd.promise(); - context = context || this.options.context || promise; - if (resolveOrReject === true) { - dfd.resolveWith(context, args); - } else if (resolveOrReject === false) { - dfd.rejectWith(context, args); - } - promise.abort = dfd.promise; - return this._enhancePromise(promise); - }, - - // Adds convenience methods to the data callback argument: - _addConvenienceMethods: function (e, data) { - var that = this, - getPromise = function (args) { - return $.Deferred().resolveWith(that, args).promise(); - }; - data.process = function (resolveFunc, rejectFunc) { - if (resolveFunc || rejectFunc) { - data._processQueue = this._processQueue = - (this._processQueue || getPromise([this])).then( - function () { - if (data.errorThrown) { - return $.Deferred() - .rejectWith(that, [data]).promise(); - } - return getPromise(arguments); - } - ).then(resolveFunc, rejectFunc); - } - return this._processQueue || getPromise([this]); - }; - data.submit = function () { - if (this.state() !== 'pending') { - data.jqXHR = this.jqXHR = - (that._trigger( - 'submit', - $.Event('submit', {delegatedEvent: e}), - this - ) !== false) && that._onSend(e, this); - } - return this.jqXHR || that._getXHRPromise(); - }; - data.abort = function () { - if (this.jqXHR) { - return this.jqXHR.abort(); - } - this.errorThrown = 'abort'; - that._trigger('fail', null, this); - return that._getXHRPromise(false); - }; - data.state = function () { - if (this.jqXHR) { - return that._getDeferredState(this.jqXHR); - } - if (this._processQueue) { - return that._getDeferredState(this._processQueue); - } - }; - data.processing = function () { - return !this.jqXHR && this._processQueue && that - ._getDeferredState(this._processQueue) === 'pending'; - }; - data.progress = function () { - return this._progress; - }; - data.response = function () { - return this._response; - }; - }, - - // Parses the Range header from the server response - // and returns the uploaded bytes: - _getUploadedBytes: function (jqXHR) { - var range = jqXHR.getResponseHeader('Range'), - parts = range && range.split('-'), - upperBytesPos = parts && parts.length > 1 && - parseInt(parts[1], 10); - return upperBytesPos && upperBytesPos + 1; - }, - - // Uploads a file in multiple, sequential requests - // by splitting the file up in multiple blob chunks. - // If the second parameter is true, only tests if the file - // should be uploaded in chunks, but does not invoke any - // upload requests: - _chunkedUpload: function (options, testOnly) { - options.uploadedBytes = options.uploadedBytes || 0; - var that = this, - file = options.files[0], - fs = file.size, - ub = options.uploadedBytes, - mcs = options.maxChunkSize || fs, - slice = this._blobSlice, - dfd = $.Deferred(), - promise = dfd.promise(), - jqXHR, - upload; - if (!(this._isXHRUpload(options) && slice && (ub || ($.type(mcs) === 'function' ? mcs(options) : mcs) < fs)) || - options.data) { - return false; - } - if (testOnly) { - return true; - } - if (ub >= fs) { - file.error = options.i18n('uploadedBytes'); - return this._getXHRPromise( - false, - options.context, - [null, 'error', file.error] - ); - } - // The chunk upload method: - upload = function () { - // Clone the options object for each chunk upload: - var o = $.extend({}, options), - currentLoaded = o._progress.loaded; - o.blob = slice.call( - file, - ub, - ub + ($.type(mcs) === 'function' ? mcs(o) : mcs), - file.type - ); - // Store the current chunk size, as the blob itself - // will be dereferenced after data processing: - o.chunkSize = o.blob.size; - // Expose the chunk bytes position range: - o.contentRange = 'bytes ' + ub + '-' + - (ub + o.chunkSize - 1) + '/' + fs; - // Trigger chunkbeforesend to allow form data to be updated for this chunk - that._trigger('chunkbeforesend', null, o); - // Process the upload data (the blob and potential form data): - that._initXHRData(o); - // Add progress listeners for this chunk upload: - that._initProgressListener(o); - jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) || - that._getXHRPromise(false, o.context)) - .done(function (result, textStatus, jqXHR) { - ub = that._getUploadedBytes(jqXHR) || - (ub + o.chunkSize); - // Create a progress event if no final progress event - // with loaded equaling total has been triggered - // for this chunk: - if (currentLoaded + o.chunkSize - o._progress.loaded) { - that._onProgress($.Event('progress', { - lengthComputable: true, - loaded: ub - o.uploadedBytes, - total: ub - o.uploadedBytes - }), o); - } - options.uploadedBytes = o.uploadedBytes = ub; - o.result = result; - o.textStatus = textStatus; - o.jqXHR = jqXHR; - that._trigger('chunkdone', null, o); - that._trigger('chunkalways', null, o); - if (ub < fs) { - // File upload not yet complete, - // continue with the next chunk: - upload(); - } else { - dfd.resolveWith( - o.context, - [result, textStatus, jqXHR] - ); - } - }) - .fail(function (jqXHR, textStatus, errorThrown) { - o.jqXHR = jqXHR; - o.textStatus = textStatus; - o.errorThrown = errorThrown; - that._trigger('chunkfail', null, o); - that._trigger('chunkalways', null, o); - dfd.rejectWith( - o.context, - [jqXHR, textStatus, errorThrown] - ); - }) - .always(function () { - that._deinitProgressListener(o); - }); - }; - this._enhancePromise(promise); - promise.abort = function () { - return jqXHR.abort(); - }; - upload(); - return promise; - }, - - _beforeSend: function (e, data) { - if (this._active === 0) { - // the start callback is triggered when an upload starts - // and no other uploads are currently running, - // equivalent to the global ajaxStart event: - this._trigger('start'); - // Set timer for global bitrate progress calculation: - this._bitrateTimer = new this._BitrateTimer(); - // Reset the global progress values: - this._progress.loaded = this._progress.total = 0; - this._progress.bitrate = 0; - } - // Make sure the container objects for the .response() and - // .progress() methods on the data object are available - // and reset to their initial state: - this._initResponseObject(data); - this._initProgressObject(data); - data._progress.loaded = data.loaded = data.uploadedBytes || 0; - data._progress.total = data.total = this._getTotal(data.files) || 1; - data._progress.bitrate = data.bitrate = 0; - this._active += 1; - // Initialize the global progress values: - this._progress.loaded += data.loaded; - this._progress.total += data.total; - }, - - _onDone: function (result, textStatus, jqXHR, options) { - var total = options._progress.total, - response = options._response; - if (options._progress.loaded < total) { - // Create a progress event if no final progress event - // with loaded equaling total has been triggered: - this._onProgress($.Event('progress', { - lengthComputable: true, - loaded: total, - total: total - }), options); - } - response.result = options.result = result; - response.textStatus = options.textStatus = textStatus; - response.jqXHR = options.jqXHR = jqXHR; - this._trigger('done', null, options); - }, - - _onFail: function (jqXHR, textStatus, errorThrown, options) { - var response = options._response; - if (options.recalculateProgress) { - // Remove the failed (error or abort) file upload from - // the global progress calculation: - this._progress.loaded -= options._progress.loaded; - this._progress.total -= options._progress.total; - } - response.jqXHR = options.jqXHR = jqXHR; - response.textStatus = options.textStatus = textStatus; - response.errorThrown = options.errorThrown = errorThrown; - this._trigger('fail', null, options); - }, - - _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { - // jqXHRorResult, textStatus and jqXHRorError are added to the - // options object via done and fail callbacks - this._trigger('always', null, options); - }, - - _onSend: function (e, data) { - if (!data.submit) { - this._addConvenienceMethods(e, data); - } - var that = this, - jqXHR, - aborted, - slot, - pipe, - options = that._getAJAXSettings(data), - send = function () { - that._sending += 1; - // Set timer for bitrate progress calculation: - options._bitrateTimer = new that._BitrateTimer(); - jqXHR = jqXHR || ( - ((aborted || that._trigger( - 'send', - $.Event('send', {delegatedEvent: e}), - options - ) === false) && - that._getXHRPromise(false, options.context, aborted)) || - that._chunkedUpload(options) || $.ajax(options) - ).done(function (result, textStatus, jqXHR) { - that._onDone(result, textStatus, jqXHR, options); - }).fail(function (jqXHR, textStatus, errorThrown) { - that._onFail(jqXHR, textStatus, errorThrown, options); - }).always(function (jqXHRorResult, textStatus, jqXHRorError) { - that._deinitProgressListener(options); - that._onAlways( - jqXHRorResult, - textStatus, - jqXHRorError, - options - ); - that._sending -= 1; - that._active -= 1; - if (options.limitConcurrentUploads && - options.limitConcurrentUploads > that._sending) { - // Start the next queued upload, - // that has not been aborted: - var nextSlot = that._slots.shift(); - while (nextSlot) { - if (that._getDeferredState(nextSlot) === 'pending') { - nextSlot.resolve(); - break; - } - nextSlot = that._slots.shift(); - } - } - if (that._active === 0) { - // The stop callback is triggered when all uploads have - // been completed, equivalent to the global ajaxStop event: - that._trigger('stop'); - } - }); - return jqXHR; - }; - this._beforeSend(e, options); - if (this.options.sequentialUploads || - (this.options.limitConcurrentUploads && - this.options.limitConcurrentUploads <= this._sending)) { - if (this.options.limitConcurrentUploads > 1) { - slot = $.Deferred(); - this._slots.push(slot); - pipe = slot.then(send); - } else { - this._sequence = this._sequence.then(send, send); - pipe = this._sequence; - } - // Return the piped Promise object, enhanced with an abort method, - // which is delegated to the jqXHR object of the current upload, - // and jqXHR callbacks mapped to the equivalent Promise methods: - pipe.abort = function () { - aborted = [undefined, 'abort', 'abort']; - if (!jqXHR) { - if (slot) { - slot.rejectWith(options.context, aborted); - } - return send(); - } - return jqXHR.abort(); - }; - return this._enhancePromise(pipe); - } - return send(); - }, - - _onAdd: function (e, data) { - var that = this, - result = true, - options = $.extend({}, this.options, data), - files = data.files, - filesLength = files.length, - limit = options.limitMultiFileUploads, - limitSize = options.limitMultiFileUploadSize, - overhead = options.limitMultiFileUploadSizeOverhead, - batchSize = 0, - paramName = this._getParamName(options), - paramNameSet, - paramNameSlice, - fileSet, - i, - j = 0; - if (!filesLength) { - return false; - } - if (limitSize && files[0].size === undefined) { - limitSize = undefined; - } - if (!(options.singleFileUploads || limit || limitSize) || - !this._isXHRUpload(options)) { - fileSet = [files]; - paramNameSet = [paramName]; - } else if (!(options.singleFileUploads || limitSize) && limit) { - fileSet = []; - paramNameSet = []; - for (i = 0; i < filesLength; i += limit) { - fileSet.push(files.slice(i, i + limit)); - paramNameSlice = paramName.slice(i, i + limit); - if (!paramNameSlice.length) { - paramNameSlice = paramName; - } - paramNameSet.push(paramNameSlice); - } - } else if (!options.singleFileUploads && limitSize) { - fileSet = []; - paramNameSet = []; - for (i = 0; i < filesLength; i = i + 1) { - batchSize += files[i].size + overhead; - if (i + 1 === filesLength || - ((batchSize + files[i + 1].size + overhead) > limitSize) || - (limit && i + 1 - j >= limit)) { - fileSet.push(files.slice(j, i + 1)); - paramNameSlice = paramName.slice(j, i + 1); - if (!paramNameSlice.length) { - paramNameSlice = paramName; - } - paramNameSet.push(paramNameSlice); - j = i + 1; - batchSize = 0; - } - } - } else { - paramNameSet = paramName; - } - data.originalFiles = files; - $.each(fileSet || files, function (index, element) { - var newData = $.extend({}, data); - newData.files = fileSet ? element : [element]; - newData.paramName = paramNameSet[index]; - that._initResponseObject(newData); - that._initProgressObject(newData); - that._addConvenienceMethods(e, newData); - result = that._trigger( - 'add', - $.Event('add', {delegatedEvent: e}), - newData - ); - return result; - }); - return result; - }, - - _replaceFileInput: function (data) { - var input = data.fileInput, - inputClone = input.clone(true), - restoreFocus = input.is(document.activeElement); - // Add a reference for the new cloned file input to the data argument: - data.fileInputClone = inputClone; - $('
').append(inputClone)[0].reset(); - // Detaching allows to insert the fileInput on another form - // without loosing the file input value: - input.after(inputClone).detach(); - // If the fileInput had focus before it was detached, - // restore focus to the inputClone. - if (restoreFocus) { - inputClone.focus(); - } - // Avoid memory leaks with the detached file input: - $.cleanData(input.unbind('remove')); - // Replace the original file input element in the fileInput - // elements set with the clone, which has been copied including - // event handlers: - this.options.fileInput = this.options.fileInput.map(function (i, el) { - if (el === input[0]) { - return inputClone[0]; - } - return el; - }); - // If the widget has been initialized on the file input itself, - // override this.element with the file input clone: - if (input[0] === this.element[0]) { - this.element = inputClone; - } - }, - - _handleFileTreeEntry: function (entry, path) { - var that = this, - dfd = $.Deferred(), - entries = [], - dirReader, - errorHandler = function (e) { - if (e && !e.entry) { - e.entry = entry; - } - // Since $.when returns immediately if one - // Deferred is rejected, we use resolve instead. - // This allows valid files and invalid items - // to be returned together in one set: - dfd.resolve([e]); - }, - successHandler = function (entries) { - that._handleFileTreeEntries( - entries, - path + entry.name + '/' - ).done(function (files) { - dfd.resolve(files); - }).fail(errorHandler); - }, - readEntries = function () { - dirReader.readEntries(function (results) { - if (!results.length) { - successHandler(entries); - } else { - entries = entries.concat(results); - readEntries(); - } - }, errorHandler); - }; - path = path || ''; - if (entry.isFile) { - if (entry._file) { - // Workaround for Chrome bug #149735 - entry._file.relativePath = path; - dfd.resolve(entry._file); - } else { - entry.file(function (file) { - file.relativePath = path; - dfd.resolve(file); - }, errorHandler); - } - } else if (entry.isDirectory) { - dirReader = entry.createReader(); - readEntries(); - } else { - // Return an empty list for file system items - // other than files or directories: - dfd.resolve([]); - } - return dfd.promise(); - }, - - _handleFileTreeEntries: function (entries, path) { - var that = this; - return $.when.apply( - $, - $.map(entries, function (entry) { - return that._handleFileTreeEntry(entry, path); - }) - ).then(function () { - return Array.prototype.concat.apply( - [], - arguments - ); - }); - }, - - _getDroppedFiles: function (dataTransfer) { - dataTransfer = dataTransfer || {}; - var items = dataTransfer.items; - if (items && items.length && (items[0].webkitGetAsEntry || - items[0].getAsEntry)) { - return this._handleFileTreeEntries( - $.map(items, function (item) { - var entry; - if (item.webkitGetAsEntry) { - entry = item.webkitGetAsEntry(); - if (entry) { - // Workaround for Chrome bug #149735: - entry._file = item.getAsFile(); - } - return entry; - } - return item.getAsEntry(); - }) - ); - } - return $.Deferred().resolve( - $.makeArray(dataTransfer.files) - ).promise(); - }, - - _getSingleFileInputFiles: function (fileInput) { - fileInput = $(fileInput); - var entries = fileInput.prop('webkitEntries') || - fileInput.prop('entries'), - files, - value; - if (entries && entries.length) { - return this._handleFileTreeEntries(entries); - } - files = $.makeArray(fileInput.prop('files')); - if (!files.length) { - value = fileInput.prop('value'); - if (!value) { - return $.Deferred().resolve([]).promise(); - } - // If the files property is not available, the browser does not - // support the File API and we add a pseudo File object with - // the input value as name with path information removed: - files = [{name: value.replace(/^.*\\/, '')}]; - } else if (files[0].name === undefined && files[0].fileName) { - // File normalization for Safari 4 and Firefox 3: - $.each(files, function (index, file) { - file.name = file.fileName; - file.size = file.fileSize; - }); - } - return $.Deferred().resolve(files).promise(); - }, - - _getFileInputFiles: function (fileInput) { - if (!(fileInput instanceof $) || fileInput.length === 1) { - return this._getSingleFileInputFiles(fileInput); - } - return $.when.apply( - $, - $.map(fileInput, this._getSingleFileInputFiles) - ).then(function () { - return Array.prototype.concat.apply( - [], - arguments - ); - }); - }, - - _onChange: function (e) { - var that = this, - data = { - fileInput: $(e.target), - form: $(e.target.form) - }; - this._getFileInputFiles(data.fileInput).always(function (files) { - data.files = files; - if (that.options.replaceFileInput) { - that._replaceFileInput(data); - } - if (that._trigger( - 'change', - $.Event('change', {delegatedEvent: e}), - data - ) !== false) { - that._onAdd(e, data); - } - }); - }, - - _onPaste: function (e) { - var items = e.originalEvent && e.originalEvent.clipboardData && - e.originalEvent.clipboardData.items, - data = {files: []}; - if (items && items.length) { - $.each(items, function (index, item) { - var file = item.getAsFile && item.getAsFile(); - if (file) { - data.files.push(file); - } - }); - if (this._trigger( - 'paste', - $.Event('paste', {delegatedEvent: e}), - data - ) !== false) { - this._onAdd(e, data); - } - } - }, - - _onDrop: function (e) { - e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; - var that = this, - dataTransfer = e.dataTransfer, - data = {}; - if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { - e.preventDefault(); - this._getDroppedFiles(dataTransfer).always(function (files) { - data.files = files; - if (that._trigger( - 'drop', - $.Event('drop', {delegatedEvent: e}), - data - ) !== false) { - that._onAdd(e, data); - } - }); - } - }, - - _onDragOver: getDragHandler('dragover'), - - _onDragEnter: getDragHandler('dragenter'), - - _onDragLeave: getDragHandler('dragleave'), - - _initEventHandlers: function () { - if (this._isXHRUpload(this.options)) { - this._on(this.options.dropZone, { - dragover: this._onDragOver, - drop: this._onDrop, - // event.preventDefault() on dragenter is required for IE10+: - dragenter: this._onDragEnter, - // dragleave is not required, but added for completeness: - dragleave: this._onDragLeave - }); - this._on(this.options.pasteZone, { - paste: this._onPaste - }); - } - if ($.support.fileInput) { - this._on(this.options.fileInput, { - change: this._onChange - }); - } - }, - - _destroyEventHandlers: function () { - this._off(this.options.dropZone, 'dragenter dragleave dragover drop'); - this._off(this.options.pasteZone, 'paste'); - this._off(this.options.fileInput, 'change'); - }, - - _destroy: function () { - this._destroyEventHandlers(); - }, - - _setOption: function (key, value) { - var reinit = $.inArray(key, this._specialOptions) !== -1; - if (reinit) { - this._destroyEventHandlers(); - } - this._super(key, value); - if (reinit) { - this._initSpecialOptions(); - this._initEventHandlers(); - } - }, - - _initSpecialOptions: function () { - var options = this.options; - if (options.fileInput === undefined) { - options.fileInput = this.element.is('input[type="file"]') ? - this.element : this.element.find('input[type="file"]'); - } else if (!(options.fileInput instanceof $)) { - options.fileInput = $(options.fileInput); - } - if (!(options.dropZone instanceof $)) { - options.dropZone = $(options.dropZone); - } - if (!(options.pasteZone instanceof $)) { - options.pasteZone = $(options.pasteZone); - } - }, - - _getRegExp: function (str) { - var parts = str.split('/'), - modifiers = parts.pop(); - parts.shift(); - return new RegExp(parts.join('/'), modifiers); - }, - - _isRegExpOption: function (key, value) { - return key !== 'url' && $.type(value) === 'string' && - /^\/.*\/[igm]{0,3}$/.test(value); - }, - - _initDataAttributes: function () { - var that = this, - options = this.options, - data = this.element.data(); - // Initialize options set via HTML5 data-attributes: - $.each( - this.element[0].attributes, - function (index, attr) { - var key = attr.name.toLowerCase(), - value; - if (/^data-/.test(key)) { - // Convert hyphen-ated key to camelCase: - key = key.slice(5).replace(/-[a-z]/g, function (str) { - return str.charAt(1).toUpperCase(); - }); - value = data[key]; - if (that._isRegExpOption(key, value)) { - value = that._getRegExp(value); - } - options[key] = value; - } - } - ); - }, - - _create: function () { - this._initDataAttributes(); - this._initSpecialOptions(); - this._slots = []; - this._sequence = this._getXHRPromise(true); - this._sending = this._active = 0; - this._initProgressObject(this); - this._initEventHandlers(); - }, - - // This method is exposed to the widget API and allows to query - // the number of active uploads: - active: function () { - return this._active; - }, - - // This method is exposed to the widget API and allows to query - // the widget upload progress. - // It returns an object with loaded, total and bitrate properties - // for the running uploads: - progress: function () { - return this._progress; - }, - - // This method is exposed to the widget API and allows adding files - // using the fileupload API. The data parameter accepts an object which - // must have a files property and can contain additional options: - // .fileupload('add', {files: filesList}); - add: function (data) { - var that = this; - if (!data || this.options.disabled) { - return; - } - if (data.fileInput && !data.files) { - this._getFileInputFiles(data.fileInput).always(function (files) { - data.files = files; - that._onAdd(null, data); - }); - } else { - data.files = $.makeArray(data.files); - this._onAdd(null, data); - } - }, - - // This method is exposed to the widget API and allows sending files - // using the fileupload API. The data parameter accepts an object which - // must have a files or fileInput property and can contain additional options: - // .fileupload('send', {files: filesList}); - // The method returns a Promise object for the file upload call. - send: function (data) { - if (data && !this.options.disabled) { - if (data.fileInput && !data.files) { - var that = this, - dfd = $.Deferred(), - promise = dfd.promise(), - jqXHR, - aborted; - promise.abort = function () { - aborted = true; - if (jqXHR) { - return jqXHR.abort(); - } - dfd.reject(null, 'abort', 'abort'); - return promise; - }; - this._getFileInputFiles(data.fileInput).always( - function (files) { - if (aborted) { - return; - } - if (!files.length) { - dfd.reject(); - return; - } - data.files = files; - jqXHR = that._onSend(null, data); - jqXHR.then( - function (result, textStatus, jqXHR) { - dfd.resolve(result, textStatus, jqXHR); - }, - function (jqXHR, textStatus, errorThrown) { - dfd.reject(jqXHR, textStatus, errorThrown); - } - ); - } - ); - return this._enhancePromise(promise); - } - data.files = $.makeArray(data.files); - if (data.files.length) { - return this._onSend(null, data); - } - } - return this._getXHRPromise(false, data && data.context); - } - - }); - -})); - - -/***/ }), - -/***/ "./node_modules/bootstrap-less/js/bootstrap.js": -/*!*****************************************************!*\ - !*** ./node_modules/bootstrap-less/js/bootstrap.js ***! - \*****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -/* */ -"format global"; -"deps jquery"; -"exports $"; -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -if (typeof jQuery === 'undefined') { - throw new Error('Bootstrap\'s JavaScript requires jQuery') -} - -+function ($) { - 'use strict'; - var version = $.fn.jquery.split(' ')[0].split('.') - if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) { - throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher') - } -}(jQuery); - -/* ======================================================================== - * Bootstrap: transition.js v3.3.4 - * http://getbootstrap.com/javascript/#transitions - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - WebkitTransition : 'webkitTransitionEnd', - MozTransition : 'transitionend', - OTransition : 'oTransitionEnd otransitionend', - transition : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - - return false // explicit for ie8 ( ._.) - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false - var $el = this - $(this).one('bsTransitionEnd', function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - - if (!$.support.transition) return - - $.event.special.bsTransitionEnd = { - bindType: $.support.transition.end, - delegateType: $.support.transition.end, - handle: function (e) { - if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) - } - } - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: alert.js v3.3.4 - * http://getbootstrap.com/javascript/#alerts - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // ALERT CLASS DEFINITION - // ====================== - - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.VERSION = '3.3.4' - - Alert.TRANSITION_DURATION = 150 - - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = $(selector) - - if (e) e.preventDefault() - - if (!$parent.length) { - $parent = $this.closest('.alert') - } - - $parent.trigger(e = $.Event('close.bs.alert')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - // detach from parent, fire event then clean up data - $parent.detach().trigger('closed.bs.alert').remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent - .one('bsTransitionEnd', removeElement) - .emulateTransitionEnd(Alert.TRANSITION_DURATION) : - removeElement() - } - - - // ALERT PLUGIN DEFINITION - // ======================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') - - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - var old = $.fn.alert - - $.fn.alert = Plugin - $.fn.alert.Constructor = Alert - - - // ALERT NO CONFLICT - // ================= - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - // ALERT DATA-API - // ============== - - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: button.js v3.3.4 - * http://getbootstrap.com/javascript/#buttons - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // BUTTON PUBLIC CLASS DEFINITION - // ============================== - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - this.isLoading = false - } - - Button.VERSION = '3.3.4' - - Button.DEFAULTS = { - loadingText: 'loading...' - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() - - state = state + 'Text' - - if (data.resetText == null) $el.data('resetText', $el[val]()) - - // push to event loop to allow forms to submit - setTimeout($.proxy(function () { - $el[val](data[state] == null ? this.options[state] : data[state]) - - if (state == 'loadingText') { - this.isLoading = true - $el.addClass(d).attr(d, d) - } else if (this.isLoading) { - this.isLoading = false - $el.removeClass(d).removeAttr(d) - } - }, this), 0) - } - - Button.prototype.toggle = function () { - var changed = true - var $parent = this.$element.closest('[data-toggle="buttons"]') - - if ($parent.length) { - var $input = this.$element.find('input') - if ($input.prop('type') == 'radio') { - if ($input.prop('checked') && this.$element.hasClass('active')) changed = false - else $parent.find('.active').removeClass('active') - } - if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') - } else { - this.$element.attr('aria-pressed', !this.$element.hasClass('active')) - } - - if (changed) this.$element.toggleClass('active') - } - - - // BUTTON PLUGIN DEFINITION - // ======================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - var old = $.fn.button - - $.fn.button = Plugin - $.fn.button.Constructor = Button - - - // BUTTON NO CONFLICT - // ================== - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - // BUTTON DATA-API - // =============== - - $(document) - .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - Plugin.call($btn, 'toggle') - e.preventDefault() - }) - .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { - $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: carousel.js v3.3.4 - * http://getbootstrap.com/javascript/#carousel - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CAROUSEL CLASS DEFINITION - // ========================= - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = null - this.sliding = null - this.interval = null - this.$active = null - this.$items = null - - this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) - - this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element - .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) - .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) - } - - Carousel.VERSION = '3.3.4' - - Carousel.TRANSITION_DURATION = 600 - - Carousel.DEFAULTS = { - interval: 5000, - pause: 'hover', - wrap: true, - keyboard: true - } - - Carousel.prototype.keydown = function (e) { - if (/input|textarea/i.test(e.target.tagName)) return - switch (e.which) { - case 37: this.prev(); break - case 39: this.next(); break - default: return - } - - e.preventDefault() - } - - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) - - this.interval && clearInterval(this.interval) - - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - - return this - } - - Carousel.prototype.getItemIndex = function (item) { - this.$items = item.parent().children('.item') - return this.$items.index(item || this.$active) - } - - Carousel.prototype.getItemForDirection = function (direction, active) { - var activeIndex = this.getItemIndex(active) - var willWrap = (direction == 'prev' && activeIndex === 0) - || (direction == 'next' && activeIndex == (this.$items.length - 1)) - if (willWrap && !this.options.wrap) return active - var delta = direction == 'prev' ? -1 : 1 - var itemIndex = (activeIndex + delta) % this.$items.length - return this.$items.eq(itemIndex) - } - - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" - if (activeIndex == pos) return this.pause().cycle() - - return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) - } - - Carousel.prototype.pause = function (e) { - e || (this.paused = true) - - if (this.$element.find('.next, .prev').length && $.support.transition) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - - this.interval = clearInterval(this.interval) - - return this - } - - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } - - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } - - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || this.getItemForDirection(type, $active) - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var that = this - - if ($next.hasClass('active')) return (this.sliding = false) - - var relatedTarget = $next[0] - var slideEvent = $.Event('slide.bs.carousel', { - relatedTarget: relatedTarget, - direction: direction - }) - this.$element.trigger(slideEvent) - if (slideEvent.isDefaultPrevented()) return - - this.sliding = true - - isCycling && this.pause() - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) - $nextIndicator && $nextIndicator.addClass('active') - } - - var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" - if ($.support.transition && this.$element.hasClass('slide')) { - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one('bsTransitionEnd', function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { - that.$element.trigger(slidEvent) - }, 0) - }) - .emulateTransitionEnd(Carousel.TRANSITION_DURATION) - } else { - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger(slidEvent) - } - - isCycling && this.cycle() - - return this - } - - - // CAROUSEL PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - var old = $.fn.carousel - - $.fn.carousel = Plugin - $.fn.carousel.Constructor = Carousel - - - // CAROUSEL NO CONFLICT - // ==================== - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - - // CAROUSEL DATA-API - // ================= - - var clickHandler = function (e) { - var href - var $this = $(this) - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 - if (!$target.hasClass('carousel')) return - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false - - Plugin.call($target, options) - - if (slideIndex) { - $target.data('bs.carousel').to(slideIndex) - } - - e.preventDefault() - } - - $(document) - .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) - .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) - - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - Plugin.call($carousel, $carousel.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: collapse.js v3.3.4 - * http://getbootstrap.com/javascript/#collapse - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + - '[data-toggle="collapse"][data-target="#' + element.id + '"]') - this.transitioning = null - - if (this.options.parent) { - this.$parent = this.getParent() - } else { - this.addAriaAndCollapsedClass(this.$element, this.$trigger) - } - - if (this.options.toggle) this.toggle() - } - - Collapse.VERSION = '3.3.4' - - Collapse.TRANSITION_DURATION = 350 - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return - - var activesData - var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') - - if (actives && actives.length) { - activesData = actives.data('bs.collapse') - if (activesData && activesData.transitioning) return - } - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - if (actives && actives.length) { - Plugin.call(actives, 'hide') - activesData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing')[dimension](0) - .attr('aria-expanded', true) - - this.$trigger - .removeClass('collapsed') - .attr('aria-expanded', true) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('collapse in')[dimension]('') - this.transitioning = 0 - this.$element - .trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element[dimension](this.$element[dimension]())[0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse in') - .attr('aria-expanded', false) - - this.$trigger - .addClass('collapsed') - .attr('aria-expanded', false) - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .removeClass('collapsing') - .addClass('collapse') - .trigger('hidden.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - Collapse.prototype.getParent = function () { - return $(this.options.parent) - .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') - .each($.proxy(function (i, element) { - var $element = $(element) - this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) - }, this)) - .end() - } - - Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { - var isOpen = $element.hasClass('in') - - $element.attr('aria-expanded', isOpen) - $trigger - .toggleClass('collapsed', !isOpen) - .attr('aria-expanded', isOpen) - } - - function getTargetFromTrigger($trigger) { - var href - var target = $trigger.attr('data-target') - || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 - - return $(target) - } - - - // COLLAPSE PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.collapse - - $.fn.collapse = Plugin - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { - var $this = $(this) - - if (!$this.attr('data-target')) e.preventDefault() - - var $target = getTargetFromTrigger($this) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - - Plugin.call($target, option) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: dropdown.js v3.3.4 - * http://getbootstrap.com/javascript/#dropdowns - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // DROPDOWN CLASS DEFINITION - // ========================= - - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle="dropdown"]' - var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this.toggle) - } - - Dropdown.VERSION = '3.3.4' - - Dropdown.prototype.toggle = function (e) { - var $this = $(this) - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we use a backdrop because click events don't delegate - $('