
/**
 * Extension of Array prototype that adds indexOf method to Array objects.
 */
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(searchElement /*, fromIndex */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (len === 0)
      return -1;

    var n = 0;
    if (arguments.length > 0)
    {
      n = Number(arguments[1]);
      if (n !== n) // shortcut for verifying if it's NaN
        n = 0;
      else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
        n = (n > 0 || -1) * Math.floor(Math.abs(n));
    }

    if (n >= len)
      return -1;

    var k = n >= 0
          ? n
          : Math.max(len - Math.abs(n), 0);

    for (; k < len; k++)
    {
      if (k in t && t[k] === searchElement)
        return k;
    }
    return -1;
  };
}


/**
* Logging function
*/
function log(msg) { if (console != undefined && 'log' in console) console.log(msg); }


/**
 * jQuery plugin that fixes Image onload event.
 */
//(function ($) {
//    $.event.special.load = {
//        add: function (hollaback) {
//            if ( this.nodeType === 1 && this.tagName.toLowerCase() === 'img' && this.src !== '' ) {
//                // Image is already complete, fire the hollaback (fixes browser issues were cached
//                // images isn't triggering the load event)
//                if ( this.complete || this.readyState === 4 ) {
//                    hollaback.handler.apply(this);
//                }
//
//                // Check if data URI images is supported, fire 'error' event if not
//                else if ( this.readyState === 'uninitialized' && this.src.indexOf('data:') === 0 ) {
//                    $(this).trigger('error');
//                }
//
//                else {
//                    $(this).bind('load', hollaback.handler);
//                }
//            }
//        }
//    };
//}(jQuery));


/**
 * Image preload plugin.
 */
(function($) {
    var cache = [];

    // Arguments are image paths relative to the current page.
    $.deco_preload_img = function() {
        var args_len = arguments.length;
        for (var i = args_len; i--;) {
            var cache_img = document.createElement('img');
            cache_img.src = arguments[i];
            cache.push(cache_img);
        }
    }
})(jQuery);


/**
 * Language change plugin for sites that load pages using AJAX.
 */
(function($) {

    function LangChange(root) {
        this.root = root;
        
        $(root).find('a').click(function() {
            window.location = $(this).attr('href') + window.location.hash;
            return false;
        });
    }

    // Get current language code
    LangChange.prototype.get_language = function() {
        return window.location.pathname.split('/')[1];
    };


    $.fn.deco_lang_change = function(options) {
        var langch_obj = this.eq(0).data('deco_langch');
        if (langch_obj)
            return langch_obj;
        
        return this.each(function() {
            $(this).data('deco_langch', new LangChange(this));
        });
    }

    $.deco_lang_change = {
        get_language: LangChange.prototype.get_language
    }

})(jQuery);



