Commit bd5123efcee6e52d5183ff0276274005e0c88d82

Authored by Adabriand Furtado
1 parent e8e3a9d2
Exists in master

Refat. do wikilibras.js - criação do módulo de ícones, de menu de conf., de seleção e de render.

Showing 38 changed files with 4003 additions and 3904 deletions   Show diff stats
view/assets/css/main.css
@@ -254,7 +254,7 @@ body { @@ -254,7 +254,7 @@ body {
254 } 254 }
255 255
256 /* Configuration Panel */ 256 /* Configuration Panel */
257 -#configuration-panel { 257 +#configuration-menu {
258 background-color: #556575; 258 background-color: #556575;
259 border-style: solid; 259 border-style: solid;
260 border-color: #9cbfe3; 260 border-color: #9cbfe3;
@@ -263,7 +263,7 @@ body { @@ -263,7 +263,7 @@ body {
263 padding: 10px 10px 5px 5px; 263 padding: 10px 10px 5px 5px;
264 } 264 }
265 265
266 -.configuration-panel-label { 266 +.configuration-menu-label {
267 color: #FFFFFF; 267 color: #FFFFFF;
268 font-family: 'Titillium Web', sans-serif; 268 font-family: 'Titillium Web', sans-serif;
269 font-size: 14px; 269 font-size: 14px;
view/assets/js/articulation.js
@@ -1,143 +0,0 @@ @@ -1,143 +0,0 @@
1 -(function(articulation, $, undefined) {  
2 -  
3 - var server_host = '';  
4 - var MAX_COLUMNS = 14;  
5 -  
6 - function _updateASelector(container, ballSelector, step) {  
7 - var pointSelector = parseInt(step) == 2 ? 'A' : 'B';  
8 - $(container + ' .ball-selector.active').each(function() {  
9 - $(this).removeClass('active');  
10 - $(this).find('.point-selector').remove();  
11 - });  
12 - ballSelector.addClass('active');  
13 - ballSelector.append('<div class="point-selector"><img src="'  
14 - + server_host + '/img/pa/' + pointSelector  
15 - + '-Seletor.png" class="point-selector" alt=""></div>');  
16 - $(container + ' .selection-panel-option[select=true]').attr('select',  
17 - false);  
18 - $(ballSelector).attr('select', true);  
19 - }  
20 -  
21 - function _getSelectedY(hand, subConfig, step) {  
22 - step = parseInt(step) - 1;  
23 - var previousStepId = '.selection-panel-body[mainConfig=' + hand  
24 - + '][subConfig=' + subConfig + '][step=' + step  
25 - + '] .module-x-y';  
26 - return $(previousStepId).attr('data-y');  
27 - }  
28 -  
29 - function _setupModuleZ(hand, subConfig, step, selectedY) {  
30 - if (typeof selectedY == 'undefined' || selectedY == '')  
31 - return;  
32 -  
33 - var base_id = '.selection-panel-body[mainConfig=' + hand  
34 - + '][subConfig=' + subConfig + '][step=' + step + ']';  
35 - var articulation_z = base_id + ' .module-z';  
36 - $(articulation_z + ' .ball-selector').hide();  
37 - $(articulation_z + ' .row-number-' + selectedY + ' .ball-selector')  
38 - .show();  
39 -  
40 - var z = $(articulation_z).attr('data-z');  
41 - if (typeof z != 'undefined') {  
42 - var ball_selector = $(articulation_z + ' .row-number-' + selectedY  
43 - + ' .ball-' + z);  
44 - _updateASelector(articulation_z, ball_selector, step);  
45 - }  
46 - }  
47 -  
48 - function _setupBallSelectorXY(hand, subConfig, step) {  
49 - var base_id = '.selection-panel-body[mainConfig=' + hand  
50 - + '][subConfig=' + subConfig + '][step=' + step + ']';  
51 - var articulation_x_y = base_id + ' .module-x-y';  
52 - $(articulation_x_y + ' .ball-selector')  
53 - .off('click')  
54 - .on(  
55 - 'click',  
56 - function(a) {  
57 - var b = $(a.target);  
58 - if (!b.hasClass('ball-selector')) {  
59 - dynworkflow.userSelectedAnOption();  
60 - return;  
61 - }  
62 - var c = b.parent('.grid-row'), d = $(articulation_x_y), f = b  
63 - .attr('data-x'), g = c.attr('data-y');  
64 - d.attr('data-x', f), d.attr('data-y', g);  
65 -  
66 - var nextStep = parseInt(step) + 1;  
67 - _updateASelector(articulation_x_y, b, nextStep);  
68 - _setupModuleZ(hand, subConfig, nextStep, g);  
69 -  
70 - wikilibras.updateTempParameterJSON(hand, subConfig,  
71 - step, f + ';' + g);  
72 - dynworkflow.userSelectedAnOption();  
73 - });  
74 - }  
75 -  
76 - function _setupBallSelectorZ(hand, subConfig, step) {  
77 - var base_id = '.selection-panel-body[mainConfig=' + hand  
78 - + '][subConfig=' + subConfig + '][step=' + step + ']';  
79 - var articulation_z = base_id + ' .module-z';  
80 - $(articulation_z + ' .ball-selector').off('click').on(  
81 - 'click',  
82 - function(a) {  
83 - var b = $(a.target);  
84 - if (!b.hasClass('ball-selector')) {  
85 - dynworkflow.userSelectedAnOption();  
86 - return;  
87 - }  
88 - var c = b.parent('.grid-row'), e = $(articulation_z), h = b  
89 - .attr('data-z');  
90 - b.attr('data-z') && e.attr('data-z', h), _updateASelector(  
91 - articulation_z, b, step);  
92 -  
93 - wikilibras  
94 - .updateTempParameterJSON(hand, subConfig, step, h);  
95 - dynworkflow.userSelectedAnOption();  
96 - });  
97 - }  
98 -  
99 - function _calculateArticulationPointIndex(hand, xValue, yValue, zValue) {  
100 - var x = xValue;  
101 - var y = yValue;  
102 - var z = zValue;  
103 - if (hand == 'left-hand') {  
104 - x = MAX_COLUMNS - x + 1;  
105 - }  
106 -  
107 - var value = (z - 1) * MAX_COLUMNS + x + 3 * MAX_COLUMNS * (y - 1);  
108 - //console.log(value);  
109 - return value;  
110 - }  
111 -  
112 - articulation.processValue = function(hand, selectionArray) {  
113 - var xyValueSplit = selectionArray[0].split(';');  
114 - var xValue = parseInt(xyValueSplit[0]);  
115 - var yValue = parseInt(xyValueSplit[1]);  
116 - var zValue = parseInt(selectionArray[1]);  
117 - return _calculateArticulationPointIndex(hand, xValue, yValue, zValue);  
118 - };  
119 -  
120 - articulation.setupModuleXY = function(serverhost, hand, subConfig, step) {  
121 - server_host = serverhost;  
122 - _setupBallSelectorXY(hand, subConfig, step);  
123 - };  
124 -  
125 - articulation.setupModuleZ = function(serverhost, hand, subConfig, step) {  
126 - server_host = serverhost;  
127 - _setupBallSelectorZ(hand, subConfig, step);  
128 -  
129 - var selectedY = _getSelectedY(hand, subConfig, step);  
130 - _setupModuleZ(hand, subConfig, step, selectedY);  
131 - };  
132 -  
133 - articulation.clean = function() {  
134 - $('.ball-selector.active').each(function() {  
135 - $(this).removeClass('active');  
136 - $(this).find('.point-selector').remove();  
137 - });  
138 - $('.module-x-y').attr('data-x', '');  
139 - $('.module-x-y').attr('data-y', '');  
140 - $('.module-z').attr('data-z', '');  
141 - }  
142 -  
143 -}(window.articulation = window.articulation || {}, jQuery));  
view/assets/js/configuration-screen.js 0 → 100644
@@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
  1 +(function(configurationScreen, $, undefined) {
  2 +
  3 + function _isMenuSelected() {
  4 + return $('#configuration-menu .icon_container[select=true]').length > 0;
  5 + }
  6 +
  7 + function _getCurrentMainConfiguration() {
  8 + return _isMenuSelected() ? $(
  9 + '#configuration-menu .icon_container[select=true]').attr(
  10 + 'name') : '';
  11 + }
  12 +
  13 + configurationScreen.isMenuSelected = function() {
  14 + return _isMenuSelected();
  15 + }
  16 +
  17 + configurationScreen.getCurrentMainConfiguration = function() {
  18 + return _getCurrentMainConfiguration();
  19 + }
  20 +
  21 + configurationScreen.setup = function() {
  22 + $('.icon_container').off('mouseover').on('mouseover', function() {
  23 + if (iconHelper.canHover(this)) {
  24 + iconHelper.enableIconHover(this, true);
  25 + }
  26 + });
  27 + $('.icon_container').off('mouseout').on('mouseout', function() {
  28 + if (iconHelper.canHover(this)) {
  29 + iconHelper.enableIconHover(this, false);
  30 + }
  31 + });
  32 + $('.config-menu-option').off('click').on('click', function() {
  33 + selectionPanel.show($(this).attr('panel'));
  34 + });
  35 + $('#minimize-icon-container').off('click').on('click', function() {
  36 + $('#ref-video-container').hide();
  37 + $('#minimize-icon-container').hide();
  38 + $('#maximize-icon-container').show();
  39 + });
  40 + $('#maximize-icon-container').off('click').on('click', function() {
  41 + $('#ref-video-container').show();
  42 + $('#maximize-icon-container').hide();
  43 + $('#minimize-icon-container').show();
  44 + });
  45 + selectionPanel.setup();
  46 + };
  47 +
  48 + function _showConfigurationScreen(toShow) {
  49 + if (toShow) {
  50 + $("#configuration-screen").show();
  51 + videoHelper.play("#ref-video-container video");
  52 + } else {
  53 + $("#configuration-screen").hide();
  54 + videoHelper.pause("#ref-video-container video");
  55 + }
  56 + }
  57 +
  58 + configurationScreen.show = function(toShow) {
  59 + _showConfigurationScreen(toShow);
  60 + }
  61 +
  62 +}(window.configurationScreen = window.configurationScreen || {}, jQuery));
view/assets/js/configuration.js
@@ -1,43 +0,0 @@ @@ -1,43 +0,0 @@
1 -(function(configuration, $, undefined) {  
2 -  
3 - configuration.setupFingersGroup = function(hand, subConfig, step) {  
4 - var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +  
5 - subConfig + '][step=' + step + ']';  
6 - $(baseId + ' .selection-panel-option'  
7 - ).off('click').on('click', function() {  
8 - wikilibras.selectAnOption(baseId, this);  
9 - _setupFingersToShow(hand, subConfig, step);  
10 -  
11 - dynworkflow.userSelectedAnOption();  
12 - });  
13 - };  
14 -  
15 - function _setupFingersToShow(hand, subConfig, step) {  
16 - var stepOneBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +  
17 - subConfig + '][step=' + step + ']';  
18 - var nextStep = parseInt(step) + 1;  
19 - var stepTwoBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +  
20 - subConfig + '][step=' + nextStep + ']';  
21 -  
22 - var finger_group = $(stepOneBaseId + ' .selection-panel-option[select=true]').attr('value');  
23 - finger_group = typeof finger_group == 'undefined' ? '0' : finger_group;  
24 -  
25 - // clean next step  
26 - dynworkflow.cleanStep(hand, subConfig, nextStep);  
27 - $(stepTwoBaseId + ' .finger-group').hide();  
28 - $(stepTwoBaseId + ' .finger-group[group=' + finger_group + ']').show();  
29 - }  
30 -  
31 - configuration.setupFingersPosition = function(hand, subConfig, step) {  
32 - var stepTwoBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +  
33 - subConfig + '][step=' + step + ']';  
34 - $(stepTwoBaseId + ' .selection-panel-option').off('click').on(  
35 - 'click', function() {  
36 - wikilibras.selectAnOption(stepTwoBaseId, this);  
37 - dynworkflow.userSelectedAnOption();  
38 - });  
39 - var previousStep = parseInt(step) - 1;  
40 - _setupFingersToShow(hand, subConfig, previousStep);  
41 - };  
42 -  
43 -}(window.configuration = window.configuration || {}, jQuery));  
view/assets/js/defaultConfigurationHandler.js
@@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
1 -(function(defaultConfigurationHandler, $, undefined) {  
2 -  
3 - defaultConfigurationHandler.setup = function(hand, subConfig, step) {  
4 - var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +  
5 - subConfig + '][step=' + step + ']';  
6 - $(baseId + ' .selection-panel-option').off('click').on(  
7 - 'click', function() {  
8 - wikilibras.selectAnOption(baseId, this);  
9 - dynworkflow.userSelectedAnOption();  
10 - });  
11 - };  
12 -  
13 - function _startVideoLoop(hand, subConfig, step, timeBetweenLoops) {  
14 - setTimeout(function(){  
15 - $('.selection-panel-body[mainConfig=' + hand + '][subConfig=' +  
16 - subConfig + '][step=' + step + '] video').each(function(){  
17 - $(this).get(0).play();  
18 - });  
19 - _startVideoLoop(hand, subConfig, step, timeBetweenLoops);  
20 - }, timeBetweenLoops);  
21 - }  
22 -  
23 - defaultConfigurationHandler.startVideoLoop = function(hand, subConfig, step, timeBetweenLoops) {  
24 - _startVideoLoop(hand, subConfig, step, timeBetweenLoops);  
25 - }  
26 -  
27 -}(window.defaultConfigurationHandler = window.defaultConfigurationHandler || {}, jQuery));  
view/assets/js/dynamic-loading-engine.js
@@ -1,96 +0,0 @@ @@ -1,96 +0,0 @@
1 -(function(dynengine, $, undefined) {  
2 - var setup = undefined;  
3 -  
4 - _preprocessHtml = function(data, url) {  
5 - var matchSubConfig = data.match(/sub(?:C|c)onfig="(.*?)"/);  
6 - var currentMainConfig = dynworkflow.getMainConfig(); // right-hand or left-hand  
7 - var goodData = data;  
8 -  
9 - var isRightHand = function(hand) {  
10 - return hand === 'right-hand';  
11 - };  
12 -  
13 - var replaceConfigurationTag = function(data, mainConfig) {  
14 - if (isRightHand(mainConfig)) {  
15 - return data.replace(/{{ configuracao }}/g, 'cmd');  
16 - } else {  
17 - return data.replace(/{{ configuracao }}/g, 'cme');  
18 - }  
19 - }  
20 -  
21 - var replaceOrientationTag = function(data, mainConfig) {  
22 - if (isRightHand(mainConfig)) {  
23 - return data.replace(/{{ orientacao }}/g, 'ord');  
24 - } else {  
25 - return data.replace(/{{ orientacao }}/g, 'ore');  
26 - }  
27 - }  
28 -  
29 - var replaceHandFolderTag = function(data, mainConfig) {  
30 - if (isRightHand(mainConfig)) {  
31 - return data.replace(/{{ hand-folder }}/g, 'md');  
32 - } else {  
33 - return data.replace(/{{ hand-folder }}/g, 'me');  
34 - }  
35 - }  
36 -  
37 - var replaceMovementNameTag = function(data, mainConfig) {  
38 - var selectedMovement = movement.getPreviousSelectedMovement(mainConfig);  
39 - if (typeof selectedMovement != "undefined") {  
40 - return data.replace(/{{ movement-name }}/g, selectedMovement);  
41 - }  
42 - return data  
43 - }  
44 -  
45 - if (matchSubConfig) { // case defined  
46 - // There is no specific(right or left hand dependent) assets for: articulacao, duracao, expressao, movimento, transicao  
47 - // Specific configurations: configuracao, orientacao  
48 - // possible values on the side as comment  
49 - var subConfig = matchSubConfig[1]; // articulacao | configuracao | duracao | expressao | movimento | orientacao | transicao  
50 -  
51 - // possible subconfigs that need changing  
52 - switch (subConfig) {  
53 - case 'configuracao':  
54 - goodData = replaceConfigurationTag(data, currentMainConfig);  
55 - break;  
56 - case 'configuracao-retilineo':  
57 - goodData = replaceConfigurationTag(data, currentMainConfig);  
58 - break;  
59 - case 'orientacao':  
60 - goodData = replaceOrientationTag(data, currentMainConfig);  
61 - break;  
62 - case 'orientacao-retilineo':  
63 - goodData = replaceOrientationTag(data, currentMainConfig);  
64 - break;  
65 - }  
66 - }  
67 - goodData = replaceHandFolderTag(goodData, currentMainConfig);  
68 - goodData = replaceMovementNameTag(goodData, currentMainConfig);  
69 - goodData = goodData.replace(/{{ hand }}/g, currentMainConfig);  
70 - return goodData.replace(/{{ server }}/g, url);  
71 - };  
72 -  
73 - dynengine.render = function(serverUrl, templatePath, target, prepend, callback) {  
74 - var url = serverUrl + templatePath;  
75 - $.get(url, function(data) {  
76 - var processedHtml = _preprocessHtml(data, serverUrl);  
77 - if (prepend) {  
78 - $(target).prepend(processedHtml);  
79 - } else {  
80 - $(target).append(processedHtml);  
81 - }  
82 - })  
83 - .done(function() {  
84 - callback && callback(); // call if defined  
85 - });  
86 - };  
87 -  
88 - dynengine.clean = function(target) {  
89 - $(target).html('');  
90 - };  
91 -  
92 - dynengine.load = function() {  
93 - var url = $('#server-url').data('url');  
94 - };  
95 -  
96 -}(window.dynengine = window.dynengine || {}, jQuery));  
view/assets/js/dynamic-selection-workflow.js
@@ -1,369 +0,0 @@ @@ -1,369 +0,0 @@
1 -(function(dynworkflow, $, undefined) {  
2 -  
3 - // Workflow configuration  
4 - var jsonWF = {};  
5 - var baseUrl = '';  
6 -  
7 - // Main configurations: right-hand, left-hand and facial  
8 - var mainConfig = '';  
9 - // The converted Main Config (right/left-hand) to hand for using the same configuration  
10 - var preprocessedMainConfig = '';  
11 - // Subconfigurations: movimento, articulacao, configuracao, orientacao, etc  
12 - var currentSubconfig = '';  
13 - var currentSubConfigName = '';  
14 - var currentSubconfigParent = '';  
15 - var currentStep = 0;  
16 -  
17 - function _preprocessMainConfig(config) {  
18 - config = config.replace('right-hand', 'hand');  
19 - config = config.replace('left-hand', 'hand');  
20 - return config;  
21 - }  
22 -  
23 - function _getFirstKey(json) {  
24 - var first_key = undefined;  
25 - for (first_key in json)  
26 - break;  
27 - return first_key;  
28 - }  
29 -  
30 - function _getAttributes(json) {  
31 - var result = [];  
32 - for (attr in json) {  
33 - result.push(attr);  
34 - }  
35 - return result;  
36 - }  
37 -  
38 - function _updateAndGetFirstMovementSubConfig() {  
39 - var selectedMovement = movement.getPreviousSelectedMovement(mainConfig);  
40 - if (typeof selectedMovement == 'undefined')  
41 - return -1;  
42 -  
43 - currentSubconfigParent = jsonWF[preprocessedMainConfig]['movimento'][selectedMovement];  
44 - currentSubConfigName = _getFirstKey(currentSubconfigParent);  
45 - return currentSubConfigName;  
46 - }  
47 -  
48 - function _updateAndGetMovementConfig() {  
49 - currentSubconfigParent = jsonWF[preprocessedMainConfig];  
50 - currentSubConfigName = _getFirstKey(currentSubconfigParent);  
51 - return currentSubConfigName;  
52 - }  
53 -  
54 - function _getNextSubConfig(toForward) {  
55 - var attrs = _getAttributes(currentSubconfigParent);  
56 - for (var i = 0; i < attrs.length; i++) {  
57 - if (toForward && attrs[i] == currentSubConfigName  
58 - && i < attrs.length - 1) {  
59 - return attrs[i + 1];  
60 - } else if (!toForward && attrs[i] == currentSubConfigName && i >= 1) {  
61 - return attrs[i - 1];  
62 - }  
63 - }  
64 - if (toForward && currentSubConfigName == 'movimento') {  
65 - return _updateAndGetFirstMovementSubConfig();  
66 - } else if (!toForward && preprocessedMainConfig == 'hand') {  
67 - return _updateAndGetMovementConfig();  
68 - } else if (!toForward) {  
69 - return currentSubConfigName;  
70 - } else {  
71 - return -1;  
72 - }  
73 - }  
74 -  
75 - function _showCurrentSubconfig() {  
76 - _showSubconfiguration(mainConfig, currentSubConfigName, currentStep);  
77 - }  
78 -  
79 - // It checks if a selection panel is already loaded  
80 - function _isSubconfigurationPanelLoaded(mainConfig, subConfig, stepNumber) {  
81 - var stepNumber = stepNumber + 1;  
82 - return $('.selection-panel-body[mainConfig=' + mainConfig  
83 - + '][subConfig=' + subConfig + '][step=' + stepNumber + ']').length > 0;  
84 - }  
85 -  
86 - function _showLoadedSubconfigurationPanel(mainConfig, subConfig, stepNumber) {  
87 - var stepNumber = stepNumber + 1;  
88 - return $(  
89 - '.selection-panel-body[mainConfig=' + mainConfig  
90 - + '][subConfig=' + subConfig + '][step=' + stepNumber  
91 - + ']').show();  
92 - }  
93 -  
94 - // It renders or shows the requested selection panel  
95 - function _showSubconfiguration(mainConfig, subConfig, stepNumber) {  
96 - $('.selection-panel-body').hide();  
97 - if (_isSubconfigurationPanelLoaded(mainConfig, subConfig, stepNumber)) {  
98 - _showLoadedSubconfigurationPanel(mainConfig, subConfig, stepNumber);  
99 - } else {  
100 - var step = currentSubconfig[stepNumber];  
101 - step = typeof step == 'undefined' ? 'passo-1' : step;  
102 - dynengine.render(baseUrl, '/' + preprocessedMainConfig + '/'  
103 - + subConfig + '/' + step + '.html', '#selection-panel',  
104 - true);  
105 - }  
106 - _selectTimelineIcon(mainConfig, subConfig, true);  
107 - }  
108 -  
109 - function _selectSubConfig(subConfig) {  
110 - if (subConfig == 'movimento') {  
111 - _updateAndGetMovementConfig();  
112 - } else if (currentSubConfigName == 'movimento') {  
113 - _updateAndGetFirstMovementSubConfig();  
114 - }  
115 - currentSubConfigName = subConfig;  
116 - currentSubconfig = currentSubconfigParent[currentSubConfigName];  
117 - currentStep = 0;  
118 - _showCurrentSubconfig();  
119 - }  
120 -  
121 - // It shows the next selection panel on the workflow  
122 - function _showNextSubConfig() {  
123 - _walkOnTheWorkflow(true);  
124 - }  
125 -  
126 - function _showPreviousSubConfig() {  
127 - _walkOnTheWorkflow(false);  
128 - }  
129 -  
130 - function _walkOnTheWorkflow(toForward) {  
131 - currentStep = toForward ? currentStep + 1 : currentStep - 1;  
132 -  
133 - if (currentStep >= 0 && currentStep < currentSubconfig.length) {  
134 - _showCurrentSubconfig();  
135 - } else {  
136 - var nextSubConfig = _getNextSubConfig(toForward);  
137 - if (nextSubConfig != -1) {  
138 - _selectSubConfig(nextSubConfig);  
139 - } else {  
140 - wikilibras.hideSelectionPanel();  
141 - }  
142 - }  
143 - }  
144 -  
145 - function _checkIfFinished(mainConfig, currentSubConfigName) {  
146 - var numberOfSteps = currentSubconfig.length;  
147 - var completedSteps = $('.selection-panel-body[mainConfig=' + mainConfig  
148 - + '][subConfig=' + currentSubConfigName  
149 - + '] .selection-panel-option[select=true]').length;  
150 - return completedSteps != 0 && completedSteps == numberOfSteps;  
151 - }  
152 -  
153 - // A callback function to be called when the user selects a option on a panel  
154 - function _userSelectedAnOption() {  
155 - if (_checkIfFinished(mainConfig, currentSubConfigName)) {  
156 - _setupCheckIcon(mainConfig, currentSubConfigName);  
157 - }  
158 - _showNextSubConfig();  
159 - }  
160 -  
161 - function _cleanStep(mainConfig, subConfig, step) {  
162 - var baseId = '.selection-panel-body[mainConfig=' + mainConfig  
163 - + '][subConfig=' + subConfig + '][step=' + step + ']';  
164 - $(baseId + ' .selection-panel-option').removeAttr('select');  
165 - var icon_id = '.subconfiguration-panel[mainConfig=' + mainConfig  
166 - + '] .icon_container[json_name=' + subConfig + ']';  
167 - $(icon_id).removeAttr('complete');  
168 - }  
169 -  
170 - // Timeline functions  
171 - function _selectTimelineIcon(mainConfig, subConfig) {  
172 - var baseId = '.subconfiguration-panel[mainConfig=' + mainConfig  
173 - + '] .subconfiguration-options';  
174 - var iconContainer = '.icon_container[json_name=' + subConfig + ']';  
175 - var iconId = baseId + ' ' + iconContainer;  
176 -  
177 - var previousSelected = $(baseId + ' .icon_container[select=true]')  
178 - .attr('json_name');  
179 - if (typeof previousSelected != 'undefined') {  
180 - _deselectTimelineIcon(mainConfig, previousSelected);  
181 - }  
182 -  
183 - wikilibras.enableIconHover($(iconId), true);  
184 - $(iconId).attr('select', true);  
185 - $(baseId).scrollTo(iconContainer, {  
186 - 'offset' : -60,  
187 - 'duration' : 750  
188 - });  
189 - }  
190 -  
191 - function _deselectTimelineIcon(mainConfig, subConfig) {  
192 - var icon_id = '.subconfiguration-panel[mainConfig=' + mainConfig  
193 - + '] .icon_container[json_name=' + subConfig + ']';  
194 -  
195 - if ($(icon_id + '[complete=true]').length > 0) {  
196 - _setupCheckIcon(mainConfig, subConfig);  
197 - } else {  
198 - wikilibras.enableIconHover($(icon_id), false);  
199 - $(icon_id).removeAttr('select');  
200 - }  
201 - }  
202 -  
203 - function _setupCheckIcon(mainConfig, subConfig) {  
204 - var icon_id = $('.subconfiguration-panel[mainConfig=' + mainConfig  
205 - + '] .icon_container[json_name=' + subConfig + ']');  
206 - wikilibras.enableIconCheck(icon_id, true);  
207 - $(icon_id).attr('complete', true);  
208 - $(icon_id).attr('select', false);  
209 - }  
210 -  
211 - function _isTimelineLoaded() {  
212 - return $('.subconfiguration-panel[mainConfig=' + mainConfig + ']').length > 0;  
213 - }  
214 -  
215 - function _setupTimelineListeners(timelineBaseId) {  
216 - $(timelineBaseId + ' .icon_container[json_name]').off('click').on(  
217 - 'click', function() {  
218 - var subConfig = $(this).attr('json_name');  
219 - _selectSubConfig(subConfig);  
220 - });  
221 - $(timelineBaseId + ' .icon_container[json_name]').off('mouseover').on(  
222 - 'mouseover', function() {  
223 - if (wikilibras.canHover(this)) {  
224 - wikilibras.enableIconHover(this, true);  
225 - }  
226 - });  
227 - $(timelineBaseId + ' .icon_container[json_name]').off('mouseout').on(  
228 - 'mouseout', function() {  
229 - if (wikilibras.canHover(this)) {  
230 - wikilibras.enableIconHover(this, false);  
231 - }  
232 - });  
233 - $(timelineBaseId + ' .arrow[name=right-arrow]').off('click').on(  
234 - 'click', function() {  
235 - _showNextSubConfig();  
236 - });  
237 - $(timelineBaseId + ' .arrow[name=left-arrow]').off('click').on('click',  
238 - function() {  
239 - _showPreviousSubConfig();  
240 - });  
241 - }  
242 -  
243 - function _setupTimelineIcons(timelineBaseId, toUpdate) {  
244 - if (!toUpdate) {  
245 - $(timelineBaseId).show();  
246 - $(timelineBaseId + " .subconfiguration-options").scrollTo(0, 0);  
247 - return;  
248 - }  
249 -  
250 - $(timelineBaseId + ' .icon_container[json_name]').attr("active",  
251 - "false");  
252 - for ( var name in currentSubconfigParent) {  
253 - $(timelineBaseId + ' .icon_container[json_name=' + name + ']')  
254 - .attr("active", "true");  
255 - }  
256 -  
257 - if (preprocessedMainConfig == 'hand') {  
258 - $(timelineBaseId + ' .icon_container[json_name=movimento]').attr(  
259 - "active", "true");  
260 - _setupCheckIcon(mainConfig, 'movimento');  
261 - }  
262 - _selectTimelineIcon(mainConfig, currentSubConfigName);  
263 - _setupTimelineListeners(timelineBaseId);  
264 - $(timelineBaseId).show();  
265 - }  
266 -  
267 - function _setupTimeline(toUpdate) {  
268 - var timelineBaseId = '.subconfiguration-panel[mainConfig=' + mainConfig  
269 - + ']';  
270 - if (_isTimelineLoaded()) {  
271 - _setupTimelineIcons(timelineBaseId, toUpdate);  
272 - } else {  
273 - dynengine.render(baseUrl, '/' + preprocessedMainConfig  
274 - + '/timeline.html', '#selection-panel', false, function() {  
275 - _setupTimelineIcons(timelineBaseId, true);  
276 - });  
277 - }  
278 - }  
279 -  
280 - function _initTimeline() {  
281 - if (preprocessedMainConfig != 'hand' || _isTimelineLoaded()) {  
282 - _setupTimeline(false);  
283 - }  
284 - }  
285 -  
286 - function _cleanTimeline() {  
287 - $(".subconfiguration-panel").remove();  
288 - }  
289 -  
290 - function _cleanPreviousLoadedPanel() {  
291 - $('.selection-panel-body[mainConfig=' + mainConfig + ']').each(  
292 - function() {  
293 - var subConfigName = $(this).attr("subConfig");  
294 - if (subConfigName.indexOf("articulacao") != -1  
295 - || subConfigName.indexOf("configuracao") != -1  
296 - || subConfigName.indexOf("orientacao") != -1  
297 - || subConfigName.indexOf("movimento") != -1) {  
298 - return;  
299 - }  
300 - $(  
301 - '.selection-panel-body[mainConfig=' + mainConfig  
302 - + '][subConfig=' + subConfigName + ']')  
303 - .remove();  
304 - });  
305 - }  
306 -  
307 - // Public methods  
308 - dynworkflow.selectMainConfig = function(config) {  
309 - mainConfig = config;  
310 - preprocessedMainConfig = _preprocessMainConfig(mainConfig);  
311 - currentSubconfigParent = jsonWF[preprocessedMainConfig];  
312 - currentSubConfigName = _getFirstKey(currentSubconfigParent);  
313 - currentSubconfig = currentSubconfigParent[currentSubConfigName];  
314 - currentStep = 0;  
315 -  
316 - _showCurrentSubconfig();  
317 - };  
318 -  
319 - dynworkflow.selectMovement = function(movement) {  
320 - var subconfigJSON = currentSubconfig[movement];  
321 - currentSubConfigName = _getFirstKey(subconfigJSON);  
322 - currentSubconfigParent = subconfigJSON;  
323 - currentSubconfig = subconfigJSON[currentSubConfigName];  
324 - currentStep = 0;  
325 -  
326 - _cleanPreviousLoadedPanel();  
327 - _showCurrentSubconfig();  
328 - _setupTimeline(true);  
329 - };  
330 -  
331 - dynworkflow.selectSubConfig = function(subConfig) {  
332 - _selectSubConfig(subConfig);  
333 - };  
334 -  
335 - dynworkflow.userSelectedAnOption = function() {  
336 - _userSelectedAnOption();  
337 - };  
338 -  
339 - dynworkflow.cleanStep = function(mainConfig, subConfig, step) {  
340 - _cleanStep(mainConfig, subConfig, step);  
341 - };  
342 -  
343 - dynworkflow.getFacialParameters = function() {  
344 - return _getAttributes(jsonWF['facial']);  
345 - };  
346 -  
347 - dynworkflow.getMovementParameters = function(movementName) {  
348 - return _getAttributes(jsonWF['hand']['movimento'][movementName]);  
349 - };  
350 -  
351 - dynworkflow.getMainConfig = function() {  
352 - return mainConfig;  
353 - };  
354 -  
355 - dynworkflow.initTimeline = function() {  
356 - _initTimeline();  
357 - };  
358 -  
359 - dynworkflow.load = function() {  
360 - baseUrl = $('#server-url').data('url');  
361 - $.get(baseUrl + '/conf/selection-workflow-json', function(result) {  
362 - jsonWF = $.parseJSON(result);  
363 - }).fail(function() {  
364 - console.log('Failed to load the workflow configuration');  
365 - });  
366 - _cleanTimeline();  
367 - };  
368 -  
369 -}(window.dynworkflow = window.dynworkflow || {}, jQuery));  
view/assets/js/external-libs/jquery.fileupload.js 0 → 100755
@@ -0,0 +1,1477 @@ @@ -0,0 +1,1477 @@
  1 +/*
  2 + * jQuery File Upload Plugin
  3 + * https://github.com/blueimp/jQuery-File-Upload
  4 + *
  5 + * Copyright 2010, Sebastian Tschan
  6 + * https://blueimp.net
  7 + *
  8 + * Licensed under the MIT license:
  9 + * http://www.opensource.org/licenses/MIT
  10 + */
  11 +
  12 +/* jshint nomen:false */
  13 +/* global define, require, window, document, location, Blob, FormData */
  14 +
  15 +(function (factory) {
  16 + 'use strict';
  17 + if (typeof define === 'function' && define.amd) {
  18 + // Register as an anonymous AMD module:
  19 + define([
  20 + 'jquery',
  21 + 'jquery.ui.widget'
  22 + ], factory);
  23 + } else if (typeof exports === 'object') {
  24 + // Node/CommonJS:
  25 + factory(
  26 + require('jquery'),
  27 + require('./vendor/jquery.ui.widget')
  28 + );
  29 + } else {
  30 + // Browser globals:
  31 + factory(window.jQuery);
  32 + }
  33 +}(function ($) {
  34 + 'use strict';
  35 +
  36 + // Detect file input support, based on
  37 + // http://viljamis.com/blog/2012/file-upload-support-on-mobile/
  38 + $.support.fileInput = !(new RegExp(
  39 + // Handle devices which give false positives for the feature detection:
  40 + '(Android (1\\.[0156]|2\\.[01]))' +
  41 + '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' +
  42 + '|(w(eb)?OSBrowser)|(webOS)' +
  43 + '|(Kindle/(1\\.0|2\\.[05]|3\\.0))'
  44 + ).test(window.navigator.userAgent) ||
  45 + // Feature detection for all other devices:
  46 + $('<input type="file">').prop('disabled'));
  47 +
  48 + // The FileReader API is not actually used, but works as feature detection,
  49 + // as some Safari versions (5?) support XHR file uploads via the FormData API,
  50 + // but not non-multipart XHR file uploads.
  51 + // window.XMLHttpRequestUpload is not available on IE10, so we check for
  52 + // window.ProgressEvent instead to detect XHR2 file upload capability:
  53 + $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader);
  54 + $.support.xhrFormDataFileUpload = !!window.FormData;
  55 +
  56 + // Detect support for Blob slicing (required for chunked uploads):
  57 + $.support.blobSlice = window.Blob && (Blob.prototype.slice ||
  58 + Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
  59 +
  60 + // Helper function to create drag handlers for dragover/dragenter/dragleave:
  61 + function getDragHandler(type) {
  62 + var isDragOver = type === 'dragover';
  63 + return function (e) {
  64 + e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
  65 + var dataTransfer = e.dataTransfer;
  66 + if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 &&
  67 + this._trigger(
  68 + type,
  69 + $.Event(type, {delegatedEvent: e})
  70 + ) !== false) {
  71 + e.preventDefault();
  72 + if (isDragOver) {
  73 + dataTransfer.dropEffect = 'copy';
  74 + }
  75 + }
  76 + };
  77 + }
  78 +
  79 + // The fileupload widget listens for change events on file input fields defined
  80 + // via fileInput setting and paste or drop events of the given dropZone.
  81 + // In addition to the default jQuery Widget methods, the fileupload widget
  82 + // exposes the "add" and "send" methods, to add or directly send files using
  83 + // the fileupload API.
  84 + // By default, files added via file input selection, paste, drag & drop or
  85 + // "add" method are uploaded immediately, but it is possible to override
  86 + // the "add" callback option to queue file uploads.
  87 + $.widget('blueimp.fileupload', {
  88 +
  89 + options: {
  90 + // The drop target element(s), by the default the complete document.
  91 + // Set to null to disable drag & drop support:
  92 + dropZone: $(document),
  93 + // The paste target element(s), by the default undefined.
  94 + // Set to a DOM node or jQuery object to enable file pasting:
  95 + pasteZone: undefined,
  96 + // The file input field(s), that are listened to for change events.
  97 + // If undefined, it is set to the file input fields inside
  98 + // of the widget element on plugin initialization.
  99 + // Set to null to disable the change listener.
  100 + fileInput: undefined,
  101 + // By default, the file input field is replaced with a clone after
  102 + // each input field change event. This is required for iframe transport
  103 + // queues and allows change events to be fired for the same file
  104 + // selection, but can be disabled by setting the following option to false:
  105 + replaceFileInput: true,
  106 + // The parameter name for the file form data (the request argument name).
  107 + // If undefined or empty, the name property of the file input field is
  108 + // used, or "files[]" if the file input name property is also empty,
  109 + // can be a string or an array of strings:
  110 + paramName: undefined,
  111 + // By default, each file of a selection is uploaded using an individual
  112 + // request for XHR type uploads. Set to false to upload file
  113 + // selections in one request each:
  114 + singleFileUploads: true,
  115 + // To limit the number of files uploaded with one XHR request,
  116 + // set the following option to an integer greater than 0:
  117 + limitMultiFileUploads: undefined,
  118 + // The following option limits the number of files uploaded with one
  119 + // XHR request to keep the request size under or equal to the defined
  120 + // limit in bytes:
  121 + limitMultiFileUploadSize: undefined,
  122 + // Multipart file uploads add a number of bytes to each uploaded file,
  123 + // therefore the following option adds an overhead for each file used
  124 + // in the limitMultiFileUploadSize configuration:
  125 + limitMultiFileUploadSizeOverhead: 512,
  126 + // Set the following option to true to issue all file upload requests
  127 + // in a sequential order:
  128 + sequentialUploads: false,
  129 + // To limit the number of concurrent uploads,
  130 + // set the following option to an integer greater than 0:
  131 + limitConcurrentUploads: undefined,
  132 + // Set the following option to true to force iframe transport uploads:
  133 + forceIframeTransport: false,
  134 + // Set the following option to the location of a redirect url on the
  135 + // origin server, for cross-domain iframe transport uploads:
  136 + redirect: undefined,
  137 + // The parameter name for the redirect url, sent as part of the form
  138 + // data and set to 'redirect' if this option is empty:
  139 + redirectParamName: undefined,
  140 + // Set the following option to the location of a postMessage window,
  141 + // to enable postMessage transport uploads:
  142 + postMessage: undefined,
  143 + // By default, XHR file uploads are sent as multipart/form-data.
  144 + // The iframe transport is always using multipart/form-data.
  145 + // Set to false to enable non-multipart XHR uploads:
  146 + multipart: true,
  147 + // To upload large files in smaller chunks, set the following option
  148 + // to a preferred maximum chunk size. If set to 0, null or undefined,
  149 + // or the browser does not support the required Blob API, files will
  150 + // be uploaded as a whole.
  151 + maxChunkSize: undefined,
  152 + // When a non-multipart upload or a chunked multipart upload has been
  153 + // aborted, this option can be used to resume the upload by setting
  154 + // it to the size of the already uploaded bytes. This option is most
  155 + // useful when modifying the options object inside of the "add" or
  156 + // "send" callbacks, as the options are cloned for each file upload.
  157 + uploadedBytes: undefined,
  158 + // By default, failed (abort or error) file uploads are removed from the
  159 + // global progress calculation. Set the following option to false to
  160 + // prevent recalculating the global progress data:
  161 + recalculateProgress: true,
  162 + // Interval in milliseconds to calculate and trigger progress events:
  163 + progressInterval: 100,
  164 + // Interval in milliseconds to calculate progress bitrate:
  165 + bitrateInterval: 500,
  166 + // By default, uploads are started automatically when adding files:
  167 + autoUpload: true,
  168 +
  169 + // Error and info messages:
  170 + messages: {
  171 + uploadedBytes: 'Uploaded bytes exceed file size'
  172 + },
  173 +
  174 + // Translation function, gets the message key to be translated
  175 + // and an object with context specific data as arguments:
  176 + i18n: function (message, context) {
  177 + message = this.messages[message] || message.toString();
  178 + if (context) {
  179 + $.each(context, function (key, value) {
  180 + message = message.replace('{' + key + '}', value);
  181 + });
  182 + }
  183 + return message;
  184 + },
  185 +
  186 + // Additional form data to be sent along with the file uploads can be set
  187 + // using this option, which accepts an array of objects with name and
  188 + // value properties, a function returning such an array, a FormData
  189 + // object (for XHR file uploads), or a simple object.
  190 + // The form of the first fileInput is given as parameter to the function:
  191 + formData: function (form) {
  192 + return form.serializeArray();
  193 + },
  194 +
  195 + // The add callback is invoked as soon as files are added to the fileupload
  196 + // widget (via file input selection, drag & drop, paste or add API call).
  197 + // If the singleFileUploads option is enabled, this callback will be
  198 + // called once for each file in the selection for XHR file uploads, else
  199 + // once for each file selection.
  200 + //
  201 + // The upload starts when the submit method is invoked on the data parameter.
  202 + // The data object contains a files property holding the added files
  203 + // and allows you to override plugin options as well as define ajax settings.
  204 + //
  205 + // Listeners for this callback can also be bound the following way:
  206 + // .bind('fileuploadadd', func);
  207 + //
  208 + // data.submit() returns a Promise object and allows to attach additional
  209 + // handlers using jQuery's Deferred callbacks:
  210 + // data.submit().done(func).fail(func).always(func);
  211 + add: function (e, data) {
  212 + if (e.isDefaultPrevented()) {
  213 + return false;
  214 + }
  215 + if (data.autoUpload || (data.autoUpload !== false &&
  216 + $(this).fileupload('option', 'autoUpload'))) {
  217 + data.process().done(function () {
  218 + data.submit();
  219 + });
  220 + }
  221 + },
  222 +
  223 + // Other callbacks:
  224 +
  225 + // Callback for the submit event of each file upload:
  226 + // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
  227 +
  228 + // Callback for the start of each file upload request:
  229 + // send: function (e, data) {}, // .bind('fileuploadsend', func);
  230 +
  231 + // Callback for successful uploads:
  232 + // done: function (e, data) {}, // .bind('fileuploaddone', func);
  233 +
  234 + // Callback for failed (abort or error) uploads:
  235 + // fail: function (e, data) {}, // .bind('fileuploadfail', func);
  236 +
  237 + // Callback for completed (success, abort or error) requests:
  238 + // always: function (e, data) {}, // .bind('fileuploadalways', func);
  239 +
  240 + // Callback for upload progress events:
  241 + // progress: function (e, data) {}, // .bind('fileuploadprogress', func);
  242 +
  243 + // Callback for global upload progress events:
  244 + // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
  245 +
  246 + // Callback for uploads start, equivalent to the global ajaxStart event:
  247 + // start: function (e) {}, // .bind('fileuploadstart', func);
  248 +
  249 + // Callback for uploads stop, equivalent to the global ajaxStop event:
  250 + // stop: function (e) {}, // .bind('fileuploadstop', func);
  251 +
  252 + // Callback for change events of the fileInput(s):
  253 + // change: function (e, data) {}, // .bind('fileuploadchange', func);
  254 +
  255 + // Callback for paste events to the pasteZone(s):
  256 + // paste: function (e, data) {}, // .bind('fileuploadpaste', func);
  257 +
  258 + // Callback for drop events of the dropZone(s):
  259 + // drop: function (e, data) {}, // .bind('fileuploaddrop', func);
  260 +
  261 + // Callback for dragover events of the dropZone(s):
  262 + // dragover: function (e) {}, // .bind('fileuploaddragover', func);
  263 +
  264 + // Callback for the start of each chunk upload request:
  265 + // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func);
  266 +
  267 + // Callback for successful chunk uploads:
  268 + // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func);
  269 +
  270 + // Callback for failed (abort or error) chunk uploads:
  271 + // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func);
  272 +
  273 + // Callback for completed (success, abort or error) chunk upload requests:
  274 + // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func);
  275 +
  276 + // The plugin options are used as settings object for the ajax calls.
  277 + // The following are jQuery ajax settings required for the file uploads:
  278 + processData: false,
  279 + contentType: false,
  280 + cache: false,
  281 + timeout: 0
  282 + },
  283 +
  284 + // A list of options that require reinitializing event listeners and/or
  285 + // special initialization code:
  286 + _specialOptions: [
  287 + 'fileInput',
  288 + 'dropZone',
  289 + 'pasteZone',
  290 + 'multipart',
  291 + 'forceIframeTransport'
  292 + ],
  293 +
  294 + _blobSlice: $.support.blobSlice && function () {
  295 + var slice = this.slice || this.webkitSlice || this.mozSlice;
  296 + return slice.apply(this, arguments);
  297 + },
  298 +
  299 + _BitrateTimer: function () {
  300 + this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime());
  301 + this.loaded = 0;
  302 + this.bitrate = 0;
  303 + this.getBitrate = function (now, loaded, interval) {
  304 + var timeDiff = now - this.timestamp;
  305 + if (!this.bitrate || !interval || timeDiff > interval) {
  306 + this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8;
  307 + this.loaded = loaded;
  308 + this.timestamp = now;
  309 + }
  310 + return this.bitrate;
  311 + };
  312 + },
  313 +
  314 + _isXHRUpload: function (options) {
  315 + return !options.forceIframeTransport &&
  316 + ((!options.multipart && $.support.xhrFileUpload) ||
  317 + $.support.xhrFormDataFileUpload);
  318 + },
  319 +
  320 + _getFormData: function (options) {
  321 + var formData;
  322 + if ($.type(options.formData) === 'function') {
  323 + return options.formData(options.form);
  324 + }
  325 + if ($.isArray(options.formData)) {
  326 + return options.formData;
  327 + }
  328 + if ($.type(options.formData) === 'object') {
  329 + formData = [];
  330 + $.each(options.formData, function (name, value) {
  331 + formData.push({name: name, value: value});
  332 + });
  333 + return formData;
  334 + }
  335 + return [];
  336 + },
  337 +
  338 + _getTotal: function (files) {
  339 + var total = 0;
  340 + $.each(files, function (index, file) {
  341 + total += file.size || 1;
  342 + });
  343 + return total;
  344 + },
  345 +
  346 + _initProgressObject: function (obj) {
  347 + var progress = {
  348 + loaded: 0,
  349 + total: 0,
  350 + bitrate: 0
  351 + };
  352 + if (obj._progress) {
  353 + $.extend(obj._progress, progress);
  354 + } else {
  355 + obj._progress = progress;
  356 + }
  357 + },
  358 +
  359 + _initResponseObject: function (obj) {
  360 + var prop;
  361 + if (obj._response) {
  362 + for (prop in obj._response) {
  363 + if (obj._response.hasOwnProperty(prop)) {
  364 + delete obj._response[prop];
  365 + }
  366 + }
  367 + } else {
  368 + obj._response = {};
  369 + }
  370 + },
  371 +
  372 + _onProgress: function (e, data) {
  373 + if (e.lengthComputable) {
  374 + var now = ((Date.now) ? Date.now() : (new Date()).getTime()),
  375 + loaded;
  376 + if (data._time && data.progressInterval &&
  377 + (now - data._time < data.progressInterval) &&
  378 + e.loaded !== e.total) {
  379 + return;
  380 + }
  381 + data._time = now;
  382 + loaded = Math.floor(
  383 + e.loaded / e.total * (data.chunkSize || data._progress.total)
  384 + ) + (data.uploadedBytes || 0);
  385 + // Add the difference from the previously loaded state
  386 + // to the global loaded counter:
  387 + this._progress.loaded += (loaded - data._progress.loaded);
  388 + this._progress.bitrate = this._bitrateTimer.getBitrate(
  389 + now,
  390 + this._progress.loaded,
  391 + data.bitrateInterval
  392 + );
  393 + data._progress.loaded = data.loaded = loaded;
  394 + data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(
  395 + now,
  396 + loaded,
  397 + data.bitrateInterval
  398 + );
  399 + // Trigger a custom progress event with a total data property set
  400 + // to the file size(s) of the current upload and a loaded data
  401 + // property calculated accordingly:
  402 + this._trigger(
  403 + 'progress',
  404 + $.Event('progress', {delegatedEvent: e}),
  405 + data
  406 + );
  407 + // Trigger a global progress event for all current file uploads,
  408 + // including ajax calls queued for sequential file uploads:
  409 + this._trigger(
  410 + 'progressall',
  411 + $.Event('progressall', {delegatedEvent: e}),
  412 + this._progress
  413 + );
  414 + }
  415 + },
  416 +
  417 + _initProgressListener: function (options) {
  418 + var that = this,
  419 + xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
  420 + // Accesss to the native XHR object is required to add event listeners
  421 + // for the upload progress event:
  422 + if (xhr.upload) {
  423 + $(xhr.upload).bind('progress', function (e) {
  424 + var oe = e.originalEvent;
  425 + // Make sure the progress event properties get copied over:
  426 + e.lengthComputable = oe.lengthComputable;
  427 + e.loaded = oe.loaded;
  428 + e.total = oe.total;
  429 + that._onProgress(e, options);
  430 + });
  431 + options.xhr = function () {
  432 + return xhr;
  433 + };
  434 + }
  435 + },
  436 +
  437 + _isInstanceOf: function (type, obj) {
  438 + // Cross-frame instanceof check
  439 + return Object.prototype.toString.call(obj) === '[object ' + type + ']';
  440 + },
  441 +
  442 + _initXHRData: function (options) {
  443 + var that = this,
  444 + formData,
  445 + file = options.files[0],
  446 + // Ignore non-multipart setting if not supported:
  447 + multipart = options.multipart || !$.support.xhrFileUpload,
  448 + paramName = $.type(options.paramName) === 'array' ?
  449 + options.paramName[0] : options.paramName;
  450 + options.headers = $.extend({}, options.headers);
  451 + if (options.contentRange) {
  452 + options.headers['Content-Range'] = options.contentRange;
  453 + }
  454 + if (!multipart || options.blob || !this._isInstanceOf('File', file)) {
  455 + options.headers['Content-Disposition'] = 'attachment; filename="' +
  456 + encodeURI(file.name) + '"';
  457 + }
  458 + if (!multipart) {
  459 + options.contentType = file.type || 'application/octet-stream';
  460 + options.data = options.blob || file;
  461 + } else if ($.support.xhrFormDataFileUpload) {
  462 + if (options.postMessage) {
  463 + // window.postMessage does not allow sending FormData
  464 + // objects, so we just add the File/Blob objects to
  465 + // the formData array and let the postMessage window
  466 + // create the FormData object out of this array:
  467 + formData = this._getFormData(options);
  468 + if (options.blob) {
  469 + formData.push({
  470 + name: paramName,
  471 + value: options.blob
  472 + });
  473 + } else {
  474 + $.each(options.files, function (index, file) {
  475 + formData.push({
  476 + name: ($.type(options.paramName) === 'array' &&
  477 + options.paramName[index]) || paramName,
  478 + value: file
  479 + });
  480 + });
  481 + }
  482 + } else {
  483 + if (that._isInstanceOf('FormData', options.formData)) {
  484 + formData = options.formData;
  485 + } else {
  486 + formData = new FormData();
  487 + $.each(this._getFormData(options), function (index, field) {
  488 + formData.append(field.name, field.value);
  489 + });
  490 + }
  491 + if (options.blob) {
  492 + formData.append(paramName, options.blob, file.name);
  493 + } else {
  494 + $.each(options.files, function (index, file) {
  495 + // This check allows the tests to run with
  496 + // dummy objects:
  497 + if (that._isInstanceOf('File', file) ||
  498 + that._isInstanceOf('Blob', file)) {
  499 + formData.append(
  500 + ($.type(options.paramName) === 'array' &&
  501 + options.paramName[index]) || paramName,
  502 + file,
  503 + file.uploadName || file.name
  504 + );
  505 + }
  506 + });
  507 + }
  508 + }
  509 + options.data = formData;
  510 + }
  511 + // Blob reference is not needed anymore, free memory:
  512 + options.blob = null;
  513 + },
  514 +
  515 + _initIframeSettings: function (options) {
  516 + var targetHost = $('<a></a>').prop('href', options.url).prop('host');
  517 + // Setting the dataType to iframe enables the iframe transport:
  518 + options.dataType = 'iframe ' + (options.dataType || '');
  519 + // The iframe transport accepts a serialized array as form data:
  520 + options.formData = this._getFormData(options);
  521 + // Add redirect url to form data on cross-domain uploads:
  522 + if (options.redirect && targetHost && targetHost !== location.host) {
  523 + options.formData.push({
  524 + name: options.redirectParamName || 'redirect',
  525 + value: options.redirect
  526 + });
  527 + }
  528 + },
  529 +
  530 + _initDataSettings: function (options) {
  531 + if (this._isXHRUpload(options)) {
  532 + if (!this._chunkedUpload(options, true)) {
  533 + if (!options.data) {
  534 + this._initXHRData(options);
  535 + }
  536 + this._initProgressListener(options);
  537 + }
  538 + if (options.postMessage) {
  539 + // Setting the dataType to postmessage enables the
  540 + // postMessage transport:
  541 + options.dataType = 'postmessage ' + (options.dataType || '');
  542 + }
  543 + } else {
  544 + this._initIframeSettings(options);
  545 + }
  546 + },
  547 +
  548 + _getParamName: function (options) {
  549 + var fileInput = $(options.fileInput),
  550 + paramName = options.paramName;
  551 + if (!paramName) {
  552 + paramName = [];
  553 + fileInput.each(function () {
  554 + var input = $(this),
  555 + name = input.prop('name') || 'files[]',
  556 + i = (input.prop('files') || [1]).length;
  557 + while (i) {
  558 + paramName.push(name);
  559 + i -= 1;
  560 + }
  561 + });
  562 + if (!paramName.length) {
  563 + paramName = [fileInput.prop('name') || 'files[]'];
  564 + }
  565 + } else if (!$.isArray(paramName)) {
  566 + paramName = [paramName];
  567 + }
  568 + return paramName;
  569 + },
  570 +
  571 + _initFormSettings: function (options) {
  572 + // Retrieve missing options from the input field and the
  573 + // associated form, if available:
  574 + if (!options.form || !options.form.length) {
  575 + options.form = $(options.fileInput.prop('form'));
  576 + // If the given file input doesn't have an associated form,
  577 + // use the default widget file input's form:
  578 + if (!options.form.length) {
  579 + options.form = $(this.options.fileInput.prop('form'));
  580 + }
  581 + }
  582 + options.paramName = this._getParamName(options);
  583 + if (!options.url) {
  584 + options.url = options.form.prop('action') || location.href;
  585 + }
  586 + // The HTTP request method must be "POST" or "PUT":
  587 + options.type = (options.type ||
  588 + ($.type(options.form.prop('method')) === 'string' &&
  589 + options.form.prop('method')) || ''
  590 + ).toUpperCase();
  591 + if (options.type !== 'POST' && options.type !== 'PUT' &&
  592 + options.type !== 'PATCH') {
  593 + options.type = 'POST';
  594 + }
  595 + if (!options.formAcceptCharset) {
  596 + options.formAcceptCharset = options.form.attr('accept-charset');
  597 + }
  598 + },
  599 +
  600 + _getAJAXSettings: function (data) {
  601 + var options = $.extend({}, this.options, data);
  602 + this._initFormSettings(options);
  603 + this._initDataSettings(options);
  604 + return options;
  605 + },
  606 +
  607 + // jQuery 1.6 doesn't provide .state(),
  608 + // while jQuery 1.8+ removed .isRejected() and .isResolved():
  609 + _getDeferredState: function (deferred) {
  610 + if (deferred.state) {
  611 + return deferred.state();
  612 + }
  613 + if (deferred.isResolved()) {
  614 + return 'resolved';
  615 + }
  616 + if (deferred.isRejected()) {
  617 + return 'rejected';
  618 + }
  619 + return 'pending';
  620 + },
  621 +
  622 + // Maps jqXHR callbacks to the equivalent
  623 + // methods of the given Promise object:
  624 + _enhancePromise: function (promise) {
  625 + promise.success = promise.done;
  626 + promise.error = promise.fail;
  627 + promise.complete = promise.always;
  628 + return promise;
  629 + },
  630 +
  631 + // Creates and returns a Promise object enhanced with
  632 + // the jqXHR methods abort, success, error and complete:
  633 + _getXHRPromise: function (resolveOrReject, context, args) {
  634 + var dfd = $.Deferred(),
  635 + promise = dfd.promise();
  636 + context = context || this.options.context || promise;
  637 + if (resolveOrReject === true) {
  638 + dfd.resolveWith(context, args);
  639 + } else if (resolveOrReject === false) {
  640 + dfd.rejectWith(context, args);
  641 + }
  642 + promise.abort = dfd.promise;
  643 + return this._enhancePromise(promise);
  644 + },
  645 +
  646 + // Adds convenience methods to the data callback argument:
  647 + _addConvenienceMethods: function (e, data) {
  648 + var that = this,
  649 + getPromise = function (args) {
  650 + return $.Deferred().resolveWith(that, args).promise();
  651 + };
  652 + data.process = function (resolveFunc, rejectFunc) {
  653 + if (resolveFunc || rejectFunc) {
  654 + data._processQueue = this._processQueue =
  655 + (this._processQueue || getPromise([this])).pipe(
  656 + function () {
  657 + if (data.errorThrown) {
  658 + return $.Deferred()
  659 + .rejectWith(that, [data]).promise();
  660 + }
  661 + return getPromise(arguments);
  662 + }
  663 + ).pipe(resolveFunc, rejectFunc);
  664 + }
  665 + return this._processQueue || getPromise([this]);
  666 + };
  667 + data.submit = function () {
  668 + if (this.state() !== 'pending') {
  669 + data.jqXHR = this.jqXHR =
  670 + (that._trigger(
  671 + 'submit',
  672 + $.Event('submit', {delegatedEvent: e}),
  673 + this
  674 + ) !== false) && that._onSend(e, this);
  675 + }
  676 + return this.jqXHR || that._getXHRPromise();
  677 + };
  678 + data.abort = function () {
  679 + if (this.jqXHR) {
  680 + return this.jqXHR.abort();
  681 + }
  682 + this.errorThrown = 'abort';
  683 + that._trigger('fail', null, this);
  684 + return that._getXHRPromise(false);
  685 + };
  686 + data.state = function () {
  687 + if (this.jqXHR) {
  688 + return that._getDeferredState(this.jqXHR);
  689 + }
  690 + if (this._processQueue) {
  691 + return that._getDeferredState(this._processQueue);
  692 + }
  693 + };
  694 + data.processing = function () {
  695 + return !this.jqXHR && this._processQueue && that
  696 + ._getDeferredState(this._processQueue) === 'pending';
  697 + };
  698 + data.progress = function () {
  699 + return this._progress;
  700 + };
  701 + data.response = function () {
  702 + return this._response;
  703 + };
  704 + },
  705 +
  706 + // Parses the Range header from the server response
  707 + // and returns the uploaded bytes:
  708 + _getUploadedBytes: function (jqXHR) {
  709 + var range = jqXHR.getResponseHeader('Range'),
  710 + parts = range && range.split('-'),
  711 + upperBytesPos = parts && parts.length > 1 &&
  712 + parseInt(parts[1], 10);
  713 + return upperBytesPos && upperBytesPos + 1;
  714 + },
  715 +
  716 + // Uploads a file in multiple, sequential requests
  717 + // by splitting the file up in multiple blob chunks.
  718 + // If the second parameter is true, only tests if the file
  719 + // should be uploaded in chunks, but does not invoke any
  720 + // upload requests:
  721 + _chunkedUpload: function (options, testOnly) {
  722 + options.uploadedBytes = options.uploadedBytes || 0;
  723 + var that = this,
  724 + file = options.files[0],
  725 + fs = file.size,
  726 + ub = options.uploadedBytes,
  727 + mcs = options.maxChunkSize || fs,
  728 + slice = this._blobSlice,
  729 + dfd = $.Deferred(),
  730 + promise = dfd.promise(),
  731 + jqXHR,
  732 + upload;
  733 + if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
  734 + options.data) {
  735 + return false;
  736 + }
  737 + if (testOnly) {
  738 + return true;
  739 + }
  740 + if (ub >= fs) {
  741 + file.error = options.i18n('uploadedBytes');
  742 + return this._getXHRPromise(
  743 + false,
  744 + options.context,
  745 + [null, 'error', file.error]
  746 + );
  747 + }
  748 + // The chunk upload method:
  749 + upload = function () {
  750 + // Clone the options object for each chunk upload:
  751 + var o = $.extend({}, options),
  752 + currentLoaded = o._progress.loaded;
  753 + o.blob = slice.call(
  754 + file,
  755 + ub,
  756 + ub + mcs,
  757 + file.type
  758 + );
  759 + // Store the current chunk size, as the blob itself
  760 + // will be dereferenced after data processing:
  761 + o.chunkSize = o.blob.size;
  762 + // Expose the chunk bytes position range:
  763 + o.contentRange = 'bytes ' + ub + '-' +
  764 + (ub + o.chunkSize - 1) + '/' + fs;
  765 + // Process the upload data (the blob and potential form data):
  766 + that._initXHRData(o);
  767 + // Add progress listeners for this chunk upload:
  768 + that._initProgressListener(o);
  769 + jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) ||
  770 + that._getXHRPromise(false, o.context))
  771 + .done(function (result, textStatus, jqXHR) {
  772 + ub = that._getUploadedBytes(jqXHR) ||
  773 + (ub + o.chunkSize);
  774 + // Create a progress event if no final progress event
  775 + // with loaded equaling total has been triggered
  776 + // for this chunk:
  777 + if (currentLoaded + o.chunkSize - o._progress.loaded) {
  778 + that._onProgress($.Event('progress', {
  779 + lengthComputable: true,
  780 + loaded: ub - o.uploadedBytes,
  781 + total: ub - o.uploadedBytes
  782 + }), o);
  783 + }
  784 + options.uploadedBytes = o.uploadedBytes = ub;
  785 + o.result = result;
  786 + o.textStatus = textStatus;
  787 + o.jqXHR = jqXHR;
  788 + that._trigger('chunkdone', null, o);
  789 + that._trigger('chunkalways', null, o);
  790 + if (ub < fs) {
  791 + // File upload not yet complete,
  792 + // continue with the next chunk:
  793 + upload();
  794 + } else {
  795 + dfd.resolveWith(
  796 + o.context,
  797 + [result, textStatus, jqXHR]
  798 + );
  799 + }
  800 + })
  801 + .fail(function (jqXHR, textStatus, errorThrown) {
  802 + o.jqXHR = jqXHR;
  803 + o.textStatus = textStatus;
  804 + o.errorThrown = errorThrown;
  805 + that._trigger('chunkfail', null, o);
  806 + that._trigger('chunkalways', null, o);
  807 + dfd.rejectWith(
  808 + o.context,
  809 + [jqXHR, textStatus, errorThrown]
  810 + );
  811 + });
  812 + };
  813 + this._enhancePromise(promise);
  814 + promise.abort = function () {
  815 + return jqXHR.abort();
  816 + };
  817 + upload();
  818 + return promise;
  819 + },
  820 +
  821 + _beforeSend: function (e, data) {
  822 + if (this._active === 0) {
  823 + // the start callback is triggered when an upload starts
  824 + // and no other uploads are currently running,
  825 + // equivalent to the global ajaxStart event:
  826 + this._trigger('start');
  827 + // Set timer for global bitrate progress calculation:
  828 + this._bitrateTimer = new this._BitrateTimer();
  829 + // Reset the global progress values:
  830 + this._progress.loaded = this._progress.total = 0;
  831 + this._progress.bitrate = 0;
  832 + }
  833 + // Make sure the container objects for the .response() and
  834 + // .progress() methods on the data object are available
  835 + // and reset to their initial state:
  836 + this._initResponseObject(data);
  837 + this._initProgressObject(data);
  838 + data._progress.loaded = data.loaded = data.uploadedBytes || 0;
  839 + data._progress.total = data.total = this._getTotal(data.files) || 1;
  840 + data._progress.bitrate = data.bitrate = 0;
  841 + this._active += 1;
  842 + // Initialize the global progress values:
  843 + this._progress.loaded += data.loaded;
  844 + this._progress.total += data.total;
  845 + },
  846 +
  847 + _onDone: function (result, textStatus, jqXHR, options) {
  848 + var total = options._progress.total,
  849 + response = options._response;
  850 + if (options._progress.loaded < total) {
  851 + // Create a progress event if no final progress event
  852 + // with loaded equaling total has been triggered:
  853 + this._onProgress($.Event('progress', {
  854 + lengthComputable: true,
  855 + loaded: total,
  856 + total: total
  857 + }), options);
  858 + }
  859 + response.result = options.result = result;
  860 + response.textStatus = options.textStatus = textStatus;
  861 + response.jqXHR = options.jqXHR = jqXHR;
  862 + this._trigger('done', null, options);
  863 + },
  864 +
  865 + _onFail: function (jqXHR, textStatus, errorThrown, options) {
  866 + var response = options._response;
  867 + if (options.recalculateProgress) {
  868 + // Remove the failed (error or abort) file upload from
  869 + // the global progress calculation:
  870 + this._progress.loaded -= options._progress.loaded;
  871 + this._progress.total -= options._progress.total;
  872 + }
  873 + response.jqXHR = options.jqXHR = jqXHR;
  874 + response.textStatus = options.textStatus = textStatus;
  875 + response.errorThrown = options.errorThrown = errorThrown;
  876 + this._trigger('fail', null, options);
  877 + },
  878 +
  879 + _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
  880 + // jqXHRorResult, textStatus and jqXHRorError are added to the
  881 + // options object via done and fail callbacks
  882 + this._trigger('always', null, options);
  883 + },
  884 +
  885 + _onSend: function (e, data) {
  886 + if (!data.submit) {
  887 + this._addConvenienceMethods(e, data);
  888 + }
  889 + var that = this,
  890 + jqXHR,
  891 + aborted,
  892 + slot,
  893 + pipe,
  894 + options = that._getAJAXSettings(data),
  895 + send = function () {
  896 + that._sending += 1;
  897 + // Set timer for bitrate progress calculation:
  898 + options._bitrateTimer = new that._BitrateTimer();
  899 + jqXHR = jqXHR || (
  900 + ((aborted || that._trigger(
  901 + 'send',
  902 + $.Event('send', {delegatedEvent: e}),
  903 + options
  904 + ) === false) &&
  905 + that._getXHRPromise(false, options.context, aborted)) ||
  906 + that._chunkedUpload(options) || $.ajax(options)
  907 + ).done(function (result, textStatus, jqXHR) {
  908 + that._onDone(result, textStatus, jqXHR, options);
  909 + }).fail(function (jqXHR, textStatus, errorThrown) {
  910 + that._onFail(jqXHR, textStatus, errorThrown, options);
  911 + }).always(function (jqXHRorResult, textStatus, jqXHRorError) {
  912 + that._onAlways(
  913 + jqXHRorResult,
  914 + textStatus,
  915 + jqXHRorError,
  916 + options
  917 + );
  918 + that._sending -= 1;
  919 + that._active -= 1;
  920 + if (options.limitConcurrentUploads &&
  921 + options.limitConcurrentUploads > that._sending) {
  922 + // Start the next queued upload,
  923 + // that has not been aborted:
  924 + var nextSlot = that._slots.shift();
  925 + while (nextSlot) {
  926 + if (that._getDeferredState(nextSlot) === 'pending') {
  927 + nextSlot.resolve();
  928 + break;
  929 + }
  930 + nextSlot = that._slots.shift();
  931 + }
  932 + }
  933 + if (that._active === 0) {
  934 + // The stop callback is triggered when all uploads have
  935 + // been completed, equivalent to the global ajaxStop event:
  936 + that._trigger('stop');
  937 + }
  938 + });
  939 + return jqXHR;
  940 + };
  941 + this._beforeSend(e, options);
  942 + if (this.options.sequentialUploads ||
  943 + (this.options.limitConcurrentUploads &&
  944 + this.options.limitConcurrentUploads <= this._sending)) {
  945 + if (this.options.limitConcurrentUploads > 1) {
  946 + slot = $.Deferred();
  947 + this._slots.push(slot);
  948 + pipe = slot.pipe(send);
  949 + } else {
  950 + this._sequence = this._sequence.pipe(send, send);
  951 + pipe = this._sequence;
  952 + }
  953 + // Return the piped Promise object, enhanced with an abort method,
  954 + // which is delegated to the jqXHR object of the current upload,
  955 + // and jqXHR callbacks mapped to the equivalent Promise methods:
  956 + pipe.abort = function () {
  957 + aborted = [undefined, 'abort', 'abort'];
  958 + if (!jqXHR) {
  959 + if (slot) {
  960 + slot.rejectWith(options.context, aborted);
  961 + }
  962 + return send();
  963 + }
  964 + return jqXHR.abort();
  965 + };
  966 + return this._enhancePromise(pipe);
  967 + }
  968 + return send();
  969 + },
  970 +
  971 + _onAdd: function (e, data) {
  972 + var that = this,
  973 + result = true,
  974 + options = $.extend({}, this.options, data),
  975 + files = data.files,
  976 + filesLength = files.length,
  977 + limit = options.limitMultiFileUploads,
  978 + limitSize = options.limitMultiFileUploadSize,
  979 + overhead = options.limitMultiFileUploadSizeOverhead,
  980 + batchSize = 0,
  981 + paramName = this._getParamName(options),
  982 + paramNameSet,
  983 + paramNameSlice,
  984 + fileSet,
  985 + i,
  986 + j = 0;
  987 + if (!filesLength) {
  988 + return false;
  989 + }
  990 + if (limitSize && files[0].size === undefined) {
  991 + limitSize = undefined;
  992 + }
  993 + if (!(options.singleFileUploads || limit || limitSize) ||
  994 + !this._isXHRUpload(options)) {
  995 + fileSet = [files];
  996 + paramNameSet = [paramName];
  997 + } else if (!(options.singleFileUploads || limitSize) && limit) {
  998 + fileSet = [];
  999 + paramNameSet = [];
  1000 + for (i = 0; i < filesLength; i += limit) {
  1001 + fileSet.push(files.slice(i, i + limit));
  1002 + paramNameSlice = paramName.slice(i, i + limit);
  1003 + if (!paramNameSlice.length) {
  1004 + paramNameSlice = paramName;
  1005 + }
  1006 + paramNameSet.push(paramNameSlice);
  1007 + }
  1008 + } else if (!options.singleFileUploads && limitSize) {
  1009 + fileSet = [];
  1010 + paramNameSet = [];
  1011 + for (i = 0; i < filesLength; i = i + 1) {
  1012 + batchSize += files[i].size + overhead;
  1013 + if (i + 1 === filesLength ||
  1014 + ((batchSize + files[i + 1].size + overhead) > limitSize) ||
  1015 + (limit && i + 1 - j >= limit)) {
  1016 + fileSet.push(files.slice(j, i + 1));
  1017 + paramNameSlice = paramName.slice(j, i + 1);
  1018 + if (!paramNameSlice.length) {
  1019 + paramNameSlice = paramName;
  1020 + }
  1021 + paramNameSet.push(paramNameSlice);
  1022 + j = i + 1;
  1023 + batchSize = 0;
  1024 + }
  1025 + }
  1026 + } else {
  1027 + paramNameSet = paramName;
  1028 + }
  1029 + data.originalFiles = files;
  1030 + $.each(fileSet || files, function (index, element) {
  1031 + var newData = $.extend({}, data);
  1032 + newData.files = fileSet ? element : [element];
  1033 + newData.paramName = paramNameSet[index];
  1034 + that._initResponseObject(newData);
  1035 + that._initProgressObject(newData);
  1036 + that._addConvenienceMethods(e, newData);
  1037 + result = that._trigger(
  1038 + 'add',
  1039 + $.Event('add', {delegatedEvent: e}),
  1040 + newData
  1041 + );
  1042 + return result;
  1043 + });
  1044 + return result;
  1045 + },
  1046 +
  1047 + _replaceFileInput: function (data) {
  1048 + var input = data.fileInput,
  1049 + inputClone = input.clone(true),
  1050 + restoreFocus = input.is(document.activeElement);
  1051 + // Add a reference for the new cloned file input to the data argument:
  1052 + data.fileInputClone = inputClone;
  1053 + $('<form></form>').append(inputClone)[0].reset();
  1054 + // Detaching allows to insert the fileInput on another form
  1055 + // without loosing the file input value:
  1056 + input.after(inputClone).detach();
  1057 + // If the fileInput had focus before it was detached,
  1058 + // restore focus to the inputClone.
  1059 + if (restoreFocus) {
  1060 + inputClone.focus();
  1061 + }
  1062 + // Avoid memory leaks with the detached file input:
  1063 + $.cleanData(input.unbind('remove'));
  1064 + // Replace the original file input element in the fileInput
  1065 + // elements set with the clone, which has been copied including
  1066 + // event handlers:
  1067 + this.options.fileInput = this.options.fileInput.map(function (i, el) {
  1068 + if (el === input[0]) {
  1069 + return inputClone[0];
  1070 + }
  1071 + return el;
  1072 + });
  1073 + // If the widget has been initialized on the file input itself,
  1074 + // override this.element with the file input clone:
  1075 + if (input[0] === this.element[0]) {
  1076 + this.element = inputClone;
  1077 + }
  1078 + },
  1079 +
  1080 + _handleFileTreeEntry: function (entry, path) {
  1081 + var that = this,
  1082 + dfd = $.Deferred(),
  1083 + errorHandler = function (e) {
  1084 + if (e && !e.entry) {
  1085 + e.entry = entry;
  1086 + }
  1087 + // Since $.when returns immediately if one
  1088 + // Deferred is rejected, we use resolve instead.
  1089 + // This allows valid files and invalid items
  1090 + // to be returned together in one set:
  1091 + dfd.resolve([e]);
  1092 + },
  1093 + successHandler = function (entries) {
  1094 + that._handleFileTreeEntries(
  1095 + entries,
  1096 + path + entry.name + '/'
  1097 + ).done(function (files) {
  1098 + dfd.resolve(files);
  1099 + }).fail(errorHandler);
  1100 + },
  1101 + readEntries = function () {
  1102 + dirReader.readEntries(function (results) {
  1103 + if (!results.length) {
  1104 + successHandler(entries);
  1105 + } else {
  1106 + entries = entries.concat(results);
  1107 + readEntries();
  1108 + }
  1109 + }, errorHandler);
  1110 + },
  1111 + dirReader, entries = [];
  1112 + path = path || '';
  1113 + if (entry.isFile) {
  1114 + if (entry._file) {
  1115 + // Workaround for Chrome bug #149735
  1116 + entry._file.relativePath = path;
  1117 + dfd.resolve(entry._file);
  1118 + } else {
  1119 + entry.file(function (file) {
  1120 + file.relativePath = path;
  1121 + dfd.resolve(file);
  1122 + }, errorHandler);
  1123 + }
  1124 + } else if (entry.isDirectory) {
  1125 + dirReader = entry.createReader();
  1126 + readEntries();
  1127 + } else {
  1128 + // Return an empy list for file system items
  1129 + // other than files or directories:
  1130 + dfd.resolve([]);
  1131 + }
  1132 + return dfd.promise();
  1133 + },
  1134 +
  1135 + _handleFileTreeEntries: function (entries, path) {
  1136 + var that = this;
  1137 + return $.when.apply(
  1138 + $,
  1139 + $.map(entries, function (entry) {
  1140 + return that._handleFileTreeEntry(entry, path);
  1141 + })
  1142 + ).pipe(function () {
  1143 + return Array.prototype.concat.apply(
  1144 + [],
  1145 + arguments
  1146 + );
  1147 + });
  1148 + },
  1149 +
  1150 + _getDroppedFiles: function (dataTransfer) {
  1151 + dataTransfer = dataTransfer || {};
  1152 + var items = dataTransfer.items;
  1153 + if (items && items.length && (items[0].webkitGetAsEntry ||
  1154 + items[0].getAsEntry)) {
  1155 + return this._handleFileTreeEntries(
  1156 + $.map(items, function (item) {
  1157 + var entry;
  1158 + if (item.webkitGetAsEntry) {
  1159 + entry = item.webkitGetAsEntry();
  1160 + if (entry) {
  1161 + // Workaround for Chrome bug #149735:
  1162 + entry._file = item.getAsFile();
  1163 + }
  1164 + return entry;
  1165 + }
  1166 + return item.getAsEntry();
  1167 + })
  1168 + );
  1169 + }
  1170 + return $.Deferred().resolve(
  1171 + $.makeArray(dataTransfer.files)
  1172 + ).promise();
  1173 + },
  1174 +
  1175 + _getSingleFileInputFiles: function (fileInput) {
  1176 + fileInput = $(fileInput);
  1177 + var entries = fileInput.prop('webkitEntries') ||
  1178 + fileInput.prop('entries'),
  1179 + files,
  1180 + value;
  1181 + if (entries && entries.length) {
  1182 + return this._handleFileTreeEntries(entries);
  1183 + }
  1184 + files = $.makeArray(fileInput.prop('files'));
  1185 + if (!files.length) {
  1186 + value = fileInput.prop('value');
  1187 + if (!value) {
  1188 + return $.Deferred().resolve([]).promise();
  1189 + }
  1190 + // If the files property is not available, the browser does not
  1191 + // support the File API and we add a pseudo File object with
  1192 + // the input value as name with path information removed:
  1193 + files = [{name: value.replace(/^.*\\/, '')}];
  1194 + } else if (files[0].name === undefined && files[0].fileName) {
  1195 + // File normalization for Safari 4 and Firefox 3:
  1196 + $.each(files, function (index, file) {
  1197 + file.name = file.fileName;
  1198 + file.size = file.fileSize;
  1199 + });
  1200 + }
  1201 + return $.Deferred().resolve(files).promise();
  1202 + },
  1203 +
  1204 + _getFileInputFiles: function (fileInput) {
  1205 + if (!(fileInput instanceof $) || fileInput.length === 1) {
  1206 + return this._getSingleFileInputFiles(fileInput);
  1207 + }
  1208 + return $.when.apply(
  1209 + $,
  1210 + $.map(fileInput, this._getSingleFileInputFiles)
  1211 + ).pipe(function () {
  1212 + return Array.prototype.concat.apply(
  1213 + [],
  1214 + arguments
  1215 + );
  1216 + });
  1217 + },
  1218 +
  1219 + _onChange: function (e) {
  1220 + var that = this,
  1221 + data = {
  1222 + fileInput: $(e.target),
  1223 + form: $(e.target.form)
  1224 + };
  1225 + this._getFileInputFiles(data.fileInput).always(function (files) {
  1226 + data.files = files;
  1227 + if (that.options.replaceFileInput) {
  1228 + that._replaceFileInput(data);
  1229 + }
  1230 + if (that._trigger(
  1231 + 'change',
  1232 + $.Event('change', {delegatedEvent: e}),
  1233 + data
  1234 + ) !== false) {
  1235 + that._onAdd(e, data);
  1236 + }
  1237 + });
  1238 + },
  1239 +
  1240 + _onPaste: function (e) {
  1241 + var items = e.originalEvent && e.originalEvent.clipboardData &&
  1242 + e.originalEvent.clipboardData.items,
  1243 + data = {files: []};
  1244 + if (items && items.length) {
  1245 + $.each(items, function (index, item) {
  1246 + var file = item.getAsFile && item.getAsFile();
  1247 + if (file) {
  1248 + data.files.push(file);
  1249 + }
  1250 + });
  1251 + if (this._trigger(
  1252 + 'paste',
  1253 + $.Event('paste', {delegatedEvent: e}),
  1254 + data
  1255 + ) !== false) {
  1256 + this._onAdd(e, data);
  1257 + }
  1258 + }
  1259 + },
  1260 +
  1261 + _onDrop: function (e) {
  1262 + e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
  1263 + var that = this,
  1264 + dataTransfer = e.dataTransfer,
  1265 + data = {};
  1266 + if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
  1267 + e.preventDefault();
  1268 + this._getDroppedFiles(dataTransfer).always(function (files) {
  1269 + data.files = files;
  1270 + if (that._trigger(
  1271 + 'drop',
  1272 + $.Event('drop', {delegatedEvent: e}),
  1273 + data
  1274 + ) !== false) {
  1275 + that._onAdd(e, data);
  1276 + }
  1277 + });
  1278 + }
  1279 + },
  1280 +
  1281 + _onDragOver: getDragHandler('dragover'),
  1282 +
  1283 + _onDragEnter: getDragHandler('dragenter'),
  1284 +
  1285 + _onDragLeave: getDragHandler('dragleave'),
  1286 +
  1287 + _initEventHandlers: function () {
  1288 + if (this._isXHRUpload(this.options)) {
  1289 + this._on(this.options.dropZone, {
  1290 + dragover: this._onDragOver,
  1291 + drop: this._onDrop,
  1292 + // event.preventDefault() on dragenter is required for IE10+:
  1293 + dragenter: this._onDragEnter,
  1294 + // dragleave is not required, but added for completeness:
  1295 + dragleave: this._onDragLeave
  1296 + });
  1297 + this._on(this.options.pasteZone, {
  1298 + paste: this._onPaste
  1299 + });
  1300 + }
  1301 + if ($.support.fileInput) {
  1302 + this._on(this.options.fileInput, {
  1303 + change: this._onChange
  1304 + });
  1305 + }
  1306 + },
  1307 +
  1308 + _destroyEventHandlers: function () {
  1309 + this._off(this.options.dropZone, 'dragenter dragleave dragover drop');
  1310 + this._off(this.options.pasteZone, 'paste');
  1311 + this._off(this.options.fileInput, 'change');
  1312 + },
  1313 +
  1314 + _setOption: function (key, value) {
  1315 + var reinit = $.inArray(key, this._specialOptions) !== -1;
  1316 + if (reinit) {
  1317 + this._destroyEventHandlers();
  1318 + }
  1319 + this._super(key, value);
  1320 + if (reinit) {
  1321 + this._initSpecialOptions();
  1322 + this._initEventHandlers();
  1323 + }
  1324 + },
  1325 +
  1326 + _initSpecialOptions: function () {
  1327 + var options = this.options;
  1328 + if (options.fileInput === undefined) {
  1329 + options.fileInput = this.element.is('input[type="file"]') ?
  1330 + this.element : this.element.find('input[type="file"]');
  1331 + } else if (!(options.fileInput instanceof $)) {
  1332 + options.fileInput = $(options.fileInput);
  1333 + }
  1334 + if (!(options.dropZone instanceof $)) {
  1335 + options.dropZone = $(options.dropZone);
  1336 + }
  1337 + if (!(options.pasteZone instanceof $)) {
  1338 + options.pasteZone = $(options.pasteZone);
  1339 + }
  1340 + },
  1341 +
  1342 + _getRegExp: function (str) {
  1343 + var parts = str.split('/'),
  1344 + modifiers = parts.pop();
  1345 + parts.shift();
  1346 + return new RegExp(parts.join('/'), modifiers);
  1347 + },
  1348 +
  1349 + _isRegExpOption: function (key, value) {
  1350 + return key !== 'url' && $.type(value) === 'string' &&
  1351 + /^\/.*\/[igm]{0,3}$/.test(value);
  1352 + },
  1353 +
  1354 + _initDataAttributes: function () {
  1355 + var that = this,
  1356 + options = this.options,
  1357 + data = this.element.data();
  1358 + // Initialize options set via HTML5 data-attributes:
  1359 + $.each(
  1360 + this.element[0].attributes,
  1361 + function (index, attr) {
  1362 + var key = attr.name.toLowerCase(),
  1363 + value;
  1364 + if (/^data-/.test(key)) {
  1365 + // Convert hyphen-ated key to camelCase:
  1366 + key = key.slice(5).replace(/-[a-z]/g, function (str) {
  1367 + return str.charAt(1).toUpperCase();
  1368 + });
  1369 + value = data[key];
  1370 + if (that._isRegExpOption(key, value)) {
  1371 + value = that._getRegExp(value);
  1372 + }
  1373 + options[key] = value;
  1374 + }
  1375 + }
  1376 + );
  1377 + },
  1378 +
  1379 + _create: function () {
  1380 + this._initDataAttributes();
  1381 + this._initSpecialOptions();
  1382 + this._slots = [];
  1383 + this._sequence = this._getXHRPromise(true);
  1384 + this._sending = this._active = 0;
  1385 + this._initProgressObject(this);
  1386 + this._initEventHandlers();
  1387 + },
  1388 +
  1389 + // This method is exposed to the widget API and allows to query
  1390 + // the number of active uploads:
  1391 + active: function () {
  1392 + return this._active;
  1393 + },
  1394 +
  1395 + // This method is exposed to the widget API and allows to query
  1396 + // the widget upload progress.
  1397 + // It returns an object with loaded, total and bitrate properties
  1398 + // for the running uploads:
  1399 + progress: function () {
  1400 + return this._progress;
  1401 + },
  1402 +
  1403 + // This method is exposed to the widget API and allows adding files
  1404 + // using the fileupload API. The data parameter accepts an object which
  1405 + // must have a files property and can contain additional options:
  1406 + // .fileupload('add', {files: filesList});
  1407 + add: function (data) {
  1408 + var that = this;
  1409 + if (!data || this.options.disabled) {
  1410 + return;
  1411 + }
  1412 + if (data.fileInput && !data.files) {
  1413 + this._getFileInputFiles(data.fileInput).always(function (files) {
  1414 + data.files = files;
  1415 + that._onAdd(null, data);
  1416 + });
  1417 + } else {
  1418 + data.files = $.makeArray(data.files);
  1419 + this._onAdd(null, data);
  1420 + }
  1421 + },
  1422 +
  1423 + // This method is exposed to the widget API and allows sending files
  1424 + // using the fileupload API. The data parameter accepts an object which
  1425 + // must have a files or fileInput property and can contain additional options:
  1426 + // .fileupload('send', {files: filesList});
  1427 + // The method returns a Promise object for the file upload call.
  1428 + send: function (data) {
  1429 + if (data && !this.options.disabled) {
  1430 + if (data.fileInput && !data.files) {
  1431 + var that = this,
  1432 + dfd = $.Deferred(),
  1433 + promise = dfd.promise(),
  1434 + jqXHR,
  1435 + aborted;
  1436 + promise.abort = function () {
  1437 + aborted = true;
  1438 + if (jqXHR) {
  1439 + return jqXHR.abort();
  1440 + }
  1441 + dfd.reject(null, 'abort', 'abort');
  1442 + return promise;
  1443 + };
  1444 + this._getFileInputFiles(data.fileInput).always(
  1445 + function (files) {
  1446 + if (aborted) {
  1447 + return;
  1448 + }
  1449 + if (!files.length) {
  1450 + dfd.reject();
  1451 + return;
  1452 + }
  1453 + data.files = files;
  1454 + jqXHR = that._onSend(null, data);
  1455 + jqXHR.then(
  1456 + function (result, textStatus, jqXHR) {
  1457 + dfd.resolve(result, textStatus, jqXHR);
  1458 + },
  1459 + function (jqXHR, textStatus, errorThrown) {
  1460 + dfd.reject(jqXHR, textStatus, errorThrown);
  1461 + }
  1462 + );
  1463 + }
  1464 + );
  1465 + return this._enhancePromise(promise);
  1466 + }
  1467 + data.files = $.makeArray(data.files);
  1468 + if (data.files.length) {
  1469 + return this._onSend(null, data);
  1470 + }
  1471 + }
  1472 + return this._getXHRPromise(false, data && data.context);
  1473 + }
  1474 +
  1475 + });
  1476 +
  1477 +}));
