<commit_before>/**
* DynamicForms - Build Forms in AngularJS From Nothing But JSON
* @version v0.0.2 - 2014-04-29
* @link http://bitbucket.org/danhunsaker/angular-dynamic-forms
* @license MIT, http://opensource.org/licenses/MIT
*/

/**
* Dynamically build an HTML form using a JSON object as a template.
*
* @todo Properly describe this directive.
* @param {Object} [template] - The form template itself, as an object.
* @param {string} [templateUrl] - The URL to retrieve the form template from; template overrides.
* @param {mixed} ngModel - An object in the current scope where the form data should be stored.
* @example <dynamic-form template-url="form-template.js" ng-model="formData"></dynamic-form>
*/
angular.module('dynform', [])
  .directive('dynamicForm', ['$q', '$parse', '$http', '$templateCache', '$compile', '$document', '$timeout', function ($q, $parse, $http, $templateCache, $compile, $document, $timeout) {
    var supported = {
        //  Text-based elements
        'text': {element: 'input', type: 'text', editable: true, textBased: true},
        'date': {element: 'input', type: 'date', editable: true, textBased: true},
        'datetime': {element: 'input', type: 'datetime', editable: true, textBased: true},
        'datetime-local': {element: 'input', type: 'datetime-local', editable: true, textBased: true},
        'email': {element: 'input', type: 'email', editable: true, textBased: true},
        'month': {element: 'input', type: 'month', editable: true, textBased: true},
        'number': {element: 'input', type: 'number', editable: true, textBased: true},
        'password': {element: 'input', type: 'password', editable: true, textBased: true},
        'search': {element: 'input', type: 'search', editable: true, textBased: true},
        'tel': {element: 'input', type: 'tel', editable: true, textBased: true},
        'textarea': {element: 'textarea', editable: true, textBased: true},
        'time': {element: 'input', type: 'time', editable: true, textBased: true},
        'url': {element: 'input', type: 'url', editable: true, textBased: true},
        'week': {element: 'input', type: 'week', editable: true, textBased: true},
        //  Specialized editables
        'checkbox': {element: 'input', type: 'checkbox', editable: true, textBased: false},
        'color': {element: 'input', type: 'color', editable: true, textBased: false},
        'file': {element: 'input', type: 'file', editable: true, textBased: false},
        'range': {element: 'input', type: 'range', editable: true, textBased: false},
        'select': {element: 'select', editable: true, textBased: false},
        //  Pseudo-non-editables (containers)
        'checklist': {element: 'div', editable: false, textBased: false},
        'fieldset': {element: 'fieldset', editable: false, textBased: false},
        'radio': {element: 'div', editable: false, textBased: false},
        //  Non-editables (mostly buttons)
        'button': {element: 'button', type: 'button', editable: false, textBased: false},
        'hidden': {element: 'input', type: 'hidden', editable: false, textBased: false},
        'image': {element: 'input', type: 'image', editable: false, textBased: false},
        'legend': {element: 'legend', editable: false, textBased: false},
        'reset': {element: 'button', type: 'reset', editable: false, textBased: false},
        'submit': {element: 'button', type: 'submit', editable: false, textBased: false}
      };
    
    return {
      restrict: 'E', // supports using directive as element only
      link: function ($scope, element, attrs) {
        //  Basic initialization
        var newElement = null,
          newChild = null,
          optGroups = {},
          cbAtt = '',
          foundOne = false,
          iterElem = element,
          model = null;
        
        //  Check that the required attributes are in place
        if (angular.isDefined(attrs.ngModel) && (angular.isDefined(attrs.template) || angular.isDefined(attrs.templateUrl)) && !element.hasClass('dynamic-form')) {
          model = $parse(attrs.ngModel)($scope);
          //  Grab the template. either from the template attribute, or from the URL in templateUrl
          (attrs.template ? $q.when($parse(attrs.template)($scope)) :
            $http.get(attrs.templateUrl, {cache: $templateCache}).then(function (result) {
              return result.data;
            })
          ).then(function (template) {
            var setProperty = function (obj, props, value, lastProp, buildParent) {
              props = props.split('.');
              lastProp = lastProp || props.pop();
              for (var i = 0; i < props.length; i++) {
                obj = obj[props[i]] = obj[props[i]] || {};
              }
              if (!buildParent)
                obj[lastProp] = value;
            },
            bracket = function (model, base) {
              props = model.split('.');
              return (base || props.shift()) + (props.length ? "['" + props.join("']['") + "']" : '');
            },
            buildFields = function (field, id) {
              if (!angular.isDefined(supported[field.type]) || supported[field.type] === false) {
                //  Unsupported.  Create SPAN with field.label as contents
                newElement = angular.element('<span></span>');
                if (angular.isDefined(field.label)) {angular.element(newElement).html(field.label);}
                angular.forEach(field, function (val, attr) {
                  if (["label", "type"].indexOf(attr) > -1) {return;}
                  newElement.attr(attr, val);
                });
                this.append(newElement);
                newElement = null;
              }
              else {
                //  Supported.  Create element (or container) according to type
                if (!angular.isDefined(field.model)) {
                  field.model = id;
                }
                
                newElement = angular.element($document[0].createElement(supported[field.type].element));
                if (angular.isDefined(supported[field.type].type)) {
                  newElement.attr('type', supported[field.type].type);
                }
                
                //  Editable fields (those that can feed models)
                if (angular.isDefined(supported[field.type].editable) && supported[field.type].editable) {
                  newElement.attr('name', bracket(field.model));
                  newElement.attr('ng-model', bracket(field.model, attrs.ngModel));
                  // Build parent in case of a nested model<commit_msg>Resolve GitHub Issue #29 (don't process keys added by Angular)<commit_after>/**
* DynamicForms - Build Forms in AngularJS From Nothing But JSON
* @version v0.0.2 - 2014-04-29
* @link http://bitbucket.org/danhunsaker/angular-dynamic-forms
* @license MIT, http://opensource.org/licenses/MIT
*/

/**
* Dynamically build an HTML form using a JSON object as a template.
*
* @todo Properly describe this directive.
* @param {Object} [template] - The form template itself, as an object.
* @param {string} [templateUrl] - The URL to retrieve the form template from; template overrides.
* @param {mixed} ngModel - An object in the current scope where the form data should be stored.
* @example <dynamic-form template-url="form-template.js" ng-model="formData"></dynamic-form>
*/
angular.module('dynform', [])
  .directive('dynamicForm', ['$q', '$parse', '$http', '$templateCache', '$compile', '$document', '$timeout', function ($q, $parse, $http, $templateCache, $compile, $document, $timeout) {
    var supported = {
        //  Text-based elements
        'text': {element: 'input', type: 'text', editable: true, textBased: true},
        'date': {element: 'input', type: 'date', editable: true, textBased: true},
        'datetime': {element: 'input', type: 'datetime', editable: true, textBased: true},
        'datetime-local': {element: 'input', type: 'datetime-local', editable: true, textBased: true},
        'email': {element: 'input', type: 'email', editable: true, textBased: true},
        'month': {element: 'input', type: 'month', editable: true, textBased: true},
        'number': {element: 'input', type: 'number', editable: true, textBased: true},
        'password': {element: 'input', type: 'password', editable: true, textBased: true},
        'search': {element: 'input', type: 'search', editable: true, textBased: true},
        'tel': {element: 'input', type: 'tel', editable: true, textBased: true},
        'textarea': {element: 'textarea', editable: true, textBased: true},
        'time': {element: 'input', type: 'time', editable: true, textBased: true},
        'url': {element: 'input', type: 'url', editable: true, textBased: true},
        'week': {element: 'input', type: 'week', editable: true, textBased: true},
        //  Specialized editables
        'checkbox': {element: 'input', type: 'checkbox', editable: true, textBased: false},
        'color': {element: 'input', type: 'color', editable: true, textBased: false},
        'file': {element: 'input', type: 'file', editable: true, textBased: false},
        'range': {element: 'input', type: 'range', editable: true, textBased: false},
        'select': {element: 'select', editable: true, textBased: false},
        //  Pseudo-non-editables (containers)
        'checklist': {element: 'div', editable: false, textBased: false},
        'fieldset': {element: 'fieldset', editable: false, textBased: false},
        'radio': {element: 'div', editable: false, textBased: false},
        //  Non-editables (mostly buttons)
        'button': {element: 'button', type: 'button', editable: false, textBased: false},
        'hidden': {element: 'input', type: 'hidden', editable: false, textBased: false},
        'image': {element: 'input', type: 'image', editable: false, textBased: false},
        'legend': {element: 'legend', editable: false, textBased: false},
        'reset': {element: 'button', type: 'reset', editable: false, textBased: false},
        'submit': {element: 'button', type: 'submit', editable: false, textBased: false}
      };
    
    return {
      restrict: 'E', // supports using directive as element only
      link: function ($scope, element, attrs) {
        //  Basic initialization
        var newElement = null,
          newChild = null,
          optGroups = {},
          cbAtt = '',
          foundOne = false,
          iterElem = element,
          model = null;
        
        //  Check that the required attributes are in place
        if (angular.isDefined(attrs.ngModel) && (angular.isDefined(attrs.template) || angular.isDefined(attrs.templateUrl)) && !element.hasClass('dynamic-form')) {
          model = $parse(attrs.ngModel)($scope);
          //  Grab the template. either from the template attribute, or from the URL in templateUrl
          (attrs.template ? $q.when($parse(attrs.template)($scope)) :
            $http.get(attrs.templateUrl, {cache: $templateCache}).then(function (result) {
              return result.data;
            })
          ).then(function (template) {
            var setProperty = function (obj, props, value, lastProp, buildParent) {
              props = props.split('.');
              lastProp = lastProp || props.pop();
              
              for (var i = 0; i < props.length; i++) {
                obj = obj[props[i]] = obj[props[i]] || {};
              }
              
              if (!buildParent) {
                obj[lastProp] = value;
              }
            },
            bracket = function (model, base) {
              props = model.split('.');
              return (base || props.shift()) + (props.length ? "['" + props.join("']['") + "']" : '');
            },
            buildFields = function (field, id) {
              if (String.charAt(id, 0) == '$') {
                // Don't process keys added by Angular...  See GitHub Issue #29
                return;
              }
              else if (!angular.isDefined(supported[field.type]) || supported[field.type] === false) {
                //  Unsupported.  Create SPAN with field.label as contents
                newElement = angular.element('<span></span>');
                if (angular.isDefined(field.label)) {angular.element(newElement).html(field.label);}
                angular.forEach(field, function (val, attr) {
                  if (["label", "type"].indexOf(attr) > -1) {return;}
                  newElement.attr(attr, val);
                });
                this.append(newElement);
                newElement = null;
              }
              else {
                //  Supported.  Create element (or container) according to type
                if (!angular.isDefined(field.model)) {
                  field.model = id;
                }
                
                newElement = angular.element($document[0].createElement(supported[field.type].element));
                if (angular.isDefined(supported[field.type].type)) {
                  newElement.attr('type', supported[field.type].type);
                }
                
                //  Editable fields (those that can feed models)
                if (angular.isDefined(supported[field.type].editable) && supported[field.type].editable) {
                  newElement.attr('name', bracket(field.model));
                  newElement.attr('ng-model', bracket(field.model, attrs.ngModel));
                  // Build parent in case of a nested model
{'fraction_non_alphanumeric': 0.15615060285524077, 'fraction_numerical': 0.0024410089503661514, 'mean_word_length': 2.4586850856996674, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4070701', 'n_tokens_mistral': 3815, 'n_tokens_neox': 3725, 'n_words': 1079}