<commit_before>import '../../plugins/uploader';
import '../job/tinymce';

class Tags {
    constructor(options) {
        let defaults = {
            input: '#tag',
            dropdown: '.tag-suggestions',
            container: '#tags-container',
            remove: '.btn-remove'
        };

        this.setup = $.extend(defaults, options);

        this.input = $(this.setup.input);
        this.dropdown = $(this.setup.dropdown);
        this.container = $(this.setup.container);
        this.selectedIndex = -1;

        this.dropdown.css({
            'width':			this.input.outerWidth() - 4,
            'left':				this.input.position().left,
            'top':				this.input.position().top + this.input.outerHeight()
        });

        this.onFocus();
        this.onKeyUp();
        this.onKeyDown();
        this.onHover();
        this.onItemClick();
        this.onRemove();

        $(document).bind('click', e => {
            let $target = $(e.target);

            if (!$target.is(this.input)) {
                this.hideDropdown();
            }
        });
    }

    onKeyUp() {
        this.input.on('keyup', e => {
            let keyCode = e.keyCode || window.event.keyCode;

            if (keyCode === 13) {
                if ($('li.hover', this.dropdown).find('span').text() !== '') {
                    this.addTag($('li.hover', this.dropdown).find('span').text());
                }
                else if (this.input.val() !== '') {
                    this.addTag(this.input.val());
                }

                this.hideDropdown();
                this.input.val('');

                e.preventDefault();
            }
            else if (keyCode === 40) { // down
                this.select(this.selectedIndex + 1);
            }
            else if (keyCode === 38) { // up
                this.select(this.selectedIndex - 1);
            }
            else {
                let searchText = this.input.val().toLowerCase();
                let hits = 0;

                $('li', this.dropdown).each(index => {
                    let item = $('li:eq(' + index + ')', this.dropdown);
                    let text = item.find('span').text();

                    if (text.toLowerCase().indexOf(searchText) === -1) {
                        item.hide();
                    }
                    else  {
                        item.show();
                        hits++;
                    }
                });

                this.dropdown.toggle(hits > 0);
            }
        });
    }

    onKeyDown() {
        this.input.on('keydown', e => {
            let keyCode = e.keyCode || window.event.keyCode;

            if (keyCode === 27) {
                this.input.val('');
                this.dropdown.hide();
            }
            else if (keyCode === 13) {
                e.preventDefault();
            }
        });
    }

    onHover() {
        $('li', this.dropdown).hover(e => $(e.currentTarget).addClass('hover'), e => $(e.currentTarget).removeClass('hover'));
    }

    onItemClick() {
        this.dropdown.on('click', 'li', e => {
            this.addTag($(e.currentTarget).find('span').text());
            this.hideDropdown();

            this.input.val('').focus();
        });
    }

    onRemove() {
        this.container.on('click', this.setup.remove, e => {
            $(e.currentTarget).parents('.tag-item').remove();
        });
    }

    onFocus() {
        this.input.on('focus click', () => {
            this.dropdown.show();
        });
    }

    select(position) {
        let length = $('li:visible', this.dropdown).length;

        if (length > 0) {
            if (position >= length) {
                position = 0;
            }
            else if (position < 0) {
                position = length -1;
            }
            this.selectedIndex = position;

            $('li:visible', this.dropdown).removeClass('hover');
            $('li:visible:eq(' + this.selectedIndex + ')', this.dropdown).addClass('hover');

            this.dropdown.scrollTop(position * $('li:first', this.dropdown).outerHeight());
        }
    }

    hideDropdown() {
        this.dropdown.hide();
    }

    showDropdown() {
        this.dropdown.show();
    }

    addTag(value) {
        value = $.trim(value)
            .toString()
            .replace(/</g, "<")
            .replace(/>/g, ">")
            .replace(/'/g, "'")
            .replace(/"/g, """)
            .toLowerCase()
            .replace(/ /g, '-');

        $.post(this.input.data('post-url'), {name: value}, html => {
            this.container.append(html);
        }).fail(() => {
            $('#alert').modal('show');
        });

        this.selectedIndex = - 1;
        $('li', this.dropdown).removeClass('hover').show();
    }
}

$(() => {
    'use strict';

    if ($('#tag').length) {
        new Tags();
    }

    if (typeof google !== 'undefined') {
        google.maps.event.addDomListener(window, 'load', initialize);
    }

    let navigation = $('#form-navigation');
    let fixed = $('#form-navbar-fixed');

    $('#form-navigation-container')
        .html(navigation.html())
        .on('click', ':submit', () => $('#job-posting').submit())
        .on('click', 'button[data-submit-state]', e => $(e.currentTarget).attr('disabled', 'disabled').text($(e.currentTarget).data('submit-state')));

    if (navigation.length) {
        $(window).scroll(() => {
            let bottom = $(window).scrollTop() + $(window).height();

            if (bottom > navigation.offset().top) {
                fixed.fadeOut();
            }
            else {
                fixed.show();
            }
        }).trigger('scroll');
    }

    /**
     * Save and exit button
     */
    $('.btn-save').on('click', () => {
        $('input[name="done"]').val(1);
    });

    $('.jumbotron .btn-close').click(() => {
        $('.jumbotron .close').click();
    });

    $('#job-posting').on('change', 'input[name="enable_apply"]', e => {
        if (Boolean(parseInt($(e.currentTarget).val()))) {
            tinymce.get('recruitment').hide();
            $('#recruitment').attr('disabled', 'disabled').hide();

            $('input[name="email"]').removeAttr('disabled');
        }
        else {
            tinymce.get('recruitment').show();
            $('input[name="email"]').attr('disabled', 'disabled');
            $('#recruitment').removeAttr('disabled');
        }
    })
    .on('keyup', 'input[name="deadline"]', e => {
        let $this = $(e.currentTarget);
        let value = parseInt($this.val());

        if (value > 0) {
            let date = new Date();
            date.setDate(date.getDate() + value);

            $this.next('span').children('strong').text(date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate());
        }
        else {
            $this.next('span').children('strong').text('--');
        }
    })
    .on('change keyup', 'input[maxlength]', e => {
        let $this = $(e.currentTarget);
        let maxLength = $this.attr('maxlength');
        let container = $this.next('span');
        let length = maxLength - $this.val().length;

        container.children('strong').text(length);
    })
    .on('change', 'input[name="private"]', e => {
        $('#box-edit-firm, #choose-firm').toggle($(e.currentTarget).val() == 0);
        $('#box-buttons').toggle($(e.currentTarget).val() != 0);
    })
    .on('change', 'input[name="is_agency"]', e => {
        $('.agency').toggle($(e.currentTarget).val() != 1);
    })
    .on('focus', ':input', e => {
        let $this = $(e.currentTarget);
        let offset = $this.offset().top;
        let name = $this.attr('name');

        $('.sidebar-hint').hide();

        if (typeof name !== 'undefined') {
            name = name.replace('[', '').replace(']', '');

            $('#hint-' + name).fadeIn();
            offset -= $('aside').offset().top;

            $('#hint-container').css('top', offset);
        }
    });

    if ($('input[name="private"]').val()) {
        $('input[name="private"]:checked').trigger('change');
    }

    if ($('input[name="is_agency"]').val()) {
        $('input[name="is_agency"]:checked').trigger('change');
    }

    $('.benefits').on('keyup focus blur', 'input[type="text"]', e => {
        let $this = $(e.currentTarget);
        let nextItem = $this.parent().next('li');

        if ($this.val().length > 0) {
            if (!nextItem.length) {
                let clone = $this.parent().clone();
                $('input', clone).val('');

                clone.insertAfter($this.parent());
            }
        }
        else if (nextItem.length) {
            if ($('input', nextItem).val().length === 0) {
                nextItem.remove();
            }
        }
    }).on('click', 'li.clickable', e => {
        let checkbox = $(e.currentTarget).children(':checkbox');

        checkbox.prop('checked', !checkbox.is(':checked'));
        $(e.currentTarget).toggleClass('checked');
    });

    $.uploader({
        input: 'logo',
        onChanged: function(data) {
            $('#job-posting').find('input[name="logo"]').val(data.name);
        },
        onDeleted: function() {
            $('#job-posting').find('input[name="logo"]').val('');
        }
    });

    $('#btn-add-firm').click(() => {
        $.get(_config.firm_partial, {}, (html) => {
            $('#box-edit-firm').replaceWith(html);

            $('#modal-firm').modal('hide');
            initialize();
        });
    });

    /**
     * Ability to create new firm and assign it to the offer
     */
    $('#box-edit-firm').find('input[name="name"]').one('keyup', () => {
        if ($('#firm-id').val() === '') {
            return true;
        }

        $('#modal-firm').modal('show').find('.btn-primary').one('click', () => {
            $('#btn-add-firm').click();

            return false;
        });
    });

    /**
     * Ability to assign different firm to this job offer
     */
    $('.btn-firm').click(e => {
        let self = $(e.currentTarget);

        $.get(self.attr('href'), (html) => {
            $('#box-edit-firm').replaceWith(html);
            initialize();

            $('.btn-firm').not(self).removeClass('btn-primary').addClass('btn-default');
            self.addClass('btn-primary').removeClass('btn-default');

            tinymce.EditorManager.editors = [];
            initTinymce();
        });

        return false;
    });
});

function initialize() {
    'use strict';

    var mapOptions =
    {
        zoom: 6,
        center: new google.maps.LatLng(51.919438, 19.14513599999998),
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    var geocoder = new google.maps.Geocoder();
    var map = new google.maps.Map(document.getElementById("map"), mapOptions);
    var marker;

    var geocodeResult = function (results, status) {
        if (status === google.maps.GeocoderStatus.OK) {
            map.setCenter(results[0].geometry.location);

            if (marker) {
                marker.setMap(null);
            }

            marker = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
            });

            map.setZoom(16);
            $('#address').val(results[0].formatted_address);

            var country = '', city = '', street = '', postcode = '';
            var components = results[0].address_components;

            for (let item in components) {
                if (components.hasOwnProperty(item)) {
                    let component = components[item];

                    if (!country && component.types.indexOf('country') > -1) {
                        country = component.long_name;
                    }
                    if (!postcode && component.types.indexOf('postal_code') > -1) {
                        postcode = component.long_name;
                    }
                    if (!city && component.types.indexOf('locality') > -1) {
                        city = component.long_name;
                    }
                    if (!postcode && component.types.indexOf('route') > -1) {
                        street = component.long_name;
                    }
                }
            }

            $(':hidden[name=country]').val(country);
            $(':hidden[name=city]').val(city);
            $(':hidden[name=street]').val(street);
            $(':hidden[name=postcode]').val(postcode);
            $('#longitude').val(results[0].geometry.location.lng());
            $('#latitude').val(results[0].geometry.location.lat());
        }
    };