view/assets/js/external-libs/jquery.iframe-transport.js 0 → 100755
@@ -0,0 +1,217 @@ @@ -0,0 +1,217 @@
  1 +/*
  2 + * jQuery Iframe Transport Plugin
  3 + * https://github.com/blueimp/jQuery-File-Upload
  4 + *
  5 + * Copyright 2011, Sebastian Tschan
  6 + * https://blueimp.net
  7 + *
  8 + * Licensed under the MIT license:
  9 + * http://www.opensource.org/licenses/MIT
  10 + */
  11 +
  12 +/* global define, require, window, document */
  13 +
  14 +(function (factory) {
  15 + 'use strict';
  16 + if (typeof define === 'function' && define.amd) {
  17 + // Register as an anonymous AMD module:
  18 + define(['jquery'], factory);
  19 + } else if (typeof exports === 'object') {
  20 + // Node/CommonJS:
  21 + factory(require('jquery'));
  22 + } else {
  23 + // Browser globals:
  24 + factory(window.jQuery);
  25 + }
  26 +}(function ($) {
  27 + 'use strict';
  28 +
  29 + // Helper variable to create unique names for the transport iframes:
  30 + var counter = 0;
  31 +
  32 + // The iframe transport accepts four additional options:
  33 + // options.fileInput: a jQuery collection of file input fields
  34 + // options.paramName: the parameter name for the file form data,
  35 + // overrides the name property of the file input field(s),
  36 + // can be a string or an array of strings.
  37 + // options.formData: an array of objects with name and value properties,
  38 + // equivalent to the return data of .serializeArray(), e.g.:
  39 + // [{name: 'a', value: 1}, {name: 'b', value: 2}]
  40 + // options.initialIframeSrc: the URL of the initial iframe src,
  41 + // by default set to "javascript:false;"
  42 + $.ajaxTransport('iframe', function (options) {
  43 + if (options.async) {
  44 + // javascript:false as initial iframe src
  45 + // prevents warning popups on HTTPS in IE6:
  46 + /*jshint scripturl: true */
  47 + var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
  48 + /*jshint scripturl: false */
  49 + form,
  50 + iframe,
  51 + addParamChar;
  52 + return {
  53 + send: function (_, completeCallback) {
  54 + form = $('<form style="display:none;"></form>');
  55 + form.attr('accept-charset', options.formAcceptCharset);
  56 + addParamChar = /\?/.test(options.url) ? '&' : '?';
  57 + // XDomainRequest only supports GET and POST:
  58 + if (options.type === 'DELETE') {
  59 + options.url = options.url + addParamChar + '_method=DELETE';
  60 + options.type = 'POST';
  61 + } else if (options.type === 'PUT') {
  62 + options.url = options.url + addParamChar + '_method=PUT';
  63 + options.type = 'POST';
  64 + } else if (options.type === 'PATCH') {
  65 + options.url = options.url + addParamChar + '_method=PATCH';
  66 + options.type = 'POST';
  67 + }
  68 + // IE versions below IE8 cannot set the name property of
  69 + // elements that have already been added to the DOM,
  70 + // so we set the name along with the iframe HTML markup:
  71 + counter += 1;
  72 + iframe = $(
  73 + '<iframe src="' + initialIframeSrc +
  74 + '" name="iframe-transport-' + counter + '"></iframe>'
  75 + ).bind('load', function () {
  76 + var fileInputClones,
  77 + paramNames = $.isArray(options.paramName) ?
  78 + options.paramName : [options.paramName];
  79 + iframe
  80 + .unbind('load')
  81 + .bind('load', function () {
  82 + var response;
  83 + // Wrap in a try/catch block to catch exceptions thrown
  84 + // when trying to access cross-domain iframe contents:
  85 + try {
  86 + response = iframe.contents();
  87 + // Google Chrome and Firefox do not throw an
  88 + // exception when calling iframe.contents() on
  89 + // cross-domain requests, so we unify the response:
  90 + if (!response.length || !response[0].firstChild) {
  91 + throw new Error();
  92 + }
  93 + } catch (e) {
  94 + response = undefined;
  95 + }
  96 + // The complete callback returns the
  97 + // iframe content document as response object:
  98 + completeCallback(
  99 + 200,
  100 + 'success',
  101 + {'iframe': response}
  102 + );
  103 + // Fix for IE endless progress bar activity bug
  104 + // (happens on form submits to iframe targets):
  105 + $('<iframe src="' + initialIframeSrc + '"></iframe>')
  106 + .appendTo(form);
  107 + window.setTimeout(function () {
  108 + // Removing the form in a setTimeout call
  109 + // allows Chrome's developer tools to display
  110 + // the response result
  111 + form.remove();
  112 + }, 0);
  113 + });
  114 + form
  115 + .prop('target', iframe.prop('name'))
  116 + .prop('action', options.url)
  117 + .prop('method', options.type);
  118 + if (options.formData) {
  119 + $.each(options.formData, function (index, field) {
  120 + $('<input type="hidden"/>')
  121 + .prop('name', field.name)
  122 + .val(field.value)
  123 + .appendTo(form);
  124 + });
  125 + }
  126 + if (options.fileInput && options.fileInput.length &&
  127 + options.type === 'POST') {
  128 + fileInputClones = options.fileInput.clone();
  129 + // Insert a clone for each file input field:
  130 + options.fileInput.after(function (index) {
  131 + return fileInputClones[index];
  132 + });
  133 + if (options.paramName) {
  134 + options.fileInput.each(function (index) {
  135 + $(this).prop(
  136 + 'name',
  137 + paramNames[index] || options.paramName
  138 + );
  139 + });
  140 + }
  141 + // Appending the file input fields to the hidden form
  142 + // removes them from their original location:
  143 + form
  144 + .append(options.fileInput)
  145 + .prop('enctype', 'multipart/form-data')
  146 + // enctype must be set as encoding for IE:
  147 + .prop('encoding', 'multipart/form-data');
  148 + // Remove the HTML5 form attribute from the input(s):
  149 + options.fileInput.removeAttr('form');
  150 + }
  151 + form.submit();
  152 + // Insert the file input fields at their original location
  153 + // by replacing the clones with the originals:
  154 + if (fileInputClones && fileInputClones.length) {
  155 + options.fileInput.each(function (index, input) {
  156 + var clone = $(fileInputClones[index]);
  157 + // Restore the original name and form properties:
  158 + $(input)
  159 + .prop('name', clone.prop('name'))
  160 + .attr('form', clone.attr('form'));
  161 + clone.replaceWith(input);
  162 + });
  163 + }
  164 + });
  165 + form.append(iframe).appendTo(document.body);
  166 + },
  167 + abort: function () {
  168 + if (iframe) {
  169 + // javascript:false as iframe src aborts the request
  170 + // and prevents warning popups on HTTPS in IE6.
  171 + // concat is used to avoid the "Script URL" JSLint error:
  172 + iframe
  173 + .unbind('load')
  174 + .prop('src', initialIframeSrc);
  175 + }
  176 + if (form) {
  177 + form.remove();
  178 + }
  179 + }
  180 + };
  181 + }
  182 + });
  183 +
  184 + // The iframe transport returns the iframe content document as response.
  185 + // The following adds converters from iframe to text, json, html, xml
  186 + // and script.
  187 + // Please note that the Content-Type for JSON responses has to be text/plain
  188 + // or text/html, if the browser doesn't include application/json in the
  189 + // Accept header, else IE will show a download dialog.
  190 + // The Content-Type for XML responses on the other hand has to be always
  191 + // application/xml or text/xml, so IE properly parses the XML response.
  192 + // See also
  193 + // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
  194 + $.ajaxSetup({
  195 + converters: {
  196 + 'iframe text': function (iframe) {
  197 + return iframe && $(iframe[0].body).text();
  198 + },
  199 + 'iframe json': function (iframe) {
  200 + return iframe && $.parseJSON($(iframe[0].body).text());
  201 + },
  202 + 'iframe html': function (iframe) {
  203 + return iframe && $(iframe[0].body).html();
  204 + },
  205 + 'iframe xml': function (iframe) {
  206 + var xmlDoc = iframe && iframe[0];
  207 + return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :
  208 + $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
  209 + $(xmlDoc.body).html());
  210 + },
  211 + 'iframe script': function (iframe) {
  212 + return iframe && $.globalEval($(iframe[0].body).text());
  213 + }
  214 + }
  215 + });
  216 +
  217 +}));
