Skip to content

Rebuild for 0.8.14. #953

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,8 @@
"angular-ui-sortable": ">=0.12.11",
"bootstrap-vertical-tabs": "~1.2.0",
"angular-schema-form-bootstrap": "~0.1.2"
},
"resolutions": {
"jquery": "~2.1.1"
}
}
231 changes: 132 additions & 99 deletions dist/schema-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,81 @@ angular.module('schemaForm').provider('sfPath',
};
}]);

/**
* @ngdoc service
* @name sfSelect
* @kind function
*
*/
angular.module('schemaForm').factory('sfSelect', ['sfPath', function(sfPath) {
var numRe = /^\d+$/;

/**
* @description
* Utility method to access deep properties without
* throwing errors when things are not defined.
* Can also set a value in a deep structure, creating objects when missing
* ex.
* var foo = Select('address.contact.name',obj)
* Select('address.contact.name',obj,'Leeroy')
*
* @param {string} projection A dot path to the property you want to get/set
* @param {object} obj (optional) The object to project on, defaults to 'this'
* @param {Any} valueToSet (opional) The value to set, if parts of the path of
* the projection is missing empty objects will be created.
* @returns {Any|undefined} returns the value at the end of the projection path
* or undefined if there is none.
*/
return function(projection, obj, valueToSet) {
if (!obj) {
obj = this;
}
//Support [] array syntax
var parts = typeof projection === 'string' ? sfPath.parse(projection) : projection;

if (typeof valueToSet !== 'undefined' && parts.length === 1) {
//special case, just setting one variable
obj[parts[0]] = valueToSet;
return obj;
}

if (typeof valueToSet !== 'undefined' &&
typeof obj[parts[0]] === 'undefined') {
// We need to look ahead to check if array is appropriate
obj[parts[0]] = parts.length > 2 && numRe.test(parts[1]) ? [] : {};
}

var value = obj[parts[0]];
for (var i = 1; i < parts.length; i++) {
// Special case: We allow JSON Form syntax for arrays using empty brackets
// These will of course not work here so we exit if they are found.
if (parts[i] === '') {
return undefined;
}
if (typeof valueToSet !== 'undefined') {
if (i === parts.length - 1) {
//last step. Let's set the value
value[parts[i]] = valueToSet;
return valueToSet;
} else {
// Make sure to create new objects on the way if they are not there.
// We need to look ahead to check if array is appropriate
var tmp = value[parts[i]];
if (typeof tmp === 'undefined' || tmp === null) {
tmp = numRe.test(parts[i + 1]) ? [] : {};
value[parts[i]] = tmp;
}
value = tmp;
}
} else if (value) {
//Just get nex value.
value = value[parts[i]];
}
}
return value;
};
}]);


// FIXME: type template (using custom builder)
angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(sfPathProvider) {
Expand All @@ -78,9 +153,19 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
};
var formId = 0;

if (!("firstElementChild" in document.createDocumentFragment())) {
Object.defineProperty(DocumentFragment.prototype, "firstElementChild", {
get: function () {
for (var nodes = this.childNodes, n, i = 0, l = nodes.length; i < l; ++i)
if (n = nodes[i], 1 === n.nodeType) return n;
return null;
}
});
}

