/** * jQuery plugins for OnOff * API reference: http://docs.jquery.com/ */ // Closure for plugins (function($) { /** * Easing equations * Used in animations */ $.extend($.easing, { // Exponential ease out equation // Original by Robert Penner (www.robertpenner.com) expoOut: function(p, n, firstNum, diff, duration) { return (n == duration) ? firstNum + diff : diff * (-Math.pow(2, -10 * n/duration) + 1) + firstNum; } }); /** * Carousel plugin */ $.fn.carousel = function(options) { // Set default options var o = $.extend({ duration: 1600, interval: 5000, nextClass: 'next', prevClass: 'previous', width: 750 }, options); // Return jQuery object return this.each(function() { // Vars for carousel itself, list of links, list of items var self = $(this), slides = $('ul', this), items = slides.children().length; var buttonNext = $('').addClass(o.nextClass).appendTo(self), buttonPrev = $('').addClass(o.prevClass).appendTo(self); // Store position $.data(self, 'position', 0); // Bind the click event to controls buttonNext.add(buttonPrev).bind('click.carousel', function() { var position = $.data(self, 'position'); // Go to next if($(this).hasClass(o.nextClass)) position = position + 2 > items ? 0 : position + 1; // Go to previous else position = position -1 < 0 ? items - 1 : position - 1; // Store the new position $.data(self, 'position', position); // Calculate the offset based on position and item width var offset = position * o.width; slides.animate( { left: -offset }, { duration: o.duration, easing: 'expoOut', queue: false } ); }); // Function for automatic rotation of carousel var rotate = function() { // Trigger click on button :) buttonNext.trigger('click'); } // Set a timer that runs the rotate function in intervals $.data(self, 'timer', window.setInterval(rotate, o.interval)); // When the mouse enters the carousel, stop the timer self.bind('mouseenter.carousel', function() { window.clearInterval($.data(self, 'timer')); }) // When the mouse leaves the carousel, start the timer again .bind('mouseleave.carousel', function() { $.data(self, 'timer', window.setInterval(rotate, o.interval)); }); }); } /** * Tabs plugin * Unobtrusively adds tab functionality to a list of links */ $.fn.tabs = function(options) { // Set default options var o = $.extend({ activeClass: 'active', tabbedClass: 'tabbed' }, options); // Return jQuery object return this.each(function() { // Vars for the list itself, and for the links it contains var self = $(this), links = $('a', this); // Enumerate links links.each(function() { // Get link href... var target = $(this).attr('href'); // So that we can find the element it points to // Add a class to target element // $(target).addClass(o.tabbedClass); // Bind click event to function $(this).bind('click.tabs', function() { // Add class to link parent, remove it from other links $(this).parent().addClass(o.activeClass).siblings().removeClass(o.activeClass); // Show target of this link, and hide other targets $(target).show().siblings('.' + o.tabbedClass).hide(); // Don't follow the link return false; }); }); }); } /** * Tabs plugin part 2 * Unobtrusively adds tab functionality to a list of links */ $.fn.tabs2 = function(options) { // Set default options var o = $.extend({ activeClass: 'active', tabbedClass: 'tabbed2' }, options); // Return jQuery object return this.each(function() { // Vars for the list itself, and for the links it contains var self = $(this), links = $('a', this); // Enumerate links links.each(function() { // Get link href... var target = $(this).attr('href'); // So that we can find the element it points to // Add a class to target element // $(target).addClass(o.tabbedClass); // Bind click event to function $(this).bind('click.tabs2', function() { // Add class to link parent, remove it from other links $(this).parent().addClass(o.activeClass).siblings().removeClass(o.activeClass); // Show target of this link, and hide other targets $(target).show().siblings('.' + o.tabbedClass).hide(); // Don't follow the link return false; }); }); }); } /** * Tabs plugin part 3 * Unobtrusively adds tab functionality to a list of links */ $.fn.tabs3 = function(options) { // Set default options var o = $.extend({ activeClass: 'active', tabbedClass: 'tabbed3' }, options); // Return jQuery object return this.each(function() { // Vars for the list itself, and for the links it contains var self = $(this), links = $('a', this); // Enumerate links links.each(function() { // Get link href... var target = $(this).attr('href'); // So that we can find the element it points to // Add a class to target element // $(target).addClass(o.tabbedClass); // Bind click event to function $(this).bind('click.tabs3', function() { // Add class to link parent, remove it from other links $(this).parent().addClass(o.activeClass).siblings().removeClass(o.activeClass); // Show target of this link, and hide other targets $(target).show().siblings('.' + o.tabbedClass).hide(); // Don't follow the link return false; }); }); }); } /** * Tabs plugin part 4 * Unobtrusively adds tab functionality to a list of links */ $.fn.tabs4 = function(options) { // Set default options var o = $.extend({ activeClass: 'active', tabbedClass: 'tabbed4' }, options); // Return jQuery object return this.each(function() { // Vars for the list itself, and for the links it contains var self = $(this), links = $('a', this); // Enumerate links links.each(function() { // Get link href... var target = $(this).attr('href'); // So that we can find the element it points to // Add a class to target element // $(target).addClass(o.tabbedClass); // Bind click event to function $(this).bind('click.tabs4', function() { // Add class to link parent, remove it from other links $(this).parent().addClass(o.activeClass).siblings().removeClass(o.activeClass); // Show target of this link, and hide other targets $(target).show().siblings('.' + o.tabbedClass).hide(); // Don't follow the link return false; }); }); }); } /** * Tabs plugin 5 * Unobtrusively adds tab functionality to a list of links */ $.fn.tabs5 = function(options) { // Set default options var o = $.extend({ activeClass: 'active', tabbedClass: 'tabbed5' }, options); // Return jQuery object return this.each(function() { // Vars for the list itself, and for the links it contains var self = $(this), links = $('a', this); // Enumerate links links.each(function() { // Get link href... var target = $(this).attr('href'); // So that we can find the element it points to // Add a class to target element // $(target).addClass(o.tabbedClass); // Bind click event to function $(this).bind('click.tabs5', function() { // Add class to link parent, remove it from other links $(this).parent().addClass(o.activeClass).siblings().removeClass(o.activeClass); // Show target of this link, and hide other targets $(target).show().siblings('.' + o.tabbedClass).hide(); // Don't follow the link return false; }); }); }); } /** * Sliding drawers plugin * Currently unused * $.fn.drawers = function(options) { // Default options var o = $.extend({ duration: 200, distance: 500, spacing: 30 }, options); // Return jQuery object return this.each(function() { var count = $(this).children().size(), height = o.spacing * count + o.distance; $(this).css('height', height) .children().addClass('up').css('height', height) .each(function(i) { $(this).css({ top: i * o.spacing, zIndex: i + 1 }); }) .bind('click.drawers', function() { var target = $(this); target.addClass('active').nextAll().removeClass('active') .filter('.up').removeClass('up') .animate({ marginTop: o.distance }, o.duration); target.prevAll().removeClass('active').andSelf().not('.up').addClass('up') .animate({ marginTop: 0 }, o.duration); }); }); }*/ /** * Vertical image alignment plugin */ $.fn.align = function(options) { // Default options var o = $.extend({ duration: 200, parentHeight: 65 }, options); return this.each(function() { // Get height of image and calculate position var height = $(this).height(), pHeight = $(this).parent().height() margin = (pHeight/2) - (height/2); // Set the correct margin //$(this).animate({ marginTop: margin }, o.duration); $(this).css('margin-top', margin); }); } /** * Simple toggle plugin * Used for toggling review form */ $.fn.toggle = function(options) { // Set default options var o = $.extend({ // Duration for animation duration: 400, activeClass: 'active', // Properties to animate props: { height: 'toggle', opacity: 'toggle' } }, options); // Return jQuery object return this.each(function() { // IE and older lizards have problems with opacity if(($.browser.msie && $.browser.version < 8.0) || ($.browser.mozilla && $.browser.version.substring(0,3) < 1.9)) { // So let's remove it delete o.props.opacity; } // Bind click event to toggle function $(this).bind('click.toggle', function(e) { // Switch the text content with the rev attribute var oldText = $(this).text(), newText = $(this).attr('rev') || oldText; $(this).text(newText).attr('rev', oldText); // Get the target element of this link var target = $(this).attr('href'); // Animate the target element using previously defined properties $(target).animate(o.props, { duration: o.duration, easing: 'expoOut' }); // Toggle active class on clicked link $(this).toggleClass(o.activeClass); // Prevent default action of following the link return false; }); }); } /** * Modal window script * Displays content in a modal window */ $.modal = { // Object for options options: { exploder: $.browser.msie && $.browser.version < 7 }, // Initialize modal init: function(options) { // Save options $.extend($.modal.options, options); // Create elements for overlay // and modal window $.modal.overlay = $('
') .attr('id', $.modal.options.overlayId) .appendTo('body'), $.modal.window = $('
') .attr('id', $.modal.options.modalId) .appendTo('body'), $.modal.content = $('
') .appendTo($.modal.window), $.modal.close = $('