view/assets/js/external-libs/jquery.scrollTo.js 0 → 100644
@@ -0,0 +1,210 @@ @@ -0,0 +1,210 @@
  1 +/*!
  2 + * jQuery.scrollTo
  3 + * Copyright (c) 2007-2015 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
  4 + * Licensed under MIT
  5 + * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
  6 + * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery
  7 + * @author Ariel Flesler
  8 + * @version 2.1.2
  9 + */
  10 +;(function(factory) {
  11 + 'use strict';
  12 + if (typeof define === 'function' && define.amd) {
  13 + // AMD
  14 + define(['jquery'], factory);
  15 + } else if (typeof module !== 'undefined' && module.exports) {
  16 + // CommonJS
  17 + module.exports = factory(require('jquery'));
  18 + } else {
  19 + // Global
  20 + factory(jQuery);
  21 + }
  22 +})(function($) {
  23 + 'use strict';
  24 +
  25 + var $scrollTo = $.scrollTo = function(target, duration, settings) {
  26 + return $(window).scrollTo(target, duration, settings);
  27 + };
  28 +
  29 + $scrollTo.defaults = {
  30 + axis:'xy',
  31 + duration: 0,
  32 + limit:true
  33 + };
  34 +
  35 + function isWin(elem) {
  36 + return !elem.nodeName ||
  37 + $.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1;
  38 + }
  39 +
  40 + $.fn.scrollTo = function(target, duration, settings) {
  41 + if (typeof duration === 'object') {
  42 + settings = duration;
  43 + duration = 0;
  44 + }
  45 + if (typeof settings === 'function') {
  46 + settings = { onAfter:settings };
  47 + }
  48 + if (target === 'max') {
  49 + target = 9e9;
  50 + }
  51 +
  52 + settings = $.extend({}, $scrollTo.defaults, settings);
  53 + // Speed is still recognized for backwards compatibility
  54 + duration = duration || settings.duration;
  55 + // Make sure the settings are given right
  56 + var queue = settings.queue && settings.axis.length > 1;
  57 + if (queue) {
  58 + // Let's keep the overall duration
  59 + duration /= 2;
  60 + }
  61 + settings.offset = both(settings.offset);
  62 + settings.over = both(settings.over);
  63 +
  64 + return this.each(function() {
  65 + // Null target yields nothing, just like jQuery does
  66 + if (target === null) return;
  67 +
  68 + var win = isWin(this),
  69 + elem = win ? this.contentWindow || window : this,
  70 + $elem = $(elem),
  71 + targ = target,
  72 + attr = {},
  73 + toff;
  74 +
  75 + switch (typeof targ) {
  76 + // A number will pass the regex
  77 + case 'number':
  78 + case 'string':
  79 + if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) {
  80 + targ = both(targ);
  81 + // We are done
  82 + break;
  83 + }
  84 + // Relative/Absolute selector
  85 + targ = win ? $(targ) : $(targ, elem);
  86 + /* falls through */
  87 + case 'object':
  88 + if (targ.length === 0) return;
  89 + // DOMElement / jQuery
  90 + if (targ.is || targ.style) {
  91 + // Get the real position of the target
  92 + toff = (targ = $(targ)).offset();
  93 + }
  94 + }
  95 +
  96 + var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset;
  97 +
  98 + $.each(settings.axis.split(''), function(i, axis) {
  99 + var Pos = axis === 'x' ? 'Left' : 'Top',
  100 + pos = Pos.toLowerCase(),
  101 + key = 'scroll' + Pos,
  102 + prev = $elem[key](),
  103 + max = $scrollTo.max(elem, axis);
  104 +
  105 + if (toff) {// jQuery / DOMElement
  106 + attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]);
  107 +
  108 + // If it's a dom element, reduce the margin
  109 + if (settings.margin) {
  110 + attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0;
  111 + attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0;
  112 + }
  113 +
  114 + attr[key] += offset[pos] || 0;
  115 +
  116 + if (settings.over[pos]) {
  117 + // Scroll to a fraction of its width/height
  118 + attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos];
  119 + }
  120 + } else {
  121 + var val = targ[pos];
  122 + // Handle percentage values
  123 + attr[key] = val.slice && val.slice(-1) === '%' ?
  124 + parseFloat(val) / 100 * max
  125 + : val;
  126 + }
  127 +
  128 + // Number or 'number'
  129 + if (settings.limit && /^\d+$/.test(attr[key])) {
  130 + // Check the limits
  131 + attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max);
  132 + }
  133 +
  134 + // Don't waste time animating, if there's no need.
  135 + if (!i && settings.axis.length > 1) {
  136 + if (prev === attr[key]) {
  137 + // No animation needed
  138 + attr = {};
  139 + } else if (queue) {
  140 + // Intermediate animation
  141 + animate(settings.onAfterFirst);
  142 + // Don't animate this axis again in the next iteration.
  143 + attr = {};
  144 + }
  145 + }
  146 + });
  147 +
  148 + animate(settings.onAfter);
  149 +
  150 + function animate(callback) {
  151 + var opts = $.extend({}, settings, {
  152 + // The queue setting conflicts with animate()
  153 + // Force it to always be true
  154 + queue: true,
  155 + duration: duration,
  156 + complete: callback && function() {
  157 + callback.call(elem, targ, settings);
  158 + }
  159 + });
  160 + $elem.animate(attr, opts);
  161 + }
  162 + });
  163 + };
  164 +
  165 + // Max scrolling position, works on quirks mode
  166 + // It only fails (not too badly) on IE, quirks mode.
  167 + $scrollTo.max = function(elem, axis) {
  168 + var Dim = axis === 'x' ? 'Width' : 'Height',
  169 + scroll = 'scroll'+Dim;
  170 +
  171 + if (!isWin(elem))
  172 + return elem[scroll] - $(elem)[Dim.toLowerCase()]();
  173 +
  174 + var size = 'client' + Dim,
  175 + doc = elem.ownerDocument || elem.document,
  176 + html = doc.documentElement,
  177 + body = doc.body;
  178 +
  179 + return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]);
  180 + };
  181 +
  182 + function both(val) {
  183 + return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val };
  184 + }
  185 +
  186 + // Add special hooks so that window scroll properties can be animated
  187 + $.Tween.propHooks.scrollLeft =
  188 + $.Tween.propHooks.scrollTop = {
  189 + get: function(t) {
  190 + return $(t.elem)[t.prop]();
  191 + },
  192 + set: function(t) {
  193 + var curr = this.get(t);
  194 + // If interrupt is true and user scrolled, stop animating
  195 + if (t.options.interrupt && t._last && t._last !== curr) {
  196 + return $(t.elem).stop();
  197 + }
  198 + var next = Math.round(t.now);
  199 + // Don't waste CPU
  200 + // Browsers don't render floating point scroll
  201 + if (curr !== next) {
  202 + $(t.elem)[t.prop](next);
  203 + t._last = this.get(t);
  204 + }
  205 + }
  206 + };
  207 +
  208 + // AMD requirement
  209 + return $scrollTo;
  210 +});
view/assets/js/external-libs/jquery.ui.widget.js 0 → 100755
@@ -0,0 +1,572 @@ @@ -0,0 +1,572 @@
  1 +/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28
  2 +* http://jqueryui.com
  3 +* Includes: widget.js
  4 +* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
  5 +
  6 +(function( factory ) {
  7 + if ( typeof define === "function" && define.amd ) {
  8 +
  9 + // AMD. Register as an anonymous module.
  10 + define([ "jquery" ], factory );
  11 +
  12 + } else if ( typeof exports === "object" ) {
  13 +
  14 + // Node/CommonJS
  15 + factory( require( "jquery" ) );
  16 +
  17 + } else {
  18 +
  19 + // Browser globals
  20 + factory( jQuery );
  21 + }
  22 +}(function( $ ) {
  23 +/*!
  24 + * jQuery UI Widget 1.11.4
  25 + * http://jqueryui.com
  26 + *
  27 + * Copyright jQuery Foundation and other contributors
  28 + * Released under the MIT license.
  29 + * http://jquery.org/license
  30 + *
  31 + * http://api.jqueryui.com/jQuery.widget/
  32 + */
  33 +
  34 +
  35 +var widget_uuid = 0,
  36 + widget_slice = Array.prototype.slice;
  37 +
  38 +$.cleanData = (function( orig ) {
  39 + return function( elems ) {
  40 + var events, elem, i;
  41 + for ( i = 0; (elem = elems[i]) != null; i++ ) {
  42 + try {
  43 +
  44 + // Only trigger remove when necessary to save time
  45 + events = $._data( elem, "events" );
  46 + if ( events && events.remove ) {
  47 + $( elem ).triggerHandler( "remove" );
  48 + }
  49 +
  50 + // http://bugs.jquery.com/ticket/8235
  51 + } catch ( e ) {}
  52 + }
  53 + orig( elems );
  54 + };
  55 +})( $.cleanData );
  56 +
  57 +$.widget = function( name, base, prototype ) {
  58 + var fullName, existingConstructor, constructor, basePrototype,
  59 + // proxiedPrototype allows the provided prototype to remain unmodified
  60 + // so that it can be used as a mixin for multiple widgets (#8876)
  61 + proxiedPrototype = {},
  62 + namespace = name.split( "." )[ 0 ];
  63 +
  64 + name = name.split( "." )[ 1 ];
  65 + fullName = namespace + "-" + name;
  66 +
  67 + if ( !prototype ) {
  68 + prototype = base;
  69 + base = $.Widget;
  70 + }
  71 +
  72 + // create selector for plugin
  73 + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
  74 + return !!$.data( elem, fullName );
  75 + };
  76 +
  77 + $[ namespace ] = $[ namespace ] || {};
  78 + existingConstructor = $[ namespace ][ name ];
  79 + constructor = $[ namespace ][ name ] = function( options, element ) {
  80 + // allow instantiation without "new" keyword
  81 + if ( !this._createWidget ) {
  82 + return new constructor( options, element );
  83 + }
  84 +
  85 + // allow instantiation without initializing for simple inheritance
  86 + // must use "new" keyword (the code above always passes args)
  87 + if ( arguments.length ) {
  88 + this._createWidget( options, element );
  89 + }
  90 + };
  91 + // extend with the existing constructor to carry over any static properties
  92 + $.extend( constructor, existingConstructor, {
  93 + version: prototype.version,
  94 + // copy the object used to create the prototype in case we need to
  95 + // redefine the widget later
  96 + _proto: $.extend( {}, prototype ),
  97 + // track widgets that inherit from this widget in case this widget is
  98 + // redefined after a widget inherits from it
  99 + _childConstructors: []
  100 + });
  101 +
  102 + basePrototype = new base();
  103 + // we need to make the options hash a property directly on the new instance
  104 + // otherwise we'll modify the options hash on the prototype that we're
  105 + // inheriting from
  106 + basePrototype.options = $.widget.extend( {}, basePrototype.options );
  107 + $.each( prototype, function( prop, value ) {
  108 + if ( !$.isFunction( value ) ) {
  109 + proxiedPrototype[ prop ] = value;
  110 + return;
  111 + }
  112 + proxiedPrototype[ prop ] = (function() {
  113 + var _super = function() {
  114 + return base.prototype[ prop ].apply( this, arguments );
  115 + },
  116 + _superApply = function( args ) {
  117 + return base.prototype[ prop ].apply( this, args );
  118 + };
  119 + return function() {
  120 + var __super = this._super,
  121 + __superApply = this._superApply,
  122 + returnValue;
  123 +
  124 + this._super = _super;
  125 + this._superApply = _superApply;
  126 +
  127 + returnValue = value.apply( this, arguments );
  128 +
  129 + this._super = __super;
  130 + this._superApply = __superApply;
  131 +
  132 + return returnValue;
  133 + };
  134 + })();
  135 + });
  136 + constructor.prototype = $.widget.extend( basePrototype, {
  137 + // TODO: remove support for widgetEventPrefix
  138 + // always use the name + a colon as the prefix, e.g., draggable:start
  139 + // don't prefix for widgets that aren't DOM-based
  140 + widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
  141 + }, proxiedPrototype, {
  142 + constructor: constructor,
  143 + namespace: namespace,
  144 + widgetName: name,
  145 + widgetFullName: fullName
  146 + });
  147 +
  148 + // If this widget is being redefined then we need to find all widgets that
  149 + // are inheriting from it and redefine all of them so that they inherit from
  150 + // the new version of this widget. We're essentially trying to replace one
  151 + // level in the prototype chain.
  152 + if ( existingConstructor ) {
  153 + $.each( existingConstructor._childConstructors, function( i, child ) {
  154 + var childPrototype = child.prototype;
  155 +
  156 + // redefine the child widget using the same prototype that was
  157 + // originally used, but inherit from the new version of the base
  158 + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
  159 + });
  160 + // remove the list of existing child constructors from the old constructor
  161 + // so the old child constructors can be garbage collected
  162 + delete existingConstructor._childConstructors;
  163 + } else {
  164 + base._childConstructors.push( constructor );
  165 + }
  166 +
  167 + $.widget.bridge( name, constructor );
  168 +
  169 + return constructor;
  170 +};
  171 +
  172 +$.widget.extend = function( target ) {
  173 + var input = widget_slice.call( arguments, 1 ),
  174 + inputIndex = 0,
  175 + inputLength = input.length,
  176 + key,
  177 + value;
  178 + for ( ; inputIndex < inputLength; inputIndex++ ) {
  179 + for ( key in input[ inputIndex ] ) {
  180 + value = input[ inputIndex ][ key ];
  181 + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
  182 + // Clone objects
  183 + if ( $.isPlainObject( value ) ) {
  184 + target[ key ] = $.isPlainObject( target[ key ] ) ?
  185 + $.widget.extend( {}, target[ key ], value ) :
  186 + // Don't extend strings, arrays, etc. with objects
  187 + $.widget.extend( {}, value );
  188 + // Copy everything else by reference
  189 + } else {
  190 + target[ key ] = value;
  191 + }
  192 + }
  193 + }
  194 + }
  195 + return target;
  196 +};
  197 +
  198 +$.widget.bridge = function( name, object ) {
  199 + var fullName = object.prototype.widgetFullName || name;
  200 + $.fn[ name ] = function( options ) {
  201 + var isMethodCall = typeof options === "string",
  202 + args = widget_slice.call( arguments, 1 ),
  203 + returnValue = this;
  204 +
  205 + if ( isMethodCall ) {
  206 + this.each(function() {
  207 + var methodValue,
  208 + instance = $.data( this, fullName );
  209 + if ( options === "instance" ) {
  210 + returnValue = instance;
  211 + return false;
  212 + }
  213 + if ( !instance ) {
  214 + return $.error( "cannot call methods on " + name + " prior to initialization; " +
  215 + "attempted to call method '" + options + "'" );
  216 + }
  217 + if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
  218 + return $.error( "no such method '" + options + "' for " + name + " widget instance" );
  219 + }
  220 + methodValue = instance[ options ].apply( instance, args );
  221 + if ( methodValue !== instance && methodValue !== undefined ) {
  222 + returnValue = methodValue && methodValue.jquery ?
  223 + returnValue.pushStack( methodValue.get() ) :
  224 + methodValue;
  225 + return false;
  226 + }
  227 + });
  228 + } else {
  229 +
  230 + // Allow multiple hashes to be passed on init
  231 + if ( args.length ) {
  232 + options = $.widget.extend.apply( null, [ options ].concat(args) );
  233 + }
  234 +
  235 + this.each(function() {
  236 + var instance = $.data( this, fullName );
  237 + if ( instance ) {
  238 + instance.option( options || {} );
  239 + if ( instance._init ) {
  240 + instance._init();
  241 + }
  242 + } else {
  243 + $.data( this, fullName, new object( options, this ) );
  244 + }
  245 + });
  246 + }
  247 +
  248 + return returnValue;
  249 + };
  250 +};
  251 +
  252 +$.Widget = function( /* options, element */ ) {};
  253 +$.Widget._childConstructors = [];
  254 +
  255 +$.Widget.prototype = {
  256 + widgetName: "widget",
  257 + widgetEventPrefix: "",
  258 + defaultElement: "<div>",
  259 + options: {
  260 + disabled: false,
  261 +
  262 + // callbacks
  263 + create: null
  264 + },
  265 + _createWidget: function( options, element ) {
  266 + element = $( element || this.defaultElement || this )[ 0 ];
  267 + this.element = $( element );
  268 + this.uuid = widget_uuid++;
  269 + this.eventNamespace = "." + this.widgetName + this.uuid;
  270 +
  271 + this.bindings = $();
  272 + this.hoverable = $();
  273 + this.focusable = $();
  274 +
  275 + if ( element !== this ) {
  276 + $.data( element, this.widgetFullName, this );
  277 + this._on( true, this.element, {
  278 + remove: function( event ) {
  279 + if ( event.target === element ) {
  280 + this.destroy();
  281 + }
  282 + }
  283 + });
  284 + this.document = $( element.style ?
  285 + // element within the document
  286 + element.ownerDocument :
  287 + // element is window or document
  288 + element.document || element );
  289 + this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
  290 + }
  291 +
  292 + this.options = $.widget.extend( {},
  293 + this.options,
  294 + this._getCreateOptions(),
  295 + options );
  296 +
  297 + this._create();
  298 + this._trigger( "create", null, this._getCreateEventData() );
  299 + this._init();
  300 + },
  301 + _getCreateOptions: $.noop,
  302 + _getCreateEventData: $.noop,
  303 + _create: $.noop,
  304 + _init: $.noop,
  305 +
  306 + destroy: function() {
  307 + this._destroy();
  308 + // we can probably remove the unbind calls in 2.0
  309 + // all event bindings should go through this._on()
  310 + this.element
  311 + .unbind( this.eventNamespace )
  312 + .removeData( this.widgetFullName )
  313 + // support: jquery <1.6.3
  314 + // http://bugs.jquery.com/ticket/9413
  315 + .removeData( $.camelCase( this.widgetFullName ) );
  316 + this.widget()
  317 + .unbind( this.eventNamespace )
  318 + .removeAttr( "aria-disabled" )
  319 + .removeClass(
  320 + this.widgetFullName + "-disabled " +
  321 + "ui-state-disabled" );
  322 +
  323 + // clean up events and states
  324 + this.bindings.unbind( this.eventNamespace );
  325 + this.hoverable.removeClass( "ui-state-hover" );
  326 + this.focusable.removeClass( "ui-state-focus" );
  327 + },
  328 + _destroy: $.noop,
  329 +
  330 + widget: function() {
  331 + return this.element;
  332 + },
  333 +
  334 + option: function( key, value ) {
  335 + var options = key,
  336 + parts,
  337 + curOption,
  338 + i;
  339 +
  340 + if ( arguments.length === 0 ) {
  341 + // don't return a reference to the internal hash
  342 + return $.widget.extend( {}, this.options );
  343 + }
  344 +
  345 + if ( typeof key === "string" ) {
  346 + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
  347 + options = {};
  348 + parts = key.split( "." );
  349 + key = parts.shift();
  350 + if ( parts.length ) {
  351 + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
  352 + for ( i = 0; i < parts.length - 1; i++ ) {
  353 + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
  354 + curOption = curOption[ parts[ i ] ];
  355 + }
  356 + key = parts.pop();
  357 + if ( arguments.length === 1 ) {
  358 + return curOption[ key ] === undefined ? null : curOption[ key ];
  359 + }
  360 + curOption[ key ] = value;
  361 + } else {
  362 + if ( arguments.length === 1 ) {
  363 + return this.options[ key ] === undefined ? null : this.options[ key ];
  364 + }
  365 + options[ key ] = value;
  366 + }
  367 + }
  368 +
  369 + this._setOptions( options );
  370 +
  371 + return this;
  372 + },
  373 + _setOptions: function( options ) {
  374 + var key;
  375 +
  376 + for ( key in options ) {
  377 + this._setOption( key, options[ key ] );
  378 + }
  379 +
  380 + return this;
  381 + },
  382 + _setOption: function( key, value ) {
  383 + this.options[ key ] = value;
  384 +
  385 + if ( key === "disabled" ) {
  386 + this.widget()
  387 + .toggleClass( this.widgetFullName + "-disabled", !!value );
  388 +
  389 + // If the widget is becoming disabled, then nothing is interactive
  390 + if ( value ) {
  391 + this.hoverable.removeClass( "ui-state-hover" );
  392 + this.focusable.removeClass( "ui-state-focus" );
  393 + }
  394 + }
  395 +
  396 + return this;
  397 + },
  398 +
  399 + enable: function() {
  400 + return this._setOptions({ disabled: false });
  401 + },
  402 + disable: function() {
  403 + return this._setOptions({ disabled: true });
  404 + },
  405 +
  406 + _on: function( suppressDisabledCheck, element, handlers ) {
  407 + var delegateElement,
  408 + instance = this;
  409 +
  410 + // no suppressDisabledCheck flag, shuffle arguments
  411 + if ( typeof suppressDisabledCheck !== "boolean" ) {
  412 + handlers = element;
  413 + element = suppressDisabledCheck;
  414 + suppressDisabledCheck = false;
  415 + }
  416 +
  417 + // no element argument, shuffle and use this.element
  418 + if ( !handlers ) {
  419 + handlers = element;
  420 + element = this.element;
  421 + delegateElement = this.widget();
  422 + } else {
  423 + element = delegateElement = $( element );
  424 + this.bindings = this.bindings.add( element );
  425 + }
  426 +
  427 + $.each( handlers, function( event, handler ) {
  428 + function handlerProxy() {
  429 + // allow widgets to customize the disabled handling
  430 + // - disabled as an array instead of boolean
  431 + // - disabled class as method for disabling individual parts
  432 + if ( !suppressDisabledCheck &&
  433 + ( instance.options.disabled === true ||
  434 + $( this ).hasClass( "ui-state-disabled" ) ) ) {
  435 + return;
  436 + }
  437 + return ( typeof handler === "string" ? instance[ handler ] : handler )
  438 + .apply( instance, arguments );
  439 + }
  440 +
  441 + // copy the guid so direct unbinding works
  442 + if ( typeof handler !== "string" ) {
  443 + handlerProxy.guid = handler.guid =
  444 + handler.guid || handlerProxy.guid || $.guid++;
  445 + }
  446 +
  447 + var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
  448 + eventName = match[1] + instance.eventNamespace,
  449 + selector = match[2];
  450 + if ( selector ) {
  451 + delegateElement.delegate( selector, eventName, handlerProxy );
  452 + } else {
  453 + element.bind( eventName, handlerProxy );
  454 + }
  455 + });
  456 + },
  457 +
  458 + _off: function( element, eventName ) {
  459 + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
  460 + this.eventNamespace;
  461 + element.unbind( eventName ).undelegate( eventName );
  462 +
  463 + // Clear the stack to avoid memory leaks (#10056)
  464 + this.bindings = $( this.bindings.not( element ).get() );
  465 + this.focusable = $( this.focusable.not( element ).get() );
  466 + this.hoverable = $( this.hoverable.not( element ).get() );
  467 + },
  468 +
  469 + _delay: function( handler, delay ) {
  470 + function handlerProxy() {
  471 + return ( typeof handler === "string" ? instance[ handler ] : handler )
  472 + .apply( instance, arguments );
  473 + }
  474 + var instance = this;
  475 + return setTimeout( handlerProxy, delay || 0 );
  476 + },
  477 +
  478 + _hoverable: function( element ) {
  479 + this.hoverable = this.hoverable.add( element );
  480 + this._on( element, {
  481 + mouseenter: function( event ) {
  482 + $( event.currentTarget ).addClass( "ui-state-hover" );
  483 + },
  484 + mouseleave: function( event ) {
  485 + $( event.currentTarget ).removeClass( "ui-state-hover" );
  486 + }
  487 + });
  488 + },
  489 +
  490 + _focusable: function( element ) {
  491 + this.focusable = this.focusable.add( element );
  492 + this._on( element, {
  493 + focusin: function( event ) {
  494 + $( event.currentTarget ).addClass( "ui-state-focus" );
  495 + },
  496 + focusout: function( event ) {
  497 + $( event.currentTarget ).removeClass( "ui-state-focus" );
  498 + }
  499 + });
  500 + },
  501 +
  502 + _trigger: function( type, event, data ) {
  503 + var prop, orig,
  504 + callback = this.options[ type ];
  505 +
  506 + data = data || {};
  507 + event = $.Event( event );
  508 + event.type = ( type === this.widgetEventPrefix ?
  509 + type :
  510 + this.widgetEventPrefix + type ).toLowerCase();
  511 + // the original event may come from any element
  512 + // so we need to reset the target on the new event
  513 + event.target = this.element[ 0 ];
  514 +
  515 + // copy original event properties over to the new event
  516 + orig = event.originalEvent;
  517 + if ( orig ) {
  518 + for ( prop in orig ) {
  519 + if ( !( prop in event ) ) {
  520 + event[ prop ] = orig[ prop ];
  521 + }
  522 + }
  523 + }
  524 +
  525 + this.element.trigger( event, data );
  526 + return !( $.isFunction( callback ) &&
  527 + callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
  528 + event.isDefaultPrevented() );
  529 + }
  530 +};
  531 +
  532 +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
  533 + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
  534 + if ( typeof options === "string" ) {
  535 + options = { effect: options };
  536 + }
  537 + var hasOptions,
  538 + effectName = !options ?
  539 + method :
  540 + options === true || typeof options === "number" ?
  541 + defaultEffect :
  542 + options.effect || defaultEffect;
  543 + options = options || {};
  544 + if ( typeof options === "number" ) {
  545 + options = { duration: options };
  546 + }
  547 + hasOptions = !$.isEmptyObject( options );
  548 + options.complete = callback;
  549 + if ( options.delay ) {
  550 + element.delay( options.delay );
  551 + }
  552 + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
  553 + element[ method ]( options );
  554 + } else if ( effectName !== method && element[ effectName ] ) {
  555 + element[ effectName ]( options.duration, options.easing, callback );
  556 + } else {
  557 + element.queue(function( next ) {
  558 + $( this )[ method ]();
  559 + if ( callback ) {
  560 + callback.call( element[ 0 ] );
  561 + }
  562 + next();
  563 + });
  564 + }
  565 + };
  566 +});
  567 +
  568 +var widget = $.widget;
  569 +
  570 +
  571 +
  572 +}));
view/assets/js/external-libs/js.cookie.js 0 → 100644
@@ -0,0 +1,145 @@ @@ -0,0 +1,145 @@
  1 +/*!
  2 + * JavaScript Cookie v2.0.4
  3 + * https://github.com/js-cookie/js-cookie
  4 + *
  5 + * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
  6 + * Released under the MIT license
  7 + */
  8 +(function(factory) {
  9 + if (typeof define === 'function' && define.amd) {
  10 + define(factory);
  11 + } else if (typeof exports === 'object') {
  12 + module.exports = factory();
  13 + } else {
  14 + var _OldCookies = window.Cookies;
  15 + var api = window.Cookies = factory();
  16 + api.noConflict = function() {
  17 + window.Cookies = _OldCookies;
  18 + return api;
  19 + };
  20 + }
  21 +}(function() {
  22 + function extend() {
  23 + var i = 0;
  24 + var result = {};
  25 + for (; i < arguments.length; i++) {
  26 + var attributes = arguments[ i ];
  27 + for (var key in attributes) {
  28 + result[key] = attributes[key];
  29 + }
  30 + }
  31 + return result;
  32 + }
  33 +
  34 + function init(converter) {
  35 + function api(key, value, attributes) {
  36 + var result;
  37 +
  38 + // Write
  39 +
  40 + if (arguments.length > 1) {
  41 + attributes = extend({
  42 + path: '/'
  43 + }, api.defaults, attributes);
  44 +
  45 + if (typeof attributes.expires === 'number') {
  46 + var expires = new Date();
  47 + expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
  48 + attributes.expires = expires;
  49 + }
  50 +
  51 + try {
  52 + result = JSON.stringify(value);
  53 + if (/^[\{\[]/.test(result)) {
  54 + value = result;
  55 + }
  56 + } catch (e) {}
  57 +
  58 + if (!converter.write) {
  59 + value = encodeURIComponent(String(value))
  60 + .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
  61 + } else {
  62 + value = converter.write(value, key);
  63 + }
  64 +
  65 + key = encodeURIComponent(String(key));
  66 + key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
  67 + key = key.replace(/[\(\)]/g, escape);
  68 +
  69 + return (document.cookie = [
  70 + key, '=', value,
  71 + attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
  72 + attributes.path && '; path=' + attributes.path,
  73 + attributes.domain && '; domain=' + attributes.domain,
  74 + attributes.secure ? '; secure' : ''
  75 + ].join(''));
  76 + }
  77 +
  78 + // Read
  79 +
  80 + if (!key) {
  81 + result = {};
  82 + }
  83 +
  84 + // To prevent the for loop in the first place assign an empty array
  85 + // in case there are no cookies at all. Also prevents odd result when
  86 + // calling "get()"
  87 + var cookies = document.cookie ? document.cookie.split('; ') : [];
  88 + var rdecode = /(%[0-9A-Z]{2})+/g;
  89 + var i = 0;
  90 +
  91 + for (; i < cookies.length; i++) {
  92 + var parts = cookies[i].split('=');
  93 + var name = parts[0].replace(rdecode, decodeURIComponent);
  94 + var cookie = parts.slice(1).join('=');
  95 +
  96 + if (cookie.charAt(0) === '"') {
  97 + cookie = cookie.slice(1, -1);
  98 + }
  99 +
  100 + try {
  101 + cookie = converter.read ?
  102 + converter.read(cookie, name) : converter(cookie, name) ||
  103 + cookie.replace(rdecode, decodeURIComponent);
  104 +
  105 + if (this.json) {
  106 + try {
  107 + cookie = JSON.parse(cookie);
  108 + } catch (e) {}
  109 + }
  110 +
  111 + if (key === name) {
  112 + result = cookie;
  113 + break;
  114 + }
  115 +
  116 + if (!key) {
  117 + result[name] = cookie;
  118 + }
  119 + } catch (e) {}
  120 + }
  121 +
  122 + return result;
  123 + }
  124 +
  125 + api.get = api.set = api;
  126 + api.getJSON = function() {
  127 + return api.apply({
  128 + json: true
  129 + }, [].slice.call(arguments));
  130 + };
  131 + api.defaults = {};
  132 +
  133 + api.remove = function(key, attributes) {
  134 + api(key, '', extend(attributes, {
  135 + expires: -1
  136 + }));
  137 + };
  138 +
  139 + api.withConverter = init;
  140 +
  141 + return api;
  142 + }
  143 +
  144 + return init(function() {});
  145 +}));
view/assets/js/facial.js
@@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
1 -(function(facial, $, undefined) {  
2 -  
3 - facial.setup = function(subConfig) {  
4 - var baseId = '.selection-panel-body[mainConfig=facial][subConfig='  
5 - + subConfig + ']';  
6 - $(baseId + ' .selection-panel-option').off('click').on('click',  
7 - function() {  
8 - wikilibras.selectAnOption(baseId, this);  
9 - dynworkflow.userSelectedAnOption();  
10 - });  
11 - $(baseId + ' .video-panel-option').off('mouseenter').on('mouseenter',  
12 - function(event) {  
13 - $(this).addClass('video-panel-option-hover');  
14 - });  
15 - $(baseId + ' .video-panel-option').off('mouseleave').on('mouseleave',  
16 - function(event) {  
17 - $(this).removeClass('video-panel-option-hover');  
18 - });  
19 - };  
20 -  
21 -}(window.facial = window.facial || {}, jQuery));  
view/assets/js/helpers/icon-helper.js 0 → 100644
@@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
  1 +(function(iconHelper, $, undefined) {
  2 +
  3 + var baseUrl = '';
  4 +
  5 + function _changeImage(img, url) {
  6 + img.attr('src', url);
  7 + }
  8 +
  9 + function _enableIconHover(container, isHover) {
  10 + var img = $(container).find('img').first();
  11 + var hover_img_url = baseUrl + '/img/' + $(container).attr('name');
  12 + if (isHover) {
  13 + hover_img_url += '-icon-hover.png';
  14 + } else {
  15 + hover_img_url += '-icon.png';
  16 + }
  17 + _changeImage(img, hover_img_url);
  18 + }
  19 +
  20 + function _enableIconCheck(container, isCheck) {
  21 + var img = $(container).find('img').first();
  22 + var check_img_url = baseUrl + '/img/' + $(container).attr('name');
  23 + if (isCheck) {
  24 + check_img_url += '-icon-check.png';
  25 + } else {
  26 + check_img_url += '-icon.png';
  27 + }
  28 + _changeImage(img, check_img_url);
  29 + }
  30 +
  31 + function _selectIcon(iconName, isSelect, panel) {
  32 + panel = typeof panel == 'undefined' ? '' : '[panel=' + panel + ']';
  33 + var icon_id = '.icon_container[name=' + iconName + ']' + panel;
  34 + _enableIconHover(icon_id, isSelect);
  35 + $(icon_id).attr('select', isSelect);
  36 + }
  37 +
  38 + function _deselectIcon(iconName, parent) {
  39 + _selectIcon(iconName, false, parent);
  40 + }
  41 +
  42 + function _setupCheckIcon(option, isCheck, panel) {
  43 + panel = typeof panel == 'undefined' ? '' : '[panel=' + panel + ']';
  44 + var icon_id = '.icon_container[name=' + option + ']' + panel;
  45 + iconHelper.enableIconCheck(icon_id, isCheck);
  46 + $('.icon_container[name=' + option + ']' + panel).attr('complete',
  47 + isCheck);
  48 + }
  49 +
  50 + function _canHover(el) {
  51 + var incompleteConfig = typeof $(el).attr('complete') == 'undefined'
  52 + || $(el).attr('complete') == 'false';
  53 + return (!configurationScreen.isMenuSelected() && incompleteConfig)
  54 + || (typeof $(el).attr('select') == 'undefined' && incompleteConfig);
  55 + }
  56 +
  57 + iconHelper.enableIconHover = function(container, isHover) {
  58 + _enableIconHover(container, isHover);
  59 + }
  60 +
  61 + iconHelper.enableIconCheck = function(container, isCheck) {
  62 + _enableIconCheck(container, isCheck);
  63 + }
  64 +
  65 + iconHelper.setupCheckIcon = function(option, isCheck, panel) {
  66 + _setupCheckIcon(option, isCheck, panel);
  67 + }
  68 +
  69 + iconHelper.selectIcon = function(iconName, isSelect, panel) {
  70 + _selectIcon(iconName, isSelect, panel);
  71 + }
  72 +
  73 + iconHelper.deselectIcon = function(iconName, parent) {
  74 + _deselectIcon(iconName, parent);
  75 + }
  76 +
  77 + iconHelper.canHover = function(el) {
  78 + return _canHover(el);
  79 + }
  80 +
  81 + iconHelper.setup = function(url) {
  82 + baseUrl = url;
  83 + };
  84 +
  85 +}(window.iconHelper = window.iconHelper || {}, jQuery));
view/assets/js/helpers/tmpJSONParser.js 0 → 100644
@@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
  1 +(function(tmpJSONParser, $, undefined) {
  2 +
  3 + var base_parameter_json = {};
  4 + var movement_parameter_json = {};
  5 +
  6 + function _setupBaseParameterJSON(tmpJSON) {
  7 + base_parameter_json['userId'] = tmpJSON['userId'];
  8 + base_parameter_json['sinal'] = tmpJSON['sinal'];
  9 + base_parameter_json['interpolacao'] = 'normal';
  10 + base_parameter_json['movimentos'] = [];
  11 + movement_parameter_json = {
  12 + 'facial': {},
  13 + 'mao_direita': {},
  14 + 'mao_esquerda': {}
  15 + };
  16 + base_parameter_json['movimentos'].push(movement_parameter_json);
  17 + }
  18 +
  19 + function _parseParameterValue(value) {
  20 + if (typeof value == 'string' && value.toLowerCase() == 'true') {
  21 + return true;
  22 + } else if (typeof value == 'string' && value.toLowerCase() == 'false') {
  23 + return false;
  24 + } else {
  25 + return !isNaN(value) ? parseInt(value) : value;
  26 + }
  27 + }
  28 +
  29 + function _parseTempFacialParameterJSON(tmpJSON) {
  30 + var attrs = dynworkflow.getFacialParameters();
  31 + for (var i in attrs) {
  32 + var attr = attrs[i];
  33 + parameterValue = tmpJSON['facial'][attr][0];
  34 + movement_parameter_json['facial'][attr] = _parseParameterValue(parameterValue);
  35 + }
  36 + }
  37 +
  38 + function _parseHand(hand) {
  39 + var parsedHand = hand == 'right-hand' ? 'mao_direita' : hand;
  40 + parsedHand = hand == 'left-hand' ? 'mao_esquerda' : parsedHand;
  41 + return parsedHand;
  42 + }
  43 +
  44 + // Default parser
  45 + function _defaultMovementParser(tmpJSON, movementName, hand) {
  46 + var attrs = dynworkflow.getMovementParameters(movementName);
  47 + var parsedHand = _parseHand(hand);
  48 +
  49 + for (var i in attrs) {
  50 + var attr = attrs[i];
  51 + var parameterValue = '';
  52 + if (typeof tmpJSON[hand][attr] == "undefined") {
  53 + continue;
  54 + }
  55 + if (attr == 'configuracao') {
  56 + parameterValue = tmpJSON[hand][attr][1];
  57 + } else if (attr == 'articulacao') {
  58 + parameterValue = articulation.processValue(hand, tmpJSON[hand][attr]);
  59 + } else {
  60 + parameterValue = tmpJSON[hand][attr][0];
  61 + }
  62 + movement_parameter_json[parsedHand][movementName][attr] =
  63 + _parseParameterValue(parameterValue);
  64 + }
  65 + }
  66 +
  67 + function _retilinearMovementParser(tmpJSON, movementName, hand) {
  68 + var attrs = dynworkflow.getMovementParameters(movementName);
  69 + var parsedHand = _parseHand(hand);
  70 +
  71 + for (var i in attrs) {
  72 + var attr = attrs[i];
  73 + var initParameterValue = '';
  74 + var endParameterValue = '';
  75 + if (attr == 'configuracao-retilineo') {
  76 + initParameterValue = tmpJSON[hand][attr][1];
  77 + endParameterValue = tmpJSON[hand][attr][3];
  78 + } else if (attr == 'articulacao-retilineo') {
  79 + initSlice = tmpJSON[hand][attr].slice(0, 2);
  80 + endSlice = tmpJSON[hand][attr].slice(2, 4);
  81 + initParameterValue = articulation.processValue(hand, initSlice);
  82 + endParameterValue = articulation.processValue(hand, endSlice);
  83 + } else {
  84 + initParameterValue = tmpJSON[hand][attr][0];
  85 + endParameterValue = tmpJSON[hand][attr][1];
  86 + }
  87 + attr = attr.replace('-retilineo', '');
  88 + var initAttr = attr + '_inicial';
  89 + var endAttr = attr + '_final';
  90 + movement_parameter_json[parsedHand][movementName][initAttr] =
  91 + _parseParameterValue(initParameterValue);
  92 + movement_parameter_json[parsedHand][movementName][endAttr] =
  93 + _parseParameterValue(endParameterValue);
  94 + }
  95 + }
  96 +
  97 + function _parseTempMovementParameterJSON(tmpJSON, hand) {
  98 + var movimentConfig = tmpJSON[hand]['movimento'];
  99 + if (typeof movimentConfig == 'undefined') return;
  100 +
  101 + var movementName = movimentConfig[0];
  102 + var parsedHand = _parseHand(hand);
  103 + movement_parameter_json[parsedHand][movementName] = {};
  104 +
  105 + if (movementName == 'retilineo') {
  106 + _retilinearMovementParser(tmpJSON, movementName, hand);
  107 + } else {
  108 + _defaultMovementParser(tmpJSON, movementName, hand);
  109 + }
  110 + }
  111 +
  112 + tmpJSONParser.parse = function(tmpJSON, rightHand, leftHand) {
  113 + _setupBaseParameterJSON(tmpJSON);
  114 + _parseTempFacialParameterJSON(tmpJSON);
  115 + if (rightHand) {
  116 + _parseTempMovementParameterJSON(tmpJSON, 'right-hand');
  117 + }
  118 + if (leftHand) {
  119 + _parseTempMovementParameterJSON(tmpJSON, 'left-hand');
  120 + }
  121 + return base_parameter_json;
  122 + };
  123 +
  124 +}(window.tmpJSONParser = window.tmpJSONParser || {}, jQuery));
view/assets/js/helpers/video-helper.js 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +(function(videoHelper, $, undefined) {
  2 +
  3 + function _controlVideo(elId, toPlay) {
  4 + var videoSrc = $(elId).attr("src");
  5 + if (typeof videoSrc == "undefined" ||
  6 + (typeof videoSrc != "undefined" && videoSrc === ""))
  7 + return;
  8 + if (toPlay) {
  9 + $(elId).get(0).play();
  10 + } else {
  11 + $(elId).get(0).pause();
  12 + }
  13 + }
  14 +
  15 + videoHelper.play = function(elId) {
  16 + _controlVideo(elId, true);
  17 + }
  18 +
  19 + videoHelper.pause = function(elId) {
  20 + _controlVideo(elId, false);
  21 + }
  22 +
  23 +}(window.videoHelper = window.videoHelper || {}, jQuery));
view/assets/js/jquery.fileupload.js
@@ -1,1477 +0,0 @@ @@ -1,1477 +0,0 @@
1 -/*  
2 - * jQuery File Upload Plugin  
3 - * https://github.com/blueimp/jQuery-File-Upload  
4 - *  
5 - * Copyright 2010, Sebastian Tschan  
6 - * https://blueimp.net  
7 - *  
8 - * Licensed under the MIT license:  
9 - * http://www.opensource.org/licenses/MIT  
10 - */  
11 -  
12 -/* jshint nomen:false */  
13 -/* global define, require, window, document, location, Blob, FormData */  
14 -  
15 -(function (factory) {  
16 - 'use strict';  
17 - if (typeof define === 'function' && define.amd) {  
18 - // Register as an anonymous AMD module:  
19 - define([  
20 - 'jquery',  
21 - 'jquery.ui.widget'  
22 - ], factory);  
23 - } else if (typeof exports === 'object') {  
24 - // Node/CommonJS:  
25 - factory(  
26 - require('jquery'),  
27 - require('./vendor/jquery.ui.widget')  
28 - );  
29 - } else {  
30 - // Browser globals:  
31 - factory(window.jQuery);  
32 - }  
33 -}(function ($) {  
34 - 'use strict';  
35 -  
36 - // Detect file input support, based on  
37 - // http://viljamis.com/blog/2012/file-upload-support-on-mobile/  
38 - $.support.fileInput = !(new RegExp(  
39 - // Handle devices which give false positives for the feature detection:  
40 - '(Android (1\\.[0156]|2\\.[01]))' +  
41 - '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' +  
42 - '|(w(eb)?OSBrowser)|(webOS)' +  
43 - '|(Kindle/(1\\.0|2\\.[05]|3\\.0))'  
44 - ).test(window.navigator.userAgent) ||  
45 - // Feature detection for all other devices:  
46 - $('<input type="file">').prop('disabled'));  
47 -  
48 - // The FileReader API is not actually used, but works as feature detection,  
49 - // as some Safari versions (5?) support XHR file uploads via the FormData API,  
50 - // but not non-multipart XHR file uploads.  
51 - // window.XMLHttpRequestUpload is not available on IE10, so we check for  
52 - // window.ProgressEvent instead to detect XHR2 file upload capability:  
53 - $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader);  
54 - $.support.xhrFormDataFileUpload = !!window.FormData;  
55 -  
56 - // Detect support for Blob slicing (required for chunked uploads):  
57 - $.support.blobSlice = window.Blob && (Blob.prototype.slice ||  
58 - Blob.prototype.webkitSlice || Blob.prototype.mozSlice);  
59 -  
60 - // Helper function to create drag handlers for dragover/dragenter/dragleave:  
61 - function getDragHandler(type) {  
62 - var isDragOver = type === 'dragover';  
63 - return function (e) {  
64 - e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;  
65 - var dataTransfer = e.dataTransfer;  
66 - if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 &&  
67 - this._trigger(  
68 - type,  
69 - $.Event(type, {delegatedEvent: e})  
70 - ) !== false) {  
71 - e.preventDefault();  
72 - if (isDragOver) {  
73 - dataTransfer.dropEffect = 'copy';  
74 - }  
75 - }  
76 - };  
77 - }  
78 -  
79 - // The fileupload widget listens for change events on file input fields defined  
80 - // via fileInput setting and paste or drop events of the given dropZone.  
81 - // In addition to the default jQuery Widget methods, the fileupload widget  
82 - // exposes the "add" and "send" methods, to add or directly send files using  
83 - // the fileupload API.  
84 - // By default, files added via file input selection, paste, drag & drop or  
85 - // "add" method are uploaded immediately, but it is possible to override  
86 - // the "add" callback option to queue file uploads.  
87 - $.widget('blueimp.fileupload', {  
88 -  
89 - options: {  
90 - // The drop target element(s), by the default the complete document.  
91 - // Set to null to disable drag & drop support:  
92 - dropZone: $(document),  
93 - // The paste target element(s), by the default undefined.  
94 - // Set to a DOM node or jQuery object to enable file pasting:  
95 - pasteZone: undefined,  
96 - // The file input field(s), that are listened to for change events.  
97 - // If undefined, it is set to the file input fields inside  
98 - // of the widget element on plugin initialization.  
99 - // Set to null to disable the change listener.  
100 - fileInput: undefined,  
101 - // By default, the file input field is replaced with a clone after  
102 - // each input field change event. This is required for iframe transport  
103 - // queues and allows change events to be fired for the same file  
104 - // selection, but can be disabled by setting the following option to false:  
105 - replaceFileInput: true,  
106 - // The parameter name for the file form data (the request argument name).  
107 - // If undefined or empty, the name property of the file input field is  
108 - // used, or "files[]" if the file input name property is also empty,  
109 - // can be a string or an array of strings:  
110 - paramName: undefined,  
111 - // By default, each file of a selection is uploaded using an individual  
112 - // request for XHR type uploads. Set to false to upload file  
113 - // selections in one request each:  
114 - singleFileUploads: true,  
115 - // To limit the number of files uploaded with one XHR request,  
116 - // set the following option to an integer greater than 0:  
117 - limitMultiFileUploads: undefined,  
118 - // The following option limits the number of files uploaded with one  
119 - // XHR request to keep the request size under or equal to the defined  
120 - // limit in bytes:  
121 - limitMultiFileUploadSize: undefined,  
122 - // Multipart file uploads add a number of bytes to each uploaded file,  
123 - // therefore the following option adds an overhead for each file used  
124 - // in the limitMultiFileUploadSize configuration:  
125 - limitMultiFileUploadSizeOverhead: 512,  
126 - // Set the following option to true to issue all file upload requests  
127 - // in a sequential order:  
128 - sequentialUploads: false,  
129 - // To limit the number of concurrent uploads,  
130 - // set the following option to an integer greater than 0:  
131 - limitConcurrentUploads: undefined,  
132 - // Set the following option to true to force iframe transport uploads:  
133 - forceIframeTransport: false,  
134 - // Set the following option to the location of a redirect url on the  
135 - // origin server, for cross-domain iframe transport uploads:  
136 - redirect: undefined,  
137 - // The parameter name for the redirect url, sent as part of the form  
138 - // data and set to 'redirect' if this option is empty:  
139 - redirectParamName: undefined,  
140 - // Set the following option to the location of a postMessage window,  
141 - // to enable postMessage transport uploads:  
142 - postMessage: undefined,  
143 - // By default, XHR file uploads are sent as multipart/form-data.  
144 - // The iframe transport is always using multipart/form-data.  
145 - // Set to false to enable non-multipart XHR uploads:  
146 - multipart: true,  
147 - // To upload large files in smaller chunks, set the following option  
148 - // to a preferred maximum chunk size. If set to 0, null or undefined,  
149 - // or the browser does not support the required Blob API, files will  
150 - // be uploaded as a whole.  
151 - maxChunkSize: undefined,  
152 - // When a non-multipart upload or a chunked multipart upload has been  
153 - // aborted, this option can be used to resume the upload by setting  
154 - // it to the size of the already uploaded bytes. This option is most  
155 - // useful when modifying the options object inside of the "add" or  
156 - // "send" callbacks, as the options are cloned for each file upload.  
157 - uploadedBytes: undefined,  
158 - // By default, failed (abort or error) file uploads are removed from the  
159 - // global progress calculation. Set the following option to false to  
160 - // prevent recalculating the global progress data:  
161 - recalculateProgress: true,  
162 - // Interval in milliseconds to calculate and trigger progress events:  
163 - progressInterval: 100,  
164 - // Interval in milliseconds to calculate progress bitrate:  
165 - bitrateInterval: 500,  
166 - // By default, uploads are started automatically when adding files:  
167 - autoUpload: true,  
168 -  
169 - // Error and info messages:  
170 - messages: {  
171 - uploadedBytes: 'Uploaded bytes exceed file size'  
172 - },  
173 -  
174 - // Translation function, gets the message key to be translated  
175 - // and an object with context specific data as arguments:  
176 - i18n: function (message, context) {  
177 - message = this.messages[message] || message.toString();  
178 - if (context) {  
179 - $.each(context, function (key, value) {  
180 - message = message.replace('{' + key + '}', value);  
181 - });  
182 - }  
183 - return message;  
184 - },  
185 -  
186 - // Additional form data to be sent along with the file uploads can be set  
187 - // using this option, which accepts an array of objects with name and  
188 - // value properties, a function returning such an array, a FormData  
189 - // object (for XHR file uploads), or a simple object.  
190 - // The form of the first fileInput is given as parameter to the function:  
191 - formData: function (form) {  
192 - return form.serializeArray();  
193 - },  
194 -  
195 - // The add callback is invoked as soon as files are added to the fileupload  
196 - // widget (via file input selection, drag & drop, paste or add API call).  
197 - // If the singleFileUploads option is enabled, this callback will be  
198 - // called once for each file in the selection for XHR file uploads, else  
199 - // once for each file selection.  
200 - //  
201 - // The upload starts when the submit method is invoked on the data parameter.  
202 - // The data object contains a files property holding the added files  
203 - // and allows you to override plugin options as well as define ajax settings.  
204 - //  
205 - // Listeners for this callback can also be bound the following way:  
206 - // .bind('fileuploadadd', func);  
207 - //  
208 - // data.submit() returns a Promise object and allows to attach additional  
209 - // handlers using jQuery's Deferred callbacks:  
210 - // data.submit().done(func).fail(func).always(func);  
211 - add: function (e, data) {  
212 - if (e.isDefaultPrevented()) {  
213 - return false;  
214 - }  
215 - if (data.autoUpload || (data.autoUpload !== false &&  
216 - $(this).fileupload('option', 'autoUpload'))) {  
217 - data.process().done(function () {  
218 - data.submit();  
219 - });  
220 - }  
221 - },  
222 -  
223 - // Other callbacks:  
224 -  
225 - // Callback for the submit event of each file upload:  
226 - // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);  
227 -  
228 - // Callback for the start of each file upload request:  
229 - // send: function (e, data) {}, // .bind('fileuploadsend', func);  
230 -  
231 - // Callback for successful uploads:  
232 - // done: function (e, data) {}, // .bind('fileuploaddone', func);  
233 -  
234 - // Callback for failed (abort or error) uploads:  
235 - // fail: function (e, data) {}, // .bind('fileuploadfail', func);  
236 -  
237 - // Callback for completed (success, abort or error) requests:  
238 - // always: function (e, data) {}, // .bind('fileuploadalways', func);  
239 -  
240 - // Callback for upload progress events:  
241 - // progress: function (e, data) {}, // .bind('fileuploadprogress', func);  
242 -  
243 - // Callback for global upload progress events:  
244 - // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);  
245 -  
246 - // Callback for uploads start, equivalent to the global ajaxStart event:  
247 - // start: function (e) {}, // .bind('fileuploadstart', func);  
248 -  
249 - // Callback for uploads stop, equivalent to the global ajaxStop event:  
250 - // stop: function (e) {}, // .bind('fileuploadstop', func);  
251 -  
252 - // Callback for change events of the fileInput(s):  
253 - // change: function (e, data) {}, // .bind('fileuploadchange', func);  
254 -  
255 - // Callback for paste events to the pasteZone(s):  
256 - // paste: function (e, data) {}, // .bind('fileuploadpaste', func);  
257 -  
258 - // Callback for drop events of the dropZone(s):  
259 - // drop: function (e, data) {}, // .bind('fileuploaddrop', func);  
260 -  
261 - // Callback for dragover events of the dropZone(s):  
262 - // dragover: function (e) {}, // .bind('fileuploaddragover', func);  
263 -  
264 - // Callback for the start of each chunk upload request:  
265 - // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func);  
266 -  
267 - // Callback for successful chunk uploads:  
268 - // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func);  
269 -  
270 - // Callback for failed (abort or error) chunk uploads:  
271 - // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func);  
272 -  
273 - // Callback for completed (success, abort or error) chunk upload requests:  
274 - // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func);  
275 -  
276 - // The plugin options are used as settings object for the ajax calls.  
277 - // The following are jQuery ajax settings required for the file uploads:  
278 - processData: false,  
279 - contentType: false,  
280 - cache: false,  
281 - timeout: 0  
282 - },  
283 -  
284 - // A list of options that require reinitializing event listeners and/or  
285 - // special initialization code:  
286 - _specialOptions: [  
287 - 'fileInput',  
288 - 'dropZone',  
289 - 'pasteZone',  
290 - 'multipart',  
291 - 'forceIframeTransport'  
292 - ],  
293 -  
294 - _blobSlice: $.support.blobSlice && function () {  
295 - var slice = this.slice || this.webkitSlice || this.mozSlice;  
296 - return slice.apply(this, arguments);  
297 - },  
298 -  
299 - _BitrateTimer: function () {  
300 - this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime());  
301 - this.loaded = 0;  
302 - this.bitrate = 0;  
303 - this.getBitrate = function (now, loaded, interval) {  
304 - var timeDiff = now - this.timestamp;  
305 - if (!this.bitrate || !interval || timeDiff > interval) {  
306 - this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8;  
307 - this.loaded = loaded;  
308 - this.timestamp = now;  
309 - }  
310 - return this.bitrate;  
311 - };  
312 - },  
313 -  
314 - _isXHRUpload: function (options) {  
315 - return !options.forceIframeTransport &&  
316 - ((!options.multipart && $.support.xhrFileUpload) ||  
317 - $.support.xhrFormDataFileUpload);  
318 - },  
319 -  
320 - _getFormData: function (options) {  
321 - var formData;  
322 - if ($.type(options.formData) === 'function') {  
323 - return options.formData(options.form);  
324 - }  
325 - if ($.isArray(options.formData)) {  
326 - return options.formData;  
327 - }  
328 - if ($.type(options.formData) === 'object') {  
329 - formData = [];  
330 - $.each(options.formData, function (name, value) {  
331 - formData.push({name: name, value: value});  
332 - });  
333 - return formData;  
334 - }  
335 - return [];  
336 - },  
337 -  
338 - _getTotal: function (files) {  
339 - var total = 0;  
340 - $.each(files, function (index, file) {  
341 - total += file.size || 1;  
342 - });  
343 - return total;  
344 - },  
345 -  
346 - _initProgressObject: function (obj) {  
347 - var progress = {  
348 - loaded: 0,  
349 - total: 0,  
350 - bitrate: 0  
351 - };  
352 - if (obj._progress) {  
353 - $.extend(obj._progress, progress);  
354 - } else {  
355 - obj._progress = progress;  
356 - }  
357 - },  
358 -  
359 - _initResponseObject: function (obj) {  
360 - var prop;  
361 - if (obj._response) {  
362 - for (prop in obj._response) {  
363 - if (obj._response.hasOwnProperty(prop)) {  
364 - delete obj._response[prop];  
365 - }  
366 - }  
367 - } else {  
368 - obj._response = {};  
369 - }  
370 - },  
371 -  
372 - _onProgress: function (e, data) {  
373 - if (e.lengthComputable) {  
374 - var now = ((Date.now) ? Date.now() : (new Date()).getTime()),  
375 - loaded;  
376 - if (data._time && data.progressInterval &&  
377 - (now - data._time < data.progressInterval) &&  
378 - e.loaded !== e.total) {  
379 - return;  
380 - }  
381 - data._time = now;  
382 - loaded = Math.floor(  
383 - e.loaded / e.total * (data.chunkSize || data._progress.total)  
384 - ) + (data.uploadedBytes || 0);  
385 - // Add the difference from the previously loaded state  
386 - // to the global loaded counter:  
387 - this._progress.loaded += (loaded - data._progress.loaded);  
388 - this._progress.bitrate = this._bitrateTimer.getBitrate(  
389 - now,  
390 - this._progress.loaded,  
391 - data.bitrateInterval  
392 - );  
393 - data._progress.loaded = data.loaded = loaded;  
394 - data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(  
395 - now,  
396 - loaded,  
397 - data.bitrateInterval  
398 - );  
399 - // Trigger a custom progress event with a total data property set  
400 - // to the file size(s) of the current upload and a loaded data  
401 - // property calculated accordingly:  
402 - this._trigger(  
403 - 'progress',  
404 - $.Event('progress', {delegatedEvent: e}),  
405 - data  
406 - );  
407 - // Trigger a global progress event for all current file uploads,  
408 - // including ajax calls queued for sequential file uploads:  
409 - this._trigger(  
410 - 'progressall',  
411 - $.Event('progressall', {delegatedEvent: e}),  
412 - this._progress  
413 - );  
414 - }  
415 - },  
416 -  
417 - _initProgressListener: function (options) {  
418 - var that = this,  
419 - xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();  
420 - // Accesss to the native XHR object is required to add event listeners  
421 - // for the upload progress event:  
422 - if (xhr.upload) {  
423 - $(xhr.upload).bind('progress', function (e) {  
424 - var oe = e.originalEvent;  
425 - // Make sure the progress event properties get copied over:  
426 - e.lengthComputable = oe.lengthComputable;  
427 - e.loaded = oe.loaded;  
428 - e.total = oe.total;  
429 - that._onProgress(e, options);  
430 - });  
431 - options.xhr = function () {  
432 - return xhr;  
433 - };  
434 - }  
435 - },  
436 -  
437 - _isInstanceOf: function (type, obj) {  
438 - // Cross-frame instanceof check  
439 - return Object.prototype.toString.call(obj) === '[object ' + type + ']';  
440 - },  
441 -  
442 - _initXHRData: function (options) {  
443 - var that = this,  
444 - formData,  
445 - file = options.files[0],  
446 - // Ignore non-multipart setting if not supported:  
447 - multipart = options.multipart || !$.support.xhrFileUpload,  
448 - paramName = $.type(options.paramName) === 'array' ?  
449 - options.paramName[0] : options.paramName;  
450 - options.headers = $.extend({}, options.headers);  
451 - if (options.contentRange) {  
452 - options.headers['Content-Range'] = options.contentRange;  
453 - }  
454 - if (!multipart || options.blob || !this._isInstanceOf('File', file)) {  
455 - options.headers['Content-Disposition'] = 'attachment; filename="' +  
456 - encodeURI(file.name) + '"';  
457 - }  
458 - if (!multipart) {  
459 - options.contentType = file.type || 'application/octet-stream';  
460 - options.data = options.blob || file;  
461 - } else if ($.support.xhrFormDataFileUpload) {  
462 - if (options.postMessage) {  
463 - // window.postMessage does not allow sending FormData  
464 - // objects, so we just add the File/Blob objects to  
465 - // the formData array and let the postMessage window  
466 - // create the FormData object out of this array:  
467 - formData = this._getFormData(options);  
468 - if (options.blob) {  
469 - formData.push({  
470 - name: paramName,  
471 - value: options.blob  
472 - });  
473 - } else {  
474 - $.each(options.files, function (index, file) {  
475 - formData.push({  
476 - name: ($.type(options.paramName) === 'array' &&  
477 - options.paramName[index]) || paramName,  
478 - value: file  
479 - });  
480 - });  
481 - }  
482 - } else {  
483 - if (that._isInstanceOf('FormData', options.formData)) {  
484 - formData = options.formData;  
485 - } else {  
486 - formData = new FormData();  
487 - $.each(this._getFormData(options), function (index, field) {  
488 - formData.append(field.name, field.value);  
489 - });  
490 - }  
491 - if (options.blob) {  
492 - formData.append(paramName, options.blob, file.name);  
493 - } else {  
494 - $.each(options.files, function (index, file) {  
495 - // This check allows the tests to run with  
496 - // dummy objects:  
497 - if (that._isInstanceOf('File', file) ||  
498 - that._isInstanceOf('Blob', file)) {  
499 - formData.append(  
500 - ($.type(options.paramName) === 'array' &&  
501 - options.paramName[index]) || paramName,  
502 - file,  
503 - file.uploadName || file.name  
504 - );  
505 - }  
506 - });  
507 - }  
508 - }  
509 - options.data = formData;  
510 - }  
511 - // Blob reference is not needed anymore, free memory:  
512 - options.blob = null;  
513 - },  
514 -  
515 - _initIframeSettings: function (options) {  
516 - var targetHost = $('<a></a>').prop('href', options.url).prop('host');  
517 - // Setting the dataType to iframe enables the iframe transport:  
518 - options.dataType = 'iframe ' + (options.dataType || '');  
519 - // The iframe transport accepts a serialized array as form data:  
520 - options.formData = this._getFormData(options);  
521 - // Add redirect url to form data on cross-domain uploads:  
522 - if (options.redirect && targetHost && targetHost !== location.host) {  
523 - options.formData.push({  
524 - name: options.redirectParamName || 'redirect',  
525 - value: options.redirect  
526 - });  
527 - }  
528 - },  
529 -  
530 - _initDataSettings: function (options) {  
531 - if (this._isXHRUpload(options)) {  
532 - if (!this._chunkedUpload(options, true)) {  
533 - if (!options.data) {  
534 - this._initXHRData(options);  
535 - }  
536 - this._initProgressListener(options);  
537 - }  
538 - if (options.postMessage) {  
539 - // Setting the dataType to postmessage enables the  
540 - // postMessage transport:  
541 - options.dataType = 'postmessage ' + (options.dataType || '');  
542 - }  
543 - } else {  
544 - this._initIframeSettings(options);  
545 - }  
546 - },  
547 -  
548 - _getParamName: function (options) {  
549 - var fileInput = $(options.fileInput),  
550 - paramName = options.paramName;  
551 - if (!paramName) {  
552 - paramName = [];  
553 - fileInput.each(function () {  
554 - var input = $(this),  
555 - name = input.prop('name') || 'files[]',  
556 - i = (input.prop('files') || [1]).length;  
557 - while (i) {  
558 - paramName.push(name);  
559 - i -= 1;  
560 - }  
561 - });  
562 - if (!paramName.length) {  
563 - paramName = [fileInput.prop('name') || 'files[]'];  
564 - }  
565 - } else if (!$.isArray(paramName)) {  
566 - paramName = [paramName];  
567 - }  
568 - return paramName;  
569 - },  
570 -  
571 - _initFormSettings: function (options) {  
572 - // Retrieve missing options from the input field and the  
573 - // associated form, if available:  
574 - if (!options.form || !options.form.length) {  
575 - options.form = $(options.fileInput.prop('form'));  
576 - // If the given file input doesn't have an associated form,  
577 - // use the default widget file input's form:  
578 - if (!options.form.length) {  
579 - options.form = $(this.options.fileInput.prop('form'));  
580 - }  
581 - }  
582 - options.paramName = this._getParamName(options);  
583 - if (!options.url) {  
584 - options.url = options.form.prop('action') || location.href;  
585 - }  
586 - // The HTTP request method must be "POST" or "PUT":  
587 - options.type = (options.type ||  
588 - ($.type(options.form.prop('method')) === 'string' &&  
589 - options.form.prop('method')) || ''  
590 - ).toUpperCase();  
591 - if (options.type !== 'POST' && options.type !== 'PUT' &&  
592 - options.type !== 'PATCH') {  
593 - options.type = 'POST';  
594 - }  
595 - if (!options.formAcceptCharset) {  
596 - options.formAcceptCharset = options.form.attr('accept-charset');  
597 - }  
598 - },  
599 -  
600 - _getAJAXSettings: function (data) {  
601 - var options = $.extend({}, this.options, data);  
602 - this._initFormSettings(options);  
603 - this._initDataSettings(options);  
604 - return options;  
605 - },  
606 -  
607 - // jQuery 1.6 doesn't provide .state(),  
608 - // while jQuery 1.8+ removed .isRejected() and .isResolved():  
609 - _getDeferredState: function (deferred) {  
610 - if (deferred.state) {  
611 - return deferred.state();  
612 - }  
613 - if (deferred.isResolved()) {  
614 - return 'resolved';  
615 - }  
616 - if (deferred.isRejected()) {  
617 - return 'rejected';  
618 - }  
619 - return 'pending';  
620 - },  
621 -  
622 - // Maps jqXHR callbacks to the equivalent  
623 - // methods of the given Promise object:  
624 - _enhancePromise: function (promise) {  
625 - promise.success = promise.done;  
626 - promise.error = promise.fail;  
627 - promise.complete = promise.always;  
628 - return promise;  
629 - },  
630 -  
631 - // Creates and returns a Promise object enhanced with  
632 - // the jqXHR methods abort, success, error and complete:  
633 - _getXHRPromise: function (resolveOrReject, context, args) {  
634 - var dfd = $.Deferred(),  
635 - promise = dfd.promise();  
636 - context = context || this.options.context || promise;  
637 - if (resolveOrReject === true) {  
638 - dfd.resolveWith(context, args);  
639 - } else if (resolveOrReject === false) {  
640 - dfd.rejectWith(context, args);  
641 - }  
642 - promise.abort = dfd.promise;  
643 - return this._enhancePromise(promise);  
644 - },  
645 -  
646 - // Adds convenience methods to the data callback argument:  
647 - _addConvenienceMethods: function (e, data) {  
648 - var that = this,  
649 - getPromise = function (args) {  
650 - return $.Deferred().resolveWith(that, args).promise();  
651 - };  
652 - data.process = function (resolveFunc, rejectFunc) {  
653 - if (resolveFunc || rejectFunc) {  
654 - data._processQueue = this._processQueue =  
655 - (this._processQueue || getPromise([this])).pipe(  
656 - function () {  
657 - if (data.errorThrown) {  
658 - return $.Deferred()  
659 - .rejectWith(that, [data]).promise();  
660 - }  
661 - return getPromise(arguments);  
662 - }  
663 - ).pipe(resolveFunc, rejectFunc);  
664 - }  
665 - return this._processQueue || getPromise([this]);  
666 - };  
667 - data.submit = function () {  
668 - if (this.state() !== 'pending') {  
669 - data.jqXHR = this.jqXHR =  
670 - (that._trigger(  
671 - 'submit',  
672 - $.Event('submit', {delegatedEvent: e}),  
673 - this  
674 - ) !== false) && that._onSend(e, this);  
675 - }  
676 - return this.jqXHR || that._getXHRPromise();  
677 - };  
678 - data.abort = function () {  
679 - if (this.jqXHR) {  
680 - return this.jqXHR.abort();  
681 - }  
682 - this.errorThrown = 'abort';  
683 - that._trigger('fail', null, this);  
684 - return that._getXHRPromise(false);  
685 - };  
686 - data.state = function () {  
687 - if (this.jqXHR) {  
688 - return that._getDeferredState(this.jqXHR);  
689 - }  
690 - if (this._processQueue) {  
691 - return that._getDeferredState(this._processQueue);  
692 - }  
693 - };  
694 - data.processing = function () {  
695 - return !this.jqXHR && this._processQueue && that  
696 - ._getDeferredState(this._processQueue) === 'pending';  
697 - };  
698 - data.progress = function () {  
699 - return this._progress;  
700 - };  
701 - data.response = function () {  
702 - return this._response;  
703 - };  
704 - },  
705 -  
706 - // Parses the Range header from the server response  
707 - // and returns the uploaded bytes:  
708 - _getUploadedBytes: function (jqXHR) {  
709 - var range = jqXHR.getResponseHeader('Range'),  
710 - parts = range && range.split('-'),  
711 - upperBytesPos = parts && parts.length > 1 &&  
712 - parseInt(parts[1], 10);  
713 - return upperBytesPos && upperBytesPos + 1;  
714 - },  
715 -  
716 - // Uploads a file in multiple, sequential requests  
717 - // by splitting the file up in multiple blob chunks.  
718 - // If the second parameter is true, only tests if the file  
719 - // should be uploaded in chunks, but does not invoke any  
720 - // upload requests:  
721 - _chunkedUpload: function (options, testOnly) {  
722 - options.uploadedBytes = options.uploadedBytes || 0;  
723 - var that = this,  
724 - file = options.files[0],  
725 - fs = file.size,  
726 - ub = options.uploadedBytes,  
727 - mcs = options.maxChunkSize || fs,  
728 - slice = this._blobSlice,  
729 - dfd = $.Deferred(),  
730 - promise = dfd.promise(),  
731 - jqXHR,  
732 - upload;  
733 - if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||  
734 - options.data) {  
735 - return false;  
736 - }  
737 - if (testOnly) {  
738 - return true;  
739 - }  
740 - if (ub >= fs) {  
741 - file.error = options.i18n('uploadedBytes');  
742 - return this._getXHRPromise(  
743 - false,  
744 - options.context,  
745 - [null, 'error', file.error]  
746 - );  
747 - }  
748 - // The chunk upload method:  
749 - upload = function () {  
750 - // Clone the options object for each chunk upload:  
751 - var o = $.extend({}, options),  
752 - currentLoaded = o._progress.loaded;  
753 - o.blob = slice.call(  
754 - file,  
755 - ub,  
756 - ub + mcs,  
757 - file.type  
758 - );  
759 - // Store the current chunk size, as the blob itself  
760 - // will be dereferenced after data processing:  
761 - o.chunkSize = o.blob.size;  
762 - // Expose the chunk bytes position range:  
763 - o.contentRange = 'bytes ' + ub + '-' +  
764 - (ub + o.chunkSize - 1) + '/' + fs;  
765 - // Process the upload data (the blob and potential form data):  
766 - that._initXHRData(o);  
767 - // Add progress listeners for this chunk upload:  
768 - that._initProgressListener(o);  
769 - jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) ||  
770 - that._getXHRPromise(false, o.context))  
771 - .done(function (result, textStatus, jqXHR) {  
772 - ub = that._getUploadedBytes(jqXHR) ||  
773 - (ub + o.chunkSize);  
774 - // Create a progress event if no final progress event  
775 - // with loaded equaling total has been triggered  
776 - // for this chunk:  
777 - if (currentLoaded + o.chunkSize - o._progress.loaded) {  
778 - that._onProgress($.Event('progress', {  
779 - lengthComputable: true,  
780 - loaded: ub - o.uploadedBytes,  
781 - total: ub - o.uploadedBytes  
782 - }), o);  
783 - }  
784 - options.uploadedBytes = o.uploadedBytes = ub;  
785 - o.result = result;  
786 - o.textStatus = textStatus;  
787 - o.jqXHR = jqXHR;  
788 - that._trigger('chunkdone', null, o);  
789 - that._trigger('chunkalways', null, o);  
790 - if (ub < fs) {  
791 - // File upload not yet complete,  
792 - // continue with the next chunk:  
793 - upload();  
794 - } else {  
795 - dfd.resolveWith(  
796 - o.context,  
797 - [result, textStatus, jqXHR]  
798 - );  
799 - }  
800 - })  
801 - .fail(function (jqXHR, textStatus, errorThrown) {  
802 - o.jqXHR = jqXHR;  
803 - o.textStatus = textStatus;  
804 - o.errorThrown = errorThrown;  
805 - that._trigger('chunkfail', null, o);  
806 - that._trigger('chunkalways', null, o);  
807 - dfd.rejectWith(  
808 - o.context,  
809 - [jqXHR, textStatus, errorThrown]  
810 - );  
811 - });  
812 - };  
813 - this._enhancePromise(promise);  
814 - promise.abort = function () {  
815 - return jqXHR.abort();  
816 - };  
817 - upload();  
818 - return promise;  
819 - },  
820 -  
821 - _beforeSend: function (e, data) {  
822 - if (this._active === 0) {  
823 - // the start callback is triggered when an upload starts  
824 - // and no other uploads are currently running,  
825 - // equivalent to the global ajaxStart event:  
826 - this._trigger('start');  
827 - // Set timer for global bitrate progress calculation:  
828 - this._bitrateTimer = new this._BitrateTimer();  
829 - // Reset the global progress values:  
830 - this._progress.loaded = this._progress.total = 0;  
831 - this._progress.bitrate = 0;  
832 - }  
833 - // Make sure the container objects for the .response() and  
834 - // .progress() methods on the data object are available  
835 - // and reset to their initial state:  
836 - this._initResponseObject(data);  
837 - this._initProgressObject(data);  
838 - data._progress.loaded = data.loaded = data.uploadedBytes || 0;  
839 - data._progress.total = data.total = this._getTotal(data.files) || 1;  
840 - data._progress.bitrate = data.bitrate = 0;  
841 - this._active += 1;  
842 - // Initialize the global progress values:  
843 - this._progress.loaded += data.loaded;  
844 - this._progress.total += data.total;  
845 - },  
846 -  
847 - _onDone: function (result, textStatus, jqXHR, options) {  
848 - var total = options._progress.total,  
849 - response = options._response;  
850 - if (options._progress.loaded < total) {  
851 - // Create a progress event if no final progress event  
852 - // with loaded equaling total has been triggered:  
853 - this._onProgress($.Event('progress', {  
854 - lengthComputable: true,  
855 - loaded: total,  
856 - total: total  
857 - }), options);  
858 - }  
859 - response.result = options.result = result;  
860 - response.textStatus = options.textStatus = textStatus;  
861 - response.jqXHR = options.jqXHR = jqXHR;  
862 - this._trigger('done', null, options);  
863 - },  
864 -  
865 - _onFail: function (jqXHR, textStatus, errorThrown, options) {  
866 - var response = options._response;  
867 - if (options.recalculateProgress) {  
868 - // Remove the failed (error or abort) file upload from  
869 - // the global progress calculation:  
870 - this._progress.loaded -= options._progress.loaded;  
871 - this._progress.total -= options._progress.total;  
872 - }  
873 - response.jqXHR = options.jqXHR = jqXHR;  
874 - response.textStatus = options.textStatus = textStatus;  
875 - response.errorThrown = options.errorThrown = errorThrown;  
876 - this._trigger('fail', null, options);  
877 - },  
878 -  
879 - _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {  
880 - // jqXHRorResult, textStatus and jqXHRorError are added to the  
881 - // options object via done and fail callbacks  
882 - this._trigger('always', null, options);  
883 - },  
884 -  
885 - _onSend: function (e, data) {  
886 - if (!data.submit) {  
887 - this._addConvenienceMethods(e, data);  
888 - }  
889 - var that = this,  
890 - jqXHR,  
891 - aborted,  
892 - slot,  
893 - pipe,  
894 - options = that._getAJAXSettings(data),  
895 - send = function () {  
896 - that._sending += 1;  
897 - // Set timer for bitrate progress calculation:  
898 - options._bitrateTimer = new that._BitrateTimer();  
899 - jqXHR = jqXHR || (  
900 - ((aborted || that._trigger(  
901 - 'send',  
902 - $.Event('send', {delegatedEvent: e}),  
903 - options  
904 - ) === false) &&  
905 - that._getXHRPromise(false, options.context, aborted)) ||  
906 - that._chunkedUpload(options) || $.ajax(options)  
907 - ).done(function (result, textStatus, jqXHR) {  
908 - that._onDone(result, textStatus, jqXHR, options);  
909 - }).fail(function (jqXHR, textStatus, errorThrown) {  
910 - that._onFail(jqXHR, textStatus, errorThrown, options);  
911 - }).always(function (jqXHRorResult, textStatus, jqXHRorError) {  
912 - that._onAlways(  
913 - jqXHRorResult,  
914 - textStatus,  
915 - jqXHRorError,  
916 - options  
917 - );  
918 - that._sending -= 1;  
919 - that._active -= 1;  
920 - if (options.limitConcurrentUploads &&  
921 - options.limitConcurrentUploads > that._sending) {  
922 - // Start the next queued upload,  
923 - // that has not been aborted:  
924 - var nextSlot = that._slots.shift();  
925 - while (nextSlot) {  
926 - if (that._getDeferredState(nextSlot) === 'pending') {  
927 - nextSlot.resolve();  
928 - break;  
929 - }  
930 - nextSlot = that._slots.shift();  
931 - }  
932 - }  
933 - if (that._active === 0) {  
934 - // The stop callback is triggered when all uploads have  
935 - // been completed, equivalent to the global ajaxStop event:  
936 - that._trigger('stop');  
937 - }  
938 - });  
939 - return jqXHR;  
940 - };  
941 - this._beforeSend(e, options);  
942 - if (this.options.sequentialUploads ||  
943 - (this.options.limitConcurrentUploads &&  
944 - this.options.limitConcurrentUploads <= this._sending)) {  
945 - if (this.options.limitConcurrentUploads > 1) {  
946 - slot = $.Deferred();  
947 - this._slots.push(slot);  
948 - pipe = slot.pipe(send);  
949 - } else {  
950 - this._sequence = this._sequence.pipe(send, send);  
951 - pipe = this._sequence;  
952 - }  
953 - // Return the piped Promise object, enhanced with an abort method,  
954 - // which is delegated to the jqXHR object of the current upload,  
955 - // and jqXHR callbacks mapped to the equivalent Promise methods:  
956 - pipe.abort = function () {  
957 - aborted = [undefined, 'abort', 'abort'];  
958 - if (!jqXHR) {  
959 - if (slot) {  
960 - slot.rejectWith(options.context, aborted);  
961 - }  
962 - return send();  
963 - }  
964 - return jqXHR.abort();  
965 - };  
966 - return this._enhancePromise(pipe);  
967 - }  
968 - return send();  
969 - },  
970 -  
971 - _onAdd: function (e, data) {  
972 - var that = this,  
973 - result = true,  
974 - options = $.extend({}, this.options, data),  
975 - files = data.files,  
976 - filesLength = files.length,  
977 - limit = options.limitMultiFileUploads,  
978 - limitSize = options.limitMultiFileUploadSize,  
979 - overhead = options.limitMultiFileUploadSizeOverhead,  
980 - batchSize = 0,  
981 - paramName = this._getParamName(options),  
982 - paramNameSet,  
983 - paramNameSlice,  
984 - fileSet,  
985 - i,  
986 - j = 0;  
987 - if (!filesLength) {  
988 - return false;  
989 - }  
990 - if (limitSize && files[0].size === undefined) {  
991 - limitSize = undefined;  
992 - }  
993 - if (!(options.singleFileUploads || limit || limitSize) ||  
994 - !this._isXHRUpload(options)) {  
995 - fileSet = [files];  
996 - paramNameSet = [paramName];  
997 - } else if (!(options.singleFileUploads || limitSize) && limit) {  
998 - fileSet = [];  
999 - paramNameSet = [];  
1000 - for (i = 0; i < filesLength; i += limit) {  
1001 - fileSet.push(files.slice(i, i + limit));  
1002 - paramNameSlice = paramName.slice(i, i + limit);  
1003 - if (!paramNameSlice.length) {  
1004 - paramNameSlice = paramName;  
1005 - }  
1006 - paramNameSet.push(paramNameSlice);  
1007 - }  
1008 - } else if (!options.singleFileUploads && limitSize) {  
1009 - fileSet = [];  
1010 - paramNameSet = [];  
1011 - for (i = 0; i < filesLength; i = i + 1) {  
1012 - batchSize += files[i].size + overhead;  
1013 - if (i + 1 === filesLength ||  
1014 - ((batchSize + files[i + 1].size + overhead) > limitSize) ||  
1015 - (limit && i + 1 - j >= limit)) {  
1016 - fileSet.push(files.slice(j, i + 1));  
1017 - paramNameSlice = paramName.slice(j, i + 1);  
1018 - if (!paramNameSlice.length) {  
1019 - paramNameSlice = paramName;  
1020 - }  
1021 - paramNameSet.push(paramNameSlice);  
1022 - j = i + 1;  
1023 - batchSize = 0;  
1024 - }  
1025 - }  
1026 - } else {  
1027 - paramNameSet = paramName;  
1028 - }  
1029 - data.originalFiles = files;  
1030 - $.each(fileSet || files, function (index, element) {  
1031 - var newData = $.extend({}, data);  
1032 - newData.files = fileSet ? element : [element];  
1033 - newData.paramName = paramNameSet[index];  
1034 - that._initResponseObject(newData);  
1035 - that._initProgressObject(newData);  
1036 - that._addConvenienceMethods(e, newData);  
1037 - result = that._trigger(  
1038 - 'add',  
1039 - $.Event('add', {delegatedEvent: e}),  
1040 - newData  
1041 - );  
1042 - return result;  
1043 - });  
1044 - return result;  
1045 - },  
1046 -  
1047 - _replaceFileInput: function (data) {  
1048 - var input = data.fileInput,  
1049 - inputClone = input.clone(true),  
1050 - restoreFocus = input.is(document.activeElement);  
1051 - // Add a reference for the new cloned file input to the data argument:  
1052 - data.fileInputClone = inputClone;  
1053 - $('<form></form>').append(inputClone)[0].reset();  
1054 - // Detaching allows to insert the fileInput on another form  
1055 - // without loosing the file input value:  
1056 - input.after(inputClone).detach();  
1057 - // If the fileInput had focus before it was detached,  
1058 - // restore focus to the inputClone.  
1059 - if (restoreFocus) {  
1060 - inputClone.focus();  
1061 - }  
1062 - // Avoid memory leaks with the detached file input:  
1063 - $.cleanData(input.unbind('remove'));  
1064 - // Replace the original file input element in the fileInput  
1065 - // elements set with the clone, which has been copied including  
1066 - // event handlers:  
1067 - this.options.fileInput = this.options.fileInput.map(function (i, el) {  
1068 - if (el === input[0]) {  
1069 - return inputClone[0];  
1070 - }  
1071 - return el;  
1072 - });  
1073 - // If the widget has been initialized on the file input itself,  
1074 - // override this.element with the file input clone:  
1075 - if (input[0] === this.element[0]) {  
1076 - this.element = inputClone;  
1077 - }  
1078 - },  
1079 -  
1080 - _handleFileTreeEntry: function (entry, path) {  
1081 - var that = this,  
1082 - dfd = $.Deferred(),  
1083 - errorHandler = function (e) {  
1084 - if (e && !e.entry) {  
1085 - e.entry = entry;  
1086 - }  
1087 - // Since $.when returns immediately if one  
1088 - // Deferred is rejected, we use resolve instead.  
1089 - // This allows valid files and invalid items  
1090 - // to be returned together in one set:  
1091 - dfd.resolve([e]);  
1092 - },  
1093 - successHandler = function (entries) {  
1094 - that._handleFileTreeEntries(  
1095 - entries,  
1096 - path + entry.name + '/'  
1097 - ).done(function (files) {  
1098 - dfd.resolve(files);  
1099 - }).fail(errorHandler);  
1100 - },  
1101 - readEntries = function () {  
1102 - dirReader.readEntries(function (results) {  
1103 - if (!results.length) {  
1104 - successHandler(entries);  
1105 - } else {  
1106 - entries = entries.concat(results);  
1107 - readEntries();  
1108 - }  
1109 - }, errorHandler);  
1110 - },  
1111 - dirReader, entries = [];  
1112 - path = path || '';  
1113 - if (entry.isFile) {  
1114 - if (entry._file) {  
1115 - // Workaround for Chrome bug #149735  
1116 - entry._file.relativePath = path;  
1117 - dfd.resolve(entry._file);  
1118 - } else {  
1119 - entry.file(function (file) {  
1120 - file.relativePath = path;  
1121 - dfd.resolve(file);  
1122 - }, errorHandler);  
1123 - }  
1124 - } else if (entry.isDirectory) {  
1125 - dirReader = entry.createReader();  
1126 - readEntries();  
1127 - } else {  
1128 - // Return an empy list for file system items  
1129 - // other than files or directories:  
1130 - dfd.resolve([]);  
1131 - }  
1132 - return dfd.promise();  
1133 - },  
1134 -  
1135 - _handleFileTreeEntries: function (entries, path) {  
1136 - var that = this;  
1137 - return $.when.apply(  
1138 - $,  
1139 - $.map(entries, function (entry) {  
1140 - return that._handleFileTreeEntry(entry, path);  
1141 - })  
1142 - ).pipe(function () {  
1143 - return Array.prototype.concat.apply(  
1144 - [],  
1145 - arguments  
1146 - );  
1147 - });  
1148 - },  
1149 -  
1150 - _getDroppedFiles: function (dataTransfer) {  
1151 - dataTransfer = dataTransfer || {};  
1152 - var items = dataTransfer.items;  
1153 - if (items && items.length && (items[0].webkitGetAsEntry ||  
1154 - items[0].getAsEntry)) {  
1155 - return this._handleFileTreeEntries(  
1156 - $.map(items, function (item) {  
1157 - var entry;  
1158 - if (item.webkitGetAsEntry) {  
1159 - entry = item.webkitGetAsEntry();  
1160 - if (entry) {  
1161 - // Workaround for Chrome bug #149735:  
1162 - entry._file = item.getAsFile();  
1163 - }  
1164 - return entry;  
1165 - }  
1166 - return item.getAsEntry();  
1167 - })  
1168 - );  
1169 - }  
1170 - return $.Deferred().resolve(  
1171 - $.makeArray(dataTransfer.files)  
1172 - ).promise();  
1173 - },  
1174 -  
1175 - _getSingleFileInputFiles: function (fileInput) {  
1176 - fileInput = $(fileInput);  
1177 - var entries = fileInput.prop('webkitEntries') ||  
1178 - fileInput.prop('entries'),  
1179 - files,  
1180 - value;  
1181 - if (entries && entries.length) {  
1182 - return this._handleFileTreeEntries(entries);  
1183 - }  
1184 - files = $.makeArray(fileInput.prop('files'));  
1185 - if (!files.length) {  
1186 - value = fileInput.prop('value');  
1187 - if (!value) {  
1188 - return $.Deferred().resolve([]).promise();  
1189 - }  
1190 - // If the files property is not available, the browser does not  
1191 - // support the File API and we add a pseudo File object with  
1192 - // the input value as name with path information removed:  
1193 - files = [{name: value.replace(/^.*\\/, '')}];  
1194 - } else if (files[0].name === undefined && files[0].fileName) {  
1195 - // File normalization for Safari 4 and Firefox 3:  
1196 - $.each(files, function (index, file) {  
1197 - file.name = file.fileName;  
1198 - file.size = file.fileSize;  
1199 - });  
1200 - }  
1201 - return $.Deferred().resolve(files).promise();  
1202 - },  
1203 -  
1204 - _getFileInputFiles: function (fileInput) {  
1205 - if (!(fileInput instanceof $) || fileInput.length === 1) {  
1206 - return this._getSingleFileInputFiles(fileInput);  
1207 - }  
1208 - return $.when.apply(  
1209 - $,  
1210 - $.map(fileInput, this._getSingleFileInputFiles)  
1211 - ).pipe(function () {  
1212 - return Array.prototype.concat.apply(  
1213 - [],  
1214 - arguments  
1215 - );  
1216 - });  
1217 - },  
1218 -  
1219 - _onChange: function (e) {  
1220 - var that = this,  
1221 - data = {  
1222 - fileInput: $(e.target),  
1223 - form: $(e.target.form)  
1224 - };  
1225 - this._getFileInputFiles(data.fileInput).always(function (files) {  
1226 - data.files = files;  
1227 - if (that.options.replaceFileInput) {  
1228 - that._replaceFileInput(data);  
1229 - }  
1230 - if (that._trigger(  
1231 - 'change',  
1232 - $.Event('change', {delegatedEvent: e}),  
1233 - data  
1234 - ) !== false) {  
1235 - that._onAdd(e, data);  
1236 - }  
1237 - });  
1238 - },  
1239 -  
1240 - _onPaste: function (e) {  
1241 - var items = e.originalEvent && e.originalEvent.clipboardData &&  
1242 - e.originalEvent.clipboardData.items,  
1243 - data = {files: []};  
1244 - if (items && items.length) {  
1245 - $.each(items, function (index, item) {  
1246 - var file = item.getAsFile && item.getAsFile();  
1247 - if (file) {  
1248 - data.files.push(file);  
1249 - }  
1250 - });  
1251 - if (this._trigger(  
1252 - 'paste',  
1253 - $.Event('paste', {delegatedEvent: e}),  
1254 - data  
1255 - ) !== false) {  
1256 - this._onAdd(e, data);  
1257 - }  
1258 - }  
1259 - },  
1260 -  
1261 - _onDrop: function (e) {  
1262 - e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;  
1263 - var that = this,  
1264 - dataTransfer = e.dataTransfer,  
1265 - data = {};  
1266 - if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {  
1267 - e.preventDefault();  
1268 - this._getDroppedFiles(dataTransfer).always(function (files) {  
1269 - data.files = files;  
1270 - if (that._trigger(  
1271 - 'drop',  
1272 - $.Event('drop', {delegatedEvent: e}),  
1273 - data  
1274 - ) !== false) {  
1275 - that._onAdd(e, data);  
1276 - }  
1277 - });  
1278 - }  
1279 - },  
1280 -  
1281 - _onDragOver: getDragHandler('dragover'),  
1282 -  
1283 - _onDragEnter: getDragHandler('dragenter'),  
1284 -  
1285 - _onDragLeave: getDragHandler('dragleave'),  
1286 -  
1287 - _initEventHandlers: function () {  
1288 - if (this._isXHRUpload(this.options)) {  
1289 - this._on(this.options.dropZone, {  
1290 - dragover: this._onDragOver,  
1291 - drop: this._onDrop,  
1292 - // event.preventDefault() on dragenter is required for IE10+:  
1293 - dragenter: this._onDragEnter,  
1294 - // dragleave is not required, but added for completeness:  
1295 - dragleave: this._onDragLeave  
1296 - });  
1297 - this._on(this.options.pasteZone, {  
1298 - paste: this._onPaste  
1299 - });  
1300 - }  
1301 - if ($.support.fileInput) {  
1302 - this._on(this.options.fileInput, {  
1303 - change: this._onChange  
1304 - });  
1305 - }  
1306 - },  
1307 -  
1308 - _destroyEventHandlers: function () {  
1309 - this._off(this.options.dropZone, 'dragenter dragleave dragover drop');  
1310 - this._off(this.options.pasteZone, 'paste');  
1311 - this._off(this.options.fileInput, 'change');  
1312 - },  
1313 -  
1314 - _setOption: function (key, value) {  
1315 - var reinit = $.inArray(key, this._specialOptions) !== -1;  
1316 - if (reinit) {  
1317 - this._destroyEventHandlers();  
1318 - }  
1319 - this._super(key, value);  
1320 - if (reinit) {  
1321 - this._initSpecialOptions();  
1322 - this._initEventHandlers();  
1323 - }  
1324 - },  
1325 -  
1326 - _initSpecialOptions: function () {  
1327 - var options = this.options;  
1328 - if (options.fileInput === undefined) {  
1329 - options.fileInput = this.element.is('input[type="file"]') ?  
1330 - this.element : this.element.find('input[type="file"]');  
1331 - } else if (!(options.fileInput instanceof $)) {  
1332 - options.fileInput = $(options.fileInput);  
1333 - }  
1334 - if (!(options.dropZone instanceof $)) {  
1335 - options.dropZone = $(options.dropZone);  
1336 - }  
1337 - if (!(options.pasteZone instanceof $)) {  
1338 - options.pasteZone = $(options.pasteZone);  
1339 - }  
1340 - },  
1341 -  
1342 - _getRegExp: function (str) {  
1343 - var parts = str.split('/'),  
1344 - modifiers = parts.pop();  
1345 - parts.shift();  
1346 - return new RegExp(parts.join('/'), modifiers);  
1347 - },  
1348 -  
1349 - _isRegExpOption: function (key, value) {  
1350 - return key !== 'url' && $.type(value) === 'string' &&  
1351 - /^\/.*\/[igm]{0,3}$/.test(value);  
1352 - },  
1353 -  
1354 - _initDataAttributes: function () {  
1355 - var that = this,  
1356 - options = this.options,  
1357 - data = this.element.data();  
1358 - // Initialize options set via HTML5 data-attributes:  
1359 - $.each(  
1360 - this.element[0].attributes,  
1361 - function (index, attr) {  
1362 - var key = attr.name.toLowerCase(),  
1363 - value;  
1364 - if (/^data-/.test(key)) {  
1365 - // Convert hyphen-ated key to camelCase:  
1366 - key = key.slice(5).replace(/-[a-z]/g, function (str) {  
1367 - return str.charAt(1).toUpperCase();  
1368 - });  
1369 - value = data[key];  
1370 - if (that._isRegExpOption(key, value)) {  
1371 - value = that._getRegExp(value);  
1372 - }  
1373 - options[key] = value;  
1374 - }  
1375 - }  
1376 - );  
1377 - },  
1378 -  
1379 - _create: function () {  
1380 - this._initDataAttributes();  
1381 - this._initSpecialOptions();  
1382 - this._slots = [];  
1383 - this._sequence = this._getXHRPromise(true);  
1384 - this._sending = this._active = 0;  
1385 - this._initProgressObject(this);  
1386 - this._initEventHandlers();  
1387 - },  
1388 -  
1389 - // This method is exposed to the widget API and allows to query  
1390 - // the number of active uploads:  
1391 - active: function () {  
1392 - return this._active;  
1393 - },  
1394 -  
1395 - // This method is exposed to the widget API and allows to query  
1396 - // the widget upload progress.  
1397 - // It returns an object with loaded, total and bitrate properties  
1398 - // for the running uploads:  
1399 - progress: function () {  
1400 - return this._progress;  
1401 - },  
1402 -  
1403 - // This method is exposed to the widget API and allows adding files  
1404 - // using the fileupload API. The data parameter accepts an object which  
1405 - // must have a files property and can contain additional options:  
1406 - // .fileupload('add', {files: filesList});  
1407 - add: function (data) {  
1408 - var that = this;  
1409 - if (!data || this.options.disabled) {  
1410 - return;  
1411 - }  
1412 - if (data.fileInput && !data.files) {  
1413 - this._getFileInputFiles(data.fileInput).always(function (files) {  
1414 - data.files = files;  
1415 - that._onAdd(null, data);  
1416 - });  
1417 - } else {  
1418 - data.files = $.makeArray(data.files);  
1419 - this._onAdd(null, data);  
1420 - }  
1421 - },  
1422 -  
1423 - // This method is exposed to the widget API and allows sending files  
1424 - // using the fileupload API. The data parameter accepts an object which  
1425 - // must have a files or fileInput property and can contain additional options:  
1426 - // .fileupload('send', {files: filesList});  
1427 - // The method returns a Promise object for the file upload call.  
1428 - send: function (data) {  
1429 - if (data && !this.options.disabled) {  
1430 - if (data.fileInput && !data.files) {  
1431 - var that = this,  
1432 - dfd = $.Deferred(),  
1433 - promise = dfd.promise(),  
1434 - jqXHR,  
1435 - aborted;  
1436 - promise.abort = function () {  
1437 - aborted = true;  
1438 - if (jqXHR) {  
1439 - return jqXHR.abort();  
1440 - }  
1441 - dfd.reject(null, 'abort', 'abort');  
1442 - return promise;  
1443 - };  
1444 - this._getFileInputFiles(data.fileInput).always(  
1445 - function (files) {  
1446 - if (aborted) {  
1447 - return;  
1448 - }  
1449 - if (!files.length) {  
1450 - dfd.reject();  
1451 - return;  
1452 - }  
1453 - data.files = files;  
1454 - jqXHR = that._onSend(null, data);  
1455 - jqXHR.then(  
1456 - function (result, textStatus, jqXHR) {  
1457 - dfd.resolve(result, textStatus, jqXHR);  
1458 - },  
1459 - function (jqXHR, textStatus, errorThrown) {  
1460 - dfd.reject(jqXHR, textStatus, errorThrown);  
1461 - }  
1462 - );  
1463 - }  
1464 - );  
1465 - return this._enhancePromise(promise);  
1466 - }  
1467 - data.files = $.makeArray(data.files);  
1468 - if (data.files.length) {  
1469 - return this._onSend(null, data);  
1470 - }  
1471 - }  
1472 - return this._getXHRPromise(false, data && data.context);  
1473 - }  
1474 -  
1475 - });  
1476 -  
1477 -}));  
view/assets/js/jquery.iframe-transport.js
@@ -1,217 +0,0 @@ @@ -1,217 +0,0 @@
1 -/*  
2 - * jQuery Iframe Transport Plugin  
3 - * https://github.com/blueimp/jQuery-File-Upload  
4 - *  
5 - * Copyright 2011, Sebastian Tschan  
6 - * https://blueimp.net  
7 - *  
8 - * Licensed under the MIT license:  
9 - * http://www.opensource.org/licenses/MIT  
10 - */  
11 -  
12 -/* global define, require, window, document */  
13 -  
14 -(function (factory) {  
15 - 'use strict';  
16 - if (typeof define === 'function' && define.amd) {  
17 - // Register as an anonymous AMD module:  
18 - define(['jquery'], factory);  
19 - } else if (typeof exports === 'object') {  
20 - // Node/CommonJS:  
21 - factory(require('jquery'));  
22 - } else {  
23 - // Browser globals:  
24 - factory(window.jQuery);  
25 - }  
26 -}(function ($) {  
27 - 'use strict';  
28 -  
29 - // Helper variable to create unique names for the transport iframes:  
30 - var counter = 0;  
31 -  
32 - // The iframe transport accepts four additional options:  
33 - // options.fileInput: a jQuery collection of file input fields  
34 - // options.paramName: the parameter name for the file form data,  
35 - // overrides the name property of the file input field(s),  
36 - // can be a string or an array of strings.  
37 - // options.formData: an array of objects with name and value properties,  
38 - // equivalent to the return data of .serializeArray(), e.g.:  
39 - // [{name: 'a', value: 1}, {name: 'b', value: 2}]  
40 - // options.initialIframeSrc: the URL of the initial iframe src,  
41 - // by default set to "javascript:false;"  
42 - $.ajaxTransport('iframe', function (options) {  
43 - if (options.async) {  
44 - // javascript:false as initial iframe src  
45 - // prevents warning popups on HTTPS in IE6:  
46 - /*jshint scripturl: true */  
47 - var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',  
48 - /*jshint scripturl: false */  
49 - form,  
50 - iframe,  
51 - addParamChar;  
52 - return {  
53 - send: function (_, completeCallback) {  
54 - form = $('<form style="display:none;"></form>');  
55 - form.attr('accept-charset', options.formAcceptCharset);  
56 - addParamChar = /\?/.test(options.url) ? '&' : '?';  
57 - // XDomainRequest only supports GET and POST:  
58 - if (options.type === 'DELETE') {  
59 - options.url = options.url + addParamChar + '_method=DELETE';  
60 - options.type = 'POST';  
61 - } else if (options.type === 'PUT') {  
62 - options.url = options.url + addParamChar + '_method=PUT';  
63 - options.type = 'POST';  
64 - } else if (options.type === 'PATCH') {  
65 - options.url = options.url + addParamChar + '_method=PATCH';  
66 - options.type = 'POST';  
67 - }  
68 - // IE versions below IE8 cannot set the name property of  
69 - // elements that have already been added to the DOM,  
70 - // so we set the name along with the iframe HTML markup:  
71 - counter += 1;  
72 - iframe = $(  
73 - '<iframe src="' + initialIframeSrc +  
74 - '" name="iframe-transport-' + counter + '"></iframe>'  
75 - ).bind('load', function () {  
76 - var fileInputClones,  
77 - paramNames = $.isArray(options.paramName) ?  
78 - options.paramName : [options.paramName];  
79 - iframe  
80 - .unbind('load')  
81 - .bind('load', function () {  
82 - var response;  
83 - // Wrap in a try/catch block to catch exceptions thrown  
84 - // when trying to access cross-domain iframe contents:  
85 - try {  
86 - response = iframe.contents();  
87 - // Google Chrome and Firefox do not throw an  
88 - // exception when calling iframe.contents() on  
89 - // cross-domain requests, so we unify the response:  
90 - if (!response.length || !response[0].firstChild) {  
91 - throw new Error();  
92 - }  
93 - } catch (e) {  
94 - response = undefined;  
95 - }  
96 - // The complete callback returns the  
97 - // iframe content document as response object:  
98 - completeCallback(  
99 - 200,  
100 - 'success',  
101 - {'iframe': response}  
102 - );  
103 - // Fix for IE endless progress bar activity bug  
104 - // (happens on form submits to iframe targets):  
105 - $('<iframe src="' + initialIframeSrc + '"></iframe>')  
106 - .appendTo(form);  
107 - window.setTimeout(function () {  
108 - // Removing the form in a setTimeout call  
109 - // allows Chrome's developer tools to display  
110 - // the response result  
111 - form.remove();  
112 - }, 0);  
113 - });  
114 - form  
115 - .prop('target', iframe.prop('name'))  
116 - .prop('action', options.url)  
117 - .prop('method', options.type);  
118 - if (options.formData) {  
119 - $.each(options.formData, function (index, field) {  
120 - $('<input type="hidden"/>')  
121 - .prop('name', field.name)  
122 - .val(field.value)  
123 - .appendTo(form);  
124 - });  
125 - }  
126 - if (options.fileInput && options.fileInput.length &&  
127 - options.type === 'POST') {  
128 - fileInputClones = options.fileInput.clone();  
129 - // Insert a clone for each file input field:  
130 - options.fileInput.after(function (index) {  
131 - return fileInputClones[index];  
132 - });  
133 - if (options.paramName) {  
134 - options.fileInput.each(function (index) {  
135 - $(this).prop(  
136 - 'name',  
137 - paramNames[index] || options.paramName  
138 - );  
139 - });  
140 - }  
141 - // Appending the file input fields to the hidden form  
142 - // removes them from their original location:  
143 - form  
144 - .append(options.fileInput)  
145 - .prop('enctype', 'multipart/form-data')  
146 - // enctype must be set as encoding for IE:  
147 - .prop('encoding', 'multipart/form-data');  
148 - // Remove the HTML5 form attribute from the input(s):  
149 - options.fileInput.removeAttr('form');  
150 - }  
151 - form.submit();  
152 - // Insert the file input fields at their original location  
153 - // by replacing the clones with the originals:  
154 - if (fileInputClones && fileInputClones.length) {  
155 - options.fileInput.each(function (index, input) {  
156 - var clone = $(fileInputClones[index]);  
157 - // Restore the original name and form properties:  
158 - $(input)  
159 - .prop('name', clone.prop('name'))  
160 - .attr('form', clone.attr('form'));  
161 - clone.replaceWith(input);  
162 - });  
163 - }  
164 - });  
165 - form.append(iframe).appendTo(document.body);  
166 - },  
167 - abort: function () {  
168 - if (iframe) {  
169 - // javascript:false as iframe src aborts the request  
170 - // and prevents warning popups on HTTPS in IE6.  
171 - // concat is used to avoid the "Script URL" JSLint error:  
172 - iframe  
173 - .unbind('load')  
174 - .prop('src', initialIframeSrc);  
175 - }  
176 - if (form) {  
177 - form.remove();  
178 - }  
179 - }  
180 - };  
181 - }  
182 - });  
183 -  
184 - // The iframe transport returns the iframe content document as response.  
185 - // The following adds converters from iframe to text, json, html, xml  
186 - // and script.  
187 - // Please note that the Content-Type for JSON responses has to be text/plain  
188 - // or text/html, if the browser doesn't include application/json in the  
189 - // Accept header, else IE will show a download dialog.  
190 - // The Content-Type for XML responses on the other hand has to be always  
191 - // application/xml or text/xml, so IE properly parses the XML response.  
192 - // See also  
193 - // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation  
194 - $.ajaxSetup({  
195 - converters: {  
196 - 'iframe text': function (iframe) {  
197 - return iframe && $(iframe[0].body).text();  
198 - },  
199 - 'iframe json': function (iframe) {  
200 - return iframe && $.parseJSON($(iframe[0].body).text());  
201 - },  
202 - 'iframe html': function (iframe) {  
203 - return iframe && $(iframe[0].body).html();  
204 - },  
205 - 'iframe xml': function (iframe) {  
206 - var xmlDoc = iframe && iframe[0];  
207 - return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :  
208 - $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||  
209 - $(xmlDoc.body).html());  
210 - },  
211 - 'iframe script': function (iframe) {  
212 - return iframe && $.globalEval($(iframe[0].body).text());  
213 - }  
214 - }  
215 - });  
216 -  
217 -}));  
view/assets/js/jquery.scrollTo.js
@@ -1,210 +0,0 @@ @@ -1,210 +0,0 @@
1 -/*!  
2 - * jQuery.scrollTo  
3 - * Copyright (c) 2007-2015 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com  
4 - * Licensed under MIT  
5 - * http://flesler.blogspot.com/2007/10/jqueryscrollto.html  
6 - * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery  
7 - * @author Ariel Flesler  
8 - * @version 2.1.2  
9 - */  
10 -;(function(factory) {  
11 - 'use strict';  
12 - if (typeof define === 'function' && define.amd) {  
13 - // AMD  
14 - define(['jquery'], factory);  
15 - } else if (typeof module !== 'undefined' && module.exports) {  
16 - // CommonJS  
17 - module.exports = factory(require('jquery'));  
18 - } else {  
19 - // Global  
20 - factory(jQuery);  
21 - }  
22 -})(function($) {  
23 - 'use strict';  
24 -  
25 - var $scrollTo = $.scrollTo = function(target, duration, settings) {  
26 - return $(window).scrollTo(target, duration, settings);  
27 - };  
28 -  
29 - $scrollTo.defaults = {  
30 - axis:'xy',  
31 - duration: 0,  
32 - limit:true  
33 - };  
34 -  
35 - function isWin(elem) {  
36 - return !elem.nodeName ||  
37 - $.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1;  
38 - }  
39 -  
40 - $.fn.scrollTo = function(target, duration, settings) {  
41 - if (typeof duration === 'object') {  
42 - settings = duration;  
43 - duration = 0;  
44 - }  
45 - if (typeof settings === 'function') {  
46 - settings = { onAfter:settings };  
47 - }  
48 - if (target === 'max') {  
49 - target = 9e9;  
50 - }  
51 -  
52 - settings = $.extend({}, $scrollTo.defaults, settings);  
53 - // Speed is still recognized for backwards compatibility  
54 - duration = duration || settings.duration;  
55 - // Make sure the settings are given right  
56 - var queue = settings.queue && settings.axis.length > 1;  
57 - if (queue) {  
58 - // Let's keep the overall duration  
59 - duration /= 2;  
60 - }  
61 - settings.offset = both(settings.offset);  
62 - settings.over = both(settings.over);  
63 -  
64 - return this.each(function() {  
65 - // Null target yields nothing, just like jQuery does  
66 - if (target === null) return;  
67 -  
68 - var win = isWin(this),  
69 - elem = win ? this.contentWindow || window : this,  
70 - $elem = $(elem),  
71 - targ = target,  
72 - attr = {},  
73 - toff;  
74 -  
75 - switch (typeof targ) {  
76 - // A number will pass the regex  
77 - case 'number':  
78 - case 'string':  
79 - if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) {  
80 - targ = both(targ);  
81 - // We are done  
82 - break;  
83 - }  
84 - // Relative/Absolute selector  
85 - targ = win ? $(targ) : $(targ, elem);  
86 - /* falls through */  
87 - case 'object':  
88 - if (targ.length === 0) return;  
89 - // DOMElement / jQuery  
90 - if (targ.is || targ.style) {  
91 - // Get the real position of the target  
92 - toff = (targ = $(targ)).offset();  
93 - }  
94 - }  
95 -  
96 - var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset;  
97 -  
98 - $.each(settings.axis.split(''), function(i, axis) {  
99 - var Pos = axis === 'x' ? 'Left' : 'Top',  
100 - pos = Pos.toLowerCase(),  
101 - key = 'scroll' + Pos,  
102 - prev = $elem[key](),  
103 - max = $scrollTo.max(elem, axis);  
104 -  
105 - if (toff) {// jQuery / DOMElement  
106 - attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]);  
107 -  
108 - // If it's a dom element, reduce the margin  
109 - if (settings.margin) {  
110 - attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0;  
111 - attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0;  
112 - }  
113 -  
114 - attr[key] += offset[pos] || 0;  
115 -  
116 - if (settings.over[pos]) {  
117 - // Scroll to a fraction of its width/height  
118 - attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos];  
119 - }  
120 - } else {  
121 - var val = targ[pos];  
122 - // Handle percentage values  
123 - attr[key] = val.slice && val.slice(-1) === '%' ?  
124 - parseFloat(val) / 100 * max  
125 - : val;  
126 - }  
127 -  
128 - // Number or 'number'  
129 - if (settings.limit && /^\d+$/.test(attr[key])) {  
130 - // Check the limits  
131 - attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max);  
132 - }  
133 -  
134 - // Don't waste time animating, if there's no need.  
135 - if (!i && settings.axis.length > 1) {  
136 - if (prev === attr[key]) {  
137 - // No animation needed  
138 - attr = {};  
139 - } else if (queue) {  
140 - // Intermediate animation  
141 - animate(settings.onAfterFirst);  
142 - // Don't animate this axis again in the next iteration.  
143 - attr = {};  
144 - }  
145 - }  
146 - });  
147 -  
148 - animate(settings.onAfter);  
149 -  
150 - function animate(callback) {  
151 - var opts = $.extend({}, settings, {  
152 - // The queue setting conflicts with animate()  
153 - // Force it to always be true  
154 - queue: true,  
155 - duration: duration,  
156 - complete: callback && function() {  
157 - callback.call(elem, targ, settings);  
158 - }  
159 - });  
160 - $elem.animate(attr, opts);  
161 - }  
162 - });  
163 - };  
164 -  
165 - // Max scrolling position, works on quirks mode  
166 - // It only fails (not too badly) on IE, quirks mode.  
167 - $scrollTo.max = function(elem, axis) {  
168 - var Dim = axis === 'x' ? 'Width' : 'Height',  
169 - scroll = 'scroll'+Dim;  
170 -  
171 - if (!isWin(elem))  
172 - return elem[scroll] - $(elem)[Dim.toLowerCase()]();  
173 -  
174 - var size = 'client' + Dim,  
175 - doc = elem.ownerDocument || elem.document,  
176 - html = doc.documentElement,  
177 - body = doc.body;  
178 -  
179 - return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]);  
180 - };  
181 -  
182 - function both(val) {  
183 - return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val };  
184 - }  
185 -  
186 - // Add special hooks so that window scroll properties can be animated  
187 - $.Tween.propHooks.scrollLeft =  
188 - $.Tween.propHooks.scrollTop = {  
189 - get: function(t) {  
190 - return $(t.elem)[t.prop]();  
191 - },  
192 - set: function(t) {  
193 - var curr = this.get(t);  
194 - // If interrupt is true and user scrolled, stop animating  
195 - if (t.options.interrupt && t._last && t._last !== curr) {  
196 - return $(t.elem).stop();  
197 - }  
198 - var next = Math.round(t.now);  
199 - // Don't waste CPU  
200 - // Browsers don't render floating point scroll  
201 - if (curr !== next) {  
202 - $(t.elem)[t.prop](next);  
203 - t._last = this.get(t);  
204 - }  
205 - }  
206 - };  
207 -  
208 - // AMD requirement  
209 - return $scrollTo;  
210 -});  
view/assets/js/jquery.ui.widget.js
@@ -1,572 +0,0 @@ @@ -1,572 +0,0 @@
1 -/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28  
2 -* http://jqueryui.com  
3 -* Includes: widget.js  
4 -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */  
5 -  
6 -(function( factory ) {  
7 - if ( typeof define === "function" && define.amd ) {  
8 -  
9 - // AMD. Register as an anonymous module.  
10 - define([ "jquery" ], factory );  
11 -  
12 - } else if ( typeof exports === "object" ) {  
13 -  
14 - // Node/CommonJS  
15 - factory( require( "jquery" ) );  
16 -  
17 - } else {  
18 -  
19 - // Browser globals  
20 - factory( jQuery );  
21 - }  
22 -}(function( $ ) {  
23 -/*!  
24 - * jQuery UI Widget 1.11.4  
25 - * http://jqueryui.com  
26 - *  
27 - * Copyright jQuery Foundation and other contributors  
28 - * Released under the MIT license.  
29 - * http://jquery.org/license  
30 - *  
31 - * http://api.jqueryui.com/jQuery.widget/  
32 - */  
33 -  
34 -  
35 -var widget_uuid = 0,  
36 - widget_slice = Array.prototype.slice;  
37 -  
38 -$.cleanData = (function( orig ) {  
39 - return function( elems ) {  
40 - var events, elem, i;  
41 - for ( i = 0; (elem = elems[i]) != null; i++ ) {  
42 - try {  
43 -  
44 - // Only trigger remove when necessary to save time  
45 - events = $._data( elem, "events" );  
46 - if ( events && events.remove ) {  
47 - $( elem ).triggerHandler( "remove" );  
48 - }  
49 -  
50 - // http://bugs.jquery.com/ticket/8235  
51 - } catch ( e ) {}  
52 - }  
53 - orig( elems );  
54 - };  
55 -})( $.cleanData );  
56 -  
57 -$.widget = function( name, base, prototype ) {  
58 - var fullName, existingConstructor, constructor, basePrototype,  
59 - // proxiedPrototype allows the provided prototype to remain unmodified  
60 - // so that it can be used as a mixin for multiple widgets (#8876)  
61 - proxiedPrototype = {},  
62 - namespace = name.split( "." )[ 0 ];  
63 -  
64 - name = name.split( "." )[ 1 ];  
65 - fullName = namespace + "-" + name;  
66 -  
67 - if ( !prototype ) {  
68 - prototype = base;  
69 - base = $.Widget;  
70 - }  
71 -  
72 - // create selector for plugin  
73 - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {  
74 - return !!$.data( elem, fullName );  
75 - };  
76 -  
77 - $[ namespace ] = $[ namespace ] || {};  
78 - existingConstructor = $[ namespace ][ name ];  
79 - constructor = $[ namespace ][ name ] = function( options, element ) {  
80 - // allow instantiation without "new" keyword  
81 - if ( !this._createWidget ) {  
82 - return new constructor( options, element );  
83 - }  
84 -  
85 - // allow instantiation without initializing for simple inheritance  
86 - // must use "new" keyword (the code above always passes args)  
87 - if ( arguments.length ) {  
88 - this._createWidget( options, element );  
89 - }  
90 - };  
91 - // extend with the existing constructor to carry over any static properties  
92 - $.extend( constructor, existingConstructor, {  
93 - version: prototype.version,  
94 - // copy the object used to create the prototype in case we need to  
95 - // redefine the widget later  
96 - _proto: $.extend( {}, prototype ),  
97 - // track widgets that inherit from this widget in case this widget is  
98 - // redefined after a widget inherits from it  
99 - _childConstructors: []  
100 - });  
101 -  
102 - basePrototype = new base();  
103 - // we need to make the options hash a property directly on the new instance  
104 - // otherwise we'll modify the options hash on the prototype that we're  
105 - // inheriting from  
106 - basePrototype.options = $.widget.extend( {}, basePrototype.options );  
107 - $.each( prototype, function( prop, value ) {  
108 - if ( !$.isFunction( value ) ) {  
109 - proxiedPrototype[ prop ] = value;  
110 - return;  
111 - }  
112 - proxiedPrototype[ prop ] = (function() {  
113 - var _super = function() {  
114 - return base.prototype[ prop ].apply( this, arguments );  
115 - },  
116 - _superApply = function( args ) {  
117 - return base.prototype[ prop ].apply( this, args );  
118 - };  
119 - return function() {  
120 - var __super = this._super,  
121 - __superApply = this._superApply,  
122 - returnValue;  
123 -  
124 - this._super = _super;  
125 - this._superApply = _superApply;  
126 -  
127 - returnValue = value.apply( this, arguments );  
128 -  
129 - this._super = __super;  
130 - this._superApply = __superApply;  
131 -  
132 - return returnValue;  
133 - };  
134 - })();  
135 - });  
136 - constructor.prototype = $.widget.extend( basePrototype, {  
137 - // TODO: remove support for widgetEventPrefix  
138 - // always use the name + a colon as the prefix, e.g., draggable:start  
139 - // don't prefix for widgets that aren't DOM-based  
140 - widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name  
141 - }, proxiedPrototype, {  
142 - constructor: constructor,  
143 - namespace: namespace,  
144 - widgetName: name,  
145 - widgetFullName: fullName  
146 - });  
147 -  
148 - // If this widget is being redefined then we need to find all widgets that  
149 - // are inheriting from it and redefine all of them so that they inherit from  
150 - // the new version of this widget. We're essentially trying to replace one  
151 - // level in the prototype chain.  
152 - if ( existingConstructor ) {  
153 - $.each( existingConstructor._childConstructors, function( i, child ) {  
154 - var childPrototype = child.prototype;  
155 -  
156 - // redefine the child widget using the same prototype that was  
157 - // originally used, but inherit from the new version of the base  
158 - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );  
159 - });  
160 - // remove the list of existing child constructors from the old constructor  
161 - // so the old child constructors can be garbage collected  
162 - delete existingConstructor._childConstructors;  
163 - } else {  
164 - base._childConstructors.push( constructor );  
165 - }  
166 -  
167 - $.widget.bridge( name, constructor );  
168 -  
169 - return constructor;  
170 -};  
171 -  
172 -$.widget.extend = function( target ) {  
173 - var input = widget_slice.call( arguments, 1 ),  
174 - inputIndex = 0,  
175 - inputLength = input.length,  
176 - key,  
177 - value;  
178 - for ( ; inputIndex < inputLength; inputIndex++ ) {  
179 - for ( key in input[ inputIndex ] ) {  
180 - value = input[ inputIndex ][ key ];  
181 - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {  
182 - // Clone objects  
183 - if ( $.isPlainObject( value ) ) {  
184 - target[ key ] = $.isPlainObject( target[ key ] ) ?  
185 - $.widget.extend( {}, target[ key ], value ) :  
186 - // Don't extend strings, arrays, etc. with objects  
187 - $.widget.extend( {}, value );  
188 - // Copy everything else by reference  
189 - } else {  
190 - target[ key ] = value;  
191 - }  
192 - }  
193 - }  
194 - }  
195 - return target;  
196 -};  
197 -  
198 -$.widget.bridge = function( name, object ) {  
199 - var fullName = object.prototype.widgetFullName || name;  
200 - $.fn[ name ] = function( options ) {  
201 - var isMethodCall = typeof options === "string",  
202 - args = widget_slice.call( arguments, 1 ),  
203 - returnValue = this;  
204 -  
205 - if ( isMethodCall ) {  
206 - this.each(function() {  
207 - var methodValue,  
208 - instance = $.data( this, fullName );  
209 - if ( options === "instance" ) {  
210 - returnValue = instance;  
211 - return false;  
212 - }  
213 - if ( !instance ) {  
214 - return $.error( "cannot call methods on " + name + " prior to initialization; " +  
215 - "attempted to call method '" + options + "'" );  
216 - }  
217 - if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {  
218 - return $.error( "no such method '" + options + "' for " + name + " widget instance" );  
219 - }  
220 - methodValue = instance[ options ].apply( instance, args );  
221 - if ( methodValue !== instance && methodValue !== undefined ) {  
222 - returnValue = methodValue && methodValue.jquery ?  
223 - returnValue.pushStack( methodValue.get() ) :  
224 - methodValue;  
225 - return false;  
226 - }  
227 - });  
228 - } else {  
229 -  
230 - // Allow multiple hashes to be passed on init  
231 - if ( args.length ) {  
232 - options = $.widget.extend.apply( null, [ options ].concat(args) );  
233 - }  
234 -  
235 - this.each(function() {  
236 - var instance = $.data( this, fullName );  
237 - if ( instance ) {  
238 - instance.option( options || {} );  
239 - if ( instance._init ) {  
240 - instance._init();  
241 - }  
242 - } else {  
243 - $.data( this, fullName, new object( options, this ) );  
244 - }  
245 - });  
246 - }  
247 -  
248 - return returnValue;  
249 - };  
250 -};  
251 -  
252 -$.Widget = function( /* options, element */ ) {};  
253 -$.Widget._childConstructors = [];  
254 -  
255 -$.Widget.prototype = {  
256 - widgetName: "widget",  
257 - widgetEventPrefix: "",  
258 - defaultElement: "<div>",  
259 - options: {  
260 - disabled: false,  
261 -  
262 - // callbacks  
263 - create: null  
264 - },  
265 - _createWidget: function( options, element ) {  
266 - element = $( element || this.defaultElement || this )[ 0 ];  
267 - this.element = $( element );  
268 - this.uuid = widget_uuid++;  
269 - this.eventNamespace = "." + this.widgetName + this.uuid;  
270 -  
271 - this.bindings = $();  
272 - this.hoverable = $();  
273 - this.focusable = $();  
274 -  
275 - if ( element !== this ) {  
276 - $.data( element, this.widgetFullName, this );  
277 - this._on( true, this.element, {  
278 - remove: function( event ) {  
279 - if ( event.target === element ) {  
280 - this.destroy();  
281 - }  
282 - }  
283 - });  
284 - this.document = $( element.style ?  
285 - // element within the document  
286 - element.ownerDocument :  
287 - // element is window or document  
288 - element.document || element );  
289 - this.window = $( this.document[0].defaultView || this.document[0].parentWindow );  
290 - }  
291 -  
292 - this.options = $.widget.extend( {},  
293 - this.options,  
294 - this._getCreateOptions(),  
295 - options );  
296 -  
297 - this._create();  
298 - this._trigger( "create", null, this._getCreateEventData() );  
299 - this._init();  
300 - },  
301 - _getCreateOptions: $.noop,  
302 - _getCreateEventData: $.noop,  
303 - _create: $.noop,  
304 - _init: $.noop,  
305 -  
306 - destroy: function() {  
307 - this._destroy();  
308 - // we can probably remove the unbind calls in 2.0  
309 - // all event bindings should go through this._on()  
310 - this.element  
311 - .unbind( this.eventNamespace )  
312 - .removeData( this.widgetFullName )  
313 - // support: jquery <1.6.3  
314 - // http://bugs.jquery.com/ticket/9413  
315 - .removeData( $.camelCase( this.widgetFullName ) );  
316 - this.widget()  
317 - .unbind( this.eventNamespace )  
318 - .removeAttr( "aria-disabled" )  
319 - .removeClass(  
320 - this.widgetFullName + "-disabled " +  
321 - "ui-state-disabled" );  
322 -  
323 - // clean up events and states  
324 - this.bindings.unbind( this.eventNamespace );  
325 - this.hoverable.removeClass( "ui-state-hover" );  
326 - this.focusable.removeClass( "ui-state-focus" );  
327 - },  
328 - _destroy: $.noop,  
329 -  
330 - widget: function() {  
331 - return this.element;  
332 - },  
333 -  
334 - option: function( key, value ) {  
335 - var options = key,  
336 - parts,  
337 - curOption,  
338 - i;  
339 -  
340 - if ( arguments.length === 0 ) {  
341 - // don't return a reference to the internal hash  
342 - return $.widget.extend( {}, this.options );  
343 - }  
344 -  
345 - if ( typeof key === "string" ) {  
346 - // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }  
347 - options = {};  
348 - parts = key.split( "." );  
349 - key = parts.shift();  
350 - if ( parts.length ) {  
351 - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );  
352 - for ( i = 0; i < parts.length - 1; i++ ) {  
353 - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};  
354 - curOption = curOption[ parts[ i ] ];  
355 - }  
356 - key = parts.pop();  
357 - if ( arguments.length === 1 ) {  
358 - return curOption[ key ] === undefined ? null : curOption[ key ];  
359 - }  
360 - curOption[ key ] = value;  
361 - } else {  
362 - if ( arguments.length === 1 ) {  
363 - return this.options[ key ] === undefined ? null : this.options[ key ];  
364 - }  
365 - options[ key ] = value;  
366 - }  
367 - }  
368 -  
369 - this._setOptions( options );  
370 -  
371 - return this;  
372 - },  
373 - _setOptions: function( options ) {  
374 - var key;  
375 -  
376 - for ( key in options ) {  
377 - this._setOption( key, options[ key ] );  
378 - }  
379 -  
380 - return this;  
381 - },  
382 - _setOption: function( key, value ) {  
383 - this.options[ key ] = value;  
384 -  
385 - if ( key === "disabled" ) {  
386 - this.widget()  
387 - .toggleClass( this.widgetFullName + "-disabled", !!value );  
388 -  
389 - // If the widget is becoming disabled, then nothing is interactive  
390 - if ( value ) {  
391 - this.hoverable.removeClass( "ui-state-hover" );  
392 - this.focusable.removeClass( "ui-state-focus" );  
393 - }  
394 - }  
395 -  
396 - return this;  
397 - },  
398 -  
399 - enable: function() {  
400 - return this._setOptions({ disabled: false });  
401 - },  
402 - disable: function() {  
403 - return this._setOptions({ disabled: true });  
404 - },  
405 -  
406 - _on: function( suppressDisabledCheck, element, handlers ) {  
407 - var delegateElement,  
408 - instance = this;  
409 -  
410 - // no suppressDisabledCheck flag, shuffle arguments  
411 - if ( typeof suppressDisabledCheck !== "boolean" ) {  
412 - handlers = element;  
413 - element = suppressDisabledCheck;  
414 - suppressDisabledCheck = false;  
415 - }  
416 -  
417 - // no element argument, shuffle and use this.element  
418 - if ( !handlers ) {  
419 - handlers = element;  
420 - element = this.element;  
421 - delegateElement = this.widget();  
422 - } else {  
423 - element = delegateElement = $( element );  
424 - this.bindings = this.bindings.add( element );  
425 - }  
426 -  
427 - $.each( handlers, function( event, handler ) {  
428 - function handlerProxy() {  
429 - // allow widgets to customize the disabled handling  
430 - // - disabled as an array instead of boolean  
431 - // - disabled class as method for disabling individual parts  
432 - if ( !suppressDisabledCheck &&  
433 - ( instance.options.disabled === true ||  
434 - $( this ).hasClass( "ui-state-disabled" ) ) ) {  
435 - return;  
436 - }  
437 - return ( typeof handler === "string" ? instance[ handler ] : handler )  
438 - .apply( instance, arguments );  
439 - }  
440 -  
441 - // copy the guid so direct unbinding works  
442 - if ( typeof handler !== "string" ) {  
443 - handlerProxy.guid = handler.guid =  
444 - handler.guid || handlerProxy.guid || $.guid++;  
445 - }  
446 -  
447 - var match = event.match( /^([\w:-]*)\s*(.*)$/ ),  
448 - eventName = match[1] + instance.eventNamespace,  
449 - selector = match[2];  
450 - if ( selector ) {  
451 - delegateElement.delegate( selector, eventName, handlerProxy );  
452 - } else {  
453 - element.bind( eventName, handlerProxy );  
454 - }  
455 - });  
456 - },  
457 -  
458 - _off: function( element, eventName ) {  
459 - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +  
460 - this.eventNamespace;  
461 - element.unbind( eventName ).undelegate( eventName );  
462 -  
463 - // Clear the stack to avoid memory leaks (#10056)  
464 - this.bindings = $( this.bindings.not( element ).get() );  
465 - this.focusable = $( this.focusable.not( element ).get() );  
466 - this.hoverable = $( this.hoverable.not( element ).get() );  
467 - },  
468 -  
469 - _delay: function( handler, delay ) {  
470 - function handlerProxy() {  
471 - return ( typeof handler === "string" ? instance[ handler ] : handler )  
472 - .apply( instance, arguments );  
473 - }  
474 - var instance = this;  
475 - return setTimeout( handlerProxy, delay || 0 );  
476 - },  
477 -  
478 - _hoverable: function( element ) {  
479 - this.hoverable = this.hoverable.add( element );  
480 - this._on( element, {  
481 - mouseenter: function( event ) {  
482 - $( event.currentTarget ).addClass( "ui-state-hover" );  
483 - },  
484 - mouseleave: function( event ) {  
485 - $( event.currentTarget ).removeClass( "ui-state-hover" );  
486 - }  
487 - });  
488 - },  
489 -  
490 - _focusable: function( element ) {  
491 - this.focusable = this.focusable.add( element );  
492 - this._on( element, {  
493 - focusin: function( event ) {  
494 - $( event.currentTarget ).addClass( "ui-state-focus" );  
495 - },  
496 - focusout: function( event ) {  
497 - $( event.currentTarget ).removeClass( "ui-state-focus" );  
498 - }  
499 - });  
500 - },  
501 -  
502 - _trigger: function( type, event, data ) {  
503 - var prop, orig,  
504 - callback = this.options[ type ];  
505 -  
506 - data = data || {};  
507 - event = $.Event( event );  
508 - event.type = ( type === this.widgetEventPrefix ?  
509 - type :  
510 - this.widgetEventPrefix + type ).toLowerCase();  
511 - // the original event may come from any element  
512 - // so we need to reset the target on the new event  
513 - event.target = this.element[ 0 ];  
514 -  
515 - // copy original event properties over to the new event  
516 - orig = event.originalEvent;  
517 - if ( orig ) {  
518 - for ( prop in orig ) {  
519 - if ( !( prop in event ) ) {  
520 - event[ prop ] = orig[ prop ];  
521 - }  
522 - }  
523 - }  
524 -  
525 - this.element.trigger( event, data );  
526 - return !( $.isFunction( callback ) &&  
527 - callback.apply( this.element[0], [ event ].concat( data ) ) === false ||  
528 - event.isDefaultPrevented() );  
529 - }  
530 -};  
531 -  
532 -$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {  
533 - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {  
534 - if ( typeof options === "string" ) {  
535 - options = { effect: options };  
536 - }  
537 - var hasOptions,  
538 - effectName = !options ?  
539 - method :  
540 - options === true || typeof options === "number" ?  
541 - defaultEffect :  
542 - options.effect || defaultEffect;  
543 - options = options || {};  
544 - if ( typeof options === "number" ) {  
545 - options = { duration: options };  
546 - }  
547 - hasOptions = !$.isEmptyObject( options );  
548 - options.complete = callback;  
549 - if ( options.delay ) {  
550 - element.delay( options.delay );  
551 - }  
552 - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {  
553 - element[ method ]( options );  
554 - } else if ( effectName !== method && element[ effectName ] ) {  
555 - element[ effectName ]( options.duration, options.easing, callback );  
556 - } else {  
557 - element.queue(function( next ) {  
558 - $( this )[ method ]();  
559 - if ( callback ) {  
560 - callback.call( element[ 0 ] );  
561 - }  
562 - next();  
563 - });  
564 - }  
565 - };  
566 -});  
567 -  
568 -var widget = $.widget;  
569 -  
570 -  
571 -  
572 -}));  
view/assets/js/js.cookie.js
@@ -1,145 +0,0 @@ @@ -1,145 +0,0 @@
1 -/*!  
2 - * JavaScript Cookie v2.0.4  
3 - * https://github.com/js-cookie/js-cookie  
4 - *  
5 - * Copyright 2006, 2015 Klaus Hartl & Fagner Brack  
6 - * Released under the MIT license  
7 - */  
8 -(function(factory) {  
9 - if (typeof define === 'function' && define.amd) {  
10 - define(factory);  
11 - } else if (typeof exports === 'object') {  
12 - module.exports = factory();  
13 - } else {  
14 - var _OldCookies = window.Cookies;  
15 - var api = window.Cookies = factory();  
16 - api.noConflict = function() {  
17 - window.Cookies = _OldCookies;  
18 - return api;  
19 - };  
20 - }  
21 -}(function() {  
22 - function extend() {  
23 - var i = 0;  
24 - var result = {};  
25 - for (; i < arguments.length; i++) {  
26 - var attributes = arguments[ i ];  
27 - for (var key in attributes) {  
28 - result[key] = attributes[key];  
29 - }  
30 - }  
31 - return result;  
32 - }  
33 -  
34 - function init(converter) {  
35 - function api(key, value, attributes) {  
36 - var result;  
37 -  
38 - // Write  
39 -  
40 - if (arguments.length > 1) {  
41 - attributes = extend({  
42 - path: '/'  
43 - }, api.defaults, attributes);  
44 -  
45 - if (typeof attributes.expires === 'number') {  
46 - var expires = new Date();  
47 - expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);  
48 - attributes.expires = expires;  
49 - }  
50 -  
51 - try {  
52 - result = JSON.stringify(value);  
53 - if (/^[\{\[]/.test(result)) {  
54 - value = result;  
55 - }  
56 - } catch (e) {}  
57 -  
58 - if (!converter.write) {  
59 - value = encodeURIComponent(String(value))  
60 - .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);  
61 - } else {  
62 - value = converter.write(value, key);  
63 - }  
64 -  
65 - key = encodeURIComponent(String(key));  
66 - key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);  
67 - key = key.replace(/[\(\)]/g, escape);  
68 -  
69 - return (document.cookie = [  
70 - key, '=', value,  
71 - attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE  
72 - attributes.path && '; path=' + attributes.path,  
73 - attributes.domain && '; domain=' + attributes.domain,  
74 - attributes.secure ? '; secure' : ''  
75 - ].join(''));  
76 - }  
77 -  
78 - // Read  
79 -  
80 - if (!key) {  
81 - result = {};  
82 - }  
83 -  
84 - // To prevent the for loop in the first place assign an empty array  
85 - // in case there are no cookies at all. Also prevents odd result when  
86 - // calling "get()"  
87 - var cookies = document.cookie ? document.cookie.split('; ') : [];  
88 - var rdecode = /(%[0-9A-Z]{2})+/g;  
89 - var i = 0;  
90 -  
91 - for (; i < cookies.length; i++) {  
92 - var parts = cookies[i].split('=');  
93 - var name = parts[0].replace(rdecode, decodeURIComponent);  
94 - var cookie = parts.slice(1).join('=');  
95 -  
96 - if (cookie.charAt(0) === '"') {  
97 - cookie = cookie.slice(1, -1);  
98 - }  
99 -  
100 - try {  
101 - cookie = converter.read ?  
102 - converter.read(cookie, name) : converter(cookie, name) ||  
103 - cookie.replace(rdecode, decodeURIComponent);  
104 -  
105 - if (this.json) {  
106 - try {  
107 - cookie = JSON.parse(cookie);  
108 - } catch (e) {}  
109 - }  
110 -  
111 - if (key === name) {  
112 - result = cookie;  
113 - break;  
114 - }  
115 -  
116 - if (!key) {  
117 - result[name] = cookie;  
118 - }  
119 - } catch (e) {}  
120 - }  
121 -  
122 - return result;  
123 - }  
124 -  
125 - api.get = api.set = api;  
126 - api.getJSON = function() {  
127 - return api.apply({  
128 - json: true  
129 - }, [].slice.call(arguments));  
130 - };  
131 - api.defaults = {};  
132 -  
133 - api.remove = function(key, attributes) {  
134 - api(key, '', extend(attributes, {  
135 - expires: -1  
136 - }));  
137 - };  
138 -  
139 - api.withConverter = init;  
140 -  
141 - return api;  
142 - }  
143 -  
144 - return init(function() {});  
145 -}));  
view/assets/js/movement.js
@@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
1 -(function(movement, $, undefined) {  
2 -  
3 - movement.getPreviousSelectedMovement = function(mainConfig) {  
4 - return $('.selection-panel-body[mainConfig=' + mainConfig +  
5 - '][subConfig=movimento][step=1] .selection-panel-option[select=true]').attr('value');  
6 - };  
7 -  
8 - movement.setup = function(serverhost, hand) {  
9 - var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=movimento][step=1]';  
10 - $(baseId + ' .selection-panel-option').off('click').on(  
11 - 'click', function() {  
12 - wikilibras.selectAnOption(baseId, this);  
13 - dynworkflow.selectMovement($(this).attr('value'));  
14 - });  
15 - $(baseId + ' .video-panel-option').off('mouseenter').on('mouseenter',  
16 - function(event) {  
17 - $(this).addClass('video-panel-option-hover');  
18 - });  
19 - $(baseId + ' .video-panel-option').off('mouseleave').on('mouseleave',  
20 - function(event) {  
21 - $(this).removeClass('video-panel-option-hover');  
22 - });  
23 - };  
24 -}(window.movement = window.movement || {}, jQuery));  
view/assets/js/orientation.js
@@ -1,13 +0,0 @@ @@ -1,13 +0,0 @@
1 -(function(orientation, $, undefined) {  
2 -  
3 - orientation.setup = function(hand, subConfig, step) {  
4 - var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +  
5 - subConfig + '][step=' + step + ']';  
6 - $(baseId + ' .selection-panel-option').off('click').on(  
7 - 'click', function() {  
8 - wikilibras.selectAnOption(baseId, this);  
9 - dynworkflow.userSelectedAnOption();  
10 - });  
11 - };  
12 -  
13 -}(window.orientation = window.orientation || {}, jQuery));  
view/assets/js/render-sign.js 0 → 100644
@@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
  1 +(function(renderSign, $, undefined) {
  2 +
  3 + var api_url = '';
  4 +
  5 + function _submitParameterJSON(parsedParameterJSON, callback) {
  6 + console.log(parsedParameterJSON);
  7 +
  8 + $.ajax({
  9 + type : 'POST',
  10 + url : api_url + '/sign',
  11 + data : JSON.stringify(parsedParameterJSON),
  12 + contentType : 'application/json',
  13 + success : function(response) {
  14 + console.log(response);
  15 + callback(parsedParameterJSON);
  16 + },
  17 + error : function(xhr, textStatus, error) {
  18 + alert(xhr.responseText);
  19 + }
  20 + });
  21 + }
  22 +
  23 + function _showRenderedAvatar(parameterJSON) {
  24 + var userId = parameterJSON['userId'];
  25 + var signName = parameterJSON['sinal'];
  26 + $("#render-avatar video").attr("src",
  27 + _getRenderedAvatarUrl(userId, signName));
  28 + $("#render-avatar").fadeIn(300);
  29 + }
  30 +
  31 + function _showRenderScreen(toShow) {
  32 + if (toShow) {
  33 + $("#render-screen").fadeIn(300);
  34 + videoHelper.play("#render-ref video");
  35 + videoHelper.play("#render-avatar video");
  36 + } else {
  37 + $("#render-screen").hide();
  38 + videoHelper.pause("#render-ref video");
  39 + videoHelper.pause("#render-avatar video");
  40 + }
  41 + }
  42 +
  43 + function _getRenderedAvatarUrl(userId, signName) {
  44 + return api_url + '/public/' + userId + '/' + signName + ".webm";
  45 + }
  46 +
  47 + renderSign.showRenderedAvatar = function(parameterJSON) {
  48 + _showRenderedAvatar(parameterJSON);
  49 + _showRenderScreen(true);
  50 + }
  51 +
  52 + renderSign.showRenderScreen = function(toShow) {
  53 + _showRenderScreen(toShow);
  54 + }
  55 +
  56 + renderSign.getRenderedAvatarUrl = function(userId, signName) {
  57 + return _getRenderedAvatarUrl(userId, signName);
  58 + }
  59 +
  60 + renderSign.submit = function(parsedParameterJSON) {
  61 + configurationScreen.show(false);
  62 + _showRenderScreen(true);
  63 + $("#render-avatar").hide();
  64 + $("#render-loading").fadeIn(300);
  65 + $("#render-button-container .btn").hide();
  66 + $("#finish-button").addClass("disabled");
  67 + $("#finish-button").show();
  68 +
  69 + _submitParameterJSON(parsedParameterJSON, function(parsedParameterJSON) {
  70 + $("#render-loading").fadeOut(300);
  71 + $("#finish-button").removeClass("disabled");
  72 + _showRenderedAvatar(parsedParameterJSON);
  73 + });
  74 + };
  75 +
  76 + renderSign.setup = function(apiUrl) {
  77 + api_url = apiUrl;
  78 + $("#render-edit").off("click").on("click", function() {
  79 + _showRenderScreen(false);
  80 + configurationScreen.show(true);
  81 + });
  82 + }
  83 +
  84 +}(window.renderSign = window.renderSign || {}, jQuery));
