All Downloads are FREE. Search and download functionalities are using the official Maven repository.

www.reboot.js.sync.js Maven / Gradle / Ivy

The newest version!
var nf = typeof nf !== 'undefined' ? nf : {};

nf.sync = (function() {

    'use strict';

    var dirtyCheckKeyword = '__isDirty__',
        type = {
            input         : 'input',
            select        : 'select',
            multipleSelect: 'multipleSelect'
        };

    var replicateChanges = function(sourceElement, recipientElement, elementType, listenToKeyChanges) {

        var eventName = listenToKeyChanges ? 'keyup' : 'change';

        sourceElement.addEventListener(eventName, function() {

            var changeEvent;

            if (this[dirtyCheckKeyword]) {

                this[dirtyCheckKeyword] = false;

            } else {

                changeEvent = new Event(eventName, {bubbles: true});

                pushElementValue(sourceElement, recipientElement, elementType);

                recipientElement[dirtyCheckKeyword] = true;

                recipientElement.dispatchEvent(changeEvent);

                if (changeEvent === 'keyup') {
                    //required for Angular 1.x
                    recipientElement.dispatchEvent('input');
                }

            }

        });

        if (listenToKeyChanges) {
            // calling again without 'listeningToKeyChanges' to register change events too
            replicateChanges.apply(this, [].slice.call(arguments, 0, arguments.length - 1) );
        }

    };

    var getFormElementType = function(element) {

        var elementType;

        if (element.tagName === 'INPUT') {

            elementType = type.input;

        } else if (element.tagName === 'SELECT' && element.multiple) {

            elementType = type.multipleSelect;

        } else if (element.tagName === 'SELECT') {

            elementType = type.select;

        }
        return elementType;

    };

    var watchForMutations = function(sourceElement, recipientElement, emitOnBack) {

        var observer = new MutationObserver(function() {

            if (sourceElement[dirtyCheckKeyword]) {

                sourceElement[dirtyCheckKeyword] = false;

            } else {

                recipientElement[dirtyCheckKeyword] = true;

                pushMultiSelectState(sourceElement, recipientElement, emitOnBack);

            }

        });

        observer.observe(sourceElement, {attributes: false, childList: true, characterData: false});

    };

    var sync = function(elementA, elementB, emitOnBack, listenToKeyChanges) {

        var elementType = getFormElementType(elementA);

        if (elementType === type.multipleSelect) {

            watchForMutations(elementA, elementB);
            watchForMutations(elementB, elementA, emitOnBack);

        }

        if (elementType) {

            var changeEvent;

            replicateChanges(elementA, elementB, elementType, listenToKeyChanges);
            replicateChanges(elementB, elementA, elementType, listenToKeyChanges);

            if (elementA.value && elementA.value.length) {

                changeEvent = new Event('change', {bubbles: true});
                elementB.value = elementA.value;
                elementB.dispatchEvent(changeEvent);

            }

        } else {

            console.error('The type of this form element is not currently supported');

        }

    };

    // copy all options and their states from one select to another
    var pushMultiSelectState = function(sourceElement, recipientElement, emitOnBack) {

        if (emitOnBack) {

            var event = new CustomEvent("change:selectOnly", {
                "detail":{"selected":nf.multiSelect.getValuesAsAnArray(sourceElement)}
            });

            sourceElement.dispatchEvent(event);

        } else {

            var docFrag = document.createDocumentFragment(),
                options = sourceElement.options,
                option,
                newOption,
                i, l;

            for (l = options.length, i = 0; i < l; i++) {
                option = options[i];
                newOption = document.createElement('option');
                newOption.textContent = option.textContent;
                newOption.value = option.value;
                newOption.disabled = option.disabled;
                newOption.selected = option.selected;
                docFrag.appendChild(newOption);
            }

            recipientElement.innerHTML = '';
            recipientElement.appendChild(docFrag);

        }

    };

    var pushMultiSelectValue = function(sourceElement, recipientElement) {

        var values = nf.multiSelect.getValuesAsAnArray(sourceElement);
        nf.multiSelect.setSelectedValues(recipientElement, values, true);

    };

    var pushElementValue = function(sourceElement, recipientElement, elementType) {

        switch (elementType) {

            case type.input:
                recipientElement.value = sourceElement.value;
                break;
            case type.select:
                recipientElement.value = sourceElement.value;
                break;
            case type.multipleSelect:
                pushMultiSelectValue(sourceElement, recipientElement);
                break;

        }

    };

    return {
        sync: sync
    };

}());




© 2015 - 2024 Weber Informatics LLC | Privacy Policy