diff options
Diffstat (limited to 'src/service/formFactory.js')
| -rw-r--r-- | src/service/formFactory.js | 414 | 
1 files changed, 0 insertions, 414 deletions
| diff --git a/src/service/formFactory.js b/src/service/formFactory.js deleted file mode 100644 index b051f7b9..00000000 --- a/src/service/formFactory.js +++ /dev/null @@ -1,414 +0,0 @@ -'use strict'; - -/** - * @ngdoc object - * @name angular.module.ng.$formFactory - * - * @description - * Use `$formFactory` to create a new instance of a {@link angular.module.ng.$formFactory.Form Form} - * controller or to find the nearest form instance for a given DOM element. - * - * The form instance is a collection of widgets, and is responsible for life cycle and validation - * of widget. - * - * Keep in mind that both form and widget instances are {@link api/angular.module.ng.$rootScope.Scope scopes}. - * - * @param {Form=} parentForm The form which should be the parent form of the new form controller. - *   If none specified default to the `rootForm`. - * @returns {Form} A new {@link angular.module.ng.$formFactory.Form Form} instance. - * - * @example - * - * This example shows how one could write a widget which would enable data-binding on - * `contenteditable` feature of HTML. - * -    <doc:example module="formModule"> -      <doc:source> -        <script> -          function EditorCntl($scope) { -            $scope.htmlContent = '<b>Hello</b> <i>World</i>!'; -          } - -          HTMLEditorWidget.$inject = ['$scope', '$element', '$sanitize']; -          function HTMLEditorWidget(scope, element, $sanitize) { -            scope.$parseModel = function() { -              // need to protect for script injection -              try { -                scope.$viewValue = $sanitize( -                  scope.$modelValue || ''); -                if (this.$error.HTML) { -                  // we were invalid, but now we are OK. -                  scope.$emit('$valid', 'HTML'); -                } -              } catch (e) { -                // if HTML not parsable invalidate form. -                scope.$emit('$invalid', 'HTML'); -              } -            } - -            scope.$render = function() { -              element.html(this.$viewValue); -            } - -            element.bind('keyup', function() { -              scope.$apply(function() { -                scope.$emit('$viewChange', element.html()); -              }); -            }); -          } - -       angular.module('formModule', [], function($compileProvider){ -         $compileProvider.directive('ngHtmlEditorModel', function ($formFactory) { -           return function(scope, element, attr) { -             var form = $formFactory.forElement(element), -                 widget; -             element.attr('contentEditable', true); -             widget = form.$createWidget({ -               scope: scope, -               model: attr.ngHtmlEditorModel, -               controller: HTMLEditorWidget, -               controllerArgs: {$element: element}}); -             // if the element is destroyed, then we need to -             // notify the form. -             element.bind('$destroy', function() { -               widget.$destroy(); -             }); -           }; -         }); -       }); -     </script> -     <form name='editorForm' ng:controller="EditorCntl"> -       <div ng:html-editor-model="htmlContent"></div> -       <hr/> -       HTML: <br/> -       <textarea ng:model="htmlContent" cols="80"></textarea> -       <hr/> -       <pre>editorForm = {{editorForm|json}}</pre> -     </form> -   </doc:source> -   <doc:scenario> -     it('should enter invalid HTML', function() { -       expect(element('form[name=editorForm]').prop('className')).toMatch(/ng-valid/); -       input('htmlContent').enter('<'); -       expect(element('form[name=editorForm]').prop('className')).toMatch(/ng-invalid/); -     }); -   </doc:scenario> - </doc:example> - */ - -/** - * @ngdoc object - * @name angular.module.ng.$formFactory.Form - * @description - * The `Form` is a controller which keeps track of the validity of the widgets contained within it. - */ - -function $FormFactoryProvider() { -  var $parse; -  this.$get = ['$rootScope', '$parse', '$controller', -      function($rootScope, $parse_, $controller) { -    $parse = $parse_; -    /** -     * @ngdoc proprety -     * @name rootForm -     * @propertyOf angular.module.ng.$formFactory -     * @description -     * Static property on `$formFactory` -     * -     * Each application ({@link guide/dev_guide.scopes.internals root scope}) gets a root form which -     * is the top-level parent of all forms. -     */ -    formFactory.rootForm = formFactory($rootScope); - - -    /** -     * @ngdoc method -     * @name forElement -     * @methodOf angular.module.ng.$formFactory -     * @description -     * Static method on `$formFactory` service. -     * -     * Retrieve the closest form for a given element or defaults to the `root` form. Used by the -     * {@link angular.module.ng.$compileProvider.directive.form form} element. -     * @param {Element} element The element where the search for form should initiate. -     */ -    formFactory.forElement = function(element) { -      return element.inheritedData('$form') || formFactory.rootForm; -    }; -    return formFactory; - -    function formFactory(parent) { -      var scope = (parent || formFactory.rootForm).$new(); -      $controller(FormController, {$scope: scope}); -      return scope; -    } - -  }]; - -  function propertiesUpdate(widget) { -    widget.$valid = !(widget.$invalid = -      !(widget.$readonly || widget.$disabled || equals(widget.$error, {}))); -  } - -  /** -   * @ngdoc property -   * @name $error -   * @propertyOf angular.module.ng.$formFactory.Form -   * @description -   * Property of the form and widget instance. -   * -   * Summary of all of the errors on the page. If a widget emits `$invalid` with `REQUIRED` key, -   * then the `$error` object will have a `REQUIRED` key with an array of widgets which have -   * emitted this key. `form.$error.REQUIRED == [ widget ]`. -   */ - -  /** -   * @ngdoc property -   * @name $invalid -   * @propertyOf angular.module.ng.$formFactory.Form -   * @description -   * Property of the form and widget instance. -   * -   * True if any of the widgets of the form are invalid. -   */ - -  /** -   * @ngdoc property -   * @name $valid -   * @propertyOf angular.module.ng.$formFactory.Form -   * @description -   * Property of the form and widget instance. -   * -   * True if all of the widgets of the form are valid. -   */ - -  /** -   * @ngdoc event -   * @name angular.module.ng.$formFactory.Form#$valid -   * @eventOf angular.module.ng.$formFactory.Form -   * @eventType listen on form -   * @description -   * Upon receiving the `$valid` event from the widget update the `$error`, `$valid` and `$invalid` -   * properties of both the widget as well as the from. -   * -   * @param {string} validationKey The validation key to be used when updating the `$error` object. -   *    The validation key is what will allow the template to bind to a specific validation error -   *    such as `<div ng:show="form.$error.KEY">error for key</div>`. -   */ - -  /** -   * @ngdoc event -   * @name angular.module.ng.$formFactory.Form#$invalid -   * @eventOf angular.module.ng.$formFactory.Form -   * @eventType listen on form -   * @description -   * Upon receiving the `$invalid` event from the widget update the `$error`, `$valid` and `$invalid` -   * properties of both the widget as well as the from. -   * -   * @param {string} validationKey The validation key to be used when updating the `$error` object. -   *    The validation key is what will allow the template to bind to a specific validation error -   *    such as `<div ng:show="form.$error.KEY">error for key</div>`. -   */ - -  /** -   * @ngdoc event -   * @name angular.module.ng.$formFactory.Form#$validate -   * @eventOf angular.module.ng.$formFactory.Form -   * @eventType emit on widget -   * @description -   * Emit the `$validate` event on the widget, giving a widget a chance to emit a -   * `$valid` / `$invalid` event base on its state. The `$validate` event is triggered when the -   * model or the view changes. -   */ - -  /** -   * @ngdoc event -   * @name angular.module.ng.$formFactory.Form#$viewChange -   * @eventOf angular.module.ng.$formFactory.Form -   * @eventType listen on widget -   * @description -   * A widget is responsible for emitting this event whenever the view changes do to user interaction. -   * The event takes a `$viewValue` parameter, which is the new value of the view. This -   * event triggers a call to `$parseView()` as well as `$validate` event on widget. -   * -   * @param {*} viewValue The new value for the view which will be assigned to `widget.$viewValue`. -   */ - -  FormController.$inject = ['$scope', '$injector']; -  function FormController($scope, $injector) { -    this.$injector = $injector; - -    var form = this.form = $scope, -        $error = form.$error = {}; - -    form.$on('$destroy', function(event){ -      var widget = event.targetScope; -      if (widget.$widgetId) { -        delete form[widget.$widgetId]; -      } -      forEach($error, removeWidget, widget); -    }); - -    form.$on('$valid', function(event, error){ -      var widget = event.targetScope; -      delete widget.$error[error]; -      propertiesUpdate(widget); -      removeWidget($error[error], error, widget); -    }); - -    form.$on('$invalid', function(event, error){ -      var widget = event.targetScope; -      addWidget(error, widget); -      widget.$error[error] = true; -      propertiesUpdate(widget); -    }); - -    propertiesUpdate(form); -    form.$createWidget = bind(this, this.$createWidget); - -    function removeWidget(queue, errorKey, widget) { -      if (queue) { -        widget = widget || this; // so that we can be used in forEach; -        for (var i = 0, length = queue.length; i < length; i++) { -          if (queue[i] === widget) { -            queue.splice(i, 1); -            if (!queue.length) { -              delete $error[errorKey]; -            } -          } -        } -        propertiesUpdate(form); -      } -    } - -    function addWidget(errorKey, widget) { -      var queue = $error[errorKey]; -      if (queue) { -        for (var i = 0, length = queue.length; i < length; i++) { -          if (queue[i] === widget) { -            return; -          } -        } -      } else { -        $error[errorKey] = queue = []; -      } -      queue.push(widget); -      propertiesUpdate(form); -    } -  } - - -  /** -   * @ngdoc method -   * @name $createWidget -   * @methodOf angular.module.ng.$formFactory.Form -   * @description -   * -   * Use form's `$createWidget` instance method to create new widgets. The widgets can be created -   * using an alias which makes the accessible from the form and available for data-binding, -   * useful for displaying validation error messages. -   * -   * The creation of a widget sets up: -   * -   *   - `$watch` of `expression` on `model` scope. This code path syncs the model to the view. -   *      The `$watch` listener will: -   * -   *     - assign the new model value of `expression` to `widget.$modelValue`. -   *     - call `widget.$parseModel` method if present. The `$parseModel` is responsible for copying -   *       the `widget.$modelValue` to `widget.$viewValue` and optionally converting the data. -   *       (For example to convert a number into string) -   *     - emits `$validate` event on widget giving a widget a chance to emit `$valid` / `$invalid` -   *       event. -   *     - call `widget.$render()` method on widget. The `$render` method is responsible for -   *       reading the `widget.$viewValue` and updating the DOM. -   * -   *   - Listen on `$viewChange` event from the `widget`. This code path syncs the view to the model. -   *     The `$viewChange` listener will: -   * -   *     - assign the value to `widget.$viewValue`. -   *     - call `widget.$parseView` method if present. The `$parseView` is responsible for copying -   *       the `widget.$viewValue` to `widget.$modelValue` and optionally converting the data. -   *       (For example to convert a string into number) -   *     - emits `$validate` event on widget giving a widget a chance to emit `$valid` / `$invalid` -   *       event. -   *     - Assign the  `widget.$modelValue` to the `expression` on the `model` scope. -   * -   *   - Creates these set of properties on the `widget` which are updated as a response to the -   *     `$valid` / `$invalid` events: -   * -   *     - `$error` -  object - validation errors will be published as keys on this object. -   *       Data-binding to this property is useful for displaying the validation errors. -   *     - `$valid` - boolean - true if there are no validation errors -   *     - `$invalid` - boolean - opposite of `$valid`. -   * @param {Object} params Named parameters: -   * -   *   - `scope` - `{Scope}` -  The scope to which the model for this widget is attached. -   *   - `model` - `{string}` - The name of the model property on model scope. -   *   - `controller` - {WidgetController} - The controller constructor function. -   *      The controller constructor should create these instance methods. -   *     - `$parseView()`: optional method responsible for copying `$viewVale` to `$modelValue`. -   *         The method may fire `$valid`/`$invalid` events. -   *     - `$parseModel()`: optional method responsible for copying `$modelVale` to `$viewValue`. -   *         The method may fire `$valid`/`$invalid` events. -   *     - `$render()`: required method which needs to update the DOM of the widget to match the -   *         `$viewValue`. -   * -   *   - `controllerArgs` - `{Array}` (Optional) -  Any extra arguments will be curried to the -   *     WidgetController constructor. -   *   - `onChange` - `{(string|function())}` (Optional) - Expression to execute when user changes the -   *     value. -   *   - `alias` - `{string}` (Optional) - The name of the form property under which the widget -   *     instance should be published. The name should be unique for each form. -   * @returns {Widget} Instance of a widget scope. -   */ -  FormController.prototype.$createWidget = function(params) { -    var form = this.form, -        modelScope = params.scope, -        onChange = params.onChange, -        alias = params.alias, -        scopeGet = $parse(params.model), -        scopeSet = scopeGet.assign, -        widget = form.$new(); - -    this.$injector.instantiate(params.controller, extend({$scope: widget}, params.controllerArgs)); - -    if (!scopeSet) { -      throw Error("Expression '" + params.model + "' is not assignable!"); -    } - -    widget.$error = {}; -    // Set the state to something we know will change to get the process going. -    widget.$modelValue = Number.NaN; -    // watch for scope changes and update the view appropriately -    modelScope.$watch(scopeGet, function(value) { -      if (!equals(widget.$modelValue, value)) { -        widget.$modelValue = value; -        widget.$parseModel ? widget.$parseModel() : (widget.$viewValue = value); -        widget.$emit('$validate'); -        widget.$render && widget.$render(); -      } -    }); - -    widget.$on('$viewChange', function(event, viewValue){ -      if (!equals(widget.$viewValue, viewValue)) { -        widget.$viewValue = viewValue; -        widget.$parseView ? widget.$parseView() : (widget.$modelValue = widget.$viewValue); -        scopeSet(modelScope, widget.$modelValue); -        if (onChange) modelScope.$eval(onChange); -        widget.$emit('$validate'); -      } -    }); - -    propertiesUpdate(widget); - -    // assign the widgetModel to the form -    if (alias && !form.hasOwnProperty(alias)) { -      form[alias] = widget; -      widget.$widgetId = alias; -    } else { -      alias = null; -    } - -    return widget; -  }; -} | 