view/assets/js/selection-panel/articulation.js 0 → 100644
@@ -0,0 +1,143 @@ @@ -0,0 +1,143 @@
  1 +(function(articulation, $, undefined) {
  2 +
  3 + var server_host = '';
  4 + var MAX_COLUMNS = 14;
  5 +
  6 + function _updateASelector(container, ballSelector, step) {
  7 + var pointSelector = parseInt(step) == 2 ? 'A' : 'B';
  8 + $(container + ' .ball-selector.active').each(function() {
  9 + $(this).removeClass('active');
  10 + $(this).find('.point-selector').remove();
  11 + });
  12 + ballSelector.addClass('active');
  13 + ballSelector.append('<div class="point-selector"><img src="'
  14 + + server_host + '/img/pa/' + pointSelector
  15 + + '-Seletor.png" class="point-selector" alt=""></div>');
  16 + $(container + ' .selection-panel-option[select=true]').attr('select',
  17 + false);
  18 + $(ballSelector).attr('select', true);
  19 + }
  20 +
  21 + function _getSelectedY(hand, subConfig, step) {
  22 + step = parseInt(step) - 1;
  23 + var previousStepId = '.selection-panel-body[mainConfig=' + hand
  24 + + '][subConfig=' + subConfig + '][step=' + step
  25 + + '] .module-x-y';
  26 + return $(previousStepId).attr('data-y');
  27 + }
  28 +
  29 + function _setupModuleZ(hand, subConfig, step, selectedY) {
  30 + if (typeof selectedY == 'undefined' || selectedY == '')
  31 + return;
  32 +
  33 + var base_id = '.selection-panel-body[mainConfig=' + hand
  34 + + '][subConfig=' + subConfig + '][step=' + step + ']';
  35 + var articulation_z = base_id + ' .module-z';
  36 + $(articulation_z + ' .ball-selector').hide();
  37 + $(articulation_z + ' .row-number-' + selectedY + ' .ball-selector')
  38 + .show();
  39 +
  40 + var z = $(articulation_z).attr('data-z');
  41 + if (typeof z != 'undefined') {
  42 + var ball_selector = $(articulation_z + ' .row-number-' + selectedY
  43 + + ' .ball-' + z);
  44 + _updateASelector(articulation_z, ball_selector, step);
  45 + }
  46 + }
  47 +
  48 + function _setupBallSelectorXY(hand, subConfig, step) {
  49 + var base_id = '.selection-panel-body[mainConfig=' + hand
  50 + + '][subConfig=' + subConfig + '][step=' + step + ']';
  51 + var articulation_x_y = base_id + ' .module-x-y';
  52 + $(articulation_x_y + ' .ball-selector')
  53 + .off('click')
  54 + .on(
  55 + 'click',
  56 + function(a) {
  57 + var b = $(a.target);
  58 + if (!b.hasClass('ball-selector')) {
  59 + dynworkflow.userSelectedAnOption();
  60 + return;
  61 + }
  62 + var c = b.parent('.grid-row'), d = $(articulation_x_y), f = b
  63 + .attr('data-x'), g = c.attr('data-y');
  64 + d.attr('data-x', f), d.attr('data-y', g);
  65 +
  66 + var nextStep = parseInt(step) + 1;
  67 + _updateASelector(articulation_x_y, b, nextStep);
  68 + _setupModuleZ(hand, subConfig, nextStep, g);
  69 +
  70 + wikilibras.updateTempParameterJSON(hand, subConfig,
  71 + step, f + ';' + g);
  72 + dynworkflow.userSelectedAnOption();
  73 + });
  74 + }
  75 +
  76 + function _setupBallSelectorZ(hand, subConfig, step) {
  77 + var base_id = '.selection-panel-body[mainConfig=' + hand
  78 + + '][subConfig=' + subConfig + '][step=' + step + ']';
  79 + var articulation_z = base_id + ' .module-z';
  80 + $(articulation_z + ' .ball-selector').off('click').on(
  81 + 'click',
  82 + function(a) {
  83 + var b = $(a.target);
  84 + if (!b.hasClass('ball-selector')) {
  85 + dynworkflow.userSelectedAnOption();
  86 + return;
  87 + }
  88 + var c = b.parent('.grid-row'), e = $(articulation_z), h = b
  89 + .attr('data-z');
  90 + b.attr('data-z') && e.attr('data-z', h), _updateASelector(
  91 + articulation_z, b, step);
  92 +
  93 + wikilibras
  94 + .updateTempParameterJSON(hand, subConfig, step, h);
  95 + dynworkflow.userSelectedAnOption();
  96 + });
  97 + }
  98 +
  99 + function _calculateArticulationPointIndex(hand, xValue, yValue, zValue) {
  100 + var x = xValue;
  101 + var y = yValue;
  102 + var z = zValue;
  103 + if (hand == 'left-hand') {
  104 + x = MAX_COLUMNS - x + 1;
  105 + }
  106 +
  107 + var value = (z - 1) * MAX_COLUMNS + x + 3 * MAX_COLUMNS * (y - 1);
  108 + //console.log(value);
  109 + return value;
  110 + }
  111 +
  112 + articulation.processValue = function(hand, selectionArray) {
  113 + var xyValueSplit = selectionArray[0].split(';');
  114 + var xValue = parseInt(xyValueSplit[0]);
  115 + var yValue = parseInt(xyValueSplit[1]);
  116 + var zValue = parseInt(selectionArray[1]);
  117 + return _calculateArticulationPointIndex(hand, xValue, yValue, zValue);
  118 + };
  119 +
  120 + articulation.setupModuleXY = function(serverhost, hand, subConfig, step) {
  121 + server_host = serverhost;
  122 + _setupBallSelectorXY(hand, subConfig, step);
  123 + };
  124 +
  125 + articulation.setupModuleZ = function(serverhost, hand, subConfig, step) {
  126 + server_host = serverhost;
  127 + _setupBallSelectorZ(hand, subConfig, step);
  128 +
  129 + var selectedY = _getSelectedY(hand, subConfig, step);
  130 + _setupModuleZ(hand, subConfig, step, selectedY);
  131 + };
  132 +
  133 + articulation.clean = function() {
  134 + $('.ball-selector.active').each(function() {
  135 + $(this).removeClass('active');
  136 + $(this).find('.point-selector').remove();
  137 + });
  138 + $('.module-x-y').attr('data-x', '');
  139 + $('.module-x-y').attr('data-y', '');
  140 + $('.module-z').attr('data-z', '');
  141 + }
  142 +
  143 +}(window.articulation = window.articulation || {}, jQuery));
view/assets/js/selection-panel/configuration.js 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +(function(configuration, $, undefined) {
  2 +
  3 + configuration.setupFingersGroup = function(hand, subConfig, step) {
  4 + var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +
  5 + subConfig + '][step=' + step + ']';
  6 + $(baseId + ' .selection-panel-option'
  7 + ).off('click').on('click', function() {
  8 + selectionPanel.selectAnOption(baseId, this);
  9 + _setupFingersToShow(hand, subConfig, step);
  10 +
  11 + dynworkflow.userSelectedAnOption();
  12 + });
  13 + };
  14 +
  15 + function _setupFingersToShow(hand, subConfig, step) {
  16 + var stepOneBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +
  17 + subConfig + '][step=' + step + ']';
  18 + var nextStep = parseInt(step) + 1;
  19 + var stepTwoBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +
  20 + subConfig + '][step=' + nextStep + ']';
  21 +
  22 + var finger_group = $(stepOneBaseId + ' .selection-panel-option[select=true]').attr('value');
  23 + finger_group = typeof finger_group == 'undefined' ? '0' : finger_group;
  24 +
  25 + // clean next step
  26 + dynworkflow.cleanStep(hand, subConfig, nextStep);
  27 + $(stepTwoBaseId + ' .finger-group').hide();
  28 + $(stepTwoBaseId + ' .finger-group[group=' + finger_group + ']').show();
  29 + }
  30 +
  31 + configuration.setupFingersPosition = function(hand, subConfig, step) {
  32 + var stepTwoBaseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +
  33 + subConfig + '][step=' + step + ']';
  34 + $(stepTwoBaseId + ' .selection-panel-option').off('click').on(
  35 + 'click', function() {
  36 + selectionPanel.selectAnOption(stepTwoBaseId, this);
  37 + dynworkflow.userSelectedAnOption();
  38 + });
  39 + var previousStep = parseInt(step) - 1;
  40 + _setupFingersToShow(hand, subConfig, previousStep);
  41 + };
  42 +
  43 +}(window.configuration = window.configuration || {}, jQuery));
view/assets/js/selection-panel/default-configuration-handler.js 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +(function(defaultConfigurationHandler, $, undefined) {
  2 +
  3 + defaultConfigurationHandler.setup = function(hand, subConfig, step) {
  4 + var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +
  5 + subConfig + '][step=' + step + ']';
  6 + $(baseId + ' .selection-panel-option').off('click').on(
  7 + 'click', function() {
  8 + selectionPanel.selectAnOption(baseId, this);
  9 + dynworkflow.userSelectedAnOption();
  10 + });
  11 + };
  12 +
  13 + function _startVideoLoop(hand, subConfig, step, timeBetweenLoops) {
  14 + setTimeout(function(){
  15 + $('.selection-panel-body[mainConfig=' + hand + '][subConfig=' +
  16 + subConfig + '][step=' + step + '] video').each(function(){
  17 + videoHelper.play(this);
  18 + });
  19 + _startVideoLoop(hand, subConfig, step, timeBetweenLoops);
  20 + }, timeBetweenLoops);
  21 + }
  22 +
  23 + defaultConfigurationHandler.startVideoLoop = function(hand, subConfig, step, timeBetweenLoops) {
  24 + _startVideoLoop(hand, subConfig, step, timeBetweenLoops);
  25 + }
  26 +
  27 +}(window.defaultConfigurationHandler = window.defaultConfigurationHandler || {}, jQuery));
view/assets/js/selection-panel/dynamic-loading-engine.js 0 → 100644
@@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
  1 +(function(dynengine, $, undefined) {
  2 + var setup = undefined;
  3 +
  4 + _preprocessHtml = function(data, url) {
  5 + var matchSubConfig = data.match(/sub(?:C|c)onfig="(.*?)"/);
  6 + var currentMainConfig = dynworkflow.getMainConfig(); // right-hand or left-hand
  7 + var goodData = data;
  8 +
  9 + var isRightHand = function(hand) {
  10 + return hand === 'right-hand';
  11 + };
  12 +
  13 + var replaceConfigurationTag = function(data, mainConfig) {
  14 + if (isRightHand(mainConfig)) {
  15 + return data.replace(/{{ configuracao }}/g, 'cmd');
  16 + } else {
  17 + return data.replace(/{{ configuracao }}/g, 'cme');
  18 + }
  19 + }
  20 +
  21 + var replaceOrientationTag = function(data, mainConfig) {
  22 + if (isRightHand(mainConfig)) {
  23 + return data.replace(/{{ orientacao }}/g, 'ord');
  24 + } else {
  25 + return data.replace(/{{ orientacao }}/g, 'ore');
  26 + }
  27 + }
  28 +
  29 + var replaceHandFolderTag = function(data, mainConfig) {
  30 + if (isRightHand(mainConfig)) {
  31 + return data.replace(/{{ hand-folder }}/g, 'md');
  32 + } else {
  33 + return data.replace(/{{ hand-folder }}/g, 'me');
  34 + }
  35 + }
  36 +
  37 + var replaceMovementNameTag = function(data, mainConfig) {
  38 + var selectedMovement = movement.getPreviousSelectedMovement(mainConfig);
  39 + if (typeof selectedMovement != "undefined") {
  40 + return data.replace(/{{ movement-name }}/g, selectedMovement);
  41 + }
  42 + return data
  43 + }
  44 +
  45 + if (matchSubConfig) { // case defined
  46 + // There is no specific(right or left hand dependent) assets for: articulacao, duracao, expressao, movimento, transicao
  47 + // Specific configurations: configuracao, orientacao
  48 + // possible values on the side as comment
  49 + var subConfig = matchSubConfig[1]; // articulacao | configuracao | duracao | expressao | movimento | orientacao | transicao
  50 +
  51 + // possible subconfigs that need changing
  52 + switch (subConfig) {
  53 + case 'configuracao':
  54 + goodData = replaceConfigurationTag(data, currentMainConfig);
  55 + break;
  56 + case 'configuracao-retilineo':
  57 + goodData = replaceConfigurationTag(data, currentMainConfig);
  58 + break;
  59 + case 'orientacao':
  60 + goodData = replaceOrientationTag(data, currentMainConfig);
  61 + break;
  62 + case 'orientacao-retilineo':
  63 + goodData = replaceOrientationTag(data, currentMainConfig);
  64 + break;
  65 + }
  66 + }
  67 + goodData = replaceHandFolderTag(goodData, currentMainConfig);
  68 + goodData = replaceMovementNameTag(goodData, currentMainConfig);
  69 + goodData = goodData.replace(/{{ hand }}/g, currentMainConfig);
  70 + return goodData.replace(/{{ server }}/g, url);
  71 + };
  72 +
  73 + dynengine.render = function(serverUrl, templatePath, target, prepend, callback) {
  74 + var url = serverUrl + templatePath;
  75 + $.get(url, function(data) {
  76 + var processedHtml = _preprocessHtml(data, serverUrl);
  77 + if (prepend) {
  78 + $(target).prepend(processedHtml);
  79 + } else {
  80 + $(target).append(processedHtml);
  81 + }
  82 + })
  83 + .done(function() {
  84 + callback && callback(); // call if defined
  85 + });
  86 + };
  87 +
  88 + dynengine.clean = function(target) {
  89 + $(target).html('');
  90 + };
  91 +
  92 + dynengine.load = function() {
  93 + var url = $('#server-url').data('url');
  94 + };
  95 +
  96 +}(window.dynengine = window.dynengine || {}, jQuery));
view/assets/js/selection-panel/dynamic-selection-workflow.js 0 → 100644
@@ -0,0 +1,369 @@ @@ -0,0 +1,369 @@
  1 +(function(dynworkflow, $, undefined) {
  2 +
  3 + // Workflow configuration
  4 + var jsonWF = {};
  5 + var baseUrl = '';
  6 +
  7 + // Main configurations: right-hand, left-hand and facial
  8 + var mainConfig = '';
  9 + // The converted Main Config (right/left-hand) to hand for using the same configuration
  10 + var preprocessedMainConfig = '';
  11 + // Subconfigurations: movimento, articulacao, configuracao, orientacao, etc
  12 + var currentSubconfig = '';
  13 + var currentSubConfigName = '';
  14 + var currentSubconfigParent = '';
  15 + var currentStep = 0;
  16 +
  17 + function _preprocessMainConfig(config) {
  18 + config = config.replace('right-hand', 'hand');
  19 + config = config.replace('left-hand', 'hand');
  20 + return config;
  21 + }
  22 +
  23 + function _getFirstKey(json) {
  24 + var first_key = undefined;
  25 + for (first_key in json)
  26 + break;
  27 + return first_key;
  28 + }
  29 +
  30 + function _getAttributes(json) {
  31 + var result = [];
  32 + for (attr in json) {
  33 + result.push(attr);
  34 + }
  35 + return result;
  36 + }
  37 +
  38 + function _updateAndGetFirstMovementSubConfig() {
  39 + var selectedMovement = movement.getPreviousSelectedMovement(mainConfig);
  40 + if (typeof selectedMovement == 'undefined')
  41 + return -1;
  42 +
  43 + currentSubconfigParent = jsonWF[preprocessedMainConfig]['movimento'][selectedMovement];
  44 + currentSubConfigName = _getFirstKey(currentSubconfigParent);
  45 + return currentSubConfigName;
  46 + }
  47 +
  48 + function _updateAndGetMovementConfig() {
  49 + currentSubconfigParent = jsonWF[preprocessedMainConfig];
  50 + currentSubConfigName = _getFirstKey(currentSubconfigParent);
  51 + return currentSubConfigName;
  52 + }
  53 +
  54 + function _getNextSubConfig(toForward) {
  55 + var attrs = _getAttributes(currentSubconfigParent);
  56 + for (var i = 0; i < attrs.length; i++) {
  57 + if (toForward && attrs[i] == currentSubConfigName
  58 + && i < attrs.length - 1) {
  59 + return attrs[i + 1];
  60 + } else if (!toForward && attrs[i] == currentSubConfigName && i >= 1) {
  61 + return attrs[i - 1];
  62 + }
  63 + }
  64 + if (toForward && currentSubConfigName == 'movimento') {
  65 + return _updateAndGetFirstMovementSubConfig();
  66 + } else if (!toForward && preprocessedMainConfig == 'hand') {
  67 + return _updateAndGetMovementConfig();
  68 + } else if (!toForward) {
  69 + return currentSubConfigName;
  70 + } else {
  71 + return -1;
  72 + }
  73 + }
  74 +
  75 + function _showCurrentSubconfig() {
  76 + _showSubconfiguration(mainConfig, currentSubConfigName, currentStep);
  77 + }
  78 +
  79 + // It checks if a selection panel is already loaded
  80 + function _isSubconfigurationPanelLoaded(mainConfig, subConfig, stepNumber) {
  81 + var stepNumber = stepNumber + 1;
  82 + return $('.selection-panel-body[mainConfig=' + mainConfig
  83 + + '][subConfig=' + subConfig + '][step=' + stepNumber + ']').length > 0;
  84 + }
  85 +
  86 + function _showLoadedSubconfigurationPanel(mainConfig, subConfig, stepNumber) {
  87 + var stepNumber = stepNumber + 1;
  88 + return $(
  89 + '.selection-panel-body[mainConfig=' + mainConfig
  90 + + '][subConfig=' + subConfig + '][step=' + stepNumber
  91 + + ']').show();
  92 + }
  93 +
  94 + // It renders or shows the requested selection panel
  95 + function _showSubconfiguration(mainConfig, subConfig, stepNumber) {
  96 + $('.selection-panel-body').hide();
  97 + if (_isSubconfigurationPanelLoaded(mainConfig, subConfig, stepNumber)) {
  98 + _showLoadedSubconfigurationPanel(mainConfig, subConfig, stepNumber);
  99 + } else {
  100 + var step = currentSubconfig[stepNumber];
  101 + step = typeof step == 'undefined' ? 'passo-1' : step;
  102 + dynengine.render(baseUrl, '/' + preprocessedMainConfig + '/'
  103 + + subConfig + '/' + step + '.html', '#selection-panel',
  104 + true);
  105 + }
  106 + _selectTimelineIcon(mainConfig, subConfig, true);
  107 + }
  108 +
  109 + function _selectSubConfig(subConfig) {
  110 + if (subConfig == 'movimento') {
  111 + _updateAndGetMovementConfig();
  112 + } else if (currentSubConfigName == 'movimento') {
  113 + _updateAndGetFirstMovementSubConfig();
  114 + }
  115 + currentSubConfigName = subConfig;
  116 + currentSubconfig = currentSubconfigParent[currentSubConfigName];
  117 + currentStep = 0;
  118 + _showCurrentSubconfig();
  119 + }
  120 +
  121 + // It shows the next selection panel on the workflow
  122 + function _showNextSubConfig() {
  123 + _walkOnTheWorkflow(true);
  124 + }
  125 +
  126 + function _showPreviousSubConfig() {
  127 + _walkOnTheWorkflow(false);
  128 + }
  129 +
  130 + function _walkOnTheWorkflow(toForward) {
  131 + currentStep = toForward ? currentStep + 1 : currentStep - 1;
  132 +
  133 + if (currentStep >= 0 && currentStep < currentSubconfig.length) {
  134 + _showCurrentSubconfig();
  135 + } else {
  136 + var nextSubConfig = _getNextSubConfig(toForward);
  137 + if (nextSubConfig != -1) {
  138 + _selectSubConfig(nextSubConfig);
  139 + } else {
  140 + selectionPanel.hide();
  141 + }
  142 + }
  143 + }
  144 +
  145 + function _checkIfFinished(mainConfig, currentSubConfigName) {
  146 + var numberOfSteps = currentSubconfig.length;
  147 + var completedSteps = $('.selection-panel-body[mainConfig=' + mainConfig
  148 + + '][subConfig=' + currentSubConfigName
  149 + + '] .selection-panel-option[select=true]').length;
  150 + return completedSteps != 0 && completedSteps == numberOfSteps;
  151 + }
  152 +
  153 + // A callback function to be called when the user selects a option on a panel
  154 + function _userSelectedAnOption() {
  155 + if (_checkIfFinished(mainConfig, currentSubConfigName)) {
  156 + _setupCheckIcon(mainConfig, currentSubConfigName);
  157 + }
  158 + _showNextSubConfig();
  159 + }
  160 +
  161 + function _cleanStep(mainConfig, subConfig, step) {
  162 + var baseId = '.selection-panel-body[mainConfig=' + mainConfig
  163 + + '][subConfig=' + subConfig + '][step=' + step + ']';
  164 + $(baseId + ' .selection-panel-option').removeAttr('select');
  165 + var icon_id = '.subconfiguration-panel[mainConfig=' + mainConfig
  166 + + '] .icon_container[json_name=' + subConfig + ']';
  167 + $(icon_id).removeAttr('complete');
  168 + }
  169 +
  170 + // Timeline functions
  171 + function _selectTimelineIcon(mainConfig, subConfig) {
  172 + var baseId = '.subconfiguration-panel[mainConfig=' + mainConfig
  173 + + '] .subconfiguration-options';
  174 + var iconContainer = '.icon_container[json_name=' + subConfig + ']';
  175 + var iconId = baseId + ' ' + iconContainer;
  176 +
  177 + var previousSelected = $(baseId + ' .icon_container[select=true]')
  178 + .attr('json_name');
  179 + if (typeof previousSelected != 'undefined') {
  180 + _deselectTimelineIcon(mainConfig, previousSelected);
  181 + }
  182 +
  183 + iconHelper.enableIconHover($(iconId), true);
  184 + $(iconId).attr('select', true);
  185 + $(baseId).scrollTo(iconContainer, {
  186 + 'offset' : -60,
  187 + 'duration' : 750
  188 + });
  189 + }
  190 +
  191 + function _deselectTimelineIcon(mainConfig, subConfig) {
  192 + var icon_id = '.subconfiguration-panel[mainConfig=' + mainConfig
  193 + + '] .icon_container[json_name=' + subConfig + ']';
  194 +
  195 + if ($(icon_id + '[complete=true]').length > 0) {
  196 + _setupCheckIcon(mainConfig, subConfig);
  197 + } else {
  198 + iconHelper.enableIconHover($(icon_id), false);
  199 + $(icon_id).removeAttr('select');
  200 + }
  201 + }
  202 +
  203 + function _setupCheckIcon(mainConfig, subConfig) {
  204 + var icon_id = $('.subconfiguration-panel[mainConfig=' + mainConfig
  205 + + '] .icon_container[json_name=' + subConfig + ']');
  206 + iconHelper.enableIconCheck(icon_id, true);
  207 + $(icon_id).attr('complete', true);
  208 + $(icon_id).attr('select', false);
  209 + }
  210 +
  211 + function _isTimelineLoaded() {
  212 + return $('.subconfiguration-panel[mainConfig=' + mainConfig + ']').length > 0;
  213 + }
  214 +
  215 + function _setupTimelineListeners(timelineBaseId) {
  216 + $(timelineBaseId + ' .icon_container[json_name]').off('click').on(
  217 + 'click', function() {
  218 + var subConfig = $(this).attr('json_name');
  219 + _selectSubConfig(subConfig);
  220 + });
  221 + $(timelineBaseId + ' .icon_container[json_name]').off('mouseover').on(
  222 + 'mouseover', function() {
  223 + if (iconHelper.canHover(this)) {
  224 + iconHelper.enableIconHover(this, true);
  225 + }
  226 + });
  227 + $(timelineBaseId + ' .icon_container[json_name]').off('mouseout').on(
  228 + 'mouseout', function() {
  229 + if (iconHelper.canHover(this)) {
  230 + iconHelper.enableIconHover(this, false);
  231 + }
  232 + });
  233 + $(timelineBaseId + ' .arrow[name=right-arrow]').off('click').on(
  234 + 'click', function() {
  235 + _showNextSubConfig();
  236 + });
  237 + $(timelineBaseId + ' .arrow[name=left-arrow]').off('click').on('click',
  238 + function() {
  239 + _showPreviousSubConfig();
  240 + });
  241 + }
  242 +
  243 + function _setupTimelineIcons(timelineBaseId, toUpdate) {
  244 + if (!toUpdate) {
  245 + $(timelineBaseId).show();
  246 + $(timelineBaseId + " .subconfiguration-options").scrollTo(0, 0);
  247 + return;
  248 + }
  249 +
  250 + $(timelineBaseId + ' .icon_container[json_name]').attr("active",
  251 + "false");
  252 + for ( var name in currentSubconfigParent) {
  253 + $(timelineBaseId + ' .icon_container[json_name=' + name + ']')
  254 + .attr("active", "true");
  255 + }
  256 +
  257 + if (preprocessedMainConfig == 'hand') {
  258 + $(timelineBaseId + ' .icon_container[json_name=movimento]').attr(
  259 + "active", "true");
  260 + _setupCheckIcon(mainConfig, 'movimento');
  261 + }
  262 + _selectTimelineIcon(mainConfig, currentSubConfigName);
  263 + _setupTimelineListeners(timelineBaseId);
  264 + $(timelineBaseId).show();
  265 + }
  266 +
  267 + function _setupTimeline(toUpdate) {
  268 + var timelineBaseId = '.subconfiguration-panel[mainConfig=' + mainConfig
  269 + + ']';
  270 + if (_isTimelineLoaded()) {
  271 + _setupTimelineIcons(timelineBaseId, toUpdate);
  272 + } else {
  273 + dynengine.render(baseUrl, '/' + preprocessedMainConfig
  274 + + '/timeline.html', '#selection-panel', false, function() {
  275 + _setupTimelineIcons(timelineBaseId, true);
  276 + });
  277 + }
  278 + }
  279 +
  280 + function _initTimeline() {
  281 + if (preprocessedMainConfig != 'hand' || _isTimelineLoaded()) {
  282 + _setupTimeline(false);
  283 + }
  284 + }
  285 +
  286 + function _cleanTimeline() {
  287 + $(".subconfiguration-panel").remove();
  288 + }
  289 +
  290 + function _cleanPreviousLoadedPanel() {
  291 + $('.selection-panel-body[mainConfig=' + mainConfig + ']').each(
  292 + function() {
  293 + var subConfigName = $(this).attr("subConfig");
  294 + if (subConfigName.indexOf("articulacao") != -1
  295 + || subConfigName.indexOf("configuracao") != -1
  296 + || subConfigName.indexOf("orientacao") != -1
  297 + || subConfigName.indexOf("movimento") != -1) {
  298 + return;
  299 + }
  300 + $(
  301 + '.selection-panel-body[mainConfig=' + mainConfig
  302 + + '][subConfig=' + subConfigName + ']')
  303 + .remove();
  304 + });
  305 + }
  306 +
  307 + // Public methods
  308 + dynworkflow.selectMainConfig = function(config) {
  309 + mainConfig = config;
  310 + preprocessedMainConfig = _preprocessMainConfig(mainConfig);
  311 + currentSubconfigParent = jsonWF[preprocessedMainConfig];
  312 + currentSubConfigName = _getFirstKey(currentSubconfigParent);
  313 + currentSubconfig = currentSubconfigParent[currentSubConfigName];
  314 + currentStep = 0;
  315 +
  316 + _showCurrentSubconfig();
  317 + };
  318 +
  319 + dynworkflow.selectMovement = function(movement) {
  320 + var subconfigJSON = currentSubconfig[movement];
  321 + currentSubConfigName = _getFirstKey(subconfigJSON);
  322 + currentSubconfigParent = subconfigJSON;
  323 + currentSubconfig = subconfigJSON[currentSubConfigName];
  324 + currentStep = 0;
  325 +
  326 + _cleanPreviousLoadedPanel();
  327 + _showCurrentSubconfig();
  328 + _setupTimeline(true);
  329 + };
  330 +
  331 + dynworkflow.selectSubConfig = function(subConfig) {
  332 + _selectSubConfig(subConfig);
  333 + };
  334 +
  335 + dynworkflow.userSelectedAnOption = function() {
  336 + _userSelectedAnOption();
  337 + };
  338 +
  339 + dynworkflow.cleanStep = function(mainConfig, subConfig, step) {
  340 + _cleanStep(mainConfig, subConfig, step);
  341 + };
  342 +
  343 + dynworkflow.getFacialParameters = function() {
  344 + return _getAttributes(jsonWF['facial']);
  345 + };
  346 +
  347 + dynworkflow.getMovementParameters = function(movementName) {
  348 + return _getAttributes(jsonWF['hand']['movimento'][movementName]);
  349 + };
  350 +
  351 + dynworkflow.getMainConfig = function() {
  352 + return mainConfig;
  353 + };
  354 +
  355 + dynworkflow.initTimeline = function() {
  356 + _initTimeline();
  357 + };
  358 +
  359 + dynworkflow.load = function() {
  360 + baseUrl = $('#server-url').data('url');
  361 + $.get(baseUrl + '/conf/selection-workflow-json', function(result) {
  362 + jsonWF = $.parseJSON(result);
  363 + }).fail(function() {
  364 + console.log('Failed to load the workflow configuration');
  365 + });
  366 + _cleanTimeline();
  367 + };
  368 +
  369 +}(window.dynworkflow = window.dynworkflow || {}, jQuery));
view/assets/js/selection-panel/facial.js 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +(function(facial, $, undefined) {
  2 +
  3 + facial.setup = function(subConfig) {
  4 + var baseId = '.selection-panel-body[mainConfig=facial][subConfig='
  5 + + subConfig + ']';
  6 + $(baseId + ' .selection-panel-option').off('click').on('click',
  7 + function() {
  8 + selectionPanel.selectAnOption(baseId, this);
  9 + dynworkflow.userSelectedAnOption();
  10 + });
  11 + $(baseId + ' .video-panel-option').off('mouseenter').on('mouseenter',
  12 + function(event) {
  13 + $(this).addClass('video-panel-option-hover');
  14 + });
  15 + $(baseId + ' .video-panel-option').off('mouseleave').on('mouseleave',
  16 + function(event) {
  17 + $(this).removeClass('video-panel-option-hover');
  18 + });
  19 + };
  20 +
  21 +}(window.facial = window.facial || {}, jQuery));
view/assets/js/selection-panel/movement.js 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +(function(movement, $, undefined) {
  2 +
  3 + movement.getPreviousSelectedMovement = function(mainConfig) {
  4 + return $('.selection-panel-body[mainConfig=' + mainConfig +
  5 + '][subConfig=movimento][step=1] .selection-panel-option[select=true]').attr('value');
  6 + };
  7 +
  8 + movement.setup = function(serverhost, hand) {
  9 + var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=movimento][step=1]';
  10 + $(baseId + ' .selection-panel-option').off('click').on(
  11 + 'click', function() {
  12 + selectionPanel.selectAnOption(baseId, this);
  13 + dynworkflow.selectMovement($(this).attr('value'));
  14 + });
  15 + $(baseId + ' .video-panel-option').off('mouseenter').on('mouseenter',
  16 + function(event) {
  17 + $(this).addClass('video-panel-option-hover');
  18 + });
  19 + $(baseId + ' .video-panel-option').off('mouseleave').on('mouseleave',
  20 + function(event) {
  21 + $(this).removeClass('video-panel-option-hover');
  22 + });
  23 + };
  24 +}(window.movement = window.movement || {}, jQuery));
view/assets/js/selection-panel/orientation.js 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +(function(orientation, $, undefined) {
  2 +
  3 + orientation.setup = function(hand, subConfig, step) {
  4 + var baseId = '.selection-panel-body[mainConfig=' + hand + '][subConfig=' +
  5 + subConfig + '][step=' + step + ']';
  6 + $(baseId + ' .selection-panel-option').off('click').on(
  7 + 'click', function() {
  8 + selectionPanel.selectAnOption(baseId, this);
  9 + dynworkflow.userSelectedAnOption();
  10 + });
  11 + };
  12 +
  13 +}(window.orientation = window.orientation || {}, jQuery));
view/assets/js/selection-panel/selection-panel.js 0 → 100644
@@ -0,0 +1,194 @@ @@ -0,0 +1,194 @@
  1 +(function(selectionPanel, $, undefined) {
  2 +
  3 + function _selectAnOption(parentId, el) {
  4 + $(parentId + ' .selection-panel-option[select=true]').removeAttr(
  5 + 'select');
  6 + $(el).attr('select', true);
  7 +
  8 + var mainConfig = $(parentId).attr('mainConfig');
  9 + var subConfig = $(parentId).attr('subConfig');
  10 + var step = $(parentId).attr('step');
  11 + wikilibras.updateTempParameterJSON(mainConfig, subConfig, step, $(el).attr(
  12 + 'value'));
  13 + }
  14 +
  15 + function _canRenderSignVideo() {
  16 + return _isConfigurationComplete('facial') &&
  17 + (_isConfigurationComplete('right-hand') || _isConfigurationComplete('left-hand'));
  18 + }
  19 +
  20 + function _isConfigurationComplete(config) {
  21 + var baseId = '.subconfiguration-panel[mainConfig=' + config + ']';
  22 + var total_config = $(baseId
  23 + + ' .icon_container[json_name][active=true]').length;
  24 + var completed_config = $(baseId
  25 + + ' .icon_container[active=true][complete=true]').length;
  26 + return completed_config != 0 && total_config == completed_config;
  27 + }
  28 +
  29 + function _clearPreviousSelection() {
  30 + $('.selection-panel-body').hide();
  31 + $('.subconfiguration-panel').hide();
  32 +
  33 + if (configurationScreen.isMenuSelected()) {
  34 + var current_option = configurationScreen.getCurrentMainConfiguration();
  35 + iconHelper.selectIcon(current_option, false);
  36 + if (_isConfigurationComplete(current_option)) {
  37 + iconHelper.setupCheckIcon(current_option, true);
  38 + }
  39 + $('#avatar-' + current_option).fadeOut(500);
  40 + }
  41 + }
  42 +
  43 + function _finishConfiguration(config, toFinish) {
  44 + iconHelper.setupCheckIcon(config, toFinish);
  45 + iconHelper.setupCheckIcon('avatar-' + config, toFinish);
  46 +
  47 + if (toFinish) {
  48 + $('#' + config + '-edit .check-icon').show();
  49 + } else {
  50 + $('#' + config + '-edit .check-icon').hide();
  51 + }
  52 + if (_canRenderSignVideo()) {
  53 + $('#ready-button').removeClass('disabled');
  54 + } else {
  55 + $('#ready-button').addClass('disabled');
  56 + }
  57 + }
  58 +
  59 + function _unfinishConfiguration(config, panel) {
  60 + iconHelper.setupCheckIcon(config, false, panel);
  61 + iconHelper.setupCheckIcon('avatar-' + config, false, panel);
  62 + $('#' + config + '-edit .check-icon').hide();
  63 +
  64 + if (!_canRenderSignVideo()) {
  65 + $('#ready-button').addClass('disabled');
  66 + }
  67 + }
  68 +
  69 + function _addZoomInToAvatar(option, callback) {
  70 + $('#avatar-default')
  71 + .fadeOut(
  72 + 500,
  73 + function() {
  74 + $('#avatar-container').removeClass('col-sm-7');
  75 + $('#avatar-container').addClass('col-sm-5');
  76 + $('#selection-container').removeClass('col-sm-2');
  77 + $('#selection-container').addClass('col-sm-4');
  78 + $('#avatar-container').removeClass(
  79 + 'avatar-container-zoom-out');
  80 + $('#avatar-container').addClass(
  81 + 'avatar-container-zoom-in');
  82 + $('#avatar-' + option).removeClass(
  83 + 'avatar-img-zoom-out');
  84 + $('#avatar-' + option).fadeIn(
  85 + 500,
  86 + function() {
  87 + $('#avatar-' + option).addClass(
  88 + 'avatar-' + option
  89 + + '-img-zoom-in');
  90 + callback();
  91 + });
  92 + });
  93 + }
  94 +
  95 + function _addZoomOutToAvatar(option, callback) {
  96 + $('#avatar-' + option).fadeOut(
  97 + 500,
  98 + function() {
  99 + $('#selection-container').removeClass('col-sm-4');
  100 + $('#selection-container').addClass('col-sm-2');
  101 + $('#avatar-container').removeClass('col-sm-5');
  102 + $('#avatar-container').addClass('col-sm-7');
  103 + $('#avatar-container').removeClass(
  104 + 'avatar-container-zoom-in');
  105 + $('#avatar-container')
  106 + .addClass('avatar-container-zoom-out');
  107 + $('#avatar-default').fadeIn(
  108 + 500,
  109 + function() {
  110 + $('#avatar-' + option).removeClass(
  111 + 'avatar-' + option + '-img-zoom-in');
  112 + $('#avatar-' + option).addClass(
  113 + 'avatar-img-zoom-out');
  114 + callback();
  115 + });
  116 + });
  117 + }
  118 +
  119 + function _hide() {
  120 + var config = configurationScreen.getCurrentMainConfiguration();
  121 + if (config === '') return;
  122 +
  123 + iconHelper.deselectIcon(config);
  124 + if (_isConfigurationComplete(config)) {
  125 + _finishConfiguration(config, true);
  126 + } else {
  127 + _finishConfiguration(config, false);
  128 + }
  129 +
  130 + _addZoomOutToAvatar(config, function() {
  131 + $('#ready-button').fadeIn(300);
  132 + $('.edit-container').fadeIn(300);
  133 + });
  134 + $('#selection-panel').fadeOut(300);
  135 + }
  136 +
  137 + function _setupGUIOnSelection(option, finishCallback) {
  138 + $('#ready-button').fadeOut(300);
  139 + $('.edit-container').fadeOut(300);
  140 + _addZoomInToAvatar(option, function() {
  141 + $('#selection-panel').fadeIn(300, function() {
  142 + finishCallback();
  143 + });
  144 + });
  145 + }
  146 +
  147 + function _show(option) {
  148 + _clearPreviousSelection();
  149 + iconHelper.selectIcon(option, true);
  150 + dynworkflow.selectMainConfig(option);
  151 + _setupGUIOnSelection(option, function() {
  152 + dynworkflow.initTimeline();
  153 + });
  154 + }
  155 +
  156 + selectionPanel.selectAnOption = function (parentId, el) {
  157 + _selectAnOption(parentId, el);
  158 + }
  159 +
  160 + selectionPanel.unfinishConfiguration = function(config, panel) {
  161 + return _unfinishConfiguration(config, panel);
  162 + }
  163 +
  164 + selectionPanel.isConfigurationComplete = function(config) {
  165 + return _isConfigurationComplete(config);
  166 + }
  167 +
  168 + selectionPanel.hide = function() {
  169 + return _hide();
  170 + }
  171 +
  172 + selectionPanel.show = function(option) {
  173 + _show(option);
  174 + }
  175 +
  176 + selectionPanel.clean = function() {
  177 + articulation.clean();
  178 + $(".selection-panel-option").removeAttr('select');
  179 + $(".icon_container").removeAttr("select");
  180 + $(".icon_container[complete=true]").each(
  181 + function() {
  182 + _unfinishConfiguration($(this).attr("name"), $(this).attr(
  183 + "panel"));
  184 + });
  185 + }
  186 +
  187 + selectionPanel.setup = function(url) {
  188 + $('#selection-panel .x').off('click').on('click', function() {
  189 + _hide();
  190 + });
  191 + selectionPanel.clean();
  192 + };
  193 +
  194 +}(window.selectionPanel = window.selectionPanel || {}, jQuery));