') .addClass('close') .text('sulje') .attr('id', "close") .prependTo($.modal.window); if($.browser.msie && $.browser.version < 8.0) { // Re-set MSIE "opacity", sadly did not work if specified in CSS $.modal.overlay.css('opacity', '0.6'); } // Hide everything if overlay is clicked $.modal.overlay.add($.modal.close) .bind('click.modal', function(e) { // Check so that it's either the overlay // or the close button if (e.target === this) $.modal.hide(); }); }, // Method for showing the modal show: function(content) { // Fix IE bugs if ($.modal.options.exploder) $('select').css('visibility', 'hidden'); // Show overlay $.modal.overlay.animate({ opacity: 'show' }, { duration: $.modal.options.duration, easing: 'expoOut', // Show modal window complete: function() { // Put content into window $.modal.content.html(content); // Get dimensions of content, hiding off-screen var width = $.modal.content.width(), height = $.modal.content.height(); // Set it to a fixed width $.modal.content.width(width); // Get document element var top = document.documentElement.scrollTop || document.body.scrollTop; // Window height var viewHeight = $(window).height(); // Hide it, move it into view $.modal.window.css({ display: 'none', left: '50%', marginLeft: -(width/2), marginTop: -(height/2), // Make sure it doesn't go up outside the view top: (top + (viewHeight/2) - (height/2)) < top ? top + height/2 : top + (viewHeight/2) }) // Show it with an animation .animate({ opacity: 'show' }, { duration: $.modal.options.duration, easing: 'expoOut' }); } }); }, // Method for hiding the modal hide: function() { $.modal.window.animate({ opacity: 'hide' }, { duration: $.modal.options.duration, easing: 'expoOut', complete: function() { // Unfix fixed IE bugs if ($.modal.options.exploder) $('select').css('visibility', 'visible'); // Clear the content $.modal.content.empty(); $.modal.window.css({ display: 'block', left: '-1000%' }); $.modal.overlay.animate({ opacity: 'hide' }, { duration: $.modal.options.duration, easing: 'expoOut' }); } }); } } /** * Modal plugin * Inits the modal via jQuery */ $.fn.modal = function(options) { // Set default options var o = $.extend({ duration: 400, overlayId: 'overlay', modalId: 'modal' }, options); // Initialize modal $.modal.init(o) // Return jQuery object return this.each(function() { // Find out what content to show var self = this, href = $(this).attr('href'), target = $(href), content = target.html(); $(self).bind('click.modal', function() { // Show the modal with the desired content $.modal.show(content); // Don't follow link return false; }); }); } /** * Remote click plugin * for triggering clicks on other links * scrolls the target into view, if it isn't */ $.fn.remote = function(options) { // Set default options var o = $.extend({ duration: 800, margin: 50 }, options); return this.each(function() { // Get the href var href = $(this).attr('href'), // Get the index of the link that should be clicked, or 0 index = $(this).attr('rel').split(' ')[1] || '1'; $(this).bind('click', function() { // Find the right link with the same href and click it var target = $('a[href="' + href + '"]').slice(index - 1, index), offset = target.offset().top, current = $(this).offset().top; var scroll = document.documentElement.scrollTop || document.body.scrollTop; var viewHeight = $(window).height(); // If it's out of view, or below the clicked link, scroll to it if(offset > current || offset < (scroll + o.margin)) { // var height = $(window).height(); $('html, body').animate( { scrollTop: offset - o.margin }, { duration: o.duration, easing: 'expoOut', complete: function() { // Click the link when the animation finishes target.trigger('click') } }); } else { // Click the link immediately target.trigger('click') } return false; }); }); } /** * Equalize plugin * Used for equal height columns/items */ $.fn.equalize = function(options) { // Array to keep the heights in var heights = []; // Enumerate items and push each height into the array this.each(function() { var height = $(this).outerHeight(); heights.push(height); }); // Sort the array and reverse it to get the biggest first heights.sort().reverse(); // Get the biggest one var height = heights[0] + 1; // Rounding errors // Fix IE6 if($.browser.msie && $.browser.version < 7.0) { return this.css('height', height); } // Return jQuery object and set height on all items in it return this.css('min-height', height); } /** * Fields that show/hide when inputs are changed */ $.fn.fields = function(options) { // Set default options var o = $.extend({ duration: 800 }, options); return this.each(function() { $(this).bind('change.fields', function() { // get the alt attribute var alt = $(this).attr('alt'), // find out what to show, if anything show = alt.match(/show\(([^\)]+)\)/), // find out what to hide, if anything hide = alt.match(/hide\(([^\)]+)\)/), // find out where to scroll, if anywhere scroll = alt.match(/scroll\(([\+\-=\d]+)\)/); //console.log('Visa: ' + show + ', göm: ' + hide + ', scrolla: ' + scroll); if(hide) { $(hide[1]).hide(); } if(show) { $(show[1]).show(); } if(scroll) { $('html, body').animate( { scrollTop: scroll[1] }, { duration: o.duration, easing: 'expoOut' } ); } }) .filter(':checked') .trigger('change'); // Firefox likes to save input state, // but nothing else... }); } /** * Tooltips for anything with a title */ $.fn.tooltip = function(options) { // Set default options var o = $.extend({ tipClass: 'tooltip', delay: 200, duration: 400 }, options); return this.each(function() { // Save title for later $.data(this, 'title', $(this).attr('title')); // No need for this now $(this).removeAttr('title'); $(this).bind('mouseenter.tooltip', function(e) { if(! $.data(this, 'tooltip') ) { var text = $.data(this, 'title'), top = $(this).offset().top + $(this).outerHeight(), left = $(this).offset().left + $(this).outerWidth()/2; var tooltip = $('