    var geocode = function (address) {
        geocoder.geocode({'address': address}, geocodeResult);
    };

    var reverseGeocode = function (coordinates) {
        geocoder.geocode({'latLng': coordinates}, geocodeResult);
    };

    if (!isNaN(parseFloat($('#latitude').val())) && !isNaN(parseFloat($('#longitude').val()))) {
        var coordinates = new google.maps.LatLng(parseFloat($('#latitude').val()), parseFloat($('#longitude').val()));

        marker = new google.maps.Marker({
            map: map,
            position: coordinates
        });

        map.setCenter(coordinates);
    }

    var onAddressChange = function () {
        var val = $.trim($('#address').val());

        if (val.length) {
            geocode(val);
        }
        else {
            $('#longitude, #latitude').val(0);
            $(':hidden[name=country], :hidden[name=city], :hidden[name=street], :hidden[name=postcode]').val('');

            marker.setMap(null);
        }
    };

    $('#address').keypress(function (e) {
        var code = e.keyCode || e.which;

        if (code === 13) {
            onAddressChange();
            return false;
        }
    });

    google.maps.event.addListener(map, 'click', (e) => {
        reverseGeocode(e.latLng);
    });
}
<commit_msg>bugfix: inicjalizacja mapy na ukrytym divie<commit_after>import '../../plugins/uploader';
import '../job/tinymce';

class Tags {
    constructor(options) {
        let defaults = {
            input: '#tag',
            dropdown: '.tag-suggestions',
            container: '#tags-container',
            remove: '.btn-remove'
        };

        this.setup = $.extend(defaults, options);

        this.input = $(this.setup.input);
        this.dropdown = $(this.setup.dropdown);
        this.container = $(this.setup.container);
        this.selectedIndex = -1;

        this.dropdown.css({
            'width':			this.input.outerWidth() - 4,
            'left':				this.input.position().left,
            'top':				this.input.position().top + this.input.outerHeight()
        });

        this.onFocus();
        this.onKeyUp();
        this.onKeyDown();
        this.onHover();
        this.onItemClick();
        this.onRemove();

        $(document).bind('click', e => {
            let $target = $(e.target);

            if (!$target.is(this.input)) {
                this.hideDropdown();
            }
        });
    }

    onKeyUp() {
        this.input.on('keyup', e => {
            let keyCode = e.keyCode || window.event.keyCode;

            if (keyCode === 13) {
                if ($('li.hover', this.dropdown).find('span').text() !== '') {
                    this.addTag($('li.hover', this.dropdown).find('span').text());
                }
                else if (this.input.val() !== '') {
                    this.addTag(this.input.val());
                }

                this.hideDropdown();
                this.input.val('');

                e.preventDefault();
            }
            else if (keyCode === 40) { // down
                this.select(this.selectedIndex + 1);
            }
            else if (keyCode === 38) { // up
                this.select(this.selectedIndex - 1);
            }
            else {
                let searchText = this.input.val().toLowerCase();
                let hits = 0;

                $('li', this.dropdown).each(index => {
                    let item = $('li:eq(' + index + ')', this.dropdown);
                    let text = item.find('span').text();

                    if (text.toLowerCase().indexOf(searchText) === -1) {
                        item.hide();
                    }
                    else  {
                        item.show();
                        hits++;
                    }
                });

                this.dropdown.toggle(hits > 0);
            }
        });
    }

    onKeyDown() {
        this.input.on('keydown', e => {
            let keyCode = e.keyCode || window.event.keyCode;

            if (keyCode === 27) {
                this.input.val('');
                this.dropdown.hide();
            }
            else if (keyCode === 13) {
                e.preventDefault();
            }
        });
    }

    onHover() {
        $('li', this.dropdown).hover(e => $(e.currentTarget).addClass('hover'), e => $(e.currentTarget).removeClass('hover'));
    }

    onItemClick() {
        this.dropdown.on('click', 'li', e => {
            this.addTag($(e.currentTarget).find('span').text());
            this.hideDropdown();

            this.input.val('').focus();
        });
    }

    onRemove() {
        this.container.on('click', this.setup.remove, e => {
            $(e.currentTarget).parents('.tag-item').remove();
        });
    }

    onFocus() {
        this.input.on('focus click', () => {
            this.dropdown.show();
        });
    }

    select(position) {
        let length = $('li:visible', this.dropdown).length;

        if (length > 0) {
            if (position >= length) {
                position = 0;
            }
            else if (position < 0) {
                position = length -1;
            }
            this.selectedIndex = position;

            $('li:visible', this.dropdown).removeClass('hover');
            $('li:visible:eq(' + this.selectedIndex + ')', this.dropdown).addClass('hover');

            this.dropdown.scrollTop(position * $('li:first', this.dropdown).outerHeight());
        }
    }

    hideDropdown() {
        this.dropdown.hide();
    }

    showDropdown() {
        this.dropdown.show();
    }

    addTag(value) {
        value = $.trim(value)
            .toString()
            .replace(/</g, "<")
            .replace(/>/g, ">")
            .replace(/'/g, "'")
            .replace(/"/g, """)
            .toLowerCase()
            .replace(/ /g, '-');

        $.post(this.input.data('post-url'), {name: value}, html => {
            this.container.append(html);
        }).fail(() => {
            $('#alert').modal('show');
        });

        this.selectedIndex = - 1;
        $('li', this.dropdown).removeClass('hover').show();
    }
}

$(() => {
    'use strict';

    if ($('#tag').length) {
        new Tags();
    }

    if (typeof google !== 'undefined') {
        google.maps.event.addDomListener(window, 'load', initialize);
    }

    let navigation = $('#form-navigation');
    let fixed = $('#form-navbar-fixed');

    $('#form-navigation-container')
        .html(navigation.html())
        .on('click', ':submit', () => $('#job-posting').submit())
        .on('click', 'button[data-submit-state]', e => $(e.currentTarget).attr('disabled', 'disabled').text($(e.currentTarget).data('submit-state')));

    if (navigation.length) {
        $(window).scroll(() => {
            let bottom = $(window).scrollTop() + $(window).height();

            if (bottom > navigation.offset().top) {
                fixed.fadeOut();
            }
            else {
                fixed.show();
            }
        }).trigger('scroll');
    }

    /**
     * Save and exit button
     */
    $('.btn-save').on('click', () => {
        $('input[name="done"]').val(1);
    });

    $('.jumbotron .btn-close').click(() => {
        $('.jumbotron .close').click();
    });

    $('#job-posting').on('change', 'input[name="enable_apply"]', e => {
        if (Boolean(parseInt($(e.currentTarget).val()))) {
            tinymce.get('recruitment').hide();
            $('#recruitment').attr('disabled', 'disabled').hide();

            $('input[name="email"]').removeAttr('disabled');
        }
        else {
            tinymce.get('recruitment').show();
            $('input[name="email"]').attr('disabled', 'disabled');
            $('#recruitment').removeAttr('disabled');
        }
    })
    .on('keyup', 'input[name="deadline"]', e => {
        let $this = $(e.currentTarget);
        let value = parseInt($this.val());

        if (value > 0) {
            let date = new Date();
            date.setDate(date.getDate() + value);

            $this.next('span').children('strong').text(date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate());
        }
        else {
            $this.next('span').children('strong').text('--');
        }
    })
    .on('change keyup', 'input[maxlength]', e => {
        let $this = $(e.currentTarget);
        let maxLength = $this.attr('maxlength');
        let container = $this.next('span');
        let length = maxLength - $this.val().length;

        container.children('strong').text(length);
    })
    .on('change', 'input[name="private"]', e => {
        $('#box-edit-firm, #choose-firm').toggle($(e.currentTarget).val() == 0);
        $('#box-buttons').toggle($(e.currentTarget).val() != 0);
    })
    .on('change', 'input[name="is_agency"]', e => {
        $('.agency').toggle($(e.currentTarget).val() != 1);
        google.maps.event.trigger(map, 'resize');
    })
    .on('focus', ':input', e => {
        let $this = $(e.currentTarget);
        let offset = $this.offset().top;
        let name = $this.attr('name');

        $('.sidebar-hint').hide();

        if (typeof name !== 'undefined') {
            name = name.replace('[', '').replace(']', '');

            $('#hint-' + name).fadeIn();
            offset -= $('aside').offset().top;

            $('#hint-container').css('top', offset);
        }
    });

    if ($('input[name="private"]').val()) {
        $('input[name="private"]:checked').trigger('change');
    }

    if ($('input[name="is_agency"]').val()) {
        $('input[name="is_agency"]:checked').trigger('change');
    }

    $('.benefits').on('keyup focus blur', 'input[type="text"]', e => {
        let $this = $(e.currentTarget);
        let nextItem = $this.parent().next('li');

        if ($this.val().length > 0) {
            if (!nextItem.length) {
                let clone = $this.parent().clone();
                $('input', clone).val('');

                clone.insertAfter($this.parent());
            }
        }
        else if (nextItem.length) {
            if ($('input', nextItem).val().length === 0) {
                nextItem.remove();
            }
        }
    }).on('click', 'li.clickable', e => {
        let checkbox = $(e.currentTarget).children(':checkbox');

        checkbox.prop('checked', !checkbox.is(':checked'));
        $(e.currentTarget).toggleClass('checked');
    });

    $.uploader({
        input: 'logo',
        onChanged: function(data) {
            $('#job-posting').find('input[name="logo"]').val(data.name);
        },
        onDeleted: function() {
            $('#job-posting').find('input[name="logo"]').val('');
        }
    });

    $('#btn-add-firm').click(() => {
        $.get(_config.firm_partial, {}, (html) => {
            $('#box-edit-firm').replaceWith(html);

            $('#modal-firm').modal('hide');
            initialize();
        });
    });

    /**
     * Ability to create new firm and assign it to the offer
     */
    $('#box-edit-firm').find('input[name="name"]').one('keyup', () => {
        if ($('#firm-id').val() === '') {
            return true;
        }

        $('#modal-firm').modal('show').find('.btn-primary').one('click', () => {
            $('#btn-add-firm').click();

            return false;
        });
    });

    /**
     * Ability to assign different firm to this job offer
     */
    $('.btn-firm').click(e => {
        let self = $(e.currentTarget);

        $.get(self.attr('href'), (html) => {
            $('#box-edit-firm').replaceWith(html);
            initialize();

            $('.btn-firm').not(self).removeClass('btn-primary').addClass('btn-default');
            self.addClass('btn-primary').removeClass('btn-default');

            tinymce.EditorManager.editors = [];
            initTinymce();
        });

        return false;
    });
});

function initialize() {
    'use strict';

    let mapOptions =
    {
        zoom: 6,
        center: new google.maps.LatLng(51.919438, 19.14513599999998),
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    let geocoder = new google.maps.Geocoder();
    let map = new google.maps.Map(document.getElementById("map"), mapOptions);
    let marker;

    let geocodeResult = function (results, status) {
        if (status === google.maps.GeocoderStatus.OK) {
            map.setCenter(results[0].geometry.location);

            if (marker) {
                marker.setMap(null);
            }

            marker = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
            });

            map.setZoom(16);
            $('#address').val(results[0].formatted_address);

            let country = '', city = '', street = '', postcode = '';
            let components = results[0].address_components;

            for (let item in components) {
                if (components.hasOwnProperty(item)) {
                    let component = components[item];

                    if (!country && component.types.indexOf('country') > -1) {
                        country = component.long_name;
                    }
                    if (!postcode && component.types.indexOf('postal_code') > -1) {
                        postcode = component.long_name;
                    }
                    if (!city && component.types.indexOf('locality') > -1) {
                        city = component.long_name;
                    }
                    if (!postcode && component.types.indexOf('route') > -1) {
                        street = component.long_name;
                    }
                }
            }

            $(':hidden[name=country]').val(country);
            $(':hidden[name=city]').val(city);
            $(':hidden[name=street]').val(street);
            $(':hidden[name=postcode]').val(postcode);
            $('#longitude').val(results[0].geometry.location.lng());
            $('#latitude').val(results[0].geometry.location.lat());
        }
    };

