diff --git a/view/assets/css/main.css b/view/assets/css/main.css index 60882ea..503a637 100644 --- a/view/assets/css/main.css +++ b/view/assets/css/main.css @@ -254,7 +254,7 @@ body { } /* Configuration Panel */ -#configuration-panel { +#configuration-menu { background-color: #556575; border-style: solid; border-color: #9cbfe3; @@ -263,7 +263,7 @@ body { padding: 10px 10px 5px 5px; } -.configuration-panel-label { +.configuration-menu-label { color: #FFFFFF; font-family: 'Titillium Web', sans-serif; font-size: 14px; diff --git a/view/assets/js/articulation.js b/view/assets/js/articulation.js deleted file mode 100644 index cdefabd..0000000 --- a/view/assets/js/articulation.js +++ /dev/null @@ -1,143 +0,0 @@ -(function(articulation, $, undefined) { - - var server_host = ''; - var MAX_COLUMNS = 14; - - function _updateASelector(container, ballSelector, step) { - var pointSelector = parseInt(step) == 2 ? 'A' : 'B'; - $(container + ' .ball-selector.active').each(function() { - $(this).removeClass('active'); - $(this).find('.point-selector').remove(); - }); - ballSelector.addClass('active'); - ballSelector.append('
'); - $(container + ' .selection-panel-option[select=true]').attr('select', - false); - $(ballSelector).attr('select', true); - } - - function _getSelectedY(hand, subConfig, step) { - step = parseInt(step) - 1; - var previousStepId = '.selection-panel-body[mainConfig=' + hand - + '][subConfig=' + subConfig + '][step=' + step - + '] .module-x-y'; - return $(previousStepId).attr('data-y'); - } - - function _setupModuleZ(hand, subConfig, step, selectedY) { - if (typeof selectedY == 'undefined' || selectedY == '') - return; - - var base_id = '.selection-panel-body[mainConfig=' + hand - + '][subConfig=' + subConfig + '][step=' + step + ']'; - var articulation_z = base_id + ' .module-z'; - $(articulation_z + ' .ball-selector').hide(); - $(articulation_z + ' .row-number-' + selectedY + ' .ball-selector') - .show(); - - var z = $(articulation_z).attr('data-z'); - if (typeof z != 'undefined') { - var ball_selector = $(articulation_z + ' .row-number-' + selectedY - + ' .ball-' + z); - _updateASelector(articulation_z, ball_selector, step); - } - } - - function _setupBallSelectorXY(hand, subConfig, step) { - var base_id = '.selection-panel-body[mainConfig=' + hand - + '][subConfig=' + subConfig + '][step=' + step + ']'; - var articulation_x_y = base_id + ' .module-x-y'; - $(articulation_x_y + ' .ball-selector') - .off('click') - .on( - 'click', - function(a) { - var b = $(a.target); - if (!b.hasClass('ball-selector')) { - dynworkflow.userSelectedAnOption(); - return; - } - var c = b.parent('.grid-row'), d = $(articulation_x_y), f = b - .attr('data-x'), g = c.attr('data-y'); - d.attr('data-x', f), d.attr('data-y', g); - - var nextStep = parseInt(step) + 1; - _updateASelector(articulation_x_y, b, nextStep); - _setupModuleZ(hand, subConfig, nextStep, g); - - wikilibras.updateTempParameterJSON(hand, subConfig, - step, f + ';' + g); - dynworkflow.userSelectedAnOption(); - }); - } - - function _setupBallSelectorZ(hand, subConfig, step) { - var base_id = '.selection-panel-body[mainConfig=' + hand - + '][subConfig=' + subConfig + '][step=' + step + ']'; - var articulation_z = base_id + ' .module-z'; - $(articulation_z + ' .ball-selector').off('click').on( - 'click', - function(a) { - var b = $(a.target); - if (!b.hasClass('ball-selector')) { - dynworkflow.userSelectedAnOption(); - return; - } - var c = b.parent('.grid-row'), e = $(articulation_z), h = b - .attr('data-z'); - b.attr('data-z') && e.attr('data-z', h), _updateASelector( - articulation_z, b, step); - - wikilibras - .updateTempParameterJSON(hand, subConfig, step, h); - dynworkflow.userSelectedAnOption(); - }); - } - - function _calculateArticulationPointIndex(hand, xValue, yValue, zValue) { - var x = xValue; - var y = yValue; - var z = zValue; - if (hand == 'left-hand') { - x = MAX_COLUMNS - x + 1; - } - - var value = (z - 1) * MAX_COLUMNS + x + 3 * MAX_COLUMNS * (y - 1); - //console.log(value); - return value; - } - - articulation.processValue = function(hand, selectionArray) { - var xyValueSplit = selectionArray[0].split(';'); - var xValue = parseInt(xyValueSplit[0]); - var yValue = parseInt(xyValueSplit[1]); - var zValue = parseInt(selectionArray[1]); - return _calculateArticulationPointIndex(hand, xValue, yValue, zValue); - }; - - articulation.setupModuleXY = function(serverhost, hand, subConfig, step) { - server_host = serverhost; - _setupBallSelectorXY(hand, subConfig, step); - }; - - articulation.setupModuleZ = function(serverhost, hand, subConfig, step) { - server_host = serverhost; - _setupBallSelectorZ(hand, subConfig, step); - - var selectedY = _getSelectedY(hand, subConfig, step); - _setupModuleZ(hand, subConfig, step, selectedY); - }; - - articulation.clean = function() { - $('.ball-selector.active').each(function() { - $(this).removeClass('active'); - $(this).find('.point-selector').remove(); - }); - $('.module-x-y').attr('data-x', ''); - $('.module-x-y').attr('data-y', ''); - $('.module-z').attr('data-z', ''); - } - -}(window.articulation = window.articulation || {}, jQuery)); diff --git a/view/assets/js/configuration-screen.js b/view/assets/js/configuration-screen.js new file mode 100644 index 0000000..44038ac --- /dev/null +++ b/view/assets/js/configuration-screen.js @@ -0,0 +1,62 @@ +(function(configurationScreen, $, undefined) { + + function _isMenuSelected() { + return $('#configuration-menu .icon_container[select=true]').length > 0; + } + + function _getCurrentMainConfiguration() { + return _isMenuSelected() ? $( + '#configuration-menu .icon_container[select=true]').attr( + 'name') : ''; + } + + configurationScreen.isMenuSelected = function() { + return _isMenuSelected(); + } + + configurationScreen.getCurrentMainConfiguration = function() { + return _getCurrentMainConfiguration(); + } + + configurationScreen.setup = function() { + $('.icon_container').off('mouseover').on('mouseover', function() { + if (iconHelper.canHover(this)) { + iconHelper.enableIconHover(this, true); + } + }); + $('.icon_container').off('mouseout').on('mouseout', function() { + if (iconHelper.canHover(this)) { + iconHelper.enableIconHover(this, false); + } + }); + $('.config-menu-option').off('click').on('click', function() { + selectionPanel.show($(this).attr('panel')); + }); + $('#minimize-icon-container').off('click').on('click', function() { + $('#ref-video-container').hide(); + $('#minimize-icon-container').hide(); + $('#maximize-icon-container').show(); + }); + $('#maximize-icon-container').off('click').on('click', function() { + $('#ref-video-container').show(); + $('#maximize-icon-container').hide(); + $('#minimize-icon-container').show(); + }); + selectionPanel.setup(); + }; + + function _showConfigurationScreen(toShow) { + if (toShow) { + $("#configuration-screen").show(); + videoHelper.play("#ref-video-container video"); + } else { + $("#configuration-screen").hide(); + videoHelper.pause("#ref-video-container video"); + } + } + + configurationScreen.show = function(toShow) { + _showConfigurationScreen(toShow); + } + +}(window.configurationScreen = window.configurationScreen || {}, jQuery)); diff --git a/view/assets/js/configuration.js b/view/assets/js/configuration.js deleted file mode 100644 index b342ab4..0000000 --- a/view/assets/js/configuration.js +++ /dev/null @@ -1,43 +0,0 @@ -(function(configuration, $, undefined) { - - configuration.setupFingersGroup = function(hand, subConfig, step) { - var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + - subConfig + '][step=' + step + ']'; - $(baseId + ' .selection-panel-option' - ).off('click').on('click', function() { - wikilibras.selectAnOption(baseId, this); - _setupFingersToShow(hand, subConfig, step); - - dynworkflow.userSelectedAnOption(); - }); - }; - - function _setupFingersToShow(hand, subConfig, step) { - var stepOneBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + - subConfig + '][step=' + step + ']'; - var nextStep = parseInt(step) + 1; - var stepTwoBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + - subConfig + '][step=' + nextStep + ']'; - - var finger_group = $(stepOneBaseId + ' .selection-panel-option[select=true]').attr('value'); - finger_group = typeof finger_group == 'undefined' ? '0' : finger_group; - - // clean next step - dynworkflow.cleanStep(hand, subConfig, nextStep); - $(stepTwoBaseId + ' .finger-group').hide(); - $(stepTwoBaseId + ' .finger-group[group=' + finger_group + ']').show(); - } - - configuration.setupFingersPosition = function(hand, subConfig, step) { - var stepTwoBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + - subConfig + '][step=' + step + ']'; - $(stepTwoBaseId + ' .selection-panel-option').off('click').on( - 'click', function() { - wikilibras.selectAnOption(stepTwoBaseId, this); - dynworkflow.userSelectedAnOption(); - }); - var previousStep = parseInt(step) - 1; - _setupFingersToShow(hand, subConfig, previousStep); - }; - -}(window.configuration = window.configuration || {}, jQuery)); diff --git a/view/assets/js/defaultConfigurationHandler.js b/view/assets/js/defaultConfigurationHandler.js deleted file mode 100644 index ee6a21c..0000000 --- a/view/assets/js/defaultConfigurationHandler.js +++ /dev/null @@ -1,27 +0,0 @@ -(function(defaultConfigurationHandler, $, undefined) { - - defaultConfigurationHandler.setup = function(hand, subConfig, step) { - var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + - subConfig + '][step=' + step + ']'; - $(baseId + ' .selection-panel-option').off('click').on( - 'click', function() { - wikilibras.selectAnOption(baseId, this); - dynworkflow.userSelectedAnOption(); - }); - }; - - function _startVideoLoop(hand, subConfig, step, timeBetweenLoops) { - setTimeout(function(){ - $('.selection-panel-body[mainConfig=' + hand + '][subConfig=' + - subConfig + '][step=' + step + '] video').each(function(){ - $(this).get(0).play(); - }); - _startVideoLoop(hand, subConfig, step, timeBetweenLoops); - }, timeBetweenLoops); - } - - defaultConfigurationHandler.startVideoLoop = function(hand, subConfig, step, timeBetweenLoops) { - _startVideoLoop(hand, subConfig, step, timeBetweenLoops); - } - -}(window.defaultConfigurationHandler = window.defaultConfigurationHandler || {}, jQuery)); diff --git a/view/assets/js/dynamic-loading-engine.js b/view/assets/js/dynamic-loading-engine.js deleted file mode 100644 index 101c7f0..0000000 --- a/view/assets/js/dynamic-loading-engine.js +++ /dev/null @@ -1,96 +0,0 @@ -(function(dynengine, $, undefined) { - var setup = undefined; - - _preprocessHtml = function(data, url) { - var matchSubConfig = data.match(/sub(?:C|c)onfig="(.*?)"/); - var currentMainConfig = dynworkflow.getMainConfig(); // right-hand or left-hand - var goodData = data; - - var isRightHand = function(hand) { - return hand === 'right-hand'; - }; - - var replaceConfigurationTag = function(data, mainConfig) { - if (isRightHand(mainConfig)) { - return data.replace(/{{ configuracao }}/g, 'cmd'); - } else { - return data.replace(/{{ configuracao }}/g, 'cme'); - } - } - - var replaceOrientationTag = function(data, mainConfig) { - if (isRightHand(mainConfig)) { - return data.replace(/{{ orientacao }}/g, 'ord'); - } else { - return data.replace(/{{ orientacao }}/g, 'ore'); - } - } - - var replaceHandFolderTag = function(data, mainConfig) { - if (isRightHand(mainConfig)) { - return data.replace(/{{ hand-folder }}/g, 'md'); - } else { - return data.replace(/{{ hand-folder }}/g, 'me'); - } - } - - var replaceMovementNameTag = function(data, mainConfig) { - var selectedMovement = movement.getPreviousSelectedMovement(mainConfig); - if (typeof selectedMovement != "undefined") { - return data.replace(/{{ movement-name }}/g, selectedMovement); - } - return data - } - - if (matchSubConfig) { // case defined - // There is no specific(right or left hand dependent) assets for: articulacao, duracao, expressao, movimento, transicao - // Specific configurations: configuracao, orientacao - // possible values on the side as comment - var subConfig = matchSubConfig[1]; // articulacao | configuracao | duracao | expressao | movimento | orientacao | transicao - - // possible subconfigs that need changing - switch (subConfig) { - case 'configuracao': - goodData = replaceConfigurationTag(data, currentMainConfig); - break; - case 'configuracao-retilineo': - goodData = replaceConfigurationTag(data, currentMainConfig); - break; - case 'orientacao': - goodData = replaceOrientationTag(data, currentMainConfig); - break; - case 'orientacao-retilineo': - goodData = replaceOrientationTag(data, currentMainConfig); - break; - } - } - goodData = replaceHandFolderTag(goodData, currentMainConfig); - goodData = replaceMovementNameTag(goodData, currentMainConfig); - goodData = goodData.replace(/{{ hand }}/g, currentMainConfig); - return goodData.replace(/{{ server }}/g, url); - }; - - dynengine.render = function(serverUrl, templatePath, target, prepend, callback) { - var url = serverUrl + templatePath; - $.get(url, function(data) { - var processedHtml = _preprocessHtml(data, serverUrl); - if (prepend) { - $(target).prepend(processedHtml); - } else { - $(target).append(processedHtml); - } - }) - .done(function() { - callback && callback(); // call if defined - }); - }; - - dynengine.clean = function(target) { - $(target).html(''); - }; - - dynengine.load = function() { - var url = $('#server-url').data('url'); - }; - -}(window.dynengine = window.dynengine || {}, jQuery)); diff --git a/view/assets/js/dynamic-selection-workflow.js b/view/assets/js/dynamic-selection-workflow.js deleted file mode 100644 index e746b8b..0000000 --- a/view/assets/js/dynamic-selection-workflow.js +++ /dev/null @@ -1,369 +0,0 @@ -(function(dynworkflow, $, undefined) { - - // Workflow configuration - var jsonWF = {}; - var baseUrl = ''; - - // Main configurations: right-hand, left-hand and facial - var mainConfig = ''; - // The converted Main Config (right/left-hand) to hand for using the same configuration - var preprocessedMainConfig = ''; - // Subconfigurations: movimento, articulacao, configuracao, orientacao, etc - var currentSubconfig = ''; - var currentSubConfigName = ''; - var currentSubconfigParent = ''; - var currentStep = 0; - - function _preprocessMainConfig(config) { - config = config.replace('right-hand', 'hand'); - config = config.replace('left-hand', 'hand'); - return config; - } - - function _getFirstKey(json) { - var first_key = undefined; - for (first_key in json) - break; - return first_key; - } - - function _getAttributes(json) { - var result = []; - for (attr in json) { - result.push(attr); - } - return result; - } - - function _updateAndGetFirstMovementSubConfig() { - var selectedMovement = movement.getPreviousSelectedMovement(mainConfig); - if (typeof selectedMovement == 'undefined') - return -1; - - currentSubconfigParent = jsonWF[preprocessedMainConfig]['movimento'][selectedMovement]; - currentSubConfigName = _getFirstKey(currentSubconfigParent); - return currentSubConfigName; - } - - function _updateAndGetMovementConfig() { - currentSubconfigParent = jsonWF[preprocessedMainConfig]; - currentSubConfigName = _getFirstKey(currentSubconfigParent); - return currentSubConfigName; - } - - function _getNextSubConfig(toForward) { - var attrs = _getAttributes(currentSubconfigParent); - for (var i = 0; i < attrs.length; i++) { - if (toForward && attrs[i] == currentSubConfigName - && i < attrs.length - 1) { - return attrs[i + 1]; - } else if (!toForward && attrs[i] == currentSubConfigName && i >= 1) { - return attrs[i - 1]; - } - } - if (toForward && currentSubConfigName == 'movimento') { - return _updateAndGetFirstMovementSubConfig(); - } else if (!toForward && preprocessedMainConfig == 'hand') { - return _updateAndGetMovementConfig(); - } else if (!toForward) { - return currentSubConfigName; - } else { - return -1; - } - } - - function _showCurrentSubconfig() { - _showSubconfiguration(mainConfig, currentSubConfigName, currentStep); - } - - // It checks if a selection panel is already loaded - function _isSubconfigurationPanelLoaded(mainConfig, subConfig, stepNumber) { - var stepNumber = stepNumber + 1; - return $('.selection-panel-body[mainConfig=' + mainConfig - + '][subConfig=' + subConfig + '][step=' + stepNumber + ']').length > 0; - } - - function _showLoadedSubconfigurationPanel(mainConfig, subConfig, stepNumber) { - var stepNumber = stepNumber + 1; - return $( - '.selection-panel-body[mainConfig=' + mainConfig - + '][subConfig=' + subConfig + '][step=' + stepNumber - + ']').show(); - } - - // It renders or shows the requested selection panel - function _showSubconfiguration(mainConfig, subConfig, stepNumber) { - $('.selection-panel-body').hide(); - if (_isSubconfigurationPanelLoaded(mainConfig, subConfig, stepNumber)) { - _showLoadedSubconfigurationPanel(mainConfig, subConfig, stepNumber); - } else { - var step = currentSubconfig[stepNumber]; - step = typeof step == 'undefined' ? 'passo-1' : step; - dynengine.render(baseUrl, '/' + preprocessedMainConfig + '/' - + subConfig + '/' + step + '.html', '#selection-panel', - true); - } - _selectTimelineIcon(mainConfig, subConfig, true); - } - - function _selectSubConfig(subConfig) { - if (subConfig == 'movimento') { - _updateAndGetMovementConfig(); - } else if (currentSubConfigName == 'movimento') { - _updateAndGetFirstMovementSubConfig(); - } - currentSubConfigName = subConfig; - currentSubconfig = currentSubconfigParent[currentSubConfigName]; - currentStep = 0; - _showCurrentSubconfig(); - } - - // It shows the next selection panel on the workflow - function _showNextSubConfig() { - _walkOnTheWorkflow(true); - } - - function _showPreviousSubConfig() { - _walkOnTheWorkflow(false); - } - - function _walkOnTheWorkflow(toForward) { - currentStep = toForward ? currentStep + 1 : currentStep - 1; - - if (currentStep >= 0 && currentStep < currentSubconfig.length) { - _showCurrentSubconfig(); - } else { - var nextSubConfig = _getNextSubConfig(toForward); - if (nextSubConfig != -1) { - _selectSubConfig(nextSubConfig); - } else { - wikilibras.hideSelectionPanel(); - } - } - } - - function _checkIfFinished(mainConfig, currentSubConfigName) { - var numberOfSteps = currentSubconfig.length; - var completedSteps = $('.selection-panel-body[mainConfig=' + mainConfig - + '][subConfig=' + currentSubConfigName - + '] .selection-panel-option[select=true]').length; - return completedSteps != 0 && completedSteps == numberOfSteps; - } - - // A callback function to be called when the user selects a option on a panel - function _userSelectedAnOption() { - if (_checkIfFinished(mainConfig, currentSubConfigName)) { - _setupCheckIcon(mainConfig, currentSubConfigName); - } - _showNextSubConfig(); - } - - function _cleanStep(mainConfig, subConfig, step) { - var baseId = '.selection-panel-body[mainConfig=' + mainConfig - + '][subConfig=' + subConfig + '][step=' + step + ']'; - $(baseId + ' .selection-panel-option').removeAttr('select'); - var icon_id = '.subconfiguration-panel[mainConfig=' + mainConfig - + '] .icon_container[json_name=' + subConfig + ']'; - $(icon_id).removeAttr('complete'); - } - - // Timeline functions - function _selectTimelineIcon(mainConfig, subConfig) { - var baseId = '.subconfiguration-panel[mainConfig=' + mainConfig - + '] .subconfiguration-options'; - var iconContainer = '.icon_container[json_name=' + subConfig + ']'; - var iconId = baseId + ' ' + iconContainer; - - var previousSelected = $(baseId + ' .icon_container[select=true]') - .attr('json_name'); - if (typeof previousSelected != 'undefined') { - _deselectTimelineIcon(mainConfig, previousSelected); - } - - wikilibras.enableIconHover($(iconId), true); - $(iconId).attr('select', true); - $(baseId).scrollTo(iconContainer, { - 'offset' : -60, - 'duration' : 750 - }); - } - - function _deselectTimelineIcon(mainConfig, subConfig) { - var icon_id = '.subconfiguration-panel[mainConfig=' + mainConfig - + '] .icon_container[json_name=' + subConfig + ']'; - - if ($(icon_id + '[complete=true]').length > 0) { - _setupCheckIcon(mainConfig, subConfig); - } else { - wikilibras.enableIconHover($(icon_id), false); - $(icon_id).removeAttr('select'); - } - } - - function _setupCheckIcon(mainConfig, subConfig) { - var icon_id = $('.subconfiguration-panel[mainConfig=' + mainConfig - + '] .icon_container[json_name=' + subConfig + ']'); - wikilibras.enableIconCheck(icon_id, true); - $(icon_id).attr('complete', true); - $(icon_id).attr('select', false); - } - - function _isTimelineLoaded() { - return $('.subconfiguration-panel[mainConfig=' + mainConfig + ']').length > 0; - } - - function _setupTimelineListeners(timelineBaseId) { - $(timelineBaseId + ' .icon_container[json_name]').off('click').on( - 'click', function() { - var subConfig = $(this).attr('json_name'); - _selectSubConfig(subConfig); - }); - $(timelineBaseId + ' .icon_container[json_name]').off('mouseover').on( - 'mouseover', function() { - if (wikilibras.canHover(this)) { - wikilibras.enableIconHover(this, true); - } - }); - $(timelineBaseId + ' .icon_container[json_name]').off('mouseout').on( - 'mouseout', function() { - if (wikilibras.canHover(this)) { - wikilibras.enableIconHover(this, false); - } - }); - $(timelineBaseId + ' .arrow[name=right-arrow]').off('click').on( - 'click', function() { - _showNextSubConfig(); - }); - $(timelineBaseId + ' .arrow[name=left-arrow]').off('click').on('click', - function() { - _showPreviousSubConfig(); - }); - } - - function _setupTimelineIcons(timelineBaseId, toUpdate) { - if (!toUpdate) { - $(timelineBaseId).show(); - $(timelineBaseId + " .subconfiguration-options").scrollTo(0, 0); - return; - } - - $(timelineBaseId + ' .icon_container[json_name]').attr("active", - "false"); - for ( var name in currentSubconfigParent) { - $(timelineBaseId + ' .icon_container[json_name=' + name + ']') - .attr("active", "true"); - } - - if (preprocessedMainConfig == 'hand') { - $(timelineBaseId + ' .icon_container[json_name=movimento]').attr( - "active", "true"); - _setupCheckIcon(mainConfig, 'movimento'); - } - _selectTimelineIcon(mainConfig, currentSubConfigName); - _setupTimelineListeners(timelineBaseId); - $(timelineBaseId).show(); - } - - function _setupTimeline(toUpdate) { - var timelineBaseId = '.subconfiguration-panel[mainConfig=' + mainConfig - + ']'; - if (_isTimelineLoaded()) { - _setupTimelineIcons(timelineBaseId, toUpdate); - } else { - dynengine.render(baseUrl, '/' + preprocessedMainConfig - + '/timeline.html', '#selection-panel', false, function() { - _setupTimelineIcons(timelineBaseId, true); - }); - } - } - - function _initTimeline() { - if (preprocessedMainConfig != 'hand' || _isTimelineLoaded()) { - _setupTimeline(false); - } - } - - function _cleanTimeline() { - $(".subconfiguration-panel").remove(); - } - - function _cleanPreviousLoadedPanel() { - $('.selection-panel-body[mainConfig=' + mainConfig + ']').each( - function() { - var subConfigName = $(this).attr("subConfig"); - if (subConfigName.indexOf("articulacao") != -1 - || subConfigName.indexOf("configuracao") != -1 - || subConfigName.indexOf("orientacao") != -1 - || subConfigName.indexOf("movimento") != -1) { - return; - } - $( - '.selection-panel-body[mainConfig=' + mainConfig - + '][subConfig=' + subConfigName + ']') - .remove(); - }); - } - - // Public methods - dynworkflow.selectMainConfig = function(config) { - mainConfig = config; - preprocessedMainConfig = _preprocessMainConfig(mainConfig); - currentSubconfigParent = jsonWF[preprocessedMainConfig]; - currentSubConfigName = _getFirstKey(currentSubconfigParent); - currentSubconfig = currentSubconfigParent[currentSubConfigName]; - currentStep = 0; - - _showCurrentSubconfig(); - }; - - dynworkflow.selectMovement = function(movement) { - var subconfigJSON = currentSubconfig[movement]; - currentSubConfigName = _getFirstKey(subconfigJSON); - currentSubconfigParent = subconfigJSON; - currentSubconfig = subconfigJSON[currentSubConfigName]; - currentStep = 0; - - _cleanPreviousLoadedPanel(); - _showCurrentSubconfig(); - _setupTimeline(true); - }; - - dynworkflow.selectSubConfig = function(subConfig) { - _selectSubConfig(subConfig); - }; - - dynworkflow.userSelectedAnOption = function() { - _userSelectedAnOption(); - }; - - dynworkflow.cleanStep = function(mainConfig, subConfig, step) { - _cleanStep(mainConfig, subConfig, step); - }; - - dynworkflow.getFacialParameters = function() { - return _getAttributes(jsonWF['facial']); - }; - - dynworkflow.getMovementParameters = function(movementName) { - return _getAttributes(jsonWF['hand']['movimento'][movementName]); - }; - - dynworkflow.getMainConfig = function() { - return mainConfig; - }; - - dynworkflow.initTimeline = function() { - _initTimeline(); - }; - - dynworkflow.load = function() { - baseUrl = $('#server-url').data('url'); - $.get(baseUrl + '/conf/selection-workflow-json', function(result) { - jsonWF = $.parseJSON(result); - }).fail(function() { - console.log('Failed to load the workflow configuration'); - }); - _cleanTimeline(); - }; - -}(window.dynworkflow = window.dynworkflow || {}, jQuery)); diff --git a/view/assets/js/external-libs/jquery.fileupload.js b/view/assets/js/external-libs/jquery.fileupload.js new file mode 100755 index 0000000..91b7254 --- /dev/null +++ b/view/assets/js/external-libs/jquery.fileupload.js @@ -0,0 +1,1477 @@ +/* + * jQuery File Upload Plugin + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/* jshint nomen:false */ +/* global define, require, window, document, location, Blob, FormData */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'jquery.ui.widget' + ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory( + require('jquery'), + require('./vendor/jquery.ui.widget') + ); + } else { + // Browser globals: + factory(window.jQuery); + } +}(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, + + // 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 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; + }; + } + }, + + _isInstanceOf: function (type, obj) { + // Cross-frame instanceof check + return Object.prototype.toString.call(obj) === '[object ' + type + ']'; + }, + + _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.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.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)) { + formData.append( + ($.type(options.paramName) === 'array' && + options.paramName[index]) || paramName, + file, + file.uploadName || file.name + ); + } + }); + } + } + 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])).pipe( + function () { + if (data.errorThrown) { + return $.Deferred() + .rejectWith(that, [data]).promise(); + } + return getPromise(arguments); + } + ).pipe(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 || 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 + 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; + // 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] + ); + }); + }; + 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._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.pipe(send); + } else { + this._sequence = this._sequence.pipe(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(), + 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); + }, + dirReader, entries = []; + 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 empy 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); + }) + ).pipe(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) + ).pipe(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'); + }, + + _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); + } + + }); + +})); diff --git a/view/assets/js/external-libs/jquery.iframe-transport.js b/view/assets/js/external-libs/jquery.iframe-transport.js new file mode 100755 index 0000000..a7d34e0 --- /dev/null +++ b/view/assets/js/external-libs/jquery.iframe-transport.js @@ -0,0 +1,217 @@ +/* + * jQuery Iframe Transport Plugin + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/* global define, require, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory(require('jquery')); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + // Helper variable to create unique names for the transport iframes: + var counter = 0; + + // The iframe transport accepts four additional options: + // options.fileInput: a jQuery collection of file input fields + // options.paramName: the parameter name for the file form data, + // overrides the name property of the file input field(s), + // can be a string or an array of strings. + // options.formData: an array of objects with name and value properties, + // equivalent to the return data of .serializeArray(), e.g.: + // [{name: 'a', value: 1}, {name: 'b', value: 2}] + // options.initialIframeSrc: the URL of the initial iframe src, + // by default set to "javascript:false;" + $.ajaxTransport('iframe', function (options) { + if (options.async) { + // javascript:false as initial iframe src + // prevents warning popups on HTTPS in IE6: + /*jshint scripturl: true */ + var initialIframeSrc = options.initialIframeSrc || 'javascript:false;', + /*jshint scripturl: false */ + form, + iframe, + addParamChar; + return { + send: function (_, completeCallback) { + form = $('
'); + form.attr('accept-charset', options.formAcceptCharset); + addParamChar = /\?/.test(options.url) ? '&' : '?'; + // XDomainRequest only supports GET and POST: + if (options.type === 'DELETE') { + options.url = options.url + addParamChar + '_method=DELETE'; + options.type = 'POST'; + } else if (options.type === 'PUT') { + options.url = options.url + addParamChar + '_method=PUT'; + options.type = 'POST'; + } else if (options.type === 'PATCH') { + options.url = options.url + addParamChar + '_method=PATCH'; + options.type = 'POST'; + } + // IE versions below IE8 cannot set the name property of + // elements that have already been added to the DOM, + // so we set the name along with the iframe HTML markup: + counter += 1; + iframe = $( + '' + ).bind('load', function () { + var fileInputClones, + paramNames = $.isArray(options.paramName) ? + options.paramName : [options.paramName]; + iframe + .unbind('load') + .bind('load', function () { + var response; + // Wrap in a try/catch block to catch exceptions thrown + // when trying to access cross-domain iframe contents: + try { + response = iframe.contents(); + // Google Chrome and Firefox do not throw an + // exception when calling iframe.contents() on + // cross-domain requests, so we unify the response: + if (!response.length || !response[0].firstChild) { + throw new Error(); + } + } catch (e) { + response = undefined; + } + // The complete callback returns the + // iframe content document as response object: + completeCallback( + 200, + 'success', + {'iframe': response} + ); + // Fix for IE endless progress bar activity bug + // (happens on form submits to iframe targets): + $('') + .appendTo(form); + window.setTimeout(function () { + // Removing the form in a setTimeout call + // allows Chrome's developer tools to display + // the response result + form.remove(); + }, 0); + }); + form + .prop('target', iframe.prop('name')) + .prop('action', options.url) + .prop('method', options.type); + if (options.formData) { + $.each(options.formData, function (index, field) { + $('') + .prop('name', field.name) + .val(field.value) + .appendTo(form); + }); + } + if (options.fileInput && options.fileInput.length && + options.type === 'POST') { + fileInputClones = options.fileInput.clone(); + // Insert a clone for each file input field: + options.fileInput.after(function (index) { + return fileInputClones[index]; + }); + if (options.paramName) { + options.fileInput.each(function (index) { + $(this).prop( + 'name', + paramNames[index] || options.paramName + ); + }); + } + // Appending the file input fields to the hidden form + // removes them from their original location: + form + .append(options.fileInput) + .prop('enctype', 'multipart/form-data') + // enctype must be set as encoding for IE: + .prop('encoding', 'multipart/form-data'); + // Remove the HTML5 form attribute from the input(s): + options.fileInput.removeAttr('form'); + } + form.submit(); + // Insert the file input fields at their original location + // by replacing the clones with the originals: + if (fileInputClones && fileInputClones.length) { + options.fileInput.each(function (index, input) { + var clone = $(fileInputClones[index]); + // Restore the original name and form properties: + $(input) + .prop('name', clone.prop('name')) + .attr('form', clone.attr('form')); + clone.replaceWith(input); + }); + } + }); + form.append(iframe).appendTo(document.body); + }, + abort: function () { + if (iframe) { + // javascript:false as iframe src aborts the request + // and prevents warning popups on HTTPS in IE6. + // concat is used to avoid the "Script URL" JSLint error: + iframe + .unbind('load') + .prop('src', initialIframeSrc); + } + if (form) { + form.remove(); + } + } + }; + } + }); + + // The iframe transport returns the iframe content document as response. + // The following adds converters from iframe to text, json, html, xml + // and script. + // Please note that the Content-Type for JSON responses has to be text/plain + // or text/html, if the browser doesn't include application/json in the + // Accept header, else IE will show a download dialog. + // The Content-Type for XML responses on the other hand has to be always + // application/xml or text/xml, so IE properly parses the XML response. + // See also + // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation + $.ajaxSetup({ + converters: { + 'iframe text': function (iframe) { + return iframe && $(iframe[0].body).text(); + }, + 'iframe json': function (iframe) { + return iframe && $.parseJSON($(iframe[0].body).text()); + }, + 'iframe html': function (iframe) { + return iframe && $(iframe[0].body).html(); + }, + 'iframe xml': function (iframe) { + var xmlDoc = iframe && iframe[0]; + return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc : + $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) || + $(xmlDoc.body).html()); + }, + 'iframe script': function (iframe) { + return iframe && $.globalEval($(iframe[0].body).text()); + } + } + }); + +})); diff --git a/view/assets/js/external-libs/jquery.scrollTo.js b/view/assets/js/external-libs/jquery.scrollTo.js new file mode 100644 index 0000000..7ba1776 --- /dev/null +++ b/view/assets/js/external-libs/jquery.scrollTo.js @@ -0,0 +1,210 @@ +/*! + * jQuery.scrollTo + * Copyright (c) 2007-2015 Ariel Flesler - afleslergmailcom | http://flesler.blogspot.com + * Licensed under MIT + * http://flesler.blogspot.com/2007/10/jqueryscrollto.html + * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery + * @author Ariel Flesler + * @version 2.1.2 + */ +;(function(factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // AMD + define(['jquery'], factory); + } else if (typeof module !== 'undefined' && module.exports) { + // CommonJS + module.exports = factory(require('jquery')); + } else { + // Global + factory(jQuery); + } +})(function($) { + 'use strict'; + + var $scrollTo = $.scrollTo = function(target, duration, settings) { + return $(window).scrollTo(target, duration, settings); + }; + + $scrollTo.defaults = { + axis:'xy', + duration: 0, + limit:true + }; + + function isWin(elem) { + return !elem.nodeName || + $.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1; + } + + $.fn.scrollTo = function(target, duration, settings) { + if (typeof duration === 'object') { + settings = duration; + duration = 0; + } + if (typeof settings === 'function') { + settings = { onAfter:settings }; + } + if (target === 'max') { + target = 9e9; + } + + settings = $.extend({}, $scrollTo.defaults, settings); + // Speed is still recognized for backwards compatibility + duration = duration || settings.duration; + // Make sure the settings are given right + var queue = settings.queue && settings.axis.length > 1; + if (queue) { + // Let's keep the overall duration + duration /= 2; + } + settings.offset = both(settings.offset); + settings.over = both(settings.over); + + return this.each(function() { + // Null target yields nothing, just like jQuery does + if (target === null) return; + + var win = isWin(this), + elem = win ? this.contentWindow || window : this, + $elem = $(elem), + targ = target, + attr = {}, + toff; + + switch (typeof targ) { + // A number will pass the regex + case 'number': + case 'string': + if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) { + targ = both(targ); + // We are done + break; + } + // Relative/Absolute selector + targ = win ? $(targ) : $(targ, elem); + /* falls through */ + case 'object': + if (targ.length === 0) return; + // DOMElement / jQuery + if (targ.is || targ.style) { + // Get the real position of the target + toff = (targ = $(targ)).offset(); + } + } + + var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset; + + $.each(settings.axis.split(''), function(i, axis) { + var Pos = axis === 'x' ? 'Left' : 'Top', + pos = Pos.toLowerCase(), + key = 'scroll' + Pos, + prev = $elem[key](), + max = $scrollTo.max(elem, axis); + + if (toff) {// jQuery / DOMElement + attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]); + + // If it's a dom element, reduce the margin + if (settings.margin) { + attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0; + attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0; + } + + attr[key] += offset[pos] || 0; + + if (settings.over[pos]) { + // Scroll to a fraction of its width/height + attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos]; + } + } else { + var val = targ[pos]; + // Handle percentage values + attr[key] = val.slice && val.slice(-1) === '%' ? + parseFloat(val) / 100 * max + : val; + } + + // Number or 'number' + if (settings.limit && /^\d+$/.test(attr[key])) { + // Check the limits + attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max); + } + + // Don't waste time animating, if there's no need. + if (!i && settings.axis.length > 1) { + if (prev === attr[key]) { + // No animation needed + attr = {}; + } else if (queue) { + // Intermediate animation + animate(settings.onAfterFirst); + // Don't animate this axis again in the next iteration. + attr = {}; + } + } + }); + + animate(settings.onAfter); + + function animate(callback) { + var opts = $.extend({}, settings, { + // The queue setting conflicts with animate() + // Force it to always be true + queue: true, + duration: duration, + complete: callback && function() { + callback.call(elem, targ, settings); + } + }); + $elem.animate(attr, opts); + } + }); + }; + + // Max scrolling position, works on quirks mode + // It only fails (not too badly) on IE, quirks mode. + $scrollTo.max = function(elem, axis) { + var Dim = axis === 'x' ? 'Width' : 'Height', + scroll = 'scroll'+Dim; + + if (!isWin(elem)) + return elem[scroll] - $(elem)[Dim.toLowerCase()](); + + var size = 'client' + Dim, + doc = elem.ownerDocument || elem.document, + html = doc.documentElement, + body = doc.body; + + return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]); + }; + + function both(val) { + return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val }; + } + + // Add special hooks so that window scroll properties can be animated + $.Tween.propHooks.scrollLeft = + $.Tween.propHooks.scrollTop = { + get: function(t) { + return $(t.elem)[t.prop](); + }, + set: function(t) { + var curr = this.get(t); + // If interrupt is true and user scrolled, stop animating + if (t.options.interrupt && t._last && t._last !== curr) { + return $(t.elem).stop(); + } + var next = Math.round(t.now); + // Don't waste CPU + // Browsers don't render floating point scroll + if (curr !== next) { + $(t.elem)[t.prop](next); + t._last = this.get(t); + } + } + }; + + // AMD requirement + return $scrollTo; +}); diff --git a/view/assets/js/external-libs/jquery.ui.widget.js b/view/assets/js/external-libs/jquery.ui.widget.js new file mode 100755 index 0000000..e08df3f --- /dev/null +++ b/view/assets/js/external-libs/jquery.ui.widget.js @@ -0,0 +1,572 @@ +/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28 +* http://jqueryui.com +* Includes: widget.js +* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define([ "jquery" ], factory ); + + } else if ( typeof exports === "object" ) { + + // Node/CommonJS + factory( require( "jquery" ) ); + + } else { + + // Browser globals + factory( jQuery ); + } +}(function( $ ) { +/*! + * jQuery UI Widget 1.11.4 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/jQuery.widget/ + */ + + +var widget_uuid = 0, + widget_slice = Array.prototype.slice; + +$.cleanData = (function( orig ) { + return function( elems ) { + var events, elem, i; + for ( i = 0; (elem = elems[i]) != null; i++ ) { + try { + + // Only trigger remove when necessary to save time + events = $._data( elem, "events" ); + if ( events && events.remove ) { + $( elem ).triggerHandler( "remove" ); + } + + // http://bugs.jquery.com/ticket/8235 + } catch ( e ) {} + } + orig( elems ); + }; +})( $.cleanData ); + +$.widget = function( name, base, prototype ) { + var fullName, existingConstructor, constructor, basePrototype, + // proxiedPrototype allows the provided prototype to remain unmodified + // so that it can be used as a mixin for multiple widgets (#8876) + proxiedPrototype = {}, + namespace = name.split( "." )[ 0 ]; + + name = name.split( "." )[ 1 ]; + fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); + }; + + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new constructor( options, element ); + } + + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + // extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + // copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + // track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + }); + + basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( !$.isFunction( value ) ) { + proxiedPrototype[ prop ] = value; + return; + } + proxiedPrototype[ prop ] = (function() { + var _super = function() { + return base.prototype[ prop ].apply( this, arguments ); + }, + _superApply = function( args ) { + return base.prototype[ prop ].apply( this, args ); + }; + return function() { + var __super = this._super, + __superApply = this._superApply, + returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply( this, arguments ); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + })(); + }); + constructor.prototype = $.widget.extend( basePrototype, { + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name + }, proxiedPrototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + widgetFullName: fullName + }); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); + }); + // remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } + + $.widget.bridge( name, constructor ); + + return constructor; +}; + +$.widget.extend = function( target ) { + var input = widget_slice.call( arguments, 1 ), + inputIndex = 0, + inputLength = input.length, + key, + value; + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; +}; + +$.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string", + args = widget_slice.call( arguments, 1 ), + returnValue = this; + + if ( isMethodCall ) { + this.each(function() { + var methodValue, + instance = $.data( this, fullName ); + if ( options === "instance" ) { + returnValue = instance; + return false; + } + if ( !instance ) { + return $.error( "cannot call methods on " + name + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + " widget instance" ); + } + methodValue = instance[ options ].apply( instance, args ); + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + }); + } else { + + // Allow multiple hashes to be passed on init + if ( args.length ) { + options = $.widget.extend.apply( null, [ options ].concat(args) ); + } + + this.each(function() { + var instance = $.data( this, fullName ); + if ( instance ) { + instance.option( options || {} ); + if ( instance._init ) { + instance._init(); + } + } else { + $.data( this, fullName, new object( options, this ) ); + } + }); + } + + return returnValue; + }; +}; + +$.Widget = function( /* options, element */ ) {}; +$.Widget._childConstructors = []; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "
", + options: { + disabled: false, + + // callbacks + create: null + }, + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = widget_uuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + + if ( element !== this ) { + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + }); + this.document = $( element.style ? + // element within the document + element.ownerDocument : + // element is window or document + element.document || element ); + this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); + } + + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this._create(); + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + _getCreateOptions: $.noop, + _getCreateEventData: $.noop, + _create: $.noop, + _init: $.noop, + + destroy: function() { + this._destroy(); + // we can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .unbind( this.eventNamespace ) + .removeData( this.widgetFullName ) + // support: jquery <1.6.3 + // http://bugs.jquery.com/ticket/9413 + .removeData( $.camelCase( this.widgetFullName ) ); + this.widget() + .unbind( this.eventNamespace ) + .removeAttr( "aria-disabled" ) + .removeClass( + this.widgetFullName + "-disabled " + + "ui-state-disabled" ); + + // clean up events and states + this.bindings.unbind( this.eventNamespace ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + }, + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key, + parts, + curOption, + i; + + if ( arguments.length === 0 ) { + // don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( arguments.length === 1 ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( arguments.length === 1 ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + _setOption: function( key, value ) { + this.options[ key ] = value; + + if ( key === "disabled" ) { + this.widget() + .toggleClass( this.widgetFullName + "-disabled", !!value ); + + // If the widget is becoming disabled, then nothing is interactive + if ( value ) { + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + } + } + + return this; + }, + + enable: function() { + return this._setOptions({ disabled: false }); + }, + disable: function() { + return this._setOptions({ disabled: true }); + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement, + instance = this; + + // no suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // no element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + // allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^([\w:-]*)\s*(.*)$/ ), + eventName = match[1] + instance.eventNamespace, + selector = match[2]; + if ( selector ) { + delegateElement.delegate( selector, eventName, handlerProxy ); + } else { + element.bind( eventName, handlerProxy ); + } + }); + }, + + _off: function( element, eventName ) { + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + + this.eventNamespace; + element.unbind( eventName ).undelegate( eventName ); + + // Clear the stack to avoid memory leaks (#10056) + this.bindings = $( this.bindings.not( element ).get() ); + this.focusable = $( this.focusable.not( element ).get() ); + this.hoverable = $( this.hoverable.not( element ).get() ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + $( event.currentTarget ).addClass( "ui-state-hover" ); + }, + mouseleave: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-hover" ); + } + }); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + $( event.currentTarget ).addClass( "ui-state-focus" ); + }, + focusout: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-focus" ); + } + }); + }, + + _trigger: function( type, event, data ) { + var prop, orig, + callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( $.isFunction( callback ) && + callback.apply( this.element[0], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } +}; + +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + var hasOptions, + effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + if ( options.delay ) { + element.delay( options.delay ); + } + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue(function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + }); + } + }; +}); + +var widget = $.widget; + + + +})); diff --git a/view/assets/js/external-libs/js.cookie.js b/view/assets/js/external-libs/js.cookie.js new file mode 100644 index 0000000..e808108 --- /dev/null +++ b/view/assets/js/external-libs/js.cookie.js @@ -0,0 +1,145 @@ +/*! + * JavaScript Cookie v2.0.4 + * https://github.com/js-cookie/js-cookie + * + * Copyright 2006, 2015 Klaus Hartl & Fagner Brack + * Released under the MIT license + */ +(function(factory) { + if (typeof define === 'function' && define.amd) { + define(factory); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + var _OldCookies = window.Cookies; + var api = window.Cookies = factory(); + api.noConflict = function() { + window.Cookies = _OldCookies; + return api; + }; + } +}(function() { + function extend() { + var i = 0; + var result = {}; + for (; i < arguments.length; i++) { + var attributes = arguments[ i ]; + for (var key in attributes) { + result[key] = attributes[key]; + } + } + return result; + } + + function init(converter) { + function api(key, value, attributes) { + var result; + + // Write + + if (arguments.length > 1) { + attributes = extend({ + path: '/' + }, api.defaults, attributes); + + if (typeof attributes.expires === 'number') { + var expires = new Date(); + expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); + attributes.expires = expires; + } + + try { + result = JSON.stringify(value); + if (/^[\{\[]/.test(result)) { + value = result; + } + } catch (e) {} + + if (!converter.write) { + value = encodeURIComponent(String(value)) + .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); + } else { + value = converter.write(value, key); + } + + key = encodeURIComponent(String(key)); + key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); + key = key.replace(/[\(\)]/g, escape); + + return (document.cookie = [ + key, '=', value, + attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE + attributes.path && '; path=' + attributes.path, + attributes.domain && '; domain=' + attributes.domain, + attributes.secure ? '; secure' : '' + ].join('')); + } + + // Read + + if (!key) { + result = {}; + } + + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. Also prevents odd result when + // calling "get()" + var cookies = document.cookie ? document.cookie.split('; ') : []; + var rdecode = /(%[0-9A-Z]{2})+/g; + var i = 0; + + for (; i < cookies.length; i++) { + var parts = cookies[i].split('='); + var name = parts[0].replace(rdecode, decodeURIComponent); + var cookie = parts.slice(1).join('='); + + if (cookie.charAt(0) === '"') { + cookie = cookie.slice(1, -1); + } + + try { + cookie = converter.read ? + converter.read(cookie, name) : converter(cookie, name) || + cookie.replace(rdecode, decodeURIComponent); + + if (this.json) { + try { + cookie = JSON.parse(cookie); + } catch (e) {} + } + + if (key === name) { + result = cookie; + break; + } + + if (!key) { + result[name] = cookie; + } + } catch (e) {} + } + + return result; + } + + api.get = api.set = api; + api.getJSON = function() { + return api.apply({ + json: true + }, [].slice.call(arguments)); + }; + api.defaults = {}; + + api.remove = function(key, attributes) { + api(key, '', extend(attributes, { + expires: -1 + })); + }; + + api.withConverter = init; + + return api; + } + + return init(function() {}); +})); diff --git a/view/assets/js/facial.js b/view/assets/js/facial.js deleted file mode 100644 index 8c4d270..0000000 --- a/view/assets/js/facial.js +++ /dev/null @@ -1,21 +0,0 @@ -(function(facial, $, undefined) { - - facial.setup = function(subConfig) { - var baseId = '.selection-panel-body[mainConfig=facial][subConfig=' - + subConfig + ']'; - $(baseId + ' .selection-panel-option').off('click').on('click', - function() { - wikilibras.selectAnOption(baseId, this); - dynworkflow.userSelectedAnOption(); - }); - $(baseId + ' .video-panel-option').off('mouseenter').on('mouseenter', - function(event) { - $(this).addClass('video-panel-option-hover'); - }); - $(baseId + ' .video-panel-option').off('mouseleave').on('mouseleave', - function(event) { - $(this).removeClass('video-panel-option-hover'); - }); - }; - -}(window.facial = window.facial || {}, jQuery)); diff --git a/view/assets/js/helpers/icon-helper.js b/view/assets/js/helpers/icon-helper.js new file mode 100644 index 0000000..9cc0f4f --- /dev/null +++ b/view/assets/js/helpers/icon-helper.js @@ -0,0 +1,85 @@ +(function(iconHelper, $, undefined) { + + var baseUrl = ''; + + function _changeImage(img, url) { + img.attr('src', url); + } + + function _enableIconHover(container, isHover) { + var img = $(container).find('img').first(); + var hover_img_url = baseUrl + '/img/' + $(container).attr('name'); + if (isHover) { + hover_img_url += '-icon-hover.png'; + } else { + hover_img_url += '-icon.png'; + } + _changeImage(img, hover_img_url); + } + + function _enableIconCheck(container, isCheck) { + var img = $(container).find('img').first(); + var check_img_url = baseUrl + '/img/' + $(container).attr('name'); + if (isCheck) { + check_img_url += '-icon-check.png'; + } else { + check_img_url += '-icon.png'; + } + _changeImage(img, check_img_url); + } + + function _selectIcon(iconName, isSelect, panel) { + panel = typeof panel == 'undefined' ? '' : '[panel=' + panel + ']'; + var icon_id = '.icon_container[name=' + iconName + ']' + panel; + _enableIconHover(icon_id, isSelect); + $(icon_id).attr('select', isSelect); + } + + function _deselectIcon(iconName, parent) { + _selectIcon(iconName, false, parent); + } + + function _setupCheckIcon(option, isCheck, panel) { + panel = typeof panel == 'undefined' ? '' : '[panel=' + panel + ']'; + var icon_id = '.icon_container[name=' + option + ']' + panel; + iconHelper.enableIconCheck(icon_id, isCheck); + $('.icon_container[name=' + option + ']' + panel).attr('complete', + isCheck); + } + + function _canHover(el) { + var incompleteConfig = typeof $(el).attr('complete') == 'undefined' + || $(el).attr('complete') == 'false'; + return (!configurationScreen.isMenuSelected() && incompleteConfig) + || (typeof $(el).attr('select') == 'undefined' && incompleteConfig); + } + + iconHelper.enableIconHover = function(container, isHover) { + _enableIconHover(container, isHover); + } + + iconHelper.enableIconCheck = function(container, isCheck) { + _enableIconCheck(container, isCheck); + } + + iconHelper.setupCheckIcon = function(option, isCheck, panel) { + _setupCheckIcon(option, isCheck, panel); + } + + iconHelper.selectIcon = function(iconName, isSelect, panel) { + _selectIcon(iconName, isSelect, panel); + } + + iconHelper.deselectIcon = function(iconName, parent) { + _deselectIcon(iconName, parent); + } + + iconHelper.canHover = function(el) { + return _canHover(el); + } + + iconHelper.setup = function(url) { + baseUrl = url; + }; + +}(window.iconHelper = window.iconHelper || {}, jQuery)); diff --git a/view/assets/js/helpers/tmpJSONParser.js b/view/assets/js/helpers/tmpJSONParser.js new file mode 100644 index 0000000..0c0dc60 --- /dev/null +++ b/view/assets/js/helpers/tmpJSONParser.js @@ -0,0 +1,124 @@ +(function(tmpJSONParser, $, undefined) { + + var base_parameter_json = {}; + var movement_parameter_json = {}; + + function _setupBaseParameterJSON(tmpJSON) { + base_parameter_json['userId'] = tmpJSON['userId']; + base_parameter_json['sinal'] = tmpJSON['sinal']; + base_parameter_json['interpolacao'] = 'normal'; + base_parameter_json['movimentos'] = []; + movement_parameter_json = { + 'facial': {}, + 'mao_direita': {}, + 'mao_esquerda': {} + }; + base_parameter_json['movimentos'].push(movement_parameter_json); + } + + function _parseParameterValue(value) { + if (typeof value == 'string' && value.toLowerCase() == 'true') { + return true; + } else if (typeof value == 'string' && value.toLowerCase() == 'false') { + return false; + } else { + return !isNaN(value) ? parseInt(value) : value; + } + } + + function _parseTempFacialParameterJSON(tmpJSON) { + var attrs = dynworkflow.getFacialParameters(); + for (var i in attrs) { + var attr = attrs[i]; + parameterValue = tmpJSON['facial'][attr][0]; + movement_parameter_json['facial'][attr] = _parseParameterValue(parameterValue); + } + } + + function _parseHand(hand) { + var parsedHand = hand == 'right-hand' ? 'mao_direita' : hand; + parsedHand = hand == 'left-hand' ? 'mao_esquerda' : parsedHand; + return parsedHand; + } + + // Default parser + function _defaultMovementParser(tmpJSON, movementName, hand) { + var attrs = dynworkflow.getMovementParameters(movementName); + var parsedHand = _parseHand(hand); + + for (var i in attrs) { + var attr = attrs[i]; + var parameterValue = ''; + if (typeof tmpJSON[hand][attr] == "undefined") { + continue; + } + if (attr == 'configuracao') { + parameterValue = tmpJSON[hand][attr][1]; + } else if (attr == 'articulacao') { + parameterValue = articulation.processValue(hand, tmpJSON[hand][attr]); + } else { + parameterValue = tmpJSON[hand][attr][0]; + } + movement_parameter_json[parsedHand][movementName][attr] = + _parseParameterValue(parameterValue); + } + } + + function _retilinearMovementParser(tmpJSON, movementName, hand) { + var attrs = dynworkflow.getMovementParameters(movementName); + var parsedHand = _parseHand(hand); + + for (var i in attrs) { + var attr = attrs[i]; + var initParameterValue = ''; + var endParameterValue = ''; + if (attr == 'configuracao-retilineo') { + initParameterValue = tmpJSON[hand][attr][1]; + endParameterValue = tmpJSON[hand][attr][3]; + } else if (attr == 'articulacao-retilineo') { + initSlice = tmpJSON[hand][attr].slice(0, 2); + endSlice = tmpJSON[hand][attr].slice(2, 4); + initParameterValue = articulation.processValue(hand, initSlice); + endParameterValue = articulation.processValue(hand, endSlice); + } else { + initParameterValue = tmpJSON[hand][attr][0]; + endParameterValue = tmpJSON[hand][attr][1]; + } + attr = attr.replace('-retilineo', ''); + var initAttr = attr + '_inicial'; + var endAttr = attr + '_final'; + movement_parameter_json[parsedHand][movementName][initAttr] = + _parseParameterValue(initParameterValue); + movement_parameter_json[parsedHand][movementName][endAttr] = + _parseParameterValue(endParameterValue); + } + } + + function _parseTempMovementParameterJSON(tmpJSON, hand) { + var movimentConfig = tmpJSON[hand]['movimento']; + if (typeof movimentConfig == 'undefined') return; + + var movementName = movimentConfig[0]; + var parsedHand = _parseHand(hand); + movement_parameter_json[parsedHand][movementName] = {}; + + if (movementName == 'retilineo') { + _retilinearMovementParser(tmpJSON, movementName, hand); + } else { + _defaultMovementParser(tmpJSON, movementName, hand); + } + } + + tmpJSONParser.parse = function(tmpJSON, rightHand, leftHand) { + _setupBaseParameterJSON(tmpJSON); + _parseTempFacialParameterJSON(tmpJSON); + if (rightHand) { + _parseTempMovementParameterJSON(tmpJSON, 'right-hand'); + } + if (leftHand) { + _parseTempMovementParameterJSON(tmpJSON, 'left-hand'); + } + return base_parameter_json; + }; + +}(window.tmpJSONParser = window.tmpJSONParser || {}, jQuery)); diff --git a/view/assets/js/helpers/video-helper.js b/view/assets/js/helpers/video-helper.js new file mode 100644 index 0000000..00e31ce --- /dev/null +++ b/view/assets/js/helpers/video-helper.js @@ -0,0 +1,23 @@ +(function(videoHelper, $, undefined) { + + function _controlVideo(elId, toPlay) { + var videoSrc = $(elId).attr("src"); + if (typeof videoSrc == "undefined" || + (typeof videoSrc != "undefined" && videoSrc === "")) + return; + if (toPlay) { + $(elId).get(0).play(); + } else { + $(elId).get(0).pause(); + } + } + + videoHelper.play = function(elId) { + _controlVideo(elId, true); + } + + videoHelper.pause = function(elId) { + _controlVideo(elId, false); + } + +}(window.videoHelper = window.videoHelper || {}, jQuery)); diff --git a/view/assets/js/jquery.fileupload.js b/view/assets/js/jquery.fileupload.js deleted file mode 100755 index 91b7254..0000000 --- a/view/assets/js/jquery.fileupload.js +++ /dev/null @@ -1,1477 +0,0 @@ -/* - * jQuery File Upload Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, document, location, Blob, FormData */ - -(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'jquery.ui.widget' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./vendor/jquery.ui.widget') - ); - } else { - // Browser globals: - factory(window.jQuery); - } -}(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, - - // 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 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; - }; - } - }, - - _isInstanceOf: function (type, obj) { - // Cross-frame instanceof check - return Object.prototype.toString.call(obj) === '[object ' + type + ']'; - }, - - _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.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.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)) { - formData.append( - ($.type(options.paramName) === 'array' && - options.paramName[index]) || paramName, - file, - file.uploadName || file.name - ); - } - }); - } - } - 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])).pipe( - function () { - if (data.errorThrown) { - return $.Deferred() - .rejectWith(that, [data]).promise(); - } - return getPromise(arguments); - } - ).pipe(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 || 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 + 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; - // 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] - ); - }); - }; - 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._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.pipe(send); - } else { - this._sequence = this._sequence.pipe(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(), - 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); - }, - dirReader, entries = []; - 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 empy 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); - }) - ).pipe(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) - ).pipe(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'); - }, - - _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); - } - - }); - -})); diff --git a/view/assets/js/jquery.iframe-transport.js b/view/assets/js/jquery.iframe-transport.js deleted file mode 100755 index a7d34e0..0000000 --- a/view/assets/js/jquery.iframe-transport.js +++ /dev/null @@ -1,217 +0,0 @@ -/* - * jQuery Iframe Transport Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT - */ - -/* global define, require, window, document */ - -(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory(require('jquery')); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - // Helper variable to create unique names for the transport iframes: - var counter = 0; - - // The iframe transport accepts four additional options: - // options.fileInput: a jQuery collection of file input fields - // options.paramName: the parameter name for the file form data, - // overrides the name property of the file input field(s), - // can be a string or an array of strings. - // options.formData: an array of objects with name and value properties, - // equivalent to the return data of .serializeArray(), e.g.: - // [{name: 'a', value: 1}, {name: 'b', value: 2}] - // options.initialIframeSrc: the URL of the initial iframe src, - // by default set to "javascript:false;" - $.ajaxTransport('iframe', function (options) { - if (options.async) { - // javascript:false as initial iframe src - // prevents warning popups on HTTPS in IE6: - /*jshint scripturl: true */ - var initialIframeSrc = options.initialIframeSrc || 'javascript:false;', - /*jshint scripturl: false */ - form, - iframe, - addParamChar; - return { - send: function (_, completeCallback) { - form = $('
'); - form.attr('accept-charset', options.formAcceptCharset); - addParamChar = /\?/.test(options.url) ? '&' : '?'; - // XDomainRequest only supports GET and POST: - if (options.type === 'DELETE') { - options.url = options.url + addParamChar + '_method=DELETE'; - options.type = 'POST'; - } else if (options.type === 'PUT') { - options.url = options.url + addParamChar + '_method=PUT'; - options.type = 'POST'; - } else if (options.type === 'PATCH') { - options.url = options.url + addParamChar + '_method=PATCH'; - options.type = 'POST'; - } - // IE versions below IE8 cannot set the name property of - // elements that have already been added to the DOM, - // so we set the name along with the iframe HTML markup: - counter += 1; - iframe = $( - '' - ).bind('load', function () { - var fileInputClones, - paramNames = $.isArray(options.paramName) ? - options.paramName : [options.paramName]; - iframe - .unbind('load') - .bind('load', function () { - var response; - // Wrap in a try/catch block to catch exceptions thrown - // when trying to access cross-domain iframe contents: - try { - response = iframe.contents(); - // Google Chrome and Firefox do not throw an - // exception when calling iframe.contents() on - // cross-domain requests, so we unify the response: - if (!response.length || !response[0].firstChild) { - throw new Error(); - } - } catch (e) { - response = undefined; - } - // The complete callback returns the - // iframe content document as response object: - completeCallback( - 200, - 'success', - {'iframe': response} - ); - // Fix for IE endless progress bar activity bug - // (happens on form submits to iframe targets): - $('') - .appendTo(form); - window.setTimeout(function () { - // Removing the form in a setTimeout call - // allows Chrome's developer tools to display - // the response result - form.remove(); - }, 0); - }); - form - .prop('target', iframe.prop('name')) - .prop('action', options.url) - .prop('method', options.type); - if (options.formData) { - $.each(options.formData, function (index, field) { - $('') - .prop('name', field.name) - .val(field.value) - .appendTo(form); - }); - } - if (options.fileInput && options.fileInput.length && - options.type === 'POST') { - fileInputClones = options.fileInput.clone(); - // Insert a clone for each file input field: - options.fileInput.after(function (index) { - return fileInputClones[index]; - }); - if (options.paramName) { - options.fileInput.each(function (index) { - $(this).prop( - 'name', - paramNames[index] || options.paramName - ); - }); - } - // Appending the file input fields to the hidden form - // removes them from their original location: - form - .append(options.fileInput) - .prop('enctype', 'multipart/form-data') - // enctype must be set as encoding for IE: - .prop('encoding', 'multipart/form-data'); - // Remove the HTML5 form attribute from the input(s): - options.fileInput.removeAttr('form'); - } - form.submit(); - // Insert the file input fields at their original location - // by replacing the clones with the originals: - if (fileInputClones && fileInputClones.length) { - options.fileInput.each(function (index, input) { - var clone = $(fileInputClones[index]); - // Restore the original name and form properties: - $(input) - .prop('name', clone.prop('name')) - .attr('form', clone.attr('form')); - clone.replaceWith(input); - }); - } - }); - form.append(iframe).appendTo(document.body); - }, - abort: function () { - if (iframe) { - // javascript:false as iframe src aborts the request - // and prevents warning popups on HTTPS in IE6. - // concat is used to avoid the "Script URL" JSLint error: - iframe - .unbind('load') - .prop('src', initialIframeSrc); - } - if (form) { - form.remove(); - } - } - }; - } - }); - - // The iframe transport returns the iframe content document as response. - // The following adds converters from iframe to text, json, html, xml - // and script. - // Please note that the Content-Type for JSON responses has to be text/plain - // or text/html, if the browser doesn't include application/json in the - // Accept header, else IE will show a download dialog. - // The Content-Type for XML responses on the other hand has to be always - // application/xml or text/xml, so IE properly parses the XML response. - // See also - // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation - $.ajaxSetup({ - converters: { - 'iframe text': function (iframe) { - return iframe && $(iframe[0].body).text(); - }, - 'iframe json': function (iframe) { - return iframe && $.parseJSON($(iframe[0].body).text()); - }, - 'iframe html': function (iframe) { - return iframe && $(iframe[0].body).html(); - }, - 'iframe xml': function (iframe) { - var xmlDoc = iframe && iframe[0]; - return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc : - $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) || - $(xmlDoc.body).html()); - }, - 'iframe script': function (iframe) { - return iframe && $.globalEval($(iframe[0].body).text()); - } - } - }); - -})); diff --git a/view/assets/js/jquery.scrollTo.js b/view/assets/js/jquery.scrollTo.js deleted file mode 100644 index 7ba1776..0000000 --- a/view/assets/js/jquery.scrollTo.js +++ /dev/null @@ -1,210 +0,0 @@ -/*! - * jQuery.scrollTo - * Copyright (c) 2007-2015 Ariel Flesler - afleslergmailcom | http://flesler.blogspot.com - * Licensed under MIT - * http://flesler.blogspot.com/2007/10/jqueryscrollto.html - * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery - * @author Ariel Flesler - * @version 2.1.2 - */ -;(function(factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // AMD - define(['jquery'], factory); - } else if (typeof module !== 'undefined' && module.exports) { - // CommonJS - module.exports = factory(require('jquery')); - } else { - // Global - factory(jQuery); - } -})(function($) { - 'use strict'; - - var $scrollTo = $.scrollTo = function(target, duration, settings) { - return $(window).scrollTo(target, duration, settings); - }; - - $scrollTo.defaults = { - axis:'xy', - duration: 0, - limit:true - }; - - function isWin(elem) { - return !elem.nodeName || - $.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1; - } - - $.fn.scrollTo = function(target, duration, settings) { - if (typeof duration === 'object') { - settings = duration; - duration = 0; - } - if (typeof settings === 'function') { - settings = { onAfter:settings }; - } - if (target === 'max') { - target = 9e9; - } - - settings = $.extend({}, $scrollTo.defaults, settings); - // Speed is still recognized for backwards compatibility - duration = duration || settings.duration; - // Make sure the settings are given right - var queue = settings.queue && settings.axis.length > 1; - if (queue) { - // Let's keep the overall duration - duration /= 2; - } - settings.offset = both(settings.offset); - settings.over = both(settings.over); - - return this.each(function() { - // Null target yields nothing, just like jQuery does - if (target === null) return; - - var win = isWin(this), - elem = win ? this.contentWindow || window : this, - $elem = $(elem), - targ = target, - attr = {}, - toff; - - switch (typeof targ) { - // A number will pass the regex - case 'number': - case 'string': - if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) { - targ = both(targ); - // We are done - break; - } - // Relative/Absolute selector - targ = win ? $(targ) : $(targ, elem); - /* falls through */ - case 'object': - if (targ.length === 0) return; - // DOMElement / jQuery - if (targ.is || targ.style) { - // Get the real position of the target - toff = (targ = $(targ)).offset(); - } - } - - var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset; - - $.each(settings.axis.split(''), function(i, axis) { - var Pos = axis === 'x' ? 'Left' : 'Top', - pos = Pos.toLowerCase(), - key = 'scroll' + Pos, - prev = $elem[key](), - max = $scrollTo.max(elem, axis); - - if (toff) {// jQuery / DOMElement - attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]); - - // If it's a dom element, reduce the margin - if (settings.margin) { - attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0; - attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0; - } - - attr[key] += offset[pos] || 0; - - if (settings.over[pos]) { - // Scroll to a fraction of its width/height - attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos]; - } - } else { - var val = targ[pos]; - // Handle percentage values - attr[key] = val.slice && val.slice(-1) === '%' ? - parseFloat(val) / 100 * max - : val; - } - - // Number or 'number' - if (settings.limit && /^\d+$/.test(attr[key])) { - // Check the limits - attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max); - } - - // Don't waste time animating, if there's no need. - if (!i && settings.axis.length > 1) { - if (prev === attr[key]) { - // No animation needed - attr = {}; - } else if (queue) { - // Intermediate animation - animate(settings.onAfterFirst); - // Don't animate this axis again in the next iteration. - attr = {}; - } - } - }); - - animate(settings.onAfter); - - function animate(callback) { - var opts = $.extend({}, settings, { - // The queue setting conflicts with animate() - // Force it to always be true - queue: true, - duration: duration, - complete: callback && function() { - callback.call(elem, targ, settings); - } - }); - $elem.animate(attr, opts); - } - }); - }; - - // Max scrolling position, works on quirks mode - // It only fails (not too badly) on IE, quirks mode. - $scrollTo.max = function(elem, axis) { - var Dim = axis === 'x' ? 'Width' : 'Height', - scroll = 'scroll'+Dim; - - if (!isWin(elem)) - return elem[scroll] - $(elem)[Dim.toLowerCase()](); - - var size = 'client' + Dim, - doc = elem.ownerDocument || elem.document, - html = doc.documentElement, - body = doc.body; - - return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]); - }; - - function both(val) { - return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val }; - } - - // Add special hooks so that window scroll properties can be animated - $.Tween.propHooks.scrollLeft = - $.Tween.propHooks.scrollTop = { - get: function(t) { - return $(t.elem)[t.prop](); - }, - set: function(t) { - var curr = this.get(t); - // If interrupt is true and user scrolled, stop animating - if (t.options.interrupt && t._last && t._last !== curr) { - return $(t.elem).stop(); - } - var next = Math.round(t.now); - // Don't waste CPU - // Browsers don't render floating point scroll - if (curr !== next) { - $(t.elem)[t.prop](next); - t._last = this.get(t); - } - } - }; - - // AMD requirement - return $scrollTo; -}); diff --git a/view/assets/js/jquery.ui.widget.js b/view/assets/js/jquery.ui.widget.js deleted file mode 100755 index e08df3f..0000000 --- a/view/assets/js/jquery.ui.widget.js +++ /dev/null @@ -1,572 +0,0 @@ -/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28 -* http://jqueryui.com -* Includes: widget.js -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define([ "jquery" ], factory ); - - } else if ( typeof exports === "object" ) { - - // Node/CommonJS - factory( require( "jquery" ) ); - - } else { - - // Browser globals - factory( jQuery ); - } -}(function( $ ) { -/*! - * jQuery UI Widget 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/jQuery.widget/ - */ - - -var widget_uuid = 0, - widget_slice = Array.prototype.slice; - -$.cleanData = (function( orig ) { - return function( elems ) { - var events, elem, i; - for ( i = 0; (elem = elems[i]) != null; i++ ) { - try { - - // Only trigger remove when necessary to save time - events = $._data( elem, "events" ); - if ( events && events.remove ) { - $( elem ).triggerHandler( "remove" ); - } - - // http://bugs.jquery.com/ticket/8235 - } catch ( e ) {} - } - orig( elems ); - }; -})( $.cleanData ); - -$.widget = function( name, base, prototype ) { - var fullName, existingConstructor, constructor, basePrototype, - // proxiedPrototype allows the provided prototype to remain unmodified - // so that it can be used as a mixin for multiple widgets (#8876) - proxiedPrototype = {}, - namespace = name.split( "." )[ 0 ]; - - name = name.split( "." )[ 1 ]; - fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - // create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; - - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - // allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } - - // allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - // extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - // copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - // track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - }); - - basePrototype = new base(); - // we need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( !$.isFunction( value ) ) { - proxiedPrototype[ prop ] = value; - return; - } - proxiedPrototype[ prop ] = (function() { - var _super = function() { - return base.prototype[ prop ].apply( this, arguments ); - }, - _superApply = function( args ) { - return base.prototype[ prop ].apply( this, args ); - }; - return function() { - var __super = this._super, - __superApply = this._superApply, - returnValue; - - this._super = _super; - this._superApply = _superApply; - - returnValue = value.apply( this, arguments ); - - this._super = __super; - this._superApply = __superApply; - - return returnValue; - }; - })(); - }); - constructor.prototype = $.widget.extend( basePrototype, { - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name - }, proxiedPrototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - }); - - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; - - // redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); - }); - // remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } - - $.widget.bridge( name, constructor ); - - return constructor; -}; - -$.widget.extend = function( target ) { - var input = widget_slice.call( arguments, 1 ), - inputIndex = 0, - inputLength = input.length, - key, - value; - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; -}; - -$.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string", - args = widget_slice.call( arguments, 1 ), - returnValue = this; - - if ( isMethodCall ) { - this.each(function() { - var methodValue, - instance = $.data( this, fullName ); - if ( options === "instance" ) { - returnValue = instance; - return false; - } - if ( !instance ) { - return $.error( "cannot call methods on " + name + " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + " widget instance" ); - } - methodValue = instance[ options ].apply( instance, args ); - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - }); - } else { - - // Allow multiple hashes to be passed on init - if ( args.length ) { - options = $.widget.extend.apply( null, [ options ].concat(args) ); - } - - this.each(function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} ); - if ( instance._init ) { - instance._init(); - } - } else { - $.data( this, fullName, new object( options, this ) ); - } - }); - } - - return returnValue; - }; -}; - -$.Widget = function( /* options, element */ ) {}; -$.Widget._childConstructors = []; - -$.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "
", - options: { - disabled: false, - - // callbacks - create: null - }, - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = widget_uuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); - - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - }); - this.document = $( element.style ? - // element within the document - element.ownerDocument : - // element is window or document - element.document || element ); - this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); - } - - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); - - this._create(); - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - _getCreateOptions: $.noop, - _getCreateEventData: $.noop, - _create: $.noop, - _init: $.noop, - - destroy: function() { - this._destroy(); - // we can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .unbind( this.eventNamespace ) - .removeData( this.widgetFullName ) - // support: jquery <1.6.3 - // http://bugs.jquery.com/ticket/9413 - .removeData( $.camelCase( this.widgetFullName ) ); - this.widget() - .unbind( this.eventNamespace ) - .removeAttr( "aria-disabled" ) - .removeClass( - this.widgetFullName + "-disabled " + - "ui-state-disabled" ); - - // clean up events and states - this.bindings.unbind( this.eventNamespace ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - }, - _destroy: $.noop, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key, - parts, - curOption, - i; - - if ( arguments.length === 0 ) { - // don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } - - if ( typeof key === "string" ) { - // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( arguments.length === 1 ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( arguments.length === 1 ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } - - this._setOptions( options ); - - return this; - }, - _setOptions: function( options ) { - var key; - - for ( key in options ) { - this._setOption( key, options[ key ] ); - } - - return this; - }, - _setOption: function( key, value ) { - this.options[ key ] = value; - - if ( key === "disabled" ) { - this.widget() - .toggleClass( this.widgetFullName + "-disabled", !!value ); - - // If the widget is becoming disabled, then nothing is interactive - if ( value ) { - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - } - } - - return this; - }, - - enable: function() { - return this._setOptions({ disabled: false }); - }, - disable: function() { - return this._setOptions({ disabled: true }); - }, - - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement, - instance = this; - - // no suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } - - // no element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } - - $.each( handlers, function( event, handler ) { - function handlerProxy() { - // allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - - // copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } - - var match = event.match( /^([\w:-]*)\s*(.*)$/ ), - eventName = match[1] + instance.eventNamespace, - selector = match[2]; - if ( selector ) { - delegateElement.delegate( selector, eventName, handlerProxy ); - } else { - element.bind( eventName, handlerProxy ); - } - }); - }, - - _off: function( element, eventName ) { - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + - this.eventNamespace; - element.unbind( eventName ).undelegate( eventName ); - - // Clear the stack to avoid memory leaks (#10056) - this.bindings = $( this.bindings.not( element ).get() ); - this.focusable = $( this.focusable.not( element ).get() ); - this.hoverable = $( this.hoverable.not( element ).get() ); - }, - - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, - - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - $( event.currentTarget ).addClass( "ui-state-hover" ); - }, - mouseleave: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-hover" ); - } - }); - }, - - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - $( event.currentTarget ).addClass( "ui-state-focus" ); - }, - focusout: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-focus" ); - } - }); - }, - - _trigger: function( type, event, data ) { - var prop, orig, - callback = this.options[ type ]; - - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - // the original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; - - // copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } - - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[0], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } -}; - -$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - var hasOptions, - effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - if ( options.delay ) { - element.delay( options.delay ); - } - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue(function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - }); - } - }; -}); - -var widget = $.widget; - - - -})); diff --git a/view/assets/js/js.cookie.js b/view/assets/js/js.cookie.js deleted file mode 100644 index e808108..0000000 --- a/view/assets/js/js.cookie.js +++ /dev/null @@ -1,145 +0,0 @@ -/*! - * JavaScript Cookie v2.0.4 - * https://github.com/js-cookie/js-cookie - * - * Copyright 2006, 2015 Klaus Hartl & Fagner Brack - * Released under the MIT license - */ -(function(factory) { - if (typeof define === 'function' && define.amd) { - define(factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - var _OldCookies = window.Cookies; - var api = window.Cookies = factory(); - api.noConflict = function() { - window.Cookies = _OldCookies; - return api; - }; - } -}(function() { - function extend() { - var i = 0; - var result = {}; - for (; i < arguments.length; i++) { - var attributes = arguments[ i ]; - for (var key in attributes) { - result[key] = attributes[key]; - } - } - return result; - } - - function init(converter) { - function api(key, value, attributes) { - var result; - - // Write - - if (arguments.length > 1) { - attributes = extend({ - path: '/' - }, api.defaults, attributes); - - if (typeof attributes.expires === 'number') { - var expires = new Date(); - expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); - attributes.expires = expires; - } - - try { - result = JSON.stringify(value); - if (/^[\{\[]/.test(result)) { - value = result; - } - } catch (e) {} - - if (!converter.write) { - value = encodeURIComponent(String(value)) - .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); - } else { - value = converter.write(value, key); - } - - key = encodeURIComponent(String(key)); - key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); - key = key.replace(/[\(\)]/g, escape); - - return (document.cookie = [ - key, '=', value, - attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE - attributes.path && '; path=' + attributes.path, - attributes.domain && '; domain=' + attributes.domain, - attributes.secure ? '; secure' : '' - ].join('')); - } - - // Read - - if (!key) { - result = {}; - } - - // To prevent the for loop in the first place assign an empty array - // in case there are no cookies at all. Also prevents odd result when - // calling "get()" - var cookies = document.cookie ? document.cookie.split('; ') : []; - var rdecode = /(%[0-9A-Z]{2})+/g; - var i = 0; - - for (; i < cookies.length; i++) { - var parts = cookies[i].split('='); - var name = parts[0].replace(rdecode, decodeURIComponent); - var cookie = parts.slice(1).join('='); - - if (cookie.charAt(0) === '"') { - cookie = cookie.slice(1, -1); - } - - try { - cookie = converter.read ? - converter.read(cookie, name) : converter(cookie, name) || - cookie.replace(rdecode, decodeURIComponent); - - if (this.json) { - try { - cookie = JSON.parse(cookie); - } catch (e) {} - } - - if (key === name) { - result = cookie; - break; - } - - if (!key) { - result[name] = cookie; - } - } catch (e) {} - } - - return result; - } - - api.get = api.set = api; - api.getJSON = function() { - return api.apply({ - json: true - }, [].slice.call(arguments)); - }; - api.defaults = {}; - - api.remove = function(key, attributes) { - api(key, '', extend(attributes, { - expires: -1 - })); - }; - - api.withConverter = init; - - return api; - } - - return init(function() {}); -})); diff --git a/view/assets/js/movement.js b/view/assets/js/movement.js deleted file mode 100644 index bf77dc0..0000000 --- a/view/assets/js/movement.js +++ /dev/null @@ -1,24 +0,0 @@ -(function(movement, $, undefined) { - - movement.getPreviousSelectedMovement = function(mainConfig) { - return $('.selection-panel-body[mainConfig=' + mainConfig + - '][subConfig=movimento][step=1] .selection-panel-option[select=true]').attr('value'); - }; - - movement.setup = function(serverhost, hand) { - var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=movimento][step=1]'; - $(baseId + ' .selection-panel-option').off('click').on( - 'click', function() { - wikilibras.selectAnOption(baseId, this); - dynworkflow.selectMovement($(this).attr('value')); - }); - $(baseId + ' .video-panel-option').off('mouseenter').on('mouseenter', - function(event) { - $(this).addClass('video-panel-option-hover'); - }); - $(baseId + ' .video-panel-option').off('mouseleave').on('mouseleave', - function(event) { - $(this).removeClass('video-panel-option-hover'); - }); - }; -}(window.movement = window.movement || {}, jQuery)); diff --git a/view/assets/js/orientation.js b/view/assets/js/orientation.js deleted file mode 100644 index 9af260f..0000000 --- a/view/assets/js/orientation.js +++ /dev/null @@ -1,13 +0,0 @@ -(function(orientation, $, undefined) { - - orientation.setup = function(hand, subConfig, step) { - var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + - subConfig + '][step=' + step + ']'; - $(baseId + ' .selection-panel-option').off('click').on( - 'click', function() { - wikilibras.selectAnOption(baseId, this); - dynworkflow.userSelectedAnOption(); - }); - }; - -}(window.orientation = window.orientation || {}, jQuery)); diff --git a/view/assets/js/render-sign.js b/view/assets/js/render-sign.js new file mode 100644 index 0000000..be2e7a1 --- /dev/null +++ b/view/assets/js/render-sign.js @@ -0,0 +1,84 @@ +(function(renderSign, $, undefined) { + + var api_url = ''; + + function _submitParameterJSON(parsedParameterJSON, callback) { + console.log(parsedParameterJSON); + + $.ajax({ + type : 'POST', + url : api_url + '/sign', + data : JSON.stringify(parsedParameterJSON), + contentType : 'application/json', + success : function(response) { + console.log(response); + callback(parsedParameterJSON); + }, + error : function(xhr, textStatus, error) { + alert(xhr.responseText); + } + }); + } + + function _showRenderedAvatar(parameterJSON) { + var userId = parameterJSON['userId']; + var signName = parameterJSON['sinal']; + $("#render-avatar video").attr("src", + _getRenderedAvatarUrl(userId, signName)); + $("#render-avatar").fadeIn(300); + } + + function _showRenderScreen(toShow) { + if (toShow) { + $("#render-screen").fadeIn(300); + videoHelper.play("#render-ref video"); + videoHelper.play("#render-avatar video"); + } else { + $("#render-screen").hide(); + videoHelper.pause("#render-ref video"); + videoHelper.pause("#render-avatar video"); + } + } + + function _getRenderedAvatarUrl(userId, signName) { + return api_url + '/public/' + userId + '/' + signName + ".webm"; + } + + renderSign.showRenderedAvatar = function(parameterJSON) { + _showRenderedAvatar(parameterJSON); + _showRenderScreen(true); + } + + renderSign.showRenderScreen = function(toShow) { + _showRenderScreen(toShow); + } + + renderSign.getRenderedAvatarUrl = function(userId, signName) { + return _getRenderedAvatarUrl(userId, signName); + } + + renderSign.submit = function(parsedParameterJSON) { + configurationScreen.show(false); + _showRenderScreen(true); + $("#render-avatar").hide(); + $("#render-loading").fadeIn(300); + $("#render-button-container .btn").hide(); + $("#finish-button").addClass("disabled"); + $("#finish-button").show(); + + _submitParameterJSON(parsedParameterJSON, function(parsedParameterJSON) { + $("#render-loading").fadeOut(300); + $("#finish-button").removeClass("disabled"); + _showRenderedAvatar(parsedParameterJSON); + }); + }; + + renderSign.setup = function(apiUrl) { + api_url = apiUrl; + $("#render-edit").off("click").on("click", function() { + _showRenderScreen(false); + configurationScreen.show(true); + }); + } + +}(window.renderSign = window.renderSign || {}, jQuery)); diff --git a/view/assets/js/selection-panel/articulation.js b/view/assets/js/selection-panel/articulation.js new file mode 100644 index 0000000..cdefabd --- /dev/null +++ b/view/assets/js/selection-panel/articulation.js @@ -0,0 +1,143 @@ +(function(articulation, $, undefined) { + + var server_host = ''; + var MAX_COLUMNS = 14; + + function _updateASelector(container, ballSelector, step) { + var pointSelector = parseInt(step) == 2 ? 'A' : 'B'; + $(container + ' .ball-selector.active').each(function() { + $(this).removeClass('active'); + $(this).find('.point-selector').remove(); + }); + ballSelector.addClass('active'); + ballSelector.append('
'); + $(container + ' .selection-panel-option[select=true]').attr('select', + false); + $(ballSelector).attr('select', true); + } + + function _getSelectedY(hand, subConfig, step) { + step = parseInt(step) - 1; + var previousStepId = '.selection-panel-body[mainConfig=' + hand + + '][subConfig=' + subConfig + '][step=' + step + + '] .module-x-y'; + return $(previousStepId).attr('data-y'); + } + + function _setupModuleZ(hand, subConfig, step, selectedY) { + if (typeof selectedY == 'undefined' || selectedY == '') + return; + + var base_id = '.selection-panel-body[mainConfig=' + hand + + '][subConfig=' + subConfig + '][step=' + step + ']'; + var articulation_z = base_id + ' .module-z'; + $(articulation_z + ' .ball-selector').hide(); + $(articulation_z + ' .row-number-' + selectedY + ' .ball-selector') + .show(); + + var z = $(articulation_z).attr('data-z'); + if (typeof z != 'undefined') { + var ball_selector = $(articulation_z + ' .row-number-' + selectedY + + ' .ball-' + z); + _updateASelector(articulation_z, ball_selector, step); + } + } + + function _setupBallSelectorXY(hand, subConfig, step) { + var base_id = '.selection-panel-body[mainConfig=' + hand + + '][subConfig=' + subConfig + '][step=' + step + ']'; + var articulation_x_y = base_id + ' .module-x-y'; + $(articulation_x_y + ' .ball-selector') + .off('click') + .on( + 'click', + function(a) { + var b = $(a.target); + if (!b.hasClass('ball-selector')) { + dynworkflow.userSelectedAnOption(); + return; + } + var c = b.parent('.grid-row'), d = $(articulation_x_y), f = b + .attr('data-x'), g = c.attr('data-y'); + d.attr('data-x', f), d.attr('data-y', g); + + var nextStep = parseInt(step) + 1; + _updateASelector(articulation_x_y, b, nextStep); + _setupModuleZ(hand, subConfig, nextStep, g); + + wikilibras.updateTempParameterJSON(hand, subConfig, + step, f + ';' + g); + dynworkflow.userSelectedAnOption(); + }); + } + + function _setupBallSelectorZ(hand, subConfig, step) { + var base_id = '.selection-panel-body[mainConfig=' + hand + + '][subConfig=' + subConfig + '][step=' + step + ']'; + var articulation_z = base_id + ' .module-z'; + $(articulation_z + ' .ball-selector').off('click').on( + 'click', + function(a) { + var b = $(a.target); + if (!b.hasClass('ball-selector')) { + dynworkflow.userSelectedAnOption(); + return; + } + var c = b.parent('.grid-row'), e = $(articulation_z), h = b + .attr('data-z'); + b.attr('data-z') && e.attr('data-z', h), _updateASelector( + articulation_z, b, step); + + wikilibras + .updateTempParameterJSON(hand, subConfig, step, h); + dynworkflow.userSelectedAnOption(); + }); + } + + function _calculateArticulationPointIndex(hand, xValue, yValue, zValue) { + var x = xValue; + var y = yValue; + var z = zValue; + if (hand == 'left-hand') { + x = MAX_COLUMNS - x + 1; + } + + var value = (z - 1) * MAX_COLUMNS + x + 3 * MAX_COLUMNS * (y - 1); + //console.log(value); + return value; + } + + articulation.processValue = function(hand, selectionArray) { + var xyValueSplit = selectionArray[0].split(';'); + var xValue = parseInt(xyValueSplit[0]); + var yValue = parseInt(xyValueSplit[1]); + var zValue = parseInt(selectionArray[1]); + return _calculateArticulationPointIndex(hand, xValue, yValue, zValue); + }; + + articulation.setupModuleXY = function(serverhost, hand, subConfig, step) { + server_host = serverhost; + _setupBallSelectorXY(hand, subConfig, step); + }; + + articulation.setupModuleZ = function(serverhost, hand, subConfig, step) { + server_host = serverhost; + _setupBallSelectorZ(hand, subConfig, step); + + var selectedY = _getSelectedY(hand, subConfig, step); + _setupModuleZ(hand, subConfig, step, selectedY); + }; + + articulation.clean = function() { + $('.ball-selector.active').each(function() { + $(this).removeClass('active'); + $(this).find('.point-selector').remove(); + }); + $('.module-x-y').attr('data-x', ''); + $('.module-x-y').attr('data-y', ''); + $('.module-z').attr('data-z', ''); + } + +}(window.articulation = window.articulation || {}, jQuery)); diff --git a/view/assets/js/selection-panel/configuration.js b/view/assets/js/selection-panel/configuration.js new file mode 100644 index 0000000..8e0e3d0 --- /dev/null +++ b/view/assets/js/selection-panel/configuration.js @@ -0,0 +1,43 @@ +(function(configuration, $, undefined) { + + configuration.setupFingersGroup = function(hand, subConfig, step) { + var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + + subConfig + '][step=' + step + ']'; + $(baseId + ' .selection-panel-option' + ).off('click').on('click', function() { + selectionPanel.selectAnOption(baseId, this); + _setupFingersToShow(hand, subConfig, step); + + dynworkflow.userSelectedAnOption(); + }); + }; + + function _setupFingersToShow(hand, subConfig, step) { + var stepOneBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + + subConfig + '][step=' + step + ']'; + var nextStep = parseInt(step) + 1; + var stepTwoBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + + subConfig + '][step=' + nextStep + ']'; + + var finger_group = $(stepOneBaseId + ' .selection-panel-option[select=true]').attr('value'); + finger_group = typeof finger_group == 'undefined' ? '0' : finger_group; + + // clean next step + dynworkflow.cleanStep(hand, subConfig, nextStep); + $(stepTwoBaseId + ' .finger-group').hide(); + $(stepTwoBaseId + ' .finger-group[group=' + finger_group + ']').show(); + } + + configuration.setupFingersPosition = function(hand, subConfig, step) { + var stepTwoBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + + subConfig + '][step=' + step + ']'; + $(stepTwoBaseId + ' .selection-panel-option').off('click').on( + 'click', function() { + selectionPanel.selectAnOption(stepTwoBaseId, this); + dynworkflow.userSelectedAnOption(); + }); + var previousStep = parseInt(step) - 1; + _setupFingersToShow(hand, subConfig, previousStep); + }; + +}(window.configuration = window.configuration || {}, jQuery)); diff --git a/view/assets/js/selection-panel/default-configuration-handler.js b/view/assets/js/selection-panel/default-configuration-handler.js new file mode 100644 index 0000000..93c4283 --- /dev/null +++ b/view/assets/js/selection-panel/default-configuration-handler.js @@ -0,0 +1,27 @@ +(function(defaultConfigurationHandler, $, undefined) { + + defaultConfigurationHandler.setup = function(hand, subConfig, step) { + var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + + subConfig + '][step=' + step + ']'; + $(baseId + ' .selection-panel-option').off('click').on( + 'click', function() { + selectionPanel.selectAnOption(baseId, this); + dynworkflow.userSelectedAnOption(); + }); + }; + + function _startVideoLoop(hand, subConfig, step, timeBetweenLoops) { + setTimeout(function(){ + $('.selection-panel-body[mainConfig=' + hand + '][subConfig=' + + subConfig + '][step=' + step + '] video').each(function(){ + videoHelper.play(this); + }); + _startVideoLoop(hand, subConfig, step, timeBetweenLoops); + }, timeBetweenLoops); + } + + defaultConfigurationHandler.startVideoLoop = function(hand, subConfig, step, timeBetweenLoops) { + _startVideoLoop(hand, subConfig, step, timeBetweenLoops); + } + +}(window.defaultConfigurationHandler = window.defaultConfigurationHandler || {}, jQuery)); diff --git a/view/assets/js/selection-panel/dynamic-loading-engine.js b/view/assets/js/selection-panel/dynamic-loading-engine.js new file mode 100644 index 0000000..101c7f0 --- /dev/null +++ b/view/assets/js/selection-panel/dynamic-loading-engine.js @@ -0,0 +1,96 @@ +(function(dynengine, $, undefined) { + var setup = undefined; + + _preprocessHtml = function(data, url) { + var matchSubConfig = data.match(/sub(?:C|c)onfig="(.*?)"/); + var currentMainConfig = dynworkflow.getMainConfig(); // right-hand or left-hand + var goodData = data; + + var isRightHand = function(hand) { + return hand === 'right-hand'; + }; + + var replaceConfigurationTag = function(data, mainConfig) { + if (isRightHand(mainConfig)) { + return data.replace(/{{ configuracao }}/g, 'cmd'); + } else { + return data.replace(/{{ configuracao }}/g, 'cme'); + } + } + + var replaceOrientationTag = function(data, mainConfig) { + if (isRightHand(mainConfig)) { + return data.replace(/{{ orientacao }}/g, 'ord'); + } else { + return data.replace(/{{ orientacao }}/g, 'ore'); + } + } + + var replaceHandFolderTag = function(data, mainConfig) { + if (isRightHand(mainConfig)) { + return data.replace(/{{ hand-folder }}/g, 'md'); + } else { + return data.replace(/{{ hand-folder }}/g, 'me'); + } + } + + var replaceMovementNameTag = function(data, mainConfig) { + var selectedMovement = movement.getPreviousSelectedMovement(mainConfig); + if (typeof selectedMovement != "undefined") { + return data.replace(/{{ movement-name }}/g, selectedMovement); + } + return data + } + + if (matchSubConfig) { // case defined + // There is no specific(right or left hand dependent) assets for: articulacao, duracao, expressao, movimento, transicao + // Specific configurations: configuracao, orientacao + // possible values on the side as comment + var subConfig = matchSubConfig[1]; // articulacao | configuracao | duracao | expressao | movimento | orientacao | transicao + + // possible subconfigs that need changing + switch (subConfig) { + case 'configuracao': + goodData = replaceConfigurationTag(data, currentMainConfig); + break; + case 'configuracao-retilineo': + goodData = replaceConfigurationTag(data, currentMainConfig); + break; + case 'orientacao': + goodData = replaceOrientationTag(data, currentMainConfig); + break; + case 'orientacao-retilineo': + goodData = replaceOrientationTag(data, currentMainConfig); + break; + } + } + goodData = replaceHandFolderTag(goodData, currentMainConfig); + goodData = replaceMovementNameTag(goodData, currentMainConfig); + goodData = goodData.replace(/{{ hand }}/g, currentMainConfig); + return goodData.replace(/{{ server }}/g, url); + }; + + dynengine.render = function(serverUrl, templatePath, target, prepend, callback) { + var url = serverUrl + templatePath; + $.get(url, function(data) { + var processedHtml = _preprocessHtml(data, serverUrl); + if (prepend) { + $(target).prepend(processedHtml); + } else { + $(target).append(processedHtml); + } + }) + .done(function() { + callback && callback(); // call if defined + }); + }; + + dynengine.clean = function(target) { + $(target).html(''); + }; + + dynengine.load = function() { + var url = $('#server-url').data('url'); + }; + +}(window.dynengine = window.dynengine || {}, jQuery)); diff --git a/view/assets/js/selection-panel/dynamic-selection-workflow.js b/view/assets/js/selection-panel/dynamic-selection-workflow.js new file mode 100644 index 0000000..7ede68e --- /dev/null +++ b/view/assets/js/selection-panel/dynamic-selection-workflow.js @@ -0,0 +1,369 @@ +(function(dynworkflow, $, undefined) { + + // Workflow configuration + var jsonWF = {}; + var baseUrl = ''; + + // Main configurations: right-hand, left-hand and facial + var mainConfig = ''; + // The converted Main Config (right/left-hand) to hand for using the same configuration + var preprocessedMainConfig = ''; + // Subconfigurations: movimento, articulacao, configuracao, orientacao, etc + var currentSubconfig = ''; + var currentSubConfigName = ''; + var currentSubconfigParent = ''; + var currentStep = 0; + + function _preprocessMainConfig(config) { + config = config.replace('right-hand', 'hand'); + config = config.replace('left-hand', 'hand'); + return config; + } + + function _getFirstKey(json) { + var first_key = undefined; + for (first_key in json) + break; + return first_key; + } + + function _getAttributes(json) { + var result = []; + for (attr in json) { + result.push(attr); + } + return result; + } + + function _updateAndGetFirstMovementSubConfig() { + var selectedMovement = movement.getPreviousSelectedMovement(mainConfig); + if (typeof selectedMovement == 'undefined') + return -1; + + currentSubconfigParent = jsonWF[preprocessedMainConfig]['movimento'][selectedMovement]; + currentSubConfigName = _getFirstKey(currentSubconfigParent); + return currentSubConfigName; + } + + function _updateAndGetMovementConfig() { + currentSubconfigParent = jsonWF[preprocessedMainConfig]; + currentSubConfigName = _getFirstKey(currentSubconfigParent); + return currentSubConfigName; + } + + function _getNextSubConfig(toForward) { + var attrs = _getAttributes(currentSubconfigParent); + for (var i = 0; i < attrs.length; i++) { + if (toForward && attrs[i] == currentSubConfigName + && i < attrs.length - 1) { + return attrs[i + 1]; + } else if (!toForward && attrs[i] == currentSubConfigName && i >= 1) { + return attrs[i - 1]; + } + } + if (toForward && currentSubConfigName == 'movimento') { + return _updateAndGetFirstMovementSubConfig(); + } else if (!toForward && preprocessedMainConfig == 'hand') { + return _updateAndGetMovementConfig(); + } else if (!toForward) { + return currentSubConfigName; + } else { + return -1; + } + } + + function _showCurrentSubconfig() { + _showSubconfiguration(mainConfig, currentSubConfigName, currentStep); + } + + // It checks if a selection panel is already loaded + function _isSubconfigurationPanelLoaded(mainConfig, subConfig, stepNumber) { + var stepNumber = stepNumber + 1; + return $('.selection-panel-body[mainConfig=' + mainConfig + + '][subConfig=' + subConfig + '][step=' + stepNumber + ']').length > 0; + } + + function _showLoadedSubconfigurationPanel(mainConfig, subConfig, stepNumber) { + var stepNumber = stepNumber + 1; + return $( + '.selection-panel-body[mainConfig=' + mainConfig + + '][subConfig=' + subConfig + '][step=' + stepNumber + + ']').show(); + } + + // It renders or shows the requested selection panel + function _showSubconfiguration(mainConfig, subConfig, stepNumber) { + $('.selection-panel-body').hide(); + if (_isSubconfigurationPanelLoaded(mainConfig, subConfig, stepNumber)) { + _showLoadedSubconfigurationPanel(mainConfig, subConfig, stepNumber); + } else { + var step = currentSubconfig[stepNumber]; + step = typeof step == 'undefined' ? 'passo-1' : step; + dynengine.render(baseUrl, '/' + preprocessedMainConfig + '/' + + subConfig + '/' + step + '.html', '#selection-panel', + true); + } + _selectTimelineIcon(mainConfig, subConfig, true); + } + + function _selectSubConfig(subConfig) { + if (subConfig == 'movimento') { + _updateAndGetMovementConfig(); + } else if (currentSubConfigName == 'movimento') { + _updateAndGetFirstMovementSubConfig(); + } + currentSubConfigName = subConfig; + currentSubconfig = currentSubconfigParent[currentSubConfigName]; + currentStep = 0; + _showCurrentSubconfig(); + } + + // It shows the next selection panel on the workflow + function _showNextSubConfig() { + _walkOnTheWorkflow(true); + } + + function _showPreviousSubConfig() { + _walkOnTheWorkflow(false); + } + + function _walkOnTheWorkflow(toForward) { + currentStep = toForward ? currentStep + 1 : currentStep - 1; + + if (currentStep >= 0 && currentStep < currentSubconfig.length) { + _showCurrentSubconfig(); + } else { + var nextSubConfig = _getNextSubConfig(toForward); + if (nextSubConfig != -1) { + _selectSubConfig(nextSubConfig); + } else { + selectionPanel.hide(); + } + } + } + + function _checkIfFinished(mainConfig, currentSubConfigName) { + var numberOfSteps = currentSubconfig.length; + var completedSteps = $('.selection-panel-body[mainConfig=' + mainConfig + + '][subConfig=' + currentSubConfigName + + '] .selection-panel-option[select=true]').length; + return completedSteps != 0 && completedSteps == numberOfSteps; + } + + // A callback function to be called when the user selects a option on a panel + function _userSelectedAnOption() { + if (_checkIfFinished(mainConfig, currentSubConfigName)) { + _setupCheckIcon(mainConfig, currentSubConfigName); + } + _showNextSubConfig(); + } + + function _cleanStep(mainConfig, subConfig, step) { + var baseId = '.selection-panel-body[mainConfig=' + mainConfig + + '][subConfig=' + subConfig + '][step=' + step + ']'; + $(baseId + ' .selection-panel-option').removeAttr('select'); + var icon_id = '.subconfiguration-panel[mainConfig=' + mainConfig + + '] .icon_container[json_name=' + subConfig + ']'; + $(icon_id).removeAttr('complete'); + } + + // Timeline functions + function _selectTimelineIcon(mainConfig, subConfig) { + var baseId = '.subconfiguration-panel[mainConfig=' + mainConfig + + '] .subconfiguration-options'; + var iconContainer = '.icon_container[json_name=' + subConfig + ']'; + var iconId = baseId + ' ' + iconContainer; + + var previousSelected = $(baseId + ' .icon_container[select=true]') + .attr('json_name'); + if (typeof previousSelected != 'undefined') { + _deselectTimelineIcon(mainConfig, previousSelected); + } + + iconHelper.enableIconHover($(iconId), true); + $(iconId).attr('select', true); + $(baseId).scrollTo(iconContainer, { + 'offset' : -60, + 'duration' : 750 + }); + } + + function _deselectTimelineIcon(mainConfig, subConfig) { + var icon_id = '.subconfiguration-panel[mainConfig=' + mainConfig + + '] .icon_container[json_name=' + subConfig + ']'; + + if ($(icon_id + '[complete=true]').length > 0) { + _setupCheckIcon(mainConfig, subConfig); + } else { + iconHelper.enableIconHover($(icon_id), false); + $(icon_id).removeAttr('select'); + } + } + + function _setupCheckIcon(mainConfig, subConfig) { + var icon_id = $('.subconfiguration-panel[mainConfig=' + mainConfig + + '] .icon_container[json_name=' + subConfig + ']'); + iconHelper.enableIconCheck(icon_id, true); + $(icon_id).attr('complete', true); + $(icon_id).attr('select', false); + } + + function _isTimelineLoaded() { + return $('.subconfiguration-panel[mainConfig=' + mainConfig + ']').length > 0; + } + + function _setupTimelineListeners(timelineBaseId) { + $(timelineBaseId + ' .icon_container[json_name]').off('click').on( + 'click', function() { + var subConfig = $(this).attr('json_name'); + _selectSubConfig(subConfig); + }); + $(timelineBaseId + ' .icon_container[json_name]').off('mouseover').on( + 'mouseover', function() { + if (iconHelper.canHover(this)) { + iconHelper.enableIconHover(this, true); + } + }); + $(timelineBaseId + ' .icon_container[json_name]').off('mouseout').on( + 'mouseout', function() { + if (iconHelper.canHover(this)) { + iconHelper.enableIconHover(this, false); + } + }); + $(timelineBaseId + ' .arrow[name=right-arrow]').off('click').on( + 'click', function() { + _showNextSubConfig(); + }); + $(timelineBaseId + ' .arrow[name=left-arrow]').off('click').on('click', + function() { + _showPreviousSubConfig(); + }); + } + + function _setupTimelineIcons(timelineBaseId, toUpdate) { + if (!toUpdate) { + $(timelineBaseId).show(); + $(timelineBaseId + " .subconfiguration-options").scrollTo(0, 0); + return; + } + + $(timelineBaseId + ' .icon_container[json_name]').attr("active", + "false"); + for ( var name in currentSubconfigParent) { + $(timelineBaseId + ' .icon_container[json_name=' + name + ']') + .attr("active", "true"); + } + + if (preprocessedMainConfig == 'hand') { + $(timelineBaseId + ' .icon_container[json_name=movimento]').attr( + "active", "true"); + _setupCheckIcon(mainConfig, 'movimento'); + } + _selectTimelineIcon(mainConfig, currentSubConfigName); + _setupTimelineListeners(timelineBaseId); + $(timelineBaseId).show(); + } + + function _setupTimeline(toUpdate) { + var timelineBaseId = '.subconfiguration-panel[mainConfig=' + mainConfig + + ']'; + if (_isTimelineLoaded()) { + _setupTimelineIcons(timelineBaseId, toUpdate); + } else { + dynengine.render(baseUrl, '/' + preprocessedMainConfig + + '/timeline.html', '#selection-panel', false, function() { + _setupTimelineIcons(timelineBaseId, true); + }); + } + } + + function _initTimeline() { + if (preprocessedMainConfig != 'hand' || _isTimelineLoaded()) { + _setupTimeline(false); + } + } + + function _cleanTimeline() { + $(".subconfiguration-panel").remove(); + } + + function _cleanPreviousLoadedPanel() { + $('.selection-panel-body[mainConfig=' + mainConfig + ']').each( + function() { + var subConfigName = $(this).attr("subConfig"); + if (subConfigName.indexOf("articulacao") != -1 + || subConfigName.indexOf("configuracao") != -1 + || subConfigName.indexOf("orientacao") != -1 + || subConfigName.indexOf("movimento") != -1) { + return; + } + $( + '.selection-panel-body[mainConfig=' + mainConfig + + '][subConfig=' + subConfigName + ']') + .remove(); + }); + } + + // Public methods + dynworkflow.selectMainConfig = function(config) { + mainConfig = config; + preprocessedMainConfig = _preprocessMainConfig(mainConfig); + currentSubconfigParent = jsonWF[preprocessedMainConfig]; + currentSubConfigName = _getFirstKey(currentSubconfigParent); + currentSubconfig = currentSubconfigParent[currentSubConfigName]; + currentStep = 0; + + _showCurrentSubconfig(); + }; + + dynworkflow.selectMovement = function(movement) { + var subconfigJSON = currentSubconfig[movement]; + currentSubConfigName = _getFirstKey(subconfigJSON); + currentSubconfigParent = subconfigJSON; + currentSubconfig = subconfigJSON[currentSubConfigName]; + currentStep = 0; + + _cleanPreviousLoadedPanel(); + _showCurrentSubconfig(); + _setupTimeline(true); + }; + + dynworkflow.selectSubConfig = function(subConfig) { + _selectSubConfig(subConfig); + }; + + dynworkflow.userSelectedAnOption = function() { + _userSelectedAnOption(); + }; + + dynworkflow.cleanStep = function(mainConfig, subConfig, step) { + _cleanStep(mainConfig, subConfig, step); + }; + + dynworkflow.getFacialParameters = function() { + return _getAttributes(jsonWF['facial']); + }; + + dynworkflow.getMovementParameters = function(movementName) { + return _getAttributes(jsonWF['hand']['movimento'][movementName]); + }; + + dynworkflow.getMainConfig = function() { + return mainConfig; + }; + + dynworkflow.initTimeline = function() { + _initTimeline(); + }; + + dynworkflow.load = function() { + baseUrl = $('#server-url').data('url'); + $.get(baseUrl + '/conf/selection-workflow-json', function(result) { + jsonWF = $.parseJSON(result); + }).fail(function() { + console.log('Failed to load the workflow configuration'); + }); + _cleanTimeline(); + }; + +}(window.dynworkflow = window.dynworkflow || {}, jQuery)); diff --git a/view/assets/js/selection-panel/facial.js b/view/assets/js/selection-panel/facial.js new file mode 100644 index 0000000..0958ddb --- /dev/null +++ b/view/assets/js/selection-panel/facial.js @@ -0,0 +1,21 @@ +(function(facial, $, undefined) { + + facial.setup = function(subConfig) { + var baseId = '.selection-panel-body[mainConfig=facial][subConfig=' + + subConfig + ']'; + $(baseId + ' .selection-panel-option').off('click').on('click', + function() { + selectionPanel.selectAnOption(baseId, this); + dynworkflow.userSelectedAnOption(); + }); + $(baseId + ' .video-panel-option').off('mouseenter').on('mouseenter', + function(event) { + $(this).addClass('video-panel-option-hover'); + }); + $(baseId + ' .video-panel-option').off('mouseleave').on('mouseleave', + function(event) { + $(this).removeClass('video-panel-option-hover'); + }); + }; + +}(window.facial = window.facial || {}, jQuery)); diff --git a/view/assets/js/selection-panel/movement.js b/view/assets/js/selection-panel/movement.js new file mode 100644 index 0000000..6b5fd48 --- /dev/null +++ b/view/assets/js/selection-panel/movement.js @@ -0,0 +1,24 @@ +(function(movement, $, undefined) { + + movement.getPreviousSelectedMovement = function(mainConfig) { + return $('.selection-panel-body[mainConfig=' + mainConfig + + '][subConfig=movimento][step=1] .selection-panel-option[select=true]').attr('value'); + }; + + movement.setup = function(serverhost, hand) { + var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=movimento][step=1]'; + $(baseId + ' .selection-panel-option').off('click').on( + 'click', function() { + selectionPanel.selectAnOption(baseId, this); + dynworkflow.selectMovement($(this).attr('value')); + }); + $(baseId + ' .video-panel-option').off('mouseenter').on('mouseenter', + function(event) { + $(this).addClass('video-panel-option-hover'); + }); + $(baseId + ' .video-panel-option').off('mouseleave').on('mouseleave', + function(event) { + $(this).removeClass('video-panel-option-hover'); + }); + }; +}(window.movement = window.movement || {}, jQuery)); diff --git a/view/assets/js/selection-panel/orientation.js b/view/assets/js/selection-panel/orientation.js new file mode 100644 index 0000000..ed3da57 --- /dev/null +++ b/view/assets/js/selection-panel/orientation.js @@ -0,0 +1,13 @@ +(function(orientation, $, undefined) { + + orientation.setup = function(hand, subConfig, step) { + var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' + + subConfig + '][step=' + step + ']'; + $(baseId + ' .selection-panel-option').off('click').on( + 'click', function() { + selectionPanel.selectAnOption(baseId, this); + dynworkflow.userSelectedAnOption(); + }); + }; + +}(window.orientation = window.orientation || {}, jQuery)); diff --git a/view/assets/js/selection-panel/selection-panel.js b/view/assets/js/selection-panel/selection-panel.js new file mode 100644 index 0000000..cfcc8b1 --- /dev/null +++ b/view/assets/js/selection-panel/selection-panel.js @@ -0,0 +1,194 @@ +(function(selectionPanel, $, undefined) { + + function _selectAnOption(parentId, el) { + $(parentId + ' .selection-panel-option[select=true]').removeAttr( + 'select'); + $(el).attr('select', true); + + var mainConfig = $(parentId).attr('mainConfig'); + var subConfig = $(parentId).attr('subConfig'); + var step = $(parentId).attr('step'); + wikilibras.updateTempParameterJSON(mainConfig, subConfig, step, $(el).attr( + 'value')); + } + + function _canRenderSignVideo() { + return _isConfigurationComplete('facial') && + (_isConfigurationComplete('right-hand') || _isConfigurationComplete('left-hand')); + } + + function _isConfigurationComplete(config) { + var baseId = '.subconfiguration-panel[mainConfig=' + config + ']'; + var total_config = $(baseId + + ' .icon_container[json_name][active=true]').length; + var completed_config = $(baseId + + ' .icon_container[active=true][complete=true]').length; + return completed_config != 0 && total_config == completed_config; + } + + function _clearPreviousSelection() { + $('.selection-panel-body').hide(); + $('.subconfiguration-panel').hide(); + + if (configurationScreen.isMenuSelected()) { + var current_option = configurationScreen.getCurrentMainConfiguration(); + iconHelper.selectIcon(current_option, false); + if (_isConfigurationComplete(current_option)) { + iconHelper.setupCheckIcon(current_option, true); + } + $('#avatar-' + current_option).fadeOut(500); + } + } + + function _finishConfiguration(config, toFinish) { + iconHelper.setupCheckIcon(config, toFinish); + iconHelper.setupCheckIcon('avatar-' + config, toFinish); + + if (toFinish) { + $('#' + config + '-edit .check-icon').show(); + } else { + $('#' + config + '-edit .check-icon').hide(); + } + if (_canRenderSignVideo()) { + $('#ready-button').removeClass('disabled'); + } else { + $('#ready-button').addClass('disabled'); + } + } + + function _unfinishConfiguration(config, panel) { + iconHelper.setupCheckIcon(config, false, panel); + iconHelper.setupCheckIcon('avatar-' + config, false, panel); + $('#' + config + '-edit .check-icon').hide(); + + if (!_canRenderSignVideo()) { + $('#ready-button').addClass('disabled'); + } + } + + function _addZoomInToAvatar(option, callback) { + $('#avatar-default') + .fadeOut( + 500, + function() { + $('#avatar-container').removeClass('col-sm-7'); + $('#avatar-container').addClass('col-sm-5'); + $('#selection-container').removeClass('col-sm-2'); + $('#selection-container').addClass('col-sm-4'); + $('#avatar-container').removeClass( + 'avatar-container-zoom-out'); + $('#avatar-container').addClass( + 'avatar-container-zoom-in'); + $('#avatar-' + option).removeClass( + 'avatar-img-zoom-out'); + $('#avatar-' + option).fadeIn( + 500, + function() { + $('#avatar-' + option).addClass( + 'avatar-' + option + + '-img-zoom-in'); + callback(); + }); + }); + } + + function _addZoomOutToAvatar(option, callback) { + $('#avatar-' + option).fadeOut( + 500, + function() { + $('#selection-container').removeClass('col-sm-4'); + $('#selection-container').addClass('col-sm-2'); + $('#avatar-container').removeClass('col-sm-5'); + $('#avatar-container').addClass('col-sm-7'); + $('#avatar-container').removeClass( + 'avatar-container-zoom-in'); + $('#avatar-container') + .addClass('avatar-container-zoom-out'); + $('#avatar-default').fadeIn( + 500, + function() { + $('#avatar-' + option).removeClass( + 'avatar-' + option + '-img-zoom-in'); + $('#avatar-' + option).addClass( + 'avatar-img-zoom-out'); + callback(); + }); + }); + } + + function _hide() { + var config = configurationScreen.getCurrentMainConfiguration(); + if (config === '') return; + + iconHelper.deselectIcon(config); + if (_isConfigurationComplete(config)) { + _finishConfiguration(config, true); + } else { + _finishConfiguration(config, false); + } + + _addZoomOutToAvatar(config, function() { + $('#ready-button').fadeIn(300); + $('.edit-container').fadeIn(300); + }); + $('#selection-panel').fadeOut(300); + } + + function _setupGUIOnSelection(option, finishCallback) { + $('#ready-button').fadeOut(300); + $('.edit-container').fadeOut(300); + _addZoomInToAvatar(option, function() { + $('#selection-panel').fadeIn(300, function() { + finishCallback(); + }); + }); + } + + function _show(option) { + _clearPreviousSelection(); + iconHelper.selectIcon(option, true); + dynworkflow.selectMainConfig(option); + _setupGUIOnSelection(option, function() { + dynworkflow.initTimeline(); + }); + } + + selectionPanel.selectAnOption = function (parentId, el) { + _selectAnOption(parentId, el); + } + + selectionPanel.unfinishConfiguration = function(config, panel) { + return _unfinishConfiguration(config, panel); + } + + selectionPanel.isConfigurationComplete = function(config) { + return _isConfigurationComplete(config); + } + + selectionPanel.hide = function() { + return _hide(); + } + + selectionPanel.show = function(option) { + _show(option); + } + + selectionPanel.clean = function() { + articulation.clean(); + $(".selection-panel-option").removeAttr('select'); + $(".icon_container").removeAttr("select"); + $(".icon_container[complete=true]").each( + function() { + _unfinishConfiguration($(this).attr("name"), $(this).attr( + "panel")); + }); + } + + selectionPanel.setup = function(url) { + $('#selection-panel .x').off('click').on('click', function() { + _hide(); + }); + selectionPanel.clean(); + }; + +}(window.selectionPanel = window.selectionPanel || {}, jQuery)); diff --git a/view/assets/js/submit-sign.js b/view/assets/js/submit-sign.js index 6871b30..c8b200c 100644 --- a/view/assets/js/submit-sign.js +++ b/view/assets/js/submit-sign.js @@ -32,6 +32,11 @@ $('#upload-progress-container').hide(); $('#input-sign-upload').show(); } + + submitSign.show = function() { + $(".sub-main-container").hide(); + $("#submit-sign-container").show(); + } submitSign.setup = function(uploadSignHost) { submitUrl = uploadSignHost; diff --git a/view/assets/js/teached-signs.js b/view/assets/js/teached-signs.js index 14f4c66..25086ee 100644 --- a/view/assets/js/teached-signs.js +++ b/view/assets/js/teached-signs.js @@ -51,7 +51,7 @@ function _addSign(answer) { var signName = answer.parameter_json.sinal; var apiUserId = answer.parameter_json.userId; - var videoUrl = wikilibras.getRenderedAvatarUrl(apiUserId, signName); + var videoUrl = renderSign.getRenderedAvatarUrl(apiUserId, signName); $("#signs-list-container").append( '
0; - } - - function _isConfigurationComplete(config) { - var baseId = '.subconfiguration-panel[mainConfig=' + config + ']'; - var total_config = $(baseId - + ' .icon_container[json_name][active=true]').length; - var completed_config = $(baseId - + ' .icon_container[active=true][complete=true]').length; - return completed_config != 0 && total_config == completed_config; - } - - function _canHover(el) { - var incompleteConfig = typeof $(el).attr('complete') == 'undefined' - || $(el).attr('complete') == 'false'; - return (!_isSelectingState() && incompleteConfig) - || (typeof $(el).attr('select') == 'undefined' && incompleteConfig); - } - - function _getCurrentMainConfiguration() { - return _isSelectingState() ? $( - '#configuration-panel .icon_container[select=true]').attr( - 'name') : ''; - } - - function _addZoomInToAvatar(option, callback) { - $('#avatar-default') - .fadeOut( - 500, - function() { - $('#avatar-container').removeClass('col-sm-7'); - $('#avatar-container').addClass('col-sm-5'); - $('#selection-container').removeClass('col-sm-2'); - $('#selection-container').addClass('col-sm-4'); - $('#avatar-container').removeClass( - 'avatar-container-zoom-out'); - $('#avatar-container').addClass( - 'avatar-container-zoom-in'); - $('#avatar-' + option).removeClass( - 'avatar-img-zoom-out'); - $('#avatar-' + option).fadeIn( - 500, - function() { - $('#avatar-' + option).addClass( - 'avatar-' + option - + '-img-zoom-in'); - callback(); - }); - }); - } - - function _addZoomOutToAvatar(option, callback) { - $('#avatar-' + option).fadeOut( - 500, - function() { - $('#selection-container').removeClass('col-sm-4'); - $('#selection-container').addClass('col-sm-2'); - $('#avatar-container').removeClass('col-sm-5'); - $('#avatar-container').addClass('col-sm-7'); - $('#avatar-container').removeClass( - 'avatar-container-zoom-in'); - $('#avatar-container') - .addClass('avatar-container-zoom-out'); - $('#avatar-default').fadeIn( - 500, - function() { - $('#avatar-' + option).removeClass( - 'avatar-' + option + '-img-zoom-in'); - $('#avatar-' + option).addClass( - 'avatar-img-zoom-out'); - callback(); - }); - }); - } - - function _clearPreviousSelection() { - $('.selection-panel-body').hide(); - $('.subconfiguration-panel').hide(); - - if (_isSelectingState()) { - var current_option = _getCurrentMainConfiguration(); - _selectIcon(current_option, false); - if (_isConfigurationComplete(current_option)) { - _setupCheckIcon(current_option, true); - } - $('#avatar-' + current_option).fadeOut(500); - } - } - - function _showSelectionPanel(option) { - _clearPreviousSelection(); - _selectIcon(option, true); - dynworkflow.selectMainConfig(option); - _setupGUIOnSelection(option, function() { - dynworkflow.initTimeline(); - }); - } - - function _hideSelectionPanel() { - var config = _getCurrentMainConfiguration(); - _deselectIcon(config); - if (_isConfigurationComplete(config)) { - _finishConfiguration(config, true); - } else { - _finishConfiguration(config, false); - } - - _addZoomOutToAvatar(config, function() { - $('#ready-button').fadeIn(300); - $('.edit-container').fadeIn(300); - }); - $('#selection-panel').fadeOut(300); - } - - function _canRenderSignVideo() { - return _isConfigurationComplete('facial') - && (_isConfigurationComplete('right-hand') || _isConfigurationComplete('left-hand')); - } - - function _finishConfiguration(config, toFinish) { - _setupCheckIcon(config, toFinish); - _setupCheckIcon('avatar-' + config, toFinish); - - if (toFinish) { - $('#' + config + '-edit .check-icon').show(); - } else { - $('#' + config + '-edit .check-icon').hide(); - } - if (_canRenderSignVideo()) { - $('#ready-button').removeClass('disabled'); - } else { - $('#ready-button').addClass('disabled'); - } - } - - function _unfinishConfiguration(config, panel) { - _setupCheckIcon(config, false, panel); - _setupCheckIcon('avatar-' + config, false, panel); - $('#' + config + '-edit .check-icon').hide(); - - if (!_canRenderSignVideo()) { - $('#ready-button').addClass('disabled'); - } - } - - function _setupGUIOnSelection(option, finishCallback) { - $('#ready-button').fadeOut(300); - $('.edit-container').fadeOut(300); - _addZoomInToAvatar(option, function() { - $('#selection-panel').fadeIn(300, function() { - finishCallback(); - }); - }); - } - - function _setupConfigurationPanel() { - $('.icon_container').off('mouseover').on('mouseover', function() { - if (_canHover(this)) { - _enableIconHover(this, true); - } - }); - $('.icon_container').off('mouseout').on('mouseout', function() { - if (_canHover(this)) { - _enableIconHover(this, false); - } - }); - $('.config-panel-option').off('click').on('click', function() { - _showSelectionPanel($(this).attr('panel')); - }); - $('#minimize-icon-container').off('click').on('click', function() { - $('#ref-video-container').hide(); - $('#minimize-icon-container').hide(); - $('#maximize-icon-container').show(); - }); - $('#maximize-icon-container').off('click').on('click', function() { - $('#ref-video-container').show(); - $('#maximize-icon-container').hide(); - $('#minimize-icon-container').show(); - }); - } - function _updateTempParameterJSON(mainConfig, subConfig, step, value) { var subConfigJSON = tmpParameterJSON[mainConfig][subConfig]; if (typeof subConfigJSON == 'undefined') { @@ -275,132 +47,34 @@ subConfigJSON[parseInt(step) - 1] = value; } - function _selectAnOption(parentId, el) { - $(parentId + ' .selection-panel-option[select=true]').removeAttr( - 'select'); - $(el).attr('select', true); - - var mainConfig = $(parentId).attr('mainConfig'); - var subConfig = $(parentId).attr('subConfig'); - var step = $(parentId).attr('step'); - _updateTempParameterJSON(mainConfig, subConfig, step, $(el).attr( - 'value')); - } - - function _setupSelectionPanel() { - $('#selection-panel .x').off('click').on('click', function() { - _hideSelectionPanel(); - }); - } - - // Render Screen - function _submitParameterJSON(callback) { - parsedParameterJSON = tmpJSONParser.parse(tmpParameterJSON); - console.log(parsedParameterJSON); - - $.ajax({ - type : 'POST', - url : api_url + '/sign', - data : JSON.stringify(parsedParameterJSON), - contentType : 'application/json', - success : function(response) { - console.log(response); - callback(); - }, - error : function(xhr, textStatus, error) { - alert(xhr.responseText); - } - }); - } - - function _getRenderedAvatarUrl(userId, signName) { - return api_url + '/public/' + userId + '/' + signName + ".webm"; + function _parseTmpParameterJSON() { + parsedParameterJSON = tmpJSONParser.parse(tmpParameterJSON, + selectionPanel.isConfigurationComplete('right-hand'), + selectionPanel.isConfigurationComplete('left-hand')); + return parsedParameterJSON; } - function _showRenderedAvatar(parameterJSON) { - var userId = parameterJSON['userId']; - var signName = parameterJSON['sinal']; - $("#render-avatar video").attr("src", - _getRenderedAvatarUrl(userId, signName)); - $("#render-avatar").fadeIn(300); - } - - function _controlVideo(elId, toPlay) { - var videoSrc = $(elId).attr("src"); - if (typeof videoSrc == "undefined" || - (typeof videoSrc != "undefined" && videoSrc === "")) - return; - if (toPlay) { - $(elId).get(0).play(); - } else { - $(elId).get(0).pause(); - } - } - - function _playVideo(elId) { - _controlVideo(elId, true); - } - - function _pauseVideo(elId) { - _controlVideo(elId, false); - } - function _showInitialScreen(toShow) { if (toShow) { $("#initial-screen").fadeIn(300); - _playVideo("#initial-screen video"); + videoHelper.play("#initial-screen video"); } else { $("#initial-screen").hide(); - _pauseVideo("#initial-screen video"); + videoHelper.pause("#initial-screen video"); } } - function _showConfigurationScreen(toShow) { + function _showApprovalScreen(toShow, parameterJSON) { if (toShow) { - $("#configuration-screen").show(); - _playVideo("#ref-video-container video"); + $("#render-button-container .btn").hide(); + $("#approval-button").show(); + $("#approval-msg").show(); + renderSign.showRenderedAvatar(parameterJSON); } else { - $("#configuration-screen").hide(); - _pauseVideo("#ref-video-container video"); + $("#approval-button").hide(); + $("#approval-msg").hide(); } } - - function _showRenderScreen(toShow) { - if (toShow) { - $("#render-screen").fadeIn(300); - _playVideo("#render-ref video"); - _playVideo("#render-avatar video"); - } else { - $("#render-screen").hide(); - _pauseVideo("#render-ref video"); - _pauseVideo("#render-avatar video"); - } - } - - function _setupRenderScreen() { - _showConfigurationScreen(false); - _showRenderScreen(true); - $("#render-avatar").hide(); - $("#render-loading").fadeIn(300); - $("#render-button-container .btn").hide(); - $("#finish-button").addClass("disabled"); - $("#finish-button").show(); - - _submitParameterJSON(function() { - $("#render-loading").fadeOut(300); - $("#finish-button").removeClass("disabled"); - _showRenderedAvatar(parsedParameterJSON); - }); - } - - function _setupApprovalScreen(parameterJSON) { - $("#render-button-container .btn").hide(); - $("#approval-button").show(); - $("#approval-msg").show(); - - _showRenderedAvatar(parameterJSON); - _showRenderScreen(true); - } function _submitAnswer(task, deferred, status) { var answer = _createAnswer(task, status); @@ -409,44 +83,29 @@ } else { _saveAnswer(task, deferred, answer); } - _showRenderScreen(false); + renderSign.showRenderScreen(false); $("#thanks-screen").show(); } - function _clearGUI() { - articulation.clean(); - $(".selection-panel-option").removeAttr('select'); - $(".icon_container").removeAttr("select"); - $(".icon_container[complete=true]").each( - function() { - _unfinishConfiguration($(this).attr("name"), $(this).attr( - "panel")); - }); - } - function _setupMainScreen(task, deferred) { var last_answer = task.info.last_answer; var hasLastAnswer = typeof last_answer != "undefined"; if (hasLastAnswer) { - _setupApprovalScreen(last_answer.parameter_json); + _showApprovalScreen(true, last_answer.parameter_json); } else { + _showApprovalScreen(false); _showInitialScreen(true); } - $("#start-button").off("click").on("click", function() { _showInitialScreen(false); - _showConfigurationScreen(true); + configurationScreen.show(true); }); $("#ready-button").off("click").on("click", function() { if ($(this).hasClass('disabled')) { event.preventDefault(); return; } - _setupRenderScreen(); - }); - $("#render-edit").off("click").on("click", function() { - _showRenderScreen(false); - _showConfigurationScreen(true); + renderSign.submit(_parseTmpParameterJSON()); }); $("#finish-button").off("click").on("click", function() { if ($(this).hasClass('disabled')) { @@ -461,9 +120,7 @@ } function _setupGUI(task, deferred) { - _clearGUI(); - _setupConfigurationPanel(); - _setupSelectionPanel(); + configurationScreen.setup(); _setupMainScreen(task, deferred); } @@ -532,10 +189,12 @@ } function _loadMainComponents() { + iconHelper.setup(base_url); dynengine.load(); dynworkflow.load(); submitSign.setup(upload_signs_url); teachedSigns.setup(); + renderSign.setup(api_url); _setupLoginContainer(); } @@ -572,45 +231,11 @@ _updateTempParameterJSON(mainConfig, subConfig, step, value); } - wikilibras.hideSelectionPanel = function() { - _hideSelectionPanel(); - } - - wikilibras.selectAnOption = function(parentId, el) { - _selectAnOption(parentId, el); - } - - wikilibras.enableIconCheck = function(container, isHover) { - _enableIconCheck(container, isHover); - } - - wikilibras.canHover = function(container) { - return _canHover(container); - } - - wikilibras.enableIconHover = function(container, isHover) { - _enableIconHover(container, isHover); - } - - wikilibras.getRenderedAvatarUrl = function(userId, signName) { - return _getRenderedAvatarUrl(userId, signName); - } - wikilibras.showTeachContainer = function() { $(".sub-main-container").hide(); $("#teach-container").show(); } - wikilibras.showSubmitSignContainer = function() { - $(".sub-main-container").hide(); - $("#submit-sign-container").show(); - } - - wikilibras.showTeachedSignsContainer = function() { - $(".sub-main-container").hide(); - $("#teached-signs-container").show(); - } - wikilibras.showTutorialContainer = function() { $(".sub-main-container").hide(); $("#tutorial-container").show(); diff --git a/view/template.html b/view/template.html index 9884cbf..89a8f5a 100755 --- a/view/template.html +++ b/view/template.html @@ -23,9 +23,9 @@
  • Ensinar
  • Enviar sinal
  • + onclick="submitSign.show()">Enviar sinal
  • Sinais + onclick="teachedSigns.show()">Sinais ensinados
  • Tutorial
  • @@ -76,21 +76,21 @@
    -
    -
    +
    Expressão + class="configuration-menu-label">Expressão
    -
    Mão direita + class="configuration-menu-label">Mão direita
    -
    Mão esquerda + class="configuration-menu-label">Mão esquerda
    @@ -98,38 +98,38 @@ class="col-sm-7 avatar-container-zoom-out">
    -
    -
    -
    @@ -328,23 +328,33 @@
    - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + +