summaryrefslogtreecommitdiff
path: root/horizon
diff options
context:
space:
mode:
Diffstat (limited to 'horizon')
-rw-r--r--horizon/static/framework/widgets/load-edit/load-edit.directive.js51
-rw-r--r--horizon/static/framework/widgets/load-edit/load-edit.directive.spec.js15
-rw-r--r--horizon/static/framework/widgets/load-edit/load-edit.html38
3 files changed, 60 insertions, 44 deletions
diff --git a/horizon/static/framework/widgets/load-edit/load-edit.directive.js b/horizon/static/framework/widgets/load-edit/load-edit.directive.js
index 620dcbf35..902c11f1e 100644
--- a/horizon/static/framework/widgets/load-edit/load-edit.directive.js
+++ b/horizon/static/framework/widgets/load-edit/load-edit.directive.js
@@ -18,15 +18,18 @@
/**
* @ngdoc directive
- * @name horizon.framework.widgets:loadEdit
+ * @name horizon.framework.widgets:load-edit
* @scope
* @element
* @description
- * The 'loadEdit' directive supports and validates size of the script entered
+ * The 'load-edit' directive supports and validates size of the text entered
*
- * @param {object} config
- * @param {object} userInput
+ * @param {object} title
+ * @param {object} model
+ * @param {object} maxBytes
* @param {object} key
+ * @param {object} required
+ * @param {object} rows
*
* See configuration.html for example usage.
*/
@@ -44,9 +47,12 @@
var directive = {
restrict: 'E',
scope: {
- config: '=',
- userInput: '=',
- key: '@'
+ title: '@',
+ model: '=',
+ maxBytes: '@',
+ key: '@',
+ required: '=',
+ rows: '@'
},
link: link,
templateUrl: basePath + 'load-edit.html'
@@ -65,13 +71,13 @@
/* HTML5 file API is supported by IE10+, Chrome, FireFox and Safari (on Mac).
*
* If HTML5 file API is not supported by user's browser, remove the option
- * to upload a script via file upload.
+ * to upload a text via file upload.
*/
- $scope.config.fileApiSupported = !!FileReader;
+ $scope.fileApiSupported = !!FileReader;
/* Angular won't fire change events when the <textarea> is in invalid
* status, so we have to use jQuery/jqLite to watch for <textarea> changes.
- * If there are changes, we call the onScriptChange function to update the
+ * If there are changes, we call the onTextareaChange function to update the
* size stats and perform validation.
*/
textarea.on('input propertychange', onTextareaChange);
@@ -80,7 +86,7 @@
/* onchange event occurs when a control loses the input focus and
* its value has been modified since gaining focus so we need to clear
* up the fileInput.val() when the textContent field is modified as to
- * allow reloading the same script.
+ * allow reloading the same text.
*/
var textContentWatcher = $scope.$watch(function () {
return $scope.textContent;
@@ -100,12 +106,12 @@
* invalid status, so we have to use jQuery or jqLite to get the length
* of the <textarea> content.
*/
- $scope.scriptLength = textarea.val().length;
- $scope.userInput[$scope.key] = $scope.textContent;
- if ($scope.scriptLength > 0) {
- $scope.scriptModified = true;
+ $scope.textBytes = getStrByte(textarea.val());
+ $scope.model = $scope.textContent;
+ if ($scope.textBytes > 0) {
+ $scope.textModified = true;
} else {
- $scope.scriptModified = false;
+ $scope.textModified = false;
}
});
}
@@ -121,18 +127,25 @@
function updateTextArea(fileContents) {
$scope.textContent = fileContents;
- /* Once the DOM manipulation is done, update the scriptLength, so that
- * user knows the length of the script loaded into the <textarea>.
+ /* Once the DOM manipulation is done, update the textBytes, so that
+ * user knows the bytes of the text loaded into the <textarea>.
*/
$timeout(function () {
onTextareaChange();
- $scope.scriptModified = false;
+ $scope.textModified = false;
}, 250, false);
// Focus the <textarea> element after injecting the code into it.
textarea.focus();
}
+ /* The length property for string shows only number of character.
+ * If text includes multibyte string, it doesn't mean number of bytes.
+ * So to count bytes, convert to Blob object and get its size.
+ */
+ function getStrByte(str) {
+ return (new Blob([str], {type: "text/plain"})).size;
+ }
}
}
})();
diff --git a/horizon/static/framework/widgets/load-edit/load-edit.directive.spec.js b/horizon/static/framework/widgets/load-edit/load-edit.directive.spec.js
index c4f45047f..b08514040 100644
--- a/horizon/static/framework/widgets/load-edit/load-edit.directive.spec.js
+++ b/horizon/static/framework/widgets/load-edit/load-edit.directive.spec.js
@@ -37,9 +37,10 @@
$scope = $injector.get('$rootScope').$new();
$q = $injector.get('$q');
$compile = $injector.get('$compile');
- key = 'inputKey';
+ key = 'elementKey';
element = $compile(
- '<load-edit config="{}" user-input="{}" key="' + key + '"></load-edit>'
+ '<load-edit title="{}" model="{}" max-bytes="{}" key="' + key + '" ' +
+ 'required="true" rows="8"></load-edit>'
)($scope);
$scope.$apply();
}));
@@ -51,20 +52,20 @@
textarea = element.find('textarea');
});
- it('should set scriptModified to true when textarea has content', function () {
+ it('should set textModified to true when textarea has content', function () {
textarea.val('any value');
textarea.trigger('propertychange');
$scope.$apply();
- expect(element.isolateScope().scriptModified).toBe(true);
+ expect(element.isolateScope().textModified).toBe(true);
});
- it('should set scriptModified to false when textarea has no content', function () {
+ it('should set textModified to false when textarea has no content', function () {
textarea.val('');
textarea.trigger('propertychange');
$scope.$apply();
- expect(element.isolateScope().scriptModified).toBe(false);
+ expect(element.isolateScope().textModified).toBe(false);
});
it('should set userInput to the value of the textarea', function() {
@@ -72,7 +73,7 @@
textarea.trigger('input');
$scope.$apply();
- expect(element.isolateScope().userInput[key]).toBe('user input');
+ expect(element.isolateScope().model).toBe('user input');
});
});
diff --git a/horizon/static/framework/widgets/load-edit/load-edit.html b/horizon/static/framework/widgets/load-edit/load-edit.html
index 74f88da90..4fe2cf8f7 100644
--- a/horizon/static/framework/widgets/load-edit/load-edit.html
+++ b/horizon/static/framework/widgets/load-edit/load-edit.html
@@ -1,30 +1,32 @@
-<div class="form-group" ng-class="{ 'has-error': scriptLength >= config.MAX_SCRIPT_SIZE }">
- <label for="customization-script" class="control-label">
- <span translate>Customization Script</span>
- <span ng-show="scriptModified"
+<div class="form-group" ng-show="fileApiSupported">
+ <label for="load-{$ ::key $}" translate>Load {$ ::title $} from a file</label>
+ <input id="load-{$ ::key $}" type="file">
+</div>
+
+<div class="form-group" ng-class="{ 'has-error': textBytes >= maxBytes }">
+ <label for="{$ ::key $}" class="control-label">
+ <span>{$ ::title $}</span>
+ <span class="hz-icon-required fa fa-asterisk" ng-if="required"></span>
+ <span ng-show="textModified"
translate>
(Modified)</span>
</label>
- <span class="pull-right" ng-class="{ 'text-danger': scriptLength >= config.MAX_SCRIPT_SIZE }">
+ <span class="pull-right" ng-class="{ 'text-danger': textBytes >= maxBytes }">
<span translate translate-comment="Strings between {$ and $} should be left untranslated.">
- Script size: {$ (scriptLength || 0) | bytes $} of {$ config.MAX_SCRIPT_SIZE | bytes $}
+ Content size: {$ (textBytes || 0) | bytes $} of {$ ::maxBytes | bytes $}
</span>
</span>
<textarea class="form-control"
- rows="8"
- id="customization-script"
- name="customization-script"
- ng-maxlength="config.MAX_SCRIPT_SIZE"
- ng-model="textContent">
+ id="{$ ::key $}"
+ name="{$ ::key $}"
+ ng-maxlength="::maxBytes"
+ ng-model="textContent"
+ ng-required="required"
+ rows="{$ ::rows $}">
</textarea>
<span class="help-block"
- ng-show="scriptLength >= config.MAX_SCRIPT_SIZE"
+ ng-show="textBytes >= maxBytes"
translate>
- The script is larger than the maximum size
+ The content is larger than the maximum byte size
</span>
</div>
-
-<div class="form-group" ng-show="config.fileApiSupported">
- <label for="load-script" translate>Load script from a file</label>
- <input id="load-script" type="file">
-</div>