API Docs for: 0.1.0
Show:

File: js/types/collection.js

/*
 * This file is part of the Husky Validation.
 *
 * (c) MASSIVE ART WebServices GmbH
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 *
 * @module husky-validation/type/collection
 */

// TODO min / max for each collection in config
// TODO add / remove handling (buttons)
// TODO check full and empty
// TODO empty template remove (set data add to collection)
// TODO add / remove from collection function
// TODO edit in collection

/**
 * @class Collection
 * @constructor
 *
 * @param {Object} [options] configuration object
 * @param {number} [options.min] min default min items
 * @param {number} [options.max] max default max items
 * @param {string} [options.singleValue] singleValue property name of single value
 */
define([
    'type/default',
    'form/util'
], function(Default, Util) {

    'use strict';

    return function($el, options, form) {
        var defaults = {
                min: 0,
                max: null,
                singleValue: false
            },

            subType = {
                /**
                 * initialize templates
                 * @method initializeSub
                 */
                initializeSub: function() {
                    var i, len, property, $tpl, $emptyTpl;

                    // get dom data
                    this.properties = $el.data('mapperProperty').split(',');
                    this.templates = {};

                    // extract templates from dom
                    for (i = 0, len = this.properties.length; i < len; i++) {
                        property = this.properties[i];
                        $tpl = $('#' + this.options.config[property].tpl);
                        $emptyTpl = $('#' + this.options.config[property].emptyTpl);

                        // save content from tpl
                        this.templates[property] = {
                            tpl: $tpl.html(),
                            emptyTpl: $emptyTpl.html()
                        };
                    }
                },

                /**
                 * maps given array (value) with given templates to this.$el
                 * @method internalSetValue
                 * @param {object} templates includes tpl and empty template
                 * @param {array} value array of data
                 * @param {string} propertyName name of property
                 * @returns {object} deferred objects that´s indicates end of asynchronous functions
                 */
                internalSetValue: function(templates, value, propertyName) {
                    var i, len, count, item,
                        dfd = $.Deferred(),
                        resolve = function() {
                            count--;
                            if (count === 0) {
                                dfd.resolve();
                            }
                        };

                    // remove children for this property
                    this.getChildren(propertyName).remove();

                    // get important values
                    len = value.length < this.getMinOccurs() ? this.getMinOccurs() : value.length;
                    count = len;

                    for (i = 0; i < len; i++) {
                        item = value[i] || {};

                        this.addChild(i, item, templates.tpl, propertyName).then(resolve);
                    }

                    return dfd.promise();
                },

                /**
                 * add a child to this.$el but on
                 * @method addChild
                 * @param {number} index for resulting $item dom element
                 * @param {object} item data for resulting $item dom element
                 * @param {string} template to render $item
                 * @param {string} propertyName name of property
                 * @returns {object} deferred objects that´s indicates end of asynchronous functions
                 */
                addChild: function(index, item, template, propertyName) {
                    var options, $template, tmp, dfd = $.Deferred();

                    if (typeof index === 'undefined' || index === null) {
                        index = this.getChildren(propertyName).length;
                    }

                    if (this.canAdd()) {
                        // render child
                        options = $.extend({}, {index: index}, item);
                        template = _.template(template, options, form.options.delimiter);
                        $template = $(template);

                        // set attributes to identify item
                        $template.attr('data-mapper-property-tpl', propertyName);
                        $template.attr('data-mapper-id', _.uniqueId());

                        // insert child
                        Util.insertAt(index, '> *', this.$el, $template);

                        // init fields and set data
                        this.form.initFields($template).then(function() {
                            if (!!this.options.singleValue) {
                                tmp = item;
                                item = {};
                                item[this.options.singleValue] = tmp;
                            }

                            this.form.mapper.setData(item, $template).then(function() {
                                dfd.resolve();
                            }.bind(this));
                        }.bind(this));
                    } else {
                        dfd.resolve();
                    }

                    return dfd.promise();
                },

                /**
                 * map value to this.$el
                 * @method setValue
                 * @param {array} data
                 * @param {string }propertyName
                 * @returns {object} deferred objects that´s indicates end of asynchronous functions
                 */
                setValue: function(data, propertyName) {
                    var templates = this.templates[propertyName], dfd;
                    if (data.length === 0) {
                        dfd = $.Deferred();
                        this.$el.append(_.template(templates.emptyTpl));

                        // resolve now
                        dfd.resolve();
                        return dfd.promise();
                    } else {
                        return this.internalSetValue(templates, data, propertyName);
                    }
                },

                /**
                 * returns data array
                 * @method getValue
                 * @param {string} propertyName
                 * @param {string} returnMapperId
                 * @returns {array}
                 */
                getValue: function(propertyName, returnMapperId) {
                    var $children = this.getChildren(propertyName), i, len, item, keys, result = [];

                    for (i = 0, len = $children.length; i < len; i++) {
                        item = this.form.mapper.getData($children[i], returnMapperId);
                        if (!!returnMapperId) {
                            item.mapperId = $($children[i]).data('mapperId');
                        }

                        if (!!this.options.singleValue) {
                            // for value only collection
                            keys = Object.keys(item);
                            if (item[keys[0]] !== '') {
                                result.push(item[keys[0]]);
                            }
                        } else {
                            result.push(item);
                        }
                    }

                    return result;
                },

                /**
                 * validates this type of data
                 * @method validate
                 * @returns {boolean}
                 */
                validate: function() {
                    return true;
                },

                /**
                 * indicates data to validate
                 * @method needsValidation
                 * @returns {boolean}
                 */
                needsValidation: function() {
                    return false;
                },

                /**
                 * returns children for given property
                 * @method getChildren
                 * @param {string} propertyName
                 * @returns {array}
                 */
                getChildren: function(propertyName) {
                    return this.$el.find('*[data-mapper-property-tpl="' + propertyName + '"]');
                },

                /**
                 * returns min occurs
                 * @method getMinOccurs
                 * @param {string} propertyName
                 * @returns {number}
                 */
                getMinOccurs: function(propertyName) {
                    return this.options.min;
                },

                /**
                 * returns min occurs
                 * @method getMaxOccurs
                 * @param {string} propertyName
                 * @returns {number}
                 */
                getMaxOccurs: function(propertyName) {
                    return this.options.max;
                },

                /**
                 * returns TRUE if a child can be added for given property
                 * @method canAdd
                 * @returns {boolean}
                 */
                canAdd: function(propertyName) {
                    var length = this.getChildren(propertyName).length;
                    return this.getMaxOccurs() === null || length < this.getMaxOccurs();
                },

                /**
                 * returns TRUE if a child can be removed for given property
                 * @method canRemove
                 * @returns {boolean}
                 */
                canRemove: function(propertyName) {
                    var length = this.getChildren(propertyName).length;
                    return length > this.getMinOccurs();
                }
            };

        return new Default($el, defaults, options, 'collection', subType, form);
    };
});