/* * @copyright © Copyright 2006-2012, epages GmbH, All Rights Reserved. * * @module ep.ui.core */ /*jslint browser: true, plusplus: true, nomen: true, ass: true, todo: true, regexp: true*/ /*global define*/ define("ep/ui/core", ["jquery", "ep", "util/scope"], function ($, ep, scope) { 'use strict'; /** * @class ep.ui * */ var ui = scope("ep.ui"), getId = function (selector) { var id = ""; if (typeof selector === "string") { id = selector; } else if (selector instanceof $) { id = selector.selector; } if (!id) { if (!selector[$.expando]) { selector[$.expando] = ++$.guid; } id = "Expando:" + selector[$.expando]; } return id; }, getElemData = function (item, stack) { var type = $.type(item), itemData = {}, data, elem; if (type === "string") { data = { src: item, desc: "" }; } else if (item.nodeType) { elem = $(item); if (elem.is("img")) { itemData = elem.data(); // get href from parent node if available itemData.href = elem.closest("a") .attr("href"); data = { node: item, src: elem.attr("src"), desc: (elem.attr("title") || elem.attr("alt")) .replace(/\\\\n/g, "\n") }; } } else if (type === "object" && item.src) { itemData = item; data = { src: item.src, desc: item.desc || "" }; } if (data) { data.srcL = itemData.srcL || itemData.srcM || data.src; data.srcMl = itemData.srcMl || data.srcL; data.srcM = itemData.srcM || data.srcMl; data.srcMs = itemData.srcMs || data.srcM; data.srcS = itemData.srcS || data.srcM; data.srcXs = itemData.srcXs || data.srcS; data.href = itemData.href || data.srcL; // Method to get the best src for the given container data.getSrcFor = function (selector) { var box = selector instanceof $ ? selector : $(selector), boxWidth = box.innerWidth(), boxHeight = box.innerHeight(), imgSrc; if (boxWidth >= 750 || boxHeight >= 750) { imgSrc = data.srcL; } else if (boxWidth >= 350 || boxHeight >= 350) { imgSrc = data.srcMl; } else if (boxWidth >= 200 || boxHeight >= 200) { imgSrc = data.srcM; } else if (boxWidth >= 100 || boxHeight >= 100) { imgSrc = data.srcMs; } else if (boxWidth >= 75 || boxHeight >= 75) { imgSrc = data.srcS; } else { imgSrc = data.srcXs; } return imgSrc; }; // Returns alternative src if base name matches the default src, else return default src. // TODO: Should be removed after disable the posibility to upload different images data._checkSrcName = function (defaultSrc, alternativeSrc) { var alternativeName = alternativeSrc.replace(/(_(xs|s|ms|m|ml|l))?\.[^\.]+$/i, ""), defaultName = defaultSrc.replace(/(_(xs|s|ms|m|ml|l))?\.[^\.]+$/i, ""); return alternativeName === defaultName ? alternativeSrc : defaultSrc; }; stack.push(data); } }; /** * @class ep.ui.imgData * */ /** * The `ep.ui.imgData()` method read the extended image data of elements an handle them in an array like object. * * The item objects of an image data object: * { * "desc" : <description>, * "href" : <path to an url / image>, * "src" : <path to default image>, * "srcXs": <path to thumbnail image>, * "srcS" : <path to small image>, * "srcM" : <path to medium image>, * "srcL" : <path to large image>, * "node" : <the source DOM element (optional)> * } * * ### Examples * Find all images. * * JavaScript: * * ep.ui.imgData('img'); * * HTML: * * <ul> * <li> * <a href="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010.jpg"> * <img * alt="Eureka El Capitan IV" * src="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010.jpg" * data-src-xs="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_xs.jpg" * data-src-s="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_s.jpg" * data-src-m="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_m.jpg" * data-src-l="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010.jpg" * /> * </a> * </li> * <li> * <a href="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_2.jpg"> * <img * alt="Eureka El Capitan IV" * src="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_2.jpg" * data-src-xs="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_2_xs.jpg" * data-src-s="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_2_s.jpg" * data-src-m="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_2_m.jpg" * data-src-l="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_2.jpg" * /> * </a> * </li> * <li> * <a href="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_3.jpg"> * <img * alt="Eureka El Capitan IV" * src="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_3.jpg" * data-src-xs="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_3_xs.jpg" * data-src-s="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_3_s.jpg" * data-src-m="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_3_m.jpg" * data-src-l="/WebRoot/Store/Shops/DemoShop/Products/eg_1000111010/eg_1000111010_3.jpg" * /> * </a> * </li> * </ul> * * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @param {String OR Element OR Object OR Array OR Array} p A string containing a selector expression to find images OR An image DOM element OR An existing jQuery object containing images OR An array containing a set of image DOM elements OR An array containing a set of imageData items. * * @fires change * @fires resize * @fires resizestop * * @method constructor * @member ep.ui.imgData * * @since 6.14.0 */ ui.imgData = function (selector) { var id = getId(selector), result = ui.imgData.cache[id], type, data; if (!result) { type = $.type(selector); data = []; if (type === "string" && !(/\//).test(selector)) { $(selector).each(function () { getElemData(this, data); }); } else if (type === "array") { $.each(selector, function (i, item) { /*jslint unparam: true */ getElemData(item, data); }); } else if (selector instanceof $) { selector.each(function () { getElemData(this, data); }); } else if (type === "string" || (type === "object" && (selector.src || selector.nodeType))) { getElemData(selector, data); } result = new ui.imgData.init(data); result.on("location", function () { var href = (result.current() || {}) .href; if (href) { location.href = href; } }); if (id) { ui.imgData.cache[id] = result; } } return result; }; ui.imgData.cache = {}; /** * Initialize a new instance of ep.ui.imgData. * * @param {Array} stack of image information objects. * * @method init * @static * @member ep.ui.imgData * * @since 6.14.0 */ /** * @event resize This event is triggered while the window resize. * @member ep.ui.imgData */ /** * @event resizestop This event is triggered when the window resize is stopped. * @member ep.ui.imgData */ ui.imgData.init = function (data) { var self = this; self.eventObject = $('<div/>'); $(window) .on("resize", function () { // trigger resize self.trigger("resize"); // clear trigger delay clearTimeout(self._resizestopdelay); // trigger a special event when resize stopped self._resizestopdelay = setTimeout(function () { self.trigger("resizestop"); }, 100); }); return $.merge(self, data); }; ui.imgData.init.prototype = { length: 0, currentItem: 0, /** * Iterate over a imaga data object, executing a function for each item. * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @param {Function} callback The function that will be executed on every image data item object. * * @method each * @member ep.ui.imgData * * @since 6.14.0 */ each: $.fn.each, /** * Retrieve the items matched by the image data object. * * The `.get()` method grants us access to the items underlying each image data object. Without a parameter, * `.get()` returns an array of all items. * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @param {Boolean} [index] A zero-based integer indicating which item to retrieve. * * @method get * @member ep.ui.imgData * * @since 6.14.0 */ get: function (i) { return arguments.length ? this[i] : $.merge([], this); }, /** * Retrieve the item which is marked as current of the image data object (if no argument is given) or * mark an item of the image data object as current (if an argument is given). * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @param {Boolean} [index] A zero-based integer indicating which item to mark as current. * * @method current * @member ep.ui.imgData * * @since 6.14.0 */ /** * @event change This event is triggered when the current item of image dat object is changed. * @member ep.ui.imgData */ current: function (i) { var result, set; if (arguments.length) { set = this.currentItem; if (i === 'next') { set++; } else if (i === 'prev') { set--; } else { set = i; } if (set === this.currentItem || set >= this.length || set < 0) { result = this; } else { this.currentItem = set; result = this.trigger('change'); } } else { result = this.get(this.currentItem); } return result; }, /** * Retrieve the item before the current item of the image data object. * * May is `undefined`, if current item the first of the image data object. * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @method prev * @member ep.ui.imgData * * @since 6.14.0 */ prev: function () { return this.get(this.currentItem - 1); }, /** * Retrieve the item after the current item of the image data object. * * May is `undefined`, if current item the last of the image data object. * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @method next * @member ep.ui.imgData * * @since 6.14.0 */ next: function () { return this.get(this.currentItem + 1); }, first: function () { return this.get(0); }, last: function () { return this.get(this.length - 1); }, /** * Attach an event handler function for one or more events to the image data object. * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @param {String} events One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin". * @param {Function} handler(eventObject) A function to execute when the event is triggered. * * @method on * @member ep.ui.imgData * * @since 6.14.0 */ on: function (events, handler) { this.eventObject.on(events, $.proxy(handler, this)); return this; }, /** * Remove an event handler from the image data object. * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @param {String} events One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin". * @param {Function} [handler] A handler function previously attached for the event(s). It takes the event object as its first argument: `handler(eventObject)` * * @method off * @member ep.ui.imgData * * @since 6.14.0 */ off: function (events, handler) { if (handler) { this.eventObject.off(events, $.proxy(handler, this)); } else { this.eventObject.off(events); } return this; }, /** * Execute all handlers and behaviors attached to the image data object for the given event type. * * ### Dependencies * * + `ep` * + `jQuery.scope` * * @param {String} eventType A string containing a JavaScript event type, such as click or submit. * @param {Event} event A jQuery.Event object. * * @method trigger * @member ep.ui.imgData * * @since 6.14.0,6.14.0 */ trigger: function (events) { this.eventObject.trigger(events); return this; } }; // Create a ui.createMoveToTop = function (elementName) { return function (event, silent) { var elem = this[elementName], moved = !!elem.nextAll(":visible").insertBefore(elem).length; if (moved && !silent && this._trigger) { this._trigger("focus", event); } return this; }; }; return ep; });