common.js 12.7 KB
var hash_interpreted = false;

var common = {};

$(function () {
    "use strict";
    var tabs = $('.tabs');
    tabs.tabs({
        show: function () {
            if (hash_interpreted)
                update_hash();
        }
    });
    $('button').button();
    $('input.datepicker').datepicker($.datepicker.regional.pl);
    $(document).on('mouseover', '.ui-state-default', function () {
        $(this).addClass('ui-state-hover');
    });
    $(document).on('mouseout', '.ui-state-default', function () {
        $(this).removeClass('ui-state-hover');
    });
    if ($dj.paginer || tabs.length > 0) {
        $(window).bind('hashchange', function () {
            var hash = location.hash.substr(1);
            interpret_hash(hash);
            hash_interpreted = true;
        });
        if (!$dj.paginer)
            $(window).trigger('hashchange');
    }
});

$.fn.disable = function () {
    "use strict";
    return this.prop('disabled', true);
};

$.fn.enable = function () {
    "use strict";
    return this.prop('disabled', false);
};

$.fn.value = function () {
    "use strict";
    if (this.is(':checkbox'))
        return this.prop('checked');
    else if (this.is(':radio'))
        return this.prop('checked') ? this.val() : null;
    else
        return this.val();
};

$.fn.bind_hover = function (c) {
    "use strict";
    var elem = this;
    this.hover(
        function () {
            elem.addClass(c);
        },
        function () {
            elem.removeClass(c);
        }
    );
};

// skopiowane z http://jsfiddle.net/DkHyd/
$.fn.togglepanels = function () {
    "use strict";
    return this.each(function () {
        $(this).addClass("ui-accordion ui-accordion-icons ui-widget ui-helper-reset")
            .find("h3")
            .addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-top ui-corner-bottom")
            .hover(function () {
                $(this).toggleClass("ui-state-hover");
            })
            .prepend('<span class="ui-icon ui-icon-triangle-1-e"></span>')
            .click(function () {
                $(this)
                    .toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom")
                    .find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end()
                    .next().slideToggle();
                return false;
            })
            .next()
            .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom")
            .hide();
    });
};

function multiselect_toggle(select_el, option_value, enable) {
    "use strict";
    var select, widget, option;
    select = $(select_el);
    widget = select.multiselect2("widget");
    option = widget.find('[value="' + option_value + '"]');
    if (enable)
        option.enable();
    else
        option.disable();
    option.parent().toggleClass('ui-state-disabled', !enable);
    option.parent().parent().toggleClass('ui-multiselect-disabled', !enable);
}
common.multiselect_toggle = multiselect_toggle;

function multiselect_enable(select_el, option_value) {
    "use strict";
    var select, widget, option;
    select = $(select_el);
    widget = select.multiselect2("widget");
    option = widget.find('[value="' + option_value + '"]');
    option.enable();
    option.parent().removeClass('ui-state-disabled');
    option.parent().parent().removeClass('ui-multiselect-disabled');
}
common.multiselect_enable = multiselect_enable;

function error_alert(text) {
    "use strict";
    window.alert(text);
}
common.error_alert = error_alert;

// parametry: method, url, data
// description, dest, callback, callback_args
$.ajaxJSON = function (params) {
    "use strict";
    var encoded_data = {};
    if (params.save && !before_save())
        return false;
    if (params.async === undefined)
        params.async = true;
    $.each(params.data, function (key, value) {
        encoded_data[key] = $.toJSON(value);
    });
    if (params.async === true) {
        $.ajax({
            type: params.method,
            url: params.url,
            dataType: 'json',
            data: encoded_data,
            success: parse_result(params),
            error: params.error_callback
        });
        return true;
    } else {
        return $.parseJSON($.ajax({
            type: params.method,
            url: params.url,
            dataType: 'json',
            data: encoded_data,
            async: false
        }).responseText);
    }
};

function blank(str) {
    "use strict";
    var re = /^[\t\n ]*$/;
    return re.test(str);
}
common.blank = blank;

function strip(str) {
    "use strict";
    return str.replace(/^\s+|\s+$/g, '');
}
common.strip = strip;

// parametry: description, dest, callback, callback_args
function parse_result(params) {
    "use strict";
    return function (data, status) {
        if (data.result !== 'ok' || status === 'error') {
            if (data.result === 'logout')
                error_alert("Sesja wygasła - zaloguj się i spróbuj ponownie.");
            else if (!params.bad_data_callback || params.bad_data_callback(data.result)) {
                var msg = params.description + ' ' + "nie powiodło się:\n";
                msg += data.result;
                error_alert(msg);
            }
        }
        else { // OK
            if (params.dest) {
                params.dest.html(data.html);
            }
            if (params.callback) {
                if (!params.callback_args)
                    params.callback_args = [];
                var args = [data].concat(params.callback_args);
                params.callback.apply({}, args);
            }
        }
    };
}

function debug(content) {
    "use strict";
    var doc = $('#debug').contents().get(0);
    doc.open();
    doc.writeln(content);
    doc.close();
}

$(function () {
    "use strict";
    var debug = $('#debug'), main_menu = $('#main_menu');
    $('#show-debug').click(function () {
        debug.toggle();
    });
    debug.height($(window).height() - main_menu.height());
    debug.css('top', main_menu.height());
});