    let geocode = function (address) {
        geocoder.geocode({'address': address}, geocodeResult);
    };

    let reverseGeocode = function (coordinates) {
        geocoder.geocode({'latLng': coordinates}, geocodeResult);
    };

    if (!isNaN(parseFloat($('#latitude').val())) && !isNaN(parseFloat($('#longitude').val()))) {
        let coordinates = new google.maps.LatLng(parseFloat($('#latitude').val()), parseFloat($('#longitude').val()));

        marker = new google.maps.Marker({
            map: map,
            position: coordinates
        });

        map.setCenter(coordinates);
    }

    let onAddressChange = function () {
        let val = $.trim($('#address').val());

        if (val.length) {
            geocode(val);
        }
        else {
            $('#longitude, #latitude').val(0);
            $(':hidden[name=country], :hidden[name=city], :hidden[name=street], :hidden[name=postcode]').val('');

            marker.setMap(null);
        }
    };

    $('#address').keypress(function (e) {
        let code = e.keyCode || e.which;

        if (code === 13) {
            onAddressChange();
            return false;
        }
    });

    google.maps.event.addListener(map, 'click', (e) => {
        reverseGeocode(e.latLng);
    });
}
<|endoftext|>


<commit_before>//*@public
/**
		_enyo.DataRepeater_ iterates over the items in an
		[enyo.Collection](#enyo.Collection) to repeatedly render and
		synchronize  records (instances of [enyo.Model](#enyo.Model)) to its
		own children. For any record in the collection, a new child will be
		rendered in this repeater. If  the record is destroyed, the child will
		be destroyed. These controls will automatically update when the
		properties on the underlying record are modified if they have been
		bound using bindings (see [enyo.Binding](#enyo.Binding)).
*/
enyo.kind({
	name: "enyo.DataRepeater",
	//*@public
	/**
		Set this to true to allow selection support to be enabled. Default
		is true for single-selection. Note that selection stores a reference to
		the model that is selected.
	*/
	selection: true,
	/**
		Set this to true to allow multiple children to be selected simultaneously.
		If this is true, then the _selection_ property will be set to true even if
		it has previously been set to false.
	*/
	multipleSelection: false,
	/**
		This class will be applied to the repeater when _selection_ is enabled.
		The default is _selection-enabled_. If _multipleSelection_ is true, this
		class will also be applied.
	*/
	selectionClass: "selection-enabled",
	/**
		This class will be applied to the repeater when _multipleSelection_ is
		true. The default is _multiple-selection-enabled_. If _multipleSelection_
		is true, the _selectionClass_ will also be applied.
	*/
	multipleSelectionClass: "multiple-selection-enabled",
	/**
		In cases where selection should be detected from the state of the model,
		this property should be set to the property that the repeater should
		observe for changes. If the model changes, the repeater will reflect the
		change without needing to interact directly with the model. Note that this
		property must be a part of the model's schema or its changes will not be
		detected properly.
	*/
	selectionProperty: "",
	/**
		Set this to a space-delimited string of events or an array that can trigger
		the selection of a particular child. By default it is simply the _ontap_
		event. To prevent selection entirely see _selection_ and set it to `false`.
	*/
	selectionEvents: "ontap",
	/**
		Use this hash to define _defaultBindingProperties_ for _all_ children
		(even children of children) of this repeater. This can be eliminate the
		need to write the same paths many times. You can also use any	binding
		macros. Any property defined here will be superseded by the same property if
		defined for an individual binding.
	*/
	childBindingDefaults: null,
	//*@protected
	initComponents: function () {
		this.initContainer();
		var c = this.kindComponents || this.components || [],
			o = this.getInstanceOwner(),
			d = this.defaultProps? enyo.clone(this.defaultProps): (this.defaultProps = {});
		// ensure that children know who their binding owner is
		d.bindingTransformOwner = this;
		d.bindingDefaults = this.childBindingDefaults;
		if (c) {
			// if there are multiple components in the components block they will become nested
			// children of the default kind set for the repeater
			if (c.length > 1) {
				d.components = c;
			}
			// if there is only one child, the properties will be the default kind of the repeater
			else {
				enyo.mixin(d, c[0]);
			}
			d.repeater = this;
			d.owner = o;
			d.mixins = d.mixins? d.mixins.concat(this.childMixins): this.childMixins;
		}
	},
	constructor: enyo.inherit(function (sup) {
		return function () {
			this._selection = [];
			// we need to initialize our selectionEvents array
			var se = this.selectionEvents;
			this.selectionEvents = (typeof se == "string"? se.split(" "): se);
			// we need to pre-bind these methods so they can easily be added
			// and removed as listeners later
			var h = this._handlers = enyo.clone(this._handlers);
			for (var e in h) {
				h[e] = this.bindSafely(h[e]);
			}
			sup.apply(this, arguments);
		};
	}),
	create: enyo.inherit(function (sup) {
		return function () {
			sup.apply(this, arguments);
			this.collectionChanged();
			this.selectionChanged();
		};
	}),
	observers: [
		{method: "selectionChanged", path: "multipleSelection"}
	],
	selectionChanged: function () {
		this.addRemoveClass(this.selectionClass, this.selection);
		this.addRemoveClass(this.multipleSelectionClass, this.multipleSelection && this.selection);
	},
	//*@public
	/**
		Destroys any existing children in the repeater and creates all new children
		based on the current data.
	*/
	reset: function () {
		// use the facaded dataset because this could be any
		// collection of records
		var dd = this.get("data");
		// destroy the client controls we might already have
		this.destroyClientControls();
		// and now we create new ones for each new record we have
		for (var i=0, r; (r=dd.at(i)); ++i) {
			this.add(r, i);
		}
		this.hasReset = true;
	},
	/**
		Refreshes each control in the dataset.
	*/
	refresh: function (immediate) {
		if (!this.hasReset) { return this.reset(); }
		var refresh = this.bindSafely(function () {
			var dd = this.get("data"),
				cc = this.getClientControls();
			for (var i=0, c, d; (d=dd.at(i)); ++i) {
				c = cc[i];
				if (c) {
					c.set("model", d);
				} else {
					this.add(d, i);
				}
			}
			this.prune();
		});

        // refresh is used as the event handler for
        // collection resets so checking for truthy isn't
        // enough. it must be true.
		if(immediate === true) {
			refresh();
		} else {
			this.startJob("refreshing", refresh, 16);
		}
	},
	//*@protected
	rendered: enyo.inherit(function (sup) {
		return function () {
			sup.apply(this, arguments);
			if (this.collection && this.collection.length) {
				this.reset();
			}
			this.hasRendered = true;
		};
	}),
	add: function (rec, i) {
		var c = this.createComponent({model: rec, index: i});
		if (this.generated && !this.batching) {
			c.render();
		}
	},
	remove: function (i) {
		var controls = this.getClientControls()
			, control;

		control = controls[i];

		if (control) control.destroy();
	},
	prune: function () {
		var g = this.getClientControls()
			, len = (this.collection? this.collection.length: 0)
			, x;
		if (g.length > len) {
			x = g.slice(len);
			for (var i=0, c; (c=x[i]); ++i) {
				c.destroy();
			}
		}
	},
	initContainer: function () {
		var ops = this.get("containerOptions"),
			nom = ops.name || (ops.name = this.containerName);
		this.createChrome([ops]);
		this.discoverControlParent();
		if (nom != this.containerName) {
			this.$[this.containerName] = this.$[nom];
		}
	},
	handlers: {onSelected: "childSelected", onDeselected: "childDeselected"},
	_handlers: {add: "modelsAdded", remove: "modelsRemoved", reset: "refresh", sort: "refresh", filter: "refresh"},
	collectionChanged: function (p) {
		var c = this.collection;
		if (typeof c == "string") {
			c = this.collection = enyo.getPath(c);
		}
		if (c) {
			this.initCollection(c, p);
		}
	},
	initCollection: function (c, p) {
		var e;
		if (c && c.addListener) {
			for (e in this._handlers) {
				c.addListener(e, this._handlers[e]);
			}
		}
		if (p && p.removeListener) {
			for (e in this._handlers) {
				p.removeListener(e, this._handlers[e]);
			}
		}
	},
	modelsAdded: function (sender, e, props) {
		if (sender === this.collection) this.refresh();

	// modelsAdded: function (c, e, props) {
		// if (c == this.collection) {
		// 	this.set("batching", true);
		// 	// note that these are indices when being added so they can be lazily
		// 	// instantiated
		// 	// for (var i=0, r; (!isNaN(r=props.records[i])); ++i) {
		// 	// 	this.add(c.at(r), r);
		// 	// }
		// 	this.set("batching", false);
		// }
	},
	modelsRemoved: function (sender) {
		if (sender === this.collection) this.refresh();
	},

	// modelsRemoved: function (c, e, props) {
	// 	if (c == this.collection) {
	// 		// unfortunately we need to remove these in reverse order
	// 		var idxs = enyo.keys(props.records);
	// 		for (var i=idxs.length-1, idx; (idx=idxs[i]); --i) {
	// 			this.remove(idx);
	// 			this.deselect(idx);
	// 		}
	// 	}
	// },
	batchingChanged: function (prev, val) {
		if (this.generated && false === val) {
			this.$[this.containerName].render();
			this.refresh(true);
		}
	},
	/**
		Calls _childForIndex()_, leaving for posterity.
	*/
	getChildForIndex: function (i) {
		return this.childForIndex(i);
	},
	/**
		Attempts to return the control representation of the data index.
		Returns the control or undefined if it could not be found or the
		index of out of bounds.
	*/
	childForIndex: function (i) {
		return this.$.container.children[i];
	},
	data: function () {
		return this.collection;
	},
	/**
		Consolidates selection logic and allows for deselection of a model
		that has already been removed from the collection
	*/
	_select: function (index, model, select) {
		if (!this.selection) {
			return;
		}

		var c = this.getChildForIndex(index),
			s = this._selection,
			i = enyo.indexOf(model, s);

		if (select) {
			if(i == -1) {
				if(!this.multipleSelection) {
					while (s.length) {
						i = this.collection.indexOf(s.pop());
						this.deselect(i);
					}
				}

				s.push(model);
			}
		} else {
			if(i >= 0) {
				s.splice(i, 1);
			}
		}

		if (c) {
			c.set("selected", select);
		}
		if (this.selectionProperty && model) {
			(s=this.selectionProperty) && model.set(s, select);
		}
		this.notifyObservers("selected");
	},
	//*@public
	/**
		Selects the item at the given index.
	*/
	select: function (index) {
		this._select(index, this.collection.at(index), true);
	},
	/**
		De-selects the item at the given index.
	*/
	deselect: function (index) {
		this._select(index, this.collection.at(index), false);
	},
	/**
		Returns a Boolean indicating whether the given model is selected.
	*/
	isSelected: function (model) {
		return !!~enyo.indexOf(model, this._selection);
	},
	/**
		Selects all items (if _multipleSelection_ is true).
	*/
	selectAll: function () {
		if (this.multipleSelection) {
			this.stopNotifications();
			var s = this._selection
				, len = this.collection? this.collection.length: 0;
			s.length = 0;
			for (var i=0; i<len; ++i) {
				this.select(i);
			}
			this.startNotifications();
		}
	},
	/**
		De-selects all items.
	*/
	deselectAll: function () {
		if (this.selection) {
			this.stopNotifications();
			var s = this._selection, m, i;
			while (s.length) {
				m = s.pop();
				i = this.collection.indexOf(m);
				this.deselect(i);
			}
			this.startNotifications();
		}
	},
	/**
		A computed property that returns the currently selected model
		(if _multipleSelection_ is false), or an immutable array of all currently
		selected models (if it is true).
	*/
	selected: function() {
		// to ensure that bindings will clear properly according to their api
		return (this.multipleSelection ? this._selection : this._selection[0]) || null;
	},
	//*@protected
	dataChanged: function () {
		if (this.collection && this.hasRendered) {
			this.reset();
		}
	},
	computed: [
		{method: "selected"},
		{method: "data", path: ["controller", "collection"]}
	],
	noDefer: true,
	childMixins: [enyo.RepeaterChildSupport],
	controlParentName: "container",
	containerName: "container",
	containerOptions: {name: "container", classes: "enyo-fill enyo-data-repeater-container"},
	batching: false,
	_selection: null
});

enyo.DataRepeater.concat = function (ctor, props) {
	var p = ctor.prototype || ctor;
	if (props.childMixins) {
		p.childMixins = (p.childMixins? enyo.merge(p.childMixins, props.childMixins): props.childMixins.slice());
		delete props.childMixins;
	}
};
<commit_msg>originally c74170485022bf4ce08f928aae4114cada157135<commit_after>//*@public
/**
		_enyo.DataRepeater_ iterates over the items in an
		[enyo.Collection](#enyo.Collection) to repeatedly render and
		synchronize  records (instances of [enyo.Model](#enyo.Model)) to its
		own children. For any record in the collection, a new child will be
		rendered in this repeater. If  the record is destroyed, the child will
		be destroyed. These controls will automatically update when the
		properties on the underlying record are modified if they have been
		bound using bindings (see [enyo.Binding](#enyo.Binding)).
*/
enyo.kind({
	name: "enyo.DataRepeater",
	//*@public
	/**
		Set this to true to allow selection support to be enabled. Default
		is true for single-selection. Note that selection stores a reference to
		the model that is selected.
	*/
	selection: true,
	/**
		Set this to true to allow multiple children to be selected simultaneously.
		If this is true, then the _selection_ property will be set to true even if
		it has previously been set to false.
	*/
	multipleSelection: false,
	/**
		This class will be applied to the repeater when _selection_ is enabled.
		The default is _selection-enabled_. If _multipleSelection_ is true, this
		class will also be applied.
	*/
	selectionClass: "selection-enabled",
	/**
		This class will be applied to the repeater when _multipleSelection_ is
		true. The default is _multiple-selection-enabled_. If _multipleSelection_
		is true, the _selectionClass_ will also be applied.
	*/
	multipleSelectionClass: "multiple-selection-enabled",
	/**
		In cases where selection should be detected from the state of the model,
		this property should be set to the property that the repeater should
		observe for changes. If the model changes, the repeater will reflect the
		change without needing to interact directly with the model. Note that this
		property must be a part of the model's schema or its changes will not be
		detected properly.
	*/
	selectionProperty: "",
	/**
		Set this to a space-delimited string of events or an array that can trigger
		the selection of a particular child. By default it is simply the _ontap_
		event. To prevent selection entirely see _selection_ and set it to `false`.
	*/
	selectionEvents: "ontap",
	/**
		Use this hash to define _defaultBindingProperties_ for _all_ children
		(even children of children) of this repeater. This can be eliminate the
		need to write the same paths many times. You can also use any	binding
		macros. Any property defined here will be superseded by the same property if
		defined for an individual binding.
	*/
	childBindingDefaults: null,
	//*@protected
	initComponents: function () {
		this.initContainer();
		var c = this.kindComponents || this.components || [],
			o = this.getInstanceOwner(),
			d = this.defaultProps? enyo.clone(this.defaultProps): (this.defaultProps = {});
		// ensure that children know who their binding owner is
		d.bindingTransformOwner = this;
		d.bindingDefaults = this.childBindingDefaults;
		if (c) {
			// if there are multiple components in the components block they will become nested
			// children of the default kind set for the repeater
			if (c.length > 1) {
				d.components = c;
			}
			// if there is only one child, the properties will be the default kind of the repeater
			else {
				enyo.mixin(d, c[0]);
			}
			d.repeater = this;
			d.owner = o;
			d.mixins = d.mixins? d.mixins.concat(this.childMixins): this.childMixins;
		}
	},
	constructor: enyo.inherit(function (sup) {
		return function () {
			this._selection = [];
			// we need to initialize our selectionEvents array
			var se = this.selectionEvents;
			this.selectionEvents = (typeof se == "string"? se.split(" "): se);
			// we need to pre-bind these methods so they can easily be added
			// and removed as listeners later
			var h = this._handlers = enyo.clone(this._handlers);
			for (var e in h) {
				h[e] = this.bindSafely(h[e]);
			}
			sup.apply(this, arguments);
		};
	}),
	create: enyo.inherit(function (sup) {
		return function () {
			sup.apply(this, arguments);
			this.collectionChanged();
			this.selectionChanged();
		};
	}),
	observers: [
		{method: "selectionChanged", path: "multipleSelection"}
	],
	selectionChanged: function () {
		this.addRemoveClass(this.selectionClass, this.selection);
		this.addRemoveClass(this.multipleSelectionClass, this.multipleSelection && this.selection);
	},
	//*@public
	/**
		Destroys any existing children in the repeater and creates all new children
		based on the current data.
	*/
	reset: function () {
		// use the facaded dataset because this could be any
		// collection of records
		var dd = this.get("data");
		// destroy the client controls we might already have
		this.destroyClientControls();
		// and now we create new ones for each new record we have
		for (var i=0, r; (r=dd.at(i)); ++i) {
			this.add(r, i);
		}
		this.hasReset = true;
	},
	/**
		Refreshes each control in the dataset.
	*/
	refresh: function (immediate) {
		if (!this.hasReset) { return this.reset(); }
		var refresh = this.bindSafely(function () {
			var dd = this.get("data"),
				cc = this.getClientControls();
			for (var i=0, c, d; (d=dd.at(i)); ++i) {
				c = cc[i];
				if (c) {
					c.set("model", d);
				} else {
					this.add(d, i);
				}
			}
			this.prune();
		});

		// refresh is used as the event handler for
		// collection resets so checking for truthy isn't
		// enough. it must be true.
		if(immediate === true) {
			refresh();
		} else {
			this.startJob("refreshing", refresh, 16);
		}
	},
	//*@protected
	rendered: enyo.inherit(function (sup) {
		return function () {
			sup.apply(this, arguments);
			if (this.collection && this.collection.length) {
				this.reset();
			}
			this.hasRendered = true;
		};
	}),
	add: function (rec, i) {
		var c = this.createComponent({model: rec, index: i});
		if (this.generated && !this.batching) {
			c.render();
		}
	},
	remove: function (i) {
		var controls = this.getClientControls()
			, control;

		control = controls[i];

		if (control) control.destroy();
	},
	prune: function () {
		var g = this.getClientControls()
			, len = (this.collection? this.collection.length: 0)
			, x;
		if (g.length > len) {
			x = g.slice(len);
			for (var i=0, c; (c=x[i]); ++i) {
				c.destroy();
			}
		}
	},
	initContainer: function () {
		var ops = this.get("containerOptions"),
			nom = ops.name || (ops.name = this.containerName);
		this.createChrome([ops]);
		this.discoverControlParent();
		if (nom != this.containerName) {
			this.$[this.containerName] = this.$[nom];
		}
	},
	handlers: {onSelected: "childSelected", onDeselected: "childDeselected"},
	_handlers: {add: "modelsAdded", remove: "modelsRemoved", reset: "refresh", sort: "refresh", filter: "refresh"},
	collectionChanged: function (p) {
		var c = this.collection;
		if (typeof c == "string") {
			c = this.collection = enyo.getPath(c);
		}
		if (c) {
			this.initCollection(c, p);
		}
	},
	initCollection: function (c, p) {
		var e;
		if (c && c.addListener) {
			for (e in this._handlers) {
				c.addListener(e, this._handlers[e]);
			}
		}
		if (p && p.removeListener) {
			for (e in this._handlers) {
				p.removeListener(e, this._handlers[e]);
			}
		}
	},
	modelsAdded: function (sender, e, props) {
		if (sender === this.collection) this.refresh();

	// modelsAdded: function (c, e, props) {
		// if (c == this.collection) {
		// 	this.set("batching", true);
		// 	// note that these are indices when being added so they can be lazily
		// 	// instantiated
		// 	// for (var i=0, r; (!isNaN(r=props.records[i])); ++i) {
		// 	// 	this.add(c.at(r), r);
		// 	// }
		// 	this.set("batching", false);
		// }
	},
	modelsRemoved: function (sender) {
		if (sender === this.collection) this.refresh();
	},

	// modelsRemoved: function (c, e, props) {
	// 	if (c == this.collection) {
	// 		// unfortunately we need to remove these in reverse order
	// 		var idxs = enyo.keys(props.records);
	// 		for (var i=idxs.length-1, idx; (idx=idxs[i]); --i) {
	// 			this.remove(idx);
	// 			this.deselect(idx);
	// 		}
	// 	}
	// },
	batchingChanged: function (prev, val) {
		if (this.generated && false === val) {
			this.$[this.containerName].render();
			this.refresh(true);
		}
	},
	/**
		Calls _childForIndex()_, leaving for posterity.
	*/
	getChildForIndex: function (i) {
		return this.childForIndex(i);
	},
	/**
		Attempts to return the control representation of the data index.
		Returns the control or undefined if it could not be found or the
		index of out of bounds.
	*/
	childForIndex: function (i) {
		return this.$.container.children[i];
	},
	data: function () {
		return this.collection;
	},
	/**
		Consolidates selection logic and allows for deselection of a model
		that has already been removed from the collection
	*/
	_select: function (index, model, select) {
		if (!this.selection) {
			return;
		}

		var c = this.getChildForIndex(index),
			s = this._selection,
			i = enyo.indexOf(model, s);

		if (select) {
			if(i == -1) {
				if(!this.multipleSelection) {
					while (s.length) {
						i = this.collection.indexOf(s.pop());
						this.deselect(i);
					}
				}

				s.push(model);
			}
		} else {
			if(i >= 0) {
				s.splice(i, 1);
			}
		}

		if (c) {
			c.set("selected", select);
		}
		if (this.selectionProperty && model) {
			(s=this.selectionProperty) && model.set(s, select);
		}
		this.notifyObservers("selected");
	},
	//*@public
	/**
		Selects the item at the given index.
	*/
	select: function (index) {
		this._select(index, this.collection.at(index), true);
	},
	/**
		De-selects the item at the given index.
	*/
	deselect: function (index) {
		this._select(index, this.collection.at(index), false);
	},
	/**
		Returns a Boolean indicating whether the given model is selected.
	*/
	isSelected: function (model) {
		return !!~enyo.indexOf(model, this._selection);
	},
	/**
		Selects all items (if _multipleSelection_ is true).
	*/
	selectAll: function () {
		if (this.multipleSelection) {
			this.stopNotifications();
			var s = this._selection
				, len = this.collection? this.collection.length: 0;
			s.length = 0;
			for (var i=0; i<len; ++i) {
				this.select(i);
			}
			this.startNotifications();
		}
	},
	/**
		De-selects all items.
	*/
	deselectAll: function () {
		if (this.selection) {
			this.stopNotifications();
			var s = this._selection, m, i;
			while (s.length) {
				m = s.pop();
				i = this.collection.indexOf(m);
				this.deselect(i);
			}
			this.startNotifications();
		}
	},
	/**
		A computed property that returns the currently selected model
		(if _multipleSelection_ is false), or an immutable array of all currently
		selected models (if it is true).
	*/
	selected: function() {
		// to ensure that bindings will clear properly according to their api
		return (this.multipleSelection ? this._selection : this._selection[0]) || null;
	},
	//*@protected
	dataChanged: function () {
		if (this.collection && this.hasRendered) {
			this.reset();
		}
	},
	computed: [
		{method: "selected"},
		{method: "data", path: ["controller", "collection"]}
	],
	noDefer: true,
	childMixins: [enyo.RepeaterChildSupport],
	controlParentName: "container",
	containerName: "container",
	containerOptions: {name: "container", classes: "enyo-fill enyo-data-repeater-container"},
	batching: false,
	_selection: null
});

