/* start: /SEUILibrary/hightech-portal/js/wci/WciCategoryFacets.js (cachekey: [])*/ if(typeof(window.wci) === 'undefined') { window.wci = {}; } (function (wci) { if(!wci.cfacets) { var categoryFacets = {}; wci.cfacets = categoryFacets; categoryFacets.getReqFacetParams = function() { var reqfacetParams = {} for( i in facetParams ) { reqfacetParams[i] = facetParams[i] } return reqfacetParams; } categoryFacets.collapseable = false; categoryFacets.setCollapseableDropdowns = function ( mode ) { categoryFacets.collapseable = mode; } categoryFacets.orientation = 'vertical'; categoryFacets.setOrientation = function ( orientation ) { categoryFacets.orientation = orientation; } categoryFacets.updateFacets = function() { for( f = 0 ; f < facets.length ; f++ ) { var facet = facets[f] populateDropdown(facet.id, facet.values) $("#"+facet.id).bind("dropDownOpening", function() { loadFacetStatuses() }); $("#"+facet.id).bind("selectionsChanged", function() { var facetID = $(this).attr("id"); var selections = getDropDownSelections(facetID) wci.cfacets.changeFacetCriteria(facetID, selections) }) } $("#keyword-facet").bind("inputChanged", function() { var keywordValue = getKeywordDropDownValue('keyword-facet'); wci.cfacets.changeKeywordCriteria(keywordValue) }); attachDropDownEvents(categoryFacets.collapseable) } categoryFacets.updateFacetStatus = function(facetID, data) { mystatuses = data.facets; var fid = 1; for( var ic =0; ic $(window).width() ) { myWidth = $(window).width()-40; } $('#facet-results-loader').width(myWidth); if( typeof stickyDropdowns != "undefined" && stickyDropdowns && categoryFacets.orientation == 'vertical' ) { $('#facet-results-loader').css('left',$('#facet-area').width()); } $('#facet-results-loader').show() } categoryFacets.hideResultsLoader = function() { $('#facet-results-loader').hide() } categoryFacets.statusesUpdating = false; categoryFacets.resultsLoading = false; categoryFacets.defaultFacetOptions = { selectedClass: '', disabledClass: '', choiceGroupElement: '', hoverClass: '', mainElement: '', choiceElement: '', selectionElement: '', statusUrl: '', resultsUrl: '', categoryid: '', resultElement: '', loaderElement: '', maximumItems: '', resultSortCriteria: '0' }; categoryFacets.facetOptions = {}; categoryFacets.setFacetOptions = function( myOptions ) { categoryFacets.facetOptions = $.extend({}, categoryFacets.defaultFacetOptions, myOptions); } categoryFacets.attachFacetEvents = function() { $(categoryFacets.facetOptions.choiceElement).each( function() { var choiceGroup = $(this).find(categoryFacets.facetOptions.choiceGroupElement); $(choiceGroup).each( function() { var myChild = $(this).find(categoryFacets.facetOptions.selectionElement); categoryFacets.attachFacetSelectionEvents(myChild); }); }); } categoryFacets.attachFacetSelectionEvents = function( myElement ) { if (!myElement.hasClass(categoryFacets.facetOptions.disabledClass) || myElement.hasClass(categoryFacets.facetOptions.selectedClass)) { $(myElement).hover(function() { $(this).addClass(categoryFacets.facetOptions.hoverClass); }, function() { $(this).removeClass(categoryFacets.facetOptions.hoverClass); }); $(myElement).click(function() { //Select or un-select list-item on click. if($(this).hasClass(categoryFacets.facetOptions.selectedClass)) { $(this).toggleClass(categoryFacets.facetOptions.selectedClass, false); }else { $(this).toggleClass(categoryFacets.facetOptions.selectedClass, true); }; categoryFacets.processFacetChange(); }); } } categoryFacets.processFacetChange = function() { if (!categoryFacets.statusesUpdating) { categoryFacets.statusesUpdating = true; var facetParams = categoryFacets.getMandatoryParams(); wci.ajaxEx({ ignoreErrors: false, url: categoryFacets.facetOptions.statusUrl, data: facetParams, traditional : true, dataType: "json", success: function(data, textStatus, jqXHR) { categoryFacets.updateFacetStatuses( data ); } }); } } categoryFacets.updateFacetStatuses = function( data ) { var mystatuses = data.facets; for( var i=0; i < mystatuses.length; i++) { var fstatuses = mystatuses[i]; var fid = fstatuses.facetID; var fstates = fstatuses.statuses; categoryFacets.updateFacetElements(fid, fstates); } categoryFacets.statusesUpdating = false; } categoryFacets.getFacetSelections = function() { var selectedFacetIDs = []; $(categoryFacets.facetOptions.choiceElement).each( function() { var choiceGroup = $(this).find(categoryFacets.facetOptions.choiceGroupElement); $(choiceGroup).each( function() { var choiceID = $(this).attr("id"); var myChild = $(this).find(categoryFacets.facetOptions.selectionElement); var selectedValues = []; $(myChild).each( function() { if ($(this).hasClass(categoryFacets.facetOptions.selectedClass)) { var childID = $(this).attr("id"); var idParts = childID.split("_"); if (idParts.length == 2) { selectedValues.push(idParts[1]); } else { selectedValues.push(idParts[0]); } } }); if (selectedValues.length > 0) { selectedFacetIDs.push({"id" : choiceID, "selections" : selectedValues}); } }); }); return selectedFacetIDs; } categoryFacets.removeFacetElementTriggers = function(myElem) { $(myElem).unbind(); } categoryFacets.updateFacetElements = function(id, elements) { var parentElem = $(categoryFacets.facetOptions.mainElement).find("#"+id); for(var i=0; i 0) { $(categoryFacets.facetOptions.loaderElement).show(); } var facetParams = categoryFacets.getMandatoryParams(); if (categoryFacets.facetOptions.maximumItems.length > 0) { facetParams['page-size'] = categoryFacets.facetOptions.maximumItems; } facetParams['sort-criteria'] = categoryFacets.facetOptions.resultSortCriteria; wci.ajaxEx({ ignoreErrors: false, url: categoryFacets.facetOptions.resultsUrl, data: facetParams, traditional : true, dataType: "html", success: function(data, textStatus, jqXHR) { if (categoryFacets.facetOptions.loaderElement.length > 0) { $(categoryFacets.facetOptions.loaderElement).hide(); } $(categoryFacets.facetOptions.resultElement).html( data ); categoryFacets.resultsLoading = false; } }); } } categoryFacets.clearFacets = function() { $(categoryFacets.facetOptions.choiceGroupElement).each( function() { $(this).find(categoryFacets.facetOptions.selectionElement).removeClass(categoryFacets.facetOptions.selectedClass); }); categoryFacets.processFacetChange(); $(categoryFacets.facetOptions.resultElement).html(""); } } }(window.wci)); /* end: /SEUILibrary/hightech-portal/js/wci/WciCategoryFacets.js(13106) */ /* start: /SEUILibrary/hightech-portal/js/wci/WciCatalogUtils.js (cachekey: [])*/ if(typeof(window.wci) === 'undefined') { window.wci = {}; } (function (wci) { if(!wci.catalogutils) { var catalogUtils = {}; wci.catalogutils = catalogUtils; catalogUtils.compareSelected = function( topopup, errMsgSelectOne, errMsgSelectLess ) { var ch = document.getElementsByTagName('INPUT'); var chi=0; var myIds = ""; for(i=0; i0) myIds += ","; myIds += ch[i].value; chi++; //if overlay is enabed store to cookie if(typeof(addCompareCookieValue) != "undefined") { addCompareCookieValue(ch[i].value); } } } } if(chi < 2 && typeof(getOidsFromCookieCount) != "undefined") { chi = getOidsFromCookieCount(); } if(chi<2) { if ( !errMsgSelectOne ) { errMsgSelectOne = 'Please select at least two items to compare.'; } alert( errMsgSelectOne ); return false; } /* if(chi>5) { if( !errMsgSelectLess ) { errMsgSelectLess = 'Please select at most five items to compare.'; } alert( errMsgSelectLess ); return; } */ //determine whether to use overlay or old function if(typeof(compareOverlay) != "undefined") { compareOverlay(); } else { var loc="./special-offers.workflow:compare-items?x=x&"+myIds; if( topopup ) { window.open(loc+"&popup=true", "Compare"); } else { document.location.href = loc; } } return false; } } }(window.wci)); /* end: /SEUILibrary/hightech-portal/js/wci/WciCatalogUtils.js(1932) */ /* start: /ISS_Static/WW/site/scripts/jquery/jquery.hammer.min.js (cachekey: [])*/ /*! Hammer.JS - v1.0.5 - 2013-04-07 * http://eightmedia.github.com/hammer.js * * Copyright (c) 2013 Jorik Tangelder ; * Licensed under the MIT license */ (function(t,e){"use strict";function n(){if(!i.READY){i.event.determineEventTypes();for(var t in i.gestures)i.gestures.hasOwnProperty(t)&&i.detection.register(i.gestures[t]);i.event.onTouch(i.DOCUMENT,i.EVENT_MOVE,i.detection.detect),i.event.onTouch(i.DOCUMENT,i.EVENT_END,i.detection.detect),i.READY=!0}}var i=function(t,e){return new i.Instance(t,e||{})};i.defaults={stop_browser_behavior:{userSelect:"none",touchAction:"pan-y",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},i.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,i.HAS_TOUCHEVENTS="ontouchstart"in t,i.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android/i,i.NO_MOUSEEVENTS=i.HAS_TOUCHEVENTS&&navigator.userAgent.match(i.MOBILE_REGEX),i.EVENT_TYPES={},i.DIRECTION_DOWN="down",i.DIRECTION_LEFT="left",i.DIRECTION_UP="up",i.DIRECTION_RIGHT="right",i.POINTER_MOUSE="mouse",i.POINTER_TOUCH="touch",i.POINTER_PEN="pen",i.EVENT_START="start",i.EVENT_MOVE="move",i.EVENT_END="end",i.DOCUMENT=document,i.plugins={},i.READY=!1,i.Instance=function(t,e){var r=this;return n(),this.element=t,this.enabled=!0,this.options=i.utils.extend(i.utils.extend({},i.defaults),e||{}),this.options.stop_browser_behavior&&i.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),i.event.onTouch(t,i.EVENT_START,function(t){r.enabled&&i.detection.startDetect(r,t)}),this},i.Instance.prototype={on:function(t,e){for(var n=t.split(" "),i=0;n.length>i;i++)this.element.addEventListener(n[i],e,!1);return this},off:function(t,e){for(var n=t.split(" "),i=0;n.length>i;i++)this.element.removeEventListener(n[i],e,!1);return this},trigger:function(t,e){var n=i.DOCUMENT.createEvent("Event");n.initEvent(t,!0,!0),n.gesture=e;var r=this.element;return i.utils.hasParent(e.target,r)&&(r=e.target),r.dispatchEvent(n),this},enable:function(t){return this.enabled=t,this}};var r=null,o=!1,s=!1;i.event={bindDom:function(t,e,n){for(var i=e.split(" "),r=0;i.length>r;r++)t.addEventListener(i[r],n,!1)},onTouch:function(t,e,n){var a=this;this.bindDom(t,i.EVENT_TYPES[e],function(c){var u=c.type.toLowerCase();if(!u.match(/mouse/)||!s){(u.match(/touch/)||u.match(/pointerdown/)||u.match(/mouse/)&&1===c.which)&&(o=!0),u.match(/touch|pointer/)&&(s=!0);var h=0;o&&(i.HAS_POINTEREVENTS&&e!=i.EVENT_END?h=i.PointerEvent.updatePointer(e,c):u.match(/touch/)?h=c.touches.length:s||(h=u.match(/up/)?0:1),h>0&&e==i.EVENT_END?e=i.EVENT_MOVE:h||(e=i.EVENT_END),h||null===r?r=c:c=r,n.call(i.detection,a.collectEventData(t,e,c)),i.HAS_POINTEREVENTS&&e==i.EVENT_END&&(h=i.PointerEvent.updatePointer(e,c))),h||(r=null,o=!1,s=!1,i.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=i.HAS_POINTEREVENTS?i.PointerEvent.getEvents():i.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],i.EVENT_TYPES[i.EVENT_START]=t[0],i.EVENT_TYPES[i.EVENT_MOVE]=t[1],i.EVENT_TYPES[i.EVENT_END]=t[2]},getTouchList:function(t){return i.HAS_POINTEREVENTS?i.PointerEvent.getTouchList():t.touches?t.touches:[{identifier:1,pageX:t.pageX,pageY:t.pageY,target:t.target}]},collectEventData:function(t,e,n){var r=this.getTouchList(n,e),o=i.POINTER_TOUCH;return(n.type.match(/mouse/)||i.PointerEvent.matchType(i.POINTER_MOUSE,n))&&(o=i.POINTER_MOUSE),{center:i.utils.getCenter(r),timeStamp:(new Date).getTime(),target:n.target,touches:r,eventType:e,pointerType:o,srcEvent:n,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault&&this.srcEvent.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return i.detection.stopDetect()}}}},i.PointerEvent={pointers:{},getTouchList:function(){var t=this,e=[];return Object.keys(t.pointers).sort().forEach(function(n){e.push(t.pointers[n])}),e},updatePointer:function(t,e){return t==i.EVENT_END?this.pointers={}:(e.identifier=e.pointerId,this.pointers[e.pointerId]=e),Object.keys(this.pointers).length},matchType:function(t,e){if(!e.pointerType)return!1;var n={};return n[i.POINTER_MOUSE]=e.pointerType==e.MSPOINTER_TYPE_MOUSE||e.pointerType==i.POINTER_MOUSE,n[i.POINTER_TOUCH]=e.pointerType==e.MSPOINTER_TYPE_TOUCH||e.pointerType==i.POINTER_TOUCH,n[i.POINTER_PEN]=e.pointerType==e.MSPOINTER_TYPE_PEN||e.pointerType==i.POINTER_PEN,n[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},i.utils={extend:function(t,n,i){for(var r in n)t[r]!==e&&i||(t[r]=n[r]);return t},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){for(var e=[],n=[],i=0,r=t.length;r>i;i++)e.push(t[i].pageX),n.push(t[i].pageY);return{pageX:(Math.min.apply(Math,e)+Math.max.apply(Math,e))/2,pageY:(Math.min.apply(Math,n)+Math.max.apply(Math,n))/2}},getVelocity:function(t,e,n){return{x:Math.abs(e/t)||0,y:Math.abs(n/t)||0}},getAngle:function(t,e){var n=e.pageY-t.pageY,i=e.pageX-t.pageX;return 180*Math.atan2(n,i)/Math.PI},getDirection:function(t,e){var n=Math.abs(t.pageX-e.pageX),r=Math.abs(t.pageY-e.pageY);return n>=r?t.pageX-e.pageX>0?i.DIRECTION_LEFT:i.DIRECTION_RIGHT:t.pageY-e.pageY>0?i.DIRECTION_UP:i.DIRECTION_DOWN},getDistance:function(t,e){var n=e.pageX-t.pageX,i=e.pageY-t.pageY;return Math.sqrt(n*n+i*i)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==i.DIRECTION_UP||t==i.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(t,e){var n,i=["webkit","khtml","moz","ms","o",""];if(e&&t.style){for(var r=0;i.length>r;r++)for(var o in e)e.hasOwnProperty(o)&&(n=o,i[r]&&(n=i[r]+n.substring(0,1).toUpperCase()+n.substring(1)),t.style[n]=e[o]);"none"==e.userSelect&&(t.onselectstart=function(){return!1})}}},i.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:i.utils.extend({},e),lastEvent:!1,name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);for(var e=this.current.inst.options,n=0,r=this.gestures.length;r>n;n++){var o=this.gestures[n];if(!this.stopped&&e[o.name]!==!1&&o.handler.call(o,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==i.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t}},stopDetect:function(){this.previous=i.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var e=this.current.startEvent;if(e&&(t.touches.length!=e.touches.length||t.touches===e.touches)){e.touches=[];for(var n=0,r=t.touches.length;r>n;n++)e.touches.push(i.utils.extend({},t.touches[n]))}var o=t.timeStamp-e.timeStamp,s=t.center.pageX-e.center.pageX,a=t.center.pageY-e.center.pageY,c=i.utils.getVelocity(o,s,a);return i.utils.extend(t,{deltaTime:o,deltaX:s,deltaY:a,velocityX:c.x,velocityY:c.y,distance:i.utils.getDistance(e.center,t.center),angle:i.utils.getAngle(e.center,t.center),direction:i.utils.getDirection(e.center,t.center),scale:i.utils.getScale(e.touches,t.touches),rotation:i.utils.getRotation(e.touches,t.touches),startEvent:e}),t},register:function(t){var n=t.defaults||{};return n[t.name]===e&&(n[t.name]=!0),i.utils.extend(i.defaults,n,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.indexe.index?1:0}),this.gestures}},i.gestures=i.gestures||{},i.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(t,e){switch(t.eventType){case i.EVENT_START:clearTimeout(this.timer),i.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==i.detection.current.name&&e.trigger("hold",t)},e.options.hold_timeout);break;case i.EVENT_MOVE:t.distance>e.options.hold_threshold&&clearTimeout(this.timer);break;case i.EVENT_END:clearTimeout(this.timer)}}},i.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,e){if(t.eventType==i.EVENT_END){var n=i.detection.previous,r=!1;if(t.deltaTime>e.options.tap_max_touchtime||t.distance>e.options.tap_max_distance)return;n&&"tap"==n.name&&t.timeStamp-n.lastEvent.timeStamp0&&t.touches.length>e.options.swipe_max_touches)return;(t.velocityX>e.options.swipe_velocity||t.velocityY>e.options.swipe_velocity)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},i.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,drag_max_touches:1,drag_block_horizontal:!1,drag_block_vertical:!1,drag_lock_to_axis:!1,drag_lock_min_distance:25},triggered:!1,handler:function(t,n){if(i.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),this.triggered=!1,e;if(!(n.options.drag_max_touches>0&&t.touches.length>n.options.drag_max_touches))switch(t.eventType){case i.EVENT_START:this.triggered=!1;break;case i.EVENT_MOVE:if(t.distancet.deltaY?i.DIRECTION_UP:i.DIRECTION_DOWN:0>t.deltaX?i.DIRECTION_LEFT:i.DIRECTION_RIGHT),this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),n.trigger(this.name+t.direction,t),(n.options.drag_block_vertical&&i.utils.isVertical(t.direction)||n.options.drag_block_horizontal&&!i.utils.isVertical(t.direction))&&t.preventDefault();break;case i.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},i.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,n){if(i.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),this.triggered=!1,e;if(!(2>t.touches.length))switch(n.options.transform_always_block&&t.preventDefault(),t.eventType){case i.EVENT_START:this.triggered=!1;break;case i.EVENT_MOVE:var r=Math.abs(1-t.scale),o=Math.abs(t.rotation);if(n.options.transform_min_scale>r&&n.options.transform_min_rotation>o)return;i.detection.current.name=this.name,this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),o>n.options.transform_min_rotation&&n.trigger("rotate",t),r>n.options.transform_min_scale&&(n.trigger("pinch",t),n.trigger("pinch"+(1>t.scale?"in":"out"),t));break;case i.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},i.gestures.Touch={name:"touch",index:-1/0,defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,n){return n.options.prevent_mouseevents&&t.pointerType==i.POINTER_MOUSE?(t.stopDetect(),e):(n.options.prevent_default&&t.preventDefault(),t.eventType==i.EVENT_START&&n.trigger(this.name,t),e)}},i.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==i.EVENT_END&&e.trigger(this.name,t)}},"object"==typeof module&&"object"==typeof module.exports?module.exports=i:(t.Hammer=i,"function"==typeof t.define&&t.define.amd&&t.define("hammer",[],function(){return i}))})(this),function(t,e){"use strict";t!==e&&(Hammer.event.bindDom=function(n,i,r){t(n).on(i,function(t){var n=t.originalEvent||t;n.pageX===e&&(n.pageX=t.pageX,n.pageY=t.pageY),n.target||(n.target=t.target),n.which===e&&(n.which=n.button),n.preventDefault||(n.preventDefault=t.preventDefault),n.stopPropagation||(n.stopPropagation=t.stopPropagation),r.call(this,n)})},Hammer.Instance.prototype.on=function(e,n){return t(this.element).on(e,n)},Hammer.Instance.prototype.off=function(e,n){return t(this.element).off(e,n)},Hammer.Instance.prototype.trigger=function(e,n){var i=t(this.element);return i.has(n.target).length&&(i=t(n.target)),i.trigger({type:e,gesture:n})},t.fn.hammer=function(e){return this.each(function(){var n=t(this),i=n.data("hammer");i?i&&e&&Hammer.utils.extend(i.options,e):n.data("hammer",new Hammer(this,e||{}))})})}(window.jQuery||window.Zepto); /* end: /ISS_Static/WW/site/scripts/jquery/jquery.hammer.min.js(13009) */ /* start: /ISS_Static/WW/site/scripts/owv2/menus.js (cachekey: [])*/ (function () { var app = window.LENOVO = window.LENOVO || {}, MAIN = app.MAIN, isOpenSuffix = "-is-open", navKey = "offcanvas", isExpandedClass = "is-expanded", noTransitionClass = "no-transitions", transitionEndEvents = "webkitTransitionEnd oTransitionEnd otransitionend transitionend", allMenus = ".productMenu, .generalMenu, .offCanvas-bar_3-left, .offCanvas-bar_3-left", levelOneMenus = ["productMenu", "generalMenu"], levelTwoMenus = ["offCanvas-bar_3-left", "offCanvas-bar_3-right"], leftSidebarMenu = levelTwoMenus[0], rightSidebarMenu = levelTwoMenus[1], headerBoxToggleClasses = ".js-toggles-searchBox, .js-toggles-callBox", resizeTimeoutDuration = 500, toggleDuration = 200, navAnimationDuration = 400, $body, $header, $searchInput, $searchContainers, $espots, $espotsContainers, self = app.MENUS = { //build a stack of currently open off canvas navs currentlyOpen : [], lastClosed : null, //track the latest nested menu, so it can be kept open if browser resize latestNestedMenu : null, contentHeight : null, //timer to remove class while resizing resizeNoTransitionTimeout : null, //initialize the page init : function () { $header = $("header"); $body = $("body"); $searchInput = $(".searchInput"); $searchContainers = $("[data-set=search-container]"); // Note: the espots are in offCanvas-bar_3-left at large size, but it the // content when filetermenu is not visible... while perhaps not ideal, // we're putting the JS to handle that change here. $espots = $(".espot-sidebar-list"); $espotsContainers = $("[data-set=espots]"); if (self.initialized) { return; } self.initialized = true; //open off-canvas navs when clicking on headings $header.on("click", ".js-opensOffCanvasMenu", self.openOffCanvasMenuHandler); // toggle search/call/etc box toggling $header.on("click", headerBoxToggleClasses, self.toggleHeaderBox); //toggle children in nested menus $header.on("click", ".menuLevel_1 .link-hasChildren", self.nestedMenuHeaderHandler); //close latest nested menu $body.on("click", ".js-closeNestedMenu", self.closeLatestNestedMenu); //close latest off canvas nav when clicking in overlay or specific areas that close navs $body.on("click", ".offCanvas-closeOverlay, .js-closesOffCanvasMenu", self.closeOffCanvasMenuHandler); //toggle children in expandable menus $body.on("click", ".expandableHeading, .expandableHeading-onlySmall", self.expandableMenuHeaderHandler); self.hideInitialExpandableMenus(); //handler for any transition ending $body.on(transitionEndEvents, self.transitionEndHandler); //add breakpoint specific code self.addBreakpointHandlers(); //handle anything specific to resizing the browser $(window).on("debounced-resize", self.onResize); self.onResize(); }, //determine if a specific nav is open isNavOpen : function (navName) { return navName && $body.hasClass(navName + isOpenSuffix); }, //get the last menu to be opened getLatest : function () { return self.currentlyOpen[self.currentlyOpen.length - 1]; }, //open/close a specific menu toggleOffCanvas : function (navData) { var main, navClosedCallback, latest = self.getLatest(), opening, isLevelTwo, offset, $menu; //remove previous direction if (latest) { $body.removeClass("offCanvas-" + latest.direction + isOpenSuffix); } //if no navData is passed, close latest nav navData = navData || latest; if (navData) { isLevelTwo = navData.name.indexOf("offCanvas") > -1; $menu = $("." + navData.name); //add or remove the nav from the stack if (!self.isNavOpen(navData.name)) { //if direction has changed, then first close old nav if (latest && latest.direction !== navData.direction) { //close old nav self.toggleOffCanvas(latest); //open the nav, after previous is closed (async), if transitions are supported main = $(".mainContent"); //add a one-time handler to open the requested nav after the latest is closed navClosedCallback = function () { self.toggleOffCanvas(navData); main.off(transitionEndEvents, navClosedCallback); }; main.on(transitionEndEvents, navClosedCallback); return; } opening = true; self.currentlyOpen.push(navData); } else { self.lastClosed = self.currentlyOpen.pop(); } //toggle nav specific class $body.toggleClass(navData.name + isOpenSuffix); self.addAnimationFallback(navData); //adjust level two menus if (isLevelTwo) { offset = $(".bar_3").height(); $menu.css("margin-top", navData.clearOffset ? "" : -offset); $body.removeClass("hide-offCanvas-bar_3"); } else if (opening && self.currentlyOpen.length === 1) { $body.addClass("hide-offCanvas-bar_3"); } // make sure page is tall enough to handle menus if ($body.hasClass(navData.name + isOpenSuffix)) { self.resizeContentForSidebar(navData); } else { self.undoResizeContentForSidebar(); } //see if there is still a currently open nav latest = self.getLatest(); //add current direction if (latest) { $body.removeClass("hide-offCanvas"); $body.addClass("offCanvas-" + latest.direction + isOpenSuffix); } //add/remove and position overlay self.toggleOverlay(latest); } }, resizeContentForSidebar : function (navData, animate) { // When a sidebar opens (or a sub-item), we need to make sure // the page content is tall enough to handle menus otherwise // they will get cut off var l2Menus, l2MenuHeight, contentHeight = 0, heightOffset = 0, wrapper = $(".body-inner-wrapper"), menu = $("." + navData.name); if ($.inArray(navData.name, levelOneMenus) > -1) { heightOffset = $(".bar_1").height(); contentHeight = menu.height() + heightOffset; if (MAIN.activeBreakPoints.onCanvas) { // if we're in a large size then our levelOne sub menus are absolutely // positioned, meaning we won't be able to get the height correctly, // so we'll grab the sub menu height and add it to the content height contentHeight += (menu.find(".is-expanded .menuLevel_2").outerHeight() + 5); // +5 for bottom shadow } l2Menus = self.findClasses(levelTwoMenus); if (l2Menus.is(":visible")) { // If levelTwo menus are visible, need to make sure the level two menus are visible l2MenuHeight = heightOffset + $(".bar_2").height() + l2Menus.height(); contentHeight = Math.max(contentHeight, l2MenuHeight); } } else if ($.inArray(navData.name, levelTwoMenus) > -1 && menu.is(":visible")) { heightOffset = $(".bar_1").height() + $(".bar_2").height(); contentHeight = menu.height() + heightOffset; } // GWE-983 // protect new splitter page (FP-2451) from this JS var $newSplitter = $("#seriesSplitter").length; if ($newSplitter != 1) { wrapper.animate({"min-height" : contentHeight}, ((animate === false) ? 0 : 500)); } self.resizeLevelOneMenus(); }, undoResizeContentForSidebar : function () { var l2Menus, contentHeight = 0; l2Menus = self.findClasses(levelTwoMenus); if (MAIN.activeBreakPoints.onCanvas || l2Menus.is(":visible")) { // .height() of the two menus in the jQuery will actually be the height of the largest contentHeight = $(".bar_1").height() + $(".bar_2").height() + l2Menus.height(); } // GWE-983 // protect new splitter page (FP-2451) from this JS var $newSplitter = $("#seriesSplitter").length; if ($newSplitter != 1) { $(".body-inner-wrapper").animate({"min-height" : contentHeight}); } self.resizeLevelOneMenus(); }, //make sure that bar two menus are as tall as the main content resizeLevelOneMenus : function () { self.contentHeight = $("body").height() - $(".bar_1").height(); self.findClasses(levelOneMenus).each(self.resizeLevelOneMenu); }, resizeLevelOneMenu : function () { $(this).css({"min-height" : self.contentHeight}); }, removeLevelOneMenuStyles : function () { self.contentHeight = null; self.findClasses(levelOneMenus).each(self.resizeLevelOneMenu); }, //move content to the first visible container moveContent : function ($content, $containers) { var parent = $content.parent(); //using display:none (instead of :visible) as container may not currently have height/width (small search box) if (parent.css("display") === "none") { $containers.not(parent).each(self.checkContainer, [$content]); } }, checkContainer : function ($content) { var container = $(this); //using display:none (instead of :visible) as container may not currently have height/width (small search box) if (container.css("display") !== "none") { container.html($content); return false; //break each loop } }, //for browsers that don't support CSS transitions, add a fallback addAnimationFallback : function (navData) { if (!Modernizr.csstransitions) { var shouldBeOpen = $body.hasClass(navData.name + isOpenSuffix), $menu = $("." + navData.name), isLevelOne = $menu.parent().hasClass("bar_2"), $parent = isLevelOne ? $menu.parent() : $(".bar_3"), factor = isLevelOne ? 70 : 35, maxFactor = 105, menuProps = { maxWidth : factor + "%", width : factor + "%" }, barProps, mainProps; //animate the affected menu menuProps[navData.direction] = (shouldBeOpen ? "-" + factor : "-300") + "%"; $menu.animate(menuProps, shouldBeOpen ? 0 : navAnimationDuration * 2, self.triggerTransitionEnd); //animate main content and header bar barProps = { left : !shouldBeOpen ? "0" : (navData.direction === "left" ? factor : "-" + factor) + "%" }; //animate parent of menu $parent.animate(barProps, navAnimationDuration, self.triggerTransitionEnd); //adjust the factor for the main content/footer depending on if one, both, or no menus are open on a side if (self.currentlyOpen.length) { //there is still one open, but not this one, so flip the value (will be 35) if (!shouldBeOpen) { factor = maxFactor - factor; } //multiple menus are now open, move to max % else if (self.currentlyOpen.length > 1) { factor = maxFactor; } } //no menus are open, so need to move to 0 else { factor = 0; } mainProps = { left : (navData.direction === "left" ? "" : "-") + factor + "%" }; $(".mainContent, .mainFooter").css({position : "relative"}).animate(mainProps, navAnimationDuration, self.triggerTransitionEnd); } }, //have fallback animations trigger transitionend event, so response is consistent triggerTransitionEnd : function () { $(this).trigger("transitionend"); }, //create/remove an overlay and set top properly toggleOverlay : function (currentNav) { var nav, navOffset, width, overlay = $(".offCanvas-closeOverlay"); currentNav = currentNav || self.getLatest(); if (currentNav) { //add an overlay, if it does not already exist if (!overlay.length) { overlay = $("
", {"class" : "offCanvas-closeOverlay"}).appendTo(document.body); } nav = $("." + currentNav.name); width = $body.width() - nav.width(); navOffset = nav.offset(); overlay.css({ top : navOffset ? navOffset.top : 0, width : width + "px" }); } else { overlay.remove(); } }, //click handler for opening an off-canvas menu openOffCanvasMenuHandler : function (e) { var $el = $(this), navInfo = $el.data(navKey); if (navInfo) { navInfo = navInfo.split(" "); self.toggleOffCanvas({ name : navInfo[0], direction : navInfo[1] }); } e.preventDefault(); }, //click handler for closing an off-canvas menu closeOffCanvasMenuHandler : function (e) { self.toggleOffCanvas(); e.preventDefault(); }, //resize content for the latest or closest menu resizeForLatestMenu : function () { var navData; if (self.currentlyOpen.length) { navData = self.getLatest(); } else { navData = { name : $(this).closest(allMenus).prop("class"), direction : "onscreen" }; } self.resizeContentForSidebar(navData); //toggle an overlay at large size, to allow closing menu by clicking/touching off of it if (MAIN.activeBreakPoints.onCanvas) { self.toggleNestedMenuOverlay(); } }, //click handler for expanding children in a nested menu nestedMenuHeaderHandler : function (e) { var $el = $(this), parentListItem = $el.closest("li"), latest = self.latestNestedMenu; if (typeof isRWD == 'undefined') { isRWD = "rwd" } ;//set pagetype to rwd if undefined //at larger size, only allow one menu to be open if (parentListItem.parent().hasClass("menuLevel_1")) { if ((!MAIN.activeBreakPoints.supported || MAIN.activeBreakPoints.onCanvas || isRWD == 'nonrwd') && latest && latest[0] !== $el[0]) { latest.parent().next("ol").hide(); latest.closest("li").removeClass(isExpandedClass); } //add/remove based on whether it is currently open self.latestNestedMenu = parentListItem.hasClass(isExpandedClass) ? null : $el; } else { //bindings only apply beyond top-level at small size if (MAIN.activeBreakPoints.onCanvas) { return; } } $el.parent().next("ol").slideToggle(toggleDuration, self.resizeForLatestMenu); parentListItem.toggleClass(isExpandedClass); e.preventDefault(); }, closeLatestNestedMenu : function () { var latest = self.latestNestedMenu; if (latest) { latest.parent().next("ol").slideUp(toggleDuration, self.resizeForLatestMenu); latest.closest("li").removeClass(isExpandedClass); } }, //toggle a full-width overlay for the nested menu's at large size toggleNestedMenuOverlay : function () { var overlay = $(".offCanvas-closeOverlay"), nestedMenuHeader = $(".menuLevel_1 ." + isExpandedClass), nestedMenu; //add an overlay, if necessary if (nestedMenuHeader.length) { nestedMenu = nestedMenuHeader.find("ol").first(); if (!overlay.length) { overlay = $("
", {"class" : "offCanvas-closeOverlay js-closeNestedMenu"}).appendTo(document.body); } overlay.css({ top : nestedMenu.offset().top + nestedMenu.outerHeight(), width : "100%" }); } //remove the overlay in the opposite case if (overlay.length && !nestedMenuHeader.length) { overlay.remove(); self.toggleOverlay(); } }, // we need to hide the expandable menu options by default, showing only // the first one. This allows the menu to be seen in case of no JS or JS issues hideInitialExpandableMenus : function () { var $menus = $(".expandableMenu"); //IE7/IE8 were getting infinite loop with "h3:first, h3.default-open" selector in one line $menus.find("h3:first").addClass("expandableHeading-is-expanded"); $menus.find("h3.default-open").addClass("expandableHeading-is-expanded"); $menus.find(".expandableMenu-list:gt(0):not(.default-open)").addClass("is-visuallyhidden"); }, //click handler for toggling content in an expandable menu expandableMenuHeaderHandler : function (e) { var $content, $trigger = $(this); if ($trigger.hasClass("expandableHeading-onlySmall") && !MAIN.activeBreakPoints.smallExpandable) { return true; } $content = $trigger.next(".expandableMenu-list"); if (!$content.length) { $content = $trigger.next(".expandableContent"); } // reverse the CSS class hiding so that slideToggle works (if necessary) if ($content.hasClass("is-visuallyhidden")) { $content .hide() .removeClass("is-visuallyhidden"); } // slide toggle the associated content $content.slideToggle( toggleDuration, (($content.hasClass("expandableMenu-list")) ? self.afterExpandableMenuToggle : self.afterExpandableContentToggle) ); //now toggle the class after slideToggle is kicked off $trigger.toggleClass("expandableHeading-is-expanded"); e.preventDefault(); }, //toggle the header class when animation is complete afterExpandableMenuToggle : function () { self.resizeForLatestMenu(); self.toggleExpandableMenuHiddenClass($(this)); }, //toggle the content expanded class after animation afterExpandableContentToggle : function () { $(this).toggleClass("expandableContent-is-collapsed").css("display", ""); self.toggleExpandableMenuHiddenClass($(this)); }, toggleExpandableMenuHiddenClass : function (content) { // for accessibility we apply a class to hide the content versus using // display: none (which is what jQuery does) if (content.is(":visible")) { content.removeClass("is-visuallyhidden"); } else { content .addClass("is-visuallyhidden") // hide with CSS class .show(); // remove the "display:none;" } }, //remove the left/right styles added by animation fallbacks clearFallbackStyles : function (selector) { $(selector).css({ left : "", right : "", width : "", maxWidth : "" }); }, //callback when animation finishes transitionEndHandler : function (e) { if (!self.getLatest()) { $body.removeClass("hide-offCanvas"); } if (!Modernizr.cssTransitions && self.lastClosed) { if ((MAIN.activeBreakPoints.exposeLeftSidebar && self.lastClosed.name === "offCanvas-bar_3-left") || (MAIN.activeBreakPoints.exposeRightSidebar && self.lastClosed.name === "offCanvas-bar_3-right")) { self.clearFallbackStyles(e.target); } } }, //close all open menus closeOpenNestedMenus : function () { $header.find("." + isExpandedClass).removeClass(isExpandedClass).find("ol").first().hide(); //clear override margin-top on level two menus self.findClasses(levelTwoMenus).css("margin-top", ""); self.toggleNestedMenuOverlay(); }, handleNoTransitionClass : function () { if (self.resizeNoTransitionTimeout) { clearTimeout(self.resizeNoTransitionTimeout); } else { $body.addClass(noTransitionClass); } self.resizeNoTransitionTimeout = setTimeout(self.removeNoTransitionClass, resizeTimeoutDuration); }, removeNoTransitionClass : function () { $body.removeClass(noTransitionClass); self.resizeNoTransitionTimeout = null; }, //functionality to execute when the browser resizes onResize : function () { self.moveContent($searchInput, $searchContainers); self.moveContent($espots, $espotsContainers); self.handleNoTransitionClass(); }, //handle browser moving to a large size enterLargeSizeHandler : function () { var navData; self.closeOpenNestedMenus(); //remove body level classes while (self.currentlyOpen.length) { navData = self.getLatest(); navData.clearOffset = true; self.toggleOffCanvas(navData); } //clear any styles added by fallback animations to the main menus if (!Modernizr.cssTransitions) { self.clearFallbackStyles(allMenus); } //resize content for (now) onscreen menus self.resizeContentForSidebar({name : "offCanvas-bar_3-left", direction : "onscreen"}, false); }, //handle browser moving to a smaller size exitLargeSizeHandler : function () { self.closeOpenNestedMenus(); }, clearRightSidebarFallbackStyles : function () { self.clearFallbackStyles("." + rightSidebarMenu); }, //close menu when left is exposed enterLeftSidebarExposed : function () { if (self.isNavOpen(leftSidebarMenu)) { self.toggleOffCanvas({ name : leftSidebarMenu, clearOffset : true }); } }, //when browser is at its largest size with the right sidebar always shown enterRightSidebarExposed : function () { if (self.isNavOpen(rightSidebarMenu)) { self.toggleOffCanvas({ name : rightSidebarMenu, clearOffset : true }); } //ensure that fallback styles are removed even if menu open/close is in progress setTimeout(self.clearRightSidebarFallbackStyles, navAnimationDuration); }, //attach handlers for various breakpoints addBreakpointHandlers : function () { mediaCheck({ media : MAIN.breakPoints.onCanvas, entry : self.enterLargeSizeHandler, exit : self.exitLargeSizeHandler }); mediaCheck({ media : MAIN.breakPoints.exposeLeftSidebar, entry : self.enterLeftSidebarExposed }); mediaCheck({ media : MAIN.breakPoints.exposeRightSidebar, entry : self.enterRightSidebarExposed }); }, toggleHeaderBox : function (e) { e.preventDefault(); var m = $(this).prop("class").match(/js\-toggles\-([^\s]+)/); if (m) { $header // close any open boxes, except for the one selected .find(".disclosureBox") .not("." + m[1]) .slideUp() .end() // now show the one selected .filter("." + m[1]) .slideToggle(); } }, //given an array of classes, build a selector and return the result set findClasses : function (arrayOfClasses) { var selector = ""; for (var i = 0, j = arrayOfClasses.length || []; i < j; i++) { selector += ( i ? ", ." : "." ) + arrayOfClasses[i]; } return $(selector); } }; })(); /* end: /ISS_Static/WW/site/scripts/owv2/menus.js(21850) */ /* start: /ISS_Static/WW/site/scripts/owv2/showDifferences.js (cachekey: [])*/ (function() { var app = window.LENOVO = (window.LENOVO || {}), self = app.SHOWDIFFERENCES = { init: function() { //Show Model diff $(".tabbedBrowse-productListings").on("click", ".subseries-show-diff", this.freezeColumn); $(".subseries-showModelDiff-container-mobile").find("a").on("click", this.showMobileConfigurationDiffs); //reset state on a resize $(window).on("debounced-resize", self.onResize); self.hideIfOne(); self.initModeldiff(); }, hideIfOne: function(){ var productListlen = $(".tabbedBrowse-productListing-container").length; if(productListlen == 1){$(".subseries-showModelDiff-container").remove();} }, freezeColumn: function(e){ var $parent_li = $(this).parents("li.tabbedBrowse-productListing-container"); if($parent_li.data("show-diff") != true){ $(this).find('.btn-label').text($(this).data('hide-label')); $(this).find('.btn-icon').text('x'); $parent_li.data("show-diff",true); self.showConfigurationDiffs($parent_li.parent()); }else{ $(this).find('.btn-label').text($(this).data('show-label')); $(this).find('.btn-icon').text('>'); $parent_li.data("show-diff",false).removeClass('freeze-product-column').css({'left':''}).parent().css({'padding-left':''}); $parent_li.siblings('li').find("dl:not(.pricingSummary-details)").children().css('background-color',''); } e.preventDefault(); }, showMobileConfigurationDiffs: function(e){ $parent = $(".tabbedBrowse-productListings"); if($(this).data("show-diff") != true){ $(this).find('.btn-label').text($(this).data('hide-label')); $(this).data("show-diff",true); }else{ $(this).find('.btn-label').text($(this).data('show-label')); $(this).data("show-diff",false); } var $base_configs = $parent.children('li:first-child').find("dl:not(.pricingSummary-details)"); $parent.children('li:not(:first-child)').each(function(index, item){ $(item).find("dl:not(.pricingSummary-details)").children().each(function(child_index, child_item){ if(child_item.tagName == 'DT'){ var dt_txt = $(child_item).text(); var base_dt = $base_configs.find('dt:contains('+dt_txt+')'); if($(child_item).next('dd').text() != $(base_dt).next('dd').text()){ $(child_item).css('background-color',(window.LENOVO.customizations && window.LENOVO.customizations.MODELDIFFS_COLOR)?window.LENOVO.customizations.MODELDIFFS_COLOR:'#F5F0D0'); $(child_item).next('dd').css('background-color',(window.LENOVO.customizations && window.LENOVO.customizations.MODELDIFFS_COLOR)?window.LENOVO.customizations.MODELDIFFS_COLOR:'#F5F0D0'); } } }) }); e.preventDefault(); }, showConfigurationDiffs: function($parent){ var $base_configs = $parent.children('li:first-child').find("dl:not(.pricingSummary-details)"); $parent.children('li:not(:first-child)').each(function(index, item){ $(item).find("dl:not(.pricingSummary-details)").children().each(function(child_index, child_item){ if(child_item.tagName == 'DT'){ var dt_txt = $(child_item).text(); var base_dt = $base_configs.find('dt:contains('+dt_txt+')'); if($(child_item).next('dd').text() != $(base_dt).next('dd').text()){ $(child_item).css('background-color',(window.LENOVO.customizations && window.LENOVO.customizations.MODELDIFFS_COLOR)?window.LENOVO.customizations.MODELDIFFS_COLOR:'#F5F0D0'); $(child_item).next('dd').css('background-color',(window.LENOVO.customizations && window.LENOVO.customizations.MODELDIFFS_COLOR)?window.LENOVO.customizations.MODELDIFFS_COLOR:'#F5F0D0'); } } }) }); }, initModeldiff: function(){ //Align the configuration details top margin if the the model diff enabled var listItem = $("li.tabbedBrowse-productListing-container").eq(0); if($(listItem).find('a.subseries-show-diff').length > 0){ $(listItem).siblings().find('div.tabbedBrowse-productListing-button-container').addClass('subseries-showModelDiff-align'); } }, /** This function is calls from tabbedBrowse.js from line 280 to perform pagination on Show differences is enabled **/ showDifferencesPagination: function($items, $parent, $productToFocus, newPosition, shouldAnimate, navAnimationDuration){ if($items.eq(0).data("show-diff") == true){ if(!$items.eq(0).hasClass('freeze-product-column')) $items.eq(0).addClass('freeze-product-column'); if($productToFocus.index() == 0){ $parent.css({'padding-left':$items.eq(0).width()})[shouldAnimate ? "animate" : "css"]({ left:0}, navAnimationDuration); $items.eq(0)[shouldAnimate ? "animate" : "css"]({left:0},navAnimationDuration); } else{ $parent.css({'padding-left': $items.eq(0).width()})[shouldAnimate ? "animate" : "css"]({ left: -newPosition}, navAnimationDuration); $items.eq(0)[shouldAnimate ? "animate" : "css"]({left:newPosition}, navAnimationDuration); } return false; // Show differences pagination } return true; // regular pagination }, //actions on resize onResize: function() { var _li = $("li.tabbedBrowse-productListing-container").get(0); //If show differences is enabled and resizsed to mobile width reset the show differences if($(_li).data("show-diff") == true && !app.MAIN.activeBreakPoints.paginateSubseriesListing){ $(_li).removeClass('freeze-product-column').css({'left':''}).parent().css({'padding-left':''}); } else if($(_li).data("show-diff") == true){ self.showConfigurationDiffs($(_li).parent()); } } }; })(); /* end: /ISS_Static/WW/site/scripts/owv2/showDifferences.js(5599) */ /* start: /ISS_Static/WW/site/scripts/owv2/tabbedBrowse.js (cachekey: [])*/ (function() { var app = window.LENOVO = (window.LENOVO || {}), navAnimationDuration = 400, self = app.TABBEDBROWSE = { $productListings: null, $modelsToSwipe: null, //tab related properties firstShownTabIndex: 0, selectedTabIndex: 0, totalTabCount: null, $tabs: null, $tabContent: null, $tabDots: null, $tabArrows: null, swipeOn: true, tabWidths: [], //features media $featuresMediaItems: null, $featuresWrapper: null, shouldRun: function() { return $(".tabbedBrowse-carousel").length > 0; }, init: function() { // store models in nav to watch for swipe this.$modelsToSwipe = $("#models-cto, #models-mtm"); //protect longscroll from old js running this.$longScrollWrapper = $("#longscroll-subseries"); this.isLongscroll = $("#longscroll-subseries").length > 0; if(this.isLongscroll){ this.isGaming = this.$longscrollWrapper.hasClass("gaming"); this.isDefault = this.$longscrollWrapper.hasClass("default"); } //tab-related handlers this.setupTabs(); //cache configurator price nodes this.$totalPriceNodes = $(".pricingSummary-details-price"); this.$adjustedPriceNodes = $(".pricingSummary-details-final-price, .configuratorItem-summary-priceText-value"); this.$savingsAmountNodes = $(".pricingSummary-savings-amount"); //open features tab (can't rely on hashchange in IE7 $(".mediaGallery-productDescription-body").on("click.tabbedBrowse", "a[href=#features]", this.activateTabByHash); //reset state on a resize $(window).on("debounced-resize", self.onResize); //run once on initialization self.onResize(); }, //add handlers and cache selectors related to tabs setupTabs: function() { //cache the tab content containers self.$tabs = $(".tabbedBrowse-carousel .tabs-item"); self.$tabs.parent().css("position", "relative"); self.$tabContent = $(".tabbedBrowse-module"); self.totalTabCount = self.$tabs.length; self.$tabArrows = $(".arrows-tabs").on("click.tabbedBrowse", ".arrows-tabs-arrow", this.tabScrollerEventMonitor); self.$tabDots = $(".tabbedBrowse-carousel .carouselDots span"); self.$tabScroller = $(".tabs-wrapper .scroll-wrapper"); //handle tab clicks self.$tabs.parent().on("click.tabbedBrowse", ".tabs-item", this.tabClickHandler); self.$tabDots.parent().on("click.tabbedBrowse", "span", this.tabDotClickHandler); //handle product listing navigation $(".tabbedBrowse-productListings-controls").on("click.tabbedBrowse", ".js-previous, .js-next", this.productNavigationHandler); // handle tab swipe // Note: this is disabled in IE due to a bug in the hammer library // https://github.com/EightMedia/hammer.js/issues/310 if (!app.MAIN.isIE()) { self.$tabScroller .hammer({ swipe_velocity: 0.5, "stop_browser_behavior": false }) .on("swipeleft", function(e) { if (self.swipeOn) { if (e.gesture) { e.gesture.preventDefault(); } // don't allow right swipe on last if (self.getFinalShownTabIndex() !== self.$tabs.length) { self.tabScrollerEventMonitor(e); } } }) .on("swiperight", function(e) { if (self.swipeOn) { if (e.gesture) { e.gesture.preventDefault(); } // don't allow right swipe on first if (self.firstShownTabIndex !== 0) { self.tabScrollerEventMonitor(e); } } }) .on("dragleft", function(e) { if (self.swipeOn) { if (e.gesture) { e.gesture.preventDefault(); } } }) .on("dragright", function(e) { if (self.swipeOn) { if (e.gesture) { e.gesture.preventDefault(); } } }); } // This enables browser navigation (back button, forward button) in most browsers // IE 7 and below doesn't have this, but users can still click on the tab they want // This also allows for links in the page to go directly to the tab outside of the tab bar $(window).on("hashchange.tabbedBrowse", self.activateTabFromCurrentHash); //initialize to current tab based on hash (or first tab) self.activateTabFromCurrentHash(); // handle external links to tabs $("body").on("click.tabbedBrowse", ".js-activates-tab", self.externalTabLinkHandler); // watch swipe actions on items in nav self.watchNavSwipe(self.$modelsToSwipe); }, watchNavSwipe: function(models) { // swipe left/right on models in nav // Note: this is disabled in IE due to a bug in the hammer library // https://github.com/EightMedia/hammer.js/issues/310 if (!app.MAIN.isIE()) { $(models) .hammer() .on("swipeleft", function() { if (self.swipeOn) { self.updateProductListing($(this).closest(".tabbedBrowse-module"), true, "right"); } }) .on("swiperight", function() { if (self.swipeOn) { self.updateProductListing($(this).closest(".tabbedBrowse-module"), true, "left"); } }); } }, //match heights between columns for various elements matchHeights: function() { self.updateProductListingHeights(".tabbedBrowse-productListing-featureList", "dd"); self.updateProductListingHeights(".tabbedBrowse-productListing-header", ".tabbedBrowse-productListing-title"); if(LENOVO.COLORSELECTOR && LENOVO.COLORSELECTOR.shouldRun()){ self.updateProductListingHeights(".tabbedBrowse-productListing", ".tabbedBrowse-productListing-body .pricingSummary"); self.updateProductListingHeights(".tabbedBrowse-productListing", ".colorSelector__presel"); } self.updateProductListingHeights(".tabbedBrowse-productListing", ".tabbedBrowse-productListing-body"); // Accessories tab if (!this.isGaming) { /// GWE-1509 //self.updateProductListingHeights(".tabbedBrowse-accessories-item-container", ".tabbedBrowse-accessories-item-title"); self.updateProductListingHeights(".tabbedBrowse-accessories-item-container", ".tabbedBrowse-accessories-item-description"); //self.updateProductListingHeights(".tabbedBrowse-accessories-item-container", ".pricingSummary"); self.updateProductListingHeights(".tabbedBrowse-accessories-item-container",".pricingSummary-purchase-wrapper"); } }, //update row heights appropriately within each product listing updateProductListingHeights: function(columnSelector, rowSelector) { self.$productListings = self.$productListings || $(".tabbedBrowse-module"); self.$productListings.each(self.updateRowHeights, [columnSelector, rowSelector]); }, //make row heights consistent within a set of containers updateRowHeights: function(columnSelector, rowSelector) { var columns = $(columnSelector, this), length = columns.eq(0).find(rowSelector).length, index; //remove height overrides columns.find(rowSelector).css("height", ""); //when listings are stacked, just clear any overrides if (!app.MAIN.activeBreakPoints.paginateSubseriesListing) { return; } //reset correct matching heights for (index = 0; index < length; index++) { self.updateRowHeight(columns.find(rowSelector + ":eq(" + index + ")")); } //ensure that product listings are updated on resize self.updateProductListing($(this)); }, //set a consistent height for a set of elements updateRowHeight: function(elements) { var height, hasDifference, index, length, maxHeight = 0; for (index = 0, length = elements.length; index < length; index++) { height = elements.eq(index).height(); //track whether there is actually a difference if (maxHeight && height !== maxHeight) { hasDifference = true; } maxHeight = Math.max(height, maxHeight); } //only override height, if it is necessary if (hasDifference) { elements.height(maxHeight); } }, //scroll the product listing updateProductListing: function($container, shouldAnimate, direction) { var maxProductsCanShow, totalProducts, maxStartingIndex, moveCount, newIndex, $items = $container.find(".tabbedBrowse-productListing-container"), currentIndex = ($items.parent().data("currentIndex")) || 0; if(currentIndex < 0) currentIndex = 0; //FIX: If it is negative value then it should be if (!$items.length) { return; } //get max products we can show and the maximum starting index maxProductsCanShow = self.getMaxProductsToShow($container); totalProducts = $container.find(".tabbedBrowse-productListing-container").length; maxStartingIndex = totalProducts - maxProductsCanShow + (totalProducts > 1 ? 0 : 1); //if we can only fit 1, then still allow movement if(maxStartingIndex < 0) maxStartingIndex=0; //FIX: If it is negative value then it should be //can be called with no direction to update on resize moveCount = direction ? (maxProductsCanShow - 1 || 1) : 0; newIndex = currentIndex + (direction === "right" ? moveCount : -moveCount); //index needs to be between 0 and the max starting index newIndex = Math.min(Math.max(0, newIndex), maxStartingIndex); //move to the appropriate index self.focusProductListing($items, newIndex, shouldAnimate); //update the previous/next buttons $container.find(".js-previous").attr("disabled", newIndex === 0 ? "disabled" : null); $container.find(".js-next").attr("disabled", newIndex >= maxStartingIndex ? "disabled" : null); }, //determine the maximum number of products that can currently be shown at current size getMaxProductsToShow: function($container) { var productWidth = $container.find(".tabbedBrowse-productListing-container").width(), containerWidth = $container.find(".tabbedBrowse-productListings-scroller").width(); return Math.floor(containerWidth / productWidth); }, //focus (show first in container) a specific product listing within a group of products focusProductListing: function($items, index, shouldAnimate) { var newPosition, $parent, $productToFocus = $items.eq(index || 0); if ($productToFocus.length) { newPosition = $productToFocus.length && $productToFocus.position().left; $parent = $items.parent(); //store new index $parent.data("currentIndex", index).css("position", "relative"); if(app.SHOWDIFFERENCES.showDifferencesPagination($items, $parent, $productToFocus, newPosition, shouldAnimate, navAnimationDuration)){ $parent[shouldAnimate ? "animate" : "css"]({ left: -newPosition }, navAnimationDuration); } } }, activateTabFromCurrentHash: function() { var hash = unescape(window.location.hash); if (hash == '#features') hash = "#tab-features"; var index = hash ? self.getTabIndexFromUrl(hash) : 0; //if no hash activate the first tab if (index >= 0) { self.activateTab(index, !hash); } }, //see if the hash from a url matches a tab (can pass just hash too) getTabIndexFromUrl: function(url) { var hash = url && url.match(/(#.+)$/); return hash ? self.$tabs.has("a[href=" + hash[1] + "]").index() : -1; }, //active a tab using the hash to retrieve the index externalTabLinkHandler: function(e) { var $el = $(this), index = self.getTabIndexFromUrl($el.prop("href")); if (index >= 0) { //activate the appropriate index self.activateTab(index); //scroll to the top of the tabs $(document).scrollTop(self.$tabs.offset().top); e.preventDefault(); } }, //select a tab activateTab: function(index, keepHash) { var $el, selectedClass = "tabs-item-currentTab"; //update selected class of the tab element $el = self.$tabs.eq(index || 0); $el.addClass(selectedClass).siblings().removeClass(selectedClass); //update the hash, without scrolling the page if (!keepHash) { self.updateHash($el.find("a").attr("href").replace("#", "")); } //show the appropriate content self.$tabContent.hide().eq(index).show(); /* commenting this, to prevent the page from scrolling on tabclick if (!keepHash) { $('html, body').animate({ scrollTop: self.$tabContent.eq(index).offset().top}, 0); }*/ //cache the index self.selectedTabIndex = index; self.updateTabDots(); //scroll tab into view self.focusTab($el.index(), true, true); //make sure that heights and image placements are proper when displayed self.onResize(); }, //show/hide the tab arrows depending on whether all tabs are shown toggleTabArrows: function() { var showArrows, totalTabWidth = 0; //need to find the width of all tabs, as container is not useful for this comparison self.$tabs.each(function() { totalTabWidth += $(this).width(); }); showArrows = totalTabWidth > self.$tabScroller.width(); self.$tabScroller[showArrows ? "addClass" : "removeClass"]("has-arrows"); self.$tabArrows[showArrows ? "show" : "hide"](); self.$tabDots.parent()[showArrows ? "show" : "hide"](); //clear scrolling, if all fit if (!showArrows) { self.$tabs.parent().css("left", 0); self.firstShownTabIndex = 0; } return showArrows; }, //make a tab the first tab shown focusTab: function(index, shouldAnimate, normalizeIndex) { var tab, tabLeft, tabContainerWidth, newIndex = normalizeIndex ? self.normalizeTabIndex(index) : index; tab = self.$tabs.eq(newIndex); tabLeft = (tab.length && tab.position().left) || 0; tabContainerWidth = $(".scroll-wrapper").width(); // if on last item or in final index of tabs and it is the new tab, animate to last item so no gap is revealed if (((index + 1) === self.$tabs.length || (self.getFinalShownTabIndex() === self.$tabs.length) && (newIndex === self.firstShownTabIndex))) { tabLeft = (self.$tabs.last().position().left) - (tabContainerWidth - self.$tabs.last().outerWidth()); } self.$tabs.parent()[shouldAnimate ? "animate" : "css"]({ left: -tabLeft }, navAnimationDuration); self.firstShownTabIndex = newIndex; self.updateTabs(); }, //determine the final tab that is completely shown (no scrolling required) getFinalShownTabIndex: function() { var finalShownIndex, containerWidth, index, length; //get the width of each tab (widths are different) self.tabWidths = self.$tabs.map(function() { return $(this).outerWidth(); }).get(); finalShownIndex = self.tabWidths.length; containerWidth = self.$tabScroller.width(); //determine the final tab that is completely shown for (index = self.firstShownTabIndex, length = self.tabWidths.length; index < length; index++) { containerWidth -= self.tabWidths[index]; if (containerWidth < 0) { finalShownIndex = index - 1; break; } } return finalShownIndex; }, //given an intended final index to show, determine the index we need to scroll to display it normalizeTabIndex: function(intendedFinalIndex) { var currentFinalIndex, containerWidth, index, firstIndex = 0; //if this is the first tab, then see if can scroll one to the left to match media gallery functionality if (intendedFinalIndex && intendedFinalIndex === self.firstShownTabIndex) { return intendedFinalIndex - 1; } currentFinalIndex = self.getFinalShownTabIndex(); //no action necessary, if the new tab is already shown if (intendedFinalIndex <= currentFinalIndex && intendedFinalIndex >= self.firstShownTabIndex) { return self.firstShownTabIndex; } containerWidth = self.$tabScroller.width(); //determine the final tab that is completely shown for (index = intendedFinalIndex; index >= 0; index--) { containerWidth -= self.tabWidths[index]; if (containerWidth < 0) { firstIndex = index + 1; break; } } return firstIndex; }, //hide/show arrows and scroll tabs updateTabs: function(shouldAnimate, direction) { var finalShownIndex; //if all are shown, then nothing else is necessary if (!self.toggleTabArrows()) { return; } finalShownIndex = self.getFinalShownTabIndex(); if (direction === "right") { //focus the finalShownIndex unless maxCanShow is 1 self.firstShownTabIndex = self.firstShownTabIndex + 1; // determining updated final index before focus to help detect end gap finalShownIndex = self.getFinalShownTabIndex(); self.focusTab(self.firstShownTabIndex, shouldAnimate); } if (direction === "left") { self.firstShownTabIndex = self.firstShownTabIndex - 1; // determining updated final index before to help detect end gap finalShownIndex = self.getFinalShownTabIndex(); self.focusTab(self.firstShownTabIndex, shouldAnimate); } //enable/disable tab arrows self.$tabArrows.find(".js-arrow-prev").attr("disabled", self.firstShownTabIndex === 0 ? "disabled" : null); self.$tabArrows.find(".js-arrow-next").attr("disabled", finalShownIndex >= self.$tabs.length - 1 ? "disabled" : null); }, //update the hash without scrolling updateHash: function(id) { if (id) { var $el = $("#" + id).attr("id", id + "-temp"); window.location.hash = id; $el.attr("id", id); } }, updateTabDots: function() { var $previousTab, $currentTab; $previousTab = self.$tabDots.filter(".carouselDots-active"); $currentTab = self.$tabDots.eq(self.selectedTabIndex); if ($previousTab[0] !== $currentTab[0]) { $previousTab.add($currentTab).toggleClass("carouselDots-inactive carouselDots-active"); } }, tabDotClickHandler: function(e) { self.activateTab(self.$tabDots.index(this)); e.preventDefault(); }, //handle clicking on a tab tabClickHandler: function(e) { self.activateTab(self.$tabs.index(this)); e.preventDefault(); }, tabScrollerEventMonitor: function(e) { var isLeft = $(this).hasClass("js-arrow-prev") || e.type === "swiperight"; self.updateTabs(true, isLeft ? "left" : "right"); e.preventDefault(); }, //clicking on next/previous in product listing productNavigationHandler: function(e) { var $el = $(this), isLeft = $el.hasClass("js-previous"), container = $el.closest(".tabbedBrowse-module"); self.updateProductListing(container, true, isLeft ? "left" : "right"); e.preventDefault(); }, //actions on resize onResize: function() { //adjust tabs self.updateTabs(); //adjust row heights, as necessary self.matchHeights(); }, }; })(); /* end: /ISS_Static/WW/site/scripts/owv2/tabbedBrowse.js(20487) */ /* start: /ISS_Static/WW/site/scripts/owv2/inventory.js (cachekey: [])*/ // Generated by CoffeeScript 1.8.0 /* * Dependencies: LENOVO, jQuery * * This is the INVENTORY module in the LENOVO application namespace (referenced * as LENOVO.INVENTORY). This module is intended to provide support for dynamic * inventory lookup via the REST API delivered in FP 1660 during Release 24b. * * This is an alternative to the AvailabilityHandler method(s) created in JDA's * "WciInventory.js" file, the default functionality delivered with the * requirement. * * On the page, the settings can be configured via standard LENOVO configuration * object for a module, i.e.- * * var LNV_options = window.LNV_options || {}; * LNV_options.INVENTORY_options = { * availabilityWrapper: ".pricingSummary-shipping", * ctaWrapper: ".tabbedBrowse-productListing-button-container", * ctaButton: "a.button-full", * disabledTemplate: "", * esmClass: "rci-esm", * hideDepletedItem: false, * maximumReqInQueue: 4, * maximumWaitTime: 2000, * msgClass: "rci-msg", * successFn: null, * wrappingPrefix: ".item", * wrappingSuffix: "oid", * wrappingDelimiter: "_" * }; * * These settings will be applied when the main LENOVO application is run via * LENOVO.MAIN.start(), or upon the first request made for inventory levels for * an item on the a page. * * Inventory levels are retrieved asynchronously, and single items or groups of * multiple items can be bundled into a single request. An "item queue" is * created by calling LENOVO.INVENTORY.queue() from the page, passing in the * REST URL and data object of the item to lookup: * * Single item: * LENOVO.INVENTORY.queue("http://shop.lenovo.com/rci/services/inventory/1.0/LenovoPortal/web/availability", { Oid: ":00001234:0000ABCD:" }); * * Multiple items: * var items = [{ Oid: ":00001234:0000ABCD:" }, { Oid: ":00002345:0000BCDE:" }, { Oid: ":00003456:0000CDEF:" }] * LENOVO.INVENTORY.queue("http://shop.lenovo.com/rci/services/inventory/1.0/LenovoPortal/web/availability", items); * * This call collects items in an array and can send a single request via GET, * or multiple requests based on configuration with a maximum number of items * and maximum wait time to break up requests. */ (function(app, $) { var self, _M, _MAIN, _UTILS, _ajaxDefaults, _baseurl, _debug, _decodeHtml, _defaultConfig, _defaultItemFormat, _equalHeight, _initialized, _itemQueue, _onFail, _onSuccess, _parseItem, _timer, _url, _urls, _verbose, _version; _M = "INVENTORY"; _version = "2014-11-11"; _baseurl = window.long_url || ""; _debug = window.debugAllowed || false; _verbose = false; _initialized = false; _urls = null; _MAIN = app.hasOwnProperty("MAIN"); _UTILS = app.hasOwnProperty("UTILS"); _ajaxDefaults = { url: "", data: "", dataType: "json", contentType: "application/json", type: "POST", cache: false }; _defaultConfig = { availabilityWrapper: ".pricingSummary-shipping, .pricingSummary-expressShip", ctaWrapper: ".tabbedBrowse-productListing-button-container", ctaButton: "a.button-full", disabledTemplate: "", esmClass: "rci-esm", hideDepletedItem: false, maximumReqInQueue: 4, maximumWaitTime: 2000, msgClass: "rci-msg", successFn: null, wrappingPrefix: ".item", wrappingSuffix: "oid", wrappingDelimiter: "_" }; _defaultItemFormat = { GroupName: "", ItemCode: "", Oid: "" }; _itemQueue = []; _timer = []; _url = null; _decodeHtml = function(input) { var e; e = document.createElement("div"); e.innerHTML = input; if (e.childNodes.length === 0) { return ""; } else { return e.childNodes[0].nodeValue; } }; _equalHeight = function(ele) { var t; t = 0; $(ele).css("height", "auto").each(function() { var h; h = $(this).height(); if (h > t) { t = h; } }).height(t); }; _onSuccess = function(data) { var items; if (_verbose) { console.group("LENOVO.INVENTORY: _onSuccess"); console.log(data); console.groupEnd(); } if (data.Items.Item) { items = $.makeArray(data.Items.Item); $.each(items, _parseItem); self.onResize(); $(window).one("scroll.resize", self.onResize); } }; _parseItem = function(index, item) { var $item, d, disabledBtn, esm, esmClass, groupname, itemcode, msg, msgClass, oid, pfx, sfx; $item = null; oid = item.Oid; groupname = item.GroupName; itemcode = item.ItemCode; d = self.settings.wrappingDelimiter; sfx = self.settings.wrappingSuffix.toLowerCase(); pfx = self.settings.wrappingPrefix; msg = item.InventoryMessage; esm = item.EstimatedShipMessage; disabledBtn = _decodeHtml(self.settings.disabledTemplate); msgClass = "." + self.settings.msgClass; esmClass = "." + self.settings.esmClass; if (sfx === "oid" && oid !== "") { $item = $(pfx + oid.replace(/:/g, d)); } else if (sfx === "itemgroup" && (groupname !== "" && itemcode !== "")) { $item = $(pfx + d + groupname + d + itemcode); } if (_verbose) { console.group("LENOVO.INVENTORY: _parseItem -> " + oid); console.log("$item[0] = " + $item[0]); console.log("msg = " + msg); console.log("esm = " + esm); } if ($item && item.IsValid === "true") { if (item.InInventory === "true") { $item.find(msgClass).html(msg).end().find(esmClass).html(esm); } else if (self.settings.hideDepletedItem === true) { $item.hide(); } else { $item.find(msgClass).empty().end().find(esmClass).html(esm).end().find(self.settings.ctaWrapper).find(self.settings.ctaButton).replaceWith(disabledBtn); } self.onResize(); } else { if (_debug) { console.warn("WARNING: Could not apply dynamic inventory to item."); console.group("Item details"); console.groupCollapsed("Item wrapper:"); console.log($item); console.groupEnd(); console.groupCollapsed("Item JSON data:"); console.log(item); console.groupEnd(); console.groupEnd(); } if (_verbose) { console.groupEnd(); } } }; _onFail = function(jqXHR, textStatus, errorThrown) { if (_verbose) { console.group("LENOVO.INVENTORY: _onFail"); console.error("[" + textStatus + "]: " + errorThrown); console.log(jqXHR.responseText); console.groupEnd(); } }; self = app[_M] = { settings: null, callback: _onSuccess, onfail: _onFail, shouldRun: function() { return app.hasOwnProperty(_M); }, init: function(options) { var LNV_options, debug, verbose; if (!_initialized) { if (_debug) { console.info("LENOVO.INVENTORY: init"); } if (options == null) { LNV_options = window.LNV_options || {}; options = LNV_options.inventory_options || {}; } _MAIN = app.hasOwnProperty("MAIN"); _UTILS = app.hasOwnProperty("UTILS"); if (_UTILS) { debug = app.UTILS.isDebug(); verbose = app.UTILS.isVerbose(); } self.settings = $.extend(true, _defaultConfig, options); if ((typeof successFn !== "undefined" && successFn !== null) && $.isFunction(self.settings.successFn)) { self.callback = self.settings.successFn; } $(window).on(app.MAIN.resizeEventName || "debounced-resize", self.onResize); _initialized = true; } }, /* * LENOVO.INVENTORY.queue(url, items) -> Called externally, this should * collect requests then call LENOVO.INVENTORY.lookup with a bundled * request object * @param {String} url RCI (REST) URL * @param {Array} items Array of Item objects to process */ queue: function(url, items) { var LNV_options, config; if (url !== "" && typeof url === "string") { clearTimeout(_timer); items = $.makeArray(items); if (!_initialized) { LNV_options = window.LNV_options || {}; config = LNV_options.INVENTORY_options || {}; self.init(config.INVENTORY_options); } if (items.length < self.settings.maximumReqInQueue) { _url = url; $.merge(_itemQueue, items); _timer = setTimeout(self.process, self.settings.maximumWaitTime, _url, $.merge([], _itemQueue)); } else { _url = url; self.process(_url, items); } } }, /* * LENOVO.INVENTORY.process(url, items) -> Used to process an array of * items, grouping them based on the maximumReqInQueue settings * @param {String} url RCI (REST) URL * @param {Array} items Array of Item objects to process */ process: function(url, items) { var groups; groups = self.group(items); _itemQueue.length = 0; $.each(groups, function(i, group) { self.lookup(url, group); }); }, /* * LENOVO.INVENTORY.group(items) -> Formats item objects in an array to * get them in the correct format for REST lookup, and then returns a * nested array of smaller arrays based on the maximumReqInQueue setting * @param {Array} items Array of item objects to format and group * @return {Array} New array of array groups */ group: function(items) { var groups, idx, len, max; items = $.makeArray(items); $.each(items, function(i, item) { items[i] = $.extend(true, {}, _defaultItemFormat, item); }); groups = []; max = parseInt(self.settings.maximumReqInQueue, 10); idx = 0; len = items.length; while (idx < len) { groups.push(items.slice(idx, idx += max)); } return groups; }, /* * LENOVO.INVENTORY.lookup(url, params) -> Called externally, this * performs a single item inventory request (synchronous). * @param {String} url RCI (REST) URL * @param {Object} items Array of items */ lookup: function(url, items) { var req; items = $.makeArray(items); req = { Items: { Item: $.merge([], items) } }; self.request({ url: url, data: JSON.stringify(req), type: "POST" }); }, /* * LENOVO.INVENTORY.request(options) -> Performs an AJAX request to get * item inventory levels based on the options passed into it. * @param {[type]} options AJAX overrides for the request */ request: function(options) { var LNV_options, config, settings; if (!_initialized) { LNV_options = window.LNV_options || {}; config = LNV_options.INVENTORY_options || {}; self.init(config.INVENTORY_options); } settings = $.extend(true, _ajaxDefaults, options); $.ajax(settings).done(self.callback).fail(self.onfail); }, onResize: function() { var $avail, esm, msg; $avail = $(self.settings.availabilityWrapper); msg = "." + self.settings.msgClass; esm = "." + self.settings.esmClass; _equalHeight($avail.find(msg)); _equalHeight($avail.find(esm)); _equalHeight($avail); if (app.TABBEDBROWSE != null) { app.TABBEDBROWSE.matchHeights(); } } }; })(window.LENOVO = window.LENOVO || {}, jQuery); /* * https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout * * A completely unobtrusive hack for every other mobile or desktop browser, * including IE9 and above, using JavaScript conditional comments to provide * additional parameter support to the setTimeout/setInterval methods in < IE8. */ /*@cc_on //conditional IE < 9 only fix @if (@_jscript_version <= 6) (function(f){ window.setTimeout =f(window.setTimeout); window.setInterval =f(window.setInterval); })(function(f){return function(c,t){var a=[].slice.call(arguments,2);return f(function(){c.apply(this,a)},t)}}); @end @*/; /* end: /ISS_Static/WW/site/scripts/owv2/inventory.js(12463) */ /* start: /ISS_Static/WW/site/scripts/owv2/common.js (cachekey: [])*/ $(function () { //Init Galleria with proper theme if gallery markup is present on page if (!!window.Galleria && $('.galleria').length) { Galleria.loadTheme('/ISS_Static/WW/site/scripts/galleria/themes/lenovorwd/galleria.lenovorwd.js'); Galleria.run('.galleria'); } //To hide limited offers when not exists if ($(".calloutBox-mediaGallery").length > 0 && $(".calloutBox-mediaGallery div.calloutBox-item").length < 1 && $(".calloutBox-mediaGallery #standard-on").length < 1) { $(".offCanvas-bar_3-right").empty(); } //To hide the links when OffCanvas left section is empty if (!$.trim($('.offCanvas-bar_3-left').html()).length) { $(".bar_3-leftLink").hide(); } //show 'offers' when Offcanvas right section is not empty if ($.trim($('.offCanvas-bar_3-right').text()).length) { $(".bar_3-rightLink").addClass("offerShow"); } //For Sidebar Navigation Fix var txt = $('.sidebarNav-section .sidebarNav-heading'); $.each(txt, function () { if ($(this).text().length > 18) { $(this).parent('.expandableHeading.has-arrowLink, .has-arrowLink.unexpandableHeading').addClass('twolines'); } }); //To hide the narrow results off canvas link if no faceted browse or sidebarnav var facetBrowserWrapper = $('div.offCanvas-bar_3-left div#facetedBrowseWrapper'); var sidebarNav = $('div.offCanvas-bar_3-left div.sidebarNav'); if (facetBrowserWrapper.length == 0 && sidebarNav.length == 0) { $(".bar_3-leftLink").hide(); } //To hide the espots in navigation when no espot is present var espots = $(".productList .espots"); $.each(espots, function () { if ($(this).find("li[itemprop='itemOffered'], div[itemprop='itemOffered']").length < 1) { $(this).remove(); } }); /* //To hide the show differences button when only one model in subseries page var showDifference = $(".tabbedBrowse-productListings"); $.each(showDifference,function(){ if($(this).find(".tabbedBrowse-productListing-container" ).length < 2){ $(".subseries-showModelDiff-container").remove(); } }); */ //Stop event bubbling on links in IE8 if ($('html').hasClass('lt-ie9') && $("#splitterPage").length) { $(".mainContent a").click(function (event) { event.stopPropagation(); }); $(".bar_3-offCanvas-heading").removeClass("js-closesOffCanvasMenu"); } //To adjust the height of two columns in myaccount login page var highestBox = 0; $('.signInModule .signInModule-content').each(function () { if ($(this).height() > highestBox) { highestBox = $(this).height(); } }); $('.signInModule .signInModule-content').height(highestBox); //Add to cart accessories $(".accessories-add-to-cart").click(function () { var $this = $(this), btn_label = $this.text(), cache = $this.children(), $parent = $this.parents(".tabbedBrowse-accessories-and-services-wrapper"); $parent.addClass("configuratorAjax"); $.get($this.data('url')).done(function () { if($("#longscroll-subseries").hasClass("gaming")){ $this.text(AddedToCart).append(cache).animate({disabled : true}); }else{ $this.text(AddedToCart).append(cache).animate({disabled : true}).addClass("button-standard").removeClass("button-called-out"); } //setTimeout(function(){$this.text(btn_label).append(cache).animate({disabled:false}).removeClass("button-called-out-alt")},3000); }).always(function () { $parent.removeClass("configuratorAjax"); }); }); //FP1912- To toggle the tabbed navigation $(".productList .menuLevel_2").each(function () { $(".menu_with_tabs > li > ul > li:first").addClass("selected"); $(".menu_with_tabs .menu_tabs > ol:last").hide(); $(".menu_with_tabs > li > ul > li:first").click(function (event) { $(this).addClass("selected"); $(this).siblings('li').removeClass("selected"); $(".menu_with_tabs .menu_tabs > ol:last").hide(); $(".menu_with_tabs .menu_tabs > ol:first").show(); return false; }); $(".menu_with_tabs > li > ul > li:last").click(function (event) { $(this).addClass("selected"); $(this).siblings('li').removeClass("selected"); $(".menu_with_tabs .menu_tabs > ol:last").show(); $(".menu_with_tabs .menu_tabs > ol:first").hide(); if ($(".promo_links").attr("style") !== typeof undefined) { $(".menu_with_tabs .menu_tabs > ol:last").height($(".promo_links").height() - 80); } return false; }); }); //FP1912 - To adjust the height in navigation for grey column $(".link-wrapper > a").each(function () { $(this).click(function () { var menu_with_tabs = $(this).parent('.link-wrapper').siblings('.menuLevel_2').find('.menu_with_tabs'); if ($(menu_with_tabs).length = 1) { setTimeout(function () { var tab_menu = menu_with_tabs.children('.menu_tabs:nth-child(1)'); var tab_content = menu_with_tabs.children('.menu_tabs:nth-child(2)'); var promo_links = menu_with_tabs.find('.tabpromo .promo_links'); if ((tab_content.height() + tab_menu.outerHeight()) > promo_links.height()) { promo_links.height(tab_content.height() + tab_menu.outerHeight()); } else { tab_content.height(promo_links.height() - tab_menu.outerHeight()); } }, 200); } }); }); //To hide the tabs when only one is present if ($(".tabbedBrowse .tabs-main .tab-item a.sytems-tab").length < 2) { $(".tabbedBrowse .tabs-main .tab-item a.sytems-tab").remove(); if ($(window).width() > 896) { $(".tabbedBrowse .tabs-main .tab-item .tabbedBrowse-Xsystems").css('margin-top', '-75px'); } } // protect new splitter page (FP-2451) from this JS var $newSplitter = $("#seriesSplitter").length; if ($newSplitter != 1) { //To fix long sidebar after expanding overlapsing into footer var expandingCheckHeight = (function checkHeight() { if ($(window).width() >= 960) { var pageTypeContainer = null; if ($('.categoryWrapper').length) pageTypeContainer = $('.categoryWrapper') else if ($('.brandListingWrapper').length) pageTypeContainer = $('.brandListingWrapper') else if ($('.seriesListings').length) pageTypeContainer = $('.seriesListings') if (pageTypeContainer != null) { window.setTimeout(function () { if ($('.offCanvas-bar_3-left').outerHeight() > pageTypeContainer.outerHeight()) { pageTypeContainer.outerHeight($('.offCanvas-bar_3-left').outerHeight() - (pageTypeContainer.offset().top - $('.offCanvas-bar_3-left').offset().top)); if (pageTypeContainer.hasClass('seriesListings')) pageTypeContainer.css('float', 'none'); } else { pageTypeContainer.outerHeight('auto'); if ($('.offCanvas-bar_3-left').outerHeight() > pageTypeContainer.outerHeight()) { pageTypeContainer.outerHeight($('.offCanvas-bar_3-left').outerHeight() - (pageTypeContainer.offset().top - $('.offCanvas-bar_3-left').offset().top)); if (pageTypeContainer.hasClass('seriesListings')) pageTypeContainer.css('float', 'none'); } else { if (pageTypeContainer.hasClass('seriesListings')) pageTypeContainer.css('float', 'left'); } } $('.body-inner-wrapper').css('min-height', ($('.mainFooter').offset().top + $('.mainFooter').outerHeight())); }, 300); } } else { if (pageTypeContainer != null) { pageTypeContainer.outerHeight('auto'); } } return checkHeight; //return the function itself to reference }()); //auto-run $('.offCanvas-bar_3-left .expandableHeading').on('click', function () { expandingCheckHeight(); }); } //set LMD values var lmdTagging = JSON.parse(sessionStorage.getItem("lmdTagging")); if(lmdTagging && lmd){ lmd.selectiontype = lmdTagging.type; lmd.selectionvalue = lmdTagging.value; sessionStorage.removeItem("lmdTagging"); } }); /* end: /ISS_Static/WW/site/scripts/owv2/common.js(7642) */ /* start: /ISS_Static/WW/site/scripts/owv2/compare-table.js (cachekey: [])*/ (function(Modernizr) { var app = window.LENOVO = (window.LENOVO || {}); var self = app.COMPARETABLE = { win: $(window), wrapper: null, colCloneWrapper: $("
"), // rowCloneWrapper: $("
"), rowCloneWrapper: $("
"), scroller: null, table: null, mainHeadings: null, colClone: null, rowClone: null, resizeTO: null, shouldRun: function() { return !!$(".compareTable-table").length; }, init: function() { // cache various elements this.wrapper = $(".compareTable"); this.scroller = $(".compareTable-scrollable .compareTable-overflowContainer"); this.table = $(".compareTable-table"); this.mainHeadings = $(".compareTable-mainHeadings"); self.setupFixedColumn(); self.setupSectionAccordion(); self.setupColumnToggle(); self.setupTooltips(); // This feature is being moved to M2 // if (!$("#no-fixed-header").length) { // self.setupFixedRow(); // } self.setupResizeEvent(); self.setupScrollEvent(); if (!Modernizr.borderradius) { this.addFeatureImgFallback(); } }, setupFixedColumn: function() { self.colClone = self.table.clone(); self.colClone .addClass("compareTable-clone") .appendTo(self.colCloneWrapper); self.colCloneWrapper.appendTo(self.wrapper); self.toggleColumnClone(); // see if we need it right now }, setupFixedRow: function() { var offset; // wait for things to settle before doing the initial clone setTimeout(function() { // set up the cloned header row self.rowClone = self.table.clone(); self.rowClone .find("tbody") .remove() .end() .find("thead") .not(":first") .remove() .end() .end() .addClass("compareTable-headingClone") .css("position", "relative") // .appendTo(self.rowCloneWrapper.find(".compareTable-headingClone-parent")); .appendTo(self.rowCloneWrapper); offset = self.table.offset(); // set up the wrapper to be fixed and positioned correctly initially self.rowCloneWrapper.appendTo("body"); // set up side scrolling match on cloned header self.scroller.on("scroll", function() { self.rowClone.css("left", (self.scroller.scrollLeft() * -1)); }); self.repositionHeaderClone(); self.resizeHeaderClone(); self.toggleHeaderClone(); // see if we need it right now }, 500); }, toggleColumnClone: function() { if (this.colClone) { if (this.scroller.get(0).offsetWidth < (this.scroller.get(0).scrollWidth - 5)) { this.colClone.show(); } else { this.colClone.hide(); } } }, toggleHeaderClone: function() { var scrollTop, tableTop; if (this.rowClone) { scrollTop = this.win.scrollTop(); tableTop = this.mainHeadings.offset().top; if (scrollTop > tableTop && scrollTop < (tableTop + this.table.height() - this.rowClone.height())) { this.rowCloneWrapper.show(); } else { this.rowCloneWrapper.hide(); } } }, resizeHeaderClone: function() { var headingRow = this.table.find(".compareTable-mainHeadings"), headings = headingRow.find("td, th"); this.rowCloneWrapper .width(this.scroller.width() - headings.filter(".compareTable-addRemoveItems").width() - 2) .find("table") .width((headingRow.width() + 2) + "px") .end() // resize each cell, necessary since the row clone is not in the // original table's container .find(".compareTable-mainHeadings") .find("td, th") .each(function() { $(this).width(headings.filter(":eq(" + $(this).index() + ")").width()); }); }, repositionHeaderClone: function() { if (this.rowCloneWrapper) { this.rowCloneWrapper.css("left", this.table.find(".compareTable-mainHeadings th:visible:first").offset().left); } }, setupColumnToggle: function() { var container = this.table.find(".compareTable-addRemoveItems"); container // toggle the selection checkboxes .find("button") .on("click", function() { container.toggleClass("is-expanded"); }) .end() // handle changes to the selections .on("change", ":checkbox", function() { self.handleColumnSelection(this); }); // Add pass-through event on clone self.colClone.find(".compareTable-addRemoveItems button").click(function(e) { e.preventDefault(); e.stopPropagation(); // no need to bubble the cloned event container.find("button").click(); }); }, handleColumnSelection: function(checkbox) { var cells, colHeader, groupBrandCount, groupHeader, active = $(checkbox).is(":checked"), headerRow = this.table.find(".compareTable-mainHeadings"), val = checkbox.value; colHeader = headerRow.find(".compareTable-heading[data-productid='" + val + "']"); if (colHeader && colHeader.length) { // determine all cells to be hidden cells = this.table .find("tbody tr") // can't be in one find() because it would only find the first .find("td:eq(" + colHeader.index() + ")") // add in our header cell (and clone) .add(colHeader); if (this.rowClone) { cells = cells.add(this.rowClone.find(".compareTable-mainHeadings > *:eq(" + colHeader.index() + ")")); } // toggle the data cells (and headers) if (active) { cells.show(); } else { cells.hide(); } // set correct colspan on section headers... this.table .find(".expandableHeading") .prop("colspan", headerRow.find(".compareTable-heading:visible").length + 1); // ... and on the brand group header groupBrandCount = headerRow.find(".compareTable-heading[data-brandgroup='" + colHeader.data("brandgroup") + "']:visible").length; groupHeader = this.table.find(".compareTable-brandRow > *:contains('" + colHeader.data("brandgroup") + "')"); if (groupBrandCount) { groupHeader.prop("colspan", groupBrandCount).show(); } else { // none left in the group, hide it. groupHeader.hide(); } // see if we still need the column clone this.toggleColumnClone(); this.repositionHeaderClone(); this.resizeHeaderClone(); } }, setupTooltips: function() { self.table .on("click", ".compareTable-rowHeading .has-additionalInfoOverlay", function(e) { var $header = $(this).parent(); e.preventDefault(); e.stopPropagation(); // don't let the body handler get this! (it hides the tooltip) // remove overlay from any other header cell in this table $(e.delegateTarget) .find(".compareTable-rowHeading") .not($header) .removeClass("show-overlay sticky-overlay"); // toggle overlay class to this element if ($header.hasClass("sticky-overlay")) { $header.removeClass("show-overlay sticky-overlay"); } else { $header.addClass("show-overlay sticky-overlay"); } }) .on("mouseenter", ".compareTable-rowHeading .has-additionalInfoOverlay", function(e) { var $header = $(this).parent(); // don't show tooltips if a "sticky" one is showing if (!$(e.delegateTarget).find(".sticky-overlay").length) { $header.addClass("show-overlay"); } }) .on("mouseleave", ".compareTable-rowHeading .has-additionalInfoOverlay", function(e) { var $header = $(this).parent(); if (!$header.hasClass("sticky-overlay")) { $header.removeClass("show-overlay sticky-overlay"); } }); // pass events through from the cloned table to the original self.colClone .on("click mouseenter mouseleave", ".compareTable-rowHeading .has-additionalInfoOverlay", function(e) { self.passThroughClonedEvent(e); }); // remove overlay class when body is clicked anywhere else $("body").on("click", function() { self.table .find(".compareTable-rowHeading") .removeClass("show-overlay sticky-overlay"); }); }, passThroughClonedEvent: function(event) { // since we're passing events through to the original table, stop them here event.preventDefault(); event.stopPropagation(); this.table .find(".has-additionalInfoOverlay:contains(" + $(event.target).text() + ")") .trigger(event.type); }, setupResizeEvent: function() { // any time the window changes we need to determine if we need the clone(s) $(window).resize(function() { // throttle resize calls if (self.resizeTO) { clearTimeout(self.resizeTO); } // wait for elements to finish moving before seeing if we need the fixed headers self.resizeTO = setTimeout(function() { self.resizeTO = null; self.toggleColumnClone(); self.toggleHeaderClone(); self.repositionHeaderClone(); self.resizeHeaderClone(); }, 500); }); }, setupScrollEvent: function() { // any time the window scrolls we need to determine if we need the header clone $(window).on("scroll", function() { self.toggleHeaderClone(); }); }, setupSectionAccordion: function() { self.wrapper.on("click", ".expandableHeading", function(e) { e.preventDefault(); self.wrapper .find("." + $(this).data("section")) .toggle(); // we need to flip the cloned section header class so it shows the correct icon self.colClone .find("[data-section='" + $(this).data("section") + "']") .toggleClass("expandableHeading-is-expanded"); // showing and hiding these can affect the width of columns, // so we need to resize the cloned header row self.repositionHeaderClone(); self.resizeHeaderClone(); }); // close all sections by default (they are open in the raw html) self.table.find(".expandableHeading").click(); }, addFeatureImgFallback: function() { $(".compareTable-standard") .append("\"\""); $(".compareTable-select") .append("\"\""); } }; })(Modernizr); /* end: /ISS_Static/WW/site/scripts/owv2/compare-table.js(11349) */ /* start: /ISS_Static/WW/site/scripts/owv2/pressquotes.js (cachekey: [])*/ /** * BxSlider v4.1 - Fully loaded, responsive content slider */ ;(function($){ var plugin = {}; var defaults = { // GENERAL mode: 'horizontal', slideSelector: '', infiniteLoop: true, hideControlOnEnd: false, speed: 500, easing: null, slideMargin: 0, startSlide: 0, randomStart: false, captions: false, ticker: false, tickerHover: false, adaptiveHeight: false, adaptiveHeightSpeed: 500, video: false, useCSS: true, preloadImages: 'visible', // TOUCH touchEnabled: true, swipeThreshold: 50, oneToOneTouch: true, preventDefaultSwipeX: true, preventDefaultSwipeY: false, // PAGER pager: true, pagerType: 'full', pagerShortSeparator: ' / ', pagerSelector: null, buildPager: null, pagerCustom: null, // CONTROLS controls: true, nextText: 'Next', prevText: 'Prev', nextSelector: null, prevSelector: null, autoControls: false, startText: 'Start', stopText: 'Stop', autoControlsCombine: false, autoControlsSelector: null, // AUTO auto: false, pause: 4000, autoStart: true, autoDirection: 'next', autoHover: false, autoDelay: 0, // CAROUSEL minSlides: 1, maxSlides: 1, moveSlides: 0, slideWidth: 0, // CALLBACKS onSliderLoad: function() {}, onSlideBefore: function() {}, onSlideAfter: function() {}, onSlideNext: function() {}, onSlidePrev: function() {} } $.fn.bxSlider = function(options){ if(this.length == 0) return; // support mutltiple elements if(this.length > 1){ this.each(function(){$(this).bxSlider(options)}); return this; } // create a namespace to be used throughout the plugin var slider = {}; // set a reference to our slider element var el = this; plugin.el = this; /** * Makes slideshow responsive */ // first get the original window dimens (thanks alot IE) var windowWidth = $(window).width(); var windowHeight = $(window).height(); /** * =================================================================================== * = PRIVATE FUNCTIONS * =================================================================================== */ /** * Initializes namespace settings to be used throughout plugin */ var init = function(){ // merge user-supplied options with the defaults slider.settings = $.extend({}, defaults, options); // parse slideWidth setting slider.settings.slideWidth = parseInt(slider.settings.slideWidth); // store the original children slider.children = el.children(slider.settings.slideSelector); // check if actual number of slides is less than minSlides / maxSlides if(slider.children.length < slider.settings.minSlides) slider.settings.minSlides = slider.children.length; if(slider.children.length < slider.settings.maxSlides) slider.settings.maxSlides = slider.children.length; // if random start, set the startSlide setting to random number if(slider.settings.randomStart) slider.settings.startSlide = Math.floor(Math.random() * slider.children.length); // store active slide information slider.active = { index: slider.settings.startSlide } // store if the slider is in carousel mode (displaying / moving multiple slides) slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1; // if carousel, force preloadImages = 'all' if(slider.carousel) slider.settings.preloadImages = 'all'; // calculate the min / max width thresholds based on min / max number of slides // used to setup and update carousel slides dimensions slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin); slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); // store the current state of the slider (if currently animating, working is true) slider.working = false; // initialize the controls object slider.controls = {}; // initialize an auto interval slider.interval = null; // determine which property to use for transitions slider.animProp = slider.settings.mode == 'vertical' ? 'top' : 'left'; // determine if hardware acceleration can be used slider.usingCSS = slider.settings.useCSS && slider.settings.mode != 'fade' && (function(){ // create our test div element var div = document.createElement('div'); // css transition properties var props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']; // test for each property for(var i in props){ if(div.style[props[i]] !== undefined){ slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase(); slider.animProp = '-' + slider.cssPrefix + '-transform'; return true; } } return false; }()); // if vertical mode always make maxSlides and minSlides equal if(slider.settings.mode == 'vertical') slider.settings.maxSlides = slider.settings.minSlides; // perform all DOM / CSS modifications setup(); } /** * Performs all DOM and CSS modifications */ var setup = function(){ // wrap el in a wrapper el.wrap('
'); // store a namspace reference to .bx-viewport slider.viewport = el.parent(); // add a loading div to display while images are loading slider.loader = $('
'); slider.viewport.prepend(slider.loader); // set el to a massive width, to hold any needed slides // also strip any margin and padding from el el.css({ width: slider.settings.mode == 'horizontal' ? slider.children.length * 215 + '%' : 'auto', position: 'relative' }); // if using CSS, add the easing property if(slider.usingCSS && slider.settings.easing){ el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing); // if not using CSS and no easing value was supplied, use the default JS animation easing (swing) }else if(!slider.settings.easing){ slider.settings.easing = 'swing'; } var slidesShowing = getNumberSlidesShowing(); // make modifications to the viewport (.bx-viewport) slider.viewport.css({ width: '100%', overflow: 'hidden', position: 'relative' }); slider.viewport.parent().css({ maxWidth: getViewportMaxWidth() }); // apply css to all slider children slider.children.css({ 'float': slider.settings.mode == 'horizontal' ? 'left' : 'none', listStyle: 'none', position: 'relative' }); // apply the calculated width after the float is applied to prevent scrollbar interference slider.children.width(getSlideWidth()); // if slideMargin is supplied, add the css if(slider.settings.mode == 'horizontal' && slider.settings.slideMargin > 0) slider.children.css('marginRight', slider.settings.slideMargin); if(slider.settings.mode == 'vertical' && slider.settings.slideMargin > 0) slider.children.css('marginBottom', slider.settings.slideMargin); // if "fade" mode, add positioning and z-index CSS if(slider.settings.mode == 'fade'){ slider.children.css({ position: 'absolute', zIndex: 0, display: 'none' }); // prepare the z-index on the showing element slider.children.eq(slider.settings.startSlide).css({zIndex: 50, display: 'block'}); } // create an element to contain all slider controls (pager, start / stop, etc) slider.controls.el = $('
'); // if captions are requested, add them if(slider.settings.captions) appendCaptions(); // if infinite loop, prepare additional slides if(slider.settings.infiniteLoop && slider.settings.mode != 'fade' && !slider.settings.ticker){ var slice = slider.settings.mode == 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides; var sliceAppend = slider.children.slice(0, slice).clone().addClass('bx-clone'); var slicePrepend = slider.children.slice(-slice).clone().addClass('bx-clone'); el.append(sliceAppend).prepend(slicePrepend); } // check if startSlide is last slide slider.active.last = slider.settings.startSlide == getPagerQty() - 1; // if video is true, set up the fitVids plugin if(slider.settings.video) el.fitVids(); // set the default preload selector (visible) var preloadSelector = slider.children.eq(slider.settings.startSlide); if (slider.settings.preloadImages == "all") preloadSelector = el.children(); // only check for control addition if not in "ticker" mode if(!slider.settings.ticker){ // if pager is requested, add it if(slider.settings.pager) appendPager(); // if controls are requested, add them if(slider.settings.controls) appendControls(); // if auto is true, and auto controls are requested, add them if(slider.settings.auto && slider.settings.autoControls) appendControlsAuto(); // if any control option is requested, add the controls wrapper if(slider.settings.controls || slider.settings.autoControls || slider.settings.pager) slider.viewport.after(slider.controls.el); } // preload all images, then perform final DOM / CSS modifications that depend on images being loaded preloadSelector.imagesLoaded(start); } /** * Start the slider */ var start = function(){ // remove the loading DOM element slider.loader.remove(); // set the left / top position of "el" setSlidePosition(); // if "vertical" mode, always use adaptiveHeight to prevent odd behavior if (slider.settings.mode == 'vertical') slider.settings.adaptiveHeight = true; // set the viewport height slider.viewport.height(getViewportHeight()); // make sure everything is positioned just right (same as a window resize) el.redrawSlider(); // onSliderLoad callback slider.settings.onSliderLoad(slider.active.index); // slider has been fully initialized slider.initialized = true; // bind the resize call to the window $(window).bind('resize', resizeWindow); // if auto is true, start the show if (slider.settings.auto && slider.settings.autoStart) initAuto(); // if ticker is true, start the ticker if (slider.settings.ticker) initTicker(); // if pager is requested, make the appropriate pager link active if (slider.settings.pager) updatePagerActive(slider.settings.startSlide); // check for any updates to the controls (like hideControlOnEnd updates) if (slider.settings.controls) updateDirectionControls(); // if touchEnabled is true, setup the touch events if (slider.settings.touchEnabled && !slider.settings.ticker) initTouch(); } /** * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value */ var getViewportHeight = function(){ var height = 0; // first determine which children (slides) should be used in our height calculation var children = $(); // if mode is not "vertical" and adaptiveHeight is false, include all children if(slider.settings.mode != 'vertical' && !slider.settings.adaptiveHeight){ children = slider.children; }else{ // if not carousel, return the single active child if(!slider.carousel){ children = slider.children.eq(slider.active.index); // if carousel, return a slice of children }else{ // get the individual slide index var currentIndex = slider.settings.moveSlides == 1 ? slider.active.index : slider.active.index * getMoveBy(); // add the current slide to the children children = slider.children.eq(currentIndex); // cycle through the remaining "showing" slides for (i = 1; i <= slider.settings.maxSlides - 1; i++){ // if looped back to the start if(currentIndex + i >= slider.children.length){ children = children.add(slider.children.eq(i - 1)); }else{ children = children.add(slider.children.eq(currentIndex + i)); } } } } // if "vertical" mode, calculate the sum of the heights of the children if(slider.settings.mode == 'vertical'){ children.each(function(index) { height += $(this).outerHeight(); }); // add user-supplied margins if(slider.settings.slideMargin > 0){ height += slider.settings.slideMargin * (slider.settings.minSlides - 1); } // if not "vertical" mode, calculate the max height of the children }else{ height = Math.max.apply(Math, children.map(function(){ return $(this).outerHeight(false); }).get()); } return height; } /** * Returns the calculated width to be used for the outer wrapper / viewport */ var getViewportMaxWidth = function(){ var width = '100%'; if(slider.settings.slideWidth > 0){ if(slider.settings.mode == 'horizontal'){ width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); }else{ width = slider.settings.slideWidth; } } return width; } /** * Returns the calculated width to be applied to each slide */ var getSlideWidth = function(){ // start with any user-supplied slide width var newElWidth = slider.settings.slideWidth; // get the current viewport width var wrapWidth = slider.viewport.width(); // if slide width was not supplied, or is larger than the viewport use the viewport width if(slider.settings.slideWidth == 0 || (slider.settings.slideWidth > wrapWidth && !slider.carousel) || slider.settings.mode == 'vertical'){ newElWidth = wrapWidth; // if carousel, use the thresholds to determine the width }else if(slider.settings.maxSlides > 1 && slider.settings.mode == 'horizontal'){ if(wrapWidth > slider.maxThreshold){ // newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides; }else if(wrapWidth < slider.minThreshold){ newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides; } } return newElWidth; } /** * Returns the number of slides currently visible in the viewport (includes partially visible slides) */ var getNumberSlidesShowing = function(){ var slidesShowing = 1; if(slider.settings.mode == 'horizontal' && slider.settings.slideWidth > 0){ // if viewport is smaller than minThreshold, return minSlides if(slider.viewport.width() < slider.minThreshold){ slidesShowing = slider.settings.minSlides; // if viewport is larger than minThreshold, return maxSlides }else if(slider.viewport.width() > slider.maxThreshold){ slidesShowing = slider.settings.maxSlides; // if viewport is between min / max thresholds, divide viewport width by first child width }else{ var childWidth = slider.children.first().width(); slidesShowing = Math.floor(slider.viewport.width() / childWidth); } // if "vertical" mode, slides showing will always be minSlides }else if(slider.settings.mode == 'vertical'){ slidesShowing = slider.settings.minSlides; } return slidesShowing; } /** * Returns the number of pages (one full viewport of slides is one "page") */ var getPagerQty = function(){ var pagerQty = 0; // if moveSlides is specified by the user if(slider.settings.moveSlides > 0){ if(slider.settings.infiniteLoop){ pagerQty = slider.children.length / getMoveBy(); }else{ // use a while loop to determine pages var breakPoint = 0; var counter = 0 // when breakpoint goes above children length, counter is the number of pages while (breakPoint < slider.children.length){ ++pagerQty; breakPoint = counter + getNumberSlidesShowing(); counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing(); } } // if moveSlides is 0 (auto) divide children length by sides showing, then round up }else{ pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing()); } return pagerQty; } /** * Returns the number of indivual slides by which to shift the slider */ var getMoveBy = function(){ // if moveSlides was set by the user and moveSlides is less than number of slides showing if(slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()){ return slider.settings.moveSlides; } // if moveSlides is 0 (auto) return getNumberSlidesShowing(); } /** * Sets the slider's (el) left or top position */ var setSlidePosition = function(){ // if last slide, not infinite loop, and number of children is larger than specified maxSlides if(slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop){ if (slider.settings.mode == 'horizontal'){ // get the last child's position var lastChild = slider.children.last(); var position = lastChild.position(); // set the left position setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.width())), 'reset', 0); }else if(slider.settings.mode == 'vertical'){ // get the last showing index's position var lastShowingIndex = slider.children.length - slider.settings.minSlides; var position = slider.children.eq(lastShowingIndex).position(); // set the top position setPositionProperty(-position.top, 'reset', 0); } // if not last slide }else{ // get the position of the first showing slide var position = slider.children.eq(slider.active.index * getMoveBy()).position(); // check for last slide if (slider.active.index == getPagerQty() - 1) slider.active.last = true; // set the repective position if (position != undefined){ if (slider.settings.mode == 'horizontal') setPositionProperty(-position.left, 'reset', 0); else if (slider.settings.mode == 'vertical') setPositionProperty(-position.top, 'reset', 0); } } } /** * Sets the el's animating property position (which in turn will sometimes animate el). * If using CSS, sets the transform property. If not using CSS, sets the top / left property. * * @param value (int) * - the animating property's value * * @param type (string) 'slider', 'reset', 'ticker' * - the type of instance for which the function is being * * @param duration (int) * - the amount of time (in ms) the transition should occupy * * @param params (array) optional * - an optional parameter containing any variables that need to be passed in */ var setPositionProperty = function(value, type, duration, params){ // use CSS transform if(slider.usingCSS){ // determine the translate3d value var propValue = slider.settings.mode == 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)'; // add the CSS transition-duration el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's'); if(type == 'slide'){ // set the property value el.css(slider.animProp, propValue); // bind a callback method - executes when CSS transition completes el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){ // unbind the callback el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); updateAfterSlideTransition(); }); }else if(type == 'reset'){ el.css(slider.animProp, propValue); }else if(type == 'ticker'){ // make the transition use 'linear' el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear'); el.css(slider.animProp, propValue); // bind a callback method - executes when CSS transition completes el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){ // unbind the callback el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); // reset the position setPositionProperty(params['resetValue'], 'reset', 0); // start the loop again tickerLoop(); }); } // use JS animate }else{ var animateObj = {}; animateObj[slider.animProp] = value; if(type == 'slide'){ el.animate(animateObj, duration, slider.settings.easing, function(){ updateAfterSlideTransition(); }); }else if(type == 'reset'){ el.css(slider.animProp, value) }else if(type == 'ticker'){ el.animate(animateObj, speed, 'linear', function(){ setPositionProperty(params['resetValue'], 'reset', 0); // run the recursive loop after animation tickerLoop(); }); } } } /** * Populates the pager with proper amount of pages */ var populatePager = function(){ var pagerHtml = ''; pagerQty = getPagerQty(); // loop through each pager item for(var i=0; i < pagerQty; i++){ var linkContent = ''; // if a buildPager function is supplied, use it to get pager link value, else use index + 1 if(slider.settings.buildPager && $.isFunction(slider.settings.buildPager)){ linkContent = slider.settings.buildPager(i); slider.pagerEl.addClass('bx-custom-pager'); }else{ linkContent = i + 1; slider.pagerEl.addClass('bx-default-pager'); } // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1; // add the markup to the string pagerHtml += ''; }; // populate the pager element with pager links slider.pagerEl.html(pagerHtml); } /** * Appends the pager to the controls element */ var appendPager = function(){ if(!slider.settings.pagerCustom){ // create the pager DOM element slider.pagerEl = $('
'); // if a pager selector was supplied, populate it with the pager if(slider.settings.pagerSelector){ $(slider.settings.pagerSelector).html(slider.pagerEl); // if no pager selector was supplied, add it after the wrapper }else{ slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl); } // populate the pager populatePager(); }else{ slider.pagerEl = $(slider.settings.pagerCustom); } // assign the pager click binding slider.pagerEl.delegate('a', 'click', clickPagerBind); } /** * Appends prev / next controls to the controls element */ var appendControls = function(){ slider.controls.next = $('' + slider.settings.nextText + ''); slider.controls.prev = $('' + slider.settings.prevText + ''); // bind click actions to the controls slider.controls.next.bind('click', clickNextBind); slider.controls.prev.bind('click', clickPrevBind); // if nextSlector was supplied, populate it if(slider.settings.nextSelector){ $(slider.settings.nextSelector).append(slider.controls.next); } // if prevSlector was supplied, populate it if(slider.settings.prevSelector){ $(slider.settings.prevSelector).append(slider.controls.prev); } // if no custom selectors were supplied if(!slider.settings.nextSelector && !slider.settings.prevSelector){ // add the controls to the DOM slider.controls.directionEl = $('
'); // add the control elements to the directionEl slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next); // slider.viewport.append(slider.controls.directionEl); slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl); } } /** * Appends start / stop auto controls to the controls element */ var appendControlsAuto = function(){ slider.controls.start = $(''); slider.controls.stop = $(''); // add the controls to the DOM slider.controls.autoEl = $('
'); // bind click actions to the controls slider.controls.autoEl.delegate('.bx-start', 'click', clickStartBind); slider.controls.autoEl.delegate('.bx-stop', 'click', clickStopBind); // if autoControlsCombine, insert only the "start" control if(slider.settings.autoControlsCombine){ slider.controls.autoEl.append(slider.controls.start); // if autoControlsCombine is false, insert both controls }else{ slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop); } // if auto controls selector was supplied, populate it with the controls if(slider.settings.autoControlsSelector){ $(slider.settings.autoControlsSelector).html(slider.controls.autoEl); // if auto controls selector was not supplied, add it after the wrapper }else{ slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl); } // update the auto controls updateAutoControls(slider.settings.autoStart ? 'stop' : 'start'); } /** * Appends image captions to the DOM */ var appendCaptions = function(){ // cycle through each child slider.children.each(function(index){ // get the image title attribute var title = $(this).find('img:first').attr('title'); // append the caption if (title != undefined) $(this).append('
' + title + '
'); }); } /** * Click next binding * * @param e (event) * - DOM event object */ var clickNextBind = function(e){ // if auto show is running, stop it if (slider.settings.auto) el.stopAuto(); el.goToNextSlide(); e.preventDefault(); } /** * Click prev binding * * @param e (event) * - DOM event object */ var clickPrevBind = function(e){ // if auto show is running, stop it if (slider.settings.auto) el.stopAuto(); el.goToPrevSlide(); e.preventDefault(); } /** * Click start binding * * @param e (event) * - DOM event object */ var clickStartBind = function(e){ el.startAuto(); e.preventDefault(); } /** * Click stop binding * * @param e (event) * - DOM event object */ var clickStopBind = function(e){ el.stopAuto(); e.preventDefault(); } /** * Click pager binding * * @param e (event) * - DOM event object */ var clickPagerBind = function(e){ // if auto show is running, stop it if (slider.settings.auto) el.stopAuto(); var pagerLink = $(e.currentTarget); var pagerIndex = parseInt(pagerLink.attr('data-slide-index')); // if clicked pager link is not active, continue with the goToSlide call if(pagerIndex != slider.active.index) el.goToSlide(pagerIndex); e.preventDefault(); } /** * Updates the pager links with an active class * * @param slideIndex (int) * - index of slide to make active */ var updatePagerActive = function(slideIndex){ // if "short" pager type if(slider.settings.pagerType == 'short'){ slider.pagerEl.html((slideIndex + 1) + slider.settings.pagerShortSeparator + slider.children.length); return; } // remove all pager active classes slider.pagerEl.find('a').removeClass('active'); // apply the active class for all pagers slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); }); } /** * Performs needed actions after a slide transition */ var updateAfterSlideTransition = function(){ // if infinte loop is true if(slider.settings.infiniteLoop){ var position = ''; // first slide if(slider.active.index == 0){ // set the new position position = slider.children.eq(0).position(); // carousel, last slide }else if(slider.active.index == getPagerQty() - 1 && slider.carousel){ position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position(); // last slide }else if(slider.active.index == slider.children.length - 1){ position = slider.children.eq(slider.children.length - 1).position(); } if (slider.settings.mode == 'horizontal') { setPositionProperty(-position.left, 'reset', 0);; } else if (slider.settings.mode == 'vertical') { setPositionProperty(-position.top, 'reset', 0);; } } // declare that the transition is complete slider.working = false; // onSlideAfter callback slider.settings.onSlideAfter(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); } /** * Updates the auto controls state (either active, or combined switch) * * @param state (string) "start", "stop" * - the new state of the auto show */ var updateAutoControls = function(state){ // if autoControlsCombine is true, replace the current control with the new state if(slider.settings.autoControlsCombine){ slider.controls.autoEl.html(slider.controls[state]); // if autoControlsCombine is false, apply the "active" class to the appropriate control }else{ slider.controls.autoEl.find('a').removeClass('active'); slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active'); } } /** * Updates the direction controls (checks if either should be hidden) */ var updateDirectionControls = function(){ // if infiniteLoop is false and hideControlOnEnd is true if(!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd){ // if first slide if (slider.active.index == 0){ slider.controls.prev.addClass('disabled'); slider.controls.next.removeClass('disabled'); // if last slide }else if(slider.active.index == getPagerQty() - 1){ slider.controls.next.addClass('disabled'); slider.controls.prev.removeClass('disabled'); // if any slide in the middle }else{ slider.controls.prev.removeClass('disabled'); slider.controls.next.removeClass('disabled'); } // if slider has only one page, disable controls }else if(getPagerQty() == 1){ slider.controls.prev.addClass('disabled'); slider.controls.next.addClass('disabled'); } } /** * Initialzes the auto process */ var initAuto = function(){ // if autoDelay was supplied, launch the auto show using a setTimeout() call if(slider.settings.autoDelay > 0){ var timeout = setTimeout(el.startAuto, slider.settings.autoDelay); // if autoDelay was not supplied, start the auto show normally }else{ el.startAuto(); } // if autoHover is requested if(slider.settings.autoHover){ // on el hover el.hover(function(){ // if the auto show is currently playing (has an active interval) if(slider.interval){ // stop the auto show and pass true agument which will prevent control update el.stopAuto(true); // create a new autoPaused value which will be used by the relative "mouseout" event slider.autoPaused = true; } }, function(){ // if the autoPaused value was created be the prior "mouseover" event if(slider.autoPaused){ // start the auto show and pass true agument which will prevent control update el.startAuto(true); // reset the autoPaused value slider.autoPaused = null; } }); } } /** * Initialzes the ticker process */ var initTicker = function(){ var startPosition = 0; // if autoDirection is "next", append a clone of the entire slider if(slider.settings.autoDirection == 'next'){ el.append(slider.children.clone().addClass('bx-clone')); // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position }else{ el.prepend(slider.children.clone().addClass('bx-clone')); var position = slider.children.first().position(); startPosition = slider.settings.mode == 'horizontal' ? -position.left : -position.top; } setPositionProperty(startPosition, 'reset', 0); // do not allow controls in ticker mode slider.settings.pager = false; slider.settings.controls = false; slider.settings.autoControls = false; // if autoHover is requested if(slider.settings.tickerHover && !slider.usingCSS){ // on el hover slider.viewport.hover(function(){ el.stop(); }, function(){ // calculate the total width of children (used to calculate the speed ratio) var totalDimens = 0; slider.children.each(function(index){ totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); }); // calculate the speed ratio (used to determine the new speed to finish the paused animation) var ratio = slider.settings.speed / totalDimens; // determine which property to use var property = slider.settings.mode == 'horizontal' ? 'left' : 'top'; // calculate the new speed var newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property))))); tickerLoop(newSpeed); }); } // start the ticker loop tickerLoop(); } /** * Runs a continuous loop, news ticker-style */ var tickerLoop = function(resumeSpeed){ speed = resumeSpeed ? resumeSpeed : slider.settings.speed; var position = {left: 0, top: 0}; var reset = {left: 0, top: 0}; // if "next" animate left position to last child, then reset left to 0 if(slider.settings.autoDirection == 'next'){ position = el.find('.bx-clone').first().position(); // if "prev" animate left position to 0, then reset left to first non-clone child }else{ reset = slider.children.first().position(); } var animateProperty = slider.settings.mode == 'horizontal' ? -position.left : -position.top; var resetValue = slider.settings.mode == 'horizontal' ? -reset.left : -reset.top; var params = {resetValue: resetValue}; setPositionProperty(animateProperty, 'ticker', speed, params); } /** * Initializes touch events */ var initTouch = function(){ // initialize object to contain all touch values slider.touch = { start: {x: 0, y: 0}, end: {x: 0, y: 0} } slider.viewport.bind('touchstart', onTouchStart); } /** * Event handler for "touchstart" * * @param e (event) * - DOM event object */ var onTouchStart = function(e){ if(slider.working){ e.preventDefault(); }else{ // record the original position when touch starts slider.touch.originalPos = el.position(); var orig = e.originalEvent; // record the starting touch x, y coordinates slider.touch.start.x = orig.changedTouches[0].pageX; slider.touch.start.y = orig.changedTouches[0].pageY; // bind a "touchmove" event to the viewport slider.viewport.bind('touchmove', onTouchMove); // bind a "touchend" event to the viewport slider.viewport.bind('touchend', onTouchEnd); } } /** * Event handler for "touchmove" * * @param e (event) * - DOM event object */ var onTouchMove = function(e){ var orig = e.originalEvent; // if scrolling on y axis, do not prevent default var xMovement = Math.abs(orig.changedTouches[0].pageX - slider.touch.start.x); var yMovement = Math.abs(orig.changedTouches[0].pageY - slider.touch.start.y); // x axis swipe if((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX){ e.preventDefault(); // y axis swipe }else if((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY){ e.preventDefault(); } if(slider.settings.mode != 'fade' && slider.settings.oneToOneTouch){ var value = 0; // if horizontal, drag along x axis if(slider.settings.mode == 'horizontal'){ var change = orig.changedTouches[0].pageX - slider.touch.start.x; value = slider.touch.originalPos.left + change; // if vertical, drag along y axis }else{ var change = orig.changedTouches[0].pageY - slider.touch.start.y; value = slider.touch.originalPos.top + change; } setPositionProperty(value, 'reset', 0); } } /** * Event handler for "touchend" * * @param e (event) * - DOM event object */ var onTouchEnd = function(e){ slider.viewport.unbind('touchmove', onTouchMove); var orig = e.originalEvent; var value = 0; // record end x, y positions slider.touch.end.x = orig.changedTouches[0].pageX; slider.touch.end.y = orig.changedTouches[0].pageY; // if fade mode, check if absolute x distance clears the threshold if(slider.settings.mode == 'fade'){ var distance = Math.abs(slider.touch.start.x - slider.touch.end.x); if(distance >= slider.settings.swipeThreshold){ slider.touch.start.x > slider.touch.end.x ? el.goToNextSlide() : el.goToPrevSlide(); el.stopAuto(); } // not fade mode }else{ var distance = 0; // calculate distance and el's animate property if(slider.settings.mode == 'horizontal'){ distance = slider.touch.end.x - slider.touch.start.x; value = slider.touch.originalPos.left; }else{ distance = slider.touch.end.y - slider.touch.start.y; value = slider.touch.originalPos.top; } // if not infinite loop and first / last slide, do not attempt a slide transition if(!slider.settings.infiniteLoop && ((slider.active.index == 0 && distance > 0) || (slider.active.last && distance < 0))){ setPositionProperty(value, 'reset', 200); }else{ // check if distance clears threshold if(Math.abs(distance) >= slider.settings.swipeThreshold){ distance < 0 ? el.goToNextSlide() : el.goToPrevSlide(); el.stopAuto(); }else{ // el.animate(property, 200); setPositionProperty(value, 'reset', 200); } } } slider.viewport.unbind('touchend', onTouchEnd); } /** * Window resize event callback */ var resizeWindow = function(e){ // get the new window dimens (again, thank you IE) var windowWidthNew = $(window).width(); var windowHeightNew = $(window).height(); // make sure that it is a true window resize // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements // are resized. Can you just die already?* if(windowWidth != windowWidthNew || windowHeight != windowHeightNew){ // set the new window dimens windowWidth = windowWidthNew; windowHeight = windowHeightNew; // update all dynamic elements el.redrawSlider(); } } /** * =================================================================================== * = PUBLIC FUNCTIONS * =================================================================================== */ /** * Performs slide transition to the specified slide * * @param slideIndex (int) * - the destination slide's index (zero-based) * * @param direction (string) * - INTERNAL USE ONLY - the direction of travel ("prev" / "next") */ el.goToSlide = function(slideIndex, direction){ // if plugin is currently in motion, ignore request if(slider.working || slider.active.index == slideIndex) return; // declare that plugin is in motion slider.working = true; // store the old index slider.oldIndex = slider.active.index; // if slideIndex is less than zero, set active index to last child (this happens during infinite loop) if(slideIndex < 0){ slider.active.index = getPagerQty() - 1; // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop) }else if(slideIndex >= getPagerQty()){ slider.active.index = 0; // set active index to requested slide }else{ slider.active.index = slideIndex; } // onSlideBefore, onSlideNext, onSlidePrev callbacks slider.settings.onSlideBefore(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); if(direction == 'next'){ slider.settings.onSlideNext(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); }else if(direction == 'prev'){ slider.settings.onSlidePrev(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); } // check if last slide slider.active.last = slider.active.index >= getPagerQty() - 1; // update the pager with active class if(slider.settings.pager) updatePagerActive(slider.active.index); // // check for direction control update if(slider.settings.controls) updateDirectionControls(); // if slider is set to mode: "fade" if(slider.settings.mode == 'fade'){ // if adaptiveHeight is true and next height is different from current height, animate to the new height if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){ slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); } // fade out the visible child and reset its z-index value slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0}); // fade in the newly requested slide slider.children.eq(slider.active.index).css('zIndex', 51).fadeIn(slider.settings.speed, function(){ $(this).css('zIndex', 50); updateAfterSlideTransition(); }); // slider mode is not "fade" }else{ // if adaptiveHeight is true and next height is different from current height, animate to the new height if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){ slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); } var moveBy = 0; var position = {left: 0, top: 0}; // if carousel and not infinite loop if(!slider.settings.infiniteLoop && slider.carousel && slider.active.last){ if(slider.settings.mode == 'horizontal'){ // get the last child position var lastChild = slider.children.eq(slider.children.length - 1); position = lastChild.position(); // calculate the position of the last slide moveBy = slider.viewport.width() - lastChild.width(); }else{ // get last showing index position var lastShowingIndex = slider.children.length - slider.settings.minSlides; position = slider.children.eq(lastShowingIndex).position(); } // horizontal carousel, going previous while on first slide (infiniteLoop mode) }else if(slider.carousel && slider.active.last && direction == 'prev'){ // get the last child position var eq = slider.settings.moveSlides == 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides); var lastChild = el.children('.bx-clone').eq(eq); position = lastChild.position(); // if infinite loop and "Next" is clicked on the last slide }else if(direction == 'next' && slider.active.index == 0){ // get the last clone position position = el.find('.bx-clone').eq(slider.settings.maxSlides).position(); slider.active.last = false; // normal non-zero requests }else if(slideIndex >= 0){ var requestEl = slideIndex * getMoveBy(); position = slider.children.eq(requestEl).position(); } // plugin values to be animated var value = slider.settings.mode == 'horizontal' ? -(position.left - moveBy) : -position.top; setPositionProperty(value, 'slide', slider.settings.speed); } } /** * Transitions to the next slide in the show */ el.goToNextSlide = function(){ // if infiniteLoop is false and last page is showing, disregard call if (!slider.settings.infiniteLoop && slider.active.last) return; var pagerIndex = parseInt(slider.active.index) + 1; el.goToSlide(pagerIndex, 'next'); } /** * Transitions to the prev slide in the show */ el.goToPrevSlide = function(){ // if infiniteLoop is false and last page is showing, disregard call if (!slider.settings.infiniteLoop && slider.active.index == 0) return; var pagerIndex = parseInt(slider.active.index) - 1; el.goToSlide(pagerIndex, 'prev'); } /** * Starts the auto show * * @param preventControlUpdate (boolean) * - if true, auto controls state will not be updated */ el.startAuto = function(preventControlUpdate){ // if an interval already exists, disregard call if(slider.interval) return; // create an interval slider.interval = setInterval(function(){ slider.settings.autoDirection == 'next' ? el.goToNextSlide() : el.goToPrevSlide(); }, slider.settings.pause); // if auto controls are displayed and preventControlUpdate is not true if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('stop'); } /** * Stops the auto show * * @param preventControlUpdate (boolean) * - if true, auto controls state will not be updated */ el.stopAuto = function(preventControlUpdate){ // if no interval exists, disregard call if(!slider.interval) return; // clear the interval clearInterval(slider.interval); slider.interval = null; // if auto controls are displayed and preventControlUpdate is not true if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('start'); } /** * Returns current slide index (zero-based) */ el.getCurrentSlide = function(){ return slider.active.index; } /** * Returns number of slides in show */ el.getSlideCount = function(){ return slider.children.length; } /** * Update all dynamic slider elements */ el.redrawSlider = function(){ // resize all children in ratio to new screen size slider.children.add(el.find('.bx-clone')).width(getSlideWidth()); // adjust the height slider.viewport.css('height', getViewportHeight()); // update the slide position if(!slider.settings.ticker) setSlidePosition(); // if active.last was true before the screen resize, we want // to keep it last no matter what screen size we end on if (slider.active.last) slider.active.index = getPagerQty() - 1; // if the active index (page) no longer exists due to the resize, simply set the index as last if (slider.active.index >= getPagerQty()) slider.active.last = true; // if a pager is being displayed and a custom pager is not being used, update it if(slider.settings.pager && !slider.settings.pagerCustom){ populatePager(); updatePagerActive(slider.active.index); } } /** * Destroy the current instance of the slider (revert everything back to original state) */ el.destroySlider = function(){ // don't do anything if slider has already been destroyed if(!slider.initialized) return; slider.initialized = false; $('.bx-clone', this).remove(); slider.children.removeAttr('style'); this.removeAttr('style').unwrap().unwrap(); if(slider.controls.el) slider.controls.el.remove(); if(slider.controls.next) slider.controls.next.remove(); if(slider.controls.prev) slider.controls.prev.remove(); if(slider.pagerEl) slider.pagerEl.remove(); $('.bx-caption', this).remove(); if(slider.controls.autoEl) slider.controls.autoEl.remove(); clearInterval(slider.interval); $(window).unbind('resize', resizeWindow); } /** * Reload the slider (revert all DOM changes, and re-initialize) */ el.reloadSlider = function(settings){ if (settings != undefined) options = settings; el.destroySlider(); init(); } init(); // returns the current jQuery object return this; } })(jQuery); /*! * jQuery imagesLoaded plugin v2.1.0 * http://github.com/desandro/imagesloaded * * MIT License. by Paul Irish et al. */ /*jshint curly: true, eqeqeq: true, noempty: true, strict: true, undef: true, browser: true */ /*global jQuery: false */ (function(c,n){var l="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";c.fn.imagesLoaded=function(f){function m(){var b=c(i),a=c(h);d&&(h.length?d.reject(e,b,a):d.resolve(e));c.isFunction(f)&&f.call(g,e,b,a)}function j(b,a){b.src===l||-1!==c.inArray(b,k)||(k.push(b),a?h.push(b):i.push(b),c.data(b,"imagesLoaded",{isBroken:a,src:b.src}),o&&d.notifyWith(c(b),[a,e,c(i),c(h)]),e.length===k.length&&(setTimeout(m),e.unbind(".imagesLoaded")))}var g=this,d=c.isFunction(c.Deferred)?c.Deferred(): 0,o=c.isFunction(d.notify),e=g.find("img").add(g.filter("img")),k=[],i=[],h=[];c.isPlainObject(f)&&c.each(f,function(b,a){if("callback"===b)f=a;else if(d)d[b](a)});e.length?e.bind("load.imagesLoaded error.imagesLoaded",function(b){j(b.target,"error"===b.type)}).each(function(b,a){var d=a.src,e=c.data(a,"imagesLoaded");if(e&&e.src===d)j(a,e.isBroken);else if(a.complete&&a.naturalWidth!==n)j(a,0===a.naturalWidth||0===a.naturalHeight);else if(a.readyState||a.complete)a.src=l,a.src=d}):m();return d?d.promise(g): g}})(jQuery); /* end: /ISS_Static/WW/site/scripts/owv2/pressquotes.js(48962) */ /* start: /ISS_Static/WW/site/scripts/owv2/legal-footer.js (cachekey: [])*/ $(function() { if ($ && $.fancybox) { $(".acc-prom").fancybox({ 'width' : '75%', 'height' : '75%', 'autoScale' : false, 'transitionIn' : 'none', 'transitionOut' : 'none', 'type' : 'iframe' }); } if ($ && $.fancybox) { $(".lightbox").fancybox({ 'width' : '75%', 'height' : '35%', 'autoScale' : false, 'transitionIn' : 'none', 'transitionOut' : 'none', 'type' : 'iframe' }); } if ($ && $.fancybox) { $(".optionOffers").fancybox({ 'width' : '75%', 'height' : '75%', 'autoScale' : false, 'transitionIn' : 'none', 'transitionOut' : 'none', 'type' : 'iframe' }); } if ($ && $.fancybox) { $("#GSI_pop-up").fancybox({ 'width' : '75%', 'height' : '75%', 'autoScale' : false, 'transitionIn' : 'none', 'transitionOut' : 'none', 'type' : 'iframe' }); } }); /* end: /ISS_Static/WW/site/scripts/owv2/legal-footer.js(934) */ /* start: /ISS_Static/WW/site/scripts/owv2/sidebar-navigator.js (cachekey: [])*/ $(function(){ /*---Detect Page Type and Expand/Collapse Side Bar Nav Section on Page Load---*/ var metaPageType = $('meta[name]').filter(function() { return $(this).attr('name').toLowerCase() == "taxonomytype" }).attr('content'); //Prevent event bubbling on title arrow $(".sidebarNav .greyArrow-link").click(function(e) { e.stopPropagation(); }); var isSystemx = $(".sidebarNav").attr("data-type"); if(isSystemx == 'nonsystemx' || typeof isSystemx == 'undefined'){ var currentURL = window.location.pathname; if(metaPageType != "SplitterPage"){ $(".brandLink a").each(function(){ var brandLink = $(this).attr("href"); var indexOfLink = currentURL.indexOf(brandLink); if(indexOfLink < 0){ $(this).parent(".expandableHeading").removeClass("expandableHeading-is-expanded"); $(this).parent(".expandableHeading").next(".expandableContent").addClass("expandableContent-is-collapsed").hide(); } }); } /*---Remove Series Title if no Subseries---*/ $("ul.subSeries").each(function(){ var lenOfSubSeries = $(this).find("li").length; if(lenOfSubSeries == 0){$(this).parent(".series").parent().remove();} }); /*---Remove Brand Title if no Series---*/ $(".sidebarNav-section .series").each(function(){ var lenOfSeries = $(this).find(".seriesLink").length; if(lenOfSeries == 0){$(this).prev(".brandLink").addClass("no-series");} if(lenOfSeries == 0){$(this).hide();} }); } }); /* end: /ISS_Static/WW/site/scripts/owv2/sidebar-navigator.js(1411) */ /* start: /ISS_Static/WW/site/scripts/owv2/media.js (cachekey: [])*/ /* * LENOVO.MEDIA module * -------------------------- * Dependencies: jQuery, LENOVO.MAIN, LENOVO.UTILS, LENOVO.TEMPLATES, LENOVO.MODAL */ ;(function(app, $, undefined) { var _M = "MEDIA"; var _version = "2014-06-27"; var _baseurl = window.long_url || ""; var _debug = window.debugAllowed || false; var _verbose = false; var _initialized = false; var $window = $(window); var $document = $(document); var $body = null; var _urlParams = null; var _domain = document.domain; var _protocol = window.location.protocol; var _hostname = window.location.hostname; var _pathname = window.location.pathname; //encodeURIComponent helper var __e = function(string) { return encodeURIComponent(string); }; //ratio/proportion calculator helper var __r = function(w, h, n, d) { var value = null; if (typeof n === "number" && typeof d === "number") { var scalar = (n / (d > 0 ? d : 1)); if (typeof w !== "undefined") { //solve for width value = Math.round(w / scalar); } else if (typeof h !== "undefined") { //solve for height value = Math.round(h * scalar); } } return value; }; var self = app[_M.toUpperCase()] = { shouldRun: function() { //only run automatically if UTILS and MODAL are loaded return app.hasOwnProperty("UTILS") && app.hasOwnProperty("MODAL"); }, init: function(options) { if (!_initialized) { //output status in console on dev domains if (_debug) { console.info("LENOVO.MEDIA: init"); } //prevent multiple init calls _initialized = true; //set $body reference (just in case) $body = $("body"); //check for forced debug/verbose/defaults settings _debug = app.UTILS.isDebug(); //triggers automatically on *.leni2.com domain, or can trigger in production with &debug=true param _verbose = app.UTILS.isVerbose(); //need to add &verbose=true (_debug must be true as well; can set &debug=verbose to set both to true) //store urlParams to private var for later access _urlParams = $.extend(true, {}, app.UTILS.urlParams); //open video in modal only if Brightcove video ID in the URL if ("bctid" in urlParams) { //pass video ID into videoModal method self.videoModal(urlParams.bctid); } } }, videoModal: function(videoId) { //output status to console if verbose mode if (_verbose == true) { console.info("LENOVO.MEDIA: videoModal(" + urlParams.bctid + ")"); } //start building iframe url var iframeUrl = "http://www.lenovo.com/media/videos/watch/?autoStart=true"; iframeUrl += ("&bctid=" + videoId); iframeUrl += ("&linkBaseHost=" + __e(_domain)); iframeUrl += ("&linkBaseURL=" + __e(_protocol + "//" + _hostname + _pathname)); //get viewport dimensions var winW = $window.width(); var winH = $window.height(); //iframe dimenstions should be ~86% of window (margin/padding, etc) var iW = winW * 0.86; var iH = winH * 0.86; //set iframe+video sizes based on current viewport //keep 16:9 ratio; maxheight=360px, maxwidth=640px if (iW > 640) { iW = 640; if (iH > 360) { iH = 360; } else { iW = __r(undefined, iH, 16, 9); } } else { iH = __r(iW, undefined, 16, 9); } iframeUrl += ("&width=" + iW + "&height=" + iH); //call openModal method via app.MODAL if ("openModal" in app.MODAL) app.MODAL.openModal(iframeUrl, { contentType: "iframe", //force iframe content modalType: "overlay" //force overlay method }); $body.find(".lnvmodal .lnvmodal-content").addClass("lnvmodal-video") .find("iframe").width(iW).height(iH); } }; })(window.LENOVO = window.LENOVO || {}, jQuery); /* end: /ISS_Static/WW/site/scripts/owv2/media.js(3938) */ /* start: /ISS_Static/WW/site/scripts/owv3/colorSelector.js (cachekey: [])*/ /* * LENOVO.COLORSELECTOR module * -------------------------- * Dependencies: jQuery, LENOVO.MAIN, LENOVO.ENV, LENOVO.UTILS, LENOVO.TEMPLATES, LENOVO.SHOWDIFFERENCES */ (function (app, $) { "use strict" var _M = "COLORSELECTOR"; var _version = "2016-10-17"; var _baseurl = window.long_url || ""; var _debug = window.debugAllowed || false; var _verbose = false; var _usedefaults = false; var _initialized = false; var _urls = null; var _soldOutImg; var productInfo = {}; var groupedListings = null; var DEFAULTS = { diffCriteria: 'dl:not(.pricingSummary-details)', diffHilightColor: '#D9EEF7', groupCriteria: 'dl', keepOriginal: false, // keep the original set for debugging purposes modelDifferencesText: 'Model Differences', productListings: '.tabbedBrowse-productListings', // column wrapper productListingBody: '.tabbedBrowse-productListing-body', // element to append the new swatches productListingCTABottom: '.tabbedBrowse-productListing-footer > .tabbedBrowse-productListing-button-container:last-child', // lower CTA productListingCTAMobile: '.tabbedBrowse-productListing-body > .tabbedBrowse-productListing-button-container-mobile', // mobile CTA productListingCTATop: '.tabbedBrowse-productListing-footer > .tabbedBrowse-productListing-button-container:first-child', // upper CTA (with Add to Wishlist + Compare) productListingHeader: '.tabbedBrowse-productListing-header', // product column productListingItem: '.tabbedBrowse-productListings > li', // product column productListingPartNumber: '.tabbedBrowse-productListing-body .partnumber > span', // part number productListingPreselection: '.tabbedBrowse-productListing-presel', // preselection container productListingScroller: '.tabbedBrowse-productListings-scroller', // column wrapper parent productListingTitle: '.tabbedBrowse-productListing-title', // product title soldOut: '.sostamp', soldOutImg: '.soiimage img', templateSources: ['/ISS_Static/WW/site/templates/handlebars/owv3/colorSelector.html'], templates: { ctas: 'colorSelector_ctas', pns: 'colorSelector_partnums', presel: 'colorSelector_presels', swatches: 'colorSelector_swatches', thumbnails: 'colorSelector_thumbnails' } }; var self = app[_M] = { shouldRun: function () { var colorSelector = window.colorSelector; if (typeof colorSelector === 'undefined' || !$.isPlainObject(colorSelector)) { return false; } var keys = Object.keys && Object.keys(colorSelector); return keys && keys.length > 0 && keys[0] !== ""; }, init: function ( options ) { options = options || {}; if ( !_initialized ) { if ( _debug ) { console.info("LENOVO.COLORSELECTOR: init"); } if ( app.hasOwnProperty('UTILS') ) { _debug = app.UTILS.isDebug(); _verbose = app.UTILS.isVerbose(); _usedefaults = app.UTILS.useDefaults(); } if ( app.hasOwnProperty('ENV') ) { _urls = app.ENV.urls(_baseurl); } self.settings = $.extend(true, {}, DEFAULTS); self.settings.data = $.extend(true, {}, window.colorSelector); $.extend(true, {}, self.settings, options); if ( app.TEMPLATES ) { app.TEMPLATES.precompile(self.settings.templateSources, true).then(_start, _handleAjaxError); } else { console.warn("LENOVO.COLORSELECTOR: Missing required dependency -> LENOVO.TEMPLATES"); } } } }; function _handleAjaxError ( jqXHR, textStatus, errorThrown ) { if ( jqXHR != null && jqXHR.getResponseHeader("X-Important-Error") && jqXHR.getResponseHeader("X-Important-Error") === "true" ) { document.open(); document.write(jqXHR.responseText); document.close(); } else if ( _debug ) { console.group("LENOVO.COLORSELECTOR: _handleAjaxError"); console.error("[" + textStatus + "]: " + jqXHR.responseText); console.error(errorThrown); console.log($.extend(true, {}, _builderdata)); console.groupEnd(); } else { console.error("[" + textStatus + "]: " + jqXHR.responseText); } } function _start () { var originals; if ( self.settings.keepOriginal ) { originals = _clone(); // need to clone and append after mods are complete } // add class to parent wrapper //$(self.settings.productListingScroller).addClass('colorSelector'); // group products with same specs groupedListings = _group( self.settings.productListingItem ); // modify structure of columns _reformat(groupedListings); // add to DOM _render(groupedListings); // add event listeners _activate(); // show diffs _showDiffs(); if ( typeof originals !== 'undefined' ) { // output original set originals.appendTo(settings.productListingScroller); } // trigger resize event to force recalc of height/widths, etc. of new elements $(window).trigger('resize'); _initialized = true; } function _clone () { return $(settings.productListings).clone(true).addClass('is-original'); } function _group ( selector ) { var map = _quickMap(selector); var data = self.settings.data; // abort if only 1 item (singleSku?) if ( $(selector).length < 2 ) { if ( _debug ) { console.warn("LENOVO.COLORSELECTOR: Less than 2 items detected. Aborting."); } return; } // create new product listings group var productKeys = []; var productListings = []; $(selector).each(function(i, el) { // store a flattened string as the key of this column to use for comparison var key = _flatten($(el).find(self.settings.groupCriteria)); // check if this key already exists in the productKeys array var index = productKeys.indexOf(key); // if this is the first time the color has been seen... if ( index === -1 ) { // add the key to productKeys array (save) productKeys.push(key); // add new listing to productListings array productListings.push({ // store the html html: $(el).clone(true), // create the empty attributes colors: [], ctasBottom: [], ctasMobile: [], ctasTop: [], icons: [], images: [], pns: [], presels: [], title: [] }); // set index to the index most recently added productListing index = productListings.length - 1; } var listing = productListings[index]; // populate the attributes var color = data[map[i].color].color; listing.colors.push(color); listing.ctasBottom.push({ rel: color, cta: map[i].ctaBottom, soldOut: map[i].soldOut }); listing.ctasMobile.push({ rel: color, cta: map[i].ctaMobile, soldOut: map[i].soldOut }); listing.ctasTop.push({ rel: color, cta: map[i].ctaTop, soldOut: map[i].soldOut }); listing.icons.push({ rel: color, src: data[map[i].color].icon, soldOut: map[i].soldOut }); listing.images.push({ alt: map[i].title, rel: color, src: data[map[i].color].image, soldOut: map[i].soldOut, soi: map[i].soi }); listing.pns.push({ rel: color, pn: map[i].pn }); listing.presels.push({ rel: color, presel: map[i].presel }); }); // result should be left with minimal columns return productListings; } function _quickMap ( selector ) { var map = []; // create a quick map of the config colors (from template) var colors = Object.keys(self.settings.data); // loop and... $(selector).each(function( i, el ) { var part = {}; // -- store relevant data $(el).find(self.settings.productListingCTABottom).find(".tabbedBrowse-productListing-footer-button-first").attr("style", ""); part.ctaBottom = $(el).find(self.settings.productListingCTABottom).html(); part.ctaMobile = $(el).find(self.settings.productListingCTAMobile).html(); part.ctaTop = $(el).find(self.settings.productListingCTATop).html(); part.pn = $(el).find(self.settings.productListingPartNumber).text(); part.presel = $(el).find(self.settings.productListingPreselection).html(); part.title = $(el).find(self.settings.productListingTitle).text(); // attempt to determine the color from the product title part.color = _arrayFind(part.title, colors); part.soldOut = $(el).find(self.settings.soldOut).length > 0; part.soi = ($(el).find(self.settings.soldOutImg).length > 0)? $(el).find(self.settings.soldOutImg).attr("src") : ""; if(part.soldOut){ _soldOutImg = $(el).find(self.settings.soldOutImg); } map.push(part); }); return map; } function _arrayFind ( needle, haystack ) { // TODO: Handle 'none' found'!! function __inString( str ) { return needle.indexOf(str) >= 0 } var found = haystack.find(__inString); return found ? found : null; } // convert a jQuery object's textNodes to a flattened string for simple comparison function _flatten ( jQ ) { return jQ.jquery ? $.trim(jQ.text().replace(/\r?\n|\r|\s+/ig,' ').toLowerCase()) : false; } // update the product columns for output function _reformat ( products ) { products.forEach(function( listing, index, ref ) { // add prod images (handlebars?) _addThumbnails( listing.html, listing.images ); // add swatches (handlebars?) _addSwatches( listing.html, listing.icons ); // add CTAs _addCTAs( listing.html, listing.ctasTop, listing.ctasBottom, listing.ctasMobile ); // add diff alignment class to CTA containers if ( index > 0 ) { $(self.settings.productListingCTABottom, listing.html).add(self.settings.productListingCTATop, listing.html).addClass('subseries-showModelDiff-align'); } // add PNs _addPNs( listing.html, listing.pns ); // add presel _addPresels( listing.html, listing.presels ); }); } function _addThumbnails ( html, images ) { var template = _getTemplate(self.settings.templates.thumbnails, images); // replace listing title with new image thumbs html.find(self.settings.productListingTitle).replaceWith(template); } function _addSwatches ( html, icons ) { var template = _getTemplate(self.settings.templates.swatches, icons); // add swatches to UI html.find(self.settings.productListingBody).append(template); } function _addCTAs ( html, ctasTop, ctasBottom, ctasMobile ) { var templateBottom = _getTemplate(self.settings.templates.ctas, ctasBottom); var templateMobile = _getTemplate(self.settings.templates.ctas, ctasMobile); var templateTop = _getTemplate(self.settings.templates.ctas, ctasTop); // add CTAs to UI html.find(self.settings.productListingCTABottom).replaceWith(templateBottom).end() .find(self.settings.productListingCTAMobile).replaceWith( $(templateMobile).addClass('tabbedBrowse-productListing-button-container-mobile') ).end() .find(self.settings.productListingCTATop).replaceWith(templateTop); } function _addPNs ( html, pns ) { var template = _getTemplate(self.settings.templates.pns, pns); // add CTAs to UI html.find(self.settings.productListingPartNumber).parent().replaceWith(template); } function _addPresels ( html, presels ) { var template = _getTemplate(self.settings.templates.presel, presels); // add CTAs to UI html.find(self.settings.productListingPreselection).replaceWith(template); } function _getTemplate (name, data) { var template; if (name == null) { return null; } if (data == null) { data = {}; } template = app.TEMPLATES.getTemplate(name)(data); if (_verbose) { console.groupCollapsed("LENOVO.COLORSELECTOR: _getTemplate: " + name); console.log(template); console.groupEnd(); } return template; }; function _render ( products ) { var list = $(self.settings.productListings); if ( $.isArray(products) ) { // clear the current list first list.empty(); // populate with new columns products.forEach(function( item ) { list.append(item.html); }); } } function _activate () { var columns = $(self.settings.productListingItem); columns.on('click.colorSelector.selectColor', '.js-colorSelector-select', _selectColor); columns.each(function( i, col ) { ($(col).find('.js-colorSelector-select:not(.colorSelector__swatchBtn--soldOut)').length > 0) ? $(col).find('.js-colorSelector-select:not(.colorSelector__swatchBtn--soldOut)').first().trigger('click.colorSelector') : $(col).find('.js-colorSelector-select').first().trigger('click.colorSelector'); }); } function _selectColor ( event ) { var color = $(this).data('colorselector'); var col = $(this).closest(self.settings.productListingItem); if ( color ) { var toggles = col.find('[data-colorselector]'); var active = toggles.filter('[data-colorselector="' + color + '"]'); toggles.removeClass('is-active').addClass('is-hidden') .filter(active).addClass('is-active').removeClass('is-hidden'); } } function _showDiffs () { var items = $(self.settings.productListingItem); var base = items.first().find(self.settings.diffCriteria); // disable show differences button click action $(self.settings.productListingScroller).off('click', '.subseries-show-diff') // also change the label text and remove the link .find('.btn-label').text( self.settings.modelDifferencesText ).unwrap(); // adjust background color of label $('.btn-label', self.settings.productListingScroller).parent().addClass('colorSelector__modelDiffs').css('background-color', self.settings.diffHilightColor); // highlight different items $(self.settings.productListingItem).slice(1).each(function() { $(this).find(self.settings.diffCriteria).children().each(function( index, child_item ) { if ( child_item.tagName === 'DT' ) { var child_dt = $.trim($(child_item).text()); var child_txt = $.trim($(child_item).next('dd').text().toLowerCase()); var base_dt = base.find('dt:contains(' + child_dt + ')'); var base_txt = $.trim($(base_dt).next('dd').text().toLowerCase()); if ( base_txt.replace(/\s/g) == '' ) { base_txt = $.trim(base.find('dt').eq(index).next('dd').text().toLowerCase()); } if ( base_txt !== child_txt ) { $(child_item).next('dd').addBack().css('background-color', self.settings.diffHilightColor); } } }); }); // adjust model differences label ribbon width if ( items.length > 0 ) { var rightMost = items.eq(items.length - 1); $('.colorSelector__modelDiffs').css('width', rightMost.width() + rightMost.position().left); } } })(window.LENOVO = window.LENOVO || {}, jQuery); /* end: /ISS_Static/WW/site/scripts/owv3/colorSelector.js(17396) */ /* start: /ISS_Static/WW/site/scripts/owv3/gaming-models.js (cachekey: [])*/ /* * LENOVO.MODELCUST module * -------------------------- * Dependencies: jQuery, LENOVO.MAIN, LENOVO.ENV, LENOVO.UTILS, LENOVO.TEMPLATES, LENOVO.SHOWDIFFERENCES */ (function (app, $) { "use strict" var _M = "MODELCUST"; var _version = "2016-10-12"; var _baseurl = window.long_url || ""; var _debug = window.debugAllowed || false; var _verbose = false; var _usedefaults = false; var _initialized = false; var _urls = null; var $window = $(window); var $document = $(document); var $body = null; var DEFAULTS = { diffCriteria: 'dl:not(.pricingSummary-details)', diffHilightColor: '#D9EEF7', modelDifferencesText: 'Model Differences', productListings: '.tabbedBrowse-productListings', // column wrapper productListingBody: '.tabbedBrowse-productListing-body', // element to append the new swatches productListingHeader: '.tabbedBrowse-productListing-header', // product column productListingItem: '.tabbedBrowse-productListings > li', // product column productListingPartNumber: '.tabbedBrowse-productListing-body .partnumber > span', // part number productListingPreselection: '.tabbedBrowse-productListing-presel', // preselection container productListingRibbon: '.ribbon-header' }; var self = app[_M] = { shouldRun: function () { var modelCust = window.modelCust; if (typeof modelCust === 'undefined' || !$.isPlainObject(modelCust)) { return false; } var keys = Object.keys && Object.keys(modelCust); return keys && keys.length > 0 && keys[0] !== ""; }, init: function ( options ) { options = options || {}; if ( !_initialized ) { if ( _debug ) { console.info("LENOVO.MODELCUST: init"); } if ( app.hasOwnProperty('UTILS') ) { _debug = app.UTILS.isDebug(); _verbose = app.UTILS.isVerbose(); _usedefaults = app.UTILS.useDefaults(); } if ( app.hasOwnProperty('ENV') ) { _urls = app.ENV.urls(_baseurl); } // merge and save/cache settings self.settings = $.extend(true, {}, DEFAULTS); self.settings.data = $.extend(true, {}, window.modelCust); $.extend(true, {}, self.settings, options); // add class to #longscroll-subseries for new CSS styles $('#longscroll-subseries, #tab-li-currentmodels').addClass('modelcust'); _start(); } } }; function _start () { // render the new DOM elements $(self.settings.productListingItem).each(_render); if ( $(window).width() > 768 ) { // show diffs _showDiffs(); } // save init state (run once per page load) _initialized = true; } function _render ( index, column ) { // get part number var pn = $.trim($(column).find(self.settings.productListingPartNumber).text()); // add thumbs to DOM _addThumbnail( column, pn ); // add product ribbons _addRibbon( column, pn ); // add barchart _addBarChart( column, pn ); } function _addThumbnail ( column, prodId ) { var image = self.settings.data[prodId].image; if ( image ) { var img = $('').attr('src', image); $(column).find(self.settings.productListingHeader).append(img); } } function _addRibbon ( column, prodId ) { var bannerTxt = self.settings.data[prodId].bannerTxt; var ribbon = $(column).find(self.settings.productListingRibbon); if ( bannerTxt && ribbon && ribbon.text() === '' ) { ribbon.addClass('modelCust__ribbon').text(bannerTxt); } } function _addBarChart ( column, prodId ) { var barchartgraphic = self.settings.data[prodId].barchart; if ( barchartgraphic ) { var chart = $('').attr('src', barchartgraphic); $(column).find(self.settings.productListingBody).append(chart); } } function _showDiffs () { // activate diffs app.SHOWDIFFERENCES.initModeldiff(); app.SHOWDIFFERENCES.showConfigurationDiffs( $(self.settings.productListings) ); // disable show differences button click action $(self.settings.productListings).off('click', '.subseries-show-diff') // also change the label text and remove the link .find('.btn-label').text( self.settings.modelDifferencesText ).unwrap(); // adjust background color of label $('.btn-label', self.settings.productListings).parent().css('background-color', self.settings.diffHilightColor); } })(window.LENOVO = window.LENOVO || {}, jQuery); /* end: /ISS_Static/WW/site/scripts/owv3/gaming-models.js(5166) */ /* start: /SEUILibrary/js/common/itemstatus.js (cachekey: [])*/ (function(win) { if(!win.itemstatus) { var itemst = {}; win.itemstatus = itemst; itemst.iStatusMsg = null; itemst.iStatusMsgLong = null; itemst.iRb = null; itemst.hideElementByRule = function( items, mydiv, etype, eparam ) { alinks = mydiv.children(etype); alinks.each( function( ) { content = $(this).attr(eparam); for( var i=0;i= 0 || content.indexOf( format2 ) >= 0 || content == format3 ) ) { win.itemstatus.iStatusMsg = itemstatus_iStatusMsg; win.itemstatus.iStatusMsgLong = itemstatus_iStatusMsg; if( !win.itemstatus.iStatusMsg ) { win.itemstatus.iStatusMsg = "Item not available"; } if( !win.itemstatus.iStatusMsgLong ) { win.itemstatus.iStatusMsgLong = "Item not available"; } if( mydiv.hasClass( 'buttonText-right' ) ) // special for builder page { mydiv = mydiv.parent('div').parent('div'); } mydiv.html(''+win.itemstatus.iStatusMsg+''); } } }); } itemst.hideElementByRule2 = function( items, etype, eparam ) { $(etype).each( function( ) { var mydiv = $(this); content = mydiv.attr(eparam); for( var i=0;i= 0 ) { win.itemstatus.iStatusMsg = itemstatus_iStatusMsg; win.itemstatus.iStatusMsgLong = itemstatus_iStatusMsg; if( !win.itemstatus.iStatusMsg ) { win.itemstatus.iStatusMsg = "Item not available"; } if( !win.itemstatus.iStatusMsgLong ) { win.itemstatus.iStatusMsgLong = "Item not available"; } mydiv = mydiv.closest('table'); mydiv.html(''+win.itemstatus.iStatusMsg+''); } } }); } itemst.hideAll = function ( items ) { $( "div" ).each( function () { mydiv = $(this); itemstatus.hideElementByRule( items, mydiv, "A", "href"); itemstatus.hideElementByRule( items, mydiv, "BUTTON", "onclick"); }); itemstatus.hideElementByRule2( items, "img", "onclick"); for( var i=0;i 0 ) { myItems[i++] = t; } }); } }) itemstatus.doHiding( myItems ); }, error : function( jqXHR, textStatus, errorThrown ) { // console.log( 'itemstatus: '+ errorThrown ); } } ); } itemst.doHiding = function ( items ) { if( !items || items.length < 1 ) { return; } win.itemstatus.hideAll(items); } } })(window); $(document).ready( function () { var items = itemstatus.checkState(); }); /* end: /SEUILibrary/js/common/itemstatus.js(5326) */ /* start: /SEUILibrary/hightech-portal/js/wci/WciCart.js (cachekey: [])*/ /** * @requires /js<%=jqueryLibVersion%> */ if(typeof(window.wci) === 'undefined') { window.wci = {}; } (function (wci) { if(!wci.cart) { var cart = {}; wci.cart = cart; } if (!wci.cart.deltaQtyArray) { wci.cart.deltaQtyArray = new Array(); } wci.cart.eCouponPostDone = false; wci.cart.cartFormId = ""; wci.cart.escapeId = function( id ) { return id.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1"); } wci.cart.removeItemFromCart = function( formId, url, itemId ) { formId = wci.cart.escapeId(formId); var mainFrm = $("#"+formId); mainFrm.append(''); //if this is a stackable warranty term part, also remove any stackable parts with matching applicability var $item = $("a[name='cat_" + itemId + "_removeLink']"); if($item.length >0){ var key = $item.closest(".cart-item-details").data("applicablekey"); console.info("key: " + key); if(typeof key != "undefined"){ $(".cart-item-details[data-applicable*='" + key + "']").each(function(){ var remUrl = $(this).find("a[name*='removeLink']").attr("onClick"); mainFrm.append(''); }); } } mainFrm.attr('action', url); mainFrm.submit(); } wci.cart.navigateToUrl = function( url ) { window.location = url; } wci.cart.submit = function( formId, url ) { formId = wci.cart.escapeId(formId); var mainFrm = $("#"+formId); mainFrm.attr('action', url); mainFrm.submit(); } wci.cart.markDeltaQty = function(obj) { if(!obj.jquery) { obj = $(obj); } for(var i=0;i'); } mForm.attr('action', url); mForm.submit(); } wci.cart.checkForEnterPress = function(e) { var keynum = 0; if(window.event) { keynum = window.event.keyCode; } else if(e != null && e.which) { keynum = e.which; } return keynum == 13; } wci.cart.checkForNumberPress = function(e) { if(e != null) { if( e.which!=8 && e.which!=0 && e.which!=46 && (e.which<48 || e.which>57)) e.preventDefault(); } } wci.cart.goOverview = function( selectId, formId, brandUrl, catalogUrl ) { var selOpt = $("#"+wci.cart.escapeId(selectId)+" option:selected"); if(selOpt.attr('type') == "" || selOpt.attr("type") == null) { return false; } var mForm = $("#"+wci.cart.escapeId(formId)); if(selOpt.attr('type') == "1") { var mUrl = brandUrl + "¤t-category-id=" + selOpt.val(); mUrl += "¤t-catalog-id=" + selOpt.attr('catalogID'); mForm.attr('action', mUrl); mForm.submit(); return false; } else if(selOpt.attr('type') == "3") { mForm.attr('action', catalogUrl); mForm.submit(); return false; } else if(selOpt.attr('type') == "masthead") { var linkk = unescape(selOpt.val()); if(linkk.indexOf("JavaScript") == 0 || linkk.indexOf("javascript") == 0) { eval(linkk); } else { mForm.attr('action', linkk); mForm.submit(); } return false; } return true; } wci.cart.addECoupon = function( formId, url ) { if(!wci.cart.eCouponPostDone) { wci.cart.eCouponPostDone=true; var pForm = $("#"+wci.cart.escapeId(formId)); pForm.attr('action', url); pForm.submit(); pForm.attr('disabled', 'disabled'); return false; } return true; } wci.cart.showLoginRequired = function(formId, message, url) { alert(message); formId = wci.cart.escapeId(formId); var mainFrm = $("#"+formId); mainFrm.attr('action', url); mainFrm.submit(); return true; } wci.cart.saveCartPopup = function(url, params, formId) { wci.cart.cartFormId = wci.cart.escapeId(formId); window.open(url, '', params); } wci.cart.saveCart = function(description, companyCart, url, cartType) { var saveIndicator = $("#saveIndicator"); if(saveIndicator != null) { saveIndicator.css("display", "inline"); } var mainFrm = $("#"+wci.cart.cartFormId); mainFrm.append(''); if (companyCart) { mainFrm.append(''); } mainFrm.attr('action', url); mainFrm.submit(); window.focus(); } wci.cart.closeRolloverCart = function(rolloverId, duration) { $('#' + rolloverId).hide(duration); } wci.cart.toggleRolloverCart = function(cartLinkId, rolloverId, duration) { var pos = $('#' + cartLinkId).offset(); var countTop = pos.top + $('#' + cartLinkId).height() + 14; if ($('#' + rolloverId).css('display') != 'block') { $('#' + rolloverId).css({position:"absolute", top: countTop, left: pos.left}).show(duration); } else { wci.cart.closeRolloverCart(rolloverId, duration); } } wci.cart.getCartFromCookie = function(cookieName) { var aCookies = document.cookie.split(';'); var x,y; for (i=0;i 0) { cartCountElem.empty(); } } wci.cart.addExternalCheckoutElements = function(externalCheckoutMsg) { $('').appendTo('body'); var form = $('
'); form.append(''); $('body').append(form); var postedForm = $('
'); postedForm.append(''); $('body').append(postedForm); if(document.getElementById("externalCheckoutOverlay") == null) { $("

"+externalCheckoutMsg+"
").appendTo('body'); $("#externalCheckoutOverlay").overlay( { expose: { loadSpeed: 'fast', opacity: 0.75 }, closeOnClick: false, load: false }); $("#externalCheckoutOverlay").css("left", Math.max(0, (($(window).width() - $("#externalCheckoutOverlay").outerWidth()) / 2) + $(window).scrollLeft()) + "px"); } } }(window.wci)); /* end: /SEUILibrary/hightech-portal/js/wci/WciCart.js(8492) */ /* start: /SEUILibrary/hightech-portal/js/wci/WciAccount.js (cachekey: [])*/ if(typeof(window.wci) === 'undefined') { window.wci = {}; } (function (wci) { if(!wci.account) { account = {}; wci.account = account; wci.account.pendingUrl = null; wci.account.loginUrl = ''; wci.account.checkLoginUrl = ''; } wci.account.escapeId = function( id ) { return id.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1"); } wci.account.popupsubmit = function (formId, url) { formId = wci.account.escapeId(formId); var mainFrm = $("#"+formId); wci.ajaxEx({ crossDomain: true, url: url, data: mainFrm.serialize(), async: true, type: "POST", dataType: 'html', xhrFields: { withCredentials: true }, error: function(xhr, textStatus, errorThrown) { console.log('error!'); }, success: function (data, status) { if( status == 'success' ) { var errorInfoMsg=$(data).find("msg").text(); if( errorInfoMsg != null && errorInfoMsg != '' ) { $("#systemErrorMsgTable").show(); $("#popuperrorMsg").text(errorInfoMsg); } else { wci.account.loginTried(); } } } }); mainFrm.action="#" } wci.account.submit = function (formId, url) { formId = wci.account.escapeId(formId); var mainFrm = $("#"+formId); mainFrm.removeAttr('onsubmit') mainFrm.attr('action', url); mainFrm.submit(); } wci.account.runLoginInOverlay = function (targetUrl,hideCloseButton) { wci.account.pendingUrl = targetUrl; wci.account.runCmdInOverlay( wci.account.loginUrl,hideCloseButton ); }; wci.account.loginTried = function () { if( wci.account.pendingUrl ) { var runningNextUrl = wci.account.pendingUrl; wci.account.pendingUrl = null; wci.account.runInOverlay( runningNextUrl, true ) } } wci.account.runCmdInOverlay = function ( url, hideCloseButton ) { wci.ajaxEx({ dataType: 'html', crossDomain: true, url: url, async: true, xhrFields: { withCredentials: true }, success: function(data , status) { if( status == 'success' ) { openFloatingPopup(data, null); if(url == wci.account.loginUrl || typeof(hideCloseButton) == 'undefined' || hideCloseButton == false) { floatingPopupShowCloseButton(); } } } }); } wci.account.runInOverlay = function ( url, checkLogin, updateReturnWf, hideCloseButton ) { if( checkLogin ) { if( updateReturnWf ) { wci.ajaxEx({ dataType: 'html', crossDomain: true, url: updateReturnWf, async: true, xhrFields: { withCredentials: true }, success: function(response) { } }); } wci.ajaxEx({ dataType: 'html', crossDomain: true, url: wci.account.checkLoginUrl, async: true, xhrFields: { withCredentials: true }, success: function(data, status) { if( status == 'success' ) { var jdata = $.parseJSON(data); if( !jdata || jdata.loggedIn != true ) { wci.account.runLoginInOverlay(url,hideCloseButton); } else { wci.account.runCmdInOverlay(url,hideCloseButton); } } } }); } } wci.account.resetPassword = function (formId, url) { formId = wci.account.escapeId(formId); $('').attr({ type: 'hidden', id: 'Account.LoginName', name: 'Account.LoginName', value: $('input[name=EmailAsLoginName]').val() }).appendTo('#' + formId); $('').attr({ type: 'hidden', id: 'Account.Email', name: 'Account.Email', value: $('input[name=Email]').val() }).appendTo('#' + formId); var mainFrm = $("#"+formId); mainFrm.attr('action', url); mainFrm.submit(); } wci.account.navigateToUrl = function( url ) { window.location = url; } wci.account.takeMeToSSOOVP = function(data, textStatus, jqXHR) { var myStatus = data.internalStatus; var myResponse = data.response; var token; var url; if (myStatus == 200) { token = myResponse; url = wci.account.SSOOVPUrl; url = url.replace("_TOKEN_", token); window.open(url); } else { setErrorMessage(myResponse); } } wci.account.ViewSSOOVPOrders = function(url, loginMsg, SSOOVPUrl) { wci.account.getExternalOrderStatusSSOToken(url, loginMsg, wci.account.takeMeToSSOOVP); wci.account.SSOOVPUrl = SSOOVPUrl; } wci.account.getExternalOrderStatusSSOToken = function(url, loginMsg, fnSuccess) { showNoMessage(); startGauge(loginMsg); wci.ajaxEx({ url: url, async: true, type: "GET", dataType: "json", success: fnSuccess, complete: function() { stopGauge(); } }); } wci.account.isJWSInstalled = function () { // For Internet Explorer. if (navigator.userAgent.indexOf('MSIE') > -1) { try { var jws = new ActiveXObject('JavaWebStart.isInstalled'); return true; } catch (e) { return false; } } return navigator.mimeTypes && navigator.mimeTypes.length && (navigator.mimeTypes['application/x-java-jnlp-file'] != null || navigator.mimeTypes['application/x-java-vm'] != null); } wci.account.startJLNP = function (url, installationPage, requiredMsg) { if (wci.account.isJWSInstalled()) { window.open(url, 'Maintenance', 'toolbar=yes,location=yes,resizable=yes,scrollbars=yes,width=600,height=480'); } else { alert(requiredMsg); window.open(installationPage); } } wci.account.getCookieLoginName = function(cookieName) { var aCookies = document.cookie.split(';'); var x,y; for (i=0;i&"\­\\]/g, replaceTag); } wci.account.saveCartpopup = function(sharedcarttype, defaultcarttype, savelink,blankalertmessage,longdescriptionmessage) { var savedescription= document.getElementById("cart-description").value.trim(); if(savedescription ==''){ alert(blankalertmessage); return false; } if(wci.account.getUTF8Length(savedescription)> 254){ alert(longdescriptionmessage); return false; } var decodedSavedescription = wci.account.decodeString(savedescription); var createSharedCart = false; if( document.getElementById("CreateSharedCart") ) { createSharedCart = (document.getElementById("CreateSharedCart").checked == true); } var mainFrm = $("#mainForms"); mainFrm.append(''); if (createSharedCart) { mainFrm.append(''); } else{ mainFrm.append(''); } mainFrm.attr('action', savelink); mainFrm.submit(); } wci.account.closeSavePopup= function() { closeFloatingPopup(floatingPositiveResponse); } wci.account.getUTF8Length=function(str) { var utf8length = 0; for (var n = 0; n < str.length; n++) { var c = str.charCodeAt(n); if (c < 128) { utf8length++; } else if((c > 127) && (c < 2048)) { utf8length = utf8length+2; } else { utf8length = utf8length+3; } } return utf8length; } wci.account.addItemToWishlist = function(url, updateReturnWfUrl, isPopup) { if(isPopup) { wci.account.runInOverlay(url, true, updateReturnWfUrl); } else { window.location.href = url; } }; wci.account.generateQuickQuote = function(url, updateReturnWfUrl) { wci.account.runInOverlay(url, true, updateReturnWfUrl, true); }; /** * Parses layout based profile data provided by the REST framework and converts it to a single profile object. */ wci.account.convertLayoutToProfileObject = function(data) { var profile = {}; var profile_rows = []; if(data.Row.length) { profile_rows = data.Row; } else { profile_rows[0] = data.Row; } for(var i = 0; i < profile_rows.length; i++) { var element = profile_rows[i].Element; var field = element.Field; if($.isArray(field)) { for(var j = 0; j < field.length; j++) { var elemName = field[j].Name; var elemValue = field[j].Value; var elemDisplayValue = field[j].DisplayValue; profile[elemName] = elemDisplayValue && elemDisplayValue !== '' ? elemDisplayValue : elemValue; } } else { profile[field.Name] = field.DisplayValue && field.DisplayValue !== '' ? field.DisplayValue : field.Value; } } return profile; }; }(window.wci)); /* end: /SEUILibrary/hightech-portal/js/wci/WciAccount.js(10447) */ /* start: /SEUILibrary/js/jquery/jquery.easyXDM.js (cachekey: [])*/ /* * https://github.com/GyldendalDigital/jQuery-easyXDM */ (function ($) { var jquery_easyXDM = {}; var global = this; // Used pattern from http://backtothefront.net/2012/asynchronous-singleton-api/ // for thread safe single instance easyXDM instantiation. var state = "before"; var callbackQueue = []; var easyXDM_connection = null; var error = null; var JQUERY_PATH = '/SEUILibrary/js/jquery'; // Allow forced usage and debugging of easyXDM by adding jquery.easyXDM.debug=true as parameter // to the page that uses this plugin. var easyXDM_debug = false; if (/jquery\.easyXDM\.debug=true/.test(String(window.location))) { easyXDM_debug = true; } if (easyXDM_debug) { if ($("#log").length == 0) $("body").append("
"); } var doRequests = function (provider_base_url,callbacks) { var jquery_path_full = provider_base_url + JQUERY_PATH; if (!$.support.cors || easyXDM_debug) { var easyXDM_url = jquery_path_full + "/easyXDM/easyXDM.min.js"; if (easyXDM_debug) { easyXDM_url = jquery_path_full + "/easyXDM/easyXDM.debug.js"; } function continue_after_easyXDM_load() { // Use noConflict to release any global state, to avoid conflict with // other easyXDM instances in the window of this page. var scoped_easyXDM = easyXDM.noConflict("jquery_easyXDM"); // Make the scoped easyXDM available as a unique global name, that can // be found from the easyXDM provider, and must match the noConflict // name in the provider. jquery_easyXDM.easyXDM = scoped_easyXDM; var remote_url = jquery_path_full + "/jquery.easyXDM.provider.html"; var container = $("#jquery_easyXDM_provider_container")[0] || null; if (easyXDM_debug) { remote_url += "?jquery.easyXDM.debug=true" if (!container) container = $("
").appendTo($("body"))[0]; } easyXDM_connection = new scoped_easyXDM.Rpc( { remote:remote_url, swf:jquery_path_full + "/easyXDM/easyxdm.swf", container: container, onReady:function() { callbacks.success(easyXDM_connection); } }, { remote:{ jquery_proxy:{} } }); } $.getScript(easyXDM_url, function () { // Load a json implementation if needed by old browsers // Avoid easyXDM helper that returns before the script is loaded. if (!(typeof(window["JSON"]) == 'object' && window["JSON"])) { $.getScript(jquery_path_full + "/easyXDM/json2.js", continue_after_easyXDM_load); } else { continue_after_easyXDM_load(); } }); } }; jquery_easyXDM.getConnection = function (provider_base_url,callbacks) { switch (state) { case "before": state = "working"; callbackQueue.push(callbacks); doRequests(provider_base_url,{ success:function (singletonInstance) { state = "success"; easyXDM_connection = singletonInstance; for (var i = 0; i < callbackQueue.length; i++) { callbackQueue[i].success(easyXDM_connection); } callbackQueue = []; }, failure:function (errorObj) { state = "failure"; error = errorObj; for (var i = 0; i < callbackQueue.length; i++) { callbackQueue[i].failure(error); } callbackQueue = []; } }); break; case "working": callbackQueue.push(callbacks); break; case "success": callbacks.success(easyXDM_connection); break; case "failure": callbacks.failure(error); break; default: throw new Error("Invalid state: " + state) } }; $.ajaxTransport("+*",function (options, originalOptions, jqXHR) { if ( options.crossDomain && (!$.support.cors || easyXDM_debug) ) { // Assume a relative url as fallback, even if it is senseless, it may be used for testing. var provider_base_url = ""; // Each CORS enabled provider must have a unique connection, therefore // generate a name from the provider_base_url as an index. var regexp_results = options.url.match(/^(https?:\/\/[^\/]*)\/?.*/); if(regexp_results){ provider_base_url = regexp_results[1]; }; return { send :function (headers, completeCallback) { jquery_easyXDM.getConnection(provider_base_url,{ success:function (easyXDM_connection) { function continuation_proxy(results) { completeCallback(results.status, results.statusText, results.responses, results.headers); } originalOptions.context = null; easyXDM_connection.jquery_proxy(originalOptions, continuation_proxy); }, error:function () { // Unable to get easyXDM connection } }); }, abort:function () { } }; } }); global.jquery_easyXDM = jquery_easyXDM; })(jQuery); /* end: /SEUILibrary/js/jquery/jquery.easyXDM.js(5210) */ /* start: /SEUILibrary/js/jquery/easyXDM/easyXDM.min.js (cachekey: [])*/ /** * easyXDM * http://easyxdm.net/ * Copyright(c) 2009-2011, �yvind Sean Kinsey, oyvind@kinsey.no. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ (function(N,d,p,K,k,H){var b=this;var n=Math.floor(Math.random()*10000);var q=Function.prototype;var Q=/^((http.?:)\/\/([^:\/\s]+)(:\d+)*)/;var R=/[\-\w]+\/\.\.\//;var F=/([^:])\/\//g;var I="";var o={};var M=N.easyXDM;var U="easyXDM_";var E;var y=false;var i;var h;function C(X,Z){var Y=typeof X[Z];return Y=="function"||(!!(Y=="object"&&X[Z]))||Y=="unknown"}function u(X,Y){return !!(typeof(X[Y])=="object"&&X[Y])}function r(X){return Object.prototype.toString.call(X)==="[object Array]"}function c(){var Z="Shockwave Flash",ad="application/x-shockwave-flash";if(!t(navigator.plugins)&&typeof navigator.plugins[Z]=="object"){var ab=navigator.plugins[Z].description;if(ab&&!t(navigator.mimeTypes)&&navigator.mimeTypes[ad]&&navigator.mimeTypes[ad].enabledPlugin){i=ab.match(/\d+/g)}}if(!i){var Y;try{Y=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");i=Array.prototype.slice.call(Y.GetVariable("$version").match(/(\d+),(\d+),(\d+),(\d+)/),1);Y=null}catch(ac){}}if(!i){return false}var X=parseInt(i[0],10),aa=parseInt(i[1],10);h=X>9&&aa>0;return true}var v,x;if(C(N,"addEventListener")){v=function(Z,X,Y){Z.addEventListener(X,Y,false)};x=function(Z,X,Y){Z.removeEventListener(X,Y,false)}}else{if(C(N,"attachEvent")){v=function(X,Z,Y){X.attachEvent("on"+Z,Y)};x=function(X,Z,Y){X.detachEvent("on"+Z,Y)}}else{throw new Error("Browser not supported")}}var W=false,J=[],L;if("readyState" in d){L=d.readyState;W=L=="complete"||(~navigator.userAgent.indexOf("AppleWebKit/")&&(L=="loaded"||L=="interactive"))}else{W=!!d.body}function s(){if(W){return}W=true;for(var X=0;X')}else{ac=d.createElement("IFRAME");ac.name=Y.props.name}ac.id=ac.name=Y.props.name;delete Y.props.name;if(typeof Y.container=="string"){Y.container=d.getElementById(Y.container)}if(!Y.container){T(ac.style,{position:"absolute",top:"-2000px",left:"0px"});Y.container=d.body}var ab=Y.props.src;Y.props.src="javascript:false";T(ac,Y.props);ac.border=ac.frameBorder=0;ac.allowTransparency=true;Y.container.appendChild(ac);if(Y.onLoad){v(ac,"load",Y.onLoad)}if(Y.usePost){var aa=Y.container.appendChild(d.createElement("form")),X;aa.target=ac.name;aa.action=ab;aa.method="POST";if(typeof(Y.usePost)==="object"){for(var Z in Y.usePost){if(Y.usePost.hasOwnProperty(Z)){if(E){X=d.createElement('')}else{X=d.createElement("INPUT");X.name=Z}X.value=Y.usePost[Z];aa.appendChild(X)}}}aa.submit();aa.parentNode.removeChild(aa)}else{ac.src=ab}Y.props.src=ab;return ac}function V(aa,Z){if(typeof aa=="string"){aa=[aa]}var Y,X=aa.length;while(X--){Y=aa[X];Y=new RegExp(Y.substr(0,1)=="^"?Y:("^"+Y.replace(/(\*)/g,".$1").replace(/\?/g,".")+"$"));if(Y.test(Z)){return true}}return false}function l(Z){var ae=Z.protocol,Y;Z.isHost=Z.isHost||t(S.xdm_p);y=Z.hash||false;if(!Z.props){Z.props={}}if(!Z.isHost){Z.channel=S.xdm_c.replace(/["'<>\\]/g,"");Z.secret=S.xdm_s;Z.remote=S.xdm_e.replace(/["'<>\\]/g,"");ae=S.xdm_p;if(Z.acl&&!V(Z.acl,Z.remote)){throw new Error("Access denied for "+Z.remote)}}else{Z.remote=B(Z.remote);Z.channel=Z.channel||"default"+n++;Z.secret=Math.random().toString(16).substring(2);if(t(ae)){if(j(p.href)==j(Z.remote)){ae="4"}else{if(C(N,"postMessage")||C(d,"postMessage")){ae="1"}else{if(Z.swf&&C(N,"ActiveXObject")&&c()){ae="6"}else{if(navigator.product==="Gecko"&&"frameElement" in N&&navigator.userAgent.indexOf("WebKit")==-1){ae="5"}else{if(Z.remoteHelper){ae="2"}else{ae="0"}}}}}}}Z.protocol=ae;switch(ae){case"0":T(Z,{interval:100,delay:2000,useResize:true,useParent:false,usePolling:false},true);if(Z.isHost){if(!Z.local){var ac=p.protocol+"//"+p.host,X=d.body.getElementsByTagName("img"),ad;var aa=X.length;while(aa--){ad=X[aa];if(ad.src.substring(0,ac.length)===ac){Z.local=ad.src;break}}if(!Z.local){Z.local=N}}var ab={xdm_c:Z.channel,xdm_p:0};if(Z.local===N){Z.usePolling=true;Z.useParent=true;Z.local=p.protocol+"//"+p.host+p.pathname+p.search;ab.xdm_e=Z.local;ab.xdm_pa=1}else{ab.xdm_e=B(Z.local)}if(Z.container){Z.useResize=false;ab.xdm_po=1}Z.remote=P(Z.remote,ab)}else{T(Z,{channel:S.xdm_c,remote:S.xdm_e,useParent:!t(S.xdm_pa),usePolling:!t(S.xdm_po),useResize:Z.useParent?false:Z.useResize})}Y=[new o.stack.HashTransport(Z),new o.stack.ReliableBehavior({}),new o.stack.QueueBehavior({encode:true,maxLength:4000-Z.remote.length}),new o.stack.VerifyBehavior({initiate:Z.isHost})];break;case"1":Y=[new o.stack.PostMessageTransport(Z)];break;case"2":Z.remoteHelper=B(Z.remoteHelper);Y=[new o.stack.NameTransport(Z),new o.stack.QueueBehavior(),new o.stack.VerifyBehavior({initiate:Z.isHost})];break;case"3":Y=[new o.stack.NixTransport(Z)];break;case"4":Y=[new o.stack.SameOriginTransport(Z)];break;case"5":Y=[new o.stack.FrameElementTransport(Z)];break;case"6":if(!i){c()}Y=[new o.stack.FlashTransport(Z)];break}Y.push(new o.stack.QueueBehavior({lazy:Z.lazy,remove:true}));return Y}function D(aa){var ab,Z={incoming:function(ad,ac){this.up.incoming(ad,ac)},outgoing:function(ac,ad){this.down.outgoing(ac,ad)},callback:function(ac){this.up.callback(ac)},init:function(){this.down.init()},destroy:function(){this.down.destroy()}};for(var Y=0,X=aa.length;Y<\/script>')}}}; (function(){var X={};o.Fn={set:function(Y,Z){X[Y]=Z},get:function(Z,Y){var aa=X[Z];if(Y){delete X[Z]}return aa}}}());o.Socket=function(Y){var X=D(l(Y).concat([{incoming:function(ab,aa){Y.onMessage(ab,aa)},callback:function(aa){if(Y.onReady){Y.onReady(aa)}}}])),Z=j(Y.remote);this.origin=j(Y.remote);this.destroy=function(){X.destroy()};this.postMessage=function(aa){X.outgoing(aa,Z)};X.init()};o.Rpc=function(Z,Y){if(Y.local){for(var ab in Y.local){if(Y.local.hasOwnProperty(ab)){var aa=Y.local[ab];if(typeof aa==="function"){Y.local[ab]={method:aa}}}}}var X=D(l(Z).concat([new o.stack.RpcBehavior(this,Y),{callback:function(ac){if(Z.onReady){Z.onReady(ac)}}}]));this.origin=j(Z.remote);this.destroy=function(){X.destroy()};X.init()};o.stack.SameOriginTransport=function(Y){var Z,ab,aa,X;return(Z={outgoing:function(ad,ae,ac){aa(ad);if(ac){ac()}},destroy:function(){if(ab){ab.parentNode.removeChild(ab);ab=null}},onDOMReady:function(){X=j(Y.remote);if(Y.isHost){T(Y.props,{src:P(Y.remote,{xdm_e:p.protocol+"//"+p.host+p.pathname,xdm_c:Y.channel,xdm_p:4}),name:U+Y.channel+"_provider"});ab=A(Y);o.Fn.set(Y.channel,function(ac){aa=ac;K(function(){Z.up.callback(true)},0);return function(ad){Z.up.incoming(ad,X)}})}else{aa=m().Fn.get(Y.channel,true)(function(ac){Z.up.incoming(ac,X)});K(function(){Z.up.callback(true)},0)}},init:function(){G(Z.onDOMReady,Z)}})};o.stack.FlashTransport=function(aa){var ac,X,ab,ad,Y,ae;function af(ah,ag){K(function(){ac.up.incoming(ah,ad)},0)}function Z(ah){var ag=aa.swf+"?host="+aa.isHost;var aj="easyXDM_swf_"+Math.floor(Math.random()*10000);o.Fn.set("flash_loaded"+ah.replace(/[\-.]/g,"_"),function(){o.stack.FlashTransport[ah].swf=Y=ae.firstChild;var ak=o.stack.FlashTransport[ah].queue;for(var al=0;al"}return(ac={outgoing:function(ah,ai,ag){Y.postMessage(aa.channel,ah.toString());if(ag){ag()}},destroy:function(){try{Y.destroyChannel(aa.channel)}catch(ag){}Y=null;if(X){X.parentNode.removeChild(X);X=null}},onDOMReady:function(){ad=aa.remote;o.Fn.set("flash_"+aa.channel+"_init",function(){K(function(){ac.up.callback(true)})});o.Fn.set("flash_"+aa.channel+"_onMessage",af);aa.swf=B(aa.swf);var ah=z(aa.swf);var ag=function(){o.stack.FlashTransport[ah].init=true;Y=o.stack.FlashTransport[ah].swf;Y.createChannel(aa.channel,aa.secret,j(aa.remote),aa.isHost);if(aa.isHost){if(h&&aa.swfNoThrottle){T(aa.props,{position:"fixed",right:0,top:0,height:"20px",width:"20px"})}T(aa.props,{src:P(aa.remote,{xdm_e:j(p.href),xdm_c:aa.channel,xdm_p:6,xdm_s:aa.secret}),name:U+aa.channel+"_provider"});X=A(aa)}};if(o.stack.FlashTransport[ah]&&o.stack.FlashTransport[ah].init){ag()}else{if(!o.stack.FlashTransport[ah]){o.stack.FlashTransport[ah]={queue:[ag]};Z(ah)}else{o.stack.FlashTransport[ah].queue.push(ag)}}},init:function(){G(ac.onDOMReady,ac)}})};o.stack.PostMessageTransport=function(aa){var ac,ad,Y,Z;function X(ae){if(ae.origin){return j(ae.origin)}if(ae.uri){return j(ae.uri)}if(ae.domain){return p.protocol+"//"+ae.domain}throw"Unable to retrieve the origin of the event"}function ab(af){var ae=X(af);if(ae==Z&&af.data.substring(0,aa.channel.length+1)==aa.channel+" "){ac.up.incoming(af.data.substring(aa.channel.length+1),ae)}}return(ac={outgoing:function(af,ag,ae){Y.postMessage(aa.channel+" "+af,ag||Z);if(ae){ae()}},destroy:function(){x(N,"message",ab);if(ad){Y=null;ad.parentNode.removeChild(ad);ad=null}},onDOMReady:function(){Z=j(aa.remote);if(aa.isHost){var ae=function(af){if(af.data==aa.channel+"-ready"){Y=("postMessage" in ad.contentWindow)?ad.contentWindow:ad.contentWindow.document;x(N,"message",ae);v(N,"message",ab);K(function(){ac.up.callback(true)},0)}};v(N,"message",ae);T(aa.props,{src:P(aa.remote,{xdm_e:j(p.href),xdm_c:aa.channel,xdm_p:1}),name:U+aa.channel+"_provider"});ad=A(aa)}else{v(N,"message",ab);Y=("postMessage" in N.parent)?N.parent:N.parent.document;Y.postMessage(aa.channel+"-ready",Z);K(function(){ac.up.callback(true)},0)}},init:function(){G(ac.onDOMReady,ac)}})};o.stack.FrameElementTransport=function(Y){var Z,ab,aa,X;return(Z={outgoing:function(ad,ae,ac){aa.call(this,ad);if(ac){ac()}},destroy:function(){if(ab){ab.parentNode.removeChild(ab);ab=null}},onDOMReady:function(){X=j(Y.remote);if(Y.isHost){T(Y.props,{src:P(Y.remote,{xdm_e:j(p.href),xdm_c:Y.channel,xdm_p:5}),name:U+Y.channel+"_provider"});ab=A(Y);ab.fn=function(ac){delete ab.fn;aa=ac;K(function(){Z.up.callback(true)},0);return function(ad){Z.up.incoming(ad,X)}}}else{if(d.referrer&&j(d.referrer)!=S.xdm_e){N.top.location=S.xdm_e}aa=N.frameElement.fn(function(ac){Z.up.incoming(ac,X)});Z.up.callback(true)}},init:function(){G(Z.onDOMReady,Z)}})};o.stack.NameTransport=function(ab){var ac;var ae,ai,aa,ag,ah,Y,X;function af(al){var ak=ab.remoteHelper+(ae?"#_3":"#_2")+ab.channel;ai.contentWindow.sendMessage(al,ak)}function ad(){if(ae){if(++ag===2||!ae){ac.up.callback(true)}}else{af("ready");ac.up.callback(true)}}function aj(ak){ac.up.incoming(ak,Y)}function Z(){if(ah){K(function(){ah(true)},0)}}return(ac={outgoing:function(al,am,ak){ah=ak;af(al)},destroy:function(){ai.parentNode.removeChild(ai);ai=null;if(ae){aa.parentNode.removeChild(aa);aa=null}},onDOMReady:function(){ae=ab.isHost;ag=0;Y=j(ab.remote);ab.local=B(ab.local);if(ae){o.Fn.set(ab.channel,function(al){if(ae&&al==="ready"){o.Fn.set(ab.channel,aj);ad()}});X=P(ab.remote,{xdm_e:ab.local,xdm_c:ab.channel,xdm_p:2});T(ab.props,{src:X+"#"+ab.channel,name:U+ab.channel+"_provider"});aa=A(ab)}else{ab.remoteHelper=ab.remote;o.Fn.set(ab.channel,aj)}var ak=function(){var al=ai||this;x(al,"load",ak);o.Fn.set(ab.channel+"_load",Z);(function am(){if(typeof al.contentWindow.sendMessage=="function"){ad()}else{K(am,50)}}())};ai=A({props:{src:ab.local+"#_4"+ab.channel},onLoad:ak})},init:function(){G(ac.onDOMReady,ac)}})};o.stack.HashTransport=function(Z){var ac;var ah=this,af,aa,X,ad,am,ab,al;var ag,Y;function ak(ao){if(!al){return}var an=Z.remote+"#"+(am++)+"_"+ao;((af||!ag)?al.contentWindow:al).location=an}function ae(an){ad=an;ac.up.incoming(ad.substring(ad.indexOf("_")+1),Y)}function aj(){if(!ab){return}var an=ab.location.href,ap="",ao=an.indexOf("#");if(ao!=-1){ap=an.substring(ao)}if(ap&&ap!=ad){ae(ap)}}function ai(){aa=setInterval(aj,X)}return(ac={outgoing:function(an,ao){ak(an)},destroy:function(){N.clearInterval(aa);if(af||!ag){al.parentNode.removeChild(al)}al=null},onDOMReady:function(){af=Z.isHost;X=Z.interval;ad="#"+Z.channel;am=0;ag=Z.useParent;Y=j(Z.remote);if(af){T(Z.props,{src:Z.remote,name:U+Z.channel+"_provider"});if(ag){Z.onLoad=function(){ab=N;ai();ac.up.callback(true)}}else{var ap=0,an=Z.delay/50;(function ao(){if(++ap>an){throw new Error("Unable to reference listenerwindow")}try{ab=al.contentWindow.frames[U+Z.channel+"_consumer"]}catch(aq){}if(ab){ai();ac.up.callback(true)}else{K(ao,50)}}())}al=A(Z)}else{ab=N;ai();if(ag){al=parent;ac.up.callback(true)}else{T(Z,{props:{src:Z.remote+"#"+Z.channel+new Date(),name:U+Z.channel+"_consumer"},onLoad:function(){ac.up.callback(true)}});al=A(Z)}}},init:function(){G(ac.onDOMReady,ac)}})}; o.stack.ReliableBehavior=function(Y){var aa,ac;var ab=0,X=0,Z="";return(aa={incoming:function(af,ad){var ae=af.indexOf("_"),ag=af.substring(0,ae).split(",");af=af.substring(ae+1);if(ag[0]==ab){Z="";if(ac){ac(true);ac=null}}if(af.length>0){aa.down.outgoing(ag[1]+","+ab+"_"+Z,ad);if(X!=ag[1]){X=ag[1];aa.up.incoming(af,ad)}}},outgoing:function(af,ad,ae){Z=af;ac=ae;aa.down.outgoing(X+","+(++ab)+"_"+af,ad)}})};o.stack.QueueBehavior=function(Z){var ac,ad=[],ag=true,aa="",af,X=0,Y=false,ab=false;function ae(){if(Z.remove&&ad.length===0){w(ac);return}if(ag||ad.length===0||af){return}ag=true;var ah=ad.shift();ac.down.outgoing(ah.data,ah.origin,function(ai){ag=false;if(ah.callback){K(function(){ah.callback(ai)},0)}ae()})}return(ac={init:function(){if(t(Z)){Z={}}if(Z.maxLength){X=Z.maxLength;ab=true}if(Z.lazy){Y=true}else{ac.down.init()}},callback:function(ai){ag=false;var ah=ac.up;ae();ah.callback(ai)},incoming:function(ak,ai){if(ab){var aj=ak.indexOf("_"),ah=parseInt(ak.substring(0,aj),10);aa+=ak.substring(aj+1);if(ah===0){if(Z.encode){aa=k(aa)}ac.up.incoming(aa,ai);aa=""}}else{ac.up.incoming(ak,ai)}},outgoing:function(al,ai,ak){if(Z.encode){al=H(al)}var ah=[],aj;if(ab){while(al.length!==0){aj=al.substring(0,X);al=al.substring(aj.length);ah.push(aj)}while((aj=ah.shift())){ad.push({data:ah.length+"_"+aj,origin:ai,callback:ah.length===0?ak:null})}}else{ad.push({data:al,origin:ai,callback:ak})}if(Y){ac.down.init()}else{ae()}},destroy:function(){af=true;ac.down.destroy()}})};o.stack.VerifyBehavior=function(ab){var ac,aa,Y,Z=false;function X(){aa=Math.random().toString(16).substring(2);ac.down.outgoing(aa)}return(ac={incoming:function(af,ad){var ae=af.indexOf("_");if(ae===-1){if(af===aa){ac.up.callback(true)}else{if(!Y){Y=af;if(!ab.initiate){X()}ac.down.outgoing(af)}}}else{if(af.substring(0,ae)===Y){ac.up.incoming(af.substring(ae+1),ad)}}},outgoing:function(af,ad,ae){ac.down.outgoing(aa+"_"+af,ad,ae)},callback:function(ad){if(ab.initiate){X()}}})};o.stack.RpcBehavior=function(ad,Y){var aa,af=Y.serializer||O();var ae=0,ac={};function X(ag){ag.jsonrpc="2.0";aa.down.outgoing(af.stringify(ag))}function ab(ag,ai){var ah=Array.prototype.slice;return function(){var aj=arguments.length,al,ak={method:ai};if(aj>0&&typeof arguments[aj-1]==="function"){if(aj>1&&typeof arguments[aj-2]==="function"){al={success:arguments[aj-2],error:arguments[aj-1]};ak.params=ah.call(arguments,0,aj-2)}else{al={success:arguments[aj-1]};ak.params=ah.call(arguments,0,aj-1)}ac[""+(++ae)]=al;ak.id=ae}else{ak.params=ah.call(arguments,0)}if(ag.namedParams&&ak.params.length===1){ak.params=ak.params[0]}X(ak)}}function Z(an,am,ai,al){if(!ai){if(am){X({id:am,error:{code:-32601,message:"Procedure not found."}})}return}var ak,ah;if(am){ak=function(ao){ak=q;X({id:am,result:ao})};ah=function(ao,ap){ah=q;var aq={id:am,error:{code:-32099,message:ao}};if(ap){aq.error.data=ap}X(aq)}}else{ak=ah=q}if(!r(al)){al=[al]}try{var ag=ai.method.apply(ai.scope,al.concat([ak,ah]));if(!t(ag)){ak(ag)}}catch(aj){ah(aj.message)}}return(aa={incoming:function(ah,ag){var ai=af.parse(ah);if(ai.method){if(Y.handle){Y.handle(ai,X)}else{Z(ai.method,ai.id,Y.local[ai.method],ai.params)}}else{var aj=ac[ai.id];if(ai.error){if(aj.error){aj.error(ai.error)}}else{if(aj.success){aj.success(ai.result)}}delete ac[ai.id]}},init:function(){if(Y.remote){for(var ag in Y.remote){if(Y.remote.hasOwnProperty(ag)){ad[ag]=ab(Y.remote[ag],ag)}}}aa.down.init()},destroy:function(){for(var ag in Y.remote){if(Y.remote.hasOwnProperty(ag)&&ad.hasOwnProperty(ag)){delete ad[ag]}}aa.down.destroy()}})};b.easyXDM=o})(window,document,location,window.setTimeout,decodeURIComponent,encodeURIComponent); /* end: /SEUILibrary/js/jquery/easyXDM/easyXDM.min.js(20669) */ /* start: /SEUILibrary/hightech-portal/js/wci/catalog/ItemAddToCartButton.js (cachekey: [])*/ function getHtml(pageUrl, errorStatus) { $.ajax({ ignoreErrors : false, url : pageUrl + "?errorStatus=" + errorStatus, type : "GET", dataType : "html", //timeout : 3000, success : function(data) { $('#unavailableDiv').html(data); }, error : function(data, status, validate) { $('#unavailableDiv').html('

Unavailable

Tried to access error page but even that is unavailable: ' + pageUrl); } }); } function showForm(continueUrl, errorUrl) { floatingPopupShowUpperRightCloseButton(true); $ .ajax({ ignoreErrors : false, url : continueUrl, type : "GET", // timeout : 3000, dataType : "html", beforeSend : function() { openFloatingPopup( "
" + " " + "
", 'unavailableDiv'); }, success : function(data) { $('#unavailableDiv').html(data); }, error : function(data, status, validate) { getHtml(errorUrl, status); }, complete : function() { } }); } /* end: /SEUILibrary/hightech-portal/js/wci/catalog/ItemAddToCartButton.js(1104) */ /* start: /SEUILibrary/js/common/BrowserCompatibility.js (cachekey: [])*/ /*\ |*| |*| IE-specific polyfill which enables the passage of arbitrary arguments to the |*| callback functions of javascript timers (HTML5 standard syntax). |*| |*| https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval |*| |*| Syntax: |*| var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]); |*| var timeoutID = window.setTimeout(code, delay); |*| var intervalID = window.setInterval(func, delay[, param1, param2, ...]); |*| var intervalID = window.setInterval(code, delay); |*| \*/ if (document.all && !window.setTimeout.isPolyfill) { var __nativeST__ = window.setTimeout; window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) { var aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function ? function () { vCallback.apply(null, aArgs); } : vCallback, nDelay); }; window.setTimeout.isPolyfill = true; } if (document.all && !window.setInterval.isPolyfill) { var __nativeSI__ = window.setInterval; window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) { var aArgs = Array.prototype.slice.call(arguments, 2); return __nativeSI__(vCallback instanceof Function ? function () { vCallback.apply(null, aArgs); } : vCallback, nDelay); }; window.setInterval.isPolyfill = true; } /* end: /SEUILibrary/js/common/BrowserCompatibility.js(1390) */ /* start: /SEUILibrary/hightech-portal/js/commonScripts/json2.js (cachekey: [])*/ /* json2.js 2012-10-08 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html This code should be minified before deployment. See http://javascript.crockford.com/jsmin.html USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL. This file creates a global JSON object containing two methods: stringify and parse. JSON.stringify(value, replacer, space) value any JavaScript value, usually an object or array. replacer an optional parameter that determines how object values are stringified for objects. It can be a function or an array of strings. space an optional parameter that specifies the indentation of nested structures. If it is omitted, the text will be packed without extra whitespace. If it is a number, it will specify the number of spaces to indent at each level. If it is a string (such as '\t' or ' '), it contains the characters used to indent at each level. This method produces a JSON text from a JavaScript value. When an object value is found, if the object contains a toJSON method, its toJSON method will be called and the result will be stringified. A toJSON method does not serialize: it returns the value represented by the name/value pair that should be serialized, or undefined if nothing should be serialized. The toJSON method will be passed the key associated with the value, and this will be bound to the value For example, this would serialize Dates as ISO strings. Date.prototype.toJSON = function (key) { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; }; You can provide an optional replacer method. It will be passed the key and value of each member, with this bound to the containing object. The value that is returned from your method will be serialized. If your method returns undefined, then the member will be excluded from the serialization. If the replacer parameter is an array of strings, then it will be used to select the members to be serialized. It filters the results such that only members with keys listed in the replacer array are stringified. Values that do not have JSON representations, such as undefined or functions, will not be serialized. Such values in objects will be dropped; in arrays they will be replaced with null. You can use a replacer function to replace those with JSON values. JSON.stringify(undefined) returns undefined. The optional space parameter produces a stringification of the value that is filled with line breaks and indentation to make it easier to read. If the space parameter is a non-empty string, then that string will be used for indentation. If the space parameter is a number, then the indentation will be that many spaces. Example: text = JSON.stringify(['e', {pluribus: 'unum'}]); // text is '["e",{"pluribus":"unum"}]' text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' text = JSON.stringify([new Date()], function (key, value) { return this[key] instanceof Date ? 'Date(' + this[key] + ')' : value; }); // text is '["Date(---current time---)"]' JSON.parse(text, reviver) This method parses a JSON text to produce an object or array. It can throw a SyntaxError exception. The optional reviver parameter is a function that can filter and transform the results. It receives each of the keys and values, and its return value is used instead of the original value. If it returns what it received, then the structure is not modified. If it returns undefined then the member is deleted. Example: // Parse the text. Values that look like ISO date strings will // be converted to Date objects. myData = JSON.parse(text, function (key, value) { var a; if (typeof value === 'string') { a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); if (a) { return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6])); } } return value; }); myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { var d; if (typeof value === 'string' && value.slice(0, 5) === 'Date(' && value.slice(-1) === ')') { d = new Date(value.slice(5, -1)); if (d) { return d; } } return value; }); This is a reference implementation. You are free to copy, modify, or redistribute. */ /*jslint evil: true, regexp: true */ /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, parse, prototype, push, replace, slice, stringify, test, toJSON, toString, valueOf */ // Create a JSON object only if one does not already exist. We create the // methods in a closure to avoid creating global variables. if (typeof JSON !== 'object') { JSON = {}; } (function () { 'use strict'; function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } if (typeof Date.prototype.toJSON !== 'function') { Date.prototype.toJSON = function (key) { return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null; }; String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) { return this.valueOf(); }; } var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }, rep; function quote(string) { // If the string contains no control characters, no quote characters, and no // backslash characters, then we can safely slap some quotes around it. // Otherwise we must also replace the offending characters with safe escape // sequences. escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { // Produce a string from holder[key]. var i, // The loop counter. k, // The member key. v, // The member value. length, mind = gap, partial, value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // If we were called with a replacer function, then call the replacer to // obtain a replacement value. if (typeof rep === 'function') { value = rep.call(holder, key, value); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); // If the type is 'object', we might be dealing with an object or an array or // null. case 'object': // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null'; } // Make an array to hold the partial results of stringifying this object value. gap += indent; partial = []; // Is the value an array? if (Object.prototype.toString.apply(value) === '[object Array]') { // The value is an array. Stringify every element. Use null as a placeholder // for non-JSON values. length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in // brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // If the replacer is an array, use it to select the members to be stringified. if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { if (typeof rep[i] === 'string') { k = rep[i]; v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { // Otherwise, iterate through all of the keys in the object. for (k in value) { if (Object.prototype.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } // Join all of the member texts together, separated with commas, // and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } // If the JSON object does not yet have a stringify method, give it one. if (typeof JSON.stringify !== 'function') { JSON.stringify = function (value, replacer, space) { // The stringify method takes a value and an optional replacer, and an optional // space parameter, and returns a JSON text. The replacer can be a function // that can replace values, or an array of strings that will select the keys. // A default replacer method can be provided. Use of the space parameter can // produce text that is more easily readable. var i; gap = ''; indent = ''; // If the space parameter is a number, make an indent string containing that // many spaces. if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } // If the space parameter is a string, it will be used as the indent string. } else if (typeof space === 'string') { indent = space; } // If there is a replacer, it must be a function or an array. // Otherwise, throw an error. rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', {'': value}); }; } // If the JSON object does not yet have a parse method, give it one. if (typeof JSON.parse !== 'function') { JSON.parse = function (text, reviver) { // The parse method takes a text and an optional reviver function, and returns // a JavaScript value if the text is a valid JSON text. var j; function walk(holder, key) { // The walk method is used to recursively walk the resulting structure so // that modifications can be made. var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.prototype.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } // Parsing happens in four stages. In the first stage, we replace certain // Unicode characters with escape sequences. JavaScript handles many characters // incorrectly, either silently deleting them, or treating them as line endings. text = String(text); cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } // In the second stage, we run the text against regular expressions that look // for non-JSON patterns. We are especially concerned with '()' and 'new' // because they can cause invocation, and '=' because it can cause mutation. // But just to be safe, we want to reject all unexpected forms. // We split the second stage into 4 regexp operations in order to work around // crippling inefficiencies in IE's and Safari's regexp engines. First we // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we // replace all simple value tokens with ']' characters. Third, we delete all // open brackets that follow a colon or comma or that begin the text. Finally, // we look to see that the remaining characters are only whitespace or ']' or // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. if (/^[\],:{}\s]*$/ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // In the third stage we use the eval function to compile the text into a // JavaScript structure. The '{' operator is subject to a syntactic ambiguity // in JavaScript: it can begin a block or an object literal. We wrap the text // in parens to eliminate the ambiguity. j = eval('(' + text + ')'); // In the optional fourth stage, we recursively walk the new structure, passing // each name/value pair to a reviver function for possible transformation. return typeof reviver === 'function' ? walk({'': j}, '') : j; } // If the text is not JSON parseable, then a SyntaxError is thrown. throw new SyntaxError('JSON.parse'); }; } }()); /* end: /SEUILibrary/hightech-portal/js/commonScripts/json2.js(17530) */ /* start: /ISS_Static/WW/site/scripts/windowprops.js (cachekey: [])*/ function windowprops() { this.initdomain = document.domain; this.getPropertyArray = getPropertyArray; this.getProperty = getWindowProperty; this.setProperty = setWindowProperty; } function getPropertyArray() { var proparray = window.name.split("#"); return proparray; } function setWindowProperty(wp, wv) { //check domain in order to prevent cross domain scripting if(document.domain == this.initdomain) { var proparray = this.getPropertyArray(); var currentindex = proparray.indexOf(wp); if(currentindex == -1) { proparray[proparray.length] = wp; proparray[proparray.length] = wv; } else { proparray[currentindex] = wp; proparray[currentindex+1] = wv; } var newproparray = proparray.join("#"); window.name = newproparray; } } function getWindowProperty(wp) { if(document.domain == this.initdomain) { var proparray = this.getPropertyArray(); var currentindex = proparray.indexOf(wp); if(currentindex >= 0) { return proparray[currentindex+1]; } else { return null; } } else { return null; } } if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(elt /*, from*/) { var len = this.length; var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from); if (from < 0) from += len; for (; from < len; from++) { if (from in this && this[from] === elt) return from; } return -1; }; } var wpinstance = null; function getWindowPropInstance() { if(wpinstance != null) { return wpinstance; } else { wpinstance = new windowprops(); return wpinstance; } } /* end: /ISS_Static/WW/site/scripts/windowprops.js(1758) */ /* start: /ISS_Static/WW/site/scripts/owv3/footer-dry.js (cachekey: [])*/ //globals var userChoice = true; // sentinel to guard user choice $(function(){ //update flag on page load /**/ var $flag = $("meta[name='Lenovo.Country']").attr("content"); if ($flag === null || typeof $flag === "undefined"){ //DO OPTION $flag = $("#countrySelector option[selected]").attr("cc"); if ($flag === null || typeof $flag === "undefined") { console.log("CC not available, parsing URL string"); //do purl // or do JSLT tag? } } var $flagClass = "flag-" + $flag, $trustClass = "trust-" + $flag; $(".countrySelector-flag").addClass($flagClass); // bugzilla 1826 $("#truste").addClass($trustClass); //column behavior var $thisList, $otherList, $allFooterLists = $(".footer-navigation-links-list ul"), $allFooterHeaders = $(".footer-navigation-links-list h3"), $row1FooterLists, $row1FooterHeaders, $row2FooterLists, $row2FooterHeaders, $thisIndex, tallestList = 0, maxList = 0, rowsShown = [true, true], listsShown = false; // default for medium, large is open //find tallest list and max list Number $allFooterLists.each(function(index){ if($(this).outerHeight() > tallestList){ tallestList = $(this).outerHeight(); } }); maxList = $allFooterLists.length; $(".footer-navigation-links > ul").addClass("footer-navigation-column-" + maxList); if (maxList === 4){ $row1FooterLists = $allFooterLists.slice(0,2); $row1FooterHeaders = $allFooterHeaders.slice(0,2); $row2FooterLists = $allFooterLists.slice(2,$allFooterHeaders.length); $row2FooterHeaders = $allFooterHeaders.slice(2,$allFooterHeaders.length); } else if (maxList === 3){ $row1FooterLists = $allFooterLists.slice(0,3); $row1FooterHeaders = $allFooterHeaders.slice(0,3); } else if (maxList === 2){ $row1FooterLists = $allFooterLists.slice(0,2); $row1FooterHeaders = $allFooterHeaders.slice(0,2); } else if (maxList === 1){ $row1FooterLists = $allFooterLists.slice(0,1); $row1FooterHeaders = $allFooterHeaders.slice(0,1); } else if (maxList === 5){ $row1FooterLists = $allFooterLists.slice(0,3); $row1FooterHeaders = $allFooterHeaders.slice(0,3); $row2FooterLists = $allFooterLists.slice(3,$allFooterHeaders.length); $row2FooterHeaders = $allFooterHeaders.slice(3,$allFooterHeaders.length); } else if (maxList === 6){ $row1FooterLists = $allFooterLists.slice(0,3); $row1FooterHeaders = $allFooterHeaders.slice(0,3); $row2FooterLists = $allFooterLists.slice(3,$allFooterHeaders.length); $row2FooterHeaders = $allFooterHeaders.slice(3,$allFooterHeaders.length); } //on load check for small if small, then hide lists if (viewport().width < 560) { listsShown = true; listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); $("#truste a").removeClass("footer-icons-truste-logo").addClass("footer-icons-m-truste-logo"); } else{ $allFooterHeaders.addClass("footer-nav-list-open"); } listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); //check for resize events $(window).resize(function(){ $thisIndex = -1; //represents resize Event to prevent false toggles //headerCollapse($allFooterHeaders,$allFooterLists); if (typeof $row1FooterHeaders != "undefined"){ if(($row1FooterHeaders).hasClass("footer-nav-list-open")){ ($row1FooterHeaders).addClass("footer-nav-list-collapsed").removeClass("footer-nav-list-open"); animationToggle($row1FooterLists); listsShown = true; } } if (typeof $row2FooterHeaders != "undefined"){ if(($row2FooterHeaders).hasClass("footer-nav-list-open")){ ($row2FooterHeaders).addClass("footer-nav-list-collapsed").removeClass("footer-nav-list-open"); animationToggle($row2FooterLists); listsShown = true; } } if (viewport().width < 560 ){ $("#truste a").removeClass("footer-icons-truste-logo").addClass("footer-icons-m-truste-logo"); } else if (viewport().width >= 560){ // medium and large $("#truste a").removeClass("footer-icons-m-truste-logo").addClass("footer-icons-truste-logo"); } if (viewport().width < 560 ){ //small listsShown = true; //force all closed listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 6 && viewport().width > 1216 && listsShown === false){ // single row listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 5 && viewport().width > 1023 && listsShown === false){ //single row listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 4 && viewport().width > 865 && listsShown === false){ //single row listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 3 && viewport().width > 560 && listsShown === false){ //single row listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 2 && viewport().width > 560 && listsShown === false){ //single row listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 1 && viewport().width > 560 && listsShown === false){ //single row listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } }); // Click functionality $(".footer-navigation-links-title").click(function(){ //cache this ul $thisList = $(this).siblings("ul"); $thisIndex = $(this).parent().index(); // used for 2row function if(maxList === 6 && viewport().width > 1216){ // single row userChoice = !userChoice; // click tracker listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 6 && viewport().width <= 1216 && viewport().width > 560){ // double row userChoice = !userChoice; // click tracker rowsShown = lists2RowController($row1FooterLists, $row1FooterHeaders, $row2FooterLists, $row2FooterHeaders, rowsShown, $thisIndex, maxList); } else if(maxList === 5 && viewport().width > 1023){ //single row userChoice = !userChoice; // click tracker listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 5 && viewport().width <= 1023 && viewport().width > 560){ // double row userChoice = !userChoice; // click tracker rowsShown = lists2RowController($row1FooterLists, $row1FooterHeaders, $row2FooterLists, $row2FooterHeaders, rowsShown, $thisIndex, maxList); } else if(maxList === 4 && viewport().width > 865){ //single row userChoice = !userChoice; // click tracker listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 3 && viewport().width > 560){ // single row - no double row for three column userChoice = !userChoice; // click tracker listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 2 && viewport().width > 560){ // single row - no double row for three column userChoice = !userChoice; // click tracker listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 1 && viewport().width > 560){ // single row - no double row for three column userChoice = !userChoice; // click tracker listsShown = listsController($allFooterLists, $allFooterHeaders, listsShown); } else if(maxList === 4 && viewport().width <= 865 && viewport().width > 560){ // double row userChoice = !userChoice; // click tracker rowsShown = lists2RowController($row1FooterLists, $row1FooterHeaders, $row2FooterLists, $row2FooterHeaders, rowsShown, $thisIndex, maxList); } else if (viewport().width < 560){ //small //show this list if ($(this).hasClass("footer-nav-list-collapsed")) { //close any open lists $allFooterHeaders.each(function(index){ if ($(this).hasClass("footer-nav-list-open")){ $otherList = $(this).siblings("ul"); animationToggle($otherList); classToggleClosed($(this)); } }); animationToggle($thisList); classToggleOpen($(this)); } //hide this list else if ($(this).hasClass("footer-nav-list-open")) { animationToggle($thisList); classToggleClosed($(this)); } } }); }); //DRY Functions function animationToggle(thisList){ thisList.animate({ opacity: "toggle", height: "toggle" }, 500, function() { // Animation complete. }); } function classToggleOpen(thisList){ thisList.removeClass("footer-nav-list-collapsed").addClass("footer-nav-list-open"); } function classToggleClosed(thisList){ thisList.addClass("footer-nav-list-collapsed").removeClass("footer-nav-list-open"); } function classToggle(thisList) { if (thisList.hasClass("footer-nav-list-open")){ thisList.addClass("footer-nav-list-collapsed").removeClass("footer-nav-list-open"); } else{ thisList.removeClass("footer-nav-list-collapsed").addClass("footer-nav-list-open"); } } // single Row Controller function listsController(allFooterLists, allFooterHeaders, listsShown){ if (viewport().width >= 560) { if (!listsShown && userChoice) { //show lists animationToggle(allFooterLists); classToggle(allFooterHeaders); listsShown = true; } else if (listsShown && !userChoice) { //hide all lists animationToggle(allFooterLists); classToggle(allFooterHeaders); listsShown = false; } } else if (listsShown && viewport().width < 560) { // mobile override allFooterLists.hide(); classToggleClosed(allFooterHeaders); listsShown = false; } return listsShown; } // 2 Row Controller function lists2RowController($row1FooterLists, $row1FooterHeaders, $row2FooterLists, $row2FooterHeaders, rowsShown, $thisIndex, maxList ){ if (maxList == 4) { if($thisIndex == 0 || $thisIndex == 1) { //row1 animationToggle($row1FooterLists); classToggle($row1FooterHeaders); } else { //row2 animationToggle($row2FooterLists); classToggle($row2FooterHeaders); } } else if (maxList == 3) { if($thisIndex == 0 || $thisIndex == 1) { //row1 animationToggle($row1FooterLists); classToggle($row1FooterHeaders); } else { //row2 animationToggle($row2FooterLists); classToggle($row2FooterHeaders); } } else if (maxList == 5 || maxList == 6) { if($thisIndex == 0 || $thisIndex == 1 || $thisIndex == 2 ) { //row1 animationToggle($row1FooterLists); classToggle($row1FooterHeaders); } else { //row2 animationToggle($row2FooterLists); classToggle($row2FooterHeaders); } } return rowsShown; } /*-------------Fix to get viewport size instead of window to match CSS media queries---------*/ /*---From http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript---*/ function viewport() { var e = window, a = 'inner'; if (!('innerWidth' in window )) { a = 'client'; e = document.documentElement || document.body; } return { width : e[ a+'Width' ] , height : e[ a+'Height' ] }; } /* end: /ISS_Static/WW/site/scripts/owv3/footer-dry.js(12615) */ /* start: /SEUILibrary/hightech-portal/js/commonScripts/json2xml.js (cachekey: [])*/ /* This work is licensed under Creative Commons GNU LGPL License. License: http://creativecommons.org/licenses/LGPL/2.1/ Version: 0.9/modified to conform to commonjs modules pattern Author: Stefan Goessner/2006 Web: http://goessner.net/ */ var json2xml = (typeof exports === 'undefined')? {} : exports; // like commonjs (function() { json2xml.convert = function(o) { var toXml = function(v, name, ind) { var xml = ""; if (v instanceof Array) { for (var i=0, n=v.length; i\n" : "/>"; if (hasChild) { for (var m in v) { if (m == "#text") xml += makeSafe(v[m]); else if (m == "#cdata") xml += ""; else if (m.charAt(0) != "@") xml += toXml(v[m], m, ind+"\t"); } xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "\n"; } } else { // added special-character transform, but this needs to be better handled [micmath] xml += ind + "<" + name + ">" + makeSafe(v.toString()) + "\n"; } return xml; }, xml=""; for (var m in o) { xml += toXml(o[m], m, ""); } return xml; } function lines(str) { // normalise line endings, all in file will be unixy str = str.replace(/\r\n/g, '\n'); return str; } function makeSafe(str) { // xml special charaters str = str.replace(/