view/assets/js/submit-sign.js
@@ -32,6 +32,11 @@ @@ -32,6 +32,11 @@
32 $('#upload-progress-container').hide(); 32 $('#upload-progress-container').hide();
33 $('#input-sign-upload').show(); 33 $('#input-sign-upload').show();
34 } 34 }
  35 +
  36 + submitSign.show = function() {
  37 + $(".sub-main-container").hide();
  38 + $("#submit-sign-container").show();
  39 + }
35 40
36 submitSign.setup = function(uploadSignHost) { 41 submitSign.setup = function(uploadSignHost) {
37 submitUrl = uploadSignHost; 42 submitUrl = uploadSignHost;
view/assets/js/teached-signs.js
@@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
51 function _addSign(answer) { 51 function _addSign(answer) {
52 var signName = answer.parameter_json.sinal; 52 var signName = answer.parameter_json.sinal;
53 var apiUserId = answer.parameter_json.userId; 53 var apiUserId = answer.parameter_json.userId;
54 - var videoUrl = wikilibras.getRenderedAvatarUrl(apiUserId, signName); 54 + var videoUrl = renderSign.getRenderedAvatarUrl(apiUserId, signName);
55 $("#signs-list-container").append( 55 $("#signs-list-container").append(
56 '<div class="col-btn col-xs-6 col-sm-3 col-md-2" sign-name="' 56 '<div class="col-btn col-xs-6 col-sm-3 col-md-2" sign-name="'
57 + signName 57 + signName
@@ -77,6 +77,11 @@ @@ -77,6 +77,11 @@
77 _createSigns(answers); 77 _createSigns(answers);
78 }); 78 });
79 } 79 }
  80 +
  81 + teachedSigns.show = function() {
  82 + $(".sub-main-container").hide();
  83 + $("#teached-signs-container").show();
  84 + }
80 85
81 teachedSigns.setup = function() { 86 teachedSigns.setup = function() {
82 _getProjectId().done(function(response) { 87 _getProjectId().done(function(response) {
view/assets/js/tmpJSONParser.js
@@ -1,118 +0,0 @@ @@ -1,118 +0,0 @@
1 -(function(tmpJSONParser, $, undefined) {  
2 -  
3 - var base_parameter_json = {};  
4 - var movement_parameter_json = {};  
5 -  
6 - function _setupBaseParameterJSON(tmpJSON) {  
7 - base_parameter_json['userId'] = tmpJSON['userId'];  
8 - base_parameter_json['sinal'] = tmpJSON['sinal'];  
9 - base_parameter_json['interpolacao'] = 'normal';  
10 - base_parameter_json['movimentos'] = [];  
11 - movement_parameter_json = {  
12 - 'facial': {},  
13 - 'mao_direita': {},  
14 - 'mao_esquerda': {}  
15 - };  
16 - base_parameter_json['movimentos'].push(movement_parameter_json);  
17 - }  
18 -  
19 - function _parseParameterValue(value) {  
20 - if (typeof value == 'string' && value.toLowerCase() == 'true') {  
21 - return true;  
22 - } else if (typeof value == 'string' && value.toLowerCase() == 'false') {  
23 - return false;  
24 - } else {  
25 - return !isNaN(value) ? parseInt(value) : value;  
26 - }  
27 - }  
28 -  
29 - function _parseTempFacialParameterJSON(tmpJSON) {  
30 - var attrs = dynworkflow.getFacialParameters();  
31 - for (var i in attrs) {  
32 - var attr = attrs[i];  
33 - parameterValue = tmpJSON['facial'][attr][0];  
34 - movement_parameter_json['facial'][attr] = _parseParameterValue(parameterValue);  
35 - }  
36 - }  
37 -  
38 - function _parseHand(hand) {  
39 - var parsedHand = hand == 'right-hand' ? 'mao_direita' : hand;  
40 - parsedHand = hand == 'left-hand' ? 'mao_esquerda' : parsedHand;  
41 - return parsedHand;  
42 - }  
43 -  
44 - // Default parser  
45 - function _defaultMovementParser(tmpJSON, movementName, hand) {  
46 - var attrs = dynworkflow.getMovementParameters(movementName);  
47 - var parsedHand = _parseHand(hand);  
48 -  
49 - for (var i in attrs) {  
50 - var attr = attrs[i];  
51 - var parameterValue = '';  
52 - if (attr == 'configuracao') {  
53 - parameterValue = tmpJSON[hand][attr][1];  
54 - } else if (attr == 'articulacao') {  
55 - parameterValue = articulation.processValue(hand,  
56 - tmpJSON[hand][attr]);  
57 - } else {  
58 - parameterValue = tmpJSON[hand][attr][0];  
59 - }  
60 - movement_parameter_json[parsedHand][movementName][attr] =  
61 - _parseParameterValue(parameterValue);  
62 - }  
63 - }  
64 -  
65 - function _retilinearMovementParser(tmpJSON, movementName, hand) {  
66 - var attrs = dynworkflow.getMovementParameters(movementName);  
67 - var parsedHand = _parseHand(hand);  
68 -  
69 - for (var i in attrs) {  
70 - var attr = attrs[i];  
71 - var initParameterValue = '';  
72 - var endParameterValue = '';  
73 - if (attr == 'configuracao-retilineo') {  
74 - initParameterValue = tmpJSON[hand][attr][1];  
75 - endParameterValue = tmpJSON[hand][attr][3];  
76 - } else if (attr == 'articulacao-retilineo') {  
77 - initSlice = tmpJSON[hand][attr].slice(0, 2);  
78 - endSlice = tmpJSON[hand][attr].slice(2, 4);  
79 - initParameterValue = articulation.processValue(hand, initSlice);  
80 - endParameterValue = articulation.processValue(hand, endSlice);  
81 - } else {  
82 - initParameterValue = tmpJSON[hand][attr][0];  
83 - endParameterValue = tmpJSON[hand][attr][1];  
84 - }  
85 - attr = attr.replace('-retilineo', '');  
86 - var initAttr = attr + '_inicial';  
87 - var endAttr = attr + '_final';  
88 - movement_parameter_json[parsedHand][movementName][initAttr] =  
89 - _parseParameterValue(initParameterValue);  
90 - movement_parameter_json[parsedHand][movementName][endAttr] =  
91 - _parseParameterValue(endParameterValue);  
92 - }  
93 - }  
94 -  
95 - function _parseTempMovementParameterJSON(tmpJSON, hand) {  
96 - var movimentConfig = tmpJSON[hand]['movimento'];  
97 - if (typeof movimentConfig == 'undefined') return;  
98 -  
99 - var movementName = movimentConfig[0];  
100 - var parsedHand = _parseHand(hand);  
101 - movement_parameter_json[parsedHand][movementName] = {};  
102 -  
103 - if (movementName == 'retilineo') {  
104 - _retilinearMovementParser(tmpJSON, movementName, hand);  
105 - } else {  
106 - _defaultMovementParser(tmpJSON, movementName, hand);  
107 - }  
108 - }  
109 -  
110 - tmpJSONParser.parse = function(tmpJSON) {  
111 - _setupBaseParameterJSON(tmpJSON);  
112 - _parseTempFacialParameterJSON(tmpJSON);  
113 - _parseTempMovementParameterJSON(tmpJSON, 'right-hand');  
114 - _parseTempMovementParameterJSON(tmpJSON, 'left-hand');  
115 - return base_parameter_json;  
116 - };  
117 -  
118 -}(window.tmpJSONParser = window.tmpJSONParser || {}, jQuery));  
view/assets/js/wikilibras.js
@@ -37,234 +37,6 @@ @@ -37,234 +37,6 @@
37 _setupTmpParameterJSON(task.info.sign_name); 37 _setupTmpParameterJSON(task.info.sign_name);
38 } 38 }
39 39
40 - function _changeImage(img, url) {  
41 - img.attr('src', url);  
42 - }  
43 -  
44 - function _enableIconHover(container, isHover) {  
45 - var img = $(container).find('img').first();  
46 - var hover_img_url = base_url + '/img/' + $(container).attr('name');  
47 - if (isHover) {  
48 - hover_img_url += '-icon-hover.png';  
49 - } else {  
50 - hover_img_url += '-icon.png';  
51 - }  
52 - _changeImage(img, hover_img_url);  
53 - }  
54 -  
55 - function _selectIcon(iconName, isSelect, panel) {  
56 - panel = typeof panel == 'undefined' ? '' : '[panel=' + panel + ']';  
57 - var icon_id = '.icon_container[name=' + iconName + ']' + panel;  
58 - _enableIconHover(icon_id, isSelect);  
59 - $(icon_id).attr('select', isSelect);  
60 - }  
61 -  
62 - function _deselectIcon(iconName, parent) {  
63 - _selectIcon(iconName, false, parent);  
64 - }  
65 -  
66 - function _enableIconCheck(container, isCheck) {  
67 - var img = $(container).find('img').first();  
68 - var check_img_url = base_url + '/img/' + $(container).attr('name');  
69 -  
70 - if (isCheck) {  
71 - check_img_url += '-icon-check.png';  
72 - } else {  
73 - check_img_url += '-icon.png';  
74 - }  
75 - _changeImage(img, check_img_url);  
76 - }  
77 -  
78 - function _setupCheckIcon(option, isCheck, panel) {  
79 - panel = typeof panel == 'undefined' ? '' : '[panel=' + panel + ']';  
80 - var icon_id = '.icon_container[name=' + option + ']' + panel;  
81 - _enableIconCheck(icon_id, isCheck);  
82 - $('.icon_container[name=' + option + ']' + panel).attr('complete',  
83 - isCheck);  
84 - }  
85 -  
86 - function _isSelectingState() {  
87 - return $('#configuration-panel .icon_container[select=true]').length > 0;  
88 - }  
89 -  
90 - function _isConfigurationComplete(config) {  
91 - var baseId = '.subconfiguration-panel[mainConfig=' + config + ']';  
92 - var total_config = $(baseId  
93 - + ' .icon_container[json_name][active=true]').length;  
94 - var completed_config = $(baseId  
95 - + ' .icon_container[active=true][complete=true]').length;  
96 - return completed_config != 0 && total_config == completed_config;  
97 - }  
98 -  
99 - function _canHover(el) {  
100 - var incompleteConfig = typeof $(el).attr('complete') == 'undefined'  
101 - || $(el).attr('complete') == 'false';  
102 - return (!_isSelectingState() && incompleteConfig)  
103 - || (typeof $(el).attr('select') == 'undefined' && incompleteConfig);  
104 - }  
105 -  
106 - function _getCurrentMainConfiguration() {  
107 - return _isSelectingState() ? $(  
108 - '#configuration-panel .icon_container[select=true]').attr(  
109 - 'name') : '';  
110 - }  
111 -  
112 - function _addZoomInToAvatar(option, callback) {  
113 - $('#avatar-default')  
114 - .fadeOut(  
115 - 500,  
116 - function() {  
117 - $('#avatar-container').removeClass('col-sm-7');  
118 - $('#avatar-container').addClass('col-sm-5');  
119 - $('#selection-container').removeClass('col-sm-2');  
120 - $('#selection-container').addClass('col-sm-4');  
121 - $('#avatar-container').removeClass(  
122 - 'avatar-container-zoom-out');  
123 - $('#avatar-container').addClass(  
124 - 'avatar-container-zoom-in');  
125 - $('#avatar-' + option).removeClass(  
126 - 'avatar-img-zoom-out');  
127 - $('#avatar-' + option).fadeIn(  
128 - 500,  
129 - function() {  
130 - $('#avatar-' + option).addClass(  
131 - 'avatar-' + option  
132 - + '-img-zoom-in');  
133 - callback();  
134 - });  
135 - });  
136 - }  
137 -  
138 - function _addZoomOutToAvatar(option, callback) {  
139 - $('#avatar-' + option).fadeOut(  
140 - 500,  
141 - function() {  
142 - $('#selection-container').removeClass('col-sm-4');  
143 - $('#selection-container').addClass('col-sm-2');  
144 - $('#avatar-container').removeClass('col-sm-5');  
145 - $('#avatar-container').addClass('col-sm-7');  
146 - $('#avatar-container').removeClass(  
147 - 'avatar-container-zoom-in');  
148 - $('#avatar-container')  
149 - .addClass('avatar-container-zoom-out');  
150 - $('#avatar-default').fadeIn(  
151 - 500,  
152 - function() {  
153 - $('#avatar-' + option).removeClass(  
154 - 'avatar-' + option + '-img-zoom-in');  
155 - $('#avatar-' + option).addClass(  
156 - 'avatar-img-zoom-out');  
157 - callback();  
158 - });  
159 - });  
160 - }  
161 -  
162 - function _clearPreviousSelection() {  
163 - $('.selection-panel-body').hide();  
164 - $('.subconfiguration-panel').hide();  
165 -  
166 - if (_isSelectingState()) {  
167 - var current_option = _getCurrentMainConfiguration();  
168 - _selectIcon(current_option, false);  
169 - if (_isConfigurationComplete(current_option)) {  
170 - _setupCheckIcon(current_option, true);  
171 - }  
172 - $('#avatar-' + current_option).fadeOut(500);  
173 - }  
174 - }  
175 -  
176 - function _showSelectionPanel(option) {  
177 - _clearPreviousSelection();  
178 - _selectIcon(option, true);  
179 - dynworkflow.selectMainConfig(option);  
180 - _setupGUIOnSelection(option, function() {  
181 - dynworkflow.initTimeline();  
182 - });  
183 - }  
184 -  
185 - function _hideSelectionPanel() {  
186 - var config = _getCurrentMainConfiguration();  
187 - _deselectIcon(config);  
188 - if (_isConfigurationComplete(config)) {  
189 - _finishConfiguration(config, true);  
190 - } else {  
191 - _finishConfiguration(config, false);  
192 - }  
193 -  
194 - _addZoomOutToAvatar(config, function() {  
195 - $('#ready-button').fadeIn(300);  
196 - $('.edit-container').fadeIn(300);  
197 - });  
198 - $('#selection-panel').fadeOut(300);  
199 - }  
200 -  
201 - function _canRenderSignVideo() {  
202 - return _isConfigurationComplete('facial')  
203 - && (_isConfigurationComplete('right-hand') || _isConfigurationComplete('left-hand'));  
204 - }  
205 -  
206 - function _finishConfiguration(config, toFinish) {  
207 - _setupCheckIcon(config, toFinish);  
208 - _setupCheckIcon('avatar-' + config, toFinish);  
209 -  
210 - if (toFinish) {  
211 - $('#' + config + '-edit .check-icon').show();  
212 - } else {  
213 - $('#' + config + '-edit .check-icon').hide();  
214 - }  
215 - if (_canRenderSignVideo()) {  
216 - $('#ready-button').removeClass('disabled');  
217 - } else {  
218 - $('#ready-button').addClass('disabled');  
219 - }  
220 - }  
221 -  
222 - function _unfinishConfiguration(config, panel) {  
223 - _setupCheckIcon(config, false, panel);  
224 - _setupCheckIcon('avatar-' + config, false, panel);  
225 - $('#' + config + '-edit .check-icon').hide();  
226 -  
227 - if (!_canRenderSignVideo()) {  
228 - $('#ready-button').addClass('disabled');  
229 - }  
230 - }  
231 -  
232 - function _setupGUIOnSelection(option, finishCallback) {  
233 - $('#ready-button').fadeOut(300);  
234 - $('.edit-container').fadeOut(300);  
235 - _addZoomInToAvatar(option, function() {  
236 - $('#selection-panel').fadeIn(300, function() {  
237 - finishCallback();  
238 - });  
239 - });  
240 - }  
241 -  
242 - function _setupConfigurationPanel() {  
243 - $('.icon_container').off('mouseover').on('mouseover', function() {  
244 - if (_canHover(this)) {  
245 - _enableIconHover(this, true);  
246 - }  
247 - });  
248 - $('.icon_container').off('mouseout').on('mouseout', function() {  
249 - if (_canHover(this)) {  
250 - _enableIconHover(this, false);  
251 - }  
252 - });  
253 - $('.config-panel-option').off('click').on('click', function() {  
254 - _showSelectionPanel($(this).attr('panel'));  
255 - });  
256 - $('#minimize-icon-container').off('click').on('click', function() {  
257 - $('#ref-video-container').hide();  
258 - $('#minimize-icon-container').hide();  
259 - $('#maximize-icon-container').show();  
260 - });  
261 - $('#maximize-icon-container').off('click').on('click', function() {  
262 - $('#ref-video-container').show();  
263 - $('#maximize-icon-container').hide();  
264 - $('#minimize-icon-container').show();  
265 - });  
266 - }  
267 -  
268 function _updateTempParameterJSON(mainConfig, subConfig, step, value) { 40 function _updateTempParameterJSON(mainConfig, subConfig, step, value) {
269 var subConfigJSON = tmpParameterJSON[mainConfig][subConfig]; 41 var subConfigJSON = tmpParameterJSON[mainConfig][subConfig];
270 if (typeof subConfigJSON == 'undefined') { 42 if (typeof subConfigJSON == 'undefined') {
@@ -275,132 +47,34 @@ @@ -275,132 +47,34 @@
275 subConfigJSON[parseInt(step) - 1] = value; 47 subConfigJSON[parseInt(step) - 1] = value;
276 } 48 }
277 49
278 - function _selectAnOption(parentId, el) {  
279 - $(parentId + ' .selection-panel-option[select=true]').removeAttr(  
280 - 'select');  
281 - $(el).attr('select', true);  
282 -  
283 - var mainConfig = $(parentId).attr('mainConfig');  
284 - var subConfig = $(parentId).attr('subConfig');  
285 - var step = $(parentId).attr('step');  
286 - _updateTempParameterJSON(mainConfig, subConfig, step, $(el).attr(  
287 - 'value'));  
288 - }  
289 -  
290 - function _setupSelectionPanel() {  
291 - $('#selection-panel .x').off('click').on('click', function() {  
292 - _hideSelectionPanel();  
293 - });  
294 - }  
295 -  
296 - // Render Screen  
297 - function _submitParameterJSON(callback) {  
298 - parsedParameterJSON = tmpJSONParser.parse(tmpParameterJSON);  
299 - console.log(parsedParameterJSON);  
300 -  
301 - $.ajax({  
302 - type : 'POST',  
303 - url : api_url + '/sign',  
304 - data : JSON.stringify(parsedParameterJSON),  
305 - contentType : 'application/json',  
306 - success : function(response) {  
307 - console.log(response);  
308 - callback();  
309 - },  
310 - error : function(xhr, textStatus, error) {  
311 - alert(xhr.responseText);  
312 - }  
313 - });  
314 - }  
315 -  
316 - function _getRenderedAvatarUrl(userId, signName) {  
317 - return api_url + '/public/' + userId + '/' + signName + ".webm"; 50 + function _parseTmpParameterJSON() {
  51 + parsedParameterJSON = tmpJSONParser.parse(tmpParameterJSON,
  52 + selectionPanel.isConfigurationComplete('right-hand'),
  53 + selectionPanel.isConfigurationComplete('left-hand'));
  54 + return parsedParameterJSON;
318 } 55 }
319 56
320 - function _showRenderedAvatar(parameterJSON) {  
321 - var userId = parameterJSON['userId'];  
322 - var signName = parameterJSON['sinal'];  
323 - $("#render-avatar video").attr("src",  
324 - _getRenderedAvatarUrl(userId, signName));  
325 - $("#render-avatar").fadeIn(300);  
326 - }  
327 -  
328 - function _controlVideo(elId, toPlay) {  
329 - var videoSrc = $(elId).attr("src");  
330 - if (typeof videoSrc == "undefined" ||  
331 - (typeof videoSrc != "undefined" && videoSrc === ""))  
332 - return;  
333 - if (toPlay) {  
334 - $(elId).get(0).play();  
335 - } else {  
336 - $(elId).get(0).pause();  
337 - }  
338 - }  
339 -  
340 - function _playVideo(elId) {  
341 - _controlVideo(elId, true);  
342 - }  
343 -  
344 - function _pauseVideo(elId) {  
345 - _controlVideo(elId, false);  
346 - }  
347 -  
348 function _showInitialScreen(toShow) { 57 function _showInitialScreen(toShow) {
349 if (toShow) { 58 if (toShow) {
350 $("#initial-screen").fadeIn(300); 59 $("#initial-screen").fadeIn(300);
351 - _playVideo("#initial-screen video"); 60 + videoHelper.play("#initial-screen video");
352 } else { 61 } else {
353 $("#initial-screen").hide(); 62 $("#initial-screen").hide();
354 - _pauseVideo("#initial-screen video"); 63 + videoHelper.pause("#initial-screen video");
355 } 64 }
356 } 65 }
357 66
358 - function _showConfigurationScreen(toShow) { 67 + function _showApprovalScreen(toShow, parameterJSON) {
359 if (toShow) { 68 if (toShow) {
360 - $("#configuration-screen").show();  
361 - _playVideo("#ref-video-container video"); 69 + $("#render-button-container .btn").hide();
  70 + $("#approval-button").show();
  71 + $("#approval-msg").show();
  72 + renderSign.showRenderedAvatar(parameterJSON);
362 } else { 73 } else {
363 - $("#configuration-screen").hide();  
364 - _pauseVideo("#ref-video-container video"); 74 + $("#approval-button").hide();
  75 + $("#approval-msg").hide();
365 } 76 }
366 } 77 }
367 -  
368 - function _showRenderScreen(toShow) {  
369 - if (toShow) {  
370 - $("#render-screen").fadeIn(300);  
371 - _playVideo("#render-ref video");  
372 - _playVideo("#render-avatar video");  
373 - } else {  
374 - $("#render-screen").hide();  
375 - _pauseVideo("#render-ref video");  
376 - _pauseVideo("#render-avatar video");  
377 - }  
378 - }  
379 -  
380 - function _setupRenderScreen() {  
381 - _showConfigurationScreen(false);  
382 - _showRenderScreen(true);  
383 - $("#render-avatar").hide();  
384 - $("#render-loading").fadeIn(300);  
385 - $("#render-button-container .btn").hide();  
386 - $("#finish-button").addClass("disabled");  
387 - $("#finish-button").show();  
388 -  
389 - _submitParameterJSON(function() {  
390 - $("#render-loading").fadeOut(300);  
391 - $("#finish-button").removeClass("disabled");  
392 - _showRenderedAvatar(parsedParameterJSON);  
393 - });  
394 - }  
395 -  
396 - function _setupApprovalScreen(parameterJSON) {  
397 - $("#render-button-container .btn").hide();  
398 - $("#approval-button").show();  
399 - $("#approval-msg").show();  
400 -  
401 - _showRenderedAvatar(parameterJSON);  
402 - _showRenderScreen(true);  
403 - }  
404 78
405 function _submitAnswer(task, deferred, status) { 79 function _submitAnswer(task, deferred, status) {
406 var answer = _createAnswer(task, status); 80 var answer = _createAnswer(task, status);
@@ -409,44 +83,29 @@ @@ -409,44 +83,29 @@
409 } else { 83 } else {
410 _saveAnswer(task, deferred, answer); 84 _saveAnswer(task, deferred, answer);
411 } 85 }
412 - _showRenderScreen(false); 86 + renderSign.showRenderScreen(false);
413 $("#thanks-screen").show(); 87 $("#thanks-screen").show();
414 } 88 }
415 89
416 - function _clearGUI() {  
417 - articulation.clean();  
418 - $(".selection-panel-option").removeAttr('select');  
419 - $(".icon_container").removeAttr("select");  
420 - $(".icon_container[complete=true]").each(  
421 - function() {  
422 - _unfinishConfiguration($(this).attr("name"), $(this).attr(  
423 - "panel"));  
424 - });  
425 - }  
426 -  
427 function _setupMainScreen(task, deferred) { 90 function _setupMainScreen(task, deferred) {
428 var last_answer = task.info.last_answer; 91 var last_answer = task.info.last_answer;
429 var hasLastAnswer = typeof last_answer != "undefined"; 92 var hasLastAnswer = typeof last_answer != "undefined";
430 if (hasLastAnswer) { 93 if (hasLastAnswer) {
431 - _setupApprovalScreen(last_answer.parameter_json); 94 + _showApprovalScreen(true, last_answer.parameter_json);
432 } else { 95 } else {
  96 + _showApprovalScreen(false);
433 _showInitialScreen(true); 97 _showInitialScreen(true);
434 } 98 }
435 -  
436 $("#start-button").off("click").on("click", function() { 99 $("#start-button").off("click").on("click", function() {
437 _showInitialScreen(false); 100 _showInitialScreen(false);
438 - _showConfigurationScreen(true); 101 + configurationScreen.show(true);
439 }); 102 });
440 $("#ready-button").off("click").on("click", function() { 103 $("#ready-button").off("click").on("click", function() {
441 if ($(this).hasClass('disabled')) { 104 if ($(this).hasClass('disabled')) {
442 event.preventDefault(); 105 event.preventDefault();
443 return; 106 return;
444 } 107 }
445 - _setupRenderScreen();  
446 - });  
447 - $("#render-edit").off("click").on("click", function() {  
448 - _showRenderScreen(false);  
449 - _showConfigurationScreen(true); 108 + renderSign.submit(_parseTmpParameterJSON());
450 }); 109 });
451 $("#finish-button").off("click").on("click", function() { 110 $("#finish-button").off("click").on("click", function() {
452 if ($(this).hasClass('disabled')) { 111 if ($(this).hasClass('disabled')) {
@@ -461,9 +120,7 @@ @@ -461,9 +120,7 @@
461 } 120 }
462 121
463 function _setupGUI(task, deferred) { 122 function _setupGUI(task, deferred) {
464 - _clearGUI();  
465 - _setupConfigurationPanel();  
466 - _setupSelectionPanel(); 123 + configurationScreen.setup();
467 _setupMainScreen(task, deferred); 124 _setupMainScreen(task, deferred);
468 } 125 }
469 126
@@ -532,10 +189,12 @@ @@ -532,10 +189,12 @@
532 } 189 }
533 190
534 function _loadMainComponents() { 191 function _loadMainComponents() {
  192 + iconHelper.setup(base_url);
535 dynengine.load(); 193 dynengine.load();
536 dynworkflow.load(); 194 dynworkflow.load();
537 submitSign.setup(upload_signs_url); 195 submitSign.setup(upload_signs_url);
538 teachedSigns.setup(); 196 teachedSigns.setup();
  197 + renderSign.setup(api_url);
539 _setupLoginContainer(); 198 _setupLoginContainer();
540 } 199 }
541 200
@@ -572,45 +231,11 @@ @@ -572,45 +231,11 @@
572 _updateTempParameterJSON(mainConfig, subConfig, step, value); 231 _updateTempParameterJSON(mainConfig, subConfig, step, value);
573 } 232 }
574 233
575 - wikilibras.hideSelectionPanel = function() {  
576 - _hideSelectionPanel();  
577 - }  
578 -  
579 - wikilibras.selectAnOption = function(parentId, el) {  
580 - _selectAnOption(parentId, el);  
581 - }  
582 -  
583 - wikilibras.enableIconCheck = function(container, isHover) {  
584 - _enableIconCheck(container, isHover);  
585 - }  
586 -  
587 - wikilibras.canHover = function(container) {  
588 - return _canHover(container);  
589 - }  
590 -  
591 - wikilibras.enableIconHover = function(container, isHover) {  
592 - _enableIconHover(container, isHover);  
593 - }  
594 -  
595 - wikilibras.getRenderedAvatarUrl = function(userId, signName) {  
596 - return _getRenderedAvatarUrl(userId, signName);  
597 - }  
598 -  
599 wikilibras.showTeachContainer = function() { 234 wikilibras.showTeachContainer = function() {
600 $(".sub-main-container").hide(); 235 $(".sub-main-container").hide();
601 $("#teach-container").show(); 236 $("#teach-container").show();
602 } 237 }
603 238
604 - wikilibras.showSubmitSignContainer = function() {  
605 - $(".sub-main-container").hide();  
606 - $("#submit-sign-container").show();  
607 - }  
608 -  
609 - wikilibras.showTeachedSignsContainer = function() {  
610 - $(".sub-main-container").hide();  
611 - $("#teached-signs-container").show();  
612 - }  
613 -  
614 wikilibras.showTutorialContainer = function() { 239 wikilibras.showTutorialContainer = function() {
615 $(".sub-main-container").hide(); 240 $(".sub-main-container").hide();
616 $("#tutorial-container").show(); 241 $("#tutorial-container").show();
view/template.html
@@ -23,9 +23,9 @@ @@ -23,9 +23,9 @@
23 <li><a href="javascript:void(0);" 23 <li><a href="javascript:void(0);"
24 onclick="wikilibras.showTeachContainer()">Ensinar</a></li> 24 onclick="wikilibras.showTeachContainer()">Ensinar</a></li>
25 <li><a href="javascript:void(0);" 25 <li><a href="javascript:void(0);"
26 - onclick="wikilibras.showSubmitSignContainer()">Enviar sinal</a></li> 26 + onclick="submitSign.show()">Enviar sinal</a></li>
27 <li><a href="javascript:void(0);" 27 <li><a href="javascript:void(0);"
28 - onclick="wikilibras.showTeachedSignsContainer()">Sinais 28 + onclick="teachedSigns.show()">Sinais
29 ensinados</a></li> 29 ensinados</a></li>
30 <li><a href="javascript:void(0);" 30 <li><a href="javascript:void(0);"
31 onclick="wikilibras.showTutorialContainer()">Tutorial</a></li> 31 onclick="wikilibras.showTutorialContainer()">Tutorial</a></li>
@@ -76,21 +76,21 @@ @@ -76,21 +76,21 @@
76 <img id="maximize-icon" src="{{ server }}/img/maximize-icon.png"></img> 76 <img id="maximize-icon" src="{{ server }}/img/maximize-icon.png"></img>
77 </div> 77 </div>
78 </div> 78 </div>
79 - <div id="configuration-panel" class="col-sm-8">  
80 - <div class="icon_container config-panel-option" name="facial" 79 + <div id="configuration-menu" class="col-sm-8">
  80 + <div class="icon_container config-menu-option" name="facial"
81 panel="facial"> 81 panel="facial">
82 <img src="{{ server }}/img/facial-icon.png"</img> <span 82 <img src="{{ server }}/img/facial-icon.png"</img> <span
83 - class="configuration-panel-label">Expressão</span> 83 + class="configuration-menu-label">Expressão</span>
84 </div> 84 </div>
85 - <div class="icon_container config-panel-option" name="right-hand" 85 + <div class="icon_container config-menu-option" name="right-hand"
86 panel="right-hand"> 86 panel="right-hand">
87 <img src="{{ server }}/img/right-hand-icon.png"></img> <span 87 <img src="{{ server }}/img/right-hand-icon.png"></img> <span
88 - class="configuration-panel-label">Mão direita</span> 88 + class="configuration-menu-label">Mão direita</span>
89 </div> 89 </div>
90 - <div class="icon_container config-panel-option" name="left-hand" 90 + <div class="icon_container config-menu-option" name="left-hand"
91 panel="left-hand"> 91 panel="left-hand">
92 <img src="{{ server }}/img/left-hand-icon.png"></img> <span 92 <img src="{{ server }}/img/left-hand-icon.png"></img> <span
93 - class="configuration-panel-label">Mão esquerda</span> 93 + class="configuration-menu-label">Mão esquerda</span>
94 </div> 94 </div>
95 </div> 95 </div>
96 </div> 96 </div>
@@ -98,38 +98,38 @@ @@ -98,38 +98,38 @@
98 class="col-sm-7 avatar-container-zoom-out"> 98 class="col-sm-7 avatar-container-zoom-out">
99 <div id="facial-edit" class="edit-container"> 99 <div id="facial-edit" class="edit-container">
100 <img class="check-icon" src="{{ server }}/img/check-icon.png"></img> 100 <img class="check-icon" src="{{ server }}/img/check-icon.png"></img>
101 - <div class="icon_container config-panel-option" name="edit" 101 + <div class="icon_container config-menu-option" name="edit"
102 panel="facial"> 102 panel="facial">
103 <img src="{{ server }}/img/edit-icon.png"></img> 103 <img src="{{ server }}/img/edit-icon.png"></img>
104 </div> 104 </div>
105 </div> 105 </div>
106 <div id="right-hand-edit" class="edit-container"> 106 <div id="right-hand-edit" class="edit-container">
107 <img class="check-icon" src="{{ server }}/img/check-icon.png"></img> 107 <img class="check-icon" src="{{ server }}/img/check-icon.png"></img>
108 - <div class="icon_container config-panel-option" name="edit" 108 + <div class="icon_container config-menu-option" name="edit"
109 panel="right-hand"> 109 panel="right-hand">
110 <img src="{{ server }}/img/edit-icon.png"></img> 110 <img src="{{ server }}/img/edit-icon.png"></img>
111 </div> 111 </div>
112 </div> 112 </div>
113 <div id="left-hand-edit" class="edit-container"> 113 <div id="left-hand-edit" class="edit-container">
114 <img class="check-icon" src="{{ server }}/img/check-icon.png"></img> 114 <img class="check-icon" src="{{ server }}/img/check-icon.png"></img>
115 - <div class="icon_container config-panel-option" name="edit" 115 + <div class="icon_container config-menu-option" name="edit"
116 panel="left-hand"> 116 panel="left-hand">
117 <img src="{{ server }}/img/edit-icon.png"></img> 117 <img src="{{ server }}/img/edit-icon.png"></img>
118 </div> 118 </div>
119 </div> 119 </div>
120 <div id="avatar-default" class="avatar-img"> 120 <div id="avatar-default" class="avatar-img">
121 <div id="avatar-body-face" 121 <div id="avatar-body-face"
122 - class="icon_container config-panel-option" name="avatar-facial" 122 + class="icon_container config-menu-option" name="avatar-facial"
123 panel="facial"> 123 panel="facial">
124 <img src="{{ server }}/img/avatar-facial-icon.png"></img> 124 <img src="{{ server }}/img/avatar-facial-icon.png"></img>
125 </div> 125 </div>
126 <div id="avatar-body-right-hand" 126 <div id="avatar-body-right-hand"
127 - class="icon_container config-panel-option" 127 + class="icon_container config-menu-option"
128 name="avatar-right-hand" panel="right-hand"> 128 name="avatar-right-hand" panel="right-hand">
129 <img src="{{ server }}/img/avatar-right-hand-icon.png"></img> 129 <img src="{{ server }}/img/avatar-right-hand-icon.png"></img>
130 </div> 130 </div>
131 <div id="avatar-body-left-hand" 131 <div id="avatar-body-left-hand"
132 - class="icon_container config-panel-option" 132 + class="icon_container config-menu-option"
133 name="avatar-left-hand" panel="left-hand"> 133 name="avatar-left-hand" panel="left-hand">
134 <img src="{{ server }}/img/avatar-left-hand-icon.png"></img> 134 <img src="{{ server }}/img/avatar-left-hand-icon.png"></img>
135 </div> 135 </div>
@@ -328,23 +328,33 @@ @@ -328,23 +328,33 @@
328 </div> 328 </div>
329 </div> 329 </div>
330 330
331 -<script src="{{ server }}/assets/js/jquery.scrollTo.js"></script>  
332 -<script src="{{ server }}/assets/js/js.cookie.js"></script>  
333 -<script src="{{ server }}/assets/js/jquery.ui.widget.js"></script>  
334 -<script src="{{ server }}/assets/js/jquery.iframe-transport.js"></script>  
335 -<script src="{{ server }}/assets/js/jquery.fileupload.js"></script> 331 +<!-- External Libs -->
  332 +<script src="{{ server }}/assets/js/external-libs/jquery.scrollTo.js"></script>
  333 +<script src="{{ server }}/assets/js/external-libs/js.cookie.js"></script>
  334 +<script src="{{ server }}/assets/js/external-libs/jquery.ui.widget.js"></script>
  335 +<script src="{{ server }}/assets/js/external-libs/jquery.iframe-transport.js"></script>
  336 +<script src="{{ server }}/assets/js/external-libs/jquery.fileupload.js"></script>
  337 +
  338 +<!-- Selection Panel -->
  339 +<script src="{{ server }}/assets/js/selection-panel/facial.js"></script>
  340 +<script src="{{ server }}/assets/js/selection-panel/movement.js"></script>
  341 +<script src="{{ server }}/assets/js/selection-panel/articulation.js"></script>
  342 +<script src="{{ server }}/assets/js/selection-panel/configuration.js"></script>
  343 +<script src="{{ server }}/assets/js/selection-panel/orientation.js"></script>
  344 +<script src="{{ server }}/assets/js/selection-panel/default-configuration-handler.js"></script>
  345 +<script src="{{ server }}/assets/js/selection-panel/dynamic-loading-engine.js"></script>
  346 +<script src="{{ server }}/assets/js/selection-panel/dynamic-selection-workflow.js"></script>
  347 +<script src="{{ server }}/assets/js/selection-panel/selection-panel.js"></script>
  348 +
  349 +<!-- Helpers -->
  350 +<script src="{{ server }}/assets/js/helpers/video-helper.js"></script>
  351 +<script src="{{ server }}/assets/js/helpers/icon-helper.js"></script>
  352 +<script src="{{ server }}/assets/js/helpers/tmpJSONParser.js"></script>
336 353
337 <script src="{{ server }}/assets/js/teached-signs.js"></script> 354 <script src="{{ server }}/assets/js/teached-signs.js"></script>
338 <script src="{{ server }}/assets/js/submit-sign.js"></script> 355 <script src="{{ server }}/assets/js/submit-sign.js"></script>
339 -<script src="{{ server }}/assets/js/facial.js"></script>  
340 -<script src="{{ server }}/assets/js/movement.js"></script>  
341 -<script src="{{ server }}/assets/js/articulation.js"></script>  
342 -<script src="{{ server }}/assets/js/configuration.js"></script>  
343 -<script src="{{ server }}/assets/js/orientation.js"></script>  
344 -<script src="{{ server }}/assets/js/defaultConfigurationHandler.js"></script>  
345 -<script src="{{ server }}/assets/js/dynamic-loading-engine.js"></script>  
346 -<script src="{{ server }}/assets/js/dynamic-selection-workflow.js"></script>  
347 -<script src="{{ server }}/assets/js/tmpJSONParser.js"></script> 356 +<script src="{{ server }}/assets/js/configuration-screen.js"></script>
  357 +<script src="{{ server }}/assets/js/render-sign.js"></script>
348 <script src="{{ server }}/assets/js/wikilibras.js"></script> 358 <script src="{{ server }}/assets/js/wikilibras.js"></script>
349 359
350 <script type="text/javascript"> 360 <script type="text/javascript">