var builders = {
sfField: function(args) {
args.fieldFrag.firstChild.setAttribute('sf-field', formId);
args.fieldFrag.firstElementChild.setAttribute('sf-field', formId);

// We use a lookup table for easy access to our form.
args.lookup['f' + formId] = args.form;
Expand Down Expand Up @@ -183,24 +268,27 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
}

var children = args.fieldFrag.children || args.fieldFrag.childNodes;
var child;
var ngIf;
for (var i = 0; i < children.length; i++) {
var child = children[i];
var ngIf = child.getAttribute('ng-if');
child.setAttribute(
'ng-if',
ngIf ?
'(' + ngIf +
') || (' + evalExpr + ')'
: evalExpr
);
child = children[i];
ngIf = false;

if (child.hasAttribute && child.hasAttribute('ng-if')) {
ngIf = child.getAttribute('ng-if');
};

if (child.setAttribute) {
child.setAttribute('ng-if', ngIf ? '(' + ngIf + ') || (' + evalExpr + ')' : evalExpr);
};
}
}
},
array: function(args) {
var items = args.fieldFrag.querySelector('[schema-form-array-items]');
if (items) {
state = angular.copy(args.state);
state.keyRedaction = state.keyRedaction || 0;
state.keyRedaction = 0;
state.keyRedaction += args.form.key.length + 1;

// Special case, an array with just one item in it that is not an object.
Expand Down Expand Up @@ -489,8 +577,14 @@ angular.module('schemaForm').provider('schemaFormDecorators',
if (!scope.ngModel) {
return false;
}
return scope.ngModel.$valid &&
(!scope.ngModel.$pristine || !scope.ngModel.$isEmpty(scope.ngModel.$modelValue));
if (scope.options && scope.options.pristine &&
scope.options.pristine.success === false) {
return scope.ngModel.$valid &&
(!scope.ngModel.$pristine && !scope.ngModel.$isEmpty(scope.ngModel.$modelValue));
} else {
return scope.ngModel.$valid &&
(!scope.ngModel.$pristine || !scope.ngModel.$isEmpty(scope.ngModel.$modelValue));
}
};

scope.hasError = function() {
Expand Down Expand Up @@ -580,12 +674,20 @@ angular.module('schemaForm').provider('schemaFormDecorators',
// It looks better with dot notation.
scope.$on(
'schemaForm.error.' + form.key.join('.'),
function(event, error, validationMessage, validity) {
function(event, error, validationMessage, validity, formName) {
// validationMessage and validity are mutually exclusive
formName = validity;
if (validationMessage === true || validationMessage === false) {
validity = validationMessage;
validationMessage = undefined;
}

// If we have specified a form name, and this model is not within
// that form, then leave things be.
if(formName != undefined && scope.ngModel.$$parentForm.$name !== formName) {
return;
}

if (scope.ngModel && error) {
if (scope.ngModel.$setDirty) {
scope.ngModel.$setDirty();
Expand Down Expand Up @@ -1171,6 +1273,7 @@ angular.module('schemaForm').provider('schemaForm',
if (stripNullType(schema.type) === 'object') {
var f = stdFormObj(name, schema, options);
f.type = 'fieldset';
f.key = options.path;
f.items = [];
options.lookup[sfPathProvider.stringify(options.path)] = f;

Expand Down Expand Up @@ -1389,7 +1492,7 @@ angular.module('schemaForm').provider('schemaForm',
if (obj.type === 'checkbox' && angular.isUndefined(obj.schema['default'])) {
obj.schema['default'] = false;
}

// Special case: template type with tempplateUrl that's needs to be loaded before rendering
// TODO: this is not a clean solution. Maybe something cleaner can be made when $ref support
// is introduced since we need to go async then anyway
Expand Down Expand Up @@ -1481,81 +1584,6 @@ angular.module('schemaForm').provider('schemaForm',

}]);

/**
* @ngdoc service
* @name sfSelect
* @kind function
*
*/
angular.module('schemaForm').factory('sfSelect', ['sfPath', function(sfPath) {
var numRe = /^\d+$/;

/**
* @description
* Utility method to access deep properties without
* throwing errors when things are not defined.
* Can also set a value in a deep structure, creating objects when missing
* ex.
* var foo = Select('address.contact.name',obj)
* Select('address.contact.name',obj,'Leeroy')
*
* @param {string} projection A dot path to the property you want to get/set
* @param {object} obj (optional) The object to project on, defaults to 'this'
* @param {Any} valueToSet (opional) The value to set, if parts of the path of
* the projection is missing empty objects will be created.
* @returns {Any|undefined} returns the value at the end of the projection path
* or undefined if there is none.
*/
return function(projection, obj, valueToSet) {
if (!obj) {
obj = this;
}
//Support [] array syntax
var parts = typeof projection === 'string' ? sfPath.parse(projection) : projection;

if (typeof valueToSet !== 'undefined' && parts.length === 1) {
//special case, just setting one variable
obj[parts[0]] = valueToSet;
return obj;
}

if (typeof valueToSet !== 'undefined' &&
typeof obj[parts[0]] === 'undefined') {
// We need to look ahead to check if array is appropriate
obj[parts[0]] = parts.length > 2 && numRe.test(parts[1]) ? [] : {};
}

var value = obj[parts[0]];
for (var i = 1; i < parts.length; i++) {
// Special case: We allow JSON Form syntax for arrays using empty brackets
// These will of course not work here so we exit if they are found.
if (parts[i] === '') {
return undefined;
}
if (typeof valueToSet !== 'undefined') {
if (i === parts.length - 1) {
//last step. Let's set the value
value[parts[i]] = valueToSet;
return valueToSet;
} else {
// Make sure to create new objects on the way if they are not there.
// We need to look ahead to check if array is appropriate
var tmp = value[parts[i]];
if (typeof tmp === 'undefined' || tmp === null) {
tmp = numRe.test(parts[i + 1]) ? [] : {};
value[parts[i]] = tmp;
}
value = tmp;
}
} else if (value) {
//Just get nex value.
value = value[parts[i]];
}
}
return value;
};
}]);

/* Common code for validating a value against its form and schema definition */
/* global tv4 */
angular.module('schemaForm').factory('sfValidator', [function() {
Expand Down Expand Up @@ -2085,12 +2113,20 @@ angular.module('schemaForm').directive('sfField',
// It looks better with dot notation.
scope.$on(
'schemaForm.error.' + form.key.join('.'),
function(event, error, validationMessage, validity) {
function(event, error, validationMessage, validity, formName) {
// validationMessage and validity are mutually exclusive
formName = validity;
if (validationMessage === true || validationMessage === false) {
validity = validationMessage;
validationMessage = undefined;
}

// If we have specified a form name, and this model is not within
// that form, then leave things be.
if(formName != undefined && scope.ngModel.$$parentForm.$name !== formName) {
return;
}

if (scope.ngModel && error) {
if (scope.ngModel.$setDirty) {
scope.ngModel.$setDirty();
Expand Down Expand Up @@ -2388,15 +2424,12 @@ function(sel, sfPath, schemaForm) {
if (vals && vals !== old) {
var arr = getOrCreateModel();

// Apparently the fastest way to clear an array, readable too.
// http://jsperf.com/array-destroy/32
while (arr.length > 0) {
arr.pop();
}
form.titleMap.forEach(function(item, index) {
if (vals[index]) {
form.titleMap.forEach(function (item, index) {
var arrIndex = arr.indexOf(item.value);
if (arrIndex === -1 && vals[index])
arr.push(item.value);
}
if (arrIndex !== -1 && !vals[index])
arr.splice(arrIndex, 1);
});

// Time to validate the rebuilt array.
Expand Down
Loading