').text(text).addClass(o.tipClass) .css({ top: top, left: left }).appendTo('body'); $('').appendTo(tooltip); var width = tooltip.outerWidth(); tooltip.css({ marginLeft: - width/2 }); $.data(this, 'tooltip', tooltip); } var tooltip = $.data(this, 'tooltip'); $.data(this, 'timer', window.setTimeout(function() { tooltip.animate( { opacity: 'show' }, { duration: o.duration, easing: 'expoOut' } ); }, o.delay)) }).bind('mouseleave.tooltip', function(e) { window.clearTimeout( $.data(this, 'timer') ); $.data(this, 'tooltip') .animate( { opacity: 'hide' }, { duration: o.duration, easing: 'expoOut' } ); }); }); } })(jQuery); // On DOM ready jQuery(function($) { // Add class 'js' to html element // For styles that should only be applied when JS is available $('body').addClass('js'); // Equalize item heights $('ul.department > li').equalize(); $('div.main div.featured div.product').equalize(); $('div.checkout div.accessory').equalize(); // Initialize carousel plugin // Used on start page $('div.carousel').carousel(); // Initialize tabs plugin and trigger a click on the active tab $('ul.tabs').tabs().find('li.active a').trigger('click'); // Initialize tabs2 plugin and trigger a click on the active tab $('ul.tabs2').tabs2().find('li.active a').trigger('click'); // Initialize tabs3 plugin and trigger a click on the active tab $('ul.tabs3').tabs3().find('li.active a').trigger('click'); // Initialize tabs4 plugin and trigger a click on the active tab $('ul.tabs4').tabs4().find('li.active a').trigger('click'); // Initialize tabs5 plugin and trigger a click on the active tab $('ul.tabs5').tabs5().find('li.active a').trigger('click'); // Use drawers plugin // $('ul.drawers').drawers({ distance: 382 }); // Toggle plugin $('a[rel="toggle"]').toggle(); // Remote plugin $('a[rel^="remote"]').remote(); // Modal plugin (should only be called once) $('a[rel="modal"]').modal(); // Tooltip plugin $('#content .tip[title]').tooltip(); // Fields plugin $('input[alt]').fields(); // Add a class to all odd rows of a table body, for zebra striped tables $('tbody tr:nth-child(2n+1)').addClass('odd'); // Clearfix on start page $('

').css({ width: '100%', clear: 'both' }) .insertAfter('div.start div.featured:odd'); // Clear search input value the first time it receives focus $('#header input').one('focus.clear', function() { $(this).removeAttr('value'); }); // Print links :) $('a[rel="print"]').bind('click.print', function() { window.print(); return false; }); // Fix labels and stuff in IE6 if($.browser.msie && $.browser.version < 7.0) { $('label:has(input)').bind('click.iefix', function() { $('input', this).trigger('click'); }); $('legend').remove(); } }); // On load jQuery(window).bind('load.onoff', function() { // Use image centering plugin now that images are loaded if(jQuery.browser.msie && jQuery.browser.version < 7.0) { jQuery('div.column.last ul:visible p.photo img').align(); jQuery('div.column.checkout table span.photo img').align(); jQuery('div.column.main div.product p.photo img').align(); jQuery('div.column.main div.history img').align(); // Not needed here anymore since images have fixed dimensions // jQuery('ul.department img, ul.department-categories img').align(); } });