function parse_error(event, request, settings) {
    "use strict";
    debug(request.responseText);
    $('#show-debug').show();
}

//$.ajaxSetup({global: true, error: parse_error});

$(function () {
    "use strict";
    $('#debug').ajaxError(parse_error);
});

$('html').ajaxSend(function (event, xhr, settings) {
    "use strict";
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }

    if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
        // Only send the token to relative URLs i.e. locally.
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});

// http://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/2117698#2117698
(function ($) {
    "use strict";
    $.fn.textMetrics = function () {
        var h, w, el = this;
        var div = document.createElement('div');
        document.body.appendChild(div);
        $(div).css({
            position: 'absolute',
            left: -1000,
            top: -1000,
            display: 'none'
        });
        $(div).html($(el).html());
        var styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
        $(styles).each(function () {
            var s = this.toString();
            $(div).css(s, $(el).css(s));
        });
        h = $(div).outerHeight();
        w = $(div).outerWidth();
        $(div).remove();
        return {
            height: h,
            width: w
        };
    };
})(jQuery);

function update_hash() {
    "use strict";
    var new_hash = make_hash();
    old_hash = new_hash;
    location.href = '#' + new_hash;
}
common.update_hash = update_hash;

function make_hash() {
    "use strict";
    var bottom_tabs, tabs, tab_path = [], query, id, data, original_data;
    var paginer_el;
    var are_tabs = $('.tabs').length > 0;
    if (are_tabs) {
        tabs = $('.tabs:visible').first();
        while (tabs.find('.tabs:visible').length > 0) {
            tabs = tabs.find('.tabs:visible').first();
        }
        bottom_tabs = tabs;
        do {
            tab_path.unshift(tabs.children('.ui-tabs-panel:visible')[0].id);
            tabs = tabs.parents('.tabs').first();
        } while (tabs.length > 0);
    } else
        tab_path = [''];
    paginer_el = $('.paginer:visible', bottom_tabs);
    if (paginer_el.length > 0) {
        id = paginer_el[0].id;
        data = $dj.paginer[id][1];
        original_data = $dj.original_paginer[id][1];
        query = [];
        if (data.order_by !== original_data.order_by)
            query.push('order_by=' + data.order_by);
        $.each(data.filters, function (i, filter) {
            if (i >= original_data.filters.length)
                query.push(filter[0] + '-' + filter[1] + '=' + filter[2]);
        });
        if (paginer.get_page_number(id) > 1)
            query.push('page=' + paginer.get_page_number(id));
        tab_path.push(query.join('&'));
    } else
        tab_path.push('');
    return tab_path.join('/');
}

var old_hash = 'not gonna happen';

function interpret_hash(hash) {
    "use strict";
    var data = hash.split('/'), children;
    if (hash === old_hash)
        return;
    var id, paginer_data, original_data, new_order_by, new_filters, new_page;
    var paginer_container, paginer_el;
    if (hash !== '')
        $.each(data.slice(0, data.length - 1), function (i, part) {
            if (part)
                $('#' + part).parents('.tabs').first().tabs('select', '#' + part);
        });
    else {
        paginer_container = $('.ui-tabs-panel').first();
        //hash_interpreted = false; // HACK
        while (paginer_container.length > 0) {
            paginer_container.parents('.tabs').first().tabs(
                'select', '#' + paginer_container[0].id);
            children = $('.ui-tabs-panel', paginer_container);
            if (children.length > 0)
                paginer_container = children.first();
            else
                paginer_container = children;
        }
        hash_interpreted = true; // HACK
    }
    if (window.paginer) {
        if (data[0] !== '')
            paginer_container = $('#' + data[data.length - 2]);
        else { // nie ma tabów (lub pusty hash...)
            paginer_container = $(document.body);
            do {
                children = $('.ui-tabs-panel:visible', paginer_container);
                if (children.length)
                    paginer_container = children[0];
            } while (children.length);
        }
        paginer_el = $('.paginer', paginer_container);
        if (paginer_el.length > 0) {
            id = paginer_el[0].id;
            paginer_data = $dj.paginer[id][1];
            original_data = $dj.original_paginer[id][1];
            new_order_by = original_data.order_by;
            new_page = 1;
            new_filters = $.extend([], original_data.filters);
            if (data[data.length - 1])
                $.each(data[data.length - 1].split('&'), function (i, pair) {
                    if (pair) {
                        var p = pair.split('=', 2);
                        var field_lookup = p[0].split('-', 2), value = p[1];
                        var field = field_lookup[0], lookup = field_lookup[1];
                        if (value === 'false')
                            value = false;
                        if (value === 'true')
                            value = true; // nieodporne na tekstowe filtry (jeśli będą)
                        if (p[0] === 'order_by') {
                            new_order_by = value;
                        } else if (p[0] === 'page') {
                            new_page = window.parseInt(value);
                        } else { // jakieś sprawdzanie poprawności? w sumie serwer to zrobi...
                            new_filters.push([field, lookup, value]);
                        }
                    }
                });
            paginer_data.order_by = new_order_by;
            paginer_data.filters = new_filters;
            paginer.page_numbers[id] = new_page;
            paginer.update_list(id, true); // protect hash
            paginer.show_order(id);
            paginer.reload_panel(id);
        }
    }
    old_hash = hash;
}