﻿String.prototype.parseBool = function () {
    var t = this.toLowerCase();
    return t === "on" || t === "yes" || t === "true";
};

String.prototype.normalize = function () {
    return this.replace(/\s+/g, ' ').replace(/^\s+|\s+/g, '');
};

String.prototype.isEmpty = function () {
    return this.normalize().length == 0;
};

(function ($, ß) {

    $.fn.extend({
        API: function () { return this.data('API') || false; }
    });

    $.extend({
        range: function (from, to, it) {
            var ret = [], it = it || 1;
            for (var i = from; i <= to; i += it) {
                ret.push(i);
            }
            return ret;
        }
    });

    var Framework = {

        /**
        * Augments the viewModel with convenience methods and objects
        */
        augmentViewModel: function (viewModel, widget) {
            return $.extend({}, viewModel, {
                widget: widget,
                config: widget.data('config') || false,
                API: widget.API() || false,
                templates: (function () {
                    var tmpl = {};
                    widget.find('script[type="text/x-jquery-tmpl"]').each(function () {
                        var className = $.trim($(this).attr('class'));
                        // convert dashed-class-name to camelCaseName
                        className = className.replace(/-[\w\d]/g, function ($0) { return $0.toUpperCase(); }).replace(/[^\w\d]/g, '');
                        tmpl[className] = $(this).html();
                    });
                    return tmpl;
                })()
            });
        },

        Widgets: {

            FeaturedItemBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: '/Service/FeaturedItems',
                            context: null,
                            interval: 30,
                            autoplay: true,
                            mode: 'master-detail',
                            hideNavigation: false,
                            itemsPerPage: 2,
                            thumbsPerPage: 15,
                            gridViewSwitch: false,
                            initialTab: null
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        currentCategory = 0,
                        currentItem = 0,
                        currentPage = 0,
                        currentTab = null,
                        currentViewModel = null,
                        list = widget.find('ul'),
                        pages = 0,
                        mode = 'master-detail',
                        pager, display, controls, selector, noItemsBox; // UI elements, fetched in API.init()

                    var API = {

                        refresh: function () {
                            $.get(config.dataUrl, { context: config.context, initialTab: config.initialTab, tab: API.getTab() }, function (data) {
                                API.rebuildContent(Framework.augmentViewModel(data, widget));
                            });
                        },

                        setCategory: function (id) {
                            currentCategory = id;
                            API.rebuildContent(widget.data('viewModel'), false);
                        },

                        setMode: function (m) {
                            m = m.toLowerCase();
                            if (!/^(master-detail|grid)$/.test(m)) return;
                            mode = m;
                            var pageItems = (mode == 'grid') ? config.thumbsPerPage : config.itemsPerPage;
                            pages = Math.ceil(list.children().length / pageItems);
                            switch (mode) {
                                case 'master-detail':
                                    widget.removeClass('thumb');
                                    controls.find('[data-action=full]').addClass('active').end().find('[data-action=thumb]').removeClass('active');
                                    if (currentViewModel != null) {
                                        API.goToItem(currentItem);
                                    }
                                    break;
                                case 'grid':
                                    widget.addClass('thumb');
                                    controls.find('[data-action=thumb]').addClass('active').end().find('[data-action=full]').removeClass('active');
                                    if (currentViewModel != null) {
                                        API.goToPage(0);
                                    }
                                    API.pause();
                                    break;
                            }
                            API.rebuildPager(Framework.augmentViewModel({ pages: $.range(1, pages) }, widget));
                        },

                        next: function () {
                            API.goToItem(currentItem + 1);
                        },

                        prev: function () {
                            API.goToItem(currentItem - 1);
                        },

                        goToItem: function (i) {
                            if (config.gridViewSwitch && mode == 'grid') {
                                API.setMode('master-detail');
                                API.goToItem(i);
                            }
                            var items = list.children(), page, itemCount = (mode == 'grid') ? config.thumbsPerPage : config.itemsPerPage;
                            i = i % items.length;
                            i = i < 0 ? i + items.length : i;
                            page = Math.floor(i / itemCount);
                            API.goToPage(page);
                            items.removeClass('current').eq(i).addClass('current');
                            display.replaceWith($.tmpl(currentViewModel.templates.display, currentViewModel.Categories[currentCategory].Items[i]));
                            display = widget.find('>section>figure');
                            currentItem = i;
                        },

                        goToPage: function (i) {
                            i = Math.max(0, Math.min(i, pages - 1));
                            list.children().hide();
                            var itemCount = (mode == 'grid') ? config.thumbsPerPage : config.itemsPerPage;
                            for (var j = i * itemCount; j < (i + 1) * itemCount; j++) {
                                list.children().eq(j).show();
                            }
                            pager.find('a').removeClass('current').eq(i).addClass('current');
                        },

                        setTab: function (name) {
                            if ($.inArray(name, currentViewModel.Tabs) > -1) {
                                widget.find('ol.tabs li').removeClass('active').filter(':contains(' + name + ')').addClass('active');
                                currentTab = name;
                            }
                        },

                        getTab: function () {
                            return currentTab;
                        },

                        pause: function () {
                            config.autoplay = false;
                            controls.find('[data-action=pause]').addClass('active').end().find('[data-action=play]').removeClass('active');
                        },

                        resume: function () {
                            config.autoplay = true;
                            controls.find('[data-action=play]').addClass('active').end().find('[data-action=pause]').removeClass('active');
                        },

                        init: function () {
                            var viewModel = Framework.augmentViewModel({ pages: [] }, widget);

                            //$.tmpl(viewModel.templates.pager, viewModel).appendTo(widget.find('section'));
                            pager = widget.find('.pager:not(script)');

                            $(viewModel.templates.controls).appendTo(widget.find('section'));
                            controls = widget.find('section>div:last');

                            //$.tmpl(viewModel.templates.noItems, viewModel).prependTo(widget).hide();
                            noItemsBox = widget.find('div.no-items');

                            display = $('<figure/>').insertBefore(widget.find('ul'));
                            //selector = $.tmpl(viewModel.templates.categories, viewModel).appendTo(controls.find('div'));
                            API.setMode(config.mode);
                            if (config.autoplay) API.resume(); else API.pause();
                            widget.trigger('relayout');
                        },

                        rebuildContent: function (viewModel, rebuildSelector) {
                            var pageItems = (mode == 'master-detail') ? config.itemsPerPage : config.thumbsPerPage;
                            widget.data('viewModel', viewModel);
                            currentViewModel = viewModel;

                            rebuildSelector = rebuildSelector || false;

                            if (rebuildSelector) {
                                //selector.replaceWith($.tmpl(viewModel.templates.categories, viewModel));
                                selector = widget.find('[name=Category]');
                            }

                            if (viewModel.Tabs.length > 1 && widget.find('ol.tabs').length == 0) {
                                widget.find('ol.tabs').remove();
                                $.tmpl(viewModel.templates.tabs, viewModel).prependTo(widget);
                                API.setTab(viewModel.CurrentTab);
                            }

                            list.children().remove();

                            if (viewModel.Categories.length == 0 || viewModel.Categories[currentCategory].Items.length == 0) {
                                noItemsBox.show();
                                widget.find('>section').hide();
                            } else {
                                noItemsBox.hide();
                                widget.find('>section').show();

                                for (var i = 0; i < viewModel.Categories[currentCategory].Items.length; i++) {
                                    //$.tmpl(viewModel.templates.thumb, viewModel.Categories[currentCategory].Items[i]).appendTo(list);
                                }

                                pages = Math.ceil(list.children().length / pageItems);

                                list.children(':gt(' + (pageItems - 1) + ')').hide();
                                list.children(':first').addClass('current');

                                display.replaceWith($.tmpl(viewModel.templates.display, viewModel.Categories[currentCategory].Items[0]));
                                display = widget.find('>section>figure');

                                API.rebuildPager(viewModel);

                                API.goToItem(0);
                            }
                            widget.trigger('relayout');
                        },

                        rebuildPager: function (viewModel) {
                            pager.replaceWith($.tmpl(viewModel.templates.pager, { pages: $.range(1, pages) }));
                            pager = widget.find('.pager:not(script)');
                            pager.find('a:first').addClass('current');
                        }
                    };

                    widget.data('config', config);

                    widget.data('API', {
                        setCategory: API.setCategory,
                        setMode: API.setMode,
                        next: API.next,
                        prev: API.prev,
                        goToItem: API.goToItem,
                        pause: API.pause,
                        resume: API.resume
                    });

                    API.init();

                    setInterval(function () {
                        if (config.autoplay && config.interval > 0 && list.children().length > 0) {
                            API.next();
                        }
                    }, parseInt(config.interval, 10) * 1000);

                    if (config.dataUrl.length > 0) {
                        $.get(config.dataUrl, { context: config.context, initialTab: config.initialTab, tab: null }, function (data) {
                            API.rebuildContent(Framework.augmentViewModel(data, widget), true);
                        });
                    }

                    widget.delegate('[data-action]', 'click', function (ev) {
                        var el = $(this);
                        switch (el.data('action')) {
                            case 'full':
                                API.setMode('master-detail');
                                break;
                            case 'thumb':
                                API.setMode('grid');
                                break;
                            case 'pause':
                                API.pause();
                                break;
                            case 'play':
                                API.resume();
                                break;
                        }
                        ev.preventDefault();
                    }).delegate('[name=Category]', 'change', function (ev) {
                        var id = parseInt($(this).val(), 10);
                        API.setCategory(id);
                    }).delegate('.pager a', 'click', function (ev) {
                        API.pause();
                        API.goToPage($(this).index());
                        ev.preventDefault();
                    }).delegate('ul li', 'click', function (ev) {
                        currentItem = $(this).addClass('current').siblings().removeClass('current').end().index();
                        API.pause();
                        API.goToItem(currentItem);
                    }).delegate('div>button', 'click', function (ev) {
                        switch ($(this).attr('class').toLowerCase()) {
                            case 'prev':
                                API.pause();
                                API.prev();
                                break;
                            case 'next':
                                API.pause();
                                API.next();
                                break;
                        }
                    }).delegate('ol.tabs a', 'click', function (ev) {
                        API.setTab($(this).text());
                        API.refresh();
                        ev.preventDefault();
                    });

                });
            },

            FeaturedItemBrowserStatic: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: '/Service/FeaturedItems',
                            context: null,
                            interval: 30,
                            autoplay: true,
                            mode: 'master-detail',
                            hideNavigation: false,
                            itemsPerPage: 2,
                            thumbsPerPage: 15,
                            gridViewSwitch: false,
                            initialTab: null,
                            isManual:false
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        currentCategory = 0,
                        currentItem = 0,
                        currentPage = 0,
                        currentTab = null,
                        currentViewModel = null,
                        list = widget.find('ul'),
                        pages = 0,
                        mode = 'master-detail',
                        tatic = false,
                        isManual = config.isManual,
                        pager, display, controls, selector, noItemsBox; // UI elements, fetched in API.init()

                    var API = {

                        refresh: function () {
                            $.get(config.dataUrl, { context: config.context, initialTab: config.initialTab, tab: API.getTab() }, function (data) {
                                API.rebuildContent(Framework.augmentViewModel(data, widget));
                            });
                        },

                        setCategory: function (id) {
                            currentCategory = id;
                            API.rebuildContent(widget.data('viewModel'), false);
                        },

                        setMode: function (m) {
                            m = m.toLowerCase();
                            if (!/^(master-detail|grid)$/.test(m)) return;
                            mode = m;
                            var pageItems = (mode == 'grid') ? config.thumbsPerPage : config.itemsPerPage;
                            pages = Math.ceil(list.children().length / pageItems);
                            switch (mode) {
                                case 'master-detail':
                                    widget.removeClass('thumb');
                                    controls.find('[data-action=full]').addClass('active').end().find('[data-action=thumb]').removeClass('active');
                                    if (currentViewModel != null) {
                                        API.goToItem(currentItem);
                                    }
                                    break;
                                case 'grid':
                                    widget.addClass('thumb');
                                    controls.find('[data-action=thumb]').addClass('active').end().find('[data-action=full]').removeClass('active');
                                    if (currentViewModel != null) {
                                        API.goToPage(0);
                                    }
                                    API.pause();
                                    break;
                            }
                            API.rebuildPager(Framework.augmentViewModel({ pages: $.range(1, pages) }, widget));
                        },

                        next: function () {
                            API.goToItem(currentItem + 1);
                        },

                        prev: function () {
                            API.goToItem(currentItem - 1);
                        },

                        goToItem: function (i) {
                            if (config.gridViewSwitch && mode == 'grid') {
                                API.setMode('master-detail');
                                API.goToItem(i);
                            }
                            var items = list.children(), page, itemCount = (mode == 'grid') ? config.thumbsPerPage : config.itemsPerPage;
                            i = i % items.length;
                            i = i < 0 ? i + items.length : i;
                            page = Math.floor(i / itemCount);
                            API.goToPage(page);
                            items.removeClass('current').eq(i).addClass('current');
                            display.replaceWith($.tmpl(currentViewModel.templates.display, currentViewModel.Categories[currentCategory].Items[i]));
                            display = widget.find('>section>figure');
                            currentItem = i;
                        },

                        goToPage: function (i) {
                            i = Math.max(0, Math.min(i, pages - 1));
                            list.children().hide();
                            var itemCount = (mode == 'grid') ? config.thumbsPerPage : config.itemsPerPage;
                            for (var j = i * itemCount; j < (i + 1) * itemCount; j++) {
                                list.children().eq(j).show();
                            }
                            pager.find('a').removeClass('current').eq(i).addClass('current');
                        },

                        setTab: function (name) {
                            if ($.inArray(name, currentViewModel.Tabs) > -1) {
                                widget.find('ol.tabs li').removeClass('active').filter(':contains(' + name + ')').addClass('active');
                                currentTab = name;
                            }
                        },

                        getTab: function () {
                            return currentTab;
                        },

                        pause: function () {
                            config.autoplay = false;
                            controls.find('[data-action=pause]').addClass('active').end().find('[data-action=play]').removeClass('active');
                        },

                        resume: function () {
                            config.autoplay = true;
                            controls.find('[data-action=play]').addClass('active').end().find('[data-action=pause]').removeClass('active');
                        },

                        init: function () {
                            var viewModel = Framework.augmentViewModel({ pages: [] }, widget);
                            
                            if (!isManual) {
                                tatic = true;
                                
                                $.tmpl(viewModel.templates.pager, viewModel).appendTo(widget.find('section'));
                                pager = widget.find('.pager:not(script)');
                                
                                $(viewModel.templates.controls).appendTo(widget.find('section'));
                                controls = widget.find('section>div:last');
                                
                                $.tmpl(viewModel.templates.noItems, viewModel).prependTo(widget).hide();
                                noItemsBox = widget.find('div.no-items');

                                display = $('<figure/>').insertBefore(widget.find('ul'));
                                selector = $.tmpl(viewModel.templates.categories, viewModel).appendTo(controls.find('div'));
                                API.setMode(config.mode);
                                if (config.autoplay) API.resume(); else API.pause();
                                widget.trigger('relayout');
                                return;
                            }else {
                                $.tmpl(viewModel.templates.pager, viewModel).appendTo(widget.find('section'));
                                pager = widget.find('.pager:not(script)');

                                $(viewModel.templates.controls).appendTo(widget.find('section'));
                                controls = widget.find('section>div:last');

                                $.tmpl(viewModel.templates.noItems, viewModel).prependTo(widget).hide();
                                noItemsBox = widget.find('div.no-items');

                                display = $('<figure/>').insertBefore(widget.find('ul'));
                                selector = $.tmpl(viewModel.templates.categories, viewModel).appendTo(controls.find('div'));
                                API.setMode(config.mode);
                                if (config.autoplay) API.resume(); else API.pause();
                                widget.trigger('relayout');
                            }
                        },

                        rebuildContent: function (viewModel, rebuildSelector) {
                            var pageItems = (mode == 'master-detail') ? config.itemsPerPage : config.thumbsPerPage;
                            widget.data('viewModel', viewModel);
                            currentViewModel = viewModel;

                            rebuildSelector = rebuildSelector || false;

                            if (rebuildSelector) {
                                selector.replaceWith($.tmpl(viewModel.templates.categories, viewModel));
                                selector = widget.find('[name=Category]');
                            }

                            if (viewModel.Tabs.length > 1 && widget.find('ol.tabs').length == 0) {
                                widget.find('ol.tabs').remove();
                                $.tmpl(viewModel.templates.tabs, viewModel).prependTo(widget);
                                API.setTab(viewModel.CurrentTab);
                            }

                            list.children().remove();

                            if (viewModel.Categories.length == 0 || viewModel.Categories[currentCategory].Items.length == 0) {
                                noItemsBox.show();
                                widget.find('>section').hide();
                            } else {
                                noItemsBox.hide();
                                widget.find('>section').show();
                                
                                
                                    
                                for (var i = 0; i < viewModel.Categories[currentCategory].Items.length; i++) {
                                    $.tmpl(viewModel.templates.thumb, viewModel.Categories[currentCategory].Items[i]).appendTo(list);
                                }
                                    
                                
                                
                                pages = Math.ceil(list.children().length / pageItems);

                                list.children(':gt(' + (pageItems - 1) + ')').hide();
                                list.children(':first').addClass('current');
                                
                                if (tatic) {
                                    
                                    display.replaceWith($.tmpl(viewModel.templates.display, viewModel.Categories[currentCategory].Items[0]));
                                    display = widget.find('>section>figure');
                                  
                                    
                                } else {
                                    display.replaceWith($.tmpl(viewModel.templates.display, viewModel.Categories[currentCategory].Items[0]));
                                    display = widget.find('>section>figure');
                                }

                                API.rebuildPager(viewModel);

                                API.goToItem(0);
                            }
                            widget.trigger('relayout');
                        },

                        rebuildPager: function (viewModel) {
                            pager.replaceWith($.tmpl(viewModel.templates.pager, { pages: $.range(1, pages) }));
                            pager = widget.find('.pager:not(script)');
                            pager.find('a:first').addClass('current');
                        }
                    };

                    widget.data('config', config);

                    widget.data('API', {
                        setCategory: API.setCategory,
                        setMode: API.setMode,
                        next: API.next,
                        prev: API.prev,
                        goToItem: API.goToItem,
                        pause: API.pause,
                        resume: API.resume
                    });

                    API.init();

                    setInterval(function () {
                        if (config.autoplay && config.interval > 0 && list.children().length > 0) {
                            API.next();
                        }
                    }, parseInt(config.interval, 10) * 1000);
                    
                    if (config.dataUrl.length > 0) {
                        $.get(config.dataUrl, { context: config.context, initialTab: config.initialTab, tab: null }, function (data) {
                            API.rebuildContent(Framework.augmentViewModel(data, widget), true);
                        });
                    }

                    widget.delegate('[data-action]', 'click', function (ev) {
                        var el = $(this);
                        switch (el.data('action')) {
                            case 'full':
                                API.setMode('master-detail');
                                break;
                            case 'thumb':
                                API.setMode('grid');
                                break;
                            case 'pause':
                                API.pause();
                                break;
                            case 'play':
                                API.resume();
                                break;
                        }
                        ev.preventDefault();
                    }).delegate('[name=Category]', 'change', function (ev) {
                        var id = parseInt($(this).val(), 10);
                        API.setCategory(id);
                    }).delegate('.pager a', 'click', function (ev) {
                        API.pause();
                        API.goToPage($(this).index());
                        ev.preventDefault();
                    }).delegate('ul li', 'click', function (ev) {
                        currentItem = $(this).addClass('current').siblings().removeClass('current').end().index();
                        API.pause();
                        API.goToItem(currentItem);
                    }).delegate('div>button', 'click', function (ev) {
                        switch ($(this).attr('class').toLowerCase()) {
                            case 'prev':
                                API.pause();
                                API.prev();
                                break;
                            case 'next':
                                API.pause();
                                API.next();
                                break;
                        }
                    }).delegate('ol.tabs a', 'click', function (ev) {
                        API.setTab($(this).text());
                        API.refresh();
                        ev.preventDefault();
                    });

                });
            },            

            HtmlListBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: null,
                            context: null,
                            visibleItems: 3
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        currentPage = 0,
                        pages = 0,
                        pager, list = widget.find('ul'); // UI elements

                    var API = {
                        refresh: function () {
                            $.get(config.dataUrl, { context: config.context }, function (viewModel) {
                                viewModel = Framework.augmentViewModel(viewModel, widget);
                                widget.data('viewModel', viewModel);
                                API.buildContent(viewModel);
                            });
                        },

                        buildContent: function (viewModel, staticContent) {
                            staticContent = staticContent || false;
                            if (!staticContent) {
                                list.children().remove();
                                $.tmpl(viewModel.templates.item, viewModel.Items).appendTo(list);
                                pages = Math.ceil(viewModel.Items.length / config.visibleItems);
                            } else {
                                pages = Math.ceil(list.children().length / config.visibleItems);
                            }
                            list.children(':gt(' + (config.visibleItems - 1) + ')').hide();
                            list.children().equalizeSize();
                            list.height(list.children().outerHeight(true) * config.visibleItems);
                            pager.replaceWith($.tmpl(viewModel.templates.pager, { pages: $.range(1, pages) }));
                            pager = widget.find('.pager:not(script)');
                            API.moveToPage(0);
                            widget.trigger('relayout');
                        },

                        next: function () {
                            API.moveToPage(currentPage + 1);
                        },

                        prev: function () {
                            API.moveToPage(currentPage - 1);
                        },

                        moveToPage: function (n) {
                            n = Math.max(0, Math.min(n, pages - 1));
                            pager.children().removeClass('current').eq(n).addClass('current');
                            list.children().hide();
                            for (var i = n * config.visibleItems; i < (n + 1) * config.visibleItems; i++) {
                                list.children().eq(i).show();
                            }
                        },

                        init: function () {
                            var viewModel = Framework.augmentViewModel({}, widget);
                            $.tmpl(viewModel.templates.pager, { pages: [] }).insertAfter(list);
                            pager = widget.find('.pager:not(script)');
                            API.buildContent(viewModel, true);
                        }
                    };

                    API.init();

                    if (config.dataUrl != null) {
                        API.refresh();
                    }

                    widget.delegate('.pager a', 'click', function (ev) {
                        API.moveToPage($(this).index());
                        ev.preventDefault();
                    });

                    widget.data('API', {
                        refresh: API.refresh,
                        next: API.next,
                        prev: API.prev,
                        moveToPage: API.moveToPage
                    });
                });
            }, // end HtmlListBrowser

            HtmlRelatedItemsBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: null,
                            context: null,
                            visibleItems: 3
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        currentPage = 0,
                        pages = 0,
                        pager, list = widget.find('ul'); // UI elements

                    var API = {
                        refresh: function () {
                            $.get(config.dataUrl, { context: config.context }, function (viewModel) {
                                viewModel = Framework.augmentViewModel(viewModel, widget);
                                widget.data('viewModel', viewModel);
                                API.buildContent(viewModel);
                            });
                        },

                        buildContent: function (viewModel, staticContent) {
                            staticContent = staticContent || false;
                            if (!staticContent) {
                                list.children().remove();
                                $.tmpl(viewModel.templates.item, viewModel.Items).appendTo(list);
                                pages = Math.ceil(viewModel.Items.length / config.visibleItems);
                            } else {
                                pages = Math.ceil(list.children().length / config.visibleItems);
                            }
                            list.children(':gt(' + (config.visibleItems - 1) + ')').hide();
                            if (list.children().length > config.visibleItems) {
                                list.height(list.children().outerHeight(true) * config.visibleItems + 40);
                            }
                            pager.replaceWith($.tmpl(viewModel.templates.pager, { pages: $.range(1, pages) }));
                            pager = widget.find('.pager:not(script)');
                            API.moveToPage(0);
                            widget.trigger('relayout');
                        },

                        next: function () {
                            API.moveToPage(currentPage + 1);
                        },

                        prev: function () {
                            API.moveToPage(currentPage - 1);
                        },

                        moveToPage: function (n) {
                            n = Math.max(0, Math.min(n, pages - 1));
                            pager.children().removeClass('current').eq(n).addClass('current');
                            list.children().hide();
                            for (var i = n * config.visibleItems; i < (n + 1) * config.visibleItems; i++) {
                                list.children().eq(i).show();
                            }
                        },

                        init: function () {
                            var viewModel = Framework.augmentViewModel({}, widget);
                            $.tmpl(viewModel.templates.pager, { pages: [] }).insertAfter(list);
                            pager = widget.find('.pager:not(script)');
                            API.buildContent(viewModel, true);
                        }
                    };

                    API.init();

                    if (config.dataUrl != null) {
                        API.refresh();
                    }

                    widget.delegate('.pager a', 'click', function (ev) {
                        API.moveToPage($(this).index());
                        ev.preventDefault();
                    });

                    widget.data('API', {
                        refresh: API.refresh,
                        next: API.next,
                        prev: API.prev,
                        moveToPage: API.moveToPage
                    });
                });
            }, // end HtmlListBrowser

            RelatedContentItemBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: null,
                            context: null,
                            visibleItems: 3
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        pages = 0, currentPage = 0,
                        pager, list = widget.find('ul'); // UI elements

                    var API = {
                        refresh: function () {
                            $.get(config.dataUrl, { context: config.context }, function (viewModel) {
                                viewModel = Framework.augmentViewModel(viewModel, widget);
                                API.rebuildContent(viewModel);
                            });
                        },

                        rebuildContent: function (viewModel) {
                            widget.data('viewModel', viewModel);
                            list.children().remove();
                            $.tmpl(viewModel.templates.item, viewModel.Items).appendTo(list);
                            pages = Math.ceil(viewModel.Items.length / config.visibleItems);
                            pager.replaceWith($.tmpl(viewModel.templates.pager, { pages: $.range(1, pages) }));
                            pager = widget.find('.pager:not(script)');
                            list.children().equalizeSize();
                            API.moveToPage(0);
                            widget.trigger('relayout');
                        },

                        next: function () {
                            API.moveToPage(currentPage + 1);
                        },

                        prev: function () {
                            API.moveToPage(currentPage - 1);
                        },

                        moveToPage: function (n) {
                            n = Math.max(0, Math.min(n, pages - 1));
                            pager.children().removeClass('current').eq(n).addClass('current');
                            list.children().hide();
                            for (var i = n * config.visibleItems; i < (n + 1) * config.visibleItems; i++) {
                                list.children().eq(i).show();
                            }
                            currentPage = n;
                        },

                        init: function () {
                            var viewModel = Framework.augmentViewModel({ pages: [1] }, widget);
                            widget.data('viewModel', viewModel);
                            $.tmpl(viewModel.templates.controls, viewModel).appendTo(widget);
                            pager = widget.find('.pager:not(script)');
                            API.moveToPage(0);
                        }
                    };

                    API.init();

                    if (config.dataUrl != '') {
                        API.refresh();
                    }

                    widget.delegate('.pager a', 'click', function (ev) {
                        API.moveToPage($(this).index());
                        ev.preventDefault();
                    }).delegate('.controls button', 'click', function (ev) {
                        switch ($.trim($(this).attr('class'))) {
                            case 'next':
                                API.next();
                                break;
                            case 'prev':
                                API.prev();
                                break;
                        }
                        ev.preventDefault();
                    });

                    widget.data('API', {
                        refresh: API.refresh,
                        next: API.next,
                        prev: API.prev,
                        moveToPage: API.moveToPage
                    });
                });
            }, // end RelatedContentItemBrowser

            TabbedAccordionContentBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            visibleItems: 2,
                            initialGroup: ''
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        currentGroup = config.initialGroup,
                        tabs = widget.find('ul.tabs'), content = widget.find('ul:not(.tabs)'); // UI elements

                    var API = {
                        switchGroup: function (name) {
                            content.children().show().find('ol li').show();
                            if (name == '') {
                                tabs.find('li:first').addClass('current').siblings().removeClass('current');
                                content.children().each(function () {
                                    var c = $(this);
                                    if (c.find('ol li').length == 0) c.hide(); else c.show();
                                });
                            } else {
                                content.find('ol li').hide().filter('[data-group=' + name + ']');
                                content.children().each(function () {
                                    var c = $(this);
                                    if (c.find('ol li[data-group=' + name + ']').length == 0) c.hide(); else c.show();
                                });
                            }

                            content.children().removeClass('current').children('div').hide();
                            setTimeout(function () {
                                content.children(':visible').eq(0).find('header').trigger('click');
                            }, 200);

                            currentGroup = name;
                            content.find('ol').each(function () {
                                API.rebuildPager($(this));
                            });
                            tabs.find('a').each(function () {
                                var t = $(this);
                                if (t.data('group-name') == '') return;
                                if (content.find('ol li[data-group=' + t.data('group-name') + ']').length == 0) {
                                    t.parent().hide();
                                } else {
                                    t.parent().show();
                                }
                            });
                        },

                        rebuildPager: function (list) {
                            var items = list.children();
                            if (currentGroup != '') {
                                items = items.filter('[data-group=' + currentGroup + ']');
                            };
                            var pages = Math.ceil(items.length / config.visibleItems),
                                viewModel = Framework.augmentViewModel({ pages: $.range(1, pages) }, widget),
                                pager;
                            list.siblings('.pager:not(script)').remove();
                            $.tmpl(viewModel.templates.pager, viewModel).insertAfter(list);
                            pager = list.next('.pager:not(script)');
                            API.moveToPage(0, list, pager);
                        },

                        init: function () {
                            var viewModel = Framework.augmentViewModel({ pages: [1] }, widget);
                            content.find('ol').each(function () {
                                $.tmpl(viewModel.templates.pager, viewModel).appendTo($(this).parent());
                            });
                            API.switchGroup(config.initialGroup);
                            widget.find('header+div').filter(':gt(0)').hide();
                            widget.find('ul:not(.tabs)>li:first').addClass('current');
                        },

                        moveToPage: function (n, list, pager) {
                            var items = list.children();
                            if (currentGroup != '') {
                                items = items.filter('[data-group=' + currentGroup + ']');
                            }
                            var pages = Math.ceil(items.length / config.visibleItems);
                            n = Math.max(0, Math.min(n, pages - 1));
                            list.children().hide();
                            for (var i = n * config.visibleItems; i < (n + 1) * config.visibleItems; i++) {
                                items.eq(i).show();
                            }
                            pager.children().removeClass('current').eq(n).addClass('current');
                        }
                    };

                    API.init();

                    tabs.delegate('a,li', 'click', function (ev) {
                        var el = $(this);
                        if (el.is('a')) el = el.parent();
                        var name = el.children('a').data('group-name');
                        el.addClass('current').siblings().removeClass('current');
                        API.switchGroup(name);
                        ev.preventDefault();
                    });

                    content.delegate('header', 'click', function (ev) {
                        $(this).next().slideDown('fast');
                        $(this).closest('li').addClass('current').siblings().removeClass('current').children('div').slideUp('fast');
                    });

                    content.delegate('.pager a', 'click', function (ev) {
                        var a = $(this);
                        API.moveToPage(a.index(), a.parent().siblings('ol'), a.closest('.pager:not(script)'));
                        ev.preventDefault();
                    });

                    widget.data('API', {
                        switchGroup: API.switchGroup
                    });
                });
            }, // end Tabbed Accordion Content Browser

            TabbedContentBox: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        contentItems = widget.find('ol.content>li'),
                        titles = $.map(contentItems, function (el, idx) {
                            return $(el).attr('title');
                        }),
                        viewModel = Framework.augmentViewModel({ tabs: titles }, widget);

                    $.tmpl(viewModel.templates.controls, viewModel).prependTo(widget);

                    contentItems.not(':first').hide();
                    widget.find('ol.tabs>li:first').addClass('active');

                    widget.delegate('ol.tabs a', 'click', function (ev) {
                        var li = $(this).parent();
                        li.addClass('active').siblings().removeClass('active');
                        contentItems.hide().eq(li.index()).show();
                        widget.trigger('relayout');
                        ev.preventDefault();
                    });
                });
            }, // end TabbedContentBox

            // rok 
            GenericContentItemBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: null,
                            context: null,
                            itemsPerPage: 4,
                            controlsOnBottom: false,
                            tab: null,
                            isManual: false,
                            isViewSwitch: false
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        pages = 0, currentPage = 0, currentTab = config.tab, isManual = config.isManual,
                        list, pager, tabs, noItemsBox; // UI elements

                    var API = {
                        refresh: function () {
                            $.get(
                                config.dataUrl,
                                {
                                    context: config.context,
                                    sort: API.getSorter(),
                                    filter: API.getFilter(),
                                    tab: API.getTab(),
                                    checkedFilters: API.getCheckedFilters().join(';')
                                },
                                function (viewModel) {
                                    API.rebuildContent(Framework.augmentViewModel(viewModel, widget));
                                }
                            );
                        },

                        rebuildContent: function (viewModel) {
                            var items,
                                buildItems = function (template, items, callback) {
                                    if (items.length > 0) {
                                        $.tmpl(template, items.slice(0, config.itemsPerPage * 4)).appendTo(list);
                                        var leftover = items.slice(config.itemsPerPage * 4);
                                        if (leftover.length > 0) {
                                            setTimeout(function () { buildItems(template, leftover, callback); }, 20);
                                        } else {
                                            callback();
                                            return;
                                        }
                                    } else {
                                        callback();
                                    }
                                }, prepContent = function () {
                                    items = list.show().children();
                                    pages = Math.ceil(items.length / config.itemsPerPage);
                                    items.equalizeSize();
                                    viewModel = $.extend({ current: 1, all: pages }, viewModel);
                                    var controls = $.tmpl(viewModel.templates.controls, viewModel);
                                    widget.find('.controls:not(script)').replaceWith(controls);
                                    var selects = controls.find('select');
                                    if (selects.length == 1) {
                                        selects.width(selects.width() * 2);
                                    }
                                    pager = widget.find('.pager:not(script)');
                                    if (viewModel.Tabs.length > 0 && config.showTabs) {
                                        tabs.html();
                                        tabs.replaceWith($.tmpl(viewModel.templates.tabs, viewModel));
                                        tabs = widget.find('.tabs:not(script)');
                                        API.setTab(viewModel.CurrentTab);
                                    }
                                    API.moveToPage(0);
                                    if (config.isViewSwitch) {
                                        //API.addSwitchTab();
                                    }
                                    setTimeout(function () { widget.trigger('relayout'); }, 1000);
                                };


                            noItemsBox.hide();
                            list.show().children().remove();
                            if (viewModel.Items.length == 0) {
                                list.hide();
                                noItemsBox.show();
                            } else {
                                list.hide();
                                buildItems($.template(viewModel.templates.item), viewModel.Items, prepContent);
                            }


                        },

                        next: function () {
                            API.moveToPage(currentPage + 1);
                        },

                        prev: function () {
                            API.moveToPage(currentPage - 1);
                        },

                        moveToPage: function (n) {
                            n = Math.max(0, Math.min(n, pages - 1));
                            var items = list.children().hide();
                            for (var i = n * config.itemsPerPage; i < (n + 1) * config.itemsPerPage; i++) {
                                items.eq(i).show();
                            }
                            pager.replaceWith($.tmpl(widget.find('script.pager'), { current: n + 1, all: pages }));
                            pager = widget.find('.pager:not(script)');
                            currentPage = n;
                        },

                        getFilters: function () {
                            return $.map(widget.find('select[name=Filter]>option'), function (el, idx) { return el.value; });
                        },

                        getFilter: function () {
                            return widget.find('select[name=Filter]').val();
                        },

                        setFilter: function (name) {
                            var filters = API.getFilters();
                            name = ($.inArray(name, filters) > -1) ? name : filters[0];
                            widget.find('select[name=Filter]').val(name);
                        },

                        getSorters: function () {
                            return $.map(widget.find('select[name=Sort]>option'), function (el, idx) { return el.value; });
                        },

                        getSorter: function () {
                            return widget.find('select[name=Sort]').val();
                        },

                        setSorter: function (name) {
                            var sorters = API.getSorters();
                            name = ($.inArray(name, sorters) > -1) ? name : sorters[0];
                            widget.find('select[name=Sort]').val(name);
                        },

                        getCheckFilters: function () {
                            return $.map(widget.find('input[type=checkbox]'), function (el, idx) { return el.name; });
                        },

                        setCheckFilter: function (name, value) {
                            var i = widget.find('input[type=checkbox][name=' + name + ']');
                            if (!!value) {
                                i.attr('checked', 'checked');
                            } else {
                                i.removeAttr('checked');
                            }
                        },

                        getCheckFilter: function (name) {
                            return widget.find('input[type=checkbox][name=' + name + ']').is(':checked');
                        },

                        getCheckedFilters: function () {
                            return $.map(widget.find('input[type=checkbox]:checked'), function (el, idx) { return el.name; });
                        },

                        getTab: function () {
                            return currentTab;
                        },

                        setTab: function (name) {
                            currentTab = name;
                            tabs.children(':contains(' + currentTab + ')').addClass('active').siblings().removeClass('active');
                        },
                        
                        addSwitchTab: function () {
                            var wlmswitch = '<div id="ViewSwitch"><a class="list widget-l-m-switch">&nbsp;&nbsp;&nbsp;</a><a id="printgib" class="print printgib">&nbsp;&nbsp;&nbsp;</a></div>';
                            $(".tabs:not(script)").after(wlmswitch);
                        },
                        
                        init: function () {
                            list = widget.find('>ol');
                            items = list.children();
                            if(!isManual)
                            {
                                var viewModel = Framework.augmentViewModel({ current: 0, all: 0, Filters: [], Sorters: [], Tabs: [], CheckFilters: [], CheckedFilters: [] }, widget), items;

                                if (config.controlsOnBottom) {
                                    $.tmpl(viewModel.templates.controls, viewModel).appendTo(widget);
                                } else {
                                    $.tmpl(viewModel.templates.controls, viewModel).prependTo(widget);
                                }
                                pager = widget.find('.pager:not(script)');
                                $.tmpl(viewModel.templates.noItems, {}).insertBefore(list);
                                noItemsBox = widget.find('div.no-items');
                                if (list.children().length == 0) noItemsBox.show();
                                else noItemsBox.hide();

                                if (config.showTabs) {
                                    $.tmpl(viewModel.templates.tabs, viewModel).prependTo(widget);
                                    tabs = widget.find('.tabs:not(script)');
                                }

                                if (config.dataUrl !== null) {
                                    API.refresh();
                                } else {
                                    pages = Math.ceil(list.children().length / config.itemsPerPage);
                                    API.moveToPage(0);
                                }

                            }
                            else
                            {
                                
                                var viewModel = Framework.augmentViewModel({ current: 0, all: 0, Filters: [], Sorters: [], Tabs: [], CheckFilters: [], CheckedFilters: [] }, widget), items;
                                pager = widget.find('.pager:not(script)');
                                noItemsBox = widget.find('div.no-items');
                                if (list.children().length == 0) noItemsBox.show();
                                else noItemsBox.hide();
                                if (config.showTabs) {
                                    tabs = widget.find('.tabs:not(script)');
                                }
                                
                                pager.replaceWith($.tmpl(widget.find('script.pager'), { current:  1, all: pages }));
                                pager = widget.find('.pager:not(script)');
                                items = list.show().children();
                                pages = Math.ceil(list.children().length / config.itemsPerPage);
                                API.moveToPage(0);
                                items.equalizeSize();
                                var controls = widget.find('.controls:not(script)');
                                var selects = controls.find('select');
                                if (selects.length == 1) {
                                        selects.width(selects.width() * 2);
                                }
                                setTimeout(function () { widget.trigger('relayout'); }, 100);
                            /*
                                if (config.showTabs) {
                                    tabs = widget.find('.tabs:not(script)');
                                }
                                noItemsBox = widget.find('div.no-items');
                                if (list.children().length == 0) noItemsBox.show();
                                else noItemsBox.hide();
                                pager = widget.find('.pager:not(script)');
                                pages = Math.ceil(list.children().length / config.itemsPerPage);
                                API.moveToPage(0)
                                */
                            }
                            if (config.isViewSwitch) {
                                API.addSwitchTab();
                            }
                        }
                    };

                    widget.data('API', {
                        refresh: API.refresh,
                        next: API.next,
                        prev: API.prev,
                        moveToPage: API.moveToPage,
                        getFilters: API.getFilters,
                        getFilter: API.getFilter,
                        setFilter: API.setFilter,
                        getSorters: API.getSorters,
                        getSorter: API.getSorter,
                        setSorter: API.setSorter,
                        setTab: API.setTab,
                        getTab: API.getTab,
                        getCheckedFilters: API.getCheckedFilters,
                        getCheckFilters: API.getCheckFilters
                    });

                    API.init();

                    widget.delegate('select[name=Filter],select[name=Sort]', 'change', function (ev) {
                        API.refresh();
                    }).delegate('input[type=checkbox]', 'change', function (ev) {
                        setTimeout(function () {
                            //console.debug(API.getCheckedFilters(), widget.find('input[type=checkbox]'));
                            API.refresh();
                        }, 50);
                    }).delegate('.controls button', 'click', function (ev) {
                        var command = $(this).attr('class').split(' ')[0];
                        switch (command) {
                            case 'prev':
                                API.prev();
                                ev.preventDefault();
                                break;
                            case 'next':
                                API.next();
                                ev.preventDefault();
                                break;
                        }
                    }).delegate('.tabs a', 'click', function (ev) {
                        API.setTab($(this).text());
                        API.refresh();
                        ev.preventDefault();
                    }).delegate('.widget-l-m-switch', 'click', function (ev) {
                        if ($('.widget-generic-item-browser ol').hasClass('widget-l-m')) {
                            $('.widget-generic-item-browser ol').removeClass('widget-l-m');
                            var h = 0;
                            var c = $(".widget-generic-item-browser ol li");
                            c.each(function () {
                                h = Math.max($(this).css('height', 'auto').height(), h);
                            });
                            c.height(h);
                            $('.widget-l-m-switch').addClass('list').removeClass('net');

                        } else {
                            $(".widget-generic-item-browser ol li").height("");
                            $('.widget-generic-item-browser ol').addClass('widget-l-m');
                            $('.widget-l-m-switch').addClass('net').removeClass('list');
                        }
                        ev.preventDefault();
                    }).delegate('#printgib', 'click', function (ev) {
                        $("#print").remove();
                        $("#ifprint").remove();
                        var grst = $('<div id="print"></div>');
                        grst.css({ position: "absolute", width: "0px", height: "0px", left: "-600px", top: "-600px" });
                        var wlm = $('<div id="print_"></div>');
                        var wlm0 = $('<div class="widget-l-m_"></div>');
                        var printi = $(this).parent().parent().find('ol li').clone();
                        printi.height("").show().appendTo(wlm0);
                        wlm0.appendTo(wlm);
                        wlm.appendTo(grst);
                        var sti = $('<style type="text/css">a {color: #257EB6;text-decoration: none;} ul, ol, li {list-style: none;}div.widget-l-m_ {background: #ffffff;z-index: 101;}#print_ .widget-l-m_ figure, #print_ .widget-l-m_ p { display: none;}div.widget-l-m_ li, div.widget-l-m_ li  {width: 94%;margin: 0% 1%;padding: 1% 2%;}div.widget-l-m_ li.shop-item h3 {background: url("http://www.btc-city.com/Content/images/widgets/arrows.png") no-repeat scroll -15px -9px transparent;border-bottom: 1px dashed #B0B0B0;padding-left: 10px;margin: 0;font: bold 12px Arial;padding-bottom: 8px;}</style>');
                        sti.appendTo(grst);
                        grst.appendTo('body');
                        $("#print").print0({ operaSupport: true });
                        ev.preventDefault();
                    });

                });
            }, // end GenericContentItemBrowser

            Lightbox: function (domEl) {
                var lightboxTemplate = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl,
                    defaults = {
                        dataUrl: '/Service/Lightbox',
                        context: null,
                        attachment: 'body',
                        position: 'fixed'
                    },
                    config = $.extend({}, defaults, lightboxTemplate.data('config') || {}),
                    currentItem = 0, lightbox = null, overlay = null, items;

                var API = {
                    show: function (context) {
                        config.context = context;
                        API.refresh();
                    },

                    close: function () {
                        if (lightbox != null) {
                            lightbox.remove();
                            overlay.remove();
                            lightbox = null;
                            overlay = null;
                            currentItem = 0;
                        }
                    },

                    next: function () {
                        API.moveToPage(currentItem + 1);
                    },

                    prev: function () {
                        API.moveToPage(currentItem - 1);
                    },

                    moveToPage: function (n) {
                        if (lightbox != null) {
                            n = Math.max(0, Math.min(n, items.length - 1));
                            items.hide().eq(n).show();
                            lightbox.find('.pager:not(script) strong').text(n + 1);
                            lightbox.find('.caption:not(script)').text(items.eq(n).attr('title'));
                            currentItem = n;
                        }
                    },

                    rebuildContent: function (viewModel) {
                        $.tmpl(lightboxTemplate, viewModel).appendTo(config.attachment);
                        lightbox = $('.widget-lightbox');
                        overlay = $('.widget-overlay');
                        items = lightbox.find('>ul>li');

                        API.moveToPage(0);

                        lightbox.delegate('button', 'click', function (ev) {
                            var command = $(this).attr('class');
                            switch (command) {
                                case 'next':
                                    API.next();
                                    ev.preventDefault();
                                    break;
                                case 'prev':
                                    API.prev();
                                    ev.preventDefault();
                                    break;
                                case 'close':
                                    API.close();
                                    ev.preventDefault();
                                    break;
                            }
                        }).bind('relayout', function (ev) {
                            if (config.position === 'fixed') {
                                lightbox.css({
                                    position: config.position,
                                    top: ($(window).height() - lightbox.outerHeight()) / 2 + 'px',
                                    left: ($(window).width() - lightbox.outerWidth()) / 2 + 'px'
                                });
                            } else {
                                var offsetParent = lightbox.offsetParent();
                                lightbox.css({
                                    position: config.position,
                                    top: (offsetParent.outerHeight() - lightbox.outerHeight()) / 2 + 'px',
                                    left: (offsetParent.outerWidth() - lightbox.outerWidth()) / 2 + 'px'
                                });
                            }
                        });

                        overlay.one('click', function (ev) {
                            API.close();
                        });

                        lightbox.trigger('relayout');
                    },

                    refresh: function () {
                        $.get(config.dataUrl, { context: config.context }, function (viewModel) {
                            API.rebuildContent(Framework.augmentViewModel(viewModel, lightboxTemplate));
                        });
                    }
                };

                Framework.Registry.Lightbox = {
                    show: API.show,
                    close: API.close,
                    next: API.next,
                    prev: API.prev,
                    moveToPage: API.moveToPage,
                    refresh: API.refresh
                };
            }, // end Lightbox

            LoginBox: function (domEl) {
                var widget = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl,
                    defaults = {
                        position: 'fixed'
                    },
                    config = $.extend({}, defaults, widget.data('config') || {}),
                    lightbox = widget.find('.widget-lightbox');

                if (config.position == 'fixed') {
                    var w = $(window);
                    lightbox.css({
                        position: 'fixed',
                        top: (w.height() - lightbox.outerHeight()) / 2 + 'px',
                        left: (w.width() - lightbox.outerWidth()) / 2 + 'px'
                    });
                } else {
                    var p = lightbox.offsetParent();
                    lightbox.css({
                        position: 'absolute',
                        top: (p.outerHeight() - lightbox.outerHeight()) / 2 + 'px',
                        left: (p.outerWidth() - lightbox.outerWidth()) / 2 + 'px'
                    });
                }

                widget.hide();

                var API = {
                    show: function () {
                        widget.show();
                    },
                    hide: function () {
                        widget.hide();
                    }
                };

                widget.delegate('button.close', 'click', function (ev) {
                    API.hide();
                    ev.preventDefault();
                });

                Framework.Registry.LoginBox = {
                    show: API.show,
                    hide: API.hide
                }
            },

            PollBox: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: '/Service/GetPoll',
                            context: null,
                            submitUrl: '/Service/SubmitPoll',
                            cookieName: 'votedPolls',
                            archive: false
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        currentViewModel = null,
                        form, results; // UI elements

                    var API = {
                        refresh: function () {
                            $.get(config.dataUrl, { context: config.context }, function (data) {
                                API.rebuildContent(Framework.augmentViewModel(data, widget));
                            });
                        },

                        rebuildContent: function (viewModel) {
                            var questionList = form.find('>ol');
                            questionList.children().remove();
                            var vms = [];
                            $.each(viewModel.Questions, function (el) {
                                vms.push(Framework.augmentViewModel(this, widget));
                            });
                            $.tmpl(viewModel.templates.question, vms).appendTo(questionList);
                            results.children('[data-filter]').each(function () {
                                var filtered = $(this), section = filtered.data('filter');
                                var vms = [];
                                switch (section) {
                                    case 'all':
                                        $.each(viewModel.Questions, function (idx, el) {
                                            $.each(el.Answers, function () { this.currentVotes = this.Votes });
                                            el.Filter = 'all';
                                            vms.push(Framework.augmentViewModel(el, widget));
                                        });
                                        break;
                                    case 'female':
                                        $.each(viewModel.Questions, function (idx, el) {
                                            $.each(el.Answers, function () { this.currentVotes = this.FemaleVotes; });
                                            el.Filter = 'female';
                                            vms.push(Framework.augmentViewModel(el, widget));
                                        });
                                        break;
                                    case 'male':
                                        $.each(viewModel.Questions, function (idx, el) {
                                            $.each(el.Answers, function () { this.currentVotes = this.MaleVotes; });
                                            el.Filter = 'male';
                                            vms.push(Framework.augmentViewModel(el, widget));
                                        });
                                        break;
                                }
                                filtered.replaceWith($.tmpl(viewModel.templates.votes, vms));
                            });
                            API.switchFilter('all');
                            if (API.alreadyVoted() || config.archive) {
                                form.hide();
                                results.show();
                            } else {
                                form.show();
                                results.hide();
                            }
                            form.find('[name=PollId]').val(viewModel.PollId);
                            currentViewModel = viewModel;
                            widget.trigger('relayout');
                        },

                        isValidForm: function () {
                            var valid = true, names = [];
                            form.find('ol input').each(function (idx, el) {
                                var name = $(el).attr('name');
                                if ($.inArray(name, names) < 0) {
                                    names.push(name);
                                }
                            });
                            $.each(names, function (idx, el) {
                                if (form.find('[name=' + el + ']:checked').length == 0) {
                                    valid = false;
                                }
                            });
                            return valid;
                        },

                        submitPoll: function (gender) {
                            if (API.isValidForm()) {
                                var formData = form.serialize();
                                formData += '&Gender=' + gender + '&context=' + encodeURIComponent(config.context);
                                $.post(config.submitUrl, formData, function (data) {
                                    if ($.cookie(config.cookieName) === false) {
                                        $.cookie(config.cookieName, currentViewModel.PollId);
                                    } else {
                                        $.cookie(config.cookieName, $.cookie(config.cookieName) + ',' + currentViewModel.PollId);
                                    }
                                    API.rebuildContent(Framework.augmentViewModel(data, widget));
                                });
                            }
                        },

                        showResults: function () {
                            widget.find('form').hide().end().find('.results').show();
                            widget.find('.results [data-filter=all]').show().siblings(':not(.filter)').hide();
                        },

                        switchFilter: function (filter) {
                            var filters = widget.find('.results ul:not(.filter)').map(function (el, idx) {
                                return $(this).data('filter');
                            });
                            filter = $.inArray(filter, filters) ? filter : 'all';
                            widget.find('.results ul:not(.filter)').hide().filter('[data-filter=' + filter + ']').show();
                            results.find('.filter a').removeClass('active').end().find('.filter a[data-filter=' + filter + ']').addClass('active');
                        },

                        alreadyVoted: function () {
                            var cookie = $.cookie(config.cookieName);
                            if (cookie === null) return false;
                            var votedPolls = cookie.split(',');
                            return $.inArray(API.getPollId(), votedPolls);
                        },

                        getPollId: function () {
                            if (currentViewModel !== null) {
                                return currentViewModel.PollId;
                            }
                            return null;
                        },

                        init: function () {
                            form = widget.find('form').show();
                            results = widget.find('.results'); //.hide();
                            API.refresh();
                        }
                    };

                    widget.data('API', {
                        refresh: API.refresh,
                        submitPoll: API.submitPoll,
                        showResults: API.showResults,
                        switchFilter: API.switchFilter,
                        alreadyVoted: API.alreadyVoted
                    }).data('config', config);

                    API.init();

                    widget.delegate('.filter a', 'click', function (ev) {
                        var filter = $(this).data('filter');
                        API.switchFilter(filter);
                        ev.preventDefault();
                    }).delegate('form', 'submit', function (ev) {
                        ev.preventDefault();
                    }).delegate('form [type=submit]', 'click', function (ev) {
                        API.submitPoll($(this).val());
                        ev.preventDefault();
                    });
                });
            }, // end PollBox

            ContentAccordionBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: '/Service/Shops',
                            flashUrl: '/Content/swf/btc_small.swf',
                            flashWidth: '600',
                            flashHeight: '390',
                            context: null
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        firstLoad = true;

                    var API = {
                        show: function (letter) {
                            if (typeof letter === 'undefined') {
                                return;
                            }
                            var id = '#shops-' + letter.toString().toLowerCase(), active = $(id), list = active.find('ol:first');
                            if (list.length == 0) {
                                $.ajax({
                                    url: config.dataUrl,
                                    data: { context: config.context, initial: letter },
                                    async: false,
                                    success: function (data) {
                                        var viewModel = Framework.augmentViewModel(data, widget);
                                        viewModel.a = function (msg) { alert(msg); return ""; };
                                        $.tmpl(viewModel.templates.shopList, viewModel).appendTo(active);
                                        list = active.find('ol:first');
                                    }
                                });
                            }
                            widget.find('section>ol>li').not(active).find('ol').hide().parent().removeClass('active');
                            list.show().parent().addClass('active');
                            if (!firstLoad) $('html').animate({ scrollTop: active.offset().top }, 500);
                            firstLoad = false;
                        },
                        init: function () {
                            var id = $('li[id^=shops-]').attr('id');
                            API.show(id[id.length - 1]);
                        }
                    };

                    API.init();

                    widget.delegate('aside a', 'click', function (ev) {
                        var href = $(this).attr('href');
                        API.show(href[href.length - 1]);
                        ev.preventDefault();
                    }).delegate('section li>h4', 'click', function (ev) {
                        $(this).next('div').slideToggle('fast');
                    }).delegate('section h3', 'click', function (ev) {
                        API.show($.trim($(this).text()));
                    }).delegate('p.map-link>a', 'click', function (ev) {
                        var flashVars = {
                            queryPath: '/zemljevid/query/',
                            categoriesPath: '/zemljevid/categorydata',
                            map: $(this).attr('data-location'),
                            activeBuilding: $(this).attr('data-building')
                        }, objVars = {
                            scale: 'scale'
                        }, link = $(this);

                        $('.widget-generic-content-popup').remove();
                        $('script#map-popup-box').tmpl().appendTo('body');
                        var popup = $('.widget-generic-content-popup'),
                            name = 'flash-' + Math.ceil(Math.random() * 1000),
                            reposition = function () {
                                if (popup == null) {
                                    clearTimeout(repositionTimer);
                                    return;
                                }
                                popup.css({
                                    left: link.offset().left + link.outerWidth() + 30 + 'px',
                                    top: link.offset().top + (link.outerHeight() - popup.outerHeight()) / 2 + 'px'
                                });
                                repositionTimer = setTimeout(reposition, 200);
                            };

                        popup.children('div').append('<div id="' + name + '"/>');

                        swfobject.embedSWF(
                            config.flashUrl,
                            name,
                            config.flashWidth, config.flashHeight, '8',
                            '/Content/swf/expressInstall.swf',
                            flashVars,
                            objVars
                        );

                        reposition();

                        $('body').one('click', function (ev) {
                            $('.widget-generic-content-popup').remove();
                            ev.preventDefault();
                        });

                        return false;
                    });

                    widget.data('API', {
                        show: API.show
                    });
                });
            }, // end ContentAccordionBrowser

            AdvancedSearch: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            dataUrl: '/Service/Search',
                            context: null,
                            searchTerm: null,
                            resultsPerPage: 10
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        currentPage = 0,
                        pages = 0,
                        currentCategory = null,
                        currentViewModel = null,
                        resultLists, pagers, tabs; // UI elements

                    var API = {
                        init: function () {
                            resultLists = widget.find('.results ol[data-category]');
                            if (resultLists.length > 0) {
                                currentCategory = resultLists.eq(0);
                                currentViewModel = Framework.augmentViewModel({
                                    from: 1, to: config.resultsPerPage,
                                    current: 1, all: pages,
                                    SearchTerm: config.searchTerm,
                                    Results: $.range(1, currentCategory.children().length)
                                }, widget);
                                $.tmpl(currentViewModel.templates.pager, currentViewModel).insertBefore(resultLists.eq(0)).clone().insertAfter(resultLists.filter(':last'));
                                pagers = widget.find('.pager:not(script)');
                                tabs = widget.find('ol.tabs');
                                API.switchToCategory(resultLists.eq(0).data('category'));
                            }
                        },

                        next: function () {
                            API.switchToPage(currentPage + 1);
                        },

                        prev: function () {
                            API.switchToPage(currentPage - 1);
                        },

                        switchToPage: function (n) {
                            n = Math.max(0, Math.min(n, pages - 1));
                            var items = currentCategory.children().hide();
                            for (var i = n * config.resultsPerPage; i < (n + 1) * config.resultsPerPage; i++) {
                                items.eq(i).show();
                            }
                            var vm = {
                                from: n * config.resultsPerPage + 1,
                                to: (n + 1) * config.resultsPerPage + 1,
                                current: n + 1, all: pages,
                                Results: { length: items.length }
                            };
                            pagers.each(function () {
                                $(this).replaceWith($.tmpl(currentViewModel.templates.pager, vm));
                            });
                            pagers = widget.find('.pager:not(script)');
                            currentPage = n;
                        },

                        switchToCategory: function (name) {
                            currentCategory = resultLists.filter('[data-category=' + name + ']');
                            resultLists.hide();
                            currentCategory.show();
                            pages = Math.ceil(currentCategory.children().length / config.resultsPerPage);
                            tabs.children(':contains(' + name + ')').addClass('active').siblings().removeClass('active');
                            API.switchToPage(0);
                        },

                        getPageCount: function () {
                            return pages;
                        }
                    };

                    widget.data('API', {
                        next: API.next,
                        prev: API.prev,
                        switchToPage: API.switchToPage,
                        getPageCount: API.getPageCount
                    });

                    API.init();

                    widget.delegate('.pager button', 'click', function (ev) {
                        switch ($(this).attr('class')) {
                            case 'next':
                                API.next();
                                break;
                            case 'prev':
                                API.prev();
                                break;
                        }
                        ev.preventDefault();
                    }).delegate('.tabs li a', 'click', function (ev) {
                        API.switchToCategory($(this).text());
                        ev.preventDefault();
                    });
                });
            }, // end AdvancedSearch

            ImageBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        pages = 0, currentPage = 0, itemsPerPage = 3, scrollWidth = 0, currentItem = 0,
                        currentViewModel = null,
                        items, list, lightbox; // UI elements

                    var API = {
                        next: function () {
                            API.goToPage(currentPage + 1);
                        },
                        prev: function () {
                            API.goToPage(currentPage - 1);
                        },
                        goToPage: function (n) {
                            n = Math.max(0, Math.min(n, pages - 1));
                            list.stop().animate({
                                left: -n * scrollWidth + 'px'
                            }, 'fast');
                            currentPage = n;
                        },
                        openLightbox: function (n) {
                            var box, LBAPI;
                            n = Math.max(0, Math.min(n, items.length - 1));
                            if (currentViewModel == null) {
                                currentViewModel = Framework.augmentViewModel({
                                    Images: items.map(function (idx, el) {
                                        var img = $(el).find('img');
                                        return {
                                            Caption: img.attr('title'),
                                            ImageUrl: img.attr('src'),
                                            Description: img.attr('alt')
                                        };
                                    }),
                                    CurrentImage: n,
                                    Title: widget.find('h2').text()
                                }, widget);
                            }
                            $.tmpl(currentViewModel.templates.lightbox, currentViewModel).appendTo('body');
                            lightbox = $('.widget-image-browser-lightbox');
                            box = lightbox.children('.widget-lightbox');
                            box.css({
                                left: ($(window).width() - box.outerWidth()) / 2 + 'px',
                                top: ($(window).height() - box.outerHeight()) / 2 + 'px'
                            });

                            LBAPI = {
                                next: function () {
                                    LBAPI.goToItem(currentItem + 1);
                                },
                                prev: function () {
                                    LBAPI.goToItem(currentItem - 1);
                                },
                                goToItem: function (n) {
                                    n = Math.max(0, Math.min(n, items.length - 1));
                                    box.find('ul li').eq(n).show().siblings().hide();
                                    currentItem = n;
                                    box.find('.pager strong').text(n + 1);
                                    box.find('.caption').text(box.find('ul li').eq(n).find('img').attr('title'));

                                        var a = box.find('ul li').eq(n).find('img');
                                        if(a.attr('height')>545) {
                                            a.attr('height', '545');
                                        }else {
                                            if (a.attr('width') > 650) {
                                                a.attr('width', '650');
                                            }
                                        }                                    
                                }
                            };

                            lightbox.delegate('button.close', 'click', function (ev) {
                                API.closeLightbox();
                                return false;
                            }).delegate('button.prev, button.next', 'click', function (ev) {
                                if ($(this).is('.prev')) {
                                    LBAPI.prev();
                                } else {
                                    LBAPI.next();
                                }
                                return false;
                            }).delegate('.widget-overlay', 'click', function (ev) {
                                API.closeLightbox();
                                ev.preventDefault();
                            });

                            LBAPI.goToItem(n);
                        },
                        closeLightbox: function () {
                            if (lightbox != null) {
                                lightbox.remove();
                                lightbox = null;
                            }
                        },
                        init: function () {
                            widget.append('<button class="prev">Nazaj</button><button class="next">Naprej</button>');
                            widget.find('ul').wrap('<div class="wrapper"/>');
                            list = widget.find('ul');
                            items = list.children();
                            scrollWidth = items.eq(0).outerWidth(true) * itemsPerPage;
                            pages = Math.ceil(items.length / itemsPerPage);
                            API.goToPage(0);
                        }
                    };

                    widget.delegate('button', 'click', function (ev) {
                        var action = $(this).attr('class');
                        switch (action) {
                            case 'prev':
                                API.prev();
                                break;
                            case 'next':
                                API.next();
                                break;
                        }
                        ev.preventDefault();
                    }).delegate('li', 'click', function (ev) {
                        API.openLightbox($(this).index());
                        ev.preventDefault();
                    });

                    widget.data('API', {
                        next: API.next,
                        prev: API.prev,
                        openLightbox: API.openLightbox,
                        closeLightbox: API.closeLightbox
                    });

                    API.init();
                });
            }, // end ImageBrowser

            VideoBrowser: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        pages = 0, currentPage = 0, itemsPerPage = 3, scrollWidth = 0, currentItem = 0,
                        urlTemplate = 'http://www.youtube.com/e/%id%?enablejsapi=1&version=3',
                        videoContainerId = 'video-' + Math.ceil(Math.random() * 1e8),
                        items, list, videoContainer;

                    var API = {
                        next: function () {
                            API.goToPage(currentPage + 1);
                        },
                        prev: function () {
                            API.goToPage(currentPage - 1);
                        },
                        goToPage: function (n) {
                            n = Math.max(0, Math.min(n, pages - 1));
                            list.stop().animate({
                                left: -n * scrollWidth + 'px'
                            }, 'fast');
                            currentPage = n;
                        },
                        goToItem: function (n) {
                            n = Math.max(0, Math.min(n, items.length - 1));
                            items.eq(n).addClass('current').siblings().removeClass('current');
                            videoContainer.children().remove();
                            swfobject.embedSWF(
                                urlTemplate.replace('%id%', items.eq(n).data('video-id')),
                                videoContainerId,
                                '420', '315', '10',
                                '/Content/swf/expressInstall.swf',
                                null,
                                { allowFullScreen: 'true', wmode: 'transparent' }
                            );
                            currentItem = n;
                        },
                        init: function () {
                            widget.find('ul').wrap('<div class="wrapper"/>');
                            widget.append('<button class="prev">Nazaj</button><button class="next">Naprej</button>');
                            list = widget.find('ul');
                            items = list.children();
                            pages = Math.ceil(items.length / itemsPerPage);
                            scrollWidth = items.outerWidth(true) * itemsPerPage;
                            videoContainer = widget.find('.video-container');
                            videoContainer.attr('id', videoContainerId);
                            API.goToPage(0);
                            API.goToItem(0);
                        }
                    };

                    widget.data('API', {
                        next: API.next,
                        prev: API.prev
                    });

                    API.init();

                    widget.delegate('button.prev,button.next', 'click', function (ev) {
                        if ($(this).is('.next')) {
                            API.next();
                        } else {
                            API.prev();
                        }
                        ev.preventDefault();
                    }).delegate('li', 'click', function (ev) {
                        API.goToItem($(this).index());
                        ev.preventDefault();
                    });
                });
            }, // end VideoBrowser

            StarRating: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            context: null,
                            dataUrl: null,
                            ratingId: 0,
                            rating: 0,
                            stars: 5,
                            cookieName: "starRating"
                        },
                        config = $.extend({}, defaults, widget.data('config') || {}),
                        elements; // UI elements

                    var API = {
                        init: function () {
                            var viewModel = Framework.augmentViewModel({}, widget),
                                userVote = API.getVote();
                            for (var i = 1; i <= config.stars; i++) {
                                $.tmpl(viewModel.templates.star, {
                                    Voted: (userVote != null) ? i <= API.getVote() : false,
                                    Rated: i <= config.rating
                                }).appendTo(widget);
                            }
                            elements = widget.children('li');
                        },
                        update: function (rating, vote) {
                            elements.each(function (idx, el) {
                                if (idx + 1 <= rating) $(el).addClass('rated'); else $(el).removeClass('rated');
                                if (idx + 1 <= vote) $(el).addClass('voted'); else $(el).removeClass('voted');
                            });
                        },
                        vote: function (vote) {
                            if (!API.alreadyVoted() && !widget.is('.locked')) {
                                $.post(config.dataUrl, { context: config.context, ratingId: config.ratingId, vote: vote }, function (data) {
                                    var cookie = $.cookie(config.cookieName) || '',
                                        ratings = cookie.split(',');
                                    ratings.push(config.ratingId + '=' + vote);
                                    $.cookie(config.cookieName, ratings.join(','));
                                    widget.addClass('locked');
                                    API.update(data.Rating, vote);
                                    API.showMessage('Hvala za vaš glas!');
                                });
                            }
                        },
                        getVote: function () {
                            var cookie = $.cookie(config.cookieName) || '',
                                ratings = cookie.split(','),
                                r = new RegExp('^' + config.ratingId + '=');

                            for (var i = 0; i < ratings.length; i++) {
                                if (r.test(ratings[i])) {
                                    return parseInt(ratings[i].split('=')[1]);
                                }
                            }
                            return null;
                        },
                        alreadyVoted: function () {
                            return ($.cookie(config.cookieName) || '').indexOf(config.ratingId) > -1;
                        },
                        showMessage: function (message) {
                            var viewModel = Framework.augmentViewModel({ Message: message }, widget),
                                msg = $.tmpl(viewModel.templates.message, viewModel).appendTo('body').css('position', 'absolute');
                            msg.css({
                                opacity: 0,
                                top: widget.offset().top + 'px',
                                left: widget.offset().left + ((widget.outerWidth(true) - msg.outerWidth(true)) / 2) + 'px'
                            }).animate({
                                opacity: 1,
                                top: '-=20px'
                            }, 500);

                            setTimeout(function () {
                                msg.fadeOut(500).queue(function () { $(this).remove(); });
                            }, 5000);
                        }
                    };

                    API.init();

                    widget.data('API', {
                        vote: API.vote,
                        alreadyVoted: API.alreadyVoted
                    });

                    widget.delegate('li', 'click', function (ev) {
                        API.vote(elements.index(this) + 1);
                        ev.preventDefault();
                    });
                });

            }, // end StarRating

            MapPopup: function (domEl) {
                var widgets = (typeof domEl.jquery === 'undefined') ? $(domEl) : domEl;

                return widgets.each(function () {
                    var widget = $(this),
                        defaults = {
                            flashUrl: '/Content/swf/btc.swf?a=1',
                            flashVars: { queryPath: '/zemljevid/query/', categoriesPath: '/zemljevid/categorydata' },
                            params: { scale: 'scale' },
                            width: '600',
                            height: '390'
                        },
                        config = $.extend(true, {}, defaults, widget.data('config') || {}),
                        repositionTimer = null,
                        popup = null; // UI elements


                    var showPopup = function () {
                        $('.widget-generic-content-popup').remove();
                        popup = null;
                        $('script#map-popup-box').tmpl().appendTo('body');
                        popup = $('.widget-generic-content-popup');

                        var name = 'flash-' + Math.ceil(Math.random() * 1000),
                            reposition = function () {
                                if (popup == null) {
                                    clearTimeout(repositionTimer);
                                    return;
                                }
                                popup.css({
                                    left: widget.offset().left + widget.outerWidth() + 30 + 'px',
                                    top: widget.offset().top + (widget.outerHeight() - popup.outerHeight()) / 2 + 'px'
                                });
                                repositionTimer = setTimeout(reposition, 100);
                            };

                        popup.children('div').append('<div id="' + name + '"/>');

                        swfobject.embedSWF(
                            config.flashUrl,
                            name,
                            config.width, config.height, '8',
                            '/Content/swf/expressInstall.swf',
                            config.flashVars,
                            config.params
                        );

                        reposition();
                    }

                    widget.click(function (ev) {
                        showPopup();
                        return false;
                    });

                    $('body').click(function (ev) {
                        if (popup) popup.remove();
                        popup = null;
                    });
                });
            } // end MapPopup

        }, // end Widgets

        Registry: {}
    };

    $.extend(ß, { Framework: Framework });

})(jQuery, BTC);