enyo.DataRepeater.concat = function (ctor, props) {
	var p = ctor.prototype || ctor;
	if (props.childMixins) {
		p.childMixins = (p.childMixins? enyo.merge(p.childMixins, props.childMixins): props.childMixins.slice());
		delete props.childMixins;
	}
};
<|endoftext|>


<commit_before>/**
 * @author: Dennis Hernández
 * @webSite: http://djhvscf.github.io/Blog
 * @version: v1.0.0
 */

!function ($) {

    'use strict';

    var sprintf = function (str) {
        var args = arguments,
                flag = true,
                i = 1;

        str = str.replace(/%s/g, function () {
            var arg = args[i++];

            if (typeof arg === 'undefined') {
                flag = false;
                return '';
            }
            return arg;
        });
        return flag ? str : '';
    };

    var getFieldIndex = function (columns, field) {
        var index = -1;

        $.each(columns, function (i, column) {
            if (column.field === field) {
                index = i;
                return false;
            }
            return true;
        });
        return index;
    };

    var calculateObjectValue = function (self, name, args, defaultValue) {
        if (typeof name === 'string') {
            // support obj.func1.func2
            var names = name.split('.');

            if (names.length > 1) {
                name = window;
                $.each(names, function (i, f) {
                    name = name[f];
                });
            } else {
                name = window[name];
            }
        }
        if (typeof name === 'object') {
            return name;
        }
        if (typeof name === 'function') {
            return name.apply(self, args);
        }
        return defaultValue;
    };

    $.extend($.fn.bootstrapTable.defaults, {
        filterControl: false,
        onColumnSearch: function (field, text) {
            return false;
        }
    });

    $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
        filterControl: undefined,
        filterData: undefined
    });

    $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
        'column-search.bs.table': 'onColumnSearch'
    });

    var BootstrapTable = $.fn.bootstrapTable.Constructor,
            _initHeader = BootstrapTable.prototype.initHeader,
            _initBody = BootstrapTable.prototype.initBody,
            _initSearch = BootstrapTable.prototype.initSearch;

    BootstrapTable.prototype.initHeader = function () {
        _initHeader.apply(this, Array.prototype.slice.apply(arguments));

        if (!this.options.filterControl) {
            return;
        }

        var addedFilterControl = false,
                that = this,
                isVisible,
                html,
                timeoutId = 0;

        $.each(this.options.columns, function (i, column) {
            isVisible = 'hidden';
            html = [];

            if (!column.filterControl) {
                html.push('

');
            } else {
                html.push('
');

                if (column.filterControl && column.searchable) {
                    addedFilterControl = true;
                    isVisible = 'visible'
                }
                switch (column.filterControl.toLowerCase()) {
                    case 'input' :
                        html.push(sprintf('<input type="text" class="form-control" style="width: 100%; visibility: %s">', isVisible));
                        break;
                    case 'select':
                        html.push(sprintf('<select class="%s form-control" style="width: 100%; visibility: %s"></select>',
                                column.field, isVisible));
                        break;
                }
            }

            that.$header.find(sprintf('.th-inner:contains("%s")', column.title)).next().append(html.join(''));
            if (column.filterData !== undefined && column.filterData.toLowerCase() !== 'column') {
                var filterDataType = column.filterData.substring(0, 3);
                var filterDataSource = column.filterData.substring(4, column.filterData.length);
                var selectControl = $('.' + column.field);
                selectControl.append($("<option></option>")
                        .attr("value", '')
                        .text(''));
                switch (filterDataType) {
                    case 'url':
                        $.ajax({
                            url: filterDataSource,
                            dataType: 'json',
                            success: function (data) {
                                $.each(data, function (key, value) {
                                    selectControl.append($("<option></option>")
                                            .attr("value", key)
                                            .text(value));
                                });
                            }
                        });
                        break;
                    case 'var':
                        var variableValues = window[filterDataSource];
                        for (var key in variableValues) {
                            selectControl.append($("<option></option>")
                                    .attr("value", key)
                                    .text(variableValues[key]));
                        }
                        ;
                        break;
                }
            }
        });

        if (addedFilterControl) {
            this.$header.off('keyup', 'input').on('keyup', 'input', function (event) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    that.onColumnSearch(event);
                }, that.options.searchTimeOut);
            });

            this.$header.off('change', 'select').on('change', 'select', function (event) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    that.onColumnSearch(event);
                }, that.options.searchTimeOut);
            });
        } else {
            this.$header.find('.filterControl').hide();
        }
    };

    BootstrapTable.prototype.initBody = function () {
        _initBody.apply(this, Array.prototype.slice.apply(arguments));

        var that = this,
                data = this.getData();

        for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
            var key,
                    item = data[i];

            $.each(this.header.fields, function (j, field) {
                var value = item[field],
                        column = that.options.columns[getFieldIndex(that.options.columns, field)];

                value = calculateObjectValue(that.header,
                        that.header.formatters[j], [value, item, i], value);

                if ((!column.checkbox) || (!column.radio)) {
                    if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'select'
                            && column.searchable) {

                        if (column.filterData === undefined || column.filterData.toLowerCase() === 'column') {
                            var selectControl = $('.' + column.field),
                                    iOpt = 0,
                                    exitsOpt = false,
                                    options;
                            if (selectControl !== undefined) {
                                options = selectControl.get(0).options;

                                if (options.length === 0) {

                                    //Added the default option
                                    selectControl.append($("<option></option>")
                                            .attr("value", '')
                                            .text(''));

                                    selectControl.append($("<option></option>")
                                            .attr("value", value)
                                            .text(value));
                                } else {
                                    for (; iOpt < options.length; iOpt++) {
                                        if (options[iOpt].value === value) {
                                            exitsOpt = true;
                                            break;
                                        }
                                    }

                                    if (!exitsOpt) {
                                        selectControl.append($("<option></option>")
                                                .attr("value", value)
                                                .text(value));
                                    }
                                }
                            }
                        }
                    }
                }
            });
        }
    };

    BootstrapTable.prototype.initSearch = function () {
        _initSearch.apply(this, Array.prototype.slice.apply(arguments));

        var that = this;
        var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;

        //Check partial column filter
        this.data = fp ? $.grep(this.data, function (item, i) {
            for (var key in fp) {
                var fval = fp[key].toLowerCase();
                var value = item[key];
                value = calculateObjectValue(that.header,
                        that.header.formatters[$.inArray(key, that.header.fields)],
                        [value, item, i], value);

                if (!($.inArray(key, that.header.fields) !== -1 &&
                        (typeof value === 'string' || typeof value === 'number') &&
                        (value + '').toLowerCase().indexOf(fval) !== -1)) {
                    return false;
                }
            }
            return true;
        }) : this.data;
    };

    BootstrapTable.prototype.onColumnSearch = function (event) {
        var text = $.trim($(event.currentTarget).val());
        var $field = $(event.currentTarget).parent().parent().parent().data('field')

        if ($.isEmptyObject(this.filterColumnsPartial)) {
            this.filterColumnsPartial = {};
        }
        if (text) {
            this.filterColumnsPartial[$field] = text;
        } else {
            delete this.filterColumnsPartial[$field];
        }

        this.options.pageNumber = 1;
        this.onSearch(event);
        this.updatePagination();
        this.trigger('column-search', $field, text);
    };
}(jQuery);
<commit_msg>Update bootstrap-table-filter-control.js<commit_after>/**
 * @author: Dennis Hernández
 * @webSite: http://djhvscf.github.io/Blog
 * @version: v1.0.0
 */