(function($) {


    /**
     * Plugin for opening links in new window.
     */
    $.fn.deco_new_window = function(options) {
        return this.each(function() {
           $(this).click(function() {
                window.open($(this).attr('href'));
                return false;
            });
        });
    };


    /**
     * Plugin for dynamic and asynchronous page loading.
     */
    $.deco_ajax = (function() {
        var self = {};

        /**
         * public
         */

        self.init = function(options) {
            self.opts = $.extend({}, $.deco_ajax.defaults, options);
            self.page_data = null;
            self.$container = self.opts.page_container;
            self.$loader = $('<iframe name="page-loader" id="page-loader" class="hidden" />');
            self.base_title = $.address.title();
            self.base_page_class = self.$container.children('.p').attr('class');

            self.$container.children('.p').eq(0).addClass('active');
            $('<div></div>')
                .appendTo(self.$container)
                .addClass(self.base_page_class);

            self.$container.bind('can_load.deco_ajax', self.load_page);

            self.$loader.appendTo($('body'));
            self.$loader.load(self.onload);
            self.loader = window.frames['page-loader']

            $.address.change(self.on_address_change);
        };

        self.active_page = function() { return self.$container.children('.active'); }
        self.hidden_page = function() { return self.$container.children(':not(.active)'); }

        // Return current page id
        self.page_id = function() {
            return self.get_page_id($.address.path());
        }

        // trigger can_load event, call it in before_load callback to inform that you've done.
        self.trigger_can_load = function(url) {
            self.$container.trigger('can_load.deco_ajax', [url]);
        }


        /**
         * private
         */

        self.get_page_id = function(url) {
            var split = url.split('/');

            if (split[split.length-1] == '')
                split.pop()

            return split[split.length-1];
        }

        self.on_address_change = function(event) {
            self.opts.before_load(self.$container, event.value);
        };

        self.before_load = function(url) {
            self.trigger_can_load(url);
        };

        self.load_page = function(event, url) {
            var current_lang = $.deco_lang_change.get_language();
            var lang_prefix = '';

            if (current_lang)
                lang_prefix = '/' + current_lang;

            if (url == '/') {
                self.loader.location.replace(lang_prefix + '/fpcontent/');
            }
            else {
                var page_id = Number(self.get_page_id(url));
                self.loader.location.replace(lang_prefix + '/pcontent/' + (isNaN(page_id) ? 0 : page_id) + '/');
            }
        };

        self.onload = function() {
            var $cnt = self.$container;
            var $hidden = self.hidden_page();
            var $active = self.active_page();
            var pcontent = self.$loader.contents().find('body').html();
            var $pdata = self.$loader.contents().find('#page-data');

            var current_data = self.page_data;
            var new_data = {};

            $pdata.children().each(function() {
                var $item = $(this);
                new_data[$item.attr('class')] = $item.text();
            });

            $hidden.html(pcontent);
            $hidden.removeClass().addClass(self.base_page_class + ' ' + new_data.type);

            if (new_data.title)
                $.address.title(self.base_title + self.opts.title_separator + new_data.title);
            else
                $.address.title(self.base_title);


            if (self.opts.after_load) {
                self.opts.after_load($cnt, current_data, new_data);
            }
            else {
                $cnt
                    .one('can_show.deco_ajax', function() {
                        $hidden
                            .fadeIn(self.opts.fadein_speed, function() {
                                self.opts.after_show($cnt, current_data, new_data)
                            })
                            .addClass('active');
                        $active
                            .removeClass('active');
                    })
                    .one('can_hide.deco_ajax', function() {
                        $active
                            .fadeOut(self.opts.fadeout_speed, function() {
                                $('body').removeClass().addClass(new_data.type);
                                self.opts.after_hide($cnt, current_data, new_data);
                            });
                    });

                self.opts.before_hide($cnt, current_data, new_data);
            }

            self.page_data = new_data;
        }

        return self;
    })();

    $.deco_ajax.defaults = {
        page_container: $('#cnt'),
        title_separator: ' - ',
        before_load: function($cnt, url) {              // called before asynchronous request is sent.
            $cnt.trigger('can_load.deco_ajax', [url]);
        },
        after_load: null,                               // called after page content is completely loaded, use it to
                                                        // completely override page change logic and default animations.
        before_hide: function($cnt, opage, npage) {     // called after page content is loaded but before current page is hidden.
            $cnt.trigger('can_hide.deco_ajax');
        },    
        after_hide: function($cnt, opage, npage) {      // after current page is hidden but before new one is shown
            $cnt.trigger('can_show.deco_ajax');
        },
        after_show: function($cnt, opage, npage) {},    // called after new page is shown (showing animation is complete)
        fadein_speed: 'normal',
        fadeout_speed: 'normal'
    };


    /**
     * Inline gallery plugin.
     *
     * Expected HTML markup:
     * <outer_element>
     *  <inner_element> [collection of photos (any structure)] </inner_element>
     * </outer_element>
     *
     * Usage: $('outer_element').deco_gallery({ ... })
     */
    $.fn.deco_gallery = function(options) {
        var opts = $.extend({}, $.fn.deco_gallery.defaults, options);
        var $thumbs = opts.thumbs;

        return this.each(function() {
            var $outer = $(this);
            var $photos = opts.photos ? $outer.children(':first').find(opts.photos)
                                      : $outer.children(':first').children();
            init();

            function init() {
                $thumbs.click(function() {
                    var index = $thumbs.index($(this));
                    show_photo(index);
                    return false;
                });

                if (opts.prev_next) setup_prevnext();
            }

            function setup_prevnext() {
                $('<div class="nav prev"><span></span></div>')
                    .appendTo($outer)
                    .hide()
                    .click(function() { show_photo(current_photo() - 1); });
                $('<div class="nav next"><span></span></div>')
                    .appendTo($outer)
                    .click(function() { show_photo(current_photo() + 1); });
            }

            function show_photo(index) {
                var $nav = $outer.children('.nav');

                if (index < 0 || index >= $photos.size())
                    return;
                if (index == current_photo())
                    return;

                var $next_photo = $photos.eq(index);

                if (opts.prev_next) {
                    if (index == 0)
                        $nav.filter('.prev').hide()
                    else
                        $nav.filter('.prev:not(:visible)').show();
                    if (index == $photos.size()-1)
                        $nav.filter('.next').hide()
                    else
                        $nav.filter('.next:not(:visible)').show();
                }

                $thumbs.removeClass('active').eq(index).addClass('active');

                $photos.filter(':visible').fadeOut(1000);
                $photos.eq(index).fadeIn(1000);
                opts.after_change($next_photo);
            }

            function current_photo() {
                return $photos.index($photos.filter(':visible'))
            }
        });
    };
    $.fn.deco_gallery.defaults = {
        photos: '',         // selector for photos if should be something else than all children
        thumbs: $(),        // jQuery collection containing thumbnails
        prev_next: true,    // prev_next functionality disabled/enabled
        after_change: function($nphoto) {} // photo after change callback
    };


    
    /**
     * Dropdown menu plugin
     */
    var menuitem = null;
    var menuactive = null;
    $.fn.deco_dropmenu = function(options) {
        var functions = {
            activate_page: function(id) {
                var $menu = $(this).eq(0);

                $menu
                    .find('li.active ul')
                        .stop().animate({ opacity: 0 }, 500).css('display', 'none')
                    .end().find('li.active')
                        .removeClass('active');

                if (id) {
                    var $li = $menu.find('#p-'+id);
                    $li.parentsUntil('#menu').andSelf()
                        .filter('li')
                            .addClass('active')
                        .end().filter('ul')
                            .stop().animate({ opacity: 1 }, 500).css('display', 'block');

                    menuitem = $menu.find('li.active > ul').eq(0);
                    if ($li.parentsUntil('#menu').filter('ul').length)
                        menuactive = $li;
                    else
                        menuactive = null;
                } else {
                    menuitem = null;
                    menuactive = null;
                }
            }
        };


        if (typeof options == "string") {
            functions[options].apply($(this).get(0), $.makeArray(arguments).slice(1));
        } else
            return setup(this);


        function setup(jqcollection) {
        var opts = $.extend({}, $.fn.deco_dropmenu.defaults, options);

        return jqcollection.each(function() {
            var closetimer = 0;
            var $menu = $(this);
            var $active = $();


            function init() {
                var $action_items = $menu.children('li');
                if (opts.active_stay_expanded)
                    $action_items = $action_items.not('.active');

                $menu.find('a ~ ul').prevAll('a').click(function() { return false; });
                $menu.children('li').hoverIntent({
                    over: jsddm_open,
                    out: jsddm_timer,
                    interval: opts.show_timeout
                });

                $(document).click(jsddm_close);

                $menu.find('li > a').mouseenter(function() {
                    var $li = $(this).parent();
                    $li.addClass('hover');
                    opts.item_enter.call($li.get(0));
                }).mouseleave(function() {
                    var $li = $(this).parent();
                    $li.removeClass('hover');
                    opts.item_leave.call($li.get(0));
                });
            }

            function jsddm_open() {
                jsddm_canceltimer();
                jsddm_close(true, true);

                menuitem = $(this).find('ul');
                if (menuitem.size()) {
                    $menu.trigger('opt_dropmenu.before-show', [menuitem.get(0)]);
                    menuitem.stop().css('display', 'block').animate({ opacity: 1 }, 250);
                }
            }

            function jsddm_close(fadeout, opening) {
                if (menuitem) {
                    var mitem = menuitem;
                    if (!mitem.parent().hasClass('active')) {
                        if (menuactive) {
                            menuitem = menuactive.parent();
                            menuactive.parent().stop().animate({ opacity: 1 }, 500).css('display', 'block');
                        }
                    }

                    if (!opening && mitem.parent().hasClass('active')) {
                        return;
                    }

                    if (fadeout) {
                        mitem.stop().animate({ opacity: 0 }, 500, function() {
                            mitem.hide();
                            $menu.trigger('opt_dropmenu.after-hide', [mitem.get(0)]);
                        });
                    } else {
                        mitem.stop().hide();
                        $menu.trigger('opt_dropmenu.after-hide', [mitem.get(0)]);
                    }
                }
            }

            function jsddm_timer() {
                closetimer = window.setTimeout(function() { jsddm_close(true, false); }, opts.hide_timeout);
            }

            function jsddm_canceltimer() {
                if (closetimer) {
                    window.clearTimeout(closetimer);
                    closetimer = null;
                }
            }

            init();
        });
        }
    };
    $.fn.deco_dropmenu.defaults = {
        hide_timeout: 200,
        show_timeout: 35,
        active_stay_expanded: false, // menu mode in which active submenus are permanently expanded
        item_enter: function() {},
        item_leave: function() {}
    };

})(jQuery);



