| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /** |
| * A service for maintaining form-related metadata and linking that data to |
| * corresponding controllers and templates. |
| */ |
| angular.module('form').provider('formService', function formServiceProvider() { |
| |
| /** |
| * Reference to the provider itself. |
| * |
| * @type formServiceProvider |
| */ |
| var provider = this; |
| |
| /** |
| * Map of all registered field type definitions by name. |
| * |
| * @type Object.<String, FieldType> |
| */ |
| this.fieldTypes = { |
| |
| /** |
| * Text field type. |
| * |
| * @see {@link Field.Type.TEXT} |
| * @type FieldType |
| */ |
| 'TEXT' : { |
| module : 'form', |
| controller : 'textFieldController', |
| templateUrl : 'app/form/templates/textField.html' |
| }, |
| |
| /** |
| * Email address field type. |
| * |
| * @see {@link Field.Type.EMAIL} |
| * @type FieldType |
| */ |
| 'EMAIL' : { |
| templateUrl : 'app/form/templates/emailField.html' |
| }, |
| |
| /** |
| * Numeric field type. |
| * |
| * @see {@link Field.Type.NUMERIC} |
| * @type FieldType |
| */ |
| 'NUMERIC' : { |
| module : 'form', |
| controller : 'numberFieldController', |
| templateUrl : 'app/form/templates/numberField.html' |
| }, |
| |
| /** |
| * Boolean field type. |
| * |
| * @see {@link Field.Type.BOOLEAN} |
| * @type FieldType |
| */ |
| 'BOOLEAN' : { |
| module : 'form', |
| controller : 'checkboxFieldController', |
| templateUrl : 'app/form/templates/checkboxField.html' |
| }, |
| |
| /** |
| * Username field type. Identical in principle to a text field, but may |
| * have different semantics. |
| * |
| * @see {@link Field.Type.USERNAME} |
| * @type FieldType |
| */ |
| 'USERNAME' : { |
| templateUrl : 'app/form/templates/textField.html' |
| }, |
| |
| /** |
| * Password field type. Similar to a text field, but the contents of |
| * the field are masked. |
| * |
| * @see {@link Field.Type.PASSWORD} |
| * @type FieldType |
| */ |
| 'PASSWORD' : { |
| module : 'form', |
| controller : 'passwordFieldController', |
| templateUrl : 'app/form/templates/passwordField.html' |
| }, |
| |
| /** |
| * Enumerated field type. The user is presented a finite list of values |
| * to choose from. |
| * |
| * @see {@link Field.Type.ENUM} |
| * @type FieldType |
| */ |
| 'ENUM' : { |
| module : 'form', |
| controller : 'selectFieldController', |
| templateUrl : 'app/form/templates/selectField.html' |
| }, |
| |
| /** |
| * Multiline field type. The user may enter multiple lines of text. |
| * |
| * @see {@link Field.Type.MULTILINE} |
| * @type FieldType |
| */ |
| 'MULTILINE' : { |
| templateUrl : 'app/form/templates/textAreaField.html' |
| }, |
| |
| /** |
| * Field type which allows selection of languages. The languages |
| * displayed are the set of languages supported by the Guacamole web |
| * application. Legal values are valid language IDs, as dictated by |
| * the filenames of Guacamole's available translations. |
| * |
| * @see {@link Field.Type.LANGUAGE} |
| * @type FieldType |
| */ |
| 'LANGUAGE' : { |
| module : 'form', |
| controller : 'languageFieldController', |
| templateUrl : 'app/form/templates/languageField.html' |
| }, |
| |
| /** |
| * Field type which allows selection of time zones. |
| * |
| * @see {@link Field.Type.TIMEZONE} |
| * @type FieldType |
| */ |
| 'TIMEZONE' : { |
| module : 'form', |
| controller : 'timeZoneFieldController', |
| templateUrl : 'app/form/templates/timeZoneField.html' |
| }, |
| |
| /** |
| * Field type which allows selection of individual dates. |
| * |
| * @see {@link Field.Type.DATE} |
| * @type FieldType |
| */ |
| 'DATE' : { |
| module : 'form', |
| controller : 'dateFieldController', |
| templateUrl : 'app/form/templates/dateField.html' |
| }, |
| |
| /** |
| * Field type which allows selection of times of day. |
| * |
| * @see {@link Field.Type.TIME} |
| * @type FieldType |
| */ |
| 'TIME' : { |
| module : 'form', |
| controller : 'timeFieldController', |
| templateUrl : 'app/form/templates/timeField.html' |
| }, |
| |
| /** |
| * Field type which allows selection of color schemes accepted by the |
| * Guacamole server terminal emulator and protocols which leverage it. |
| * |
| * @see {@link Field.Type.TERMINAL_COLOR_SCHEME} |
| * @type FieldType |
| */ |
| 'TERMINAL_COLOR_SCHEME' : { |
| module : 'form', |
| controller : 'terminalColorSchemeFieldController', |
| templateUrl : 'app/form/templates/terminalColorSchemeField.html' |
| } |
| |
| }; |
| |
| /** |
| * Registers a new field type under the given name. |
| * |
| * @param {String} fieldTypeName |
| * The name which uniquely identifies the field type being registered. |
| * |
| * @param {FieldType} fieldType |
| * The field type definition to associate with the given name. |
| */ |
| this.registerFieldType = function registerFieldType(fieldTypeName, fieldType) { |
| |
| // Store field type |
| provider.fieldTypes[fieldTypeName] = fieldType; |
| |
| }; |
| |
| // Factory method required by provider |
| this.$get = ['$injector', function formServiceFactory($injector) { |
| |
| // Required services |
| var $compile = $injector.get('$compile'); |
| var $q = $injector.get('$q'); |
| var $templateRequest = $injector.get('$templateRequest'); |
| |
| /** |
| * Map of module name to the injector instance created for that module. |
| * |
| * @type {Object.<String, injector>} |
| */ |
| var injectors = {}; |
| |
| var service = {}; |
| |
| service.fieldTypes = provider.fieldTypes; |
| |
| /** |
| * Given the name of a module, returns an injector instance which |
| * injects dependencies within that module. A new injector may be |
| * created and initialized if no such injector has yet been requested. |
| * If the injector available to formService already includes the |
| * requested module, that injector will simply be returned. |
| * |
| * @param {String} module |
| * The name of the module to produce an injector for. |
| * |
| * @returns {injector} |
| * An injector instance which injects dependencies for the given |
| * module. |
| */ |
| var getInjector = function getInjector(module) { |
| |
| // Use the formService's injector if possible |
| if ($injector.modules[module]) |
| return $injector; |
| |
| // If the formService's injector does not include the requested |
| // module, create the necessary injector, reusing that injector for |
| // future calls |
| injectors[module] = injectors[module] || angular.injector(['ng', module]); |
| return injectors[module]; |
| |
| }; |
| |
| /** |
| * Compiles and links the field associated with the given name to the given |
| * scope, producing a distinct and independent DOM Element which functions |
| * as an instance of that field. The scope object provided must include at |
| * least the following properties: |
| * |
| * namespace: |
| * A String which defines the unique namespace associated the |
| * translation strings used by the form using a field of this type. |
| * |
| * fieldId: |
| * A String value which is reasonably likely to be unique and may |
| * be used to associate the main element of the field with its |
| * label. |
| * |
| * field: |
| * The Field object that is being rendered, representing a field of |
| * this type. |
| * |
| * model: |
| * The current String value of the field, if any. |
| * |
| * @param {Element} fieldContainer |
| * The DOM Element whose contents should be replaced with the |
| * compiled field template. |
| * |
| * @param {String} fieldTypeName |
| * The name of the field type defining the nature of the element to be |
| * created. |
| * |
| * @param {Object} scope |
| * The scope to which the new element will be linked. |
| * |
| * @return {Promise.<Element>} |
| * A Promise which resolves to the compiled Element. If an error occurs |
| * while retrieving the field type, this Promise will be rejected. |
| */ |
| service.insertFieldElement = function insertFieldElement(fieldContainer, |
| fieldTypeName, scope) { |
| |
| // Ensure field type is defined |
| var fieldType = provider.fieldTypes[fieldTypeName]; |
| if (!fieldType) |
| return $q.reject(); |
| |
| var templateRequest; |
| |
| // Use raw HTML template if provided |
| if (fieldType.template) { |
| var deferredTemplate = $q.defer(); |
| deferredTemplate.resolve(fieldType.template); |
| templateRequest = deferredTemplate.promise; |
| } |
| |
| // If no raw HTML template is provided, retrieve template from URL |
| else if (fieldType.templateUrl) |
| templateRequest = $templateRequest(fieldType.templateUrl); |
| |
| // Otherwise, use empty template |
| else { |
| var emptyTemplate= $q.defer(); |
| emptyTemplate.resolve(''); |
| templateRequest = emptyTemplate.promise; |
| } |
| |
| // Defer compilation of template pending successful retrieval |
| var compiledTemplate = $q.defer(); |
| |
| // Resolve with compiled HTML upon success |
| templateRequest.then(function templateRetrieved(html) { |
| |
| // Insert template into DOM |
| fieldContainer.innerHTML = html; |
| |
| // Populate scope using defined controller |
| if (fieldType.module && fieldType.controller) { |
| var $controller = getInjector(fieldType.module).get('$controller'); |
| $controller(fieldType.controller, { |
| '$scope' : scope, |
| '$element' : angular.element(fieldContainer.childNodes) |
| }); |
| } |
| |
| // Compile DOM with populated scope |
| compiledTemplate.resolve($compile(fieldContainer.childNodes)(scope)); |
| |
| }) |
| |
| // Reject on failure |
| ['catch'](function templateError() { |
| compiledTemplate.reject(); |
| }); |
| |
| // Return promise which resolves to the compiled template |
| return compiledTemplate.promise; |
| |
| }; |
| |
| return service; |
| |
| }]; |
| |
| }); |