!function ($) {

    'use strict';

    var sprintf = function (str) {
        var args = arguments,
            flag = true,
            i = 1;

        str = str.replace(/%s/g, function () {
            var arg = args[i++];

            if (typeof arg === 'undefined') {
                flag = false;
                return '';
            }
            return arg;
        });
        return flag ? str : '';
    };

    var getFieldIndex = function (columns, field) {
        var index = -1;

        $.each(columns, function (i, column) {
            if (column.field === field) {
                index = i;
                return false;
            }
            return true;
        });
        return index;
    };

    var calculateObjectValue = function (self, name, args, defaultValue) {
        if (typeof name === 'string') {
            // support obj.func1.func2
            var names = name.split('.');

            if (names.length > 1) {
                name = window;
                $.each(names, function (i, f) {
                    name = name[f];
                });
            } else {
                name = window[name];
            }
        }
        if (typeof name === 'object') {
            return name;
        }
        if (typeof name === 'function') {
            return name.apply(self, args);
        }
        return defaultValue;
    };

    $.extend($.fn.bootstrapTable.defaults, {
        filterControl: false,
        onColumnSearch: function (field, text) {
            return false;
        }
    });

    $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
        filterControl: undefined,
        filterData: undefined
    });

    $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
        'column-search.bs.table': 'onColumnSearch'
    });

    var BootstrapTable = $.fn.bootstrapTable.Constructor,
            _initHeader = BootstrapTable.prototype.initHeader,
            _initBody = BootstrapTable.prototype.initBody,
            _initSearch = BootstrapTable.prototype.initSearch;

    BootstrapTable.prototype.initHeader = function () {
        _initHeader.apply(this, Array.prototype.slice.apply(arguments));

        if (!this.options.filterControl) {
            return;
        }

        var addedFilterControl = false,
                that = this,
                isVisible,
                html,
                timeoutId = 0;

        $.each(this.options.columns, function (i, column) {
            isVisible = 'hidden';
            html = [];

            if (!column.filterControl) {
                html.push('

');
            } else {
                html.push('
');

                if (column.filterControl && column.searchable) {
                    addedFilterControl = true;
                    isVisible = 'visible'
                }
                switch (column.filterControl.toLowerCase()) {
                    case 'input' :
                        html.push(sprintf('<input type="text" class="form-control" style="width: 100%; visibility: %s">', isVisible));
                        break;
                    case 'select':
                        html.push(sprintf('<select class="%s form-control" style="width: 100%; visibility: %s"></select>',
                                column.field, isVisible));
                        break;
                }
            }

            that.$header.find(sprintf('.th-inner:contains("%s")', column.title)).next().append(html.join(''));
            if (column.filterData !== undefined && column.filterData.toLowerCase() !== 'column') {
                var filterDataType = column.filterData.substring(0, 3);
                var filterDataSource = column.filterData.substring(4, column.filterData.length);
                var selectControl = $('.' + column.field);
                selectControl.append($("<option></option>")
                        .attr("value", '')
                        .text(''));
                switch (filterDataType) {
                    case 'url':
                        $.ajax({
                            url: filterDataSource,
                            dataType: 'json',
                            success: function (data) {
                                $.each(data, function (key, value) {
                                    selectControl.append($("<option></option>")
                                            .attr("value", key)
                                            .text(value));
                                });
                            }
                        });
                        break;
                    case 'var':
                        var variableValues = window[filterDataSource];
                        for (var key in variableValues) {
                            selectControl.append($("<option></option>")
                                    .attr("value", key)
                                    .text(variableValues[key]));
                        }
                        ;
                        break;
                }
            }
        });

        if (addedFilterControl) {
            this.$header.off('keyup', 'input').on('keyup', 'input', function (event) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    that.onColumnSearch(event);
                }, that.options.searchTimeOut);
            });

            this.$header.off('change', 'select').on('change', 'select', function (event) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    that.onColumnSearch(event);
                }, that.options.searchTimeOut);
            });
        } else {
            this.$header.find('.filterControl').hide();
        }
    };

    BootstrapTable.prototype.initBody = function () {
        _initBody.apply(this, Array.prototype.slice.apply(arguments));

        var that = this,
                data = this.getData();

        for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
            var key,
                    item = data[i];

            $.each(this.header.fields, function (j, field) {
                var value = item[field],
                        column = that.options.columns[getFieldIndex(that.options.columns, field)];

                value = calculateObjectValue(that.header,
                        that.header.formatters[j], [value, item, i], value);

                if ((!column.checkbox) || (!column.radio)) {
                    if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'select'
                            && column.searchable) {

                        if (column.filterData === undefined || column.filterData.toLowerCase() === 'column') {
                            var selectControl = $('.' + column.field),
                                    iOpt = 0,
                                    exitsOpt = false,
                                    options;
                            if (selectControl !== undefined) {
                                options = selectControl.get(0).options;

                                if (options.length === 0) {

                                    //Added the default option
                                    selectControl.append($("<option></option>")
                                            .attr("value", '')
                                            .text(''));

                                    selectControl.append($("<option></option>")
                                            .attr("value", value)
                                            .text(value));
                                } else {
                                    for (; iOpt < options.length; iOpt++) {
                                        if (options[iOpt].value === value) {
                                            exitsOpt = true;
                                            break;
                                        }
                                    }

                                    if (!exitsOpt) {
                                        selectControl.append($("<option></option>")
                                                .attr("value", value)
                                                .text(value));
                                    }
                                }
                            }
                        }
                    }
                }
            });
        }
    };

    BootstrapTable.prototype.initSearch = function () {
        _initSearch.apply(this, Array.prototype.slice.apply(arguments));

        var that = this;
        var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;

        //Check partial column filter
        this.data = fp ? $.grep(this.data, function (item, i) {
            for (var key in fp) {
                var fval = fp[key].toLowerCase();
                var value = item[key];
                value = calculateObjectValue(that.header,
                        that.header.formatters[$.inArray(key, that.header.fields)],
                        [value, item, i], value);

                if (!($.inArray(key, that.header.fields) !== -1 &&
                        (typeof value === 'string' || typeof value === 'number') &&
                        (value + '').toLowerCase().indexOf(fval) !== -1)) {
                    return false;
                }
            }
            return true;
        }) : this.data;
    };

    BootstrapTable.prototype.onColumnSearch = function (event) {
        var text = $.trim($(event.currentTarget).val());
        var $field = $(event.currentTarget).parent().parent().parent().data('field')

        if ($.isEmptyObject(this.filterColumnsPartial)) {
            this.filterColumnsPartial = {};
        }
        if (text) {
            this.filterColumnsPartial[$field] = text;
        } else {
            delete this.filterColumnsPartial[$field];
        }

        this.options.pageNumber = 1;
        this.onSearch(event);
        this.updatePagination();
        this.trigger('column-search', $field, text);
    };
}(jQuery);
<|endoftext|>