/**
 * Pager plugin that scrolls content vertically up-down in viewport window.
 *
 * @event recalc.deco-pager      - fired when recalculations are done (number of pages)
 * @event before-seek.deco-pager - fired before seek
 * @event after-seek.deco-pager  - fired after seek
 *
 * Expected structure: <viewport> <content></content> </viewport>
 */
(function ($) {

    function DecoPager($pager, opts) {
        this.opts = opts;
        this.pager = $pager;
        this.content = $pager.children('.text');

        this.page_height = 0;     // height of page
        this.content_height = 0;  // content total height
        this.pages_num = 1;       // number of pages
        this.page_num = 0;        // current page number

        this.recalc_pages();
    }

    /**
     * @public
     * Recalculate number of pages and page height using viewport and content current heights.
     * Current page is changed if it is out of range after recalculations.
     */
    DecoPager.prototype.recalc_pages = function() {
        this.page_height = this.pager.height();
        this.content_height = this.content.height();
        this.pages_num = Math.ceil(this.content_height / this.page_height);

        //this.pages_num = 2;

        if (this.pages_num == 0)
            this.pages_num = 1;
        if (this.page_num >= this.pages_num)
            this.page_num = this.pages_num-1;

        this.pager.trigger('recalc.deco-pager', [this.page_num, this.pages_num]);
        return this;
    };

    // @public Seek to given page_num (zero-based index)
    DecoPager.prototype.seek = function(page_num) {
        var _this = this;
        this.page_num = page_num;

        this.pager.trigger('before-seek.deco-pager', [this.page_num, this.pages_num]);
        this.content.stop().animate(
            { top: -page_num * this.page_height },
            500,
            function() {
                _this.pager.trigger('after-seek.deco-pager', [_this.page_num, _this.pages_num]);
            }
        );
        return this;
    };

    // @public Seek to previous page if possible
    DecoPager.prototype.prev = function() {
        if (this.page_num > 0) this.seek(this.page_num-1);
        return this;
    };

    // @public Seek to next page if possible
    DecoPager.prototype.next = function() {
        if (this.page_num < this.pages_num-1) this.seek(this.page_num+1);
        return this;
    };


    $.fn.deco_pager = function(options) {
        var opts = $.extend({}, options, $.fn.deco_pager.defaults);

        if (this.eq(0).data('deco-pager'))
            return this.eq(0).data('deco-pager');

        return this.each(function() {
            $(this).data('deco-pager', new DecoPager($(this), opts));
        });
    }
    $.fn.deco_pager.defaults = {};

})(jQuery);
