diff --git a/.gitignore b/.gitignore index 141e1d4dc..a8abf019b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,10 @@ .project .metadata bin/ -/utilities/proxy/node_modules/ +/utilities/nodeproxy/node_modules/ +/utilities/nodeproxy/jt.key +/utilities/nodeproxy/www-spork* +/utilities/nodeproxy/www.spork* tmp/ proxy/ *extensions/_notes/ diff --git a/LICENSE.txt b/LICENSE.txt index d0f9348ce..2c13d1e3b 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013 anyCommerce.com +Copyright (c) 2014 Zoovy, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,4 +19,3 @@ 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. - diff --git a/README b/README index 3eb3213ee..6ff40fc60 100755 --- a/README +++ b/README @@ -1,18 +1,25 @@ +AnyCommerce Framework - v.201405 -Zoovy/AnyCommerce MVC JQuery Developer Framework - -Rich Internet Application, Model View Controller created using jQuery for creating standalone or -pluggable shopping applications that connect to the Zoovy e-Commerce Platform. - -WIKI Documentation: - https://github.com/zoovy/AnyCommerce-Development/wiki +Description: +Rich Internet Application, Model View Controller created using jQuery for creating awesome shopping applications that +connects to the CommerceRack Backend-As-A-Service (BAAS) via a JSON/REST API. Official Repository: - https://github.com/zoovy/AnyCommerce-Development - -API Calls Input/Output Reference: - http://www.zoovy.com/webdoc/index.cgi?VERB=DOC&DOCID=51609 + https://github.com/Commercerack/anycommerce Examples are stored in examples sub-directory. Extensions are stored in the extensions sub-directory. +MIT License stored in license.txt + +------------------------------------------------------------------------------- + +Hey Developers!! + +When you fork this REPO - please write any project specific notes such as the URL's to the podio/basecamp project along +with usability instructions into this file. + +Custom functionality should be documented how it is /supposed to work/ here, along with contact info for who is the +responsible party for maintenance. + +Thanks! diff --git a/admin_logout.html b/admin_logout.html index e9b1998bb..7b9e037f1 100644 --- a/admin_logout.html +++ b/admin_logout.html @@ -6,13 +6,41 @@ + + + + + + - +
-

Thank you!


-

You are now logged out


+

Thank you!

+

You are now logged out

+ +

+

click here to log in

diff --git a/app-acreate.html b/app-acreate.html index cc71013d8..2f5638445 100644 --- a/app-acreate.html +++ b/app-acreate.html @@ -26,7 +26,7 @@ var app = {vars:{ /////////////////////////////////\ - "release":"201344.a", ///|> Increment this with each change. model version followed by each deployed update getting a new letter in the alphabet. + "release":"201405.a", ///|> Increment this with each change. model version followed by each deployed update getting a new letter in the alphabet. ////////////////////////////////// "thisSessionIsAdmin": true, "_clientid":"admin", @@ -63,8 +63,8 @@ var tmp = new zController(app); //instantiate wiki parser. // myCreole = new Parse.Simple.Creole(); - app.model.addExtensions([{'namespace':'acreate','filename':'app-acreate/extension.js','callback':'initExtension'}]); - app.u.handleEventDelegation($(document.body)); + _app.model.addExtensions([{'namespace':'acreate','filename':'app-acreate/extension.js','callback':'initExtension'}]); + _app.u.addEventDelegation($(document.body)); }); diff --git a/app-acreate/extension.js b/app-acreate/extension.js index e0db226d3..596a37113 100644 --- a/app-acreate/extension.js +++ b/app-acreate/extension.js @@ -53,6 +53,7 @@ var acreate = function() { onSuccess : function() { app.u.dump('BEGIN lookup.initExtension.onSuccess '); //the zoovy branding is in place by default. override if on anycommerce.com OR if an anycommerce URI param is present (for debugging) +// ## TODO -> need a better way to handle Zoovy vs non-zoovy content. if(document.domain && document.domain.toLowerCase().indexOf('anycommerce') > -1) { app.u.dump(" -> Treat as anycommerce"); $('.logo img').attr('src','app-admin/images/anycommerce_logo-173x30.png'); @@ -279,7 +280,7 @@ var acreate = function() { else { //kewl. found a match. now show them their logo, a link and a countdown till auto-redirect occurs. if(app.data[rd.datapointer].adminURL) { - window.location = app.data[rd.datapointer].adminURL+"?fromLookup="+app.u.unixNow(); //timestamp is passed so it can be used on landing page to determine if the user bookmarked w/ this param in the url + window.location = app.data[rd.datapointer].adminURL+"?fromLookup="+app.u.epochNow(); //timestamp is passed so it can be used on landing page to determine if the user bookmarked w/ this param in the url } else { $ele.prepend("
We found a match on the domain, but no admin URL. Please contact your provider for assistance.
"); diff --git a/app-acreate/styles.css b/app-acreate/styles.css index 74f2dc7ea..ea3adb610 100644 --- a/app-acreate/styles.css +++ b/app-acreate/styles.css @@ -48,11 +48,3 @@ img {border:0px;} .alignedInputs input[type=url], .alignedInputs input[type=text] {width:55%; } /* slighly less than 100% is used for label/input so room for toolTip or linkDoc is available */ -.treatAsthreePLSprite, .threePLSprite {height:30px; width:162px; display:block; float:left; margin:0 4px 4px 0; text-align:left;} -.threePLSprite {background-image:url(third_party_logins-176x276.png); background-repeat:no-repeat;} -.twitter {background-position:0 0;} -.facebook {background-position:0 -48px;} -.linkedin {background-position:0 -93px;} -.yahoo {background-position:0 -141px;} -.openid {background-position:0 -188px;} -.google {background-position:0 -235px;} \ No newline at end of file diff --git a/app-admin-init.js b/app-admin-init.js index 6625633f9..23a83797e 100644 --- a/app-admin-init.js +++ b/app-admin-init.js @@ -1,172 +1,285 @@ -var app = app || {vars:{},u:{}}; //make sure app exists. -app.rq = app.rq || []; //ensure array is defined. rq = resource queue. - - - -app.rq.push(['extension',0,'admin','extensions/admin/extension.js','initExtension']); -app.rq.push(['extension',0,'admin_prodEdit','extensions/admin/product_editor.js']); -app.rq.push(['extension',0,'admin_orders','extensions/admin/orders.js']); -app.rq.push(['extension',0,'admin_launchpad','extensions/admin/launchpad.js']); +adminApp.rq.push(['extension',0,'admin','extensions/admin/extension.js','initExtension']); +adminApp.rq.push(['extension',0,'admin_prodedit','extensions/admin/product_editor.js']); +adminApp.rq.push(['extension',0,'admin_orders','extensions/admin/orders.js']); +adminApp.rq.push(['extension',0,'admin_sites','extensions/admin/sites.js']); +//adminApp.rq.push(['extension',0,'admin_launchpad','extensions/admin/launchpad.js']); //these can be loaded later because none of them are required for a page to load. //this will change going forward. -app.rq.push(['extension',1,'store_prodlist','extensions/store_prodlist.js']); -app.rq.push(['extension',1,'store_navcats','extensions/store_navcats.js']); -app.rq.push(['extension',1,'store_search','extensions/store_search.js']); -app.rq.push(['extension',1,'store_cart','extensions/store_cart.js']); -app.rq.push(['extension',1,'store_product','extensions/store_product.js']); - - +adminApp.rq.push(['extension',1,'store_prodlist','extensions/store_prodlist.js']); +adminApp.rq.push(['extension',1,'store_navcats','extensions/store_navcats.js']); +adminApp.rq.push(['extension',1,'store_search','extensions/store_search.js']); +adminApp.rq.push(['extension',1,'store_product','extensions/store_product.js']); -//app.rq.push(['extension',0,'cco','extensions/cart_checkout_order.js']); -//app.rq.push(['extension',0,'orderCreate','extensions/checkout/extension.js']); -app.rq.push(['extension',0,'store_checkout','extensions/store_checkout.js']); -app.rq.push(['extension',0,'convertSessionToOrder','extensions/admin/order_create.js']); +adminApp.rq.push(['extension',0,'cco','extensions/cart_checkout_order.js']); +adminApp.rq.push(['extension',0,'order_create','extensions/checkout/extension.js']); +adminApp.rq.push(['extension',0,'cart_message','extensions/cart_message/extension.js']); -app.rq.push(['extension',0,'admin_support','extensions/admin/support.js']); -app.rq.push(['extension',0,'admin_tools','extensions/admin/tools.js']); -app.rq.push(['extension',0,'admin_navcats','extensions/admin/navcats.js']); -app.rq.push(['extension',0,'admin_task','extensions/admin/task.js']); -app.rq.push(['extension',0,'admin_templateEditor','extensions/admin/template_editor.js']); -app.rq.push(['extension',0,'admin_syndication','extensions/admin/syndication.js']); //needs to be in pass 0 for linkFrom (links from marketplaces) +adminApp.rq.push(['extension',0,'admin_support','extensions/admin/support.js']); +adminApp.rq.push(['extension',0,'admin_tools','extensions/admin/tools.js']); +adminApp.rq.push(['extension',0,'admin_navcats','extensions/admin/navcats.js']); +adminApp.rq.push(['extension',0,'admin_blast','extensions/admin/blast.js']); +adminApp.rq.push(['extension',0,'admin_task','extensions/admin/task.js']); +adminApp.rq.push(['extension',0,'admin_template','extensions/admin/template_editor.js']); +adminApp.rq.push(['extension',0,'admin_marketplace','extensions/admin/marketplace.js']); //needs to be in pass 0 for linkFrom (links from marketplaces) -app.rq.push(['extension',0,'admin_config','extensions/admin/config.js']); -app.rq.push(['extension',0,'admin_reports','extensions/admin/reports.js']); -app.rq.push(['extension',0,'admin_batchJob','extensions/admin/batchjob.js']); -app.rq.push(['extension',0,'admin_customer','extensions/admin/customer.js']); -app.rq.push(['extension',0,'admin_wholesale','extensions/admin/wholesale.js']); -app.rq.push(['extension',1,'admin_user','extensions/admin/user.js']); -app.rq.push(['extension',1,'admin_medialib','extensions/admin/medialib.js']); //do NOT set to zero. causes a script issue. -app.rq.push(['extension',0,'admin_trainer','extensions/admin/trainer.js']); //load in pass 0 for local testing. - - -app.rq.push(['extension',0,'tools_animation','extensions/tools_animation.js', function(){ +adminApp.rq.push(['extension',0,'admin_config','extensions/admin/config.js']); +adminApp.rq.push(['extension',0,'admin_reports','extensions/admin/reports.js']); +adminApp.rq.push(['extension',0,'admin_batchjob','extensions/admin/batchjob.js']); +adminApp.rq.push(['extension',0,'admin_customer','extensions/admin/customer.js']); +adminApp.rq.push(['extension',0,'admin_wholesale','extensions/admin/wholesale.js']); +adminApp.rq.push(['extension',0,'admin_user','extensions/admin/user.js']); +adminApp.rq.push(['extension',0,'admin_medialib','extensions/admin/medialib.js']); //do NOT set to zero. causes a script issue. +adminApp.rq.push(['extension',0,'admin_trainer','extensions/admin/trainer.js']); //load in pass 0 for local testing. + +adminApp.rq.push(['extension',0,'tools_animation','extensions/tools_animation.js', function(){ $('.mhTabsContainer [data-animation]').each(function(){ var args = $(this).attr('data-animation'); var anim = args.split('?')[0]; - var params = app.u.kvp2Array(args.split('?')[1]); - app.ext.tools_animation.u.loadAnim($(this),anim,params); + var params = adminApp.u.kvp2Array(args.split('?')[1]); + adminApp.ext.tools_animation.u.loadAnim($(this),anim,params); }); }]); //required for init. don't change from 0. -app.rq.push(['script',0,app.vars.baseURL+'model.js']); //'validator':function(){return (typeof zoovyModel == 'function') ? true : false;}} -app.rq.push(['script',0,app.vars.baseURL+'includes.js']); //','validator':function(){return (typeof handlePogs == 'function') ? true : false;}}) -app.rq.push(['script',0,app.vars.baseURL+'controller.js']); +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'includes.js']); //','validator':function(){return (typeof handlePogs == 'function') ? true : false;}}) +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'resources/jsonpath.0.8.0.js']); //used pretty early in process.. +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'resources/tlc.js']); //used pretty early in process.. +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'resources/anycontent.js']); +//once peg is loaded, need to retrieve the grammar file. Order is important there. This will validate the file too. +adminApp.u.loadScript(adminApp.vars.baseURL+'resources/peg-0.8.0.js',function(){ + adminApp.model.getGrammar(adminApp.vars.baseURL+"resources/pegjs-grammar-20140203.pegjs"); + }); // ### TODO -> callback on RQ.push wasn't getting executed. investigate. -app.rq.push(['script',1,app.vars.baseURL+'resources/jquery.ui.jeditable.js']); //used for making text editable (customer address). non-essential. loaded late. used in orders. -app.rq.push(['script',0,app.vars.baseURL+'extensions/admin/resources/highcharts-3.0.1/highcharts.js']); //used for KPI +adminApp.rq.push(['script',1,adminApp.vars.baseURL+'resources/jquery.ui.jeditable.js']); //used for making text editable (customer address). non-essential. loaded late. used in orders. +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'app-admin/resources/highcharts-3.0.1/highcharts.js']); //used for KPI -app.rq.push(['script',0,'https://crypto-js.googlecode.com/files/2.5.3-crypto-md5.js']); //used for authentication and in various other places. +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'resources/crypto-md5-2.5.3.js']); //used for authentication and in various other places. //have showLoading as early as possible. pretty handy feature. used everywhere. -app.rq.push(['script',0,app.vars.baseURL+'resources/jquery.showloading-v1.0.jt.js']); +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'resources/jquery.showloading-v1.0.jt.js']); //these are resources that are not currently used. -//app.rq.push(['script',0,app.vars.baseURL+'resources/jquery.mousewheel-3.0.6.min.js']);//used in the launchpad. needed early. -//app.rq.push(['script',1,app.vars.baseURL+'resources/jquery.fullscreen-1.2.js']); //used in template editor. will likely get used more. +//adminApp.rq.push(['script',0,adminApp.vars.baseURL+'resources/jquery.mousewheel-3.0.6.min.js']);//used in the launchpad. needed early. +//adminApp.rq.push(['script',1,adminApp.vars.baseURL+'resources/jquery.fullscreen-1.2.js']); //used in template editor. will likely get used more. //used in campaigns. probably get used more. allows for time selection in datepicker. -app.rq.push(['css',1,app.vars.baseURL+'resources/jquery-ui-timepicker-addon.css']); -app.rq.push(['script',1,app.vars.baseURL+'resources/jquery-ui-timepicker-addon.js']); +adminApp.rq.push(['css',1,adminApp.vars.baseURL+'resources/jquery-ui-timepicker-addon.css']); +adminApp.rq.push(['script',1,adminApp.vars.baseURL+'resources/jquery-ui-timepicker-addon.js']); // required for building/restoring ebay item specifics from @RECOMMENDATIONS list + 'ebay:itemspecifics' -app.rq.push(['script',1,app.vars.baseURL+'extensions/admin/resources/jquery.ebay-specifics-form.js']); +adminApp.rq.push(['script',1,adminApp.vars.baseURL+'app-admin/resources/jquery.ebay-specifics-form.js']); //anycommerce plugins, such as anycontent, anytable, anycb, etc. -app.rq.push(['script',0,app.vars.baseURL+'resources/jquery.ui.anyplugins.js']); -app.rq.push(['css',1,app.vars.baseURL+'resources/anyplugins.css']); +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'resources/jquery.ui.anyplugins.js']); +adminApp.rq.push(['css',1,adminApp.vars.baseURL+'resources/anyplugins.css']); -app.rq.push(['script',0,app.vars.baseURL+'resources/jquery.ui.qrcode-0.7.0.js']); +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'resources/jquery.ui.qrcode-0.7.0.js']); // jQuery-contextMenu - http://medialize.github.com/jQuery-contextMenu/ used in orders. -app.rq.push(['css',1,app.vars.baseURL+'extensions/admin/resources/jquery.contextMenu.css']); -app.rq.push(['script',0,app.vars.baseURL+'extensions/admin/resources/jquery.contextMenu.js']); //must be in first pass in case orders is the landing page. -app.rq.push(['script',1,app.vars.baseURL+'extensions/admin/resources/jquery.ui.position.js']); +adminApp.rq.push(['css',1,adminApp.vars.baseURL+'app-admin/resources/jquery.contextMenu.css']); +adminApp.rq.push(['script',0,adminApp.vars.baseURL+'app-admin/resources/jquery.contextMenu.js']); //must be in first pass in case orders is the landing page. +adminApp.rq.push(['script',1,adminApp.vars.baseURL+'app-admin/resources/jquery.ui.position.js']); //used for image enlargement in template chooser (in syndication but suspect it will be in email, newsletter, app, etc soon enough) -app.rq.push(['script',1,app.vars.baseURL+'resources/load-image.min.js']); //in zero pass in case product page is first page. -app.rq.push(['script',1,app.vars.baseURL+'resources/jquery.image-gallery.jt.js']); //in zero pass in case product page is first page. +adminApp.rq.push(['script',1,adminApp.vars.baseURL+'resources/load-image.min.js']); //in zero pass in case product page is first page. +adminApp.rq.push(['script',1,adminApp.vars.baseURL+'resources/jquery.image-gallery.jt.js']); //in zero pass in case product page is first page. -//app.rq.push(['script',0,app.vars.baseURL+'extensions/admin/resources/jquery.ui.touch-punch.min.js']); -//app.rq.push(['script',0,app.vars.baseURL+'extensions/admin/resources/jquery.shapeshift.js']); +//adminApp.rq.push(['script',0,adminApp.vars.baseURL+'app-admin/resources/jquery.ui.touch-punch.min.js']); +//adminApp.rq.push(['script',0,adminApp.vars.baseURL+'app-admin/resources/jquery.shapeshift.js']); +//gets executed from app-admin.html as part of controller init process. +//progress is an object that will get updated as the resources load. /* -This function is overwritten once the controller is instantiated. -Having a placeholder allows us to always reference the same messaging function, but not impede load time with a bulky error function. +'passZeroResourcesLength' : [INT], +'passZeroResourcesLoaded' : [INT], +'passZeroTimeout' : null //the timeout instance running within loadResources that updates this object. it will run indef unless clearTimeout run here OR all resources are loaded. + */ -app.u.throwMessage = function(m) { - alert(m); +adminApp.u.showProgress = function(progress) { + function showProgress(attempt) { +// dump(" -> passZeroResourcesLength: "+progress.passZeroResourcesLength+" and progress.passZeroResourcesLoaded: "+progress.passZeroResourcesLoaded); + if(progress.passZeroResourcesLength == progress.passZeroResourcesLoaded) { + + //All pass zero resources have loaded. + //the app will handle hiding the loading screen. + } + else if(attempt > 150) { + //hhhhmmm.... something must have gone wrong. + clearTimeout(progress.passZeroTimeout); //end the resource loading timeout. + } + else { + var percentPerInclude = (100 / progress.passZeroResourcesLength); + var percentComplete = Math.round(progress.passZeroResourcesLength * percentPerInclude); //used to sum how many includes have successfully loaded. +// dump(" -> percentPerInclude: "+percentPerInclude+" and percentComplete: "+percentComplete); + $('#appPreViewProgressBar').val(percentComplete); + $('#appPreViewProgressText').empty().append(percentComplete+"% Complete"); + attempt++; + setTimeout(function(){showProgress(attempt);},200); + } + } + showProgress(0) } -app.u.howManyPassZeroResourcesAreLoaded = function(debug) { - var L = app.vars.rq.length; - var r = 0; //what is returned. total # of scripts that have finished loading. - for(var i = 0; i < L; i++) { - if(app.vars.rq[i][app.vars.rq[i].length - 1] === true) { - r++; +//don't execute script till both jquery AND the dom are ready. + +adminApp.cmr.push(['cart.orderCreate',function(message,$context){ + if(message.who != 'ADMIN') { + //cart was checked out by someone else. + //leave the dialog open so communication can continue, but pull the cart from the session. and 'lock' the edit cart button. + $("button[data-app-role='cartEditButton']").button('disable'); + adminApp.model.removeCartFromSession($context.data('cartid')); + dump(" -------> cart.orderCreate cartMessage received. Cart dropped: "+$context.data('cartid')); + } + }]); + +adminApp.cmr.push(["view",function(message,$context){ + var $history = $("[data-app-role='messageHistory']",$context); + var $o = "

"+message.FROM+"<\/span>sent page view:
"; + if(message.vars && message.vars.pageType) { +// dump(' -> pageType is set to: '+message.vars.pageType); + switch(message.vars.pageType) { + case 'product': + if(message.vars.pid) { + $o += 'product: '+message.vars.pid+' has been added to the product task list.' + adminApp.ext.admin_prodedit.u.addProductAsTask({'pid':message.vars.pid,'tab':'product','mode':'add'}); + } + else {$o += 'Page type set to product but no pid specified.'} + break; + case 'homepage': + $o += 'homepage'; + break; + case 'category': + if(message.vars.navcat) { + $o += 'category: '+message.vars.navcat; + if(message.vars.domain) {$o.addClass('lookLikeLink').on('click',function(){ + window.open(message.vars.domain+"/category/"+message.vars.navcat+"/"); + })} + } + else {$o += 'Page type set to category but no navcat specified.'} + break; + + case 'search': + if(message.vars.keywords) {} + else {$o += 'Page type set to search but no keywords specified.'} + break; + + case 'company': + if(message.vars.show) {} + else {$o += 'Page type set to company but show not specified.'} + break; + + case 'customer': + if(message.vars.show) {} + else {$o += 'Page type set to customer but show not specified.'} + break; + + default: + $o += 'unknown page type: '+message.vars.pageType+' (console contains more detail)'; + dump("Unrecognized pageType in cart message.vars. vars follow:"); dump(message.vars); } - if(debug) {app.u.dump(" -> "+i+": "+app.vars.rq[i][2]+": "+app.vars.rq[i][app.vars.rq[i].length -1]);} } - return r; - } + else { + $o += 'unspecified page type or no vars set in message. (console contains more detail)'; + dump("Unspecified pageType in cart message.vars. vars follow:"); dump(message.vars); + } + $o += "
<\/p>"; + $history.append($o); + $history.parent().scrollTop($history.height()); + }]); -//gets executed once controller.js is loaded. -//check dependencies and make sure all other .js files are done, then init controller. -//function will get re-executed if not all the scripts in app.vars.scripts pass 1 are done loading. -//the 'attempts' var is incremented each time the function is executed. +adminApp.router.addAlias('404',function(v) { + $('#globalMessaging').anymessage({'message':'No route has been specified for '+v.hash,'gMessage':true,'errtype':'apperr'}); + dump(" -> v from 404 alias:"); dump(v); + }); -app.u.initMVC = function(attempts){ -// app.u.dump("app.u.initMVC activated ["+attempts+"]"); - var includesAreDone = true; -//what percentage of completion a single include represents (if 10 includes, each is 10%). - var percentPerInclude = (100 / app.vars.rq.length); - var resourcesLoaded = app.u.howManyPassZeroResourcesAreLoaded(); - var percentComplete = Math.round(resourcesLoaded * percentPerInclude); //used to sum how many includes have successfully loaded. +adminApp.router.appendHash({'type':'match','route':'/biz/vstore*','callback':function(v){ +// _app.u.dump(" -> Welcome to legacy compat mode."); +// console.dir(v); + adminApp.model.fetchAdminResource(v.hash.substr(2),{'tab':adminApp.ext.admin.vars.tab,'targetID':adminApp.ext.admin.vars.tab+'Content'}); + }}); - $('#appPreViewProgressBar').val(percentComplete); - $('#appPreViewProgressText').empty().append(percentComplete+"% Complete"); +adminApp.router.appendHash({'type':'exact','route':'dashboard','callback':function(v){ + adminApp.ext.admin.a.showDashboard(); //will load itself into 'home' content area and bring that into focus. + }}); +adminApp.router.appendHash({'type':'exact','route':'product','callback':function(v){ + adminApp.ext.admin_prodedit.a.showProductManager(v.hashParams); + }}); - if(resourcesLoaded == app.vars.rq.length) { -//instantiate controller. handles all logic and communication between model and view. -//passing in app will extend app so all previously declared functions will exist in addition to all the built in functions. -//tmp is a throw away variable. app is what should be used as is referenced within the mvc. - app.vars.rq = null; //to get here, all these resources have been loaded. nuke record to keep DOM clean and avoid any duplication. note this is NOT app.rq - var tmp = new zController(app); -//instantiate wiki parser. - myCreole = new Parse.Simple.Creole(); - - } - else if(attempts > 100) { - app.u.dump("WARNING! something went wrong in init.js"); - //this is 10 seconds of trying. something isn't going well. - $('.appMessaging').empty().append("

Not all resources were able to be loaded.

Several attempts were made to load the store but some necessary files were not found or could not load. We apologize for the inconvenience. This is most likely due to a slow computer and/or slow internet connection<\/b>. Please try 'refresh' and see if that helps.
If the error persists, please contact the site administrator
- dev: see console.

"); - app.u.howManyPassZeroResourcesAreLoaded(true); - } - else { - setTimeout("app.u.initMVC("+(attempts+1)+")",250); - } +adminApp.router.appendHash({'type':'exact','route':'mediaLibraryManageMode','callback':function(v){ + adminApp.ext.admin_medialib.a.showMediaLib({'mode':'manage'}); + }}); - } +adminApp.router.appendHash({'type':'exact','route':'showPlatformInfo','callback':function(v){ + adminApp.ext.admin_support.a.showPlatformInfo({'mode':'manage'}); + }}); -//don't execute script till both jquery AND the dom are ready. -$(document).ready(function(){ - app.u.handleRQ(0); //will start loading resources and eventually init the app. + +adminApp.router.appendHash({'type':'exact','route':'logout','callback':function(v){ + adminApp.ext.admin.a.logout(); + }}); + +//will handle any clicks directly on the tabs. +adminApp.router.appendHash({'type':'match','route':'tab/{{tab}}','callback':function(v){ + adminApp.ext.admin.a.handleTabClick(v.params.tab,v.hashParams); + if(v.params.tab == 'product') { + //product page tab is 'special'. the navtab section needs to always show up. handleTabClick nukes the navTabs and the function below re-adds them. + adminApp.ext.admin_prodedit.u.handleNavTabs(); //builds the filters, search, etc menu at top, under main tabs. + } + }}); + +adminApp.router.appendHash({'type':'exact','route':'downloads','callback':function(v){ + $('#homeContent').empty(); + adminApp.ext.admin.u.bringTabIntoFocus('home'); + adminApp.ext.admin.u.bringTabContentIntoFocus($('#homeContent')); + adminApp.ext.admin.a.showDownloads($('#homeContent')); + }}); + +adminApp.router.appendHash({'type':'exact','route':'help','callback':function(v){ + $('#supportContent').empty(); + adminApp.ext.admin.u.bringTabIntoFocus('support'); + adminApp.ext.admin.u.bringTabContentIntoFocus($('#supportContent')); + adminApp.ext.admin_support.a.showHelpInterface($('#supportContent')); + }}); + + +//handles a lot of the defaults for loading native apps. More or less a 'catch'. +adminApp.router.appendHash({'type':'match','route':'ext/{{ext}}/{{a}}*','callback':function(v){ + adminApp.ext.admin.a.execApp(v.params.ext,v.params.a.split('?')[0],v.hashParams); + }}); + + +adminApp.router.appendInit({ + 'type':'regexp', + 'route': /^(.*?)\/future$/, + 'callback':function(f){ + $('#globalMessaging').anymessage({"message":"
Welcome to the future!<\/h5>

You are currently using a future (experimental) version of our interface. Here you'll find links labeled as 'alpha' and 'beta' which are a work in progress.<\/p>Alpha: here for your viewing pleasure. These links may have little or no working parts and you should avoid 'using' them (look don't touch).
Beta: These are features in the testing phase. These you can use, but may experience some errors.

Enjoy!<\/h6>","persistent":true}); + } }); +//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page. +adminApp.router.appendInit({ + 'type':'function', + 'route': function(v){ + return {'some':'value'} //returning anything but false triggers a match. + }, + 'callback':function(f){ + adminApp.router.handleHashChange(); + } + }); diff --git a/app-admin.html b/app-admin.html index f165eb124..d237792dc 100644 --- a/app-admin.html +++ b/app-admin.html @@ -4,6 +4,12 @@ Administrative Interface Login + + + + + + @@ -11,11 +17,10 @@ - - + - - - + + - - - - + + + + + - - - - - - - + @@ -103,7 +111,7 @@

One moment please while we load our app

Password Recovery - +
@@ -115,25 +123,39 @@

One moment please while we load our app

- +
-
+ +
Merchant Login - - +
+ + + +
- - - -
App Release #: ??
- - +
+ +
App Release #: ??
+
+ +
+ + +
+ +
@@ -184,84 +206,82 @@

One moment please while we load our app

- Logged in as: on + Logged in as: on
- - + +
@@ -293,7 +313,6 @@

One moment please while we load our app

-
@@ -303,6 +322,8 @@

One moment please while we load our app

+ +
@@ -373,7 +394,7 @@

One moment please while we load our app

{% } %} - +':o=e.settings.video_template_callback?e.settings.video_template_callback(a):'"}return o}function n(e){var t={};return new tinymce.html.SaxParser({validate:!1,allow_conditional_comments:!0,special:"script,noscript",start:function(e,i){if(t.source1||"param"!=e||(t.source1=i.map.movie),("iframe"==e||"object"==e||"embed"==e||"video"==e||"audio"==e)&&(t.type||(t.type=e),t=tinymce.extend(i.map,t)),"script"==e){var a=r(i.map.src);if(!a)return;t={type:"script",source1:i.map.src,width:a.width,height:a.height}}"source"==e&&(t.source1?t.source2||(t.source2=i.map.src):t.source1=i.map.src),"img"!=e||t.poster||(t.poster=i.map.src)}}).parse(e),t.source1=t.source1||t.src||t.data,t.source2=t.source2||"",t.poster=t.poster||"",t}function s(t){return t.getAttribute("data-mce-object")?n(e.serializer.serialize(t,{selection:!0})):{}}function m(e,t,i){function r(e,t){var i,r,a,o;for(i in t)if(a=""+t[i],e.map[i])for(r=e.length;r--;)o=e[r],o.name==i&&(a?(e.map[i]=a,o.value=a):(delete e.map[i],e.splice(r,1)));else a&&(e.push({name:i,value:a}),e.map[i]=a)}var a,o=new tinymce.html.Writer,c=0;return new tinymce.html.SaxParser({validate:!1,allow_conditional_comments:!0,special:"script,noscript",comment:function(e){o.comment(e)},cdata:function(e){o.cdata(e)},text:function(e,t){o.text(e,t)},start:function(e,n,s){switch(e){case"video":case"object":case"embed":case"img":case"iframe":r(n,{width:t.width,height:t.height})}if(i)switch(e){case"video":r(n,{poster:t.poster,src:""}),t.source2&&r(n,{src:""});break;case"iframe":r(n,{src:t.source1});break;case"source":if(c++,2>=c&&(r(n,{src:t["source"+c],type:t["source"+c+"mime"]}),!t["source"+c]))return;break;case"img":if(!t.poster)return;a=!0}o.start(e,n,s)},end:function(e){if("video"==e&&i)for(var n=1;2>=n;n++)if(t["source"+n]){var s=[];s.map={},n>c&&(r(s,{src:t["source"+n],type:t["source"+n+"mime"]}),o.start("source",s,!0))}if(t.poster&&"object"==e&&i&&!a){var m=[];m.map={},r(m,{src:t.poster,width:t.width,height:t.height}),o.start("img",m,!0)}o.end(e)}},new tinymce.html.Schema({})).parse(e),o.getContent()}var d=[{regex:/youtu\.be\/([a-z1-9.-_]+)/,type:"iframe",w:425,h:350,url:"http://www.youtube.com/embed/$1"},{regex:/youtube\.com(.+)v=([^&]+)/,type:"iframe",w:425,h:350,url:"http://www.youtube.com/embed/$2"},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"http://player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc"},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'http://maps.google.com/maps/ms?msid=$2&output=embed"'}];e.on("ResolveName",function(e){var t;1==e.target.nodeType&&(t=e.target.getAttribute("data-mce-object"))&&(e.name=t)}),e.on("preInit",function(){var t=e.schema.getSpecialElements();tinymce.each("video audio iframe object".split(" "),function(e){t[e]=new RegExp("]*>","gi")}),e.schema.addValidElements("object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]");var i=e.schema.getBoolAttrs();tinymce.each("webkitallowfullscreen mozallowfullscreen allowfullscreen".split(" "),function(e){i[e]={}}),e.parser.addNodeFilter("iframe,video,audio,object,embed,script",function(t,i){for(var a,o,c,n,s,m,d,u,l=t.length;l--;)if(o=t[l],"script"!=o.name||(u=r(o.attr("src")))){for(c=new tinymce.html.Node("img",1),c.shortEnded=!0,u&&(u.width&&o.attr("width",u.width.toString()),u.height&&o.attr("height",u.height.toString())),m=o.attributes,a=m.length;a--;)n=m[a].name,s=m[a].value,"width"!==n&&"height"!==n&&"style"!==n&&(("data"==n||"src"==n)&&(s=e.convertURL(s,n)),c.attr("data-mce-p-"+n,s));d=o.firstChild&&o.firstChild.value,d&&(c.attr("data-mce-html",escape(d)),c.firstChild=null),c.attr({width:o.attr("width")||"300",height:o.attr("height")||("audio"==i?"30":"150"),style:o.attr("style"),src:tinymce.Env.transparentSrc,"data-mce-object":i,"class":"mce-object mce-object-"+i}),o.replace(c)}}),e.serializer.addAttributeFilter("data-mce-object",function(e,t){for(var i,r,a,o,c,n,s,m=e.length;m--;){for(i=e[m],s=i.attr(t),r=new tinymce.html.Node(s,1),"audio"!=s&&"script"!=s&&r.attr({width:i.attr("width"),height:i.attr("height")}),r.attr({style:i.attr("style")}),o=i.attributes,a=o.length;a--;){var d=o[a].name;0===d.indexOf("data-mce-p-")&&r.attr(d.substr(11),o[a].value)}"script"==s&&r.attr("type","text/javascript"),c=i.attr("data-mce-html"),c&&(n=new tinymce.html.Node("#text",3),n.raw=!0,n.value=unescape(c),r.append(n)),i.replace(r)}})}),e.on("ObjectSelected",function(e){var t=e.target.getAttribute("data-mce-object");("audio"==t||"script"==t)&&e.preventDefault()}),e.on("objectResized",function(e){var t,i=e.target;i.getAttribute("data-mce-object")&&(t=i.getAttribute("data-mce-html"),t&&(t=unescape(t),i.setAttribute("data-mce-html",escape(m(t,{width:e.width,height:e.height})))))}),e.addButton("media",{tooltip:"Insert/edit video",onclick:a,stateSelector:"img[data-mce-object=video]"}),e.addMenuItem("media",{icon:"media",text:"Insert video",onclick:a,context:"insert",prependToContext:!0})}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/nonbreaking/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/nonbreaking/plugin.min.js new file mode 100644 index 000000000..866339c7d --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/nonbreaking/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("nonbreaking",function(e){var t=e.getParam("nonbreaking_force_tab");if(e.addCommand("mceNonBreaking",function(){e.insertContent(e.plugins.visualchars&&e.plugins.visualchars.state?' ':" ")}),e.addButton("nonbreaking",{title:"Insert nonbreaking space",cmd:"mceNonBreaking"}),e.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),t){var n=+t>1?+t:3;e.on("keydown",function(t){if(9==t.keyCode){if(t.shiftKey)return;t.preventDefault();for(var i=0;n>i;i++)e.execCommand("mceNonBreaking")}})}}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/noneditable/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/noneditable/plugin.min.js new file mode 100644 index 000000000..dd15d59ee --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/noneditable/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("noneditable",function(e){function t(){function t(e){var t;if(1===e.nodeType){if(t=e.getAttribute(s),t&&"inherit"!==t)return t;if(t=e.contentEditable,"inherit"!==t)return t}return null}function n(e){for(var n;e;){if(n=t(e))return"false"===n?e:null;e=e.parentNode}}function i(e){for(;e;){if(e.id===g)return e;e=e.parentNode}}function o(e){var t;if(e)for(t=new r(e,e),e=t.current();e;e=t.next())if(3===e.nodeType)return e}function a(n,i){var o,a;return"false"===t(n)&&m.isBlock(n)?(f.select(n),void 0):(a=m.createRng(),"true"===t(n)&&(n.firstChild||n.appendChild(e.getDoc().createTextNode(" ")),n=n.firstChild,i=!0),o=m.create("span",{id:g,"data-mce-bogus":!0},p),i?n.parentNode.insertBefore(o,n):m.insertAfter(o,n),a.setStart(o.firstChild,1),a.collapse(!0),f.setRng(a),o)}function l(e){var t,n,a,r;if(e)t=f.getRng(!0),t.setStartBefore(e),t.setEndBefore(e),n=o(e),n&&n.nodeValue.charAt(0)==p&&(n=n.deleteData(0,1)),m.remove(e,!0),f.setRng(t);else for(a=i(f.getStart());(e=m.get(g))&&e!==r;)a!==e&&(n=o(e),n&&n.nodeValue.charAt(0)==p&&(n=n.deleteData(0,1)),m.remove(e,!0)),r=e}function d(){function e(e,n){var i,o,a,l,s;if(i=c.startContainer,o=c.startOffset,3==i.nodeType){if(s=i.nodeValue.length,o>0&&s>o||(n?o==s:0===o))return}else{if(!(o0?o-1:o;i=i.childNodes[d],i.hasChildNodes()&&(i=i.firstChild)}for(a=new r(i,e);l=a[n?"prev":"next"]();){if(3===l.nodeType&&l.nodeValue.length>0)return;if("true"===t(l))return l}return e}var i,o,s,c,d;l(),s=f.isCollapsed(),i=n(f.getStart()),o=n(f.getEnd()),(i||o)&&(c=f.getRng(!0),s?(i=i||o,(d=e(i,!0))?a(d,!0):(d=e(i,!1))?a(d,!1):f.select(i)):(c=f.getRng(!0),i&&c.setStartBefore(i),o&&c.setEndAfter(o),f.setRng(c)))}function u(o){function a(e,t){for(;e=e[t?"previousSibling":"nextSibling"];)if(3!==e.nodeType||e.nodeValue.length>0)return e}function s(e,t){f.select(e),f.collapse(t)}function u(o){function a(e){for(var t=s;t;){if(t===e)return;t=t.parentNode}m.remove(e),d()}function r(){var i,r,l=e.schema.getNonEmptyElements();for(r=new tinymce.dom.TreeWalker(s,e.getBody());(i=o?r.prev():r.next())&&!l[i.nodeName.toLowerCase()]&&!(3===i.nodeType&&tinymce.trim(i.nodeValue).length>0);)if("false"===t(i))return a(i),!0;return n(i)?!0:!1}var l,s,c,u;if(f.isCollapsed()){if(l=f.getRng(!0),s=l.startContainer,c=l.startOffset,s=i(s)||s,u=n(s))return a(u),!1;if(3==s.nodeType&&(o?c>0:cv||v>124)&&v!=c.DELETE&&v!=c.BACKSPACE){if((tinymce.isMac?o.metaKey:o.ctrlKey)&&(67==v||88==v||86==v))return;if(o.preventDefault(),v==c.LEFT||v==c.RIGHT){var b=v==c.LEFT;if(e.dom.isBlock(g)){var x=b?g.previousSibling:g.nextSibling,w=new r(x,x),C=b?w.prev():w.next();s(C,!b)}else s(g,b)}}else if(v==c.LEFT||v==c.RIGHT||v==c.BACKSPACE||v==c.DELETE){if(p=i(h)){if(v==c.LEFT||v==c.BACKSPACE)if(g=a(p,!0),g&&"false"===t(g)){if(o.preventDefault(),v!=c.LEFT)return m.remove(g),void 0;s(g,!0)}else l(p);if(v==c.RIGHT||v==c.DELETE)if(g=a(p),g&&"false"===t(g)){if(o.preventDefault(),v!=c.RIGHT)return m.remove(g),void 0;s(g,!1)}else l(p)}if((v==c.BACKSPACE||v==c.DELETE)&&!u(v==c.BACKSPACE))return o.preventDefault(),!1}}var m=e.dom,f=e.selection,g="mce_noneditablecaret",p="";e.on("mousedown",function(n){var i=e.selection.getNode();"false"===t(i)&&i==n.target&&d()}),e.on("mouseup keyup",d),e.on("keydown",u)}function n(t){var n=a.length,i=t.content,r=tinymce.trim(o);if("raw"!=t.format){for(;n--;)i=i.replace(a[n],function(t){var n=arguments,o=n[n.length-2];return o>0&&'"'==i.charAt(o-1)?t:''+e.dom.encode("string"==typeof n[1]?n[1]:n[0])+""});t.content=i}}var i,o,a,r=tinymce.dom.TreeWalker,l="contenteditable",s="data-mce-"+l,c=tinymce.util.VK;i=" "+tinymce.trim(e.getParam("noneditable_editable_class","mceEditable"))+" ",o=" "+tinymce.trim(e.getParam("noneditable_noneditable_class","mceNonEditable"))+" ",a=e.getParam("noneditable_regexp"),a&&!a.length&&(a=[a]),e.on("PreInit",function(){t(),a&&e.on("BeforeSetContent",n),e.parser.addAttributeFilter("class",function(e){for(var t,n,a=e.length;a--;)n=e[a],t=" "+n.attr("class")+" ",-1!==t.indexOf(i)?n.attr(s,"true"):-1!==t.indexOf(o)&&n.attr(s,"false")}),e.serializer.addAttributeFilter(s,function(e){for(var t,n=e.length;n--;)t=e[n],a&&t.attr("data-mce-content")?(t.name="#text",t.type=3,t.raw=!0,t.value=t.attr("data-mce-content")):(t.attr(l,null),t.attr(s,null))}),e.parser.addAttributeFilter(l,function(e){for(var t,n=e.length;n--;)t=e[n],t.attr(s,t.attr(l)),t.attr(l,null)})})}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/pagebreak/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/pagebreak/plugin.min.js new file mode 100644 index 000000000..e224cb441 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/pagebreak/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("pagebreak",function(e){var a="mce-pagebreak",t=e.getParam("pagebreak_separator",""),n=new RegExp(t.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi"),r='';e.addCommand("mcePageBreak",function(){e.settings.pagebreak_split_block?e.insertContent("

"+r+"

"):e.insertContent(r)}),e.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),e.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),e.on("ResolveName",function(t){"IMG"==t.target.nodeName&&e.dom.hasClass(t.target,a)&&(t.name="pagebreak")}),e.on("click",function(t){t=t.target,"IMG"===t.nodeName&&e.dom.hasClass(t,a)&&e.selection.select(t)}),e.on("BeforeSetContent",function(e){e.content=e.content.replace(n,r)}),e.on("PreInit",function(){e.serializer.addNodeFilter("img",function(a){for(var n,r,c=a.length;c--;)if(n=a[c],r=n.attr("class"),r&&-1!==r.indexOf("mce-pagebreak")){var o=n.parent;if(e.schema.getBlockElements()[o.name]&&e.settings.pagebreak_split_block){o.type=3,o.value=t,o.raw=!0,n.remove();continue}n.type=3,n.value=t,n.raw=!0}})})}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/paste/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/paste/plugin.min.js new file mode 100644 index 000000000..95c0129ec --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/paste/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i"),t&&/^(PRE|DIV)$/.test(t.nodeName)||!o?e=n.filter(e,[[/\n/g,"
"]]):(e=n.filter(e,[[/\n\n/g,"

"+a],[/^(.*<\/p>)(

)$/,a+"$1"],[/\n/g,"
"]]),-1!=e.indexOf("

")&&(e=a+e)),i(e)}function a(){var e=r.dom,t=r.getBody(),n=r.dom.getViewPort(r.getWin()),i=r.inline?t.clientHeight:n.h;s(),p=e.add(r.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"1",style:"position: fixed; top: 20px;width: 10px; height: "+(i-40)+"px; overflow: hidden; opacity: 0"},g),e.setStyle(p,"left","rtl"==e.getStyle(t,"direction",!0)?65535:-65535),e.bind(p,"beforedeactivate focusin focusout",function(e){e.stopPropagation()}),m=r.selection.getRng(),p.focus(),r.selection.select(p,!0)}function s(){p&&(r.dom.unbind(p),r.dom.remove(p),m&&r.selection.setRng(m)),v=!1,p=m=null}function l(){return p?p.innerHTML:g}function c(e){var t={};if(e&&e.types){t["text/plain"]=e.getData("Text");for(var n=0;nl?n&&(n=n.parent.parent):(r=n,n=null)),n&&n.name==a?n.append(e):(r=r||n,n=new i(a,1),s>1&&n.attr("start",""+s),e.wrap(n)),e.name="li",t.value="";var c=t.next;c&&3==c.type&&(c.value=c.value.replace(/^\u00a0+/,"")),l>o&&r&&r.lastChild.append(n),o=l}for(var n,r,o=1,a=e.getAll("p"),s=0;s/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/([\s\u00a0]*)<\/span>/gi,function(e,t){return t.length>0?t.replace(/./," ").slice(Math.floor(t.length/2)).split("").join("\xa0"):""}]]);var h=l.paste_word_valid_elements;h||(h="@[style],-strong/b,-em/i,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-table,-tr,-td[colspan|rowspan],-th,-thead,-tfoot,-tbody,-a[href|name],sub,sup,strike,br");var g=new n({valid_elements:h}),v=new t({},g);v.addAttributeFilter("style",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr("style",u(n,n.attr("style"))),"span"!=n.name||n.attributes.length||n.unwrap()}),v.addNodeFilter("a",function(e){for(var t=e.length,n,r,i;t--;)n=e[t],r=n.attr("href"),i=n.attr("name"),r&&0===r.indexOf("file://")&&(r=r.split("#")[1],r&&(r="#"+r)),r||i?n.attr({href:r,name:i}):n.unwrap()});var y=v.parse(f);d(y),c.content=new r({},g).serialize(y)}})}return s.isWordContent=a,s}),r(y,[p,c,h,l],function(e,t,n,r){return function(i){function o(e){i.on("BeforePastePreProcess",function(t){t.content=e(t.content)})}function a(e){return e=r.filter(e,[/^[\s\S]*|[\s\S]*$/g,[/\u00a0<\/span>/g,"\xa0"],/
$/])}function s(e){if(!n.isWordContent(e))return e;var o=[];t.each(i.schema.getBlockElements(),function(e,t){o.push(t)});var a=new RegExp("(?:
 [\\s\\r\\n]+|
)*(<\\/?("+o.join("|")+")[^>]*>)(?:
 [\\s\\r\\n]+|
)*","g");return e=r.filter(e,[[a,"$1"]]),e=r.filter(e,[[/

/g,"

"],[/
/g," "],[/

/g,"
"]])}function l(e){return(i.settings.paste_remove_styles||i.settings.paste_remove_styles_if_webkit!==!1)&&(e=e.replace(/ style=\"[^\"]+\"/g,"")),e}e.webkit&&(o(l),o(a)),e.ie&&o(s)}}),r(b,[C,f,h,y],function(e,t,n,r){var i;e.add("paste",function(e){function o(){"text"==s.pasteFormat?(this.active(!1),s.pasteFormat="html"):(s.pasteFormat="text",this.active(!0),i||(e.windowManager.alert("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off."),i=!0))}var a=this,s,l=e.settings;a.clipboard=s=new t(e),a.quirks=new r(e),a.wordFilter=new n(e),e.settings.paste_as_text&&(a.clipboard.pasteFormat="text"),l.paste_preprocess&&e.on("PastePreProcess",function(e){l.paste_preprocess.call(a,a,e)}),l.paste_postprocess&&e.on("PastePostProcess",function(e){l.paste_postprocess.call(a,a,e)}),e.addCommand("mceInsertClipboardContent",function(e,t){t.content&&a.clipboard.pasteHtml(t.content),t.text&&a.clipboard.pasteText(t.text)}),e.paste_block_drop&&e.on("dragend dragover draggesture dragdrop drop drag",function(e){e.preventDefault(),e.stopPropagation()}),e.settings.paste_data_images||e.on("drop",function(e){var t=e.dataTransfer;t&&t.files&&t.files.length>0&&e.preventDefault()}),e.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:o,active:"text"==a.clipboard.pasteFormat}),e.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:s.pasteFormat,onclick:o})})}),a([l,f,h,y,b])}(this); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/preview/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/preview/plugin.min.js new file mode 100644 index 000000000..8a24058f7 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/preview/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("preview",function(e){var t=e.settings;e.addCommand("mcePreview",function(){e.windowManager.open({title:"Preview",width:parseInt(e.getParam("plugin_preview_width","650"),10),height:parseInt(e.getParam("plugin_preview_height","500"),10),html:'',buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var i,n=this.getEl("body").firstChild.contentWindow.document,a="";tinymce.each(e.contentCSS,function(t){a+=''});var d=t.body_id||"tinymce";-1!=d.indexOf("=")&&(d=e.getParam("body_id","","hash"),d=d[e.id]||d);var r=t.body_class||"";-1!=r.indexOf("=")&&(r=e.getParam("body_class","","hash"),r=r[e.id]||""),i=""+a+""+''+e.getContent()+""+"",n.open(),n.write(i),n.close()}})}),e.addButton("preview",{title:"Preview",cmd:"mcePreview"}),e.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/print/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/print/plugin.min.js new file mode 100644 index 000000000..abc37b5fd --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/print/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("print",function(t){t.addCommand("mcePrint",function(){t.getWin().print()}),t.addButton("print",{title:"Print",cmd:"mcePrint"}),t.addShortcut("Ctrl+P","","mcePrint"),t.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Ctrl+P",context:"file"})}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/save/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/save/plugin.min.js new file mode 100644 index 000000000..bd50cec41 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/save/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("save",function(e){function t(){var t,n;return t=tinymce.DOM.getParent(e.id,"form"),!e.getParam("save_enablewhendirty",!0)||e.isDirty()?(tinymce.triggerSave(),(n=e.getParam("save_onsavecallback"))?(e.execCallback("save_onsavecallback",e)&&(e.startContent=tinymce.trim(e.getContent({format:"raw"})),e.nodeChanged()),void 0):(t?(e.isNotDirty=!0,(!t.onsubmit||t.onsubmit())&&("function"==typeof t.submit?t.submit():e.windowManager.alert("Error: Form submit field collision.")),e.nodeChanged()):e.windowManager.alert("Error: No form element found."),void 0)):void 0}function n(){var t,n=tinymce.trim(e.startContent);return(t=e.getParam("save_oncancelcallback"))?(e.execCallback("save_oncancelcallback",e),void 0):(e.setContent(n),e.undoManager.clear(),e.nodeChanged(),void 0)}function i(){var t=this;e.on("nodeChange",function(){t.disabled(e.getParam("save_enablewhendirty",!0)&&!e.isDirty())})}e.addCommand("mceSave",t),e.addCommand("mceCancel",n),e.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:i}),e.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:i}),e.addShortcut("ctrl+s","","mceSave")}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/searchreplace/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/searchreplace/plugin.min.js new file mode 100644 index 000000000..7ffaf4610 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/searchreplace/plugin.min.js @@ -0,0 +1 @@ +!function(){function e(e,t,n,a,r){function i(e,t){if(t=t||0,!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var n=e.index;if(t>0){var a=e[t];if(!a)throw"Invalid capture group";n+=e[0].indexOf(a),e[0]=a}return[n,n+e[0].length,[e[0]]]}function d(e){var t;if(3===e.nodeType)return e.data;if(h[e.nodeName]&&!u[e.nodeName])return"";if(t="",(u[e.nodeName]||m[e.nodeName])&&(t+="\n"),e=e.firstChild)do t+=d(e);while(e=e.nextSibling);return t}function o(e,t,n){var a,r,i,d,o=[],l=0,c=e,s=t.shift(),f=0;e:for(;;){if((u[c.nodeName]||m[c.nodeName])&&l++,3===c.nodeType&&(!r&&c.length+l>=s[1]?(r=c,d=s[1]-l):a&&o.push(c),!a&&c.length+l>s[0]&&(a=c,i=s[0]-l),l+=c.length),a&&r){if(c=n({startNode:a,startNodeIndex:i,endNode:r,endNodeIndex:d,innerNodes:o,match:s[2],matchIndex:f}),l-=r.length-d,a=null,r=null,o=[],s=t.shift(),f++,!s)break}else{if((!h[c.nodeName]||u[c.nodeName])&&c.firstChild){c=c.firstChild;continue}if(c.nextSibling){c=c.nextSibling;continue}}for(;;){if(c.nextSibling){c=c.nextSibling;break}if(c.parentNode===e)break e;c=c.parentNode}}}function l(e){var t;if("function"!=typeof e){var n=e.nodeType?e:f.createElement(e);t=function(e,t){var a=n.cloneNode(!1);return a.setAttribute("data-mce-index",t),e&&a.appendChild(f.createTextNode(e)),a}}else t=e;return function(e){var n,a,r,i=e.startNode,d=e.endNode,o=e.matchIndex;if(i===d){var l=i;r=l.parentNode,e.startNodeIndex>0&&(n=f.createTextNode(l.data.substring(0,e.startNodeIndex)),r.insertBefore(n,l));var c=t(e.match[0],o);return r.insertBefore(c,l),e.endNodeIndexh;++h){var g=e.innerNodes[h],p=t(g.data,o);g.parentNode.replaceChild(p,g),u.push(p)}var x=t(d.data.substring(0,e.endNodeIndex),o);return r=i.parentNode,r.insertBefore(n,i),r.insertBefore(s,i),r.removeChild(i),r=d.parentNode,r.insertBefore(x,d),r.insertBefore(a,d),r.removeChild(d),x}}var c,s,f,u,h,m,g=[],p=0;if(f=t.ownerDocument,u=r.getBlockElements(),h=r.getWhiteSpaceElements(),m=r.getShortEndedElements(),s=d(t)){if(e.global)for(;c=e.exec(s);)g.push(i(c,a));else c=s.match(e),g.push(i(c,a));return g.length&&(p=g.length,o(t,g,l(n))),p}}function t(t){function n(){function e(){r.statusbar.find("#next").disabled(!d(s+1).length),r.statusbar.find("#prev").disabled(!d(s-1).length)}function n(){tinymce.ui.MessageBox.alert("Could not find the specified string.",function(){r.find("#find")[0].focus()})}var a={},r=tinymce.ui.Factory.create({type:"window",layout:"flex",pack:"center",align:"center",onClose:function(){t.focus(),c.done()},onSubmit:function(t){var i,o,l,f;return t.preventDefault(),o=r.find("#case").checked(),f=r.find("#words").checked(),l=r.find("#find").value(),l.length?a.text==l&&a.caseState==o&&a.wholeWord==f?0===d(s+1).length?(n(),void 0):(c.next(),e(),void 0):(i=c.find(l,o,f),i||n(),r.statusbar.items().slice(1).disabled(0===i),e(),a={text:l,caseState:o,wholeWord:f},void 0):(c.done(!1),r.statusbar.items().slice(1).disabled(!0),void 0)},buttons:[{text:"Find",onclick:function(){r.submit()}},{text:"Replace",disabled:!0,onclick:function(){c.replace(r.find("#replace").value())||(r.statusbar.items().slice(1).disabled(!0),s=-1,a={})}},{text:"Replace all",disabled:!0,onclick:function(){c.replace(r.find("#replace").value(),!0,!0),r.statusbar.items().slice(1).disabled(!0),a={}}},{type:"spacer",flex:1},{text:"Prev",name:"prev",disabled:!0,onclick:function(){c.prev(),e()}},{text:"Next",name:"next",disabled:!0,onclick:function(){c.next(),e()}}],title:"Find and replace",items:{type:"form",padding:20,labelGap:30,spacing:10,items:[{type:"textbox",name:"find",size:40,label:"Find",value:t.selection.getNode().src},{type:"textbox",name:"replace",size:40,label:"Replace with"},{type:"checkbox",name:"case",text:"Match case",label:" "},{type:"checkbox",name:"words",text:"Whole words",label:" "}]}}).renderTo().reflow()}function a(e){var t=e.getAttribute("data-mce-index");return"number"==typeof t?""+t:t}function r(n){var a,r;return r=t.dom.create("span",{"data-mce-bogus":1}),r.className="mce-match-marker",a=t.getBody(),c.done(!1),e(n,a,r,!1,t.schema)}function i(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function d(e){var n,r=[];if(n=tinymce.toArray(t.getBody().getElementsByTagName("span")),n.length)for(var i=0;is&&f[o].setAttribute("data-mce-index",m-1)}return t.undoManager.add(),s=p,n?(g=d(p+1).length>0,c.next()):(g=d(p-1).length>0,c.prev()),!r&&g},c.done=function(e){var n,r,d,o;for(r=tinymce.toArray(t.getBody().getElementsByTagName("span")),n=0;n=s[1]?(o=d,a=s[1]-l):r&&c.push(d),!r&&d.length+l>s[0]&&(r=d,i=s[0]-l),l+=d.length),r&&o){if(d=n({startNode:r,startNodeIndex:i,endNode:o,endNodeIndex:a,innerNodes:c,match:s[2],matchIndex:u}),l-=o.length-a,r=null,o=null,c=[],s=t.shift(),u++,!s)break}else{if((!m[d.nodeName]||p[d.nodeName])&&d.firstChild){d=d.firstChild;continue}if(d.nextSibling){d=d.nextSibling;continue}}for(;;){if(d.nextSibling){d=d.nextSibling;break}if(d.parentNode===e)break e;d=d.parentNode}}}function a(e){var t;if("function"!=typeof e){var n=e.nodeType?e:g.createElement(e);t=function(e,t){var r=n.cloneNode(!1);return r.setAttribute("data-mce-index",t),e&&r.appendChild(g.createTextNode(e)),r}}else t=e;return function r(e){var n,r,o,i=e.startNode,a=e.endNode,c=e.matchIndex;if(i===a){var l=i;o=l.parentNode,e.startNodeIndex>0&&(n=g.createTextNode(l.data.substring(0,e.startNodeIndex)),o.insertBefore(n,l));var d=t(e.match[0],c);return o.insertBefore(d,l),e.endNodeIndexf;++f){var p=e.innerNodes[f],m=t(p.data,c);p.parentNode.replaceChild(m,p),u.push(m)}var v=t(a.data.substring(0,e.endNodeIndex),c);return o=i.parentNode,o.insertBefore(n,i),o.insertBefore(s,i),o.removeChild(i),o=a.parentNode,o.insertBefore(v,a),o.insertBefore(r,a),o.removeChild(a),v}}function c(e){var t=[];return l(function(n,r){e(n,r)&&t.push(n)}),u=t,this}function l(e){for(var t=0,n=u.length;n>t&&e(u[t],t)!==!1;t++);return this}function d(e){return u.length&&(h=u.length,i(t,u,a(e))),this}var s,u=[],f,h=0,g,p,m,v;if(g=t.ownerDocument,p=n.getBlockElements(),m=n.getWhiteSpaceElements(),v=n.getShortEndedElements(),f=o(t),f&&e.global)for(;s=e.exec(f);)u.push(r(s));return{text:f,count:h,matches:u,each:l,filter:c,mark:d}}}),r(d,[l,s,u,f,h,g,p],function(e,t,n,r,o,i,a){t.add("spellchecker",function(t,c){function l(e){for(var t in e)return!1;return!0}function d(e,i){var a=[],c=m[i];n.each(c,function(e){a.push({text:e,onclick:function(){t.insertContent(e),u()}})}),a.push.apply(a,[{text:"-"},{text:"Ignore",onclick:function(){h(e,i)}},{text:"Ignore all",onclick:function(){h(e,i,!0)}},{text:"Finish",onclick:g}]),N=new r({items:a,context:"contextmenu",onautohide:function(e){-1!=e.target.className.indexOf("spellchecker")&&e.preventDefault()},onhide:function(){N.remove(),N=null}}),N.renderTo(document.body);var l=o.DOM.getPos(t.getContentAreaContainer()),d=t.dom.getPos(e);l.x+=d.x,l.y+=d.y,N.moveTo(l.x,l.y+e.offsetHeight)}function s(){function n(e){return t.setProgressState(!1),l(e)?(t.windowManager.alert("No misspellings found"),v=!1,void 0):(m=e,o.filter(function(t){return!!e[t[2][0]]}).mark(t.dom.create("span",{"class":"mce-spellchecker-word","data-mce-bogus":1})),o=null,t.fire("SpellcheckStart"),void 0)}function r(e,n,r){i.sendRPC({url:new a(c).toAbsolute(x.spellchecker_rpc_url),method:e,params:{lang:x.spellchecker_language||"en",words:n},success:function(e){r(e)},error:function(e,n){e="JSON Parse error."==e?"Non JSON response:"+n.responseText:"Error: "+e,t.windowManager.alert(e),t.setProgressState(!1),o=null,v=!1}})}var o,d=[],s={};if(v)return g(),void 0;v=!0;var u=t.getParam("spellchecker_wordchar_pattern")||new RegExp('[^\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`\xa7\xa9\xab\xae\xb1\xb6\xb7\xb8\xbb\xbc\xbd\xbe\xbf\xd7\xf7\xa4\u201d\u201c\u201e]+',"g");o=new e(u,t.getBody(),t.schema).each(function(e){var t=e[2][0];if(!s[t]){if(/^\d+$/.test(t)||1==t.length)return;d.push(t),s[t]=!0}}),t.setProgressState(!0);var f=x.spellchecker_callback||r;f("spellcheck",d,n)}function u(){t.dom.select("span.mce-spellchecker-word").length||g()}function f(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function h(e,r,o){o?n.each(t.dom.select("span.mce-spellchecker-word"),function(e){var t=e.innerText||e.textContent;t==r&&f(e)}):f(e),u()}function g(){var e,n,r;for(v=!1,r=t.getBody(),n=r.getElementsByTagName("span"),e=n.length;e--;)r=n[e],r.getAttribute("data-mce-index")&&f(r);t.fire("SpellcheckEnd")}function p(e){var n,r,o,i=-1,a,c;for(e=""+e,n=t.getBody().getElementsByTagName("span"),r=0;r0){for(c=u+1;c=0;c--)if(a(d[c]))return d[c];return null}var u,d,a,c;if(9===n.keyCode&&(a=r(e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))),1==a.length&&(a[1]=a[0],a[0]=":prev"),d=n.shiftKey?":prev"==a[0]?t(-1):i.get(a[0]):":next"==a[1]?t(1):i.get(a[1]))){var f=tinymce.get(d.id||d.name);d.id&&f?f.focus():window.setTimeout(function(){tinymce.Env.webkit||window.focus(),d.focus()},10),n.preventDefault()}}var i=tinymce.DOM,o=tinymce.each,r=tinymce.explode;e.on("init",function(){e.inline&&tinymce.DOM.setAttrib(e.getBody(),"tabIndex",null)}),e.on("keyup",n),tinymce.Env.gecko?e.on("keypress keydown",t):e.on("keydown",t)}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/table/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/table/plugin.min.js new file mode 100644 index 000000000..d953931ec --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/table/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i "+t+" tr",o);r(i,function(i,o){o+=e,r(H.select("> td, > th",i),function(e,r){var i,a,s,l;if(R[o])for(;R[o][r];)r++;for(s=n(e,"rowspan"),l=n(e,"colspan"),a=o;o+s>a;a++)for(R[a]||(R[a]=[]),i=r;r+l>i;i++)R[a][i]={part:t,real:a==o&&i==r,elm:e,rowspan:s,colspan:l}})}),e+=i.length})}function s(e,t){return e=e.cloneNode(t),e.removeAttribute("id"),e}function l(e,t){var n;return n=R[t],n?n[e]:void 0}function c(e,t,n){e&&(n=parseInt(n,10),1===n?e.removeAttribute(t,1):e.setAttribute(t,n,1))}function d(e){return e&&(H.hasClass(e.elm,"mce-item-selected")||e==L)}function u(){var e=[];return r(o.rows,function(t){r(t.cells,function(n){return H.hasClass(n,"mce-item-selected")||n==L.elm?(e.push(t),!1):void 0})}),e}function f(){var e=H.createRng();e.setStartAfter(o),e.setEndAfter(o),D.setRng(e),H.remove(o)}function p(n){var o,a={};return i.settings.table_clone_elements!==!1&&(a=e.makeMap((i.settings.table_clone_elements||"strong em b i span font h1 h2 h3 h4 h5 h6 p div").toUpperCase(),/[ ,]/)),e.walk(n,function(e){var i;return 3==e.nodeType?(r(H.getParents(e.parentNode,null,n).reverse(),function(e){a[e.nodeName]&&(e=s(e,!1),o?i&&i.appendChild(e):o=i=e,i=e)}),i&&(i.innerHTML=t.ie?" ":'
'),!1):void 0},"childNodes"),n=s(n,!1),c(n,"rowSpan",1),c(n,"colSpan",1),o?n.appendChild(o):t.ie||(n.innerHTML='
'),n}function m(){var e=H.createRng(),t;return r(H.select("tr",o),function(e){0===e.cells.length&&H.remove(e)}),0===H.select("tr",o).length?(e.setStartBefore(o),e.setEndBefore(o),D.setRng(e),H.remove(o),void 0):(r(H.select("thead,tbody,tfoot",o),function(e){0===e.rows.length&&H.remove(e)}),a(),t=R[Math.min(R.length-1,A.y)],t&&(D.select(t[Math.min(t.length-1,A.x)].elm,!0),D.collapse(!0)),void 0)}function h(e,t,n,r){var i,o,a,s,l;for(i=R[t][e].elm.parentNode,a=1;n>=a;a++)if(i=H.getNext(i,"tr")){for(o=e;o>=0;o--)if(l=R[t+a][o].elm,l.parentNode==i){for(s=1;r>=s;s++)H.insertAfter(p(l),l);break}if(-1==o)for(s=1;r>=s;s++)i.insertBefore(p(i.cells[0]),i.cells[0])}}function g(){r(R,function(e,t){r(e,function(e,r){var i,o,a;if(d(e)&&(e=e.elm,i=n(e,"colspan"),o=n(e,"rowspan"),i>1||o>1)){for(c(e,"rowSpan",1),c(e,"colSpan",1),a=0;i-1>a;a++)H.insertAfter(p(e),e);h(r,t,o-1,i)}})})}function v(t,n,i){var o,s,u,f,p,h,v,y,b,C,x;if(t?(o=E(t),s=o.x,u=o.y,f=s+(n-1),p=u+(i-1)):(A=B=null,r(R,function(e,t){r(e,function(e,n){d(e)&&(A||(A={x:n,y:t}),B={x:n,y:t})})}),s=A.x,u=A.y,f=B.x,p=B.y),y=l(s,u),b=l(f,p),y&&b&&y.part==b.part){for(g(),a(),y=l(s,u).elm,c(y,"colSpan",f-s+1),c(y,"rowSpan",p-u+1),v=u;p>=v;v++)for(h=s;f>=h;h++)R[v]&&R[v][h]&&(t=R[v][h].elm,t!=y&&(C=e.grep(t.childNodes),r(C,function(e){y.appendChild(e)}),C.length&&(C=e.grep(y.childNodes),x=0,r(C,function(e){"BR"==e.nodeName&&H.getAttrib(e,"data-mce-bogus")&&x++0&&R[t-1][a]&&(m=R[t-1][a].elm,h=n(m,"rowSpan"),h>1)){c(m,"rowSpan",h+1);continue}}else if(h=n(i,"rowspan"),h>1){c(i,"rowSpan",h+1);continue}f=p(i),c(f,"colSpan",i.colSpan),u.appendChild(f),o=i}u.hasChildNodes()&&(e?l.parentNode.insertBefore(u,l):H.insertAfter(u,l))}function b(e){var t,i;r(R,function(n){return r(n,function(n,r){return d(n)&&(t=r,e)?!1:void 0}),e?!t:void 0}),r(R,function(r,o){var a,s,l;r[t]&&(a=r[t].elm,a!=i&&(l=n(a,"colspan"),s=n(a,"rowspan"),1==l?e?(a.parentNode.insertBefore(p(a),a),h(t,o,s-1,l)):(H.insertAfter(p(a),a),h(t,o,s-1,l)):c(a,"colSpan",a.colSpan+1),i=a))})}function C(){var t=[];r(R,function(i){r(i,function(i,o){d(i)&&-1===e.inArray(t,o)&&(r(R,function(e){var t=e[o].elm,r;r=n(t,"colSpan"),r>1?c(t,"colSpan",r-1):H.remove(t)}),t.push(o))})}),m()}function x(){function e(e){var t,i,o;t=H.getNext(e,"tr"),r(e.cells,function(e){var t=n(e,"rowSpan");t>1&&(c(e,"rowSpan",t-1),i=E(e),h(i.x,i.y,1,1))}),i=E(e.cells[0]),r(R[i.y],function(e){var t;e=e.elm,e!=o&&(t=n(e,"rowSpan"),1>=t?H.remove(e):c(e,"rowSpan",t-1),o=e)})}var t;t=u(),r(t.reverse(),function(t){e(t)}),m()}function w(){var e=u();return H.remove(e),m(),e}function _(){var e=u();return r(e,function(t,n){e[n]=s(t,!0)}),e}function N(e,t){var n=u(),i=n[t?0:n.length-1],o=i.cells.length;e&&(r(R,function(e){var t;return o=0,r(e,function(e){e.real&&(o+=e.colspan),e.elm.parentNode==i&&(t=1)}),t?!1:void 0}),t||e.reverse(),r(e,function(e){var n,r=e.cells.length,a;for(n=0;r>n;n++)a=e.cells[n],c(a,"colSpan",1),c(a,"rowSpan",1);for(n=r;o>n;n++)e.appendChild(p(e.cells[r-1]));for(n=o;r>n;n++)H.remove(e.cells[n]);t?i.parentNode.insertBefore(e,i):H.insertAfter(e,i)}),H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function E(e){var t;return r(R,function(n,i){return r(n,function(n,r){return n.elm==e?(t={x:r,y:i},!1):void 0}),!t}),t}function k(e){A=E(e)}function S(){var e,t;return e=t=0,r(R,function(n,i){r(n,function(n,r){var o,a;d(n)&&(n=R[i][r],r>e&&(e=r),i>t&&(t=i),n.real&&(o=n.colspan-1,a=n.rowspan-1,o&&r+o>e&&(e=r+o),a&&i+a>t&&(t=i+a)))})}),{x:e,y:t}}function T(e){var t,n,r,i,o,a,s,l,c,d;if(B=E(e),A&&B){for(t=Math.min(A.x,B.x),n=Math.min(A.y,B.y),r=Math.max(A.x,B.x),i=Math.max(A.y,B.y),o=r,a=i,d=n;a>=d;d++)e=R[d][t],e.real||t-(e.colspan-1)=c;c++)e=R[n][c],e.real||n-(e.rowspan-1)=d;d++)for(c=t;r>=c;c++)e=R[d][c],e.real&&(s=e.colspan-1,l=e.rowspan-1,s&&c+s>o&&(o=c+s),l&&d+l>a&&(a=d+l));for(H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=n;a>=d;d++)for(c=t;o>=c;c++)R[d][c]&&H.addClass(R[d][c].elm,"mce-item-selected")}}var R,A,B,L,D=i.selection,H=D.dom;o=o||H.getParent(D.getStart(),"table"),a(),L=H.getParent(D.getStart(),"th,td"),L&&(A=E(L),B=S(),L=l(A.x,A.y)),e.extend(this,{deleteTable:f,split:g,merge:v,insertRow:y,insertCol:b,deleteCols:C,deleteRows:x,cutRows:w,copyRows:_,pasteRows:N,getPos:E,setStartCell:k,setEndCell:T})}}),r(u,[f,d,c],function(e,t,n){function r(e,t){return parseInt(e.getAttribute(t)||1,10)}var i=n.each;return function(n){function o(){function t(t){function o(e,r){var i=e?"previousSibling":"nextSibling",o=n.dom.getParent(r,"tr"),s=o[i];if(s)return g(n,r,s,e),t.preventDefault(),!0;var d=n.dom.getParent(o,"table"),u=o.parentNode,f=u.nodeName.toLowerCase();if("tbody"===f||f===(e?"tfoot":"thead")){var p=a(e,d,u,"tbody");if(null!==p)return l(e,p,r)}return c(e,o,i,d)}function a(e,t,r,i){var o=n.dom.select(">"+i,t),a=o.indexOf(r);if(e&&0===a||!e&&a===o.length-1)return s(e,t);if(-1===a){var l="thead"===r.tagName.toLowerCase()?0:o.length-1;return o[l]}return o[a+(e?-1:1)]}function s(e,t){var r=e?"thead":"tfoot",i=n.dom.select(">"+r,t);return 0!==i.length?i[0]:null}function l(e,r,i){var o=d(r,e);return o&&g(n,i,o,e),t.preventDefault(),!0}function c(e,r,i,a){var s=a[i];if(s)return u(s),!0;var l=n.dom.getParent(a,"td,th");if(l)return o(e,l,t);var c=d(r,!e);return u(c),t.preventDefault(),!1}function d(e,t){var r=e&&e[t?"lastChild":"firstChild"];return r&&"BR"===r.nodeName?n.dom.getParent(r,"td,th"):r}function u(e){n.selection.setCursorLocation(e,0)}function f(){return b==e.UP||b==e.DOWN}function p(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function m(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=r(n,"colspan");return t}function h(e,t){var n=0,o=0;return i(e.children,function(e,i){return n+=r(e,"colspan"),o=i,n>t?!1:void 0}),o}function g(e,t,r,i){var o=m(n.dom.getParent(t,"td,th")),a=h(r,o),s=r.childNodes[a],l=d(s,i);u(l||s)}function v(e){var t=n.selection.getNode(),r=n.dom.getParent(t,"td,th"),i=n.dom.getParent(e,"td,th");return r&&r!==i&&y(r,i)}function y(e,t){return n.dom.getParent(e,"TABLE")===n.dom.getParent(t,"TABLE")}var b=t.keyCode;if(f()&&p(n)){var C=n.selection.getNode();setTimeout(function(){v(C)&&o(!t.shiftKey&&b===e.UP,C,t)},0)}}n.on("KeyDown",function(e){t(e)})}function a(){function e(e,t){var n=t.ownerDocument,r=n.createRange(),i;return r.setStartBefore(t),r.setEnd(e.endContainer,e.endOffset),i=n.createElement("body"),i.appendChild(r.cloneContents()),0===i.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}n.on("KeyDown",function(t){var r,i,o=n.dom;(37==t.keyCode||38==t.keyCode)&&(r=n.selection.getRng(),i=o.getParent(r.startContainer,"table"),i&&n.getBody().firstChild==i&&e(r,i)&&(r=o.createRng(),r.setStartBefore(i),r.setEndBefore(i),n.selection.setRng(r),t.preventDefault()))})}function s(){n.on("KeyDown SetContent VisualAid",function(){var e;for(e=n.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&!e.getAttribute("data-mce-bogus"))break;e&&"TABLE"==e.nodeName&&(n.settings.forced_root_block?n.dom.add(n.getBody(),n.settings.forced_root_block,n.settings.forced_root_block_attrs,t.ie&&t.ie<11?" ":'
'):n.dom.add(n.getBody(),"br",{"data-mce-bogus":"1"}))}),n.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\xa0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&n.dom.remove(t)})}function l(){function e(e,t,n,r){var i=3,o=e.dom.getParent(t.startContainer,"TABLE"),a,s,l;return o&&(a=o.parentNode),s=t.startContainer.nodeType==i&&0===t.startOffset&&0===t.endOffset&&r&&("TR"==n.nodeName||n==a),l=("TD"==n.nodeName||"TH"==n.nodeName)&&!r,s||l}function t(){var t=n.selection.getRng(),r=n.selection.getNode(),i=n.dom.getParent(t.startContainer,"TD,TH");if(e(n,t,r,i)){i||(i=r);for(var o=i.lastChild;o.lastChild;)o=o.lastChild;t.setEnd(o,o.nodeValue.length),n.selection.setRng(t)}}n.on("KeyDown",function(){t()}),n.on("MouseDown",function(e){2!=e.button&&t()})}function c(){n.on("keydown",function(t){if((t.keyCode==e.DELETE||t.keyCode==e.BACKSPACE)&&!t.isDefaultPrevented()){var r=n.dom.getParent(n.selection.getStart(),"table");if(r){for(var i=n.dom.select("td,th",r),o=i.length;o--;)if(!n.dom.hasClass(i[o],"mce-item-selected"))return;t.preventDefault(),n.execCommand("mceTableDelete")}}})}c(),t.webkit&&(o(),l()),t.gecko&&(a(),s()),t.ie>10&&(a(),s())}}),r(p,[l,m,c],function(e,t,n){return function(r){function i(){r.getBody().style.webkitUserSelect="",d&&(r.dom.removeClass(r.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=!1)}function o(t){var n,i,o=t.target;if(l&&(s||o!=l)&&("TD"==o.nodeName||"TH"==o.nodeName)){i=a.getParent(o,"table"),i==c&&(s||(s=new e(r,i),s.setStartCell(l),r.getBody().style.webkitUserSelect="none"),s.setEndCell(o),d=!0),n=r.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(u){}t.preventDefault()}}var a=r.dom,s,l,c,d=!0;return r.on("MouseDown",function(e){2!=e.button&&(i(),l=a.getParent(e.target,"td,th"),c=a.getParent(l,"table"))}),a.bind(r.getDoc(),"mouseover",o),r.on("remove",function(){a.unbind(r.getDoc(),"mouseover",o)}),r.on("MouseUp",function(){function e(e,r){var o=new t(e,e);do{if(3==e.nodeType&&0!==n.trim(e.nodeValue).length)return r?i.setStart(e,0):i.setEnd(e,e.nodeValue.length),void 0;if("BR"==e.nodeName)return r?i.setStartBefore(e):i.setEndBefore(e),void 0}while(e=r?o.next():o.prev())}var i,o=r.selection,d,u,f,p,m;if(l){if(s&&(r.getBody().style.webkitUserSelect=""),d=a.select("td.mce-item-selected,th.mce-item-selected"),d.length>0){i=a.createRng(),f=d[0],m=d[d.length-1],i.setStartBefore(f),i.setEndAfter(f),e(f,1),u=new t(f,a.getParent(d[0],"table"));do if("TD"==f.nodeName||"TH"==f.nodeName){if(!a.hasClass(f,"mce-item-selected"))break;p=f}while(f=u.next());e(p),o.setRng(i)}r.nodeChanged(),l=s=c=null}}),r.on("KeyUp",function(){i()}),{clear:i}}}),r(h,[l,u,p,c,m,d,g],function(e,t,n,r,i,o,a){function s(r){function i(e){return e?e.replace(/px$/,""):""}function a(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function s(e){l("left center right".split(" "),function(t){r.formatter.remove("align"+t,{},e)})}function c(){var e=r.dom,t,n,c;t=r.dom.getParent(r.selection.getStart(),"table"),c=!1,n={width:i(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:i(e.getStyle(t,"height")||e.getAttrib(t,"height")),cellspacing:e.getAttrib(t,"cellspacing"),cellpadding:e.getAttrib(t,"cellpadding"),border:e.getAttrib(t,"border"),caption:!!e.select("caption",t)[0]},l("left center right".split(" "),function(e){r.formatter.matchNode(t,"align"+e)&&(n.align=e)}),r.windowManager.open({title:"Table properties",items:{type:"form",layout:"grid",columns:2,data:n,defaults:{type:"textbox",maxWidth:50},items:[c?{label:"Cols",name:"cols",disabled:!0}:null,c?{label:"Rows",name:"rows",disabled:!0}:null,{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell spacing",name:"cellspacing"},{label:"Cell padding",name:"cellpadding"},{label:"Border",name:"border"},{label:"Caption",name:"caption",type:"checkbox"},{label:"Alignment",minWidth:90,name:"align",type:"listbox",text:"None",maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]}]},onsubmit:function(){var n=this.toJSON(),i;r.undoManager.transact(function(){r.dom.setAttribs(t,{cellspacing:n.cellspacing,cellpadding:n.cellpadding,border:n.border}),r.dom.setStyles(t,{width:a(n.width),height:a(n.height)}),i=e.select("caption",t)[0],i&&!n.caption&&e.remove(i),!i&&n.caption&&(i=e.create("caption"),i.innerHTML=o.ie?"\xa0":'
',t.insertBefore(i,t.firstChild)),s(t),n.align&&r.formatter.apply("align"+n.align,{},t),r.focus(),r.addVisual()})}})}function d(e,t){r.windowManager.open({title:"Merge cells",body:[{label:"Cols",name:"cols",type:"textbox",size:10},{label:"Rows",name:"rows",type:"textbox",size:10}],onsubmit:function(){var n=this.toJSON();r.undoManager.transact(function(){e.merge(t,n.cols,n.rows)})}})}function u(){var e=r.dom,t,n,o=[];o=r.dom.select("td.mce-item-selected,th.mce-item-selected"),t=r.dom.getParent(r.selection.getStart(),"td,th"),!o.length&&t&&o.push(t),t=t||o[0],n={width:i(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:i(e.getStyle(t,"height")||e.getAttrib(t,"height")),scope:e.getAttrib(t,"scope")},n.type=t.nodeName.toLowerCase(),l("left center right".split(" "),function(e){r.formatter.matchNode(t,"align"+e)&&(n.align=e)}),r.windowManager.open({title:"Cell properties",items:{type:"form",data:n,layout:"grid",columns:2,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell type",name:"type",type:"listbox",text:"None",minWidth:90,maxWidth:null,menu:[{text:"Cell",value:"td"},{text:"Header cell",value:"th"}]},{label:"Scope",name:"scope",type:"listbox",text:"None",minWidth:90,maxWidth:null,menu:[{text:"None",value:""},{text:"Row",value:"row"},{text:"Column",value:"col"},{text:"Row group",value:"rowgroup"},{text:"Column group",value:"colgroup"}]},{label:"Alignment",name:"align",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]}]},onsubmit:function(){var t=this.toJSON();r.undoManager.transact(function(){l(o,function(n){r.dom.setAttrib(n,"scope",t.scope),r.dom.setStyles(n,{width:a(t.width),height:a(t.height)}),t.type&&n.nodeName.toLowerCase()!=t.type&&(n=e.rename(n,t.type)),s(n),t.align&&r.formatter.apply("align"+t.align,{},n)}),r.focus()})}})}function f(){var e=r.dom,t,n,o,c,d=[];t=r.dom.getParent(r.selection.getStart(),"table"),n=r.dom.getParent(r.selection.getStart(),"td,th"),l(t.rows,function(t){l(t.cells,function(r){return e.hasClass(r,"mce-item-selected")||r==n?(d.push(t),!1):void 0})}),o=d[0],c={height:i(e.getStyle(o,"height")||e.getAttrib(o,"height")),scope:e.getAttrib(o,"scope")},c.type=o.parentNode.nodeName.toLowerCase(),l("left center right".split(" "),function(e){r.formatter.matchNode(o,"align"+e)&&(c.align=e)}),r.windowManager.open({title:"Row properties",items:{type:"form",data:c,columns:2,defaults:{type:"textbox"},items:[{type:"listbox",name:"type",label:"Row type",text:"None",maxWidth:null,menu:[{text:"Header",value:"thead"},{text:"Body",value:"tbody"},{text:"Footer",value:"tfoot"}]},{type:"listbox",name:"align",label:"Alignment",text:"None",maxWidth:null,menu:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"Height",name:"height"}]},onsubmit:function(){var t=this.toJSON(),n,i,o;r.undoManager.transact(function(){var c=t.type;l(d,function(l){r.dom.setAttrib(l,"scope",t.scope),r.dom.setStyles(l,{height:a(t.height)}),c!=l.parentNode.nodeName.toLowerCase()&&(n=e.getParent(l,"table"),i=l.parentNode,o=e.select(c,n)[0],o||(o=e.create(c),n.firstChild?n.insertBefore(o,n.firstChild):n.appendChild(o)),o.appendChild(l),i.hasChildNodes()||e.remove(i)),s(l),t.align&&r.formatter.apply("align"+t.align,{},l)}),r.focus()})}})}function p(e){return function(){r.execCommand(e)}}function m(e,t){var n,i,a;for(a="

",n=0;t>n;n++){for(a+="",i=0;e>i;i++)a+="";a+=""}a+="
"+(o.ie?" ":"
")+"
",r.insertContent(a)}function h(e,t){function n(){e.disabled(!r.dom.getParent(r.selection.getStart(),t)),r.selection.selectorChanged(t,function(t){e.disabled(!t)})}r.initialized?n():r.on("init",n)}function g(){h(this,"table")}function v(){h(this,"td,th")}function y(){var e="";e='';for(var t=0;10>t;t++){e+="";for(var n=0;10>n;n++)e+='';e+=""}return e+="",e+='
0 x 0
'}var b,C,x=this;r.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onhide:function(){r.dom.removeClass(this.menu.items()[0].getEl().getElementsByTagName("a"),"mce-active")},menu:[{type:"container",html:y(),onmousemove:function(e){var t,n,i=e.target;if("A"==i.nodeName){var o=r.dom.getParent(i,"table"),a=i.getAttribute("data-mce-index"),s=e.control.parent().rel;if(a!=this.lastPos){if(a=a.split(","),a[0]=parseInt(a[0],10),a[1]=parseInt(a[1],10),e.control.isRtl()||"tl-tr"==s){for(n=9;n>=0;n--)for(t=0;10>t;t++)r.dom.toggleClass(o.rows[n].childNodes[t].firstChild,"mce-active",t>=a[0]&&n<=a[1]);a[0]=9-a[0],o.nextSibling.innerHTML=a[0]+" x "+(a[1]+1)}else{for(n=0;10>n;n++)for(t=0;10>t;t++)r.dom.toggleClass(o.rows[n].childNodes[t].firstChild,"mce-active",t<=a[0]&&n<=a[1]);o.nextSibling.innerHTML=a[0]+1+" x "+(a[1]+1)}this.lastPos=a}}},onclick:function(e){"A"==e.target.nodeName&&this.lastPos&&(e.preventDefault(),m(this.lastPos[0]+1,this.lastPos[1]+1),this.parent().cancel())}}]}),r.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:g,onclick:c}),r.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:g,cmd:"mceTableDelete"}),r.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:p("mceTableCellProps"),onPostRender:v},{text:"Merge cells",onclick:p("mceTableMergeCells"),onPostRender:v},{text:"Split cell",onclick:p("mceTableSplitCells"),onPostRender:v}]}),r.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:p("mceTableInsertRowBefore"),onPostRender:v},{text:"Insert row after",onclick:p("mceTableInsertRowAfter"),onPostRender:v},{text:"Delete row",onclick:p("mceTableDeleteRow"),onPostRender:v},{text:"Row properties",onclick:p("mceTableRowProps"),onPostRender:v},{text:"-"},{text:"Cut row",onclick:p("mceTableCutRow"),onPostRender:v},{text:"Copy row",onclick:p("mceTableCopyRow"),onPostRender:v},{text:"Paste row before",onclick:p("mceTablePasteRowBefore"),onPostRender:v},{text:"Paste row after",onclick:p("mceTablePasteRowAfter"),onPostRender:v}]}),r.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:p("mceTableInsertColBefore"),onPostRender:v},{text:"Insert column after",onclick:p("mceTableInsertColAfter"),onPostRender:v},{text:"Delete column",onclick:p("mceTableDeleteCol"),onPostRender:v}]});var w=[];l("inserttable tableprops deletetable | cell row column".split(" "),function(e){"|"==e?w.push({text:"-"}):w.push(r.menuItems[e])}),r.addButton("table",{type:"menubutton",title:"Table",menu:w}),o.isIE||r.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(r.selection.select(e),r.nodeChanged())}),x.quirks=new t(r),r.on("Init",function(){b=r.windowManager,x.cellSelection=new n(r)}),l({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t,n,i;i=r.dom.getParent(r.selection.getStart(),"th,td"),i&&(t=i.rowSpan,n=i.colSpan),r.dom.select("td.mce-item-selected,th.mce-item-selected").length?e.merge():d(e,i)},mceTableInsertRowBefore:function(e){e.insertRow(!0)},mceTableInsertRowAfter:function(e){e.insertRow()},mceTableInsertColBefore:function(e){e.insertCol(!0)},mceTableInsertColAfter:function(e){e.insertCol()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){C=e.cutRows()},mceTableCopyRow:function(e){C=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(C,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(C)},mceTableDelete:function(e){e.deleteTable()}},function(t,n){r.addCommand(n,function(){var n=new e(r);n&&(t(n),r.execCommand("mceRepaint"),x.cellSelection.clear())})}),l({mceInsertTable:function(){c()},mceTableRowProps:f,mceTableCellProps:u},function(e,t){r.addCommand(t,function(t,n){e(n)})})}var l=r.each;a.add("table",s)}),a([l,u,p,h])}(this); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/template/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/template/plugin.min.js new file mode 100644 index 000000000..91a8b5fa2 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/template/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("template",function(e){function t(t){return function(){var a=e.settings.templates;"string"==typeof a?tinymce.util.XHR.send({url:a,success:function(e){t(tinymce.util.JSON.parse(e))}}):t(a)}}function a(t){function a(t){function a(t){if(-1==t.indexOf("")){var a="";tinymce.each(e.contentCSS,function(t){a+=''}),t=""+a+""+""+t+""+""}t=r(t,"template_preview_replace_values");var l=n.find("iframe")[0].getEl().contentWindow.document;l.open(),l.write(t),l.close()}var c=t.control.value();c.url?tinymce.util.XHR.send({url:c.url,success:function(e){l=e,a(l)}}):(l=c.content,a(l)),n.find("#description")[0].text(t.control.value().description)}var n,l,i=[];return t&&0!==t.length?(tinymce.each(t,function(e){i.push({selected:!i.length,text:e.title,value:{url:e.url,content:e.content,description:e.description}})}),n=e.windowManager.open({title:"Insert template",layout:"flex",direction:"column",align:"stretch",padding:15,spacing:10,items:[{type:"form",flex:0,padding:0,items:[{type:"container",label:"Templates",items:{type:"listbox",label:"Templates",name:"template",values:i,onselect:a}}]},{type:"label",name:"description",label:"Description",text:" "},{type:"iframe",flex:1,border:1}],onsubmit:function(){c(!1,l)},width:e.getParam("template_popup_width",600),height:e.getParam("template_popup_height",500)}),n.find("listbox")[0].fire("select"),void 0):(e.windowManager.alert("No templates defined"),void 0)}function n(t,a){function n(e,t){if(e=""+e,e.length0&&(o=p.create("div",null),o.appendChild(s[0].cloneNode(!0))),i(p.select("*",o),function(t){c(t,e.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_cdate_format",e.getLang("template.cdate_format")))),c(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format")))),c(t,e.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(t.innerHTML=m)}),l(o),e.execCommand("mceInsertContent",!1,o.innerHTML),e.addVisual()}var i=tinymce.each;e.addCommand("mceInsertTemplate",c),e.addButton("template",{title:"Insert template",onclick:t(a)}),e.addMenuItem("template",{text:"Insert template",onclick:t(a),context:"insert"}),e.on("PreProcess",function(t){var a=e.dom;i(a.select("div",t.node),function(t){a.hasClass(t,"mceTmpl")&&(i(a.select("*",t),function(t){a.hasClass(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format"))))}),l(t))})})}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/textcolor/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/textcolor/plugin.min.js new file mode 100644 index 000000000..ee943e497 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/textcolor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textcolor",function(e){function o(){var o,t,r=[];for(t=e.settings.textcolor_map||["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo","333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080","Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Brown","C0C0C0","Silver","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum","FFFFFF","White"],o=0;o',c=t.length-1,n=e.settings.textcolor_rows||5,a=e.settings.textcolor_cols||8,i=0;n>i;i++){for(l+="",F=0;a>F;F++)d=i*a+F,d>c?l+="":(r=t[d],l+='
'+"
"+"");l+=""}return l+=""}function r(o){var t,r=this.parent();(t=o.target.getAttribute("data-mce-color"))&&(r.hidePanel(),t="#"+t,r.color(t),e.execCommand(r.settings.selectcmd,!1,t))}function l(){var o=this;o._color&&e.execCommand(o.settings.selectcmd,!1,o._color)}e.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",selectcmd:"ForeColor",panel:{html:t,onclick:r},onclick:l}),e.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",selectcmd:"HiliteColor",panel:{html:t,onclick:r},onclick:l})}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/visualblocks/css/visualblocks.css b/app-admin/resources/tinymce-4.0.12/plugins/visualblocks/css/visualblocks.css new file mode 100644 index 000000000..fe6fa930a --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/visualblocks/css/visualblocks.css @@ -0,0 +1,128 @@ +.mce-visualblocks p { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7); +} + +.mce-visualblocks h1 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==); +} + +.mce-visualblocks h2 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==); +} + +.mce-visualblocks h3 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7); +} + +.mce-visualblocks h4 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==); +} + +.mce-visualblocks h5 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==); +} + +.mce-visualblocks h6 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==); +} + +.mce-visualblocks div { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7); +} + +.mce-visualblocks section { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=); +} + +.mce-visualblocks article { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7); +} + +.mce-visualblocks blockquote { + padding-top: 10px; + border: 1px dashed #BBB; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7); +} + +.mce-visualblocks address { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=); +} + +.mce-visualblocks pre { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==); +} + +.mce-visualblocks figure { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7); +} + +.mce-visualblocks hgroup { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7); +} + +.mce-visualblocks aside { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=); +} + +.mce-visualblocks figcaption { + border: 1px dashed #BBB; +} + +.mce-visualblocks ul { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==) +} + +.mce-visualblocks ol { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==); +} diff --git a/app-admin/resources/tinymce-4.0.12/plugins/visualblocks/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/visualblocks/plugin.min.js new file mode 100644 index 000000000..cafa41873 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/visualblocks/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualblocks",function(e,t){function n(){var t=this;t.active(r),e.on("VisualBlocks",function(){t.active(e.dom.hasClass(e.getBody(),"mce-visualblocks"))})}var i,a,r;window.NodeList&&(e.addCommand("mceVisualBlocks",function(){var n,o=e.dom;i||(i=o.uniqueId(),n=o.create("link",{id:i,rel:"stylesheet",href:t+"/css/visualblocks.css"}),e.getDoc().getElementsByTagName("head")[0].appendChild(n)),e.on("PreviewFormats AfterPreviewFormats",function(t){r&&o.toggleClass(e.getBody(),"mce-visualblocks","afterpreviewformats"==t.type)}),o.toggleClass(e.getBody(),"mce-visualblocks"),r=e.dom.hasClass(e.getBody(),"mce-visualblocks"),a&&a.active(o.hasClass(e.getBody(),"mce-visualblocks")),e.fire("VisualBlocks")}),e.addButton("visualblocks",{title:"Show blocks",cmd:"mceVisualBlocks",onPostRender:n}),e.addMenuItem("visualblocks",{text:"Show blocks",cmd:"mceVisualBlocks",onPostRender:n,selectable:!0,context:"view",prependToContext:!0}),e.on("init",function(){e.settings.visualblocks_default_state&&e.execCommand("mceVisualBlocks",!1,null,{skip_focus:!0})}),e.on("remove",function(){e.dom.removeClass(e.getBody(),"mce-visualblocks")}))}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/visualchars/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/visualchars/plugin.min.js new file mode 100644 index 000000000..447423884 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/visualchars/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualchars",function(e){function t(t){var n,a,r,o,l,s,c=e.getBody(),d=e.selection;if(i=!i,e.fire("VisualChars",{state:i}),t&&(s=d.getBookmark()),i)for(a=[],tinymce.walk(c,function(e){3==e.nodeType&&e.nodeValue&&-1!=e.nodeValue.indexOf(" ")&&a.push(e)},"childNodes"),r=0;r$1'),l=e.dom.create("div",null,o);n=l.lastChild;)e.dom.insertAfter(n,a[r]);e.dom.remove(a[r])}else for(a=e.dom.select("span.mce-nbsp",c),r=a.length-1;r>=0;r--)e.dom.remove(a[r],1);d.moveToBookmark(s)}function n(){var t=this;e.on("VisualChars",function(e){t.active(e.state)})}var i;e.addCommand("mceVisualChars",t),e.addButton("visualchars",{title:"Show invisible characters",cmd:"mceVisualChars",onPostRender:n}),e.addMenuItem("visualchars",{text:"Show invisible characters",cmd:"mceVisualChars",onPostRender:n,selectable:!0,context:"view",prependToContext:!0}),e.on("beforegetcontent",function(e){i&&"raw"!=e.format&&!e.draft&&(i=!0,t(!1))})}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/plugins/wordcount/plugin.min.js b/app-admin/resources/tinymce-4.0.12/plugins/wordcount/plugin.min.js new file mode 100644 index 000000000..acda5d044 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/plugins/wordcount/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("wordcount",function(e){function t(){e.theme.panel.find("#wordcount").text(["Words: {0}",a.getCount()])}var n,o,a=this;n=e.getParam("wordcount_countregex",/[\w\u2019\x27\-\u0600-\u06FF]+/g),o=e.getParam("wordcount_cleanregex",/[0-9.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g),e.on("init",function(){var n=e.theme.panel&&e.theme.panel.find("#statusbar")[0];n&&window.setTimeout(function(){n.insert({type:"label",name:"wordcount",text:["Words: {0}",a.getCount()],classes:"wordcount",disabled:e.settings.readonly},0),e.on("setcontent beforeaddundo",t),e.on("keyup",function(e){32==e.keyCode&&t()})},0)}),a.getCount=function(){var t=e.getContent({format:"raw"}),a=0;if(t){t=t.replace(/\.\.\./g," "),t=t.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," "),t=t.replace(/(\w+)(&.+?;)+(\w+)/,"$1$3").replace(/&.+?;/g," "),t=t.replace(o,"");var r=t.match(n);r&&(a=r.length)}return a}}); \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/content.inline.min.css b/app-admin/resources/tinymce-4.0.12/skins/lightgray/content.inline.min.css new file mode 100644 index 000000000..2f0db0e95 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/skins/lightgray/content.inline.min.css @@ -0,0 +1 @@ +.mce-object{border:1px dotted #3A3A3A;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp{background:#AAA}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{background:url(img/wline.gif) repeat-x bottom left;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td.mce-item-selected,th.mce-item-selected{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333} \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/content.min.css b/app-admin/resources/tinymce-4.0.12/skins/lightgray/content.min.css new file mode 100644 index 000000000..340a53778 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/skins/lightgray/content.min.css @@ -0,0 +1 @@ +body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px}.mce-object{border:1px dotted #3A3A3A;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp{background:#AAA}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{background:url(img/wline.gif) repeat-x bottom left;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td.mce-item-selected,th.mce-item-selected{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333} \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/readme.md b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/readme.md new file mode 100644 index 000000000..fa5d63946 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/readme.md @@ -0,0 +1 @@ +Icons are generated and provided by the http://icomoon.io service. diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.eot b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.eot new file mode 100644 index 000000000..128a98f3d Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.eot differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.svg b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.svg new file mode 100644 index 000000000..fd5e3ff4d --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.svg @@ -0,0 +1,175 @@ + + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.ttf b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.ttf new file mode 100644 index 000000000..7b50bfdae Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.ttf differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.woff b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.woff new file mode 100644 index 000000000..725aaf19e Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce-small.woff differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.eot b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.eot new file mode 100644 index 000000000..b769c2c66 Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.eot differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.svg b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.svg new file mode 100644 index 000000000..fe4e31bf0 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.svg @@ -0,0 +1,153 @@ + + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.ttf b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.ttf new file mode 100644 index 000000000..a31b584c2 Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.ttf differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.woff b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.woff new file mode 100644 index 000000000..f0e8a34c6 Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/fonts/tinymce.woff differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/anchor.gif b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/anchor.gif new file mode 100644 index 000000000..606348c7f Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/anchor.gif differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/loader.gif b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/loader.gif new file mode 100644 index 000000000..c69e93723 Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/loader.gif differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/object.gif b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/object.gif new file mode 100644 index 000000000..cccd7f023 Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/object.gif differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/trans.gif b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/trans.gif new file mode 100644 index 000000000..388486517 Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/trans.gif differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/wline.gif b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/wline.gif new file mode 100644 index 000000000..7d0a4dbca Binary files /dev/null and b/app-admin/resources/tinymce-4.0.12/skins/lightgray/img/wline.gif differ diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/skin.ie7.min.css b/app-admin/resources/tinymce-4.0.12/skins/lightgray/skin.ie7.min.css new file mode 100644 index 000000000..509ce7f07 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/skins/lightgray/skin.ie7.min.css @@ -0,0 +1 @@ +.mce-container,.mce-container *,.mce-widget,.mce-widget *{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-container ::-webkit-scrollbar{width:8px;height:8px;-webkit-border-radius:4px}.mce-container ::-webkit-scrollbar-track,.mce-container ::-webkit-scrollbar-track-piece{background-color:transparent}.mce-container ::-webkit-scrollbar-thumb{background-color:rgba(53,57,71,0.3);width:6px;height:6px;-webkit-border-radius:4px}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.mce-tinymce{visibility:visible !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}div.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid #9e9e9e;width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#d9d9d9}.mce-grid td div{border:1px solid #d6d6d6;width:12px;height:12px;margin:2px;cursor:pointer}.mce-grid{border-spacing:2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover{border-color:#a1a1a1}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#d6d6d6;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#a1a1a1;background:#c8def4}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-toolbar-grp{padding-bottom:2px}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scroll{position:relative}.mce-panel{border:0 solid #9e9e9e;background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fdfdfd, #ddd);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fdfdfd), to(#ddd));background-image:-webkit-linear-gradient(top, #fdfdfd, #ddd);background-image:-o-linear-gradient(top, #fdfdfd, #ddd);background-image:linear-gradient(to bottom, #fdfdfd, #ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd', endColorstr='#ffdddddd', GradientType=0);zoom:1}.mce-floatpanel{position:absolute;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2)}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);top:0;left:0;background:#fff;border:1px solid #9e9e9e;border:1px solid rgba(0,0,0,0.25)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#9e9e9e;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;background:#fff;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#fff;position:fixed;top:0;left:0;opacity:0;-webkit-transition:opacity 150ms ease-in;transition:opacity 150ms ease-in}.mce-window.mce-in{opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:15px;top:9px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-close:hover{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:10px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#fff;border-top:1px solid #c5c5c5;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window.mce-fullscreen,.mce-window.mce-fullscreen .mce-foot{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:#fff;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-inner{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-tooltip-inner{-webkit-box-shadow:0 0 5px #000000;-moz-box-shadow:0 0 5px #000000;box-shadow:0 0 5px #000000}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-n .mce-tooltip-arrow{top:0px;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-btn{border:1px solid #b1b1b1;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25) rgba(0,0,0,0.25);position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fff, #d9d9d9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#d9d9d9));background-image:-webkit-linear-gradient(top, #fff, #d9d9d9);background-image:-o-linear-gradient(top, #fff, #d9d9d9);background-image:linear-gradient(to bottom, #fff, #d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffd9d9d9', GradientType=0);zoom:1}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;background-image:-moz-linear-gradient(top, #f2f2f2, #ccc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#ccc));background-image:-webkit-linear-gradient(top, #f2f2f2, #ccc);background-image:-o-linear-gradient(top, #f2f2f2, #ccc);background-image:linear-gradient(to bottom, #f2f2f2, #ccc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffcccccc', GradientType=0);zoom:1}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#d6d6d6;background-image:-moz-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#c0c0c0));background-image:-webkit-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-o-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:linear-gradient(to bottom, #e6e6e6, #c0c0c0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffc0c0c0', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-btn:not(.mce-disabled):active{background-color:#d6d6d6;background-image:-moz-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#c0c0c0));background-image:-webkit-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-o-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:linear-gradient(to bottom, #e6e6e6, #c0c0c0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffc0c0c0', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-btn button{padding:4px 10px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px #fff}.mce-primary{min-width:50px;color:#fff;border:1px solid #b1b1b1;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25) rgba(0,0,0,0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #08c, #04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);zoom:1}.mce-primary:hover,.mce-primary:focus{background-color:#005fb3;background-image:-moz-linear-gradient(top, #0077b3, #003cb3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0077b3), to(#003cb3));background-image:-webkit-linear-gradient(top, #0077b3, #003cb3);background-image:-o-linear-gradient(top, #0077b3, #003cb3);background-image:linear-gradient(to bottom, #0077b3, #003cb3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0077b3', endColorstr='#ff003cb3', GradientType=0);zoom:1}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#005299;background-image:-moz-linear-gradient(top, #069, #039);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#069), to(#039));background-image:-webkit-linear-gradient(top, #069, #039);background-image:-o-linear-gradient(top, #069, #039);background-image:linear-gradient(to bottom, #069, #039);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff006699', endColorstr='#ff003399', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px #333}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px 0 1px 0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-btn-group .mce-first{border-left:1px solid #b1b1b1;border-left:1px solid rgba(0,0,0,0.25);-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.mce-btn-group .mce-last{border-right:1px solid #b1b1b1;border-right:1px solid rgba(0,0,0,0.1);-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.mce-btn-group .mce-first.mce-last{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fff, #d9d9d9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#d9d9d9));background-image:-webkit-linear-gradient(top, #fff, #d9d9d9);background-image:-o-linear-gradient(top, #fff, #d9d9d9);background-image:linear-gradient(to bottom, #fff, #d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffd9d9d9', GradientType=0);zoom:1;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:4px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-14px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;border-left:1px solid transparent;border-right:1px solid transparent}.mce-colorbutton:hover .mce-open{border-left-color:#bdbdbd;border-right-color:#bdbdbd}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:4px;margin-right:-14px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;margin-right:-17px;padding-left:0}.mce-rtl .mce-colorbutton button{padding-right:10px;padding-left:10px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px}.mce-combobox{display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox.mce-has-open input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.mce-combobox .mce-btn{border-left:0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9E9E9E;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid #9e9e9e;width:100%;height:100%}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);border:0;overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:none}.mce-menubar{border:1px solid #c4c4c4}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:transparent;background:#e6e6e6;filter:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-menubtn.mce-disabled span{color:#aaa}.mce-menubtn span{color:#333;margin-right:2px;line-height:20px;*line-height:16px}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text{color:#fff}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:#fff}.mce-menu-item.mce-disabled:hover{background:#ccc}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:#fff}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:#fff}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#c8def4}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:#333}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:#fff}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:#fff;background-color:#0081c2;background-image:-moz-linear-gradient(top, #08c, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3));background-image:-webkit-linear-gradient(top, #08c, #0077b3);background-image:-o-linear-gradient(top, #08c, #0077b3);background-image:linear-gradient(to bottom, #08c, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);zoom:1}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:#cbcbcb;border-bottom:1px solid #fff;cursor:default;filter:none}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:#fff}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:2px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent;border-right:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#bdbdbd;border-right-color:#bdbdbd}.mce-splitbtn button{padding-right:4px}.mce-splitbtn .mce-open{padding-left:4px}.mce-splitbtn .mce-open.mce-active{-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:10px;padding-left:10px}.mce-rtl .mce-splitbtn .mce-open{padding-left:4px;padding-right:4px}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#e3e3e3;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#fdfdfd}.mce-tab.mce-active{background:#fdfdfd;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65)}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce';font-style:normal;font-weight:normal;font-size:16px;line-height:16px;vertical-align:text-top;-webkit-font-smoothing:antialiased;display:inline-block;background:transparent center center;width:16px;height:16px;color:#333;-ie7-icon:' '}.mce-btn-small .mce-ico{font-family:'tinymce-small'}.mce-ico,i.mce-i-checkbox{zoom:expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = this.currentStyle['-ie7-icon'].substr(1, 1) + ' ')}.mce-i-save{-ie7-icon:"\e000"}.mce-i-newdocument{-ie7-icon:"\e001"}.mce-i-fullpage{-ie7-icon:"\e002"}.mce-i-alignleft{-ie7-icon:"\e003"}.mce-i-aligncenter{-ie7-icon:"\e004"}.mce-i-alignright{-ie7-icon:"\e005"}.mce-i-alignjustify{-ie7-icon:"\e006"}.mce-i-cut{-ie7-icon:"\e007"}.mce-i-paste{-ie7-icon:"\e008"}.mce-i-searchreplace{-ie7-icon:"\e009"}.mce-i-bullist{-ie7-icon:"\e00a"}.mce-i-numlist{-ie7-icon:"\e00b"}.mce-i-indent{-ie7-icon:"\e00c"}.mce-i-outdent{-ie7-icon:"\e00d"}.mce-i-blockquote{-ie7-icon:"\e00e"}.mce-i-undo{-ie7-icon:"\e00f"}.mce-i-redo{-ie7-icon:"\e010"}.mce-i-link{-ie7-icon:"\e011"}.mce-i-unlink{-ie7-icon:"\e012"}.mce-i-anchor{-ie7-icon:"\e013"}.mce-i-image{-ie7-icon:"\e014"}.mce-i-media{-ie7-icon:"\e015"}.mce-i-help{-ie7-icon:"\e016"}.mce-i-code{-ie7-icon:"\e017"}.mce-i-inserttime{-ie7-icon:"\e018"}.mce-i-preview{-ie7-icon:"\e019"}.mce-i-forecolor{-ie7-icon:"\e01a"}.mce-i-backcolor{-ie7-icon:"\e01a"}.mce-i-table{-ie7-icon:"\e01b"}.mce-i-hr{-ie7-icon:"\e01c"}.mce-i-removeformat{-ie7-icon:"\e01d"}.mce-i-subscript{-ie7-icon:"\e01e"}.mce-i-superscript{-ie7-icon:"\e01f"}.mce-i-charmap{-ie7-icon:"\e020"}.mce-i-emoticons{-ie7-icon:"\e021"}.mce-i-print{-ie7-icon:"\e022"}.mce-i-fullscreen{-ie7-icon:"\e023"}.mce-i-spellchecker{-ie7-icon:"\e024"}.mce-i-nonbreaking{-ie7-icon:"\e025"}.mce-i-template{-ie7-icon:"\e026"}.mce-i-pagebreak{-ie7-icon:"\e027"}.mce-i-restoredraft{-ie7-icon:"\e028"}.mce-i-untitled{-ie7-icon:"\e029"}.mce-i-bold{-ie7-icon:"\e02a"}.mce-i-italic{-ie7-icon:"\e02b"}.mce-i-underline{-ie7-icon:"\e02c"}.mce-i-strikethrough{-ie7-icon:"\e02d"}.mce-i-visualchars{-ie7-icon:"\e02e"}.mce-i-ltr{-ie7-icon:"\e02f"}.mce-i-rtl{-ie7-icon:"\e030"}.mce-i-copy{-ie7-icon:"\e031"}.mce-i-resize{-ie7-icon:"\e032"}.mce-i-browse{-ie7-icon:"\e034"}.mce-i-pastetext{-ie7-icon:"\e035"}.mce-i-checkbox,.mce-i-selected{-ie7-icon:"\e033"}.mce-i-selected{visibility:hidden}.mce-i-backcolor{background:#BBB} \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/skins/lightgray/skin.min.css b/app-admin/resources/tinymce-4.0.12/skins/lightgray/skin.min.css new file mode 100644 index 000000000..bcf7b87dd --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/skins/lightgray/skin.min.css @@ -0,0 +1 @@ +.mce-container,.mce-container *,.mce-widget,.mce-widget *{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-container ::-webkit-scrollbar{width:8px;height:8px;-webkit-border-radius:4px}.mce-container ::-webkit-scrollbar-track,.mce-container ::-webkit-scrollbar-track-piece{background-color:transparent}.mce-container ::-webkit-scrollbar-thumb{background-color:rgba(53,57,71,0.3);width:6px;height:6px;-webkit-border-radius:4px}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.mce-tinymce{visibility:visible !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}div.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid #9e9e9e;width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#d9d9d9}.mce-grid td div{border:1px solid #d6d6d6;width:12px;height:12px;margin:2px;cursor:pointer}.mce-grid{border-spacing:2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover{border-color:#a1a1a1}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#d6d6d6;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#a1a1a1;background:#c8def4}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-toolbar-grp{padding-bottom:2px}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scroll{position:relative}.mce-panel{border:0 solid #9e9e9e;background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fdfdfd, #ddd);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fdfdfd), to(#ddd));background-image:-webkit-linear-gradient(top, #fdfdfd, #ddd);background-image:-o-linear-gradient(top, #fdfdfd, #ddd);background-image:linear-gradient(to bottom, #fdfdfd, #ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd', endColorstr='#ffdddddd', GradientType=0);zoom:1}.mce-floatpanel{position:absolute;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2)}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);top:0;left:0;background:#fff;border:1px solid #9e9e9e;border:1px solid rgba(0,0,0,0.25)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#9e9e9e;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;background:#fff;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#fff;position:fixed;top:0;left:0;opacity:0;-webkit-transition:opacity 150ms ease-in;transition:opacity 150ms ease-in}.mce-window.mce-in{opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:15px;top:9px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-close:hover{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:10px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#fff;border-top:1px solid #c5c5c5;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window.mce-fullscreen,.mce-window.mce-fullscreen .mce-foot{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:#fff;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-inner{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-tooltip-inner{-webkit-box-shadow:0 0 5px #000000;-moz-box-shadow:0 0 5px #000000;box-shadow:0 0 5px #000000}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-n .mce-tooltip-arrow{top:0px;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-btn{border:1px solid #b1b1b1;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25) rgba(0,0,0,0.25);position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fff, #d9d9d9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#d9d9d9));background-image:-webkit-linear-gradient(top, #fff, #d9d9d9);background-image:-o-linear-gradient(top, #fff, #d9d9d9);background-image:linear-gradient(to bottom, #fff, #d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffd9d9d9', GradientType=0);zoom:1}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;background-image:-moz-linear-gradient(top, #f2f2f2, #ccc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#ccc));background-image:-webkit-linear-gradient(top, #f2f2f2, #ccc);background-image:-o-linear-gradient(top, #f2f2f2, #ccc);background-image:linear-gradient(to bottom, #f2f2f2, #ccc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffcccccc', GradientType=0);zoom:1}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#d6d6d6;background-image:-moz-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#c0c0c0));background-image:-webkit-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-o-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:linear-gradient(to bottom, #e6e6e6, #c0c0c0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffc0c0c0', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-btn:not(.mce-disabled):active{background-color:#d6d6d6;background-image:-moz-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#c0c0c0));background-image:-webkit-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-o-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:linear-gradient(to bottom, #e6e6e6, #c0c0c0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffc0c0c0', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-btn button{padding:4px 10px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px #fff}.mce-primary{min-width:50px;color:#fff;border:1px solid #b1b1b1;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25) rgba(0,0,0,0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #08c, #04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);zoom:1}.mce-primary:hover,.mce-primary:focus{background-color:#005fb3;background-image:-moz-linear-gradient(top, #0077b3, #003cb3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0077b3), to(#003cb3));background-image:-webkit-linear-gradient(top, #0077b3, #003cb3);background-image:-o-linear-gradient(top, #0077b3, #003cb3);background-image:linear-gradient(to bottom, #0077b3, #003cb3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0077b3', endColorstr='#ff003cb3', GradientType=0);zoom:1}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#005299;background-image:-moz-linear-gradient(top, #069, #039);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#069), to(#039));background-image:-webkit-linear-gradient(top, #069, #039);background-image:-o-linear-gradient(top, #069, #039);background-image:linear-gradient(to bottom, #069, #039);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff006699', endColorstr='#ff003399', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px #333}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px 0 1px 0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-btn-group .mce-first{border-left:1px solid #b1b1b1;border-left:1px solid rgba(0,0,0,0.25);-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.mce-btn-group .mce-last{border-right:1px solid #b1b1b1;border-right:1px solid rgba(0,0,0,0.1);-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.mce-btn-group .mce-first.mce-last{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fff, #d9d9d9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#d9d9d9));background-image:-webkit-linear-gradient(top, #fff, #d9d9d9);background-image:-o-linear-gradient(top, #fff, #d9d9d9);background-image:linear-gradient(to bottom, #fff, #d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffd9d9d9', GradientType=0);zoom:1;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:4px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-14px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;border-left:1px solid transparent;border-right:1px solid transparent}.mce-colorbutton:hover .mce-open{border-left-color:#bdbdbd;border-right-color:#bdbdbd}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:4px;margin-right:-14px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;margin-right:-17px;padding-left:0}.mce-rtl .mce-colorbutton button{padding-right:10px;padding-left:10px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px}.mce-combobox{display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox.mce-has-open input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.mce-combobox .mce-btn{border-left:0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9E9E9E;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid #9e9e9e;width:100%;height:100%}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);border:0;overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:none}.mce-menubar{border:1px solid #c4c4c4}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:transparent;background:#e6e6e6;filter:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-menubtn.mce-disabled span{color:#aaa}.mce-menubtn span{color:#333;margin-right:2px;line-height:20px;*line-height:16px}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text{color:#fff}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:#fff}.mce-menu-item.mce-disabled:hover{background:#ccc}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:#fff}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:#fff}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#c8def4}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:#333}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:#fff}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:#fff;background-color:#0081c2;background-image:-moz-linear-gradient(top, #08c, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3));background-image:-webkit-linear-gradient(top, #08c, #0077b3);background-image:-o-linear-gradient(top, #08c, #0077b3);background-image:linear-gradient(to bottom, #08c, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);zoom:1}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:#cbcbcb;border-bottom:1px solid #fff;cursor:default;filter:none}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:#fff}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:2px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent;border-right:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#bdbdbd;border-right-color:#bdbdbd}.mce-splitbtn button{padding-right:4px}.mce-splitbtn .mce-open{padding-left:4px}.mce-splitbtn .mce-open.mce-active{-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:10px;padding-left:10px}.mce-rtl .mce-splitbtn .mce-open{padding-left:4px;padding-right:4px}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#e3e3e3;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#fdfdfd}.mce-tab.mce-active{background:#fdfdfd;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65)}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce',Arial;font-style:normal;font-weight:normal;font-size:16px;line-height:16px;vertical-align:text-top;-webkit-font-smoothing:antialiased;display:inline-block;background:transparent center center;width:16px;height:16px;color:#333}.mce-btn-small .mce-ico{font-family:'tinymce-small',Arial}.mce-i-save:before{content:"\e000"}.mce-i-newdocument:before{content:"\e001"}.mce-i-fullpage:before{content:"\e002"}.mce-i-alignleft:before{content:"\e003"}.mce-i-aligncenter:before{content:"\e004"}.mce-i-alignright:before{content:"\e005"}.mce-i-alignjustify:before{content:"\e006"}.mce-i-cut:before{content:"\e007"}.mce-i-paste:before{content:"\e008"}.mce-i-searchreplace:before{content:"\e009"}.mce-i-bullist:before{content:"\e00a"}.mce-i-numlist:before{content:"\e00b"}.mce-i-indent:before{content:"\e00c"}.mce-i-outdent:before{content:"\e00d"}.mce-i-blockquote:before{content:"\e00e"}.mce-i-undo:before{content:"\e00f"}.mce-i-redo:before{content:"\e010"}.mce-i-link:before{content:"\e011"}.mce-i-unlink:before{content:"\e012"}.mce-i-anchor:before{content:"\e013"}.mce-i-image:before{content:"\e014"}.mce-i-media:before{content:"\e015"}.mce-i-help:before{content:"\e016"}.mce-i-code:before{content:"\e017"}.mce-i-inserttime:before{content:"\e018"}.mce-i-preview:before{content:"\e019"}.mce-i-forecolor:before{content:"\e01a"}.mce-i-backcolor:before{content:"\e01a"}.mce-i-table:before{content:"\e01b"}.mce-i-hr:before{content:"\e01c"}.mce-i-removeformat:before{content:"\e01d"}.mce-i-subscript:before{content:"\e01e"}.mce-i-superscript:before{content:"\e01f"}.mce-i-charmap:before{content:"\e020"}.mce-i-emoticons:before{content:"\e021"}.mce-i-print:before{content:"\e022"}.mce-i-fullscreen:before{content:"\e023"}.mce-i-spellchecker:before{content:"\e024"}.mce-i-nonbreaking:before{content:"\e025"}.mce-i-template:before{content:"\e026"}.mce-i-pagebreak:before{content:"\e027"}.mce-i-restoredraft:before{content:"\e028"}.mce-i-untitled:before{content:"\e029"}.mce-i-bold:before{content:"\e02a"}.mce-i-italic:before{content:"\e02b"}.mce-i-underline:before{content:"\e02c"}.mce-i-strikethrough:before{content:"\e02d"}.mce-i-visualchars:before{content:"\e02e"}.mce-i-visualblocks:before{content:"\e02e"}.mce-i-ltr:before{content:"\e02f"}.mce-i-rtl:before{content:"\e030"}.mce-i-copy:before{content:"\e031"}.mce-i-resize:before{content:"\e032"}.mce-i-browse:before{content:"\e034"}.mce-i-pastetext:before{content:"\e035"}.mce-i-checkbox:before,.mce-i-selected:before{content:"\e033"}.mce-i-selected{visibility:hidden}i.mce-i-backcolor{text-shadow:none;background:#bbb} \ No newline at end of file diff --git a/app-admin/resources/tinymce-4.0.12/themes/modern/theme.min.js b/app-admin/resources/tinymce-4.0.12/themes/modern/theme.min.js new file mode 100644 index 000000000..6869cf761 --- /dev/null +++ b/app-admin/resources/tinymce-4.0.12/themes/modern/theme.min.js @@ -0,0 +1 @@ +tinymce.ThemeManager.add("modern",function(e){function t(){function t(t){var i,o=[];if(t)return d(t.split(/[ ,]/),function(t){function n(){var n=e.selection;"bullist"==r&&n.selectorChanged("ul > li",function(e,n){for(var i,o=n.parents.length;o--&&(i=n.parents[o].nodeName,"OL"!=i&&"UL"!=i););t.active(e&&"UL"==i)}),"numlist"==r&&n.selectorChanged("ol > li",function(e,n){for(var i,o=n.parents.length;o--&&(i=n.parents[o].nodeName,"OL"!=i&&"UL"!=i););t.active(e&&"OL"==i)}),t.settings.stateSelector&&n.selectorChanged(t.settings.stateSelector,function(e){t.active(e)},!0),t.settings.disabledStateSelector&&n.selectorChanged(t.settings.disabledStateSelector,function(e){t.disabled(e)})}var r;"|"==t?i=null:c.has(t)?(t={type:t},u.toolbar_items_size&&(t.size=u.toolbar_items_size),o.push(t),i=null):(i||(i={type:"buttongroup",items:[]},o.push(i)),e.buttons[t]&&(r=t,t=e.buttons[r],"function"==typeof t&&(t=t()),t.type=t.type||"button",u.toolbar_items_size&&(t.size=u.toolbar_items_size),t=c.create(t),i.items.push(t),e.initialized?n():e.on("init",n)))}),n.push({type:"toolbar",layout:"flow",items:o}),!0}for(var n=[],i=1;10>i&&t(u["toolbar"+i]);i++);return n.length||t(u.toolbar||f),n}function n(){function t(t){var n;return"|"==t?{text:"|"}:n=e.menuItems[t]}function n(n){var i,o,r,a,s;if(s=tinymce.makeMap((u.removed_menuitems||"").split(/[ ,]/)),u.menu?(o=u.menu[n],a=!0):o=h[n],o){i={text:o.title},r=[],d((o.items||"").split(/[ ,]/),function(e){var n=t(e);n&&!s[e]&&r.push(t(e))}),a||d(e.menuItems,function(e){e.context==n&&("before"==e.separator&&r.push({text:"|"}),e.prependToContext?r.unshift(e):r.push(e),"after"==e.separator&&r.push({text:"|"}))});for(var l=0;l1?e:"0"+e}return"#"+i(t)+i(n)+i(r)}var r=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,i=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,o=/\s*([^:]+):\s*([^;]+);?/g,a=/\s+$/,s,l,c={},d,u="\ufeff";for(e=e||{},d=("\\\" \\' \\; \\: ; : "+u).split(" "),l=0;l-1&&n||(h[e+t]=-1==l?s[0]:s.join(" "),delete h[e+"-top"+t],delete h[e+"-right"+t],delete h[e+"-bottom"+t],delete h[e+"-left"+t])}}function d(e){var t=h[e],n;if(t){for(t=t.split(" "),n=t.length;n--;)if(t[n]!==t[0])return!1;return h[e]=t[0],!0}}function u(e,t,n,r){d(t)&&d(n)&&d(r)&&(h[e]=h[t]+" "+h[n]+" "+h[r],delete h[t],delete h[n],delete h[r])}function f(e){return b=!0,c[e]}function p(e,t){return b&&(e=e.replace(/\uFEFF[0-9]/g,function(e){return c[e]})),t||(e=e.replace(/\\([\'\";:])/g,"$1")),e}function m(t,n,r,i,o,a){return(o=o||a)?(o=p(o),"'"+o.replace(/\'/g,"\\'")+"'"):(n=p(n||r||i),!e.allow_script_urls&&/(java|vb)script:/i.test(n.replace(/[\s\r\n]+/,""))?"":(C&&(n=C.call(x,n,"style")),"url('"+n.replace(/\'/g,"\\'")+"')"))}var h={},g,v,y,b,C=e.url_converter,x=e.url_converter_scope||this;if(t){for(t=t.replace(/[\u0000-\u001F]/g,""),t=t.replace(/\\[\"\';:\uFEFF]/g,f).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(e){return e.replace(/[;:]/g,f)});g=o.exec(t);){if(v=g[1].replace(a,"").toLowerCase(),y=g[2].replace(a,""),v&&y.length>0){if(!e.allow_script_urls&&("behavior"==v||/expression\s*\(/.test(y)))continue;"font-weight"===v&&"700"===y?y="bold":("color"===v||"background-color"===v)&&(y=y.toLowerCase()),y=y.replace(r,n),y=y.replace(i,m),h[v]=b?p(y,!0):y}o.lastIndex=g.index+g[0].length}s("border","",!0),s("border","-width"),s("border","-color"),s("border","-style"),s("padding",""),s("margin",""),u("border","border-width","border-style","border-color"),"medium none"===h.border&&delete h.border,"none"===h["border-image"]&&delete h["border-image"]}return h},serialize:function(e,n){function r(n){var r,o,a,l;if(r=t.styles[n])for(o=0,a=r.length;a>o;o++)n=r[o],l=e[n],l!==s&&l.length>0&&(i+=(i.length>0?" ":"")+n+": "+l+";")}var i="",o,a;if(n&&t&&t.styles)r("*"),r(n);else for(o in e)a=e[o],a!==s&&a.length>0&&(i+=(i.length>0?" ":"")+o+": "+a+";");return i}}}}),r(d,[],function(){function e(e,t,n,r){e.addEventListener?e.addEventListener(t,n,r||!1):e.attachEvent&&e.attachEvent("on"+t,n)}function t(e,t,n,r){e.removeEventListener?e.removeEventListener(t,n,r||!1):e.detachEvent&&e.detachEvent("on"+t,n)}function n(e,t){function n(){return!1}function r(){return!0}var i,o=t||{},l;for(i in e)s[i]||(o[i]=e[i]);if(o.target||(o.target=o.srcElement||document),e&&a.test(e.type)&&e.pageX===l&&e.clientX!==l){var c=o.target.ownerDocument||document,d=c.documentElement,u=c.body;o.pageX=e.clientX+(d&&d.scrollLeft||u&&u.scrollLeft||0)-(d&&d.clientLeft||u&&u.clientLeft||0),o.pageY=e.clientY+(d&&d.scrollTop||u&&u.scrollTop||0)-(d&&d.clientTop||u&&u.clientTop||0)}return o.preventDefault=function(){o.isDefaultPrevented=r,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},o.stopPropagation=function(){o.isPropagationStopped=r,e&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)},o.stopImmediatePropagation=function(){o.isImmediatePropagationStopped=r,o.stopPropagation()},o.isDefaultPrevented||(o.isDefaultPrevented=n,o.isPropagationStopped=n,o.isImmediatePropagationStopped=n),o}function r(n,r,i){function o(){i.domLoaded||(i.domLoaded=!0,r(c))}function a(){"complete"===l.readyState&&(t(l,"readystatechange",a),o())}function s(){try{l.documentElement.doScroll("left")}catch(e){return setTimeout(s,0),void 0}o()}var l=n.document,c={type:"ready"};return i.domLoaded?(r(c),void 0):(l.addEventListener?"complete"===l.readyState?o():e(n,"DOMContentLoaded",o):(e(l,"readystatechange",a),l.documentElement.doScroll&&n===n.top&&s()),e(n,"load",o),void 0)}function i(){function i(e,t){var n,r,i,o,a=s[t];if(n=a&&a[e.type])for(r=0,i=n.length;i>r;r++)if(o=n[r],o&&o.func.call(o.scope,e)===!1&&e.preventDefault(),e.isImmediatePropagationStopped())return}var a=this,s={},l,c,d,u,f;c=o+(+new Date).toString(32),u="onmouseenter"in document.documentElement,d="onfocusin"in document.documentElement,f={mouseenter:"mouseover",mouseleave:"mouseout"},l=1,a.domLoaded=!1,a.events=s,a.bind=function(t,o,p,m){function h(e){i(n(e||_.event),g)}var g,v,y,b,C,x,w,_=window;if(t&&3!==t.nodeType&&8!==t.nodeType){for(t[c]?g=t[c]:(g=l++,t[c]=g,s[g]={}),m=m||t,o=o.split(" "),y=o.length;y--;)b=o[y],x=h,C=w=!1,"DOMContentLoaded"===b&&(b="ready"),a.domLoaded&&"ready"===b&&"complete"==t.readyState?p.call(m,n({type:b})):(u||(C=f[b],C&&(x=function(e){var t,r;if(t=e.currentTarget,r=e.relatedTarget,r&&t.contains)r=t.contains(r);else for(;r&&r!==t;)r=r.parentNode;r||(e=n(e||_.event),e.type="mouseout"===e.type?"mouseleave":"mouseenter",e.target=t,i(e,g))})),d||"focusin"!==b&&"focusout"!==b||(w=!0,C="focusin"===b?"focus":"blur",x=function(e){e=n(e||_.event),e.type="focus"===e.type?"focusin":"focusout",i(e,g)}),v=s[g][b],v?"ready"===b&&a.domLoaded?p({type:b}):v.push({func:p,scope:m}):(s[g][b]=v=[{func:p,scope:m}],v.fakeName=C,v.capture=w,v.nativeHandler=x,"ready"===b?r(t,x,a):e(t,C||b,x,w)));return t=v=0,p}},a.unbind=function(e,n,r){var i,o,l,d,u,f;if(!e||3===e.nodeType||8===e.nodeType)return a;if(i=e[c]){if(f=s[i],n){for(n=n.split(" "),l=n.length;l--;)if(u=n[l],o=f[u]){if(r)for(d=o.length;d--;)if(o[d].func===r){var p=o.nativeHandler;o=o.slice(0,d).concat(o.slice(d+1)),o.nativeHandler=p,f[u]=o}r&&0!==o.length||(delete f[u],t(e,o.fakeName||u,o.nativeHandler,o.capture))}}else{for(u in f)o=f[u],t(e,o.fakeName||u,o.nativeHandler,o.capture);f={}}for(u in f)return a;delete s[i];try{delete e[c]}catch(m){e[c]=null}}return a},a.fire=function(e,t,r){var o;if(!e||3===e.nodeType||8===e.nodeType)return a;r=n(null,r),r.type=t,r.target=e;do o=e[c],o&&i(r,o),e=e.parentNode||e.ownerDocument||e.defaultView||e.parentWindow;while(e&&!r.isPropagationStopped());return a},a.clean=function(e){var t,n,r=a.unbind;if(!e||3===e.nodeType||8===e.nodeType)return a;if(e[c]&&r(e),e.getElementsByTagName||(e=e.document),e&&e.getElementsByTagName)for(r(e),n=e.getElementsByTagName("*"),t=n.length;t--;)e=n[t],e[c]&&r(e);return a},a.destroy=function(){s={}},a.cancel=function(e){return e&&(e.preventDefault(),e.stopImmediatePropagation()),!1}}var o="mce-data-",a=/^(?:mouse|contextmenu)|click/,s={keyLocation:1,layerX:1,layerY:1,returnValue:1};return i.Event=new i,i.Event.bind(window,"ready",function(){}),i}),r(u,[],function(){return function(e,t){function n(e,n,r,i){var o,a;if(e){if(!i&&e[n])return e[n];if(e!=t){if(o=e[r])return o;for(a=e.parentNode;a&&a!=t;a=a.parentNode)if(o=a[r])return o}}}var r=e;this.current=function(){return r},this.next=function(e){return r=n(r,"firstChild","nextSibling",e)},this.prev=function(e){return r=n(r,"lastChild","previousSibling",e)}}}),r(f,[],function(){function e(e,n){return n?"array"==n&&g(e)?!0:typeof e==n:e!==t}function n(e){var t=[],n,r;for(n=0,r=e.length;r>n;n++)t[n]=e[n];return t}function r(e,t,n){var r;for(e=e||[],t=t||",","string"==typeof e&&(e=e.split(t)),n=n||{},r=e.length;r--;)n[e[r]]={};return n}function i(e,n,r){var i,o;if(!e)return 0;if(r=r||e,e.length!==t){for(i=0,o=e.length;o>i;i++)if(n.call(r,e[i],i,e)===!1)return 0}else for(i in e)if(e.hasOwnProperty(i)&&n.call(r,e[i],i,e)===!1)return 0;return 1}function o(e,t){var n=[];return i(e,function(e){n.push(t(e))}),n}function a(e,t){var n=[];return i(e,function(e){(!t||t(e))&&n.push(e)}),n}function s(e,t,n){var r=this,i,o,a,s,l,c=0;if(e=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(e),a=e[3].match(/(^|\.)(\w+)$/i)[2],o=r.createNS(e[3].replace(/\.\w+$/,""),n),!o[a]){if("static"==e[2])return o[a]=t,this.onCreate&&this.onCreate(e[2],e[3],o[a]),void 0;t[a]||(t[a]=function(){},c=1),o[a]=t[a],r.extend(o[a].prototype,t),e[5]&&(i=r.resolve(e[5]).prototype,s=e[5].match(/\.(\w+)$/i)[1],l=o[a],o[a]=c?function(){return i[s].apply(this,arguments)}:function(){return this.parent=i[s],l.apply(this,arguments)},o[a].prototype[a]=o[a],r.each(i,function(e,t){o[a].prototype[t]=i[t]}),r.each(t,function(e,t){i[t]?o[a].prototype[t]=function(){return this.parent=i[t],e.apply(this,arguments)}:t!=a&&(o[a].prototype[t]=e)})),r.each(t["static"],function(e,t){o[a][t]=e})}}function l(e,t){var n,r;if(e)for(n=0,r=e.length;r>n;n++)if(e[n]===t)return n;return-1}function c(e,n){var r,i,o,a=arguments,s;for(r=1,i=a.length;i>r;r++){n=a[r];for(o in n)n.hasOwnProperty(o)&&(s=n[o],s!==t&&(e[o]=s))}return e}function d(e,t,n,r){r=r||this,e&&(n&&(e=e[n]),i(e,function(e,i){return t.call(r,e,i,n)===!1?!1:(d(e,t,n,r),void 0)}))}function u(e,t){var n,r;for(t=t||window,e=e.split("."),n=0;nn&&(t=t[e[n]],t);n++);return t}function p(t,n){return!t||e(t,"array")?t:o(t.split(n||","),h)}var m=/^\s*|\s*$/g,h=function(e){return null===e||e===t?"":(""+e).replace(m,"")},g=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};return{trim:h,isArray:g,is:e,toArray:n,makeMap:r,each:i,map:o,grep:a,inArray:l,extend:c,create:s,walk:d,createNS:u,resolve:f,explode:p}}),r(p,[f],function(e){function t(n){function r(){return M.createDocumentFragment()}function i(e,t){_(F,e,t)}function o(e,t){_(z,e,t)}function a(e){i(e.parentNode,$(e))}function s(e){i(e.parentNode,$(e)+1)}function l(e){o(e.parentNode,$(e))}function c(e){o(e.parentNode,$(e)+1)}function d(e){e?(D[U]=D[V],D[q]=D[W]):(D[V]=D[U],D[W]=D[q]),D.collapsed=F}function u(e){a(e),c(e)}function f(e){i(e,0),o(e,1===e.nodeType?e.childNodes.length:e.nodeValue.length)}function p(e,t){var n=D[V],r=D[W],i=D[U],o=D[q],a=t.startContainer,s=t.startOffset,l=t.endContainer,c=t.endOffset;return 0===e?w(n,r,a,s):1===e?w(i,o,a,s):2===e?w(i,o,l,c):3===e?w(n,r,l,c):void 0}function m(){N(I)}function h(){return N(P)}function g(){return N(O)}function v(e){var t=this[V],r=this[W],i,o;3!==t.nodeType&&4!==t.nodeType||!t.nodeValue?(t.childNodes.length>0&&(o=t.childNodes[r]),o?t.insertBefore(e,o):3==t.nodeType?n.insertAfter(e,t):t.appendChild(e)):r?r>=t.nodeValue.length?n.insertAfter(e,t):(i=t.splitText(r),t.parentNode.insertBefore(e,i)):t.parentNode.insertBefore(e,t)}function y(e){var t=D.extractContents();D.insertNode(e),e.appendChild(t),D.selectNode(e)}function b(){return j(new t(n),{startContainer:D[V],startOffset:D[W],endContainer:D[U],endOffset:D[q],collapsed:D.collapsed,commonAncestorContainer:D.commonAncestorContainer})}function C(e,t){var n;if(3==e.nodeType)return e;if(0>t)return e;for(n=e.firstChild;n&&t>0;)--t,n=n.nextSibling;return n?n:e}function x(){return D[V]==D[U]&&D[W]==D[q]}function w(e,t,r,i){var o,a,s,l,c,d;if(e==r)return t==i?0:i>t?-1:1;for(o=r;o&&o.parentNode!=e;)o=o.parentNode;if(o){for(a=0,s=e.firstChild;s!=o&&t>a;)a++,s=s.nextSibling;return a>=t?-1:1}for(o=e;o&&o.parentNode!=r;)o=o.parentNode;if(o){for(a=0,s=r.firstChild;s!=o&&i>a;)a++,s=s.nextSibling;return i>a?-1:1}for(l=n.findCommonAncestor(e,r),c=e;c&&c.parentNode!=l;)c=c.parentNode;for(c||(c=l),d=r;d&&d.parentNode!=l;)d=d.parentNode;if(d||(d=l),c==d)return 0;for(s=l.firstChild;s;){if(s==c)return-1;if(s==d)return 1;s=s.nextSibling}}function _(e,t,r){var i,o;for(e?(D[V]=t,D[W]=r):(D[U]=t,D[q]=r),i=D[U];i.parentNode;)i=i.parentNode;for(o=D[V];o.parentNode;)o=o.parentNode;o==i?w(D[V],D[W],D[U],D[q])>0&&D.collapse(e):D.collapse(e),D.collapsed=x(),D.commonAncestorContainer=n.findCommonAncestor(D[V],D[U])}function N(e){var t,n=0,r=0,i,o,a,s,l,c;if(D[V]==D[U])return E(e);for(t=D[U],i=t.parentNode;i;t=i,i=i.parentNode){if(i==D[V])return k(t,e);++n}for(t=D[V],i=t.parentNode;i;t=i,i=i.parentNode){if(i==D[U])return S(t,e);++r}for(o=r-n,a=D[V];o>0;)a=a.parentNode,o--;for(s=D[U];0>o;)s=s.parentNode,o++;for(l=a.parentNode,c=s.parentNode;l!=c;l=l.parentNode,c=c.parentNode)a=l,s=c;return T(a,s,e)}function E(e){var t,n,i,o,a,s,l,c,d;if(e!=I&&(t=r()),D[W]==D[q])return t;if(3==D[V].nodeType){if(n=D[V].nodeValue,i=n.substring(D[W],D[q]),e!=O&&(o=D[V],c=D[W],d=D[q]-D[W],0===c&&d>=o.nodeValue.length-1?o.parentNode.removeChild(o):o.deleteData(c,d),D.collapse(F)),e==I)return;return i.length>0&&t.appendChild(M.createTextNode(i)),t}for(o=C(D[V],D[W]),a=D[q]-D[W];o&&a>0;)s=o.nextSibling,l=L(o,e),t&&t.appendChild(l),--a,o=s;return e!=O&&D.collapse(F),t}function k(e,t){var n,i,o,a,s,l;if(t!=I&&(n=r()),i=R(e,t),n&&n.appendChild(i),o=$(e),a=o-D[W],0>=a)return t!=O&&(D.setEndBefore(e),D.collapse(z)),n;for(i=e.previousSibling;a>0;)s=i.previousSibling,l=L(i,t),n&&n.insertBefore(l,n.firstChild),--a,i=s;return t!=O&&(D.setEndBefore(e),D.collapse(z)),n}function S(e,t){var n,i,o,a,s,l;for(t!=I&&(n=r()),o=A(e,t),n&&n.appendChild(o),i=$(e),++i,a=D[q]-i,o=e.nextSibling;o&&a>0;)s=o.nextSibling,l=L(o,t),n&&n.appendChild(l),--a,o=s;return t!=O&&(D.setStartAfter(e),D.collapse(F)),n}function T(e,t,n){var i,o,a,s,l,c,d,u;for(n!=I&&(o=r()),i=A(e,n),o&&o.appendChild(i),a=e.parentNode,s=$(e),l=$(t),++s,c=l-s,d=e.nextSibling;c>0;)u=d.nextSibling,i=L(d,n),o&&o.appendChild(i),d=u,--c;return i=R(t,n),o&&o.appendChild(i),n!=O&&(D.setStartAfter(e),D.collapse(F)),o}function R(e,t){var n=C(D[U],D[q]-1),r,i,o,a,s,l=n!=D[U];if(n==e)return B(n,l,z,t);for(r=n.parentNode,i=B(r,z,z,t);r;){for(;n;)o=n.previousSibling,a=B(n,l,z,t),t!=I&&i.insertBefore(a,i.firstChild),l=F,n=o;if(r==e)return i;n=r.previousSibling,r=r.parentNode,s=B(r,z,z,t),t!=I&&s.appendChild(i),i=s}}function A(e,t){var n=C(D[V],D[W]),r=n!=D[V],i,o,a,s,l;if(n==e)return B(n,r,F,t);for(i=n.parentNode,o=B(i,z,F,t);i;){for(;n;)a=n.nextSibling,s=B(n,r,F,t),t!=I&&o.appendChild(s),r=F,n=a;if(i==e)return o;n=i.nextSibling,i=i.parentNode,l=B(i,z,F,t),t!=I&&l.appendChild(o),o=l}}function B(e,t,r,i){var o,a,s,l,c;if(t)return L(e,i);if(3==e.nodeType){if(o=e.nodeValue,r?(l=D[W],a=o.substring(l),s=o.substring(0,l)):(l=D[q],a=o.substring(0,l),s=o.substring(l)),i!=O&&(e.nodeValue=s),i==I)return;return c=n.clone(e,z),c.nodeValue=a,c}if(i!=I)return n.clone(e,z)}function L(e,t){return t!=I?t==O?n.clone(e,F):e:(e.parentNode.removeChild(e),void 0)}function H(){return n.create("body",null,g()).outerText}var D=this,M=n.doc,P=0,O=1,I=2,F=!0,z=!1,W="startOffset",V="startContainer",U="endContainer",q="endOffset",j=e.extend,$=n.nodeIndex;return j(D,{startContainer:M,startOffset:0,endContainer:M,endOffset:0,collapsed:F,commonAncestorContainer:M,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:i,setEnd:o,setStartBefore:a,setStartAfter:s,setEndBefore:l,setEndAfter:c,collapse:d,selectNode:u,selectNodeContents:f,compareBoundaryPoints:p,deleteContents:m,extractContents:h,cloneContents:g,insertNode:v,surroundContents:y,cloneRange:b,toStringIE:H}),D}return t.prototype.toString=function(){return this.toStringIE()},t}),r(m,[f],function(e){function t(e){var t;return t=document.createElement("div"),t.innerHTML=e,t.textContent||t.innerText||e}function n(e,t){var n,r,i,a={};if(e){for(e=e.split(","),t=t||10,n=0;n\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,l=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,c=/[<>&\"\']/g,d=/&(#x|#)?([\w]+);/g,u={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"};o={'"':""","'":"'","<":"<",">":">","&":"&"},a={"<":"<",">":">","&":"&",""":'"',"'":"'"},i=n("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);var f={encodeRaw:function(e,t){return e.replace(t?s:l,function(e){return o[e]||e})},encodeAllRaw:function(e){return(""+e).replace(c,function(e){return o[e]||e})},encodeNumeric:function(e,t){return e.replace(t?s:l,function(e){return e.length>1?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":o[e]||"&#"+e.charCodeAt(0)+";"})},encodeNamed:function(e,t,n){return n=n||i,e.replace(t?s:l,function(e){return o[e]||n[e]||e})},getEncodeFunc:function(e,t){function a(e,n){return e.replace(n?s:l,function(e){return o[e]||t[e]||"&#"+e.charCodeAt(0)+";"||e})}function c(e,n){return f.encodeNamed(e,n,t)}return t=n(t)||i,e=r(e.replace(/\+/g,",")),e.named&&e.numeric?a:e.named?t?c:f.encodeNamed:e.numeric?f.encodeNumeric:f.encodeRaw},decode:function(e){return e.replace(d,function(e,n,r){return n?(r=parseInt(r,2===n.length?16:10),r>65535?(r-=65536,String.fromCharCode(55296+(r>>10),56320+(1023&r))):u[r]||String.fromCharCode(r)):a[e]||i[e]||t(e)})}};return f}),r(h,[],function(){var e=navigator,t=e.userAgent,n,r,i,o,a,s,l;n=window.opera&&window.opera.buildNumber,r=/WebKit/.test(t),i=!r&&!n&&/MSIE/gi.test(t)&&/Explorer/gi.test(e.appName),i=i&&/MSIE (\w+)\./.exec(t)[1],o=-1==t.indexOf("Trident/")||-1==t.indexOf("rv:")&&-1==e.appName.indexOf("Netscape")?!1:11,i=i||o,a=!r&&!o&&/Gecko/.test(t),s=-1!=t.indexOf("Mac"),l=/(iPad|iPhone)/.test(t);var c=!l||t.match(/AppleWebKit\/(\d*)/)[1]>=534;return{opera:n,webkit:r,ie:i,gecko:a,mac:s,iOS:l,contentEditable:c,transparentSrc:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",caretAfter:8!=i,range:window.getSelection&&"Range"in window,documentMode:i?document.documentMode||7:10}}),r(g,[l,c,d,u,p,m,h,f],function(e,n,r,i,o,a,s,l){function c(e,t){var i=this,o;i.doc=e,i.win=window,i.files={},i.counter=0,i.stdMode=!g||e.documentMode>=8,i.boxModel=!g||"CSS1Compat"==e.compatMode||i.stdMode,i.hasOuterHTML="outerHTML"in e.createElement("a"),this.boundEvents=[],i.settings=t=m({keep_values:!1,hex_colors:1},t),i.schema=t.schema,i.styles=new n({url_converter:t.url_converter,url_converter_scope:t.url_converter_scope},t.schema),i.fixDoc(e),i.events=t.ownEvents?new r(t.proxy):r.Event,o=t.schema?t.schema.getBlockElements():{},i.isBlock=function(e){if(!e)return!1;var t=e.nodeType;return t?!(1!==t||!o[e.nodeName]):!!o[e]}}var d=l.each,u=l.is,f=l.grep,p=l.trim,m=l.extend,h=s.webkit,g=s.ie,v=/^([a-z0-9],?)+$/i,y=/^[ \t\r\n]*$/,b=l.makeMap("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"," ");return c.prototype={root:null,props:{"for":"htmlFor","class":"className",className:"className",checked:"checked",disabled:"disabled",maxlength:"maxLength",readonly:"readOnly",selected:"selected",value:"value",id:"id",name:"name",type:"type"},fixDoc:function(e){var t=this.settings,n;if(g&&t.schema){"abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video".replace(/\w+/g,function(t){e.createElement(t)});for(n in t.schema.getCustomElements())e.createElement(n)}},clone:function(e,t){var n=this,r,i;return!g||1!==e.nodeType||t?e.cloneNode(t):(i=n.doc,t?r.firstChild:(r=i.createElement(e.nodeName),d(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),r))},getRoot:function(){var e=this;return e.get(e.settings.root_element)||e.doc.body},getViewPort:function(e){var t,n;return e=e?e:this.win,t=e.document,n=this.boxModel?t.documentElement:t.body,{x:e.pageXOffset||n.scrollLeft,y:e.pageYOffset||n.scrollTop,w:e.innerWidth||n.clientWidth,h:e.innerHeight||n.clientHeight}},getRect:function(e){var t=this,n,r;return e=t.get(e),n=t.getPos(e),r=t.getSize(e),{x:n.x,y:n.y,w:r.w,h:r.h}},getSize:function(e){var t=this,n,r;return e=t.get(e),n=t.getStyle(e,"width"),r=t.getStyle(e,"height"),-1===n.indexOf("px")&&(n=0),-1===r.indexOf("px")&&(r=0),{w:parseInt(n,10)||e.offsetWidth||e.clientWidth,h:parseInt(r,10)||e.offsetHeight||e.clientHeight}},getParent:function(e,t,n){return this.getParents(e,t,n,!1)},getParents:function(e,n,r,i){var o=this,a,s=[];for(e=o.get(e),i=i===t,r=r||("BODY"!=o.getRoot().nodeName?o.getRoot().parentNode:null),u(n,"string")&&(a=n,n="*"===n?function(e){return 1==e.nodeType}:function(e){return o.is(e,a)});e&&e!=r&&e.nodeType&&9!==e.nodeType;){if(!n||n(e)){if(!i)return e;s.push(e)}e=e.parentNode}return i?s:null},get:function(e){var t;return e&&this.doc&&"string"==typeof e&&(t=e,e=this.doc.getElementById(e),e&&e.id!==t)?this.doc.getElementsByName(t)[1]:e},getNext:function(e,t){return this._findSib(e,t,"nextSibling")},getPrev:function(e,t){return this._findSib(e,t,"previousSibling")},select:function(t,n){var r=this;return e(t,r.get(n)||r.get(r.settings.root_element)||r.doc,[])},is:function(n,r){var i;if(n.length===t){if("*"===r)return 1==n.nodeType;if(v.test(r)){for(r=r.toLowerCase().split(/,/),n=n.nodeName.toLowerCase(),i=r.length-1;i>=0;i--)if(r[i]==n)return!0;return!1}}return n.nodeType&&1!=n.nodeType?!1:e.matches(r,n.nodeType?[n]:n).length>0},add:function(e,t,n,r,i){var o=this;return this.run(e,function(e){var a;return a=u(t,"string")?o.doc.createElement(t):t,o.setAttribs(a,n),r&&(r.nodeType?a.appendChild(r):o.setHTML(a,r)),i?a:e.appendChild(a)})},create:function(e,t,n){return this.add(this.doc.createElement(e),e,t,n,1)},createHTML:function(e,t,n){var r="",i;r+="<"+e;for(i in t)t.hasOwnProperty(i)&&null!==t[i]&&(r+=" "+i+'="'+this.encode(t[i])+'"');return"undefined"!=typeof n?r+">"+n+"":r+" />"},createFragment:function(e){var t,n,r=this.doc,i;for(i=r.createElement("div"),t=r.createDocumentFragment(),e&&(i.innerHTML=e);n=i.firstChild;)t.appendChild(n);return t},remove:function(e,t){return this.run(e,function(e){var n,r=e.parentNode;if(!r)return null;if(t)for(;n=e.firstChild;)!g||3!==n.nodeType||n.nodeValue?r.insertBefore(n,e):e.removeChild(n);return r.removeChild(e)})},setStyle:function(e,t,n){return this.run(e,function(e){var r=this,i,o;if(t)if("string"==typeof t){i=e.style,t=t.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),"number"!=typeof n||b[t]||(n+="px"),"opacity"===t&&e.runtimeStyle&&"undefined"==typeof e.runtimeStyle.opacity&&(i.filter=""===n?"":"alpha(opacity="+100*n+")"),"float"==t&&(t="cssFloat"in e.style?"cssFloat":"styleFloat");try{i[t]=n}catch(a){}r.settings.update_styles&&e.removeAttribute("data-mce-style")}else for(o in t)r.setStyle(e,o,t[o])})},getStyle:function(e,n,r){if(e=this.get(e)){if(this.doc.defaultView&&r){n=n.replace(/[A-Z]/g,function(e){return"-"+e});try{return this.doc.defaultView.getComputedStyle(e,null).getPropertyValue(n)}catch(i){return null}}return n=n.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),"float"==n&&(n=g?"styleFloat":"cssFloat"),e.currentStyle&&r?e.currentStyle[n]:e.style?e.style[n]:t}},setStyles:function(e,t){this.setStyle(e,t)},css:function(e,t,n){this.setStyle(e,t,n)},removeAllAttribs:function(e){return this.run(e,function(e){var t,n=e.attributes;for(t=n.length-1;t>=0;t--)e.removeAttributeNode(n.item(t))})},setAttrib:function(e,t,n){var r=this;if(e&&t)return this.run(e,function(e){var i=r.settings,o=e.getAttribute(t);if(null!==n)switch(t){case"style":if(!u(n,"string"))return d(n,function(t,n){r.setStyle(e,n,t)}),void 0;i.keep_values&&(n?e.setAttribute("data-mce-style",n,2):e.removeAttribute("data-mce-style",2)),e.style.cssText=n;break;case"class":e.className=n||"";break;case"src":case"href":i.keep_values&&(i.url_converter&&(n=i.url_converter.call(i.url_converter_scope||r,n,t,e)),r.setAttrib(e,"data-mce-"+t,n,2));break;case"shape":e.setAttribute("data-mce-style",n)}u(n)&&null!==n&&0!==n.length?e.setAttribute(t,""+n,2):e.removeAttribute(t,2),o!=n&&i.onSetAttrib&&i.onSetAttrib({attrElm:e,attrName:t,attrValue:n})})},setAttribs:function(e,t){var n=this;return this.run(e,function(e){d(t,function(t,r){n.setAttrib(e,r,t)})})},getAttrib:function(e,t,n){var r,i=this,o;if(e=i.get(e),!e||1!==e.nodeType)return n===o?!1:n;if(u(n)||(n=""),/^(src|href|style|coords|shape)$/.test(t)&&(r=e.getAttribute("data-mce-"+t)))return r;if(g&&i.props[t]&&(r=e[i.props[t]],r=r&&r.nodeValue?r.nodeValue:r),r||(r=e.getAttribute(t,2)),/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(t))return e[i.props[t]]===!0&&""===r?t:r?t:"";if("FORM"===e.nodeName&&e.getAttributeNode(t))return e.getAttributeNode(t).nodeValue;if("style"===t&&(r=r||e.style.cssText,r&&(r=i.serializeStyle(i.parseStyle(r),e.nodeName),i.settings.keep_values&&e.setAttribute("data-mce-style",r))),h&&"class"===t&&r&&(r=r.replace(/(apple|webkit)\-[a-z\-]+/gi,"")),g)switch(t){case"rowspan":case"colspan":1===r&&(r="");break;case"size":("+0"===r||20===r||0===r)&&(r="");break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":0===r&&(r="");break;case"hspace":-1===r&&(r="");break;case"maxlength":case"tabindex":(32768===r||2147483647===r||"32768"===r)&&(r="");break;case"multiple":case"compact":case"noshade":case"nowrap":return 65535===r?t:n;case"shape":r=r.toLowerCase();break;default:0===t.indexOf("on")&&r&&(r=(""+r).replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1"))}return r!==o&&null!==r&&""!==r?""+r:n},getPos:function(e,t){var n=this,r=0,i=0,o,a=n.doc,s;if(e=n.get(e),t=t||a.body,e){if(t===a.body&&e.getBoundingClientRect)return s=e.getBoundingClientRect(),t=n.boxModel?a.documentElement:a.body,r=s.left+(a.documentElement.scrollLeft||a.body.scrollLeft)-t.clientTop,i=s.top+(a.documentElement.scrollTop||a.body.scrollTop)-t.clientLeft,{x:r,y:i};for(o=e;o&&o!=t&&o.nodeType;)r+=o.offsetLeft||0,i+=o.offsetTop||0,o=o.offsetParent;for(o=e.parentNode;o&&o!=t&&o.nodeType;)r-=o.scrollLeft||0,i-=o.scrollTop||0,o=o.parentNode}return{x:r,y:i}},parseStyle:function(e){return this.styles.parse(e)},serializeStyle:function(e,t){return this.styles.serialize(e,t)},addStyle:function(e){var t=this,n=t.doc,r,i;if(t!==c.DOM&&n===document){var o=c.DOM.addedStyles;if(o=o||[],o[e])return;o[e]=!0,c.DOM.addedStyles=o}i=n.getElementById("mceDefaultStyles"),i||(i=n.createElement("style"),i.id="mceDefaultStyles",i.type="text/css",r=n.getElementsByTagName("head")[0],r.firstChild?r.insertBefore(i,r.firstChild):r.appendChild(i)),i.styleSheet?i.styleSheet.cssText+=e:i.appendChild(n.createTextNode(e))},loadCSS:function(e){var t=this,n=t.doc,r;return t!==c.DOM&&n===document?(c.DOM.loadCSS(e),void 0):(e||(e=""),r=n.getElementsByTagName("head")[0],d(e.split(","),function(e){var i;t.files[e]||(t.files[e]=!0,i=t.create("link",{rel:"stylesheet",href:e}),g&&n.documentMode&&n.recalc&&(i.onload=function(){n.recalc&&n.recalc(),i.onload=null +}),r.appendChild(i))}),void 0)},addClass:function(e,t){return this.run(e,function(e){var n;return t?this.hasClass(e,t)?e.className:(n=this.removeClass(e,t),e.className=n=(""!==n?n+" ":"")+t,n):0})},removeClass:function(e,t){var n=this,r;return n.run(e,function(e){var i;return n.hasClass(e,t)?(r||(r=new RegExp("(^|\\s+)"+t+"(\\s+|$)","g")),i=e.className.replace(r," "),i=p(" "!=i?i:""),e.className=i,i||(e.removeAttribute("class"),e.removeAttribute("className")),i):e.className})},hasClass:function(e,t){return e=this.get(e),e&&t?-1!==(" "+e.className+" ").indexOf(" "+t+" "):!1},toggleClass:function(e,n,r){r=r===t?!this.hasClass(e,n):r,this.hasClass(e,n)!==r&&(r?this.addClass(e,n):this.removeClass(e,n))},show:function(e){return this.setStyle(e,"display","block")},hide:function(e){return this.setStyle(e,"display","none")},isHidden:function(e){return e=this.get(e),!e||"none"==e.style.display||"none"==this.getStyle(e,"display")},uniqueId:function(e){return(e?e:"mce_")+this.counter++},setHTML:function(e,t){var n=this;return n.run(e,function(e){if(g){for(;e.firstChild;)e.removeChild(e.firstChild);try{e.innerHTML="
"+t,e.removeChild(e.firstChild)}catch(r){var i=n.create("div");i.innerHTML="
"+t,d(f(i.childNodes),function(t,n){n&&e.canHaveHTML&&e.appendChild(t)})}}else e.innerHTML=t;return t})},getOuterHTML:function(e){var t,n=this;return(e=n.get(e))?1===e.nodeType&&n.hasOuterHTML?e.outerHTML:(t=(e.ownerDocument||n.doc).createElement("body"),t.appendChild(e.cloneNode(!0)),t.innerHTML):null},setOuterHTML:function(e,t,n){var r=this;return r.run(e,function(e){function i(){var i,o;for(o=n.createElement("body"),o.innerHTML=t,i=o.lastChild;i;)r.insertAfter(i.cloneNode(!0),e),i=i.previousSibling;r.remove(e)}if(1==e.nodeType)if(n=n||e.ownerDocument||r.doc,g)try{1==e.nodeType&&r.hasOuterHTML?e.outerHTML=t:i()}catch(o){i()}else i()})},decode:a.decode,encode:a.encodeAllRaw,insertAfter:function(e,t){return t=this.get(t),this.run(e,function(e){var n,r;return n=t.parentNode,r=t.nextSibling,r?n.insertBefore(e,r):n.appendChild(e),e})},replace:function(e,t,n){var r=this;return r.run(t,function(t){return u(t,"array")&&(e=e.cloneNode(!0)),n&&d(f(t.childNodes),function(t){e.appendChild(t)}),t.parentNode.replaceChild(e,t)})},rename:function(e,t){var n=this,r;return e.nodeName!=t.toUpperCase()&&(r=n.create(t),d(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),n.replace(r,e,1)),r||e},findCommonAncestor:function(e,t){for(var n=e,r;n;){for(r=t;r&&n!=r;)r=r.parentNode;if(n==r)break;n=n.parentNode}return!n&&e.ownerDocument?e.ownerDocument.documentElement:n},toHex:function(e){return this.styles.toHex(l.trim(e))},run:function(e,t,n){var r=this,i;return"string"==typeof e&&(e=r.get(e)),e?(n=n||this,e.nodeType||!e.length&&0!==e.length?t.call(n,e):(i=[],d(e,function(e,o){e&&("string"==typeof e&&(e=r.get(e)),i.push(t.call(n,e,o)))}),i)):!1},getAttribs:function(e){var t;if(e=this.get(e),!e)return[];if(g){if(t=[],"OBJECT"==e.nodeName)return e.attributes;"OPTION"===e.nodeName&&this.getAttrib(e,"selected")&&t.push({specified:1,nodeName:"selected"});var n=/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;return e.cloneNode(!1).outerHTML.replace(n,"").replace(/[\w:\-]+/gi,function(e){t.push({specified:1,nodeName:e})}),t}return e.attributes},isEmpty:function(e,t){var n=this,r,o,a,s,l,c=0;if(e=e.firstChild){s=new i(e,e.parentNode),t=t||n.schema?n.schema.getNonEmptyElements():null;do{if(a=e.nodeType,1===a){if(e.getAttribute("data-mce-bogus"))continue;if(l=e.nodeName.toLowerCase(),t&&t[l]){if("br"===l){c++;continue}return!1}for(o=n.getAttribs(e),r=e.attributes.length;r--;)if(l=e.attributes[r].nodeName,"name"===l||"data-mce-bookmark"===l)return!1}if(8==a)return!1;if(3===a&&!y.test(e.nodeValue))return!1}while(e=s.next())}return 1>=c},createRng:function(){var e=this.doc;return e.createRange?e.createRange():new o(this)},nodeIndex:function(e,t){var n=0,r,i,o;if(e)for(r=e.nodeType,e=e.previousSibling,i=e;e;e=e.previousSibling)o=e.nodeType,(!t||3!=o||o!=r&&e.nodeValue.length)&&(n++,r=o);return n},split:function(e,t,n){function r(e){function t(e){var t=e.previousSibling&&"SPAN"==e.previousSibling.nodeName,n=e.nextSibling&&"SPAN"==e.nextSibling.nodeName;return t&&n}var n,o=e.childNodes,a=e.nodeType;if(1!=a||"bookmark"!=e.getAttribute("data-mce-type")){for(n=o.length-1;n>=0;n--)r(o[n]);if(9!=a){if(3==a&&e.nodeValue.length>0){var s=p(e.nodeValue).length;if(!i.isBlock(e.parentNode)||s>0||0===s&&t(e))return}else if(1==a&&(o=e.childNodes,1==o.length&&o[0]&&1==o[0].nodeType&&"bookmark"==o[0].getAttribute("data-mce-type")&&e.parentNode.insertBefore(o[0],e),o.length||/^(br|hr|input|img)$/i.test(e.nodeName)))return;i.remove(e)}return e}}var i=this,o=i.createRng(),a,s,l;return e&&t?(o.setStart(e.parentNode,i.nodeIndex(e)),o.setEnd(t.parentNode,i.nodeIndex(t)),a=o.extractContents(),o=i.createRng(),o.setStart(t.parentNode,i.nodeIndex(t)+1),o.setEnd(e.parentNode,i.nodeIndex(e)+1),s=o.extractContents(),l=e.parentNode,l.insertBefore(r(a),e),n?l.replaceChild(n,t):l.insertBefore(t,e),l.insertBefore(r(s),e),i.remove(e),n||t):void 0},bind:function(e,t,n,r){var i=this;if(l.isArray(e)){for(var o=e.length;o--;)e[o]=i.bind(e[o],t,n,r);return e}return!i.settings.collect||e!==i.doc&&e!==i.win||i.boundEvents.push([e,t,n,r]),i.events.bind(e,t,n,r||i)},unbind:function(e,t,n){var r=this,i;if(l.isArray(e)){for(i=e.length;i--;)e[i]=r.unbind(e[i],t,n);return e}if(r.boundEvents&&(e===r.doc||e===r.win))for(i=r.boundEvents.length;i--;){var o=r.boundEvents[i];e!=o[0]||t&&t!=o[1]||n&&n!=o[2]||this.events.unbind(o[0],o[1],o[2])}return this.events.unbind(e,t,n)},fire:function(e,t,n){return this.events.fire(e,t,n)},getContentEditable:function(e){var t;return 1!=e.nodeType?null:(t=e.getAttribute("data-mce-contenteditable"),t&&"inherit"!==t?t:"inherit"!==e.contentEditable?e.contentEditable:null)},destroy:function(){var t=this;if(t.boundEvents){for(var n=t.boundEvents.length;n--;){var r=t.boundEvents[n];this.events.unbind(r[0],r[1],r[2])}t.boundEvents=null}e.setDocument&&e.setDocument(),t.win=t.doc=t.root=t.events=t.frag=null},dumpRng:function(e){return"startContainer: "+e.startContainer.nodeName+", startOffset: "+e.startOffset+", endContainer: "+e.endContainer.nodeName+", endOffset: "+e.endOffset},_findSib:function(e,t,n){var r=this,i=t;if(e)for("string"==typeof i&&(i=function(e){return r.is(e,t)}),e=e[n];e;e=e[n])if(i(e))return e;return null}},c.DOM=new c(document),c}),r(v,[g,f],function(e,t){function n(){function e(e,t){function n(){o.remove(s),a&&(a.onreadystatechange=a.onload=a=null),t()}function i(){"undefined"!=typeof console&&console.log&&console.log("Failed to load: "+e)}var o=r,a,s;s=o.uniqueId(),a=document.createElement("script"),a.id=s,a.type="text/javascript",a.src=e,"onreadystatechange"in a?a.onreadystatechange=function(){/loaded|complete/.test(a.readyState)&&n()}:a.onload=n,a.onerror=i,(document.getElementsByTagName("head")[0]||document.body).appendChild(a)}var t=0,n=1,a=2,s={},l=[],c={},d=[],u=0,f;this.isDone=function(e){return s[e]==a},this.markDone=function(e){s[e]=a},this.add=this.load=function(e,n,r){var i=s[e];i==f&&(l.push(e),s[e]=t),n&&(c[e]||(c[e]=[]),c[e].push({func:n,scope:r||this}))},this.loadQueue=function(e,t){this.loadScripts(l,e,t)},this.loadScripts=function(t,r,l){function p(e){i(c[e],function(e){e.func.call(e.scope)}),c[e]=f}var m;d.push({func:r,scope:l||this}),m=function(){var r=o(t);t.length=0,i(r,function(t){return s[t]==a?(p(t),void 0):(s[t]!=n&&(s[t]=n,u++,e(t,function(){s[t]=a,u--,p(t),m()})),void 0)}),u||(i(d,function(e){e.func.call(e.scope)}),d.length=0)},m()}}var r=e.DOM,i=t.each,o=t.grep;return n.ScriptLoader=new n,n}),r(y,[v,f],function(e,n){function r(){var e=this;e.items=[],e.urls={},e.lookup={}}var i=n.each;return r.prototype={get:function(e){return this.lookup[e]?this.lookup[e].instance:t},dependencies:function(e){var t;return this.lookup[e]&&(t=this.lookup[e].dependencies),t||[]},requireLangPack:function(t,n){if(r.language&&r.languageLoad!==!1){if(n&&new RegExp("([, ]|\\b)"+r.language+"([, ]|\\b)").test(n)===!1)return;e.ScriptLoader.add(this.urls[t]+"/langs/"+r.language+".js")}},add:function(e,t,n){return this.items.push(t),this.lookup[e]={instance:t,dependencies:n},t},createUrl:function(e,t){return"object"==typeof t?t:{prefix:e.prefix,resource:t,suffix:e.suffix}},addComponents:function(t,n){var r=this.urls[t];i(n,function(t){e.ScriptLoader.add(r+"/"+t)})},load:function(n,o,a,s){function l(){var r=c.dependencies(n);i(r,function(e){var n=c.createUrl(o,e);c.load(n.resource,n,t,t)}),a&&(s?a.call(s):a.call(e))}var c=this,d=o;c.urls[n]||("object"==typeof o&&(d=o.prefix+o.resource+o.suffix),0!==d.indexOf("/")&&-1==d.indexOf("://")&&(d=r.baseURL+"/"+d),c.urls[n]=d.substring(0,d.lastIndexOf("/")),c.lookup[n]?l():e.ScriptLoader.add(d,l,s))}},r.PluginManager=new r,r.ThemeManager=new r,r}),r(b,[],function(){function e(e,t,n){var r,i,o=n?"lastChild":"firstChild",a=n?"prev":"next";if(e[o])return e[o];if(e!==t){if(r=e[a])return r;for(i=e.parent;i&&i!==t;i=i.parent)if(r=i[a])return r}}function t(e,t){this.name=e,this.type=t,1===t&&(this.attributes=[],this.attributes.map={})}var n=/^[ \t\r\n]*$/,r={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};return t.prototype={replace:function(e){var t=this;return e.parent&&e.remove(),t.insert(e,t),t.remove(),t},attr:function(e,t){var n=this,r,i,o;if("string"!=typeof e){for(i in e)n.attr(i,e[i]);return n}if(r=n.attributes){if(t!==o){if(null===t){if(e in r.map)for(delete r.map[e],i=r.length;i--;)if(r[i].name===e)return r=r.splice(i,1),n;return n}if(e in r.map){for(i=r.length;i--;)if(r[i].name===e){r[i].value=t;break}}else r.push({name:e,value:t});return r.map[e]=t,n}return r.map[e]}},clone:function(){var e=this,n=new t(e.name,e.type),r,i,o,a,s;if(o=e.attributes){for(s=[],s.map={},r=0,i=o.length;i>r;r++)a=o[r],"id"!==a.name&&(s[s.length]={name:a.name,value:a.value},s.map[a.name]=a.value);n.attributes=s}return n.value=e.value,n.shortEnded=e.shortEnded,n},wrap:function(e){var t=this;return t.parent.insert(e,t),e.append(t),t},unwrap:function(){var e=this,t,n;for(t=e.firstChild;t;)n=t.next,e.insert(t,e,!0),t=n;e.remove()},remove:function(){var e=this,t=e.parent,n=e.next,r=e.prev;return t&&(t.firstChild===e?(t.firstChild=n,n&&(n.prev=null)):r.next=n,t.lastChild===e?(t.lastChild=r,r&&(r.next=null)):n.prev=r,e.parent=e.next=e.prev=null),e},append:function(e){var t=this,n;return e.parent&&e.remove(),n=t.lastChild,n?(n.next=e,e.prev=n,t.lastChild=e):t.lastChild=t.firstChild=e,e.parent=t,e},insert:function(e,t,n){var r;return e.parent&&e.remove(),r=t.parent||this,n?(t===r.firstChild?r.firstChild=e:t.prev.next=e,e.prev=t.prev,e.next=t,t.prev=e):(t===r.lastChild?r.lastChild=e:t.next.prev=e,e.next=t.next,e.prev=t,t.next=e),e.parent=r,e},getAll:function(t){var n=this,r,i=[];for(r=n.firstChild;r;r=e(r,n))r.name===t&&i.push(r);return i},empty:function(){var t=this,n,r,i;if(t.firstChild){for(n=[],i=t.firstChild;i;i=e(i,t))n.push(i);for(r=n.length;r--;)i=n[r],i.parent=i.firstChild=i.lastChild=i.next=i.prev=null}return t.firstChild=t.lastChild=null,t},isEmpty:function(t){var r=this,i=r.firstChild,o,a;if(i)do{if(1===i.type){if(i.attributes.map["data-mce-bogus"])continue;if(t[i.name])return!1;for(o=i.attributes.length;o--;)if(a=i.attributes[o].name,"name"===a||0===a.indexOf("data-mce-"))return!1}if(8===i.type)return!1;if(3===i.type&&!n.test(i.value))return!1}while(i=e(i,r));return!0},walk:function(t){return e(this,null,t)}},t.create=function(e,n){var i,o;if(i=new t(e,r[e]||1),n)for(o in n)i.attr(o,n[o]);return i},t}),r(C,[f],function(e){function t(e,t){return e?e.split(t||" "):[]}function n(e){function n(e,n,r){function i(e){var t={},n,r;for(n=0,r=e.length;r>n;n++)t[e[n]]={};return t}var o,l,c,d=arguments;for(r=r||[],n=n||"","string"==typeof r&&(r=t(r)),l=3;lo;o++)i.attributes[n[o]]={},i.attributesOrder.push(n[o])}var a={},s,l,c,d,u,f,p;return r[e]?r[e]:(s=t("id accesskey class dir lang style tabindex title"),l=t("onabort onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onpause onplay onplaying onprogress onratechange onreset onscroll onseeked onseeking onseeking onselect onshow onstalled onsubmit onsuspend ontimeupdate onvolumechange onwaiting"),c=t("address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul"),d=t("a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment"),"html4"!=e&&(s.push.apply(s,t("contenteditable contextmenu draggable dropzone hidden spellcheck translate")),c.push.apply(c,t("article aside details dialog figure header footer hgroup section nav")),d.push.apply(d,t("audio canvas command datalist mark meter output progress time wbr video ruby bdi keygen"))),"html5-strict"!=e&&(s.push("xml:lang"),p=t("acronym applet basefont big font strike tt"),d.push.apply(d,p),o(p,function(e){n(e,"",d)}),f=t("center dir isindex noframes"),c.push.apply(c,f),u=[].concat(c,d),o(f,function(e){n(e,"",u)})),u=u||[].concat(c,d),n("html","manifest","head body"),n("head","","base command link meta noscript script style title"),n("title hr noscript br"),n("base","href target"),n("link","href rel media hreflang type sizes hreflang"),n("meta","name http-equiv content charset"),n("style","media type scoped"),n("script","src async defer type charset"),n("body","onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload",u),n("address dt dd div caption","",u),n("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn","",d),n("blockquote","cite",u),n("ol","reversed start type","li"),n("ul","","li"),n("li","value",u),n("dl","","dt dd"),n("a","href target rel media hreflang type",d),n("q","cite",d),n("ins del","cite datetime",u),n("img","src alt usemap ismap width height"),n("iframe","src name width height",u),n("embed","src type width height"),n("object","data type typemustmatch name usemap form width height",u,"param"),n("param","name value"),n("map","name",u,"area"),n("area","alt coords shape href target rel media hreflang type"),n("table","border","caption colgroup thead tfoot tbody tr"+("html4"==e?" col":"")),n("colgroup","span","col"),n("col","span"),n("tbody thead tfoot","","tr"),n("tr","","td th"),n("td","colspan rowspan headers",u),n("th","colspan rowspan headers scope abbr",u),n("form","accept-charset action autocomplete enctype method name novalidate target",u),n("fieldset","disabled form name",u,"legend"),n("label","form for",d),n("input","accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"),n("button","disabled form formaction formenctype formmethod formnovalidate formtarget name type value","html4"==e?u:d),n("select","disabled form multiple name required size","option optgroup"),n("optgroup","disabled label","option"),n("option","disabled label selected value"),n("textarea","cols dirname disabled form maxlength name readonly required rows wrap"),n("menu","type label",u,"li"),n("noscript","",u),"html4"!=e&&(n("wbr"),n("ruby","",d,"rt rp"),n("figcaption","",u),n("mark rt rp summary bdi","",d),n("canvas","width height",u),n("video","src crossorigin poster preload autoplay mediagroup loop muted controls width height",u,"track source"),n("audio","src crossorigin preload autoplay mediagroup loop muted controls",u,"track source"),n("source","src type media"),n("track","kind src srclang label default"),n("datalist","",d,"option"),n("article section nav aside header footer","",u),n("hgroup","","h1 h2 h3 h4 h5 h6"),n("figure","",u,"figcaption"),n("time","datetime",d),n("dialog","open",u),n("command","type label icon disabled checked radiogroup command"),n("output","for form name",d),n("progress","value max",d),n("meter","value min max low high optimum",d),n("details","open",u,"summary"),n("keygen","autofocus challenge disabled form keytype name")),"html5-strict"!=e&&(i("script","language xml:space"),i("style","xml:space"),i("object","declare classid codebase codetype archive standby align border hspace vspace"),i("param","valuetype type"),i("a","charset name rev shape coords"),i("br","clear"),i("applet","codebase archive code object alt name width height align hspace vspace"),i("img","name longdesc align border hspace vspace"),i("iframe","longdesc frameborder marginwidth marginheight scrolling align"),i("font basefont","size color face"),i("input","usemap align"),i("select","onchange"),i("textarea"),i("h1 h2 h3 h4 h5 h6 div p legend caption","align"),i("ul","type compact"),i("li","type"),i("ol dl menu dir","compact"),i("pre","width xml:space"),i("hr","align noshade size width"),i("isindex","prompt"),i("table","summary width frame rules cellspacing cellpadding align bgcolor"),i("col","width align char charoff valign"),i("colgroup","width align char charoff valign"),i("thead","align char charoff valign"),i("tr","align char charoff valign bgcolor"),i("th","axis align char charoff valign nowrap bgcolor width height"),i("form","accept"),i("td","abbr axis scope align char charoff valign nowrap bgcolor width height"),i("tfoot","align char charoff valign"),i("tbody","align char charoff valign"),i("area","nohref"),i("body","background bgcolor text link vlink alink")),"html4"!=e&&(i("input button select textarea","autofocus"),i("input textarea","placeholder"),i("a","download"),i("link script img","crossorigin"),i("iframe","srcdoc sandbox seamless allowfullscreen")),o(t("a form meter progress dfn"),function(e){a[e]&&delete a[e].children[e]}),delete a.caption.children.table,r[e]=a,a)}var r={},i=e.makeMap,o=e.each,a=e.extend,s=e.explode,l=e.inArray;return function(e){function c(t,n,o){var s=e[t];return s?s=i(s,",",i(s.toUpperCase()," ")):(s=r[t],s||(s=i(n," ",i(n.toUpperCase()," ")),s=a(s,o),r[t]=s)),s}function d(e){return new RegExp("^"+e.replace(/([?+*])/g,".$1")+"$")}function u(e){var n,r,o,a,s,c,u,f,p,m,h,g,y,C,x,w,_,N,E,k=/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,S=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,T=/[*?+]/;if(e)for(e=t(e,","),v["@"]&&(w=v["@"].attributes,_=v["@"].attributesOrder),n=0,r=e.length;r>n;n++)if(s=k.exec(e[n])){if(C=s[1],p=s[2],x=s[3],f=s[5],g={},y=[],c={attributes:g,attributesOrder:y},"#"===C&&(c.paddEmpty=!0),"-"===C&&(c.removeEmpty=!0),"!"===s[4]&&(c.removeEmptyAttrs=!0),w){for(N in w)g[N]=w[N];y.push.apply(y,_)}if(f)for(f=t(f,"|"),o=0,a=f.length;a>o;o++)if(s=S.exec(f[o])){if(u={},h=s[1],m=s[2].replace(/::/g,":"),C=s[3],E=s[4],"!"===h&&(c.attributesRequired=c.attributesRequired||[],c.attributesRequired.push(m),u.required=!0),"-"===h){delete g[m],y.splice(l(y,m),1);continue}C&&("="===C&&(c.attributesDefault=c.attributesDefault||[],c.attributesDefault.push({name:m,value:E}),u.defaultValue=E),":"===C&&(c.attributesForced=c.attributesForced||[],c.attributesForced.push({name:m,value:E}),u.forcedValue=E),"<"===C&&(u.validValues=i(E,"?"))),T.test(m)?(c.attributePatterns=c.attributePatterns||[],u.pattern=d(m),c.attributePatterns.push(u)):(g[m]||y.push(m),g[m]=u)}w||"@"!=p||(w=g,_=y),x&&(c.outputName=p,v[x]=c),T.test(p)?(c.pattern=d(p),b.push(c)):v[p]=c}}function f(e){v={},b=[],u(e),o(x,function(e,t){y[t]=e.children})}function p(e){var n=/^(~)?(.+)$/;e&&o(t(e,","),function(e){var t=n.exec(e),r="~"===t[1],i=r?"span":"div",s=t[2];if(y[s]=y[i],R[s]=i,r||(k[s.toUpperCase()]={},k[s]={}),!v[s]){var l=v[i];l=a({},l),delete l.removeEmptyAttrs,delete l.removeEmpty,v[s]=l}o(y,function(e){e[i]&&(e[s]=e[i])})})}function m(e){var n=/^([+\-]?)(\w+)\[([^\]]+)\]$/;e&&o(t(e,","),function(e){var r=n.exec(e),i,a;r&&(a=r[1],i=a?y[r[2]]:y[r[2]]={"#comment":{}},i=y[r[2]],o(t(r[3],"|"),function(e){"-"===a?delete i[e]:i[e]={}}))})}function h(e){var t=v[e],n;if(t)return t;for(n=b.length;n--;)if(t=b[n],t.pattern.test(e))return t}var g=this,v={},y={},b=[],C,x,w,_,N,E,k,S,T,R={},A={};e=e||{},x=n(e.schema),e.verify_html===!1&&(e.valid_elements="*[*]"),e.valid_styles&&(C={},o(e.valid_styles,function(e,t){C[t]=s(e)})),w=c("whitespace_elements","pre script noscript style textarea video audio iframe object"),_=c("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr"),N=c("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr track"),E=c("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls"),S=c("non_empty_elements","td th iframe video audio object script",N),T=c("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure"),k=c("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup",T),o((e.special||"script noscript style textarea").split(" "),function(e){A[e]=new RegExp("]*>","gi")}),e.valid_elements?f(e.valid_elements):(o(x,function(e,t){v[t]={attributes:e.attributes,attributesOrder:e.attributesOrder},y[t]=e.children}),"html5"!=e.schema&&o(t("strong/b em/i"),function(e){e=t(e,"/"),v[e[1]].outputName=e[0]}),v.img.attributesDefault=[{name:"alt",value:""}],o(t("ol ul sub sup blockquote span font a table tbody tr strong em b i"),function(e){v[e]&&(v[e].removeEmpty=!0)}),o(t("p h1 h2 h3 h4 h5 h6 th td pre div address caption"),function(e){v[e].paddEmpty=!0}),o(t("span"),function(e){v[e].removeEmptyAttrs=!0})),p(e.custom_elements),m(e.valid_children),u(e.extended_valid_elements),m("+ol[ul|ol],+ul[ul|ol]"),e.invalid_elements&&o(s(e.invalid_elements),function(e){v[e]&&delete v[e]}),h("span")||u("span[!data-mce-type|*]"),g.children=y,g.styles=C,g.getBoolAttrs=function(){return E},g.getBlockElements=function(){return k},g.getTextBlockElements=function(){return T},g.getShortEndedElements=function(){return N},g.getSelfClosingElements=function(){return _},g.getNonEmptyElements=function(){return S},g.getWhiteSpaceElements=function(){return w},g.getSpecialElements=function(){return A},g.isValidChild=function(e,t){var n=y[e];return!(!n||!n[t])},g.isValid=function(e,t){var n,r,i=h(e);if(i){if(!t)return!0;if(i.attributes[t])return!0;if(n=i.attributePatterns)for(r=n.length;r--;)if(n[r].pattern.test(e))return!0}return!1},g.getElementRule=h,g.getCustomElements=function(){return R},g.addValidElements=u,g.setValidElements=f,g.addCustomElements=p,g.addValidChildren=m,g.elements=v}}),r(x,[C,m,f],function(e,t,n){var r=n.each;return function(i,o){var a=this,s=function(){};i=i||{},a.schema=o=o||new e,i.fix_self_closing!==!1&&(i.fix_self_closing=!0),r("comment cdata text start end pi doctype".split(" "),function(e){e&&(a[e]=i[e]||s)}),a.parse=function(e){function r(e){var t,n;for(t=f.length;t--&&f[t].name!==e;);if(t>=0){for(n=f.length-1;n>=t;n--)e=f[n],e.valid&&s.end(e.name);f.length=t}}function a(e,t,n,r,o){var a,s,l=/[\s\u0000-\u001F]+/g;if(t=t.toLowerCase(),n=t in C?t:F(n||r||o||""),w&&!v&&0!==t.indexOf("data-")){if(a=S[t],!a&&T){for(s=T.length;s--&&(a=T[s],!a.pattern.test(t)););-1===s&&(a=null)}if(!a)return;if(a.validValues&&!(n in a.validValues))return}if(W[t]&&!i.allow_script_urls){var c=n.replace(l,"");try{if(c=decodeURIComponent(c),V.test(c))return}catch(d){if(c=unescape(c),V.test(c))return}}p.map[t]=n,p.push({name:t,value:n})}var s=this,l,c=0,d,u,f=[],p,m,h,g,v,y,b,C,x,w,_,N,E,k,S,T,R,A,B,L,H,D,M,P,O,I=0,F=t.decode,z,W=n.makeMap("src,href"),V=/(java|vb)script:/i;for(D=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g"),M=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g,b=o.getShortEndedElements(),H=i.self_closing_elements||o.getSelfClosingElements(),C=o.getBoolAttrs(),w=i.validate,y=i.remove_internals,z=i.fix_self_closing,P=o.getSpecialElements();l=D.exec(e);){if(c0&&f[f.length-1].name===d&&r(d),!w||(_=o.getElementRule(d))){if(N=!0,w&&(S=_.attributes,T=_.attributePatterns),(k=l[8])?(v=-1!==k.indexOf("data-mce-type"),v&&y&&(N=!1),p=[],p.map={},k.replace(M,a)):(p=[],p.map={}),w&&!v){if(R=_.attributesRequired,A=_.attributesDefault,B=_.attributesForced,L=_.removeEmptyAttrs,L&&!p.length&&(N=!1),B)for(m=B.length;m--;)E=B[m],g=E.name,O=E.value,"{$uid}"===O&&(O="mce_"+I++),p.map[g]=O,p.push({name:g,value:O});if(A)for(m=A.length;m--;)E=A[m],g=E.name,g in p.map||(O=E.value,"{$uid}"===O&&(O="mce_"+I++),p.map[g]=O,p.push({name:g,value:O}));if(R){for(m=R.length;m--&&!(R[m]in p.map););-1===m&&(N=!1)}p.map["data-mce-bogus"]&&(N=!1)}N&&s.start(d,p,x)}else N=!1;if(u=P[d]){u.lastIndex=c=l.index+l[0].length,(l=u.exec(e))?(N&&(h=e.substr(c,l.index-c)),c=l.index+l[0].length):(h=e.substr(c),c=e.length),N&&(h.length>0&&s.text(h,!0),s.end(d)),D.lastIndex=c;continue}x||(k&&k.indexOf("/")==k.length-1?N&&s.end(d):f.push({name:d,valid:N}))}else(d=l[1])?(">"===d.charAt(0)&&(d=" "+d),i.allow_conditional_comments||"[if"!==d.substr(0,3)||(d=" "+d),s.comment(d)):(d=l[2])?s.cdata(d):(d=l[3])?s.doctype(d):(d=l[4])&&s.pi(d,l[5]);c=l.index+l[0].length}for(c=0;m--)d=f[m],d.valid&&s.end(d.name)}}}),r(w,[b,C,x,f],function(e,t,n,r){var i=r.makeMap,o=r.each,a=r.explode,s=r.extend;return function(r,l){function c(t){var n,r,o,a,s,c,u,f,p,m,h,g,v,y;for(h=i("tr,td,th,tbody,thead,tfoot,table"),m=l.getNonEmptyElements(),g=l.getTextBlockElements(),n=0;n1){for(a.reverse(),s=c=d.filterNode(a[0].clone()),p=0;p0?(t.value=n,t=t.prev):(r=t.prev,t.remove(),t=r)}function g(e){var t,n={};for(t in e)"li"!==t&&"p"!=t&&(n[t]=e[t]);return n}var v,y,b,C,x,w,_,N,E,k,S,T,R,A=[],B,L,H,D,M,P,O,I;if(o=o||{},p={},m={},T=s(i("script,style,head,html,body,title,meta,param"),l.getBlockElements()),O=l.getNonEmptyElements(),P=l.children,S=r.validate,I="forced_root_block"in o?o.forced_root_block:r.forced_root_block,M=l.getWhiteSpaceElements(),R=/^[ \t\r\n]+/,L=/[ \t\r\n]+$/,H=/[ \t\r\n]+/g,D=/^[ \t\r\n]+$/,v=new n({validate:S,allow_script_urls:r.allow_script_urls,allow_conditional_comments:r.allow_conditional_comments,self_closing_elements:g(l.getSelfClosingElements()),cdata:function(e){b.append(d("#cdata",4)).value=e},text:function(e,t){var n;B||(e=e.replace(H," "),b.lastChild&&T[b.lastChild.name]&&(e=e.replace(R,""))),0!==e.length&&(n=d("#text",3),n.raw=!!t,b.append(n).value=e)},comment:function(e){b.append(d("#comment",8)).value=e},pi:function(e,t){b.append(d(e,7)).value=t,h(b)},doctype:function(e){var t;t=b.append(d("#doctype",10)),t.value=e,h(b)},start:function(e,t,n){var r,i,o,a,s;if(o=S?l.getElementRule(e):{}){for(r=d(o.outputName||e,1),r.attributes=t,r.shortEnded=n,b.append(r),s=P[b.name],s&&P[r.name]&&!s[r.name]&&A.push(r),i=f.length;i--;)a=f[i].name,a in t.map&&(E=m[a],E?E.push(r):m[a]=[r]);T[e]&&h(r),n||(b=r),!B&&M[e]&&(B=!0)}},end:function(t){var n,r,i,o,a;if(r=S?l.getElementRule(t):{}){if(T[t]&&!B){if(n=b.firstChild,n&&3===n.type)if(i=n.value.replace(R,""),i.length>0)n.value=i,n=n.next;else for(o=n.next,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.next,(0===i.length||D.test(i))&&(n.remove(),n=o),n=o;if(n=b.lastChild,n&&3===n.type)if(i=n.value.replace(L,""),i.length>0)n.value=i,n=n.prev;else for(o=n.prev,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.prev,(0===i.length||D.test(i))&&(n.remove(),n=o),n=o}if(B&&M[t]&&(B=!1),(r.removeEmpty||r.paddEmpty)&&b.isEmpty(O))if(r.paddEmpty)b.empty().append(new e("#text","3")).value="\xa0";else if(!b.attributes.map.name&&!b.attributes.map.id)return a=b.parent,b.empty().remove(),b=a,void 0;b=b.parent}}},l),y=b=new e(o.context||r.root_name,11),v.parse(t),S&&A.length&&(o.context?o.invalid=!0:c(A)),I&&("body"==y.name||o.isRootContent)&&a(),!o.invalid){for(k in p){for(E=u[k],C=p[k],_=C.length;_--;)C[_].parent||C.splice(_,1);for(x=0,w=E.length;w>x;x++)E[x](C,k,o)}for(x=0,w=f.length;w>x;x++)if(E=f[x],E.name in m){for(C=m[E.name],_=C.length;_--;)C[_].parent||C.splice(_,1);for(_=0,N=E.callbacks.length;N>_;_++)E.callbacks[_](C,E.name,o)}}return y},r.remove_trailing_brs&&d.addNodeFilter("br",function(t){var n,r=t.length,i,o=s({},l.getBlockElements()),a=l.getNonEmptyElements(),c,d,u,f,p,m;for(o.body=1,n=0;r>n;n++)if(i=t[n],c=i.parent,o[i.parent.name]&&i===c.lastChild){for(u=i.prev;u;){if(f=u.name,"span"!==f||"bookmark"!==u.attr("data-mce-type")){if("br"!==f)break;if("br"===f){i=null;break}}u=u.prev}i&&(i.remove(),c.isEmpty(a)&&(p=l.getElementRule(c.name),p&&(p.removeEmpty?c.remove():p.paddEmpty&&(c.empty().append(new e("#text",3)).value="\xa0"))))}else{for(d=i;c&&c.firstChild===d&&c.lastChild===d&&(d=c,!o[c.name]);)c=c.parent;d===c&&(m=new e("#text",3),m.value="\xa0",i.replace(m))}}),r.allow_html_in_named_anchor||d.addAttributeFilter("id,name",function(e){for(var t=e.length,n,r,i,o;t--;)if(o=e[t],"a"===o.name&&o.firstChild&&!o.attr("href")){i=o.parent,n=o.lastChild; +do r=n.prev,i.insert(n,o),n=r;while(n)}})}}),r(_,[m,f],function(e,t){var n=t.makeMap;return function(t){var r=[],i,o,a,s,l;return t=t||{},i=t.indent,o=n(t.indent_before||""),a=n(t.indent_after||""),s=e.getEncodeFunc(t.entity_encoding||"raw",t.entities),l="html"==t.element_format,{start:function(e,t,n){var c,d,u,f;if(i&&o[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n")),r.push("<",e),t)for(c=0,d=t.length;d>c;c++)u=t[c],r.push(" ",u.name,'="',s(u.value,!0),'"');r[r.length]=!n||l?">":" />",n&&i&&a[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n"))},end:function(e){var t;r.push(""),i&&a[e]&&r.length>0&&(t=r[r.length-1],t.length>0&&"\n"!==t&&r.push("\n"))},text:function(e,t){e.length>0&&(r[r.length]=t?e:s(e))},cdata:function(e){r.push("")},comment:function(e){r.push("")},pi:function(e,t){t?r.push(""):r.push(""),i&&r.push("\n")},doctype:function(e){r.push("",i?"\n":"")},reset:function(){r.length=0},getContent:function(){return r.join("").replace(/\n$/,"")}}}}),r(N,[_,C],function(e,t){return function(n,r){var i=this,o=new e(n);n=n||{},n.validate="validate"in n?n.validate:!0,i.schema=r=r||new t,i.writer=o,i.serialize=function(e){function t(e){var n=i[e.type],s,l,c,d,u,f,p,m,h;if(n)n(e);else{if(s=e.name,l=e.shortEnded,c=e.attributes,a&&c&&c.length>1){for(f=[],f.map={},h=r.getElementRule(e.name),p=0,m=h.attributesOrder.length;m>p;p++)d=h.attributesOrder[p],d in c.map&&(u=c.map[d],f.map[d]=u,f.push({name:d,value:u}));for(p=0,m=c.length;m>p;p++)d=c[p].name,d in f.map||(u=c.map[d],f.map[d]=u,f.push({name:d,value:u}));c=f}if(o.start(e.name,c,l),!l){if(e=e.firstChild)do t(e);while(e=e.next);o.end(s)}}}var i,a;return a=n.validate,i={3:function(e){o.text(e.value,e.raw)},8:function(e){o.comment(e.value)},7:function(e){o.pi(e.name,e.value)},10:function(e){o.doctype(e.value)},4:function(e){o.cdata(e.value)},11:function(e){if(e=e.firstChild)do t(e);while(e=e.next)}},o.reset(),1!=e.type||n.inner?i[11](e):t(e),o.getContent()}}}),r(E,[g,w,m,N,b,C,h,f],function(e,t,n,r,i,o,a,s){var l=s.each,c=s.trim,d=e.DOM;return function(e,i){var s,u,f;return i&&(s=i.dom,u=i.schema),s=s||d,u=u||new o(e),e.entity_encoding=e.entity_encoding||"named",e.remove_trailing_brs="remove_trailing_brs"in e?e.remove_trailing_brs:!0,f=new t(e,u),f.addAttributeFilter("src,href,style",function(t,n){for(var r=t.length,i,o,a="data-mce-"+n,l=e.url_converter,c=e.url_converter_scope,d;r--;)i=t[r],o=i.attributes.map[a],o!==d?(i.attr(n,o.length>0?o:null),i.attr(a,null)):(o=i.attributes.map[n],"style"===n?o=s.serializeStyle(s.parseStyle(o),i.name):l&&(o=l.call(c,o,n,i.name)),i.attr(n,o.length>0?o:null))}),f.addAttributeFilter("class",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr("class").replace(/(?:^|\s)mce-item-\w+(?!\S)/g,""),n.attr("class",r.length>0?r:null)}),f.addAttributeFilter("data-mce-type",function(e,t,n){for(var r=e.length,i;r--;)i=e[r],"bookmark"!==i.attributes.map["data-mce-type"]||n.cleanup||i.remove()}),f.addAttributeFilter("data-mce-expando",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),f.addNodeFilter("noscript",function(e){for(var t=e.length,r;t--;)r=e[t].firstChild,r&&(r.value=n.decode(r.value))}),f.addNodeFilter("script,style",function(e,t){function n(e){return e.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}for(var r=e.length,i,o;r--;)if(i=e[r],o=i.firstChild?i.firstChild.value:"","script"===t){var a=(i.attr("type")||"text/javascript").replace(/^mce\-/,"");i.attr("type","text/javascript"===a?null:a),o.length>0&&(i.firstChild.value="// ")}else o.length>0&&(i.firstChild.value="")}),f.addNodeFilter("#comment",function(e){for(var t=e.length,n;t--;)n=e[t],0===n.value.indexOf("[CDATA[")?(n.name="#cdata",n.type=4,n.value=n.value.replace(/^\[CDATA\[|\]\]$/g,"")):0===n.value.indexOf("mce:protected ")&&(n.name="#text",n.type=3,n.raw=!0,n.value=unescape(n.value).substr(14))}),f.addNodeFilter("xml:namespace,input",function(e,t){for(var n=e.length,r;n--;)r=e[n],7===r.type?r.remove():1===r.type&&("input"!==t||"type"in r.attributes.map||r.attr("type","text"))}),e.fix_list_elements&&f.addNodeFilter("ul,ol",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.parent,("ul"===r.name||"ol"===r.name)&&n.prev&&"li"===n.prev.name&&n.prev.append(n)}),f.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style,data-mce-selected",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),{schema:u,addNodeFilter:f.addNodeFilter,addAttributeFilter:f.addAttributeFilter,serialize:function(t,n){var i=this,o,d,p,m,h;return a.ie&&s.select("script,style,select,map").length>0?(h=t.innerHTML,t=t.cloneNode(!1),s.setHTML(t,h)):t=t.cloneNode(!0),o=t.ownerDocument.implementation,o.createHTMLDocument&&(d=o.createHTMLDocument(""),l("BODY"==t.nodeName?t.childNodes:[t],function(e){d.body.appendChild(d.importNode(e,!0))}),t="BODY"!=t.nodeName?d.body.firstChild:d.body,p=s.doc,s.doc=d),n=n||{},n.format=n.format||"html",n.selection&&(n.forced_root_block=""),n.no_events||(n.node=t,i.onPreProcess(n)),m=new r(e,u),n.content=m.serialize(f.parse(c(n.getInner?t.innerHTML:s.getOuterHTML(t)),n)),n.cleanup||(n.content=n.content.replace(/\uFEFF/g,"")),n.no_events||i.onPostProcess(n),p&&(s.doc=p),n.node=null,n.content},addRules:function(e){u.addValidElements(e)},setRules:function(e){u.setValidElements(e)},onPreProcess:function(e){i&&i.fire("PreProcess",e)},onPostProcess:function(e){i&&i.fire("PostProcess",e)}}}}),r(k,[],function(){function e(e){function t(t,n){var r,i=0,o,a,s,l,c,d,u=-1,f;if(r=t.duplicate(),r.collapse(n),f=r.parentElement(),f.ownerDocument===e.dom.doc){for(;"false"===f.contentEditable;)f=f.parentNode;if(!f.hasChildNodes())return{node:f,inside:1};for(s=f.children,o=s.length-1;o>=i;)if(d=Math.floor((i+o)/2),l=s[d],r.moveToElementText(l),u=r.compareEndPoints(n?"StartToStart":"EndToEnd",t),u>0)o=d-1;else{if(!(0>u))return{node:l};i=d+1}if(0>u)for(l?r.collapse(!1):(r.moveToElementText(f),r.collapse(!0),l=f,a=!0),c=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",1)&&f==r.parentElement();)c++;else for(r.collapse(!0),c=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",-1)&&f==r.parentElement();)c++;return{node:l,position:u,offset:c,inside:a}}}function n(){function n(e){var n=t(o,e),r,i,s=0,l,c,d;if(r=n.node,i=n.offset,n.inside&&!r.hasChildNodes())return a[e?"setStart":"setEnd"](r,0),void 0;if(i===c)return a[e?"setStartBefore":"setEndAfter"](r),void 0;if(n.position<0){if(l=n.inside?r.firstChild:r.nextSibling,!l)return a[e?"setStartAfter":"setEndAfter"](r),void 0;if(!i)return 3==l.nodeType?a[e?"setStart":"setEnd"](l,0):a[e?"setStartBefore":"setEndBefore"](l),void 0;for(;l;){if(d=l.nodeValue,s+=d.length,s>=i){r=l,s-=i,s=d.length-s;break}l=l.nextSibling}}else{if(l=r.previousSibling,!l)return a[e?"setStartBefore":"setEndBefore"](r);if(!i)return 3==r.nodeType?a[e?"setStart":"setEnd"](l,r.nodeValue.length):a[e?"setStartAfter":"setEndAfter"](l),void 0;for(;l;){if(s+=l.nodeValue.length,s>=i){r=l,s-=i;break}l=l.previousSibling}}a[e?"setStart":"setEnd"](r,s)}var o=e.getRng(),a=i.createRng(),s,l,c,d,u;if(s=o.item?o.item(0):o.parentElement(),s.ownerDocument!=i.doc)return a;if(l=e.isCollapsed(),o.item)return a.setStart(s.parentNode,i.nodeIndex(s)),a.setEnd(a.startContainer,a.startOffset+1),a;try{n(!0),l||n()}catch(f){if(-2147024809!=f.number)throw f;u=r.getBookmark(2),c=o.duplicate(),c.collapse(!0),s=c.parentElement(),l||(c=o.duplicate(),c.collapse(!1),d=c.parentElement(),d.innerHTML=d.innerHTML),s.innerHTML=s.innerHTML,r.moveToBookmark(u),o=e.getRng(),n(!0),l||n()}return a}var r=this,i=e.dom,o=!1;this.getBookmark=function(n){function r(e){var t,n,r,o,a=[];for(t=e.parentNode,n=i.getRoot().parentNode;t!=n&&9!==t.nodeType;){for(r=t.children,o=r.length;o--;)if(e===r[o]){a.push(o);break}e=t,t=t.parentNode}return a}function o(e){var n;return n=t(a,e),n?{position:n.position,offset:n.offset,indexes:r(n.node),inside:n.inside}:void 0}var a=e.getRng(),s={};return 2===n&&(a.item?s.start={ctrl:!0,indexes:r(a.item(0))}:(s.start=o(!0),e.isCollapsed()||(s.end=o()))),s},this.moveToBookmark=function(e){function t(e){var t,n,r,o;for(t=i.getRoot(),n=e.length-1;n>=0;n--)o=t.children,r=e[n],r<=o.length-1&&(t=o[r]);return t}function n(n){var i=e[n?"start":"end"],a,s,l,c;i&&(a=i.position>0,s=o.createTextRange(),s.moveToElementText(t(i.indexes)),c=i.offset,c!==l?(s.collapse(i.inside||a),s.moveStart("character",a?-c:c)):s.collapse(n),r.setEndPoint(n?"StartToStart":"EndToStart",s),n&&r.collapse(!0))}var r,o=i.doc.body;e.start&&(e.start.ctrl?(r=o.createControlRange(),r.addElement(t(e.start.indexes)),r.select()):(r=o.createTextRange(),n(!0),n(),r.select()))},this.addRange=function(t){function n(e){var t,n,a,u,m;a=i.create("a"),t=e?s:c,n=e?l:d,u=r.duplicate(),(t==f||t==f.documentElement)&&(t=p,n=0),3==t.nodeType?(t.parentNode.insertBefore(a,t),u.moveToElementText(a),u.moveStart("character",n),i.remove(a),r.setEndPoint(e?"StartToStart":"EndToEnd",u)):(m=t.childNodes,m.length?(n>=m.length?i.insertAfter(a,m[m.length-1]):t.insertBefore(a,m[n]),u.moveToElementText(a)):t.canHaveHTML&&(t.innerHTML="",a=t.firstChild,u.moveToElementText(a),u.collapse(o)),r.setEndPoint(e?"StartToStart":"EndToEnd",u),i.remove(a))}var r,a,s,l,c,d,u,f=e.dom.doc,p=f.body,m,h;if(s=t.startContainer,l=t.startOffset,c=t.endContainer,d=t.endOffset,r=p.createTextRange(),s==c&&1==s.nodeType){if(l==d&&!s.hasChildNodes()){if(s.canHaveHTML)return u=s.previousSibling,u&&!u.hasChildNodes()&&i.isBlock(u)?u.innerHTML="":u=null,s.innerHTML="",r.moveToElementText(s.lastChild),r.select(),i.doc.selection.clear(),s.innerHTML="",u&&(u.innerHTML=""),void 0;l=i.nodeIndex(s),s=s.parentNode}if(l==d-1)try{if(h=s.childNodes[l],a=p.createControlRange(),a.addElement(h),a.select(),m=e.getRng(),m.item&&h===m.item(0))return}catch(g){}}n(!0),n(),r.select()},this.getRangeAt=n}return e}),r(S,[h],function(e){return{BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(e){return e.shiftKey||e.ctrlKey||e.altKey},metaKeyPressed:function(t){return(e.mac?t.metaKey:t.ctrlKey)&&!t.altKey}}}),r(T,[S,f,h],function(e,t,n){return function(r,i){function o(e){return i.settings.object_resizing===!1?!1:/TABLE|IMG|DIV/.test(e.nodeName)?"false"===e.getAttribute("data-mce-resize")?!1:!0:!1}function a(t){var n,r;n=t.screenX-k,r=t.screenY-S,D=n*N[2]+A,M=r*N[3]+B,D=5>D?5:D,M=5>M?5:M,(e.modifierPressed(t)||"IMG"==x.nodeName&&N[2]*N[3]!==0)&&(D=Math.round(M/L),M=Math.round(D*L)),b.setStyles(w,{width:D,height:M}),N[2]<0&&w.clientWidth<=D&&b.setStyle(w,"left",T+(A-D)),N[3]<0&&w.clientHeight<=M&&b.setStyle(w,"top",R+(B-M)),H||(i.fire("ObjectResizeStart",{target:x,width:A,height:B}),H=!0)}function s(){function e(e,t){t&&(x.style[e]||!i.schema.isValid(x.nodeName.toLowerCase(),e)?b.setStyle(x,e,t):b.setAttrib(x,e,t))}H=!1,e("width",D),e("height",M),b.unbind(P,"mousemove",a),b.unbind(P,"mouseup",s),O!=P&&(b.unbind(O,"mousemove",a),b.unbind(O,"mouseup",s)),b.remove(w),I&&"TABLE"!=x.nodeName||l(x),i.fire("ObjectResized",{target:x,width:D,height:M}),i.nodeChanged()}function l(e,t,n){var r,l,d,u,f,p=i.getBody();r=b.getPos(e,p),T=r.x,R=r.y,f=e.getBoundingClientRect(),l=f.width||f.right-f.left,d=f.height||f.bottom-f.top,x!=e&&(h(),x=e,D=M=0),u=i.fire("ObjectSelected",{target:e}),o(e)&&!u.isDefaultPrevented()?C(_,function(e,r){function o(t){H=!0,k=t.screenX,S=t.screenY,A=x.clientWidth,B=x.clientHeight,L=B/A,N=e,w=x.cloneNode(!0),b.addClass(w,"mce-clonedresizable"),w.contentEditable=!1,w.unSelectabe=!0,b.setStyles(w,{left:T,top:R,margin:0}),w.removeAttribute("data-mce-selected"),i.getBody().appendChild(w),b.bind(P,"mousemove",a),b.bind(P,"mouseup",s),O!=P&&(b.bind(O,"mousemove",a),b.bind(O,"mouseup",s))}var c,u;return t?(r==t&&o(n),void 0):(c=b.get("mceResizeHandle"+r),c?b.show(c):(u=i.getBody(),c=b.add(u,"div",{id:"mceResizeHandle"+r,"data-mce-bogus":!0,"class":"mce-resizehandle",contentEditable:!1,unSelectabe:!0,style:"cursor:"+r+"-resize; margin:0; padding:0"}),b.bind(c,"mousedown",function(e){e.preventDefault(),o(e)})),b.setStyles(c,{left:l*e[0]+T-c.offsetWidth/2,top:d*e[1]+R-c.offsetHeight/2}),void 0)}):c(),x.setAttribute("data-mce-selected","1")}function c(){var e,t;x&&x.removeAttribute("data-mce-selected");for(e in _)t=b.get("mceResizeHandle"+e),t&&(b.unbind(t),b.remove(t))}function d(e){function t(e,t){do if(e===t)return!0;while(e=e.parentNode)}var n;return C(b.select("img[data-mce-selected],hr[data-mce-selected]"),function(e){e.removeAttribute("data-mce-selected")}),n="mousedown"==e.type?e.target:r.getNode(),n=b.getParent(n,I?"table":"table,img,hr"),n&&(g(),t(r.getStart(),n)&&t(r.getEnd(),n)&&(!I||n!=r.getStart()&&"IMG"!==r.getStart().nodeName))?(l(n),void 0):(c(),void 0)}function u(e,t,n){e&&e.attachEvent&&e.attachEvent("on"+t,n)}function f(e,t,n){e&&e.detachEvent&&e.detachEvent("on"+t,n)}function p(e){var t=e.srcElement,n,r,o,a,s,c,d;n=t.getBoundingClientRect(),c=E.clientX-n.left,d=E.clientY-n.top;for(r in _)if(o=_[r],a=t.offsetWidth*o[0],s=t.offsetHeight*o[1],Math.abs(a-c)<8&&Math.abs(s-d)<8){N=o;break}H=!0,i.getDoc().selection.empty(),l(t,r,E)}function m(e){var t=e.srcElement;if(t!=x){if(h(),0===t.id.indexOf("mceResizeHandle"))return e.returnValue=!1,void 0;("IMG"==t.nodeName||"TABLE"==t.nodeName)&&(c(),x=t,u(t,"resizestart",p))}}function h(){f(x,"resizestart",p)}function g(){try{i.getDoc().execCommand("enableObjectResizing",!1,!1)}catch(e){}}function v(e){var t;if(I){t=P.body.createControlRange();try{return t.addElement(e),t.select(),!0}catch(n){}}}function y(){x=w=null,I&&(h(),f(i.getBody(),"controlselect",m))}var b=i.dom,C=t.each,x,w,_,N,E,k,S,T,R,A,B,L,H,D,M,P=i.getDoc(),O=document,I=n.ie&&n.ie<11;_={n:[.5,0,0,-1],e:[1,.5,1,0],s:[.5,1,0,1],w:[0,.5,-1,0],nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};var F=".mce-content-body";return i.contentStyles.push(F+" div.mce-resizehandle {position: absolute;border: 1px solid black;background: #FFF;width: 5px;height: 5px;z-index: 10000}"+F+" .mce-resizehandle:hover {background: #000}"+F+" img[data-mce-selected], hr[data-mce-selected] {outline: 1px solid black;resize: none}"+F+" .mce-clonedresizable {position: absolute;"+(n.gecko?"":"outline: 1px dashed black;")+"opacity: .5;filter: alpha(opacity=50);z-index: 10000}"),i.on("init",function(){I?(i.on("ObjectResized",function(e){"TABLE"!=e.target.nodeName&&(c(),v(e.target))}),u(i.getBody(),"controlselect",m),i.on("mousedown",function(e){E=e})):(g(),n.ie>=11&&(i.on("mouseup",function(e){var t=e.target.nodeName;/^(TABLE|IMG|HR)$/.test(t)&&(i.selection.select(e.target,"TABLE"==t),i.nodeChanged())}),i.dom.bind(i.getBody(),"mscontrolselect",function(e){/^(TABLE|IMG|HR)$/.test(e.target.nodeName)&&e.preventDefault()}))),i.on("nodechange mousedown mouseup ResizeEditor",d),i.on("keydown keyup",function(e){x&&"TABLE"==x.nodeName&&d(e)})}),{controlSelect:v,destroy:y}}}),r(R,[u,k,T,h,f],function(e,n,r,i,o){function a(e,t,i,o){var a=this;a.dom=e,a.win=t,a.serializer=i,a.editor=o,a.controlSelection=new r(a,o),a.win.getSelection||(a.tridentSel=new n(a))}var s=o.each,l=o.grep,c=o.trim,d=i.ie,u=i.opera;return a.prototype={setCursorLocation:function(e,t){var n=this,r=n.dom.createRng();e?(r.setStart(e,t),r.setEnd(e,t),n.setRng(r),n.collapse(!1)):(n._moveEndPoint(r,n.editor.getBody(),!0),n.setRng(r))},getContent:function(e){var n=this,r=n.getRng(),i=n.dom.create("body"),o=n.getSel(),a,s,l;return e=e||{},a=s="",e.get=!0,e.format=e.format||"html",e.selection=!0,n.editor.fire("BeforeGetContent",e),"text"==e.format?n.isCollapsed()?"":r.text||(o.toString?o.toString():""):(r.cloneContents?(l=r.cloneContents(),l&&i.appendChild(l)):r.item!==t||r.htmlText!==t?(i.innerHTML="
"+(r.item?r.item(0).outerHTML:r.htmlText),i.removeChild(i.firstChild)):i.innerHTML=r.toString(),/^\s/.test(i.innerHTML)&&(a=" "),/\s+$/.test(i.innerHTML)&&(s=" "),e.getInner=!0,e.content=n.isCollapsed()?"":a+n.serializer.serialize(i,e)+s,n.editor.fire("GetContent",e),e.content)},setContent:function(e,t){var n=this,r=n.getRng(),i,o=n.win.document,a,s;if(t=t||{format:"html"},t.set=!0,t.selection=!0,e=t.content=e,t.no_events||n.editor.fire("BeforeSetContent",t),e=t.content,r.insertNode){e+='_',r.startContainer==o&&r.endContainer==o?o.body.innerHTML=e:(r.deleteContents(),0===o.body.childNodes.length?o.body.innerHTML=e:r.createContextualFragment?r.insertNode(r.createContextualFragment(e)):(a=o.createDocumentFragment(),s=o.createElement("div"),a.appendChild(s),s.outerHTML=e,r.insertNode(a))),i=n.dom.get("__caret"),r=o.createRange(),r.setStartBefore(i),r.setEndBefore(i),n.setRng(r),n.dom.remove("__caret");try{n.setRng(r)}catch(l){}}else r.item&&(o.execCommand("Delete",!1,null),r=n.getRng()),/^\s+/.test(e)?(r.pasteHTML('_'+e),n.dom.remove("__mce_tmp")):r.pasteHTML(e);t.no_events||n.editor.fire("SetContent",t)},getStart:function(){var e=this,t=e.getRng(),n,r,i,o;if(t.duplicate||t.item){if(t.item)return t.item(0);for(i=t.duplicate(),i.collapse(1),n=i.parentElement(),n.ownerDocument!==e.dom.doc&&(n=e.dom.getRoot()),r=o=t.parentElement();o=o.parentNode;)if(o==n){n=r;break}return n}return n=t.startContainer,1==n.nodeType&&n.hasChildNodes()&&(n=n.childNodes[Math.min(n.childNodes.length-1,t.startOffset)]),n&&3==n.nodeType?n.parentNode:n},getEnd:function(){var e=this,t=e.getRng(),n,r;return t.duplicate||t.item?t.item?t.item(0):(t=t.duplicate(),t.collapse(0),n=t.parentElement(),n.ownerDocument!==e.dom.doc&&(n=e.dom.getRoot()),n&&"BODY"==n.nodeName?n.lastChild||n:n):(n=t.endContainer,r=t.endOffset,1==n.nodeType&&n.hasChildNodes()&&(n=n.childNodes[r>0?r-1:r]),n&&3==n.nodeType?n.parentNode:n)},getBookmark:function(e,t){function n(e,t){var n=0;return s(a.select(e),function(e,r){e==t&&(n=r)}),n}function r(e){function t(t){var n,r,i,o=t?"start":"end";n=e[o+"Container"],r=e[o+"Offset"],1==n.nodeType&&"TR"==n.nodeName&&(i=n.childNodes,n=i[Math.min(t?r:r-1,i.length-1)],n&&(r=t?0:n.childNodes.length,e["set"+(t?"Start":"End")](n,r)))}return t(!0),t(),e}function i(){function e(e,n){var i=e[n?"startContainer":"endContainer"],a=e[n?"startOffset":"endOffset"],s=[],l,c,d=0;if(3==i.nodeType){if(t)for(l=i.previousSibling;l&&3==l.nodeType;l=l.previousSibling)a+=l.nodeValue.length;s.push(a)}else c=i.childNodes,a>=c.length&&c.length&&(d=1,a=Math.max(0,c.length-1)),s.push(o.dom.nodeIndex(c[a],t)+d);for(;i&&i!=r;i=i.parentNode)s.push(o.dom.nodeIndex(i,t));return s}var n=o.getRng(!0),r=a.getRoot(),i={};return i.start=e(n,!0),o.isCollapsed()||(i.end=e(n)),i}var o=this,a=o.dom,l,c,d,u,f,p,m="",h;if(2==e)return p=o.getNode(),f=p.nodeName,"IMG"==f?{name:f,index:n(f,p)}:o.tridentSel?o.tridentSel.getBookmark(e):i();if(e)return{rng:o.getRng()};if(l=o.getRng(),d=a.uniqueId(),u=o.isCollapsed(),h="overflow:hidden;line-height:0px",l.duplicate||l.item){if(l.item)return p=l.item(0),f=p.nodeName,{name:f,index:n(f,p)};c=l.duplicate();try{l.collapse(),l.pasteHTML(''+m+""),u||(c.collapse(!1),l.moveToElementText(c.parentElement()),0===l.compareEndPoints("StartToEnd",c)&&c.move("character",-1),c.pasteHTML(''+m+""))}catch(g){return null}}else{if(p=o.getNode(),f=p.nodeName,"IMG"==f)return{name:f,index:n(f,p)};c=r(l.cloneRange()),u||(c.collapse(!1),c.insertNode(a.create("span",{"data-mce-type":"bookmark",id:d+"_end",style:h},m))),l=r(l),l.collapse(!0),l.insertNode(a.create("span",{"data-mce-type":"bookmark",id:d+"_start",style:h},m))}return o.moveToBookmark({id:d,keep:1}),{id:d}},moveToBookmark:function(e){function t(t){var n=e[t?"start":"end"],r,i,o,s;if(n){for(o=n[0],i=c,r=n.length-1;r>=1;r--){if(s=i.childNodes,n[r]>s.length-1)return;i=s[n[r]]}3===i.nodeType&&(o=Math.min(n[0],i.nodeValue.length)),1===i.nodeType&&(o=Math.min(n[0],i.childNodes.length)),t?a.setStart(i,o):a.setEnd(i,o)}return!0}function n(t){var n=o.get(e.id+"_"+t),r,i,a,c,d=e.keep;if(n&&(r=n.parentNode,"start"==t?(d?(r=n.firstChild,i=1):i=o.nodeIndex(n),f=p=r,m=h=i):(d?(r=n.firstChild,i=1):i=o.nodeIndex(n),p=r,h=i),!d)){for(c=n.previousSibling,a=n.nextSibling,s(l(n.childNodes),function(e){3==e.nodeType&&(e.nodeValue=e.nodeValue.replace(/\uFEFF/g,""))});n=o.get(e.id+"_"+t);)o.remove(n,1);c&&a&&c.nodeType==a.nodeType&&3==c.nodeType&&!u&&(i=c.nodeValue.length,c.appendData(a.nodeValue),o.remove(a),"start"==t?(f=p=c,m=h=i):(p=c,h=i))}}function r(e){return!o.isBlock(e)||e.innerHTML||d||(e.innerHTML='
'),e}var i=this,o=i.dom,a,c,f,p,m,h;if(e)if(e.start){if(a=o.createRng(),c=o.getRoot(),i.tridentSel)return i.tridentSel.moveToBookmark(e);t(!0)&&t()&&i.setRng(a)}else e.id?(n("start"),n("end"),f&&(a=o.createRng(),a.setStart(r(f),m),a.setEnd(r(p),h),i.setRng(a))):e.name?i.select(o.select(e.name)[e.index]):e.rng&&i.setRng(e.rng)},select:function(e,t){var n=this,r=n.dom,i=r.createRng(),o;if(n.lastFocusBookmark=null,e){if(!t&&n.controlSelection.controlSelect(e))return;o=r.nodeIndex(e),i.setStart(e.parentNode,o),i.setEnd(e.parentNode,o+1),t&&(n._moveEndPoint(i,e,!0),n._moveEndPoint(i,e)),n.setRng(i)}return e},isCollapsed:function(){var e=this,t=e.getRng(),n=e.getSel();return!t||t.item?!1:t.compareEndPoints?0===t.compareEndPoints("StartToEnd",t):!n||t.collapsed},collapse:function(e){var t=this,n=t.getRng(),r;n.item&&(r=n.item(0),n=t.win.document.body.createTextRange(),n.moveToElementText(r)),n.collapse(!!e),t.setRng(n)},getSel:function(){var e=this.win;return e.getSelection?e.getSelection():e.document.selection},getRng:function(e){var t=this,n,r,i,o=t.win.document,a;if(!e&&t.lastFocusBookmark){var s=t.lastFocusBookmark;return s.startContainer?(r=o.createRange(),r.setStart(s.startContainer,s.startOffset),r.setEnd(s.endContainer,s.endOffset)):r=s,r}if(e&&t.tridentSel)return t.tridentSel.getRangeAt(0);try{(n=t.getSel())&&(r=n.rangeCount>0?n.getRangeAt(0):n.createRange?n.createRange():o.createRange())}catch(l){}if(d&&r&&r.setStart){try{a=o.selection.createRange()}catch(l){}a&&a.item&&(i=a.item(0),r=o.createRange(),r.setStartBefore(i),r.setEndAfter(i))}return r||(r=o.createRange?o.createRange():o.body.createTextRange()),r.setStart&&9===r.startContainer.nodeType&&r.collapsed&&(i=t.dom.getRoot(),r.setStart(i,0),r.setEnd(i,0)),t.selectedRange&&t.explicitRange&&(0===r.compareBoundaryPoints(r.START_TO_START,t.selectedRange)&&0===r.compareBoundaryPoints(r.END_TO_END,t.selectedRange)?r=t.explicitRange:(t.selectedRange=null,t.explicitRange=null)),r},setRng:function(e,t){var n=this,r;if(e.select)try{e.select()}catch(i){}else if(n.tridentSel){if(e.cloneRange)try{return n.tridentSel.addRange(e),void 0}catch(i){}}else if(r=n.getSel()){n.explicitRange=e;try{r.removeAllRanges(),r.addRange(e)}catch(i){}t===!1&&r.extend&&(r.collapse(e.endContainer,e.endOffset),r.extend(e.startContainer,e.startOffset)),n.selectedRange=r.rangeCount>0?r.getRangeAt(0):null}},setNode:function(e){var t=this;return t.setContent(t.dom.getOuterHTML(e)),e},getNode:function(){function e(e,t){for(var n=e;e&&3===e.nodeType&&0===e.length;)e=t?e.nextSibling:e.previousSibling;return e||n}var t=this,n=t.getRng(),r,i=n.startContainer,o=n.endContainer,a=n.startOffset,s=n.endOffset,l=t.dom.getRoot();return n?n.setStart?(r=n.commonAncestorContainer,!n.collapsed&&(i==o&&2>s-a&&i.hasChildNodes()&&(r=i.childNodes[a]),3===i.nodeType&&3===o.nodeType&&(i=i.length===a?e(i.nextSibling,!0):i.parentNode,o=0===s?e(o.previousSibling,!1):o.parentNode,i&&i===o))?i:r&&3==r.nodeType?r.parentNode:r):(r=n.item?n.item(0):n.parentElement(),r.ownerDocument!==t.win.document&&(r=l),r):l},getSelectedBlocks:function(t,n){var r=this,i=r.dom,o,a,s=[];if(a=i.getRoot(),t=i.getParent(t||r.getStart(),i.isBlock),n=i.getParent(n||r.getEnd(),i.isBlock),t&&t!=a&&s.push(t),t&&n&&t!=n){o=t;for(var l=new e(t,a);(o=l.next())&&o!=n;)i.isBlock(o)&&s.push(o)}return n&&t!=n&&n!=a&&s.push(n),s},isForward:function(){var e=this.dom,t=this.getSel(),n,r;return t&&t.anchorNode&&t.focusNode?(n=e.createRng(),n.setStart(t.anchorNode,t.anchorOffset),n.collapse(!0),r=e.createRng(),r.setStart(t.focusNode,t.focusOffset),r.collapse(!0),n.compareBoundaryPoints(n.START_TO_START,r)<=0):!0},normalize:function(){function t(t){function a(t,n){for(var r=new e(t,f.getParent(t.parentNode,f.isBlock)||p);t=r[n?"prev":"next"]();)if("BR"===t.nodeName)return!0}function s(e,t){return e.previousSibling&&e.previousSibling.nodeName==t}function l(t,n){var r,a;for(n=n||c,r=new e(n,f.getParent(n.parentNode,f.isBlock)||p);m=r[t?"prev":"next"]();){if(3===m.nodeType&&m.nodeValue.length>0)return c=m,d=t?m.nodeValue.length:0,i=!0,void 0;if(f.isBlock(m)||h[m.nodeName.toLowerCase()])return;a=m}o&&a&&(c=a,i=!0,d=0)}var c,d,u,f=n.dom,p=f.getRoot(),m,h,g,v;if(c=r[(t?"start":"end")+"Container"],d=r[(t?"start":"end")+"Offset"],h=f.schema.getNonEmptyElements(),v=t,1==c.nodeType&&d>c.childNodes.length-1&&(v=!1),9===c.nodeType&&(c=f.getRoot(),d=0),c===p){if(v&&(m=c.childNodes[d>0?d-1:0],m&&(g=m.nodeName.toLowerCase(),h[m.nodeName]||"TABLE"==m.nodeName)))return;if(c.hasChildNodes()&&(d=Math.min(!v&&d>0?d-1:d,c.childNodes.length-1),c=c.childNodes[d],d=0,c.hasChildNodes()&&!/TABLE/.test(c.nodeName))){m=c,u=new e(c,p);do{if(3===m.nodeType&&m.nodeValue.length>0){d=v?0:m.nodeValue.length,c=m,i=!0;break}if(h[m.nodeName.toLowerCase()]){d=f.nodeIndex(m),c=m.parentNode,"IMG"!=m.nodeName||v||d++,i=!0;break}}while(m=v?u.next():u.prev())}}o&&(3===c.nodeType&&0===d&&l(!0),1===c.nodeType&&(m=c.childNodes[d],!m||"BR"!==m.nodeName||s(m,"A")||a(m)||a(m,!0)||l(!0,c.childNodes[d]))),v&&!o&&3===c.nodeType&&d===c.nodeValue.length&&l(!1),i&&r["set"+(t?"Start":"End")](c,d)}var n=this,r,i,o;d||(r=n.getRng(),o=r.collapsed,t(!0),o||t(),i&&(o&&r.collapse(!0),n.setRng(r,n.isForward())))},selectorChanged:function(e,t){var n=this,r;return n.selectorChangedData||(n.selectorChangedData={},r={},n.editor.on("NodeChange",function(e){var t=e.element,i=n.dom,o=i.getParents(t,null,i.getRoot()),a={};s(n.selectorChangedData,function(e,t){s(o,function(n){return i.is(n,t)?(r[t]||(s(e,function(e){e(!0,{node:n,selector:t,parents:o})}),r[t]=e),a[t]=e,!1):void 0})}),s(r,function(e,n){a[n]||(delete r[n],s(e,function(e){e(!1,{node:t,selector:n,parents:o})}))})})),n.selectorChangedData[e]||(n.selectorChangedData[e]=[]),n.selectorChangedData[e].push(t),n},getScrollContainer:function(){for(var e,t=this.dom.getRoot();t&&"BODY"!=t.nodeName;){if(t.scrollHeight>t.clientHeight){e=t;break}t=t.parentNode}return e},scrollIntoView:function(e){function t(e){for(var t=0,n=0,r=e;r&&r.nodeType;)t+=r.offsetLeft||0,n+=r.offsetTop||0,r=r.offsetParent;return{x:t,y:n}}var n,r,i=this,o=i.dom,a=o.getRoot(),s,l;if("BODY"!=a.nodeName){var c=i.getScrollContainer();if(c)return n=t(e).y-t(c).y,l=c.clientHeight,s=c.scrollTop,(s>n||n+25>s+l)&&(c.scrollTop=s>n?n:n-l+25),void 0}r=o.getViewPort(i.editor.getWin()),n=o.getPos(e).y,s=r.y,l=r.h,(ns+l)&&i.editor.getWin().scrollTo(0,s>n?n:n-l+25)},_moveEndPoint:function(t,n,r){var o=n,a=new e(n,o),s=this.dom.schema.getNonEmptyElements();do{if(3==n.nodeType&&0!==c(n.nodeValue).length)return r?t.setStart(n,0):t.setEnd(n,n.nodeValue.length),void 0;if(s[n.nodeName])return r?t.setStartBefore(n):"BR"==n.nodeName?t.setEndBefore(n):t.setEndAfter(n),void 0;if(i.ie&&i.ie<11&&this.dom.isBlock(n)&&this.dom.isEmpty(n))return r?t.setStart(n,0):t.setEnd(n,0),void 0}while(n=r?a.next():a.prev());"BODY"==o.nodeName&&(r?t.setStart(o,0):t.setEnd(o,o.childNodes.length))},destroy:function(){this.win=null,this.controlSelection.destroy()}},a}),r(A,[f],function(e){function t(e){this.walk=function(t,r){function i(e){var t;return t=e[0],3===t.nodeType&&t===l&&c>=t.nodeValue.length&&e.splice(0,1),t=e[e.length-1],0===u&&e.length>0&&t===d&&3===t.nodeType&&e.splice(e.length-1,1),e}function o(e,t,n){for(var r=[];e&&e!=n;e=e[t])r.push(e);return r}function a(e,t){do{if(e.parentNode==t)return e;e=e.parentNode}while(e)}function s(e,t,n){var a=n?"nextSibling":"previousSibling";for(h=e,g=h.parentNode;h&&h!=t;h=g)g=h.parentNode,v=o(h==e?h:h[a],a),v.length&&(n||v.reverse(),r(i(v)))}var l=t.startContainer,c=t.startOffset,d=t.endContainer,u=t.endOffset,f,p,m,h,g,v,y;if(y=e.select("td.mce-item-selected,th.mce-item-selected"),y.length>0)return n(y,function(e){r([e])}),void 0;if(1==l.nodeType&&l.hasChildNodes()&&(l=l.childNodes[c]),1==d.nodeType&&d.hasChildNodes()&&(d=d.childNodes[Math.min(u-1,d.childNodes.length-1)]),l==d)return r(i([l]));for(f=e.findCommonAncestor(l,d),h=l;h;h=h.parentNode){if(h===d)return s(l,f,!0);if(h===f)break}for(h=d;h;h=h.parentNode){if(h===l)return s(d,f);if(h===f)break}p=a(l,f)||l,m=a(d,f)||d,s(l,p,!0),v=o(p==l?p:p.nextSibling,"nextSibling",m==d?m.nextSibling:m),v.length&&r(i(v)),s(d,m)},this.split=function(e){function t(e,t){return e.splitText(t)}var n=e.startContainer,r=e.startOffset,i=e.endContainer,o=e.endOffset;return n==i&&3==n.nodeType?r>0&&rr?(o-=r,n=i=t(i,o).previousSibling,o=i.nodeValue.length,r=0):o=0):(3==n.nodeType&&r>0&&r0&&o=e;e++)r.addShortcut("ctrl+"+e,"",["FormatBlock",!1,"h"+e]);r.addShortcut("ctrl+7","",["FormatBlock",!1,"p"]),r.addShortcut("ctrl+8","",["FormatBlock",!1,"div"]),r.addShortcut("ctrl+9","",["FormatBlock",!1,"address"])}function c(e){return e?O[e]:O}function d(e,t){e&&("string"!=typeof e?et(e,function(e,t){d(t,e)}):(t=t.length?t:[t],et(t,function(e){e.deep===X&&(e.deep=!e.selector),e.split===X&&(e.split=!e.selector||e.inline),e.remove===X&&e.selector&&!e.inline&&(e.remove="none"),e.selector&&e.inline&&(e.mixed=!0,e.block_expand=!0),"string"==typeof e.classes&&(e.classes=e.classes.split(/\s+/))}),O[e]=t))}function u(e){var t;return r.dom.getParent(e,function(e){return t=r.dom.getStyle(e,"text-decoration"),t&&"none"!==t}),t}function f(e){var t;1===e.nodeType&&e.parentNode&&1===e.parentNode.nodeType&&(t=u(e.parentNode),r.dom.getStyle(e,"color")&&t?r.dom.setStyle(e,"text-decoration",t):r.dom.getStyle(e,"textdecoration")===t&&r.dom.setStyle(e,"text-decoration",null))}function p(t,n,o){function s(e,t){t=t||h,e&&(t.onformat&&t.onformat(e,t,n,o),et(t.styles,function(t,r){I.setStyle(e,r,E(t,n))}),et(t.attributes,function(t,r){I.setAttrib(e,r,E(t,n))}),et(t.classes,function(t){t=E(t,n),I.hasClass(e,t)||I.addClass(e,t)}))}function l(){function t(t,n){var r=new e(n);for(o=r.current();o;o=r.prev())if(o.childNodes.length>1||o==t||"BR"==o.tagName)return o}var n=r.selection.getRng(),i=n.startContainer,a=n.endContainer;if(i!=a&&0===n.endOffset){var s=t(i,a),l=3==s.nodeType?s.length:s.childNodes.length;n.setEnd(s,l)}return n}function d(e,t,n,r,i){var o=[],a=-1,s,l=-1,c=-1,d;return et(e.childNodes,function(e,t){return"UL"===e.nodeName||"OL"===e.nodeName?(a=t,s=e,!1):void 0}),et(e.childNodes,function(e,n){"SPAN"===e.nodeName&&"bookmark"==I.getAttrib(e,"data-mce-type")&&(e.id==t.id+"_start"?l=n:e.id==t.id+"_end"&&(c=n))}),0>=a||a>l&&c>a?(et(tt(e.childNodes),i),0):(d=I.clone(n,K),et(tt(e.childNodes),function(e,t){(a>l&&a>t||l>a&&t>a)&&(o.push(e),e.parentNode.removeChild(e))}),a>l?e.insertBefore(d,s):l>a&&e.insertBefore(d,s.nextSibling),r.push(d),et(o,function(e){d.appendChild(e)}),d)}function u(e,r,o){var l=[],c,u,f=!0;c=h.inline||h.block,u=I.create(c),s(u),z.walk(e,function(e){function p(e){var y,C,x,_,N;return N=f,y=e.nodeName.toLowerCase(),C=e.parentNode.nodeName.toLowerCase(),1===e.nodeType&&J(e)&&(N=f,f="true"===J(e),_=!0),w(y,"br")?(v=0,h.block&&I.remove(e),void 0):h.wrapper&&g(e,t,n)?(v=0,void 0):f&&!_&&h.block&&!h.wrapper&&i(y)&&W(C,c)?(e=I.rename(e,c),s(e),l.push(e),v=0,void 0):h.selector&&(et(m,function(t){"collapsed"in t&&t.collapsed!==b||I.is(e,t.selector)&&!a(e)&&(s(e,t),x=!0)}),!h.inline||x)?(v=0,void 0):(!f||_||!W(c,y)||!W(C,c)||!o&&3===e.nodeType&&1===e.nodeValue.length&&65279===e.nodeValue.charCodeAt(0)||a(e)||h.inline&&V(e)?"li"==y&&r?v=d(e,r,u,l,p):(v=0,et(tt(e.childNodes),p),_&&(f=N),v=0):(v||(v=I.clone(u,K),e.parentNode.insertBefore(v,e),l.push(v)),v.appendChild(e)),void 0)}var v;et(e,p)}),h.wrap_links===!1&&et(l,function(e){function t(e){var n,r,i;if("A"===e.nodeName){for(r=I.clone(u,K),l.push(r),i=tt(e.childNodes),n=0;n1||!V(e))&&0===o)return I.remove(e,1),void 0;if(h.inline||h.wrapper){if(h.exact||1!==o||(e=i(e)),et(m,function(t){et(I.select(t.inline,e),function(e){var r;if(t.wrap_links===!1){r=e.parentNode;do if("A"===r.nodeName)return;while(r=r.parentNode)}R(t,n,e,t.exact?e:null)})}),g(e.parentNode,t,n))return I.remove(e,1),e=0,Y;h.merge_with_parents&&I.getParent(e.parentNode,function(r){return g(r,t,n)?(I.remove(e,1),e=0,Y):void 0}),e&&h.merge_siblings!==!1&&(e=H(B(e),e),e=H(e,B(e,Y)))}})}var m=c(t),h=m[0],v,y,b=!o&&F.isCollapsed();if(h)if(o)o.nodeType?(y=I.createRng(),y.setStartBefore(o),y.setEndAfter(o),u(T(y,m),null,!0)):u(o,null,!0);else if(b&&h.inline&&!I.select("td.mce-item-selected,th.mce-item-selected").length)M("apply",t,n);else{var C=r.selection.getNode();U||!m[0].defaultBlock||I.getParent(C,I.isBlock)||p(m[0].defaultBlock),r.selection.setRng(l()),v=F.getBookmark(),u(T(F.getRng(Y),m),v),h.styles&&(h.styles.color||h.styles.textDecoration)&&(nt(C,f,"childNodes"),f(C)),F.moveToBookmark(v),P(F.getRng(Y)),r.nodeChanged()}}function m(e,t,n){function i(e){var n,r,o,a,s;if(1===e.nodeType&&J(e)&&(a=b,b="true"===J(e),s=!0),n=tt(e.childNodes),b&&!s)for(r=0,o=p.length;o>r&&!R(p[r],t,e,e);r++);if(m.deep&&n.length){for(r=0,o=n.length;o>r;r++)i(n[r]);s&&(b=a)}}function a(n){var r;return et(o(n.parentNode).reverse(),function(n){var i;r||"_start"==n.id||"_end"==n.id||(i=g(n,e,t),i&&i.split!==!1&&(r=n))}),r}function s(e,n,r,i){var o,a,s,l,c,d;if(e){for(d=e.parentNode,o=n.parentNode;o&&o!=d;o=o.parentNode){for(a=I.clone(o,K),c=0;c=0;a--){if(s=t[a].selector,!s||t[a].defaultBlock)return Y;for(i=r.length-1;i>=0;i--)if(I.is(r[i],s))return Y}return K}function C(e,t,n){var i;return G||(G={},i={},r.on("NodeChange",function(e){var t=o(e.element),n={};et(G,function(e,r){et(t,function(o){return g(o,r,{},e.similar)?(i[r]||(et(e,function(e){e(!0,{node:o,format:r,parents:t})}),i[r]=e),n[r]=e,!1):void 0})}),et(i,function(r,o){n[o]||(delete i[o],et(r,function(n){n(!1,{node:e.element,format:o,parents:t})}))})})),et(e.split(","),function(e){G[e]||(G[e]=[],G[e].similar=n),G[e].push(t)}),this}function x(e,t){return w(e,t.inline)?Y:w(e,t.block)?Y:t.selector?1==e.nodeType&&I.is(e,t.selector):void 0}function w(e,t){return e=e||"",t=t||"",e=""+(e.nodeName||e),t=""+(t.nodeName||t),e.toLowerCase()==t.toLowerCase()}function _(e,t){return N(I.getStyle(e,t),t)}function N(e,t){return("color"==t||"backgroundColor"==t)&&(e=I.toHex(e)),"fontWeight"==t&&700==e&&(e="bold"),"fontFamily"==t&&(e=e.replace(/[\'\"]/g,"").replace(/,\s+/g,",")),""+e}function E(e,t){return"string"!=typeof e?e=e(t):t&&(e=e.replace(/%(\w+)/g,function(e,n){return t[n]||e})),e}function k(e){return e&&3===e.nodeType&&/^([\t \r\n]+|)$/.test(e.nodeValue)}function S(e,t,n){var r=I.create(t,n);return e.parentNode.insertBefore(r,e),r.appendChild(e),r}function T(t,n,a){function s(e){function t(e){return"BR"==e.nodeName&&e.getAttribute("data-mce-bogus")&&!e.nextSibling}var r,i,o,a,s;if(r=i=e?g:y,a=e?"previousSibling":"nextSibling",s=I.getRoot(),3==r.nodeType&&!k(r)&&(e?v>0:br?n:r,-1===n||a||n++):(n=o.indexOf(" ",t),r=o.indexOf("\xa0",t),n=-1!==n&&(-1===r||r>n)?n:r),n}var s,l,c,d;if(3===t.nodeType){if(c=o(t,n),-1!==c)return{container:t,offset:c};d=t}for(s=new e(t,I.getParent(t,V)||r.getBody());l=s[i?"prev":"next"]();)if(3===l.nodeType){if(d=l,c=o(l),-1!==c)return{container:l,offset:c}}else if(V(l))break;return d?(n=i?0:d.length,{container:d,offset:n}):void 0}function u(e,r){var i,a,s,l;for(3==e.nodeType&&0===e.nodeValue.length&&e[r]&&(e=e[r]),i=o(e),a=0;ap?p:v],3==g.nodeType&&(v=0)),1==y.nodeType&&y.hasChildNodes()&&(p=y.childNodes.length-1,y=y.childNodes[b>p?p:b-1],3==y.nodeType&&(b=y.nodeValue.length)),g=c(g),y=c(y),(L(g.parentNode)||L(g))&&(g=L(g)?g:g.parentNode,g=g.nextSibling||g,3==g.nodeType&&(v=0)),(L(y.parentNode)||L(y))&&(y=L(y)?y:y.parentNode,y=y.previousSibling||y,3==y.nodeType&&(b=y.length)),n[0].inline&&(t.collapsed&&(h=d(g,v,!0),h&&(g=h.container,v=h.offset),h=d(y,b),h&&(y=h.container,b=h.offset)),m=l(y,b),m.node)){for(;m.node&&0===m.offset&&m.node.previousSibling;)m=l(m.node.previousSibling);m.node&&m.offset>0&&3===m.node.nodeType&&" "===m.node.nodeValue.charAt(m.offset-1)&&m.offset>1&&(y=m.node,y.splitText(m.offset-1))}return(n[0].inline||n[0].block_expand)&&(n[0].inline&&3==g.nodeType&&0!==v||(g=s(!0)),n[0].inline&&3==y.nodeType&&b!==y.nodeValue.length||(y=s())),n[0].selector&&n[0].expand!==K&&!n[0].inline&&(g=u(g,"previousSibling"),y=u(y,"nextSibling")),(n[0].block||n[0].selector)&&(g=f(g,"previousSibling"),y=f(y,"nextSibling"),n[0].block&&(V(g)||(g=s(!0)),V(y)||(y=s()))),1==g.nodeType&&(v=q(g),g=g.parentNode),1==y.nodeType&&(b=q(y)+1,y=y.parentNode),{startContainer:g,startOffset:v,endContainer:y,endOffset:b}}function R(e,t,n,r){var i,o,a;if(!x(n,e))return K;if("all"!=e.remove)for(et(e.styles,function(e,i){e=N(E(e,t),i),"number"==typeof i&&(i=e,r=0),(!r||w(_(r,i),e))&&I.setStyle(n,i,""),a=1}),a&&""===I.getAttrib(n,"style")&&(n.removeAttribute("style"),n.removeAttribute("data-mce-style")),et(e.attributes,function(e,i){var o;if(e=E(e,t),"number"==typeof i&&(i=e,r=0),!r||w(I.getAttrib(r,i),e)){if("class"==i&&(e=I.getAttrib(n,i),e&&(o="",et(e.split(/\s+/),function(e){/mce\w+/.test(e)&&(o+=(o?" ":"")+e)}),o)))return I.setAttrib(n,i,o),void 0;"class"==i&&n.removeAttribute("className"),$.test(i)&&n.removeAttribute("data-mce-"+i),n.removeAttribute(i)}}),et(e.classes,function(e){e=E(e,t),(!r||I.hasClass(r,e))&&I.removeClass(n,e)}),o=I.getAttribs(n),i=0;ia?a:o]),3===i.nodeType&&n&&o>=i.nodeValue.length&&(i=new e(i,r.getBody()).next()||i),3!==i.nodeType||n||0!==o||(i=new e(i,r.getBody()).prev()||i),i}function M(t,n,o){function a(e){var t=I.create("span",{id:y,"data-mce-bogus":!0,style:b?"color:red":""});return e&&t.appendChild(r.getDoc().createTextNode(j)),t}function s(e,t){for(;e;){if(3===e.nodeType&&e.nodeValue!==j||e.childNodes.length>1)return!1;t&&1===e.nodeType&&t.push(e),e=e.firstChild}return!0}function l(e){for(;e;){if(e.id===y)return e;e=e.parentNode}}function d(t){var n;if(t)for(n=new e(t,t),t=n.current();t;t=n.next())if(3===t.nodeType)return t}function u(e,t){var n,r;if(e)r=F.getRng(!0),s(e)?(t!==!1&&(r.setStartBefore(e),r.setEndBefore(e)),I.remove(e)):(n=d(e),n.nodeValue.charAt(0)===j&&(n=n.deleteData(0,1)),I.remove(e,1)),F.setRng(r);else if(e=l(F.getStart()),!e)for(;e=I.get(y);)u(e,!1)}function f(){var e,t,r,i,s,u,f;e=F.getRng(!0),i=e.startOffset,u=e.startContainer,f=u.nodeValue,t=l(F.getStart()),t&&(r=d(t)),f&&i>0&&i=0;p--)d.appendChild(I.clone(f[p],!1)),d=d.firstChild;d.appendChild(I.doc.createTextNode(j)),d=d.firstChild;var v=I.getParent(u,i);v&&I.isEmpty(v)?u.parentNode.replaceChild(h,u):I.insertAfter(h,u),F.setCursorLocation(d,1),I.isEmpty(u)&&I.remove(u)}}function v(){var e;e=l(F.getStart()),e&&!I.isEmpty(e)&&nt(e,function(e){1!=e.nodeType||e.id===y||I.isEmpty(e)||I.setAttrib(e,"data-mce-bogus",null)},"childNodes")}var y="_mce_caret",b=r.settings.caret_debug;r._hasCaretEvents||(Z=function(){var e=[],t;if(s(l(F.getStart()),e))for(t=e.length;t--;)I.setAttrib(e[t],"data-mce-bogus","1")},Q=function(e){var t=e.keyCode;u(),(8==t||37==t||39==t)&&u(l(F.getStart())),v()},r.on("SetContent",function(e){e.selection&&v()}),r._hasCaretEvents=!0),"apply"==t?f():h()}function P(t){var n=t.startContainer,r=t.startOffset,i,o,a,s,l;if(3==n.nodeType&&r>=n.nodeValue.length&&(r=q(n),n=n.parentNode,i=!0),1==n.nodeType)for(s=n.childNodes,n=s[Math.min(r,s.length-1)],o=new e(n,I.getParent(n,I.isBlock)),(r>s.length-1||i)&&o.next(),a=o.current();a;a=o.next())if(3==a.nodeType&&!k(a))return l=I.create("a",null,j),a.parentNode.insertBefore(l,a),t.setStart(a,0),F.setRng(t),I.remove(l),void 0}var O={},I=r.dom,F=r.selection,z=new t(I),W=r.schema.isValidChild,V=I.isBlock,U=r.settings.forced_root_block,q=I.nodeIndex,j="\ufeff",$=/^(src|href|style)$/,K=!1,Y=!0,G,X,J=I.getContentEditable,Q,Z,et=n.each,tt=n.grep,nt=n.walk,rt=n.extend;rt(this,{get:c,register:d,apply:p,remove:m,toggle:h,match:v,matchAll:y,matchNode:g,canApply:b,formatChanged:C}),s(),l(),r.on("BeforeGetContent",function(){Z&&Z()}),r.on("mouseup keydown",function(e){Q&&Q(e)})}}),r(L,[h,f],function(e,t){var n=t.trim,r;return r=new RegExp(["]+data-mce-bogus[^>]+>[\u200b\ufeff]+<\\/span>","]+data-mce-bogus[^>]+><\\/div>",'\\s?data-mce-selected="[^"]+"'].join("|"),"gi"),function(t){function i(){return n(t.getContent({format:"raw",no_events:1}).replace(r,""))}function o(){a.typing=!1,a.add()}var a,s=0,l=[],c,d,u;return t.on("init",function(){a.add()}),t.on("BeforeExecCommand",function(e){var t=e.command;"Undo"!=t&&"Redo"!=t&&"mceRepaint"!=t&&a.beforeChange()}),t.on("ExecCommand",function(e){var t=e.command;"Undo"!=t&&"Redo"!=t&&"mceRepaint"!=t&&a.add()}),t.on("ObjectResizeStart",function(){a.beforeChange()}),t.on("SaveContent ObjectResized",o),t.dom.bind(t.dom.getRoot(),"dragend",o),t.dom.bind(t.getBody(),"focusout",function(){!t.removed&&a.typing&&o()}),t.on("KeyUp",function(n){var r=n.keyCode;(r>=33&&36>=r||r>=37&&40>=r||45==r||13==r||n.ctrlKey)&&(o(),t.nodeChanged()),(46==r||8==r||e.mac&&(91==r||93==r))&&t.nodeChanged(),d&&a.typing&&(t.isDirty()||(t.isNotDirty=!l[0]||i()==l[0].content,t.isNotDirty||t.fire("change",{level:l[0],lastLevel:null})),t.fire("TypingUndo"),d=!1,t.nodeChanged())}),t.on("KeyDown",function(e){var t=e.keyCode;return t>=33&&36>=t||t>=37&&40>=t||45==t?(a.typing&&o(),void 0):((16>t||t>20)&&224!=t&&91!=t&&!a.typing&&(a.beforeChange(),a.typing=!0,a.add(),d=!0),void 0)}),t.on("MouseDown",function(){a.typing&&o()}),t.addShortcut("ctrl+z","","Undo"),t.addShortcut("ctrl+y,ctrl+shift+z","","Redo"),t.on("AddUndo Undo Redo ClearUndos MouseUp",function(e){e.isDefaultPrevented()||t.nodeChanged()}),a={data:l,typing:!1,beforeChange:function(){u||(c=t.selection.getBookmark(2,!0))},add:function(e){var n,r=t.settings,o;if(e=e||{},e.content=i(),u||t.fire("BeforeAddUndo",{level:e}).isDefaultPrevented())return null;if(o=l[s],o&&o.content==e.content)return null;if(l[s]&&(l[s].beforeBookmark=c),r.custom_undo_redo_levels&&l.length>r.custom_undo_redo_levels){for(n=0;n0&&(t.fire("change",a),t.isNotDirty=!1),e},undo:function(){var e;return a.typing&&(a.add(),a.typing=!1),s>0&&(e=l[--s],0===s&&(t.isNotDirty=!0),t.setContent(e.content,{format:"raw"}),t.selection.moveToBookmark(e.beforeBookmark),t.fire("undo",{level:e})),e},redo:function(){var e;return s0||a.typing&&l[0]&&i()!=l[0].content},hasRedo:function(){return sB)&&(u=o.create("br"),n.parentNode.insertBefore(u,n)),l.setStartBefore(n),l.setEndBefore(n)):(l.setStartAfter(n),l.setEndAfter(n)):(l.setStart(n,0),l.setEnd(n,0));a.setRng(l),o.remove(u),a.scrollIntoView(n)}function h(e){var t=s.forced_root_block;t&&t.toLowerCase()===e.tagName.toLowerCase()&&o.setAttribs(e,s.forced_root_block_attrs)}function g(e){var t=T,r,i,a;if(e||"TABLE"==P?(r=o.create(e||I),h(r)):r=A.cloneNode(!1),a=r,s.keep_styles!==!1)do if(/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(t.nodeName)){if("_mce_caret"==t.id)continue;i=t.cloneNode(!1),o.setAttrib(i,"id",""),r.hasChildNodes()?(i.appendChild(r.firstChild),r.appendChild(i)):(a=i,r.appendChild(i))}while(t=t.parentNode);return n||(a.innerHTML='
'),r}function v(t){var n,r,i;if(3==T.nodeType&&(t?R>0:R0)return!0}function x(){var e,t,r;T&&3==T.nodeType&&R>=T.nodeValue.length&&(n||C()||(e=o.create("br"),E.insertNode(e),E.setStartAfter(e),E.setEndAfter(e),t=!0)),e=o.create("br"),E.insertNode(e),n&&"PRE"==P&&(!B||8>B)&&e.parentNode.insertBefore(o.doc.createTextNode("\r"),e),r=o.create("span",{}," "),e.parentNode.insertBefore(r,e),a.scrollIntoView(r),o.remove(r),t?(E.setStartBefore(e),E.setEndBefore(e)):(E.setStartAfter(e),E.setEndAfter(e)),a.setRng(E),l.add()}function w(e){do 3===e.nodeType&&(e.nodeValue=e.nodeValue.replace(/^[\r\n]+/,"")),e=e.firstChild;while(e)}function _(e){var t=o.getRoot(),n,r;for(n=e;n!==t&&"false"!==o.getContentEditable(n);)"true"===o.getContentEditable(n)&&(r=n),n=n.parentNode;return n!==t?r:t}function N(e){var t;n||(e.normalize(),t=e.lastChild,(!t||/^(left|right)$/gi.test(o.getStyle(t,"float",!0)))&&o.add(e,"br"))}var E=a.getRng(!0),k,S,T,R,A,B,L,H,D,M,P,O,I,F;if(!E.collapsed)return r.execCommand("Delete"),void 0;if(!i.isDefaultPrevented()&&(T=E.startContainer,R=E.startOffset,I=(s.force_p_newlines?"p":"")||s.forced_root_block,I=I?I.toUpperCase():"",B=o.doc.documentMode,L=i.shiftKey,1==T.nodeType&&T.hasChildNodes()&&(F=R>T.childNodes.length-1,T=T.childNodes[Math.min(R,T.childNodes.length-1)]||T,R=F&&3==T.nodeType?T.nodeValue.length:0),S=_(T))){if(l.beforeChange(),!o.isBlock(S)&&S!=o.getRoot())return(!I||L)&&x(),void 0;if((I&&!L||!I&&L)&&(T=y(T,R)),A=o.getParent(T,o.isBlock),M=A?o.getParent(A.parentNode,o.isBlock):null,P=A?A.nodeName.toUpperCase():"",O=M?M.nodeName.toUpperCase():"","LI"!=O||i.ctrlKey||(A=M,P=O),"LI"==P){if(!I&&L)return x(),void 0;if(o.isEmpty(A))return b(),void 0}if("PRE"==P&&s.br_in_pre!==!1){if(!L)return x(),void 0}else if(!I&&!L&&"LI"!=P||I&&L)return x(),void 0;I&&A===r.getBody()||(I=I||"P",v()?(H=/^(H[1-6]|PRE|FIGURE)$/.test(P)&&"HGROUP"!=O?g(I):g(),s.end_container_on_empty_block&&u(M)&&o.isEmpty(A)?H=o.split(M,A):o.insertAfter(H,A),m(H)):v(!0)?(H=A.parentNode.insertBefore(g(),A),f(H),m(A)):(k=E.cloneRange(),k.setEndAfter(A),D=k.extractContents(),w(D),H=D.firstChild,o.insertAfter(D,A),p(H),N(A),m(H)),o.setAttrib(H,"id",""),r.fire("NewBlock",{newBlock:H}),l.add())}}var o=r.dom,a=r.selection,s=r.settings,l=r.undoManager,c=r.schema,d=c.getNonEmptyElements();r.on("keydown",function(e){13==e.keyCode&&i(e)!==!1&&e.preventDefault()})}}),r(D,[],function(){return function(e){function t(){var t=i.getStart(),s=e.getBody(),l,c,d,u,f,p,m,h=-16777215,g,v,y,b,C;if(C=n.forced_root_block,t&&1===t.nodeType&&C){for(;t&&t!=s;){if(a[t.nodeName])return;t=t.parentNode}if(l=i.getRng(),l.setStart){c=l.startContainer,d=l.startOffset,u=l.endContainer,f=l.endOffset;try{v=e.getDoc().activeElement===s}catch(x){}}else l.item&&(t=l.item(0),l=e.getDoc().body.createTextRange(),l.moveToElementText(t)),v=l.parentElement().ownerDocument===e.getDoc(),y=l.duplicate(),y.collapse(!0),d=-1*y.move("character",h),y.collapsed||(y=l.duplicate(),y.collapse(!1),f=-1*y.move("character",h)-d);for(t=s.firstChild,b=s.nodeName.toLowerCase();t;)if((3===t.nodeType||1==t.nodeType&&!a[t.nodeName])&&o.isValidChild(b,C.toLowerCase())){if(3===t.nodeType&&0===t.nodeValue.length){m=t,t=t.nextSibling,r.remove(m);continue}p||(p=r.create(C,e.settings.forced_root_block_attrs),t.parentNode.insertBefore(p,t),g=!0),m=t,t=t.nextSibling,p.appendChild(m)}else p=null,t=t.nextSibling;if(g&&v){if(l.setStart)l.setStart(c,d),l.setEnd(u,f),i.setRng(l);else try{l=e.getDoc().body.createTextRange(),l.moveToElementText(s),l.collapse(!0),l.moveStart("character",d),f>0&&l.moveEnd("character",f),l.select()}catch(x){}e.nodeChanged()}}}var n=e.settings,r=e.dom,i=e.selection,o=e.schema,a=o.getBlockElements();n.forced_root_block&&e.on("NodeChange",t)}}),r(M,[N,h,f],function(e,n,r){var i=r.each,o=r.extend,a=r.map,s=r.inArray,l=r.explode,c=n.gecko,d=n.ie,u=!0,f=!1;return function(r){function p(e,t,n){var r;return e=e.toLowerCase(),(r=N.exec[e])?(r(e,t,n),u):f}function m(e){var t;return e=e.toLowerCase(),(t=N.state[e])?t(e):-1}function h(e){var t;return e=e.toLowerCase(),(t=N.value[e])?t(e):f}function g(e,t){t=t||"exec",i(e,function(e,n){i(n.toLowerCase().split(","),function(n){N[t][n]=e})})}function v(e,n,i){return n===t&&(n=f),i===t&&(i=null),r.getDoc().execCommand(e,n,i)}function y(e){return k.match(e)}function b(e,n){k.toggle(e,n?{value:n}:t),r.nodeChanged()}function C(e){S=_.getBookmark(e)}function x(){_.moveToBookmark(S)}var w=r.dom,_=r.selection,N={state:{},exec:{},value:{}},E=r.settings,k=r.formatter,S;o(this,{execCommand:p,queryCommandState:m,queryCommandValue:h,addCommands:g}),g({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){r.undoManager.add()},"Cut,Copy,Paste":function(e){var t=r.getDoc(),i;try{v(e)}catch(o){i=u}if(i||!t.queryCommandSupported(e)){var a=r.translate("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.");n.mac&&(a=a.replace(/Ctrl\+/g,"\u2318+")),r.windowManager.alert(a)}},unlink:function(){if(_.isCollapsed()){var e=_.getNode();return"A"==e.tagName&&r.dom.remove(e,!0),void 0}k.remove("link")},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(e){var t=e.substring(7);"full"==t&&(t="justify"),i("left,center,right,justify".split(","),function(e){t!=e&&k.remove("align"+e)}),b("align"+t),p("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(e){var t,n;v(e),t=w.getParent(_.getNode(),"ol,ul"),t&&(n=t.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(n.nodeName)&&(C(),w.split(n,t),x()))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){b(e)},"ForeColor,HiliteColor,FontName":function(e,t,n){b(e,n)},FontSize:function(e,t,n){var r,i;n>=1&&7>=n&&(i=l(E.font_size_style_values),r=l(E.font_size_classes),n=r?r[n-1]||n:i[n-1]||n),b(e,n)},RemoveFormat:function(e){k.remove(e)},mceBlockQuote:function(){b("blockquote")},FormatBlock:function(e,t,n){return b(n||"p")},mceCleanup:function(){var e=_.getBookmark();r.setContent(r.getContent({cleanup:u}),{cleanup:u}),_.moveToBookmark(e)},mceRemoveNode:function(e,t,n){var i=n||_.getNode();i!=r.getBody()&&(C(),r.dom.remove(i,u),x())},mceSelectNodeDepth:function(e,t,n){var i=0;w.getParent(_.getNode(),function(e){return 1==e.nodeType&&i++==n?(_.select(e),f):void 0},r.getBody())},mceSelectNode:function(e,t,n){_.select(n)},mceInsertContent:function(t,n,i){function o(e){function t(e){return r[e]&&3==r[e].nodeType}var n,r,i;return n=_.getRng(!0),r=n.startContainer,i=n.startOffset,3==r.nodeType&&(i>0?e=e.replace(/^ /," "):t("previousSibling")||(e=e.replace(/^ /," ")),i|)$/," "):t("nextSibling")||(e=e.replace(/( | )(
|)$/," "))),e}var a,s,l,c,u,f,p,m,h,g,v;/^ | $/.test(i)&&(i=o(i)),a=r.parser,s=new e({},r.schema),v='ÈB;',f={content:i,format:"html",selection:!0},r.fire("BeforeSetContent",f),i=f.content,-1==i.indexOf("{$caret}")&&(i+="{$caret}"),i=i.replace(/\{\$caret\}/,v),m=_.getRng();var y=m.startContainer||(m.parentElement?m.parentElement():null),b=r.getBody();y===b&&_.isCollapsed()&&w.isBlock(b.firstChild)&&w.isEmpty(b.firstChild)&&(m=w.createRng(),m.setStart(b.firstChild,0),m.setEnd(b.firstChild,0),_.setRng(m)),_.isCollapsed()||r.getDoc().execCommand("Delete",!1,null),l=_.getNode(); +var C={context:l.nodeName.toLowerCase()};if(u=a.parse(i,C),h=u.lastChild,"mce_marker"==h.attr("id"))for(p=h,h=h.prev;h;h=h.walk(!0))if(3==h.type||!w.isBlock(h.name)){h.parent.insert(p,h,"br"===h.name);break}if(C.invalid){for(_.setContent(v),l=_.getNode(),c=r.getBody(),9==l.nodeType?l=h=c:h=l;h!==c;)l=h,h=h.parentNode;i=l==c?c.innerHTML:w.getOuterHTML(l),i=s.serialize(a.parse(i.replace(//i,function(){return s.serialize(u)}))),l==c?w.setHTML(c,i):w.setOuterHTML(l,i)}else i=s.serialize(u),h=l.firstChild,g=l.lastChild,!h||h===g&&"BR"===h.nodeName?w.setHTML(l,i):_.setContent(i);p=w.get("mce_marker"),_.scrollIntoView(p),m=w.createRng(),h=p.previousSibling,h&&3==h.nodeType?(m.setStart(h,h.nodeValue.length),d||(g=p.nextSibling,g&&3==g.nodeType&&(h.appendData(g.data),g.parentNode.removeChild(g)))):(m.setStartBefore(p),m.setEndBefore(p)),w.remove(p),_.setRng(m),r.fire("SetContent",f),r.addVisual()},mceInsertRawHTML:function(e,t,n){_.setContent("tiny_mce_marker"),r.setContent(r.getContent().replace(/tiny_mce_marker/g,function(){return n}))},mceToggleFormat:function(e,t,n){b(n)},mceSetContent:function(e,t,n){r.setContent(n)},"Indent,Outdent":function(e){var t,n,r;t=E.indentation,n=/[a-z%]+$/i.exec(t),t=parseInt(t,10),m("InsertUnorderedList")||m("InsertOrderedList")?v(e):(E.forced_root_block||w.getParent(_.getNode(),w.isBlock)||k.apply("div"),i(_.getSelectedBlocks(),function(i){var o;"LI"!=i.nodeName&&(o="rtl"==w.getStyle(i,"direction",!0)?"paddingRight":"paddingLeft","outdent"==e?(r=Math.max(0,parseInt(i.style[o]||0,10)-t),w.setStyle(i,o,r?r+n:"")):(r=parseInt(i.style[o]||0,10)+t+n,w.setStyle(i,o,r)))}))},mceRepaint:function(){if(c)try{C(u),_.getSel()&&_.getSel().selectAllChildren(r.getBody()),_.collapse(u),x()}catch(e){}},InsertHorizontalRule:function(){r.execCommand("mceInsertContent",!1,"
")},mceToggleVisualAid:function(){r.hasVisual=!r.hasVisual,r.addVisual()},mceReplaceContent:function(e,t,n){r.execCommand("mceInsertContent",!1,n.replace(/\{\$selection\}/g,_.getContent({format:"text"})))},mceInsertLink:function(e,t,n){var r;"string"==typeof n&&(n={href:n}),r=w.getParent(_.getNode(),"a"),n.href=n.href.replace(" ","%20"),r&&n.href||k.remove("link"),n.href&&k.apply("link",n,r)},selectAll:function(){var e=w.getRoot(),t;_.getRng().setStart?(t=w.createRng(),t.setStart(e,0),t.setEnd(e,e.childNodes.length),_.setRng(t)):(t=_.getRng(),t.item||(t.moveToElementText(e),t.select()))},"delete":function(){v("Delete");var e=r.getBody();w.isEmpty(e)&&(r.setContent(""),e.firstChild&&w.isBlock(e.firstChild)?r.selection.setCursorLocation(e.firstChild,0):r.selection.setCursorLocation(e,0))},mceNewDocument:function(){r.setContent("")}}),g({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(e){var t="align"+e.substring(7),n=_.isCollapsed()?[w.getParent(_.getNode(),w.isBlock)]:_.getSelectedBlocks(),r=a(n,function(e){return!!k.matchNode(e,t)});return-1!==s(r,u)},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){return y(e)},mceBlockQuote:function(){return y("blockquote")},Outdent:function(){var e;if(E.inline_styles){if((e=w.getParent(_.getStart(),w.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return u;if((e=w.getParent(_.getEnd(),w.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return u}return m("InsertUnorderedList")||m("InsertOrderedList")||!E.inline_styles&&!!w.getParent(_.getNode(),"BLOCKQUOTE")},"InsertUnorderedList,InsertOrderedList":function(e){var t=w.getParent(_.getNode(),"ul,ol");return t&&("insertunorderedlist"===e&&"UL"===t.tagName||"insertorderedlist"===e&&"OL"===t.tagName)}},"state"),g({"FontSize,FontName":function(e){var t=0,n;return(n=w.getParent(_.getNode(),"span"))&&(t="fontsize"==e?n.style.fontSize:n.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()),t}},"value"),g({Undo:function(){r.undoManager.undo()},Redo:function(){r.undoManager.redo()}})}}),r(P,[f],function(e){function t(e,i){var o=this,a,s;if(e=r(e),i=o.settings=i||{},/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e))return o.source=e,void 0;var l=0===e.indexOf("//");0!==e.indexOf("/")||l||(e=(i.base_uri?i.base_uri.protocol||"http":"http")+"://mce_host"+e),/^[\w\-]*:?\/\//.test(e)||(s=i.base_uri?i.base_uri.path:new t(location.href).directory,e=""===i.base_uri.protocol?"//mce_host"+o.toAbsPath(s,e):(i.base_uri&&i.base_uri.protocol||"http")+"://mce_host"+o.toAbsPath(s,e)),e=e.replace(/@@/g,"(mce_at)"),e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e),n(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(t,n){var r=e[n];r&&(r=r.replace(/\(mce_at\)/g,"@@")),o[t]=r}),a=i.base_uri,a&&(o.protocol||(o.protocol=a.protocol),o.userInfo||(o.userInfo=a.userInfo),o.port||"mce_host"!==o.host||(o.port=a.port),o.host&&"mce_host"!==o.host||(o.host=a.host),o.source=""),l&&(o.protocol="")}var n=e.each,r=e.trim;return t.prototype={setPath:function(e){var t=this;e=/^(.*?)\/?(\w+)?$/.exec(e),t.path=e[0],t.directory=e[1],t.file=e[2],t.source="",t.getURI()},toRelative:function(e){var n=this,r;if("./"===e)return e;if(e=new t(e,{base_uri:n}),"mce_host"!=e.host&&n.host!=e.host&&e.host||n.port!=e.port||n.protocol!=e.protocol&&""!==e.protocol)return e.getURI();var i=n.getURI(),o=e.getURI();return i==o||"/"==i.charAt(i.length-1)&&i.substr(0,i.length-1)==o?i:(r=n.toRelPath(n.path,e.path),e.query&&(r+="?"+e.query),e.anchor&&(r+="#"+e.anchor),r)},toAbsolute:function(e,n){return e=new t(e,{base_uri:this}),e.getURI(this.host==e.host&&this.protocol==e.protocol?n:0)},toRelPath:function(e,t){var n,r=0,i="",o,a;if(e=e.substring(0,e.lastIndexOf("/")),e=e.split("/"),n=t.split("/"),e.length>=n.length)for(o=0,a=e.length;a>o;o++)if(o>=n.length||e[o]!=n[o]){r=o+1;break}if(e.lengtho;o++)if(o>=e.length||e[o]!=n[o]){r=o+1;break}if(1===r)return t;for(o=0,a=e.length-(r-1);a>o;o++)i+="../";for(o=r-1,a=n.length;a>o;o++)i+=o!=r-1?"/"+n[o]:n[o];return i},toAbsPath:function(e,t){var r,i=0,o=[],a,s;for(a=/\/$/.test(t)?"/":"",e=e.split("/"),t=t.split("/"),n(e,function(e){e&&o.push(e)}),e=o,r=t.length-1,o=[];r>=0;r--)0!==t[r].length&&"."!==t[r]&&(".."!==t[r]?i>0?i--:o.push(t[r]):i++);return r=e.length-i,s=0>=r?o.reverse().join("/"):e.slice(0,r).join("/")+"/"+o.reverse().join("/"),0!==s.indexOf("/")&&(s="/"+s),a&&s.lastIndexOf("/")!==s.length-1&&(s+=a),s},getURI:function(e){var t,n=this;return(!n.source||e)&&(t="",e||(t+=n.protocol?n.protocol+"://":"//",n.userInfo&&(t+=n.userInfo+"@"),n.host&&(t+=n.host),n.port&&(t+=":"+n.port)),n.path&&(t+=n.path),n.query&&(t+="?"+n.query),n.anchor&&(t+="#"+n.anchor),n.source=t),n.source}},t}),r(O,[f],function(e){function t(){}var n=e.each,r=e.extend,i,o;return t.extend=i=function(e){function t(){var e,t,n,r;if(!o&&(r=this,r.init&&r.init.apply(r,arguments),t=r.Mixins))for(e=t.length;e--;)n=t[e],n.init&&n.init.apply(r,arguments)}function a(){return this}function s(e,t){return function(){var n=this,r=n._super,i;return n._super=c[e],i=t.apply(n,arguments),n._super=r,i}}var l=this,c=l.prototype,d,u,f;o=!0,d=new l,o=!1,e.Mixins&&(n(e.Mixins,function(t){t=t;for(var n in t)"init"!==n&&(e[n]=t[n])}),c.Mixins&&(e.Mixins=c.Mixins.concat(e.Mixins))),e.Methods&&n(e.Methods.split(","),function(t){e[t]=a}),e.Properties&&n(e.Properties.split(","),function(t){var n="_"+t;e[t]=function(e){var t=this,r;return e!==r?(t[n]=e,t):t[n]}}),e.Statics&&n(e.Statics,function(e,n){t[n]=e}),e.Defaults&&c.Defaults&&(e.Defaults=r({},c.Defaults,e.Defaults));for(u in e)f=e[u],d[u]="function"==typeof f&&c[u]?s(u,f):f;return t.prototype=d,t.constructor=t,t.extend=i,t},t}),r(I,[O],function(e){function t(e){for(var t=[],n=e.length,r;n--;)r=e[n],r.__checked||(t.push(r),r.__checked=1);for(n=t.length;n--;)delete t[n].__checked;return t}var n=/^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i,r=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i=/^\s*|\s*$/g,o,a=e.extend({init:function(e){function t(e){return e?(e=e.toLowerCase(),function(t){return"*"===e||t.type===e}):void 0}function o(e){return e?function(t){return t._name===e}:void 0}function a(e){return e?(e=e.split("."),function(t){for(var n=e.length;n--;)if(!t.hasClass(e[n]))return!1;return!0}):void 0}function s(e,t,n){return e?function(r){var i=r[e]?r[e]():"";return t?"="===t?i===n:"*="===t?i.indexOf(n)>=0:"~="===t?(" "+i+" ").indexOf(" "+n+" ")>=0:"!="===t?i!=n:"^="===t?0===i.indexOf(n):"$="===t?i.substr(i.length-n.length)===n:!1:!!n}:void 0}function l(e){var t;return e?(e=/(?:not\((.+)\))|(.+)/i.exec(e),e[1]?(t=d(e[1],[]),function(e){return!u(e,t)}):(e=e[2],function(t,n,r){return"first"===e?0===n:"last"===e?n===r-1:"even"===e?n%2===0:"odd"===e?n%2===1:t[e]?t[e]():!1})):void 0}function c(e,r,c){function d(e){e&&r.push(e)}var u;return u=n.exec(e.replace(i,"")),d(t(u[1])),d(o(u[2])),d(a(u[3])),d(s(u[4],u[5],u[6])),d(l(u[7])),r.psuedo=!!u[7],r.direct=c,r}function d(e,t){var n=[],i,o,a;do if(r.exec(""),o=r.exec(e),o&&(e=o[3],n.push(o[1]),o[2])){i=o[3];break}while(o);for(i&&d(i,t),e=[],a=0;a"!=n[a]&&e.push(c(n[a],[],">"===n[a-1]));return t.push(e),t}var u=this.match;this._selectors=d(e,[])},match:function(e,t){var n,r,i,o,a,s,l,c,d,u,f,p,m;for(t=t||this._selectors,n=0,r=t.length;r>n;n++){for(a=t[n],o=a.length,m=e,p=0,i=o-1;i>=0;i--)for(c=a[i];m;){if(c.psuedo)for(f=m.parent().items(),d=u=f.length;d--&&f[d]!==m;);for(s=0,l=c.length;l>s;s++)if(!c[s](m,d,u)){s=l+1;break}if(s===l){p++;break}if(i===o-1)break;m=m.parent()}if(p===o)return!0}return!1},find:function(e){function n(e,t,i){var o,a,s,l,c,d=t[i];for(o=0,a=e.length;a>o;o++){for(c=e[o],s=0,l=d.length;l>s;s++)if(!d[s](c,o,a)){s=l+1;break}if(s===l)i==t.length-1?r.push(c):c.items&&n(c.items(),t,i+1);else if(d.direct)return;c.items&&n(c.items(),t,i)}}var r=[],i,s,l=this._selectors;if(e.items){for(i=0,s=l.length;s>i;i++)n(e.items(),l[i],0);s>1&&(r=t(r))}return o||(o=a.Collection),new o(r)}});return a}),r(F,[f,I,O],function(e,t,n){var r,i,o=Array.prototype.push,a=Array.prototype.slice;return i={length:0,init:function(e){e&&this.add(e)},add:function(t){var n=this;return e.isArray(t)?o.apply(n,t):t instanceof r?n.add(t.toArray()):o.call(n,t),n},set:function(e){var t=this,n=t.length,r;for(t.length=0,t.add(e),r=t.length;n>r;r++)delete t[r];return t},filter:function(e){var n=this,i,o,a=[],s,l;for("string"==typeof e?(e=new t(e),l=function(t){return e.match(t)}):l=e,i=0,o=n.length;o>i;i++)s=n[i],l(s)&&a.push(s);return new r(a)},slice:function(){return new r(a.apply(this,arguments))},eq:function(e){return-1===e?this.slice(e):this.slice(e,+e+1)},each:function(t){return e.each(this,t),this},toArray:function(){return e.toArray(this)},indexOf:function(e){for(var t=this,n=t.length;n--&&t[n]!==e;);return n},reverse:function(){return new r(e.toArray(this).reverse())},hasClass:function(e){return this[0]?this[0].hasClass(e):!1},prop:function(e,t){var n=this,r,i;return t!==r?(n.each(function(n){n[e]&&n[e](t)}),n):(i=n[0],i&&i[e]?i[e]():void 0)},exec:function(t){var n=this,r=e.toArray(arguments).slice(1);return n.each(function(e){e[t]&&e[t].apply(e,r)}),n},remove:function(){for(var e=this.length;e--;)this[e].remove();return this}},e.each("fire on off show hide addClass removeClass append prepend before after reflow".split(" "),function(t){i[t]=function(){var n=e.toArray(arguments);return this.each(function(e){t in e&&e[t].apply(e,n)}),this}}),e.each("text name disabled active selected checked visible parent value data".split(" "),function(e){i[e]=function(t){return this.prop(e,t)}}),r=n.extend(i),t.Collection=r,r}),r(z,[f,g],function(e,t){return{id:function(){return t.DOM.uniqueId()},createFragment:function(e){return t.DOM.createFragment(e)},getWindowSize:function(){return t.DOM.getViewPort()},getSize:function(e){var t,n;if(e.getBoundingClientRect){var r=e.getBoundingClientRect();t=Math.max(r.width||r.right-r.left,e.offsetWidth),n=Math.max(r.height||r.bottom-r.bottom,e.offsetHeight)}else t=e.offsetWidth,n=e.offsetHeight;return{width:t,height:n}},getPos:function(e,n){return t.DOM.getPos(e,n)},getViewPort:function(e){return t.DOM.getViewPort(e)},get:function(e){return document.getElementById(e)},addClass:function(e,n){return t.DOM.addClass(e,n)},removeClass:function(e,n){return t.DOM.removeClass(e,n)},hasClass:function(e,n){return t.DOM.hasClass(e,n)},toggleClass:function(e,n,r){return t.DOM.toggleClass(e,n,r)},css:function(e,n,r){return t.DOM.setStyle(e,n,r)},on:function(e,n,r,i){return t.DOM.bind(e,n,r,i)},off:function(e,n,r){return t.DOM.unbind(e,n,r)},fire:function(e,n,r){return t.DOM.fire(e,n,r)},innerHtml:function(e,n){t.DOM.setHTML(e,n)}}}),r(W,[O,f,F,z],function(e,t,n,r){var i=t.makeMap("focusin focusout scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave wheel keydown keypress keyup contextmenu"," "),o={},a="onmousewheel"in document,s=!1,l=e.extend({Statics:{controlIdLookup:{},elementIdCache:o},isRtl:function(){return l.rtl},classPrefix:"mce-",init:function(e){var n=this,i,o;if(n.settings=e=t.extend({},n.Defaults,e),n._id=r.id(),n._text=n._name="",n._width=n._height=0,n._aria={role:e.role},i=e.classes)for(i=i.split(" "),i.map={},o=i.length;o--;)i.map[i[o]]=!0;n._classes=i||[],n.visible(!0),t.each("title text width height name classes visible disabled active value".split(" "),function(t){var r=e[t],i;r!==i?n[t](r):n["_"+t]===i&&(n["_"+t]=!1)}),n.on("click",function(){return n.disabled()?!1:void 0}),e.classes&&t.each(e.classes.split(" "),function(e){n.addClass(e)}),n.settings=e,n._borderBox=n.parseBox(e.border),n._paddingBox=n.parseBox(e.padding),n._marginBox=n.parseBox(e.margin),e.hidden&&n.hide()},Properties:"parent,title,text,width,height,disabled,active,name,value",Methods:"renderHtml",getContainerElm:function(){return document.body},getParentCtrl:function(e){for(var t;e&&!(t=l.controlIdLookup[e.id]);)e=e.parentNode;return t},parseBox:function(e){var t,n=10;if(e)return"number"==typeof e?(e=e||0,{top:e,left:e,bottom:e,right:e}):(e=e.split(" "),t=e.length,1===t?e[1]=e[2]=e[3]=e[0]:2===t?(e[2]=e[0],e[3]=e[1]):3===t&&(e[3]=e[1]),{top:parseInt(e[0],n)||0,right:parseInt(e[1],n)||0,bottom:parseInt(e[2],n)||0,left:parseInt(e[3],n)||0})},borderBox:function(){return this._borderBox},paddingBox:function(){return this._paddingBox},marginBox:function(){return this._marginBox},measureBox:function(e,t){function n(t){var n=document.defaultView;return n?(t=t.replace(/[A-Z]/g,function(e){return"-"+e}),n.getComputedStyle(e,null).getPropertyValue(t)):e.currentStyle[t]}function r(e){var t=parseFloat(n(e),10);return isNaN(t)?0:t}return{top:r(t+"TopWidth"),right:r(t+"RightWidth"),bottom:r(t+"BottomWidth"),left:r(t+"LeftWidth")}},initLayoutRect:function(){var e=this,t=e.settings,n,i,o=e.getEl(),a,s,l,c,d,u,f,p;n=e._borderBox=e._borderBox||e.measureBox(o,"border"),e._paddingBox=e._paddingBox||e.measureBox(o,"padding"),e._marginBox=e._marginBox||e.measureBox(o,"margin"),p=r.getSize(o),u=t.minWidth,f=t.minHeight,l=u||p.width,c=f||p.height,a=t.width,s=t.height,d=t.autoResize,d="undefined"!=typeof d?d:!a&&!s,a=a||l,s=s||c;var m=n.left+n.right,h=n.top+n.bottom,g=t.maxWidth||65535,v=t.maxHeight||65535;return e._layoutRect=i={x:t.x||0,y:t.y||0,w:a,h:s,deltaW:m,deltaH:h,contentW:a-m,contentH:s-h,innerW:a-m,innerH:s-h,startMinWidth:u||0,startMinHeight:f||0,minW:Math.min(l,g),minH:Math.min(c,v),maxW:g,maxH:v,autoResize:d,scrollW:0},e._lastLayoutRect={},i},layoutRect:function(e){var t=this,n=t._layoutRect,r,i,o,a,s,c;return n||(n=t.initLayoutRect()),e?(o=n.deltaW,a=n.deltaH,e.x!==s&&(n.x=e.x),e.y!==s&&(n.y=e.y),e.minW!==s&&(n.minW=e.minW),e.minH!==s&&(n.minH=e.minH),i=e.w,i!==s&&(i=in.maxW?n.maxW:i,n.w=i,n.innerW=i-o),i=e.h,i!==s&&(i=in.maxH?n.maxH:i,n.h=i,n.innerH=i-a),i=e.innerW,i!==s&&(i=in.maxW-o?n.maxW-o:i,n.innerW=i,n.w=i+o),i=e.innerH,i!==s&&(i=in.maxH-a?n.maxH-a:i,n.innerH=i,n.h=i+a),e.contentW!==s&&(n.contentW=e.contentW),e.contentH!==s&&(n.contentH=e.contentH),r=t._lastLayoutRect,(r.x!==n.x||r.y!==n.y||r.w!==n.w||r.h!==n.h)&&(c=l.repaintControls,c&&c.map&&!c.map[t._id]&&(c.push(t),c.map[t._id]=!0),r.x=n.x,r.y=n.y,r.w=n.w,r.h=n.h),t):n},repaint:function(){var e=this,t,n,r,i,o=0,a=0,s,l;l=document.createRange?function(e){return e}:Math.round,t=e.getEl().style,r=e._layoutRect,s=e._lastRepaintRect||{},i=e._borderBox,o=i.left+i.right,a=i.top+i.bottom,r.x!==s.x&&(t.left=l(r.x)+"px",s.x=r.x),r.y!==s.y&&(t.top=l(r.y)+"px",s.y=r.y),r.w!==s.w&&(t.width=l(r.w-o)+"px",s.w=r.w),r.h!==s.h&&(t.height=l(r.h-a)+"px",s.h=r.h),e._hasBody&&r.innerW!==s.innerW&&(n=e.getEl("body").style,n.width=l(r.innerW)+"px",s.innerW=r.innerW),e._hasBody&&r.innerH!==s.innerH&&(n=n||e.getEl("body").style,n.height=l(r.innerH)+"px",s.innerH=r.innerH),e._lastRepaintRect=s,e.fire("repaint",{},!1)},on:function(e,t){function n(e){var t,n;return function(i){return t||r.parents().each(function(r){var i=r.settings.callbacks;return i&&(t=i[e])?(n=r,!1):void 0}),t.call(n,i)}}var r=this,o,a,s,l;if(t)for("string"==typeof t&&(t=n(t)),s=e.toLowerCase().split(" "),l=s.length;l--;)e=s[l],o=r._bindings,o||(o=r._bindings={}),a=o[e],a||(a=o[e]=[]),a.push(t),i[e]&&(r._nativeEvents?r._nativeEvents[e]=!0:r._nativeEvents={name:!0},r._rendered&&r.bindPendingEvents());return r},off:function(e,t){var n=this,r,i=n._bindings,o,a,s,l;if(i)if(e)for(s=e.toLowerCase().split(" "),r=s.length;r--;){if(e=s[r],o=i[e],!e){for(a in i)i[a].length=0;return n}if(o)if(t)for(l=o.length;l--;)o[l]===t&&o.splice(l,1);else o.length=0}else n._bindings=[];return n},fire:function(e,t,n){function r(){return!1}function i(){return!0}var o=this,a,s,l,c;if(e=e.toLowerCase(),t=t||{},t.type||(t.type=e),t.control||(t.control=o),t.preventDefault||(t.preventDefault=function(){t.isDefaultPrevented=i},t.stopPropagation=function(){t.isPropagationStopped=i},t.stopImmediatePropagation=function(){t.isImmediatePropagationStopped=i},t.isDefaultPrevented=r,t.isPropagationStopped=r,t.isImmediatePropagationStopped=r),o._bindings&&(l=o._bindings[e]))for(a=0,s=l.length;s>a&&(t.isImmediatePropagationStopped()||l[a].call(o,t)!==!1);a++);if(n!==!1)for(c=o.parent();c&&!t.isPropagationStopped();)c.fire(e,t,!1),c=c.parent();return t},hasEventListeners:function(e){return e in this._bindings},parents:function(e){var t=this,r=new n;for(t=t.parent();t;t=t.parent())r.add(t);return e&&(r=r.filter(e)),r},next:function(){var e=this.parent().items();return e[e.indexOf(this)+1]},prev:function(){var e=this.parent().items();return e[e.indexOf(this)-1]},findCommonAncestor:function(e,t){for(var n;e;){for(n=t;n&&e!=n;)n=n.parent();if(e==n)break;e=e.parent()}return e},hasClass:function(e,t){var n=this._classes[t||"control"];return e=this.classPrefix+e,n&&!!n.map[e]},addClass:function(e,t){var n=this,r,i;return e=this.classPrefix+e,r=n._classes[t||"control"],r||(r=[],r.map={},n._classes[t||"control"]=r),r.map[e]||(r.map[e]=e,r.push(e),n._rendered&&(i=n.getEl(t),i&&(i.className=r.join(" ")))),n},removeClass:function(e,t){var n=this,r,i,o;if(e=this.classPrefix+e,r=n._classes[t||"control"],r&&r.map[e])for(delete r.map[e],i=r.length;i--;)r[i]===e&&r.splice(i,1);return n._rendered&&(o=n.getEl(t),o&&(o.className=r.join(" "))),n},toggleClass:function(e,t,n){var r=this;return t?r.addClass(e,n):r.removeClass(e,n),r},classes:function(e){var t=this._classes[e||"control"];return t?t.join(" "):""},innerHtml:function(e){return r.innerHtml(this.getEl(),e),this},getEl:function(e,t){var n,i=e?this._id+"-"+e:this._id;return n=o[i]=(t===!0?null:o[i])||r.get(i)},visible:function(e){var t=this,n;return"undefined"!=typeof e?(t._visible!==e&&(t._rendered&&(t.getEl().style.display=e?"":"none"),t._visible=e,n=t.parent(),n&&(n._lastRect=null),t.fire(e?"show":"hide")),t):t._visible},show:function(){return this.visible(!0)},hide:function(){return this.visible(!1)},focus:function(){try{this.getEl().focus()}catch(e){}return this},blur:function(){return this.getEl().blur(),this},aria:function(e,t){var n=this,r=n.getEl();return"undefined"==typeof t?n._aria[e]:(n._aria[e]=t,n._rendered&&("label"==e&&r.setAttribute("aria-labeledby",n._id),r.setAttribute("role"==e?e:"aria-"+e,t)),n)},encode:function(e,t){return t!==!1&&l.translate&&(e=l.translate(e)),(e||"").replace(/[&<>"]/g,function(e){return"&#"+e.charCodeAt(0)+";"})},before:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t),!0),t},after:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t)),t},remove:function(){var e=this,t=e.getEl(),n=e.parent(),i,a;if(e.items){var s=e.items().toArray();for(a=s.length;a--;)s[a].remove()}if(n&&n.items&&(i=[],n.items().each(function(t){t!==e&&i.push(t)}),n.items().set(i),n._lastRect=null),e._eventsRoot&&e._eventsRoot==e&&r.off(t),delete l.controlIdLookup[e._id],delete o[e._id],t&&t.parentNode){var c=t.getElementsByTagName("*");for(a=c.length;a--;)delete o[c[a].id];t.parentNode.removeChild(t)}return e},renderBefore:function(e){var t=this;return e.parentNode.insertBefore(r.createFragment(t.renderHtml()),e),t.postRender(),t},renderTo:function(e){var t=this;return e=e||t.getContainerElm(),e.appendChild(r.createFragment(t.renderHtml())),t.postRender(),t},postRender:function(){var e=this,t=e.settings,n,i,o,a,s;for(a in t)0===a.indexOf("on")&&e.on(a.substr(2),t[a]);if(e._eventsRoot){for(o=e.parent();!s&&o;o=o.parent())s=o._eventsRoot;if(s)for(a in s._nativeEvents)e._nativeEvents[a]=!0}e.bindPendingEvents(),t.style&&(n=e.getEl(),n&&(n.setAttribute("style",t.style),n.style.cssText=t.style)),e._visible||r.css(e.getEl(),"display","none"),e.settings.border&&(i=e.borderBox(),r.css(e.getEl(),{"border-top-width":i.top,"border-right-width":i.right,"border-bottom-width":i.bottom,"border-left-width":i.left})),l.controlIdLookup[e._id]=e;for(var c in e._aria)e.aria(c,e._aria[c]);e.fire("postrender",{},!1)},scrollIntoView:function(e){function t(e,t){var n,r,i=e;for(n=r=0;i&&i!=t&&i.nodeType;)n+=i.offsetLeft||0,r+=i.offsetTop||0,i=i.offsetParent;return{x:n,y:r}}var n=this.getEl(),r=n.parentNode,i,o,a,s,l,c,d=t(n,r);return i=d.x,o=d.y,a=n.offsetWidth,s=n.offsetHeight,l=r.clientWidth,c=r.clientHeight,"end"==e?(i-=l-a,o-=c-s):"center"==e&&(i-=l/2-a/2,o-=c/2-s/2),r.scrollLeft=i,r.scrollTop=o,this},bindPendingEvents:function(){function e(e){var t=o.getParentCtrl(e.target);t&&t.fire(e.type,e)}function t(){var e=u._lastHoverCtrl;e&&(e.fire("mouseleave",{target:e.getEl()}),e.parents().each(function(e){e.fire("mouseleave",{target:e.getEl()})}),u._lastHoverCtrl=null)}function n(e){var t=o.getParentCtrl(e.target),n=u._lastHoverCtrl,r=0,i,a,s;if(t!==n){if(u._lastHoverCtrl=t,a=t.parents().toArray().reverse(),a.push(t),n){for(s=n.parents().toArray().reverse(),s.push(n),r=0;r=r;i--)n=s[i],n.fire("mouseleave",{target:n.getEl()})}for(i=r;il;l++)u=d[l]._eventsRoot;for(u||(u=d[d.length-1]||o),o._eventsRoot=u,c=l,l=0;c>l;l++)d[l]._eventsRoot=u;for(p in f){if(!f)return!1;"wheel"!==p||s?("mouseenter"===p||"mouseleave"===p?u._hasMouseEnter||(r.on(u.getEl(),"mouseleave",t),r.on(u.getEl(),"mouseover",n),u._hasMouseEnter=1):u[p]||(r.on(u.getEl(),p,e),u[p]=!0),f[p]=!1):a?r.on(o.getEl(),"mousewheel",i):r.on(o.getEl(),"DOMMouseScroll",i)}}},reflow:function(){return this.repaint(),this}});return l}),r(V,[],function(){var e={},t;return{add:function(t,n){e[t.toLowerCase()]=n},has:function(t){return!!e[t.toLowerCase()]},create:function(n,r){var i,o,a;if(!t){a=tinymce.ui;for(o in a)e[o.toLowerCase()]=a[o];t=!0}if("string"==typeof n?(r=r||{},r.type=n):(r=n,n=r.type),n=n.toLowerCase(),i=e[n],!i)throw new Error("Could not find control by type: "+n);return i=new i(r),i.type=n,i}}}),r(U,[W,F,I,V,f,z],function(e,t,n,r,i,o){var a={};return e.extend({layout:"",innerClass:"container-inner",init:function(e){var n=this;n._super(e),e=n.settings,n._fixed=e.fixed,n._items=new t,n.isRtl()&&n.addClass("rtl"),n.addClass("container"),n.addClass("container-body","body"),e.containerCls&&n.addClass(e.containerCls),n._layout=r.create((e.layout||n.layout)+"layout"),n.settings.items&&n.add(n.settings.items),n._hasBody=!0},items:function(){return this._items},find:function(e){return e=a[e]=a[e]||new n(e),e.find(this)},add:function(e){var t=this;return t.items().add(t.create(e)).parent(t),t},focus:function(){var e=this;return e.keyNav?e.keyNav.focusFirst():e._super(),e},replace:function(e,t){for(var n,r=this.items(),i=r.length;i--;)if(r[i]===e){r[i]=t;break}i>=0&&(n=t.getEl(),n&&n.parentNode.removeChild(n),n=e.getEl(),n&&n.parentNode.removeChild(n)),t.parent(this)},create:function(t){var n=this,o,a=[];return i.isArray(t)||(t=[t]),i.each(t,function(t){t&&(t instanceof e||("string"==typeof t&&(t={type:t}),o=i.extend({},n.settings.defaults,t),t.type=o.type=o.type||t.type||n.settings.defaultType||(o.defaults?o.defaults.type:null),t=r.create(o)),a.push(t))}),a},renderNew:function(){var e=this;return e.items().each(function(t,n){var r,i;t.parent(e),t._rendered||(r=e.getEl("body"),i=o.createFragment(t.renderHtml()),r.hasChildNodes()&&n<=r.childNodes.length-1?r.insertBefore(i,r.childNodes[n]):r.appendChild(i),t.postRender())}),e._layout.applyClasses(e),e._lastRect=null,e},append:function(e){return this.add(e).renderNew()},prepend:function(e){var t=this;return t.items().set(t.create(e).concat(t.items().toArray())),t.renderNew()},insert:function(e,t,n){var r=this,i,o,a;return e=r.create(e),i=r.items(),!n&&t=0&&t
'+(e.settings.html||"")+t.renderHtml(e)+"
"},postRender:function(){var e=this,t;return e.items().exec("postRender"),e._super(),e._layout.postRender(e),e._rendered=!0,e.settings.style&&o.css(e.getEl(),e.settings.style),e.settings.border&&(t=e.borderBox(),o.css(e.getEl(),{"border-top-width":t.top,"border-right-width":t.right,"border-bottom-width":t.bottom,"border-left-width":t.left})),e},initLayoutRect:function(){var e=this,t=e._super();return e._layout.recalc(e),t},recalc:function(){var e=this,t=e._layoutRect,n=e._lastRect;return n&&n.w==t.w&&n.h==t.h?void 0:(e._layout.recalc(e),t=e.layoutRect(),e._lastRect={x:t.x,y:t.y,w:t.w,h:t.h},!0)},reflow:function(){var t,n;if(this.visible()){for(e.repaintControls=[],e.repaintControls.map={},n=this.recalc(),t=e.repaintControls.length;t--;)e.repaintControls[t].repaint();"flow"!==this.settings.layout&&"stack"!==this.settings.layout&&this.repaint(),e.repaintControls=[]}return this}})}),r(q,[z],function(e){function t(){var e=document,t,n,r,i,o,a,s,l,c=Math.max;return t=e.documentElement,n=e.body,r=c(t.scrollWidth,n.scrollWidth),i=c(t.clientWidth,n.clientWidth),o=c(t.offsetWidth,n.offsetWidth),a=c(t.scrollHeight,n.scrollHeight),s=c(t.clientHeight,n.clientHeight),l=c(t.offsetHeight,n.offsetHeight),{width:o>r?i:r,height:l>a?s:a}}return function(n,r){function i(){return a.getElementById(r.handle||n)}var o,a=document,s,l,c,d,u,f;r=r||{},l=function(n){var l=t(),p,m;n.preventDefault(),s=n.button,p=i(),u=n.screenX,f=n.screenY,m=window.getComputedStyle?window.getComputedStyle(p,null).getPropertyValue("cursor"):p.runtimeStyle.cursor,o=a.createElement("div"),e.css(o,{position:"absolute",top:0,left:0,width:l.width,height:l.height,zIndex:2147483647,opacity:1e-4,background:"red",cursor:m}),a.body.appendChild(o),e.on(a,"mousemove",d),e.on(a,"mouseup",c),r.start(n)},d=function(e){return e.button!==s?c(e):(e.deltaX=e.screenX-u,e.deltaY=e.screenY-f,e.preventDefault(),r.drag(e),void 0)},c=function(t){e.off(a,"mousemove",d),e.off(a,"mouseup",c),o.parentNode.removeChild(o),r.stop&&r.stop(t)},this.destroy=function(){e.off(i())},e.on(i(),"mousedown",l)}}),r(j,[z,q],function(e,t){return{init:function(){var e=this;e.on("repaint",e.renderScroll)},renderScroll:function(){function n(){function t(t,a,s,l,c,d){var u,f,p,m,h,g,v,y,b;if(f=i.getEl("scroll"+t)){if(y=a.toLowerCase(),b=s.toLowerCase(),i.getEl("absend")&&e.css(i.getEl("absend"),y,i.layoutRect()[l]-1),!c)return e.css(f,"display","none"),void 0;e.css(f,"display","block"),u=i.getEl("body"),p=i.getEl("scroll"+t+"t"),m=u["client"+s]-2*o,m-=n&&r?f["client"+d]:0,h=u["scroll"+s],g=m/h,v={},v[y]=u["offset"+a]+o,v[b]=m,e.css(f,v),v={},v[y]=u["scroll"+a]*g,v[b]=m*g,e.css(p,v)}}var n,r,a;a=i.getEl("body"),n=a.scrollWidth>a.clientWidth,r=a.scrollHeight>a.clientHeight,t("h","Left","Width","contentW",n,"Height"),t("v","Top","Height","contentH",r,"Width")}function r(){function n(n,r,a,s,l){var c,d=i._id+"-scroll"+n,u=i.classPrefix;i.getEl().appendChild(e.createFragment('
')),i.draghelper=new t(d+"t",{start:function(){c=i.getEl("body")["scroll"+r],e.addClass(e.get(d),u+"active")},drag:function(e){var t,d,u,f,p=i.layoutRect();d=p.contentW>p.innerW,u=p.contentH>p.innerH,f=i.getEl("body")["client"+a]-2*o,f-=d&&u?i.getEl("scroll"+n)["client"+l]:0,t=f/i.getEl("body")["scroll"+a],i.getEl("body")["scroll"+r]=c+e["delta"+s]/t},stop:function(){e.removeClass(e.get(d),u+"active")}})}i.addClass("scroll"),n("v","Top","Height","Y","Width"),n("h","Left","Width","X","Height")}var i=this,o=2;i.settings.autoScroll&&(i._hasScroll||(i._hasScroll=!0,r(),i.on("wheel",function(e){var t=i.getEl("body");t.scrollLeft+=10*(e.deltaX||0),t.scrollTop+=10*e.deltaY,n()}),e.on(i.getEl("body"),"scroll",n)),n())}}}),r($,[U,j],function(e,t){return e.extend({Defaults:{layout:"fit",containerCls:"panel"},Mixins:[t],renderHtml:function(){var e=this,t=e._layout,n=e.settings.html;return e.preRender(),t.preRender(e),"undefined"==typeof n?n='
'+t.renderHtml(e)+"
":("function"==typeof n&&(n=n.call(e)),e._hasBody=!1),'
'+(e._preBodyHtml||"")+n+"
"}})}),r(K,[z],function(e){function t(t,n,r){var i,o,a,s,l,c,d,u,f,p;return f=e.getViewPort(),o=e.getPos(n),a=o.x,s=o.y,t._fixed&&(a-=f.x,s-=f.y),i=t.getEl(),p=e.getSize(i),l=p.width,c=p.height,p=e.getSize(n),d=p.width,u=p.height,r=(r||"").split(""),"b"===r[0]&&(s+=u),"r"===r[1]&&(a+=d),"c"===r[0]&&(s+=Math.round(u/2)),"c"===r[1]&&(a+=Math.round(d/2)),"b"===r[3]&&(s-=c),"r"===r[4]&&(a-=l),"c"===r[3]&&(s-=Math.round(c/2)),"c"===r[4]&&(a-=Math.round(l/2)),{x:a,y:s,w:l,h:c}}return{testMoveRel:function(n,r){for(var i=e.getViewPort(),o=0;o0&&a.x+a.w0&&a.y+a.hi.x&&a.x+a.wi.y&&a.y+a.he?0:e+n>t?(e=t-n,0>e?0:e):e}var i=this;if(i.settings.constrainToViewport){var o=e.getViewPort(window),a=i.layoutRect();t=r(t,o.w+o.x,a.w),n=r(n,o.h+o.y,a.h)}return i._rendered?i.layoutRect({x:t,y:n}).repaint():(i.settings.x=t,i.settings.y=n),i.fire("move",{x:t,y:n}),i +}}}),r(Y,[z],function(e){return{resizeToContent:function(){this._layoutRect.autoResize=!0,this._lastRect=null,this.reflow()},resizeTo:function(t,n){if(1>=t||1>=n){var r=e.getWindowSize();t=1>=t?t*r.w:t,n=1>=n?n*r.h:n}return this._layoutRect.autoResize=!1,this.layoutRect({minW:t,minH:n,w:t,h:n}).reflow()},resizeBy:function(e,t){var n=this,r=n.layoutRect();return n.resizeTo(r.w+e,r.h+t)}}}),r(G,[$,K,Y,z],function(e,t,n,r){function i(e){var t;for(t=s.length;t--;)s[t]===e&&s.splice(t,1);for(t=l.length;t--;)l[t]===e&&l.splice(t,1)}var o,a,s=[],l=[],c,d=e.extend({Mixins:[t,n],init:function(e){function t(){var e,t=d.zIndex||65535,n;if(l.length)for(e=0;en&&(e.fixed(!1).layoutRect({y:e._autoFixY}).repaint(),t(!1,e._autoFixY-n)):(e._autoFixY=e.layoutRect().y,e._autoFixY
'),n=n.firstChild,u.getContainerElm().appendChild(n),setTimeout(function(){r.addClass(n,i+"in"),r.addClass(u.getEl(),i+"in")},0),c=!0),l.push(u),t()}}),u.on("close hide",function(e){if(e.control==u){for(var n=l.length;n--;)l[n]===u&&l.splice(n,1);t()}}),u.on("show",function(){u.parents().each(function(e){return e._fixed?(u.fixed(!0),!1):void 0})}),e.popover&&(u._preBodyHtml='
',u.addClass("popover").addClass("bottom").addClass(u.isRtl()?"end":"start"))},fixed:function(e){var t=this;if(t._fixed!=e){if(t._rendered){var n=r.getViewPort();e?t.layoutRect().y-=n.y:t.layoutRect().y+=n.y}t.toggleClass("fixed",e),t._fixed=e}return t},show:function(){var e=this,t,n=e._super();for(t=s.length;t--&&s[t]!==e;);return-1===t&&s.push(e),n},hide:function(){return i(this),this._super()},hideAll:function(){d.hideAll()},close:function(){var e=this;return e.fire("close"),e.remove()},remove:function(){i(this),this._super()}});return d.hideAll=function(){for(var e=s.length;e--;){var t=s[e];t.settings.autohide&&(t.fire("cancel",{},!1),t.hide(),s.splice(e,1))}},d}),r(X,[z],function(e){return function(t){function n(){if(!m)if(m=[],u.find)u.find("*").each(function(e){e.canFocus&&m.push(e.getEl())});else for(var e=u.getEl().getElementsByTagName("*"),t=0;ti?i=l.length-1:i>=l.length&&(i=0),o=l[i],o.focus(),h=o.id,t.actOnFocus&&s()}function d(){var e,r;for(r=i(t.root.getEl()),n(),e=m.length;e--;)if("toolbar"==r&&m[e].id===h)return m[e].focus(),void 0;m[0].focus()}var u=t.root,f=t.enableUpDown!==!1,p=t.enableLeftRight!==!1,m=t.items,h;return u.on("keydown",function(e){var n=37,r=39,d=38,u=40,m=27,h=14,g=13,v=32,y=9,b;switch(e.keyCode){case n:p&&(t.leftAction?t.leftAction():c(-1),b=!0);break;case r:p&&("menuitem"==i()&&"menu"==o()?a("haspopup")&&s():c(1),b=!0);break;case d:f&&(c(-1),b=!0);break;case u:f&&("menuitem"==i()&&"menubar"==o()?s():"button"==i()&&a("haspopup")?s():c(1),b=!0);break;case y:b=!0,e.shiftKey?c(-1):c(1);break;case m:b=!0,l();break;case h:case g:case v:b=s()}b&&(e.stopPropagation(),e.preventDefault())}),u.on("focusin",function(e){n(),h=e.target.id}),{moveFocus:c,focusFirst:d,cancel:l}}}),r(J,[G,$,z,X,q],function(e,t,n,r,i){var o=e.extend({modal:!0,Defaults:{border:1,layout:"flex",containerCls:"panel",role:"dialog",callbacks:{submit:function(){this.fire("submit",{data:this.toJSON()})},close:function(){this.close()}}},init:function(e){var n=this;n._super(e),n.isRtl()&&n.addClass("rtl"),n.addClass("window"),n._fixed=!0,e.buttons&&(n.statusbar=new t({layout:"flex",border:"1 0 0 0",spacing:3,padding:10,align:"center",pack:n.isRtl()?"start":"end",defaults:{type:"button"},items:e.buttons}),n.statusbar.addClass("foot"),n.statusbar.parent(n)),n.on("click",function(e){-1!=e.target.className.indexOf(n.classPrefix+"close")&&n.close()}),n.aria("label",e.title),n._fullscreen=!1},recalc:function(){var e=this,t=e.statusbar,r,i,o,a;e._fullscreen&&(e.layoutRect(n.getWindowSize()),e.layoutRect().contentH=e.layoutRect().innerH),e._super(),r=e.layoutRect(),e.settings.title&&!e._fullscreen&&(i=r.headerW,i>r.w&&(o=r.x-Math.max(0,i/2),e.layoutRect({w:i,x:o}),a=!0)),t&&(t.layoutRect({w:e.layoutRect().innerW}).recalc(),i=t.layoutRect().minW+r.deltaW,i>r.w&&(o=r.x-Math.max(0,i-r.w),e.layoutRect({w:i,x:o}),a=!0)),a&&e.recalc()},initLayoutRect:function(){var e=this,t=e._super(),r=0,i;if(e.settings.title&&!e._fullscreen){i=e.getEl("head");var o=n.getSize(i);t.headerW=o.width,t.headerH=o.height,r+=t.headerH}e.statusbar&&(r+=e.statusbar.layoutRect().h),t.deltaH+=r,t.minH+=r,t.h+=r;var a=n.getWindowSize();return t.x=Math.max(0,a.w/2-t.w/2),t.y=Math.max(0,a.h/2-t.h/2),t},renderHtml:function(){var e=this,t=e._layout,n=e._id,r=e.classPrefix,i=e.settings,o="",a="",s=i.html;return e.preRender(),t.preRender(e),i.title&&(o='
'+e.encode(i.title)+'
'),i.url&&(s=''),"undefined"==typeof s&&(s=t.renderHtml(e)),e.statusbar&&(a=e.statusbar.renderHtml()),'
'+o+'
'+s+"
"+a+"
"},fullscreen:function(e){var t=this,r=document.documentElement,i,o=t.classPrefix,a;if(e!=t._fullscreen)if(n.on(window,"resize",function(){var e;if(t._fullscreen)if(i)t._timer||(t._timer=setTimeout(function(){var e=n.getWindowSize();t.moveTo(0,0).resizeTo(e.w,e.h),t._timer=0},50));else{e=(new Date).getTime();var r=n.getWindowSize();t.moveTo(0,0).resizeTo(r.w,r.h),(new Date).getTime()-e>50&&(i=!0)}}),a=t.layoutRect(),t._fullscreen=e,e){t._initial={x:a.x,y:a.y,w:a.w,h:a.h},t._borderBox=t.parseBox("0"),t.getEl("head").style.display="none",a.deltaH-=a.headerH+2,n.addClass(r,o+"fullscreen"),n.addClass(document.body,o+"fullscreen"),t.addClass("fullscreen");var s=n.getWindowSize();t.moveTo(0,0).resizeTo(s.w,s.h)}else t._borderBox=t.parseBox(t.settings.border),t.getEl("head").style.display="",a.deltaH+=a.headerH,n.removeClass(r,o+"fullscreen"),n.removeClass(document.body,o+"fullscreen"),t.removeClass("fullscreen"),t.moveTo(t._initial.x,t._initial.y).resizeTo(t._initial.w,t._initial.h);return t.reflow()},postRender:function(){var e=this,t=[],n,o,a;setTimeout(function(){e.addClass("in")},0),e.keyboardNavigation=new r({root:e,enableLeftRight:!1,enableUpDown:!1,items:t,onCancel:function(){e.close()}}),e.find("*").each(function(e){e.canFocus&&(o=o||e.settings.autofocus,n=n||e,"filepicker"==e.type?(t.push(e.getEl("inp")),e.getEl("open")&&t.push(e.getEl("open"))):t.push(e.getEl()))}),e.statusbar&&e.statusbar.find("*").each(function(e){e.canFocus&&(o=o||e.settings.autofocus,n=n||e,t.push(e.getEl()))}),e._super(),e.statusbar&&e.statusbar.postRender(),!o&&n&&n.focus(),this.dragHelper=new i(e._id+"-dragh",{start:function(){a={x:e.layoutRect().x,y:e.layoutRect().y}},drag:function(t){e.moveTo(a.x+t.deltaX,a.y+t.deltaY)}}),e.on("submit",function(t){t.isDefaultPrevented()||e.close()})},submit:function(){return this.fire("submit",{data:this.toJSON()})},remove:function(){var e=this,t=e.classPrefix;e.dragHelper.destroy(),e._super(),e.statusbar&&this.statusbar.remove(),e._fullscreen&&(n.removeClass(document.documentElement,t+"fullscreen"),n.removeClass(document.body,t+"fullscreen"))}});return o}),r(Q,[J],function(e){var t=e.extend({init:function(e){e={border:1,padding:20,layout:"flex",pack:"center",align:"center",containerCls:"panel",autoScroll:!0,buttons:{type:"button",text:"Ok",action:"ok"},items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200}},this._super(e)},Statics:{OK:1,OK_CANCEL:2,YES_NO:3,YES_NO_CANCEL:4,msgBox:function(n){var r,i=n.callback||function(){};switch(n.buttons){case t.OK_CANCEL:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close(),i(!0)}},{type:"button",text:"Cancel",onClick:function(e){e.control.parents()[1].close(),i(!1)}}];break;case t.YES_NO:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close(),i(!0)}}];break;case t.YES_NO_CANCEL:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close()}}];break;default:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close(),i(!0)}}]}return new e({padding:20,x:n.x,y:n.y,minWidth:300,minHeight:100,layout:"flex",pack:"center",align:"center",buttons:r,title:n.title,items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200,text:n.text},onClose:n.onClose}).renderTo(document.body).reflow()},alert:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,t.msgBox(e)},confirm:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,e.buttons=t.OK_CANCEL,t.msgBox(e)}}});return t}),r(Z,[J,Q],function(e,t){return function(n){function r(){return o.length?o[o.length-1]:void 0}var i=this,o=[];i.windows=o,i.open=function(t,r){var i;return n.editorManager.activeEditor=n,t.title=t.title||" ",t.url=t.url||t.file,t.url&&(t.width=parseInt(t.width||320,10),t.height=parseInt(t.height||240,10)),t.body&&(t.items={defaults:t.defaults,type:t.bodyType||"form",items:t.body}),t.url||t.buttons||(t.buttons=[{text:"Ok",subtype:"primary",onclick:function(){i.find("form")[0].submit(),i.close()}},{text:"Cancel",onclick:function(){i.close()}}]),i=new e(t),o.push(i),i.on("close",function(){for(var e=o.length;e--;)o[e]===i&&o.splice(e,1);n.focus()}),t.data&&i.on("postRender",function(){this.find("*").each(function(e){var n=e.name();n in t.data&&e.value(t.data[n])})}),i.features=t||{},i.params=r||{},n.nodeChanged(),i.renderTo(document.body).reflow()},i.alert=function(e,n,r){t.alert(e,function(){n&&n.call(r||this)})},i.confirm=function(e,n,r){t.confirm(e,function(e){n.call(r||this,e)})},i.close=function(){r()&&r().close()},i.getParams=function(){return r()?r().params:null},i.setParams=function(e){r()&&(r().params=e)}}}),r(et,[S,A,b,m,h,f],function(e,t,n,r,i,o){return function(a){function s(e,t){try{a.getDoc().execCommand(e,!1,t)}catch(n){}}function l(){var e=a.getDoc().documentMode;return e?e:6}function c(e){return e.isDefaultPrevented()}function d(){function t(e){var t=new MutationObserver(function(){});o.each(a.getBody().getElementsByTagName("*"),function(e){"SPAN"==e.tagName&&e.setAttribute("mce-data-marked",1),!e.hasAttribute("data-mce-style")&&e.hasAttribute("style")&&a.dom.setAttrib(e,"style",e.getAttribute("style"))}),t.observe(a.getDoc(),{childList:!0,attributes:!0,subtree:!0,attributeFilter:["style"]}),a.getDoc().execCommand(e?"ForwardDelete":"Delete",!1,null);var n=a.selection.getRng(),r=n.startContainer.parentNode;o.each(t.takeRecords(),function(e){if("style"==e.attributeName){var t=e.target.getAttribute("data-mce-style");t?e.target.setAttribute("style",t):e.target.removeAttribute("style")}o.each(e.addedNodes,function(e){if("SPAN"==e.nodeName&&!e.getAttribute("mce-data-marked")){var t,i;e==r&&(t=n.startOffset,i=e.firstChild),z.remove(e,!0),i&&(n.setStart(i,t),n.setEnd(i,t),a.selection.setRng(n))}})}),t.disconnect(),o.each(a.dom.select("span[mce-data-marked]"),function(e){e.removeAttribute("mce-data-marked")})}var n=a.getDoc();window.MutationObserver&&(a.on("keydown",function(n){var r=n.keyCode==F,i=e.metaKeyPressed(n);if(!c(n)&&(r||n.keyCode==I)){var o=a.selection.getRng(),s=o.startContainer,l=o.startOffset;if(!i&&o.collapsed&&3==s.nodeType&&(r?l0))return;n.preventDefault(),i&&a.selection.getSel().modify("extend",r?"forward":"backward","word"),t(r)}}),a.on("keypress",function(e){c(e)||W.isCollapsed()||!e.charCode||(e.preventDefault(),t(!0),a.selection.setContent(String.fromCharCode(e.charCode)))}),a.addCommand("Delete",function(){t()}),a.addCommand("ForwardDelete",function(){t(!0)}),a.on("dragstart",function(e){e.dataTransfer.setData("mce-internal",a.selection.getContent())}),a.on("drop",function(e){if(!c(e)){var r=e.dataTransfer.getData("mce-internal");r&&n.caretRangeFromPoint&&(e.preventDefault(),t(),a.selection.setRng(n.caretRangeFromPoint(e.x,e.y)),a.insertContent(r))}}),a.on("cut",function(e){!c(e)&&e.clipboardData&&(e.preventDefault(),e.clipboardData.clearData(),e.clipboardData.setData("text/html",a.selection.getContent()),e.clipboardData.setData("text/plain",a.selection.getContent({format:"text"})),t(!0))}))}function u(){function e(e){var t=z.create("body"),n=e.cloneContents();return t.appendChild(n),W.serializer.serialize(t,{format:"html"})}function n(n){if(!n.setStart){if(n.item)return!1;var r=n.duplicate();return r.moveToElementText(a.getBody()),t.compareRanges(n,r)}var i=e(n),o=z.createRng();o.selectNode(a.getBody());var s=e(o);return i===s}a.on("keydown",function(e){var t=e.keyCode,r,i;if(!c(e)&&(t==F||t==I)){if(r=a.selection.isCollapsed(),i=a.getBody(),r&&!z.isEmpty(i))return;if(!r&&!n(a.selection.getRng()))return;e.preventDefault(),a.setContent(""),i.firstChild&&z.isBlock(i.firstChild)?a.selection.setCursorLocation(i.firstChild,0):a.selection.setCursorLocation(i,0),a.nodeChanged()}})}function f(){a.on("keydown",function(t){!c(t)&&65==t.keyCode&&e.metaKeyPressed(t)&&(t.preventDefault(),a.execCommand("SelectAll"))})}function p(){a.settings.content_editable||(z.bind(a.getDoc(),"focusin",function(){W.setRng(W.getRng())}),z.bind(a.getDoc(),"mousedown",function(e){e.target==a.getDoc().documentElement&&(a.getWin().focus(),W.setRng(W.getRng()))}))}function m(){a.on("keydown",function(e){if(!c(e)&&e.keyCode===I&&W.isCollapsed()&&0===W.getRng(!0).startOffset){var t=W.getNode(),n=t.previousSibling;if("HR"==t.nodeName)return z.remove(t),e.preventDefault(),void 0;n&&n.nodeName&&"hr"===n.nodeName.toLowerCase()&&(z.remove(n),e.preventDefault())}})}function h(){window.Range.prototype.getClientRects||a.on("mousedown",function(e){if(!c(e)&&"HTML"===e.target.nodeName){var t=a.getBody();t.blur(),setTimeout(function(){t.focus()},0)}})}function g(){a.on("click",function(e){e=e.target,/^(IMG|HR)$/.test(e.nodeName)&&W.getSel().setBaseAndExtent(e,0,e,1),"A"==e.nodeName&&z.hasClass(e,"mce-item-anchor")&&W.select(e),a.nodeChanged()})}function v(){function e(){var e=z.getAttribs(W.getStart().cloneNode(!1));return function(){var t=W.getStart();t!==a.getBody()&&(z.setAttrib(t,"style",null),O(e,function(e){t.setAttributeNode(e.cloneNode(!0))}))}}function t(){return!W.isCollapsed()&&z.getParent(W.getStart(),z.isBlock)!=z.getParent(W.getEnd(),z.isBlock)}a.on("keypress",function(n){var r;return c(n)||8!=n.keyCode&&46!=n.keyCode||!t()?void 0:(r=e(),a.getDoc().execCommand("delete",!1,null),r(),n.preventDefault(),!1)}),z.bind(a.getDoc(),"cut",function(n){var r;!c(n)&&t()&&(r=e(),setTimeout(function(){r()},0))})}function y(){var e,n;a.on("selectionchange",function(){n&&(clearTimeout(n),n=0),n=window.setTimeout(function(){var n=W.getRng();e&&t.compareRanges(n,e)||(a.nodeChanged(),e=n)},50)})}function b(){document.body.setAttribute("role","application")}function C(){a.on("keydown",function(e){if(!c(e)&&e.keyCode===I&&W.isCollapsed()&&0===W.getRng(!0).startOffset){var t=W.getNode().previousSibling;if(t&&t.nodeName&&"table"===t.nodeName.toLowerCase())return e.preventDefault(),!1}})}function x(){l()>7||(s("RespectVisibilityInDesign",!0),a.contentStyles.push(".mceHideBrInPre pre br {display: none}"),z.addClass(a.getBody(),"mceHideBrInPre"),U.addNodeFilter("pre",function(e){for(var t=e.length,r,i,o,a;t--;)for(r=e[t].getAll("br"),i=r.length;i--;)o=r[i],a=o.prev,a&&3===a.type&&"\n"!=a.value.charAt(a.value-1)?a.value+="\n":o.parent.insert(new n("#text",3),o,!0).value="\n"}),q.addNodeFilter("pre",function(e){for(var t=e.length,n,r,i,o;t--;)for(n=e[t].getAll("br"),r=n.length;r--;)i=n[r],o=i.prev,o&&3==o.type&&(o.value=o.value.replace(/\r?\n$/,""))}))}function w(){z.bind(a.getBody(),"mouseup",function(){var e,t=W.getNode();"IMG"==t.nodeName&&((e=z.getStyle(t,"width"))&&(z.setAttrib(t,"width",e.replace(/[^0-9%]+/g,"")),z.setStyle(t,"width","")),(e=z.getStyle(t,"height"))&&(z.setAttrib(t,"height",e.replace(/[^0-9%]+/g,"")),z.setStyle(t,"height","")))})}function _(){a.on("keydown",function(t){var n,r,i,o,s;if(!c(t)&&t.keyCode==e.BACKSPACE&&(n=W.getRng(),r=n.startContainer,i=n.startOffset,o=z.getRoot(),s=r,n.collapsed&&0===i)){for(;s&&s.parentNode&&s.parentNode.firstChild==s&&s.parentNode!=o;)s=s.parentNode;"BLOCKQUOTE"===s.tagName&&(a.formatter.toggle("blockquote",null,s),n=z.createRng(),n.setStart(r,0),n.setEnd(r,0),W.setRng(n))}})}function N(){function e(){a._refreshContentEditable(),s("StyleWithCSS",!1),s("enableInlineTableEditing",!1),V.object_resizing||s("enableObjectResizing",!1)}V.readonly||a.on("BeforeExecCommand MouseDown",e)}function E(){function e(){O(z.select("a"),function(e){var t=e.parentNode,n=z.getRoot();if(t.lastChild===e){for(;t&&!z.isBlock(t);){if(t.parentNode.lastChild!==t||t===n)return;t=t.parentNode}z.add(t,"br",{"data-mce-bogus":1})}})}a.on("SetContent ExecCommand",function(t){("setcontent"==t.type||"mceInsertLink"===t.command)&&e()})}function k(){V.forced_root_block&&a.on("init",function(){s("DefaultParagraphSeparator",V.forced_root_block)})}function S(){a.on("Undo Redo SetContent",function(e){e.initial||a.execCommand("mceRepaint")})}function T(){a.on("keydown",function(e){var t;c(e)||e.keyCode!=I||(t=a.getDoc().selection.createRange(),t&&t.item&&(e.preventDefault(),a.undoManager.beforeChange(),z.remove(t.item(0)),a.undoManager.add()))})}function R(){var e;l()>=10&&(e="",O("p div h1 h2 h3 h4 h5 h6".split(" "),function(t,n){e+=(n>0?",":"")+t+":empty"}),a.contentStyles.push(e+"{padding-right: 1px !important}"))}function A(){l()<9&&(U.addNodeFilter("noscript",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.firstChild,r&&n.attr("data-mce-innertext",r.value)}),q.addNodeFilter("noscript",function(e){for(var t=e.length,i,o,a;t--;)i=e[t],o=e[t].firstChild,o?o.value=r.decode(o.value):(a=i.attributes.map["data-mce-innertext"],a&&(i.attr("data-mce-innertext",null),o=new n("#text",3),o.value=a,o.raw=!0,i.append(o)))}))}function B(){function e(e,t){var n=i.createTextRange();try{n.moveToPoint(e,t)}catch(r){n=null}return n}function t(t){var r;t.button?(r=e(t.x,t.y),r&&(r.compareEndPoints("StartToStart",a)>0?r.setEndPoint("StartToStart",a):r.setEndPoint("EndToEnd",a),r.select())):n()}function n(){var e=r.selection.createRange();a&&!e.item&&0===e.compareEndPoints("StartToEnd",e)&&a.select(),z.unbind(r,"mouseup",n),z.unbind(r,"mousemove",t),a=o=0}var r=z.doc,i=r.body,o,a,s;r.documentElement.unselectable=!0,z.bind(r,"mousedown contextmenu",function(i){if("HTML"===i.target.nodeName){if(o&&n(),s=r.documentElement,s.scrollHeight>s.clientHeight)return;o=1,a=e(i.x,i.y),a&&(z.bind(r,"mouseup",n),z.bind(r,"mousemove",t),z.win.focus(),a.select())}})}function L(){a.on("keyup focusin",function(t){65==t.keyCode&&e.metaKeyPressed(t)||W.normalize()})}function H(){a.contentStyles.push("img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}")}function D(){a.inline||a.on("keydown",function(){document.activeElement==document.body&&a.getWin().focus()})}function M(){a.inline||(a.contentStyles.push("body {min-height: 150px}"),a.on("click",function(e){"HTML"==e.target.nodeName&&(a.execCommand("SelectAll"),a.selection.collapse(!0),a.nodeChanged())}))}function P(){i.mac&&a.on("keydown",function(t){!e.metaKeyPressed(t)||37!=t.keyCode&&39!=t.keyCode||(t.preventDefault(),a.selection.getSel().modify("move",37==t.keyCode?"backward":"forward","word"))})}var O=o.each,I=e.BACKSPACE,F=e.DELETE,z=a.dom,W=a.selection,V=a.settings,U=a.parser,q=a.serializer,j=i.gecko,$=i.ie,K=i.webkit;C(),_(),u(),L(),K&&(d(),p(),g(),k(),i.iOS?(y(),D(),M()):f()),$&&i.ie<11&&(m(),b(),x(),w(),T(),R(),A(),B()),i.ie>=11&&M(),i.ie&&f(),j&&(m(),h(),v(),N(),E(),S(),H(),P())}}),r(tt,[f],function(e){function t(){return!1}function n(){return!0}var r="__bindings",i=e.makeMap("focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave keydown keypress keyup contextmenu dragstart dragend dragover draggesture dragdrop drop drag"," ");return{fire:function(e,i,o){var a=this,s,l,c,d,u;if(e=e.toLowerCase(),i=i||{},i.type=e,i.target||(i.target=a),i.preventDefault||(i.preventDefault=function(){i.isDefaultPrevented=n},i.stopPropagation=function(){i.isPropagationStopped=n},i.stopImmediatePropagation=function(){i.isImmediatePropagationStopped=n},i.isDefaultPrevented=t,i.isPropagationStopped=t,i.isImmediatePropagationStopped=t),a[r]&&(s=a[r][e]))for(l=0,c=s.length;c>l&&(s[l]=d=s[l],!i.isImmediatePropagationStopped());l++)if(d.call(a,i)===!1)return i.preventDefault(),i;if(o!==!1&&a.parent)for(u=a.parent();u&&!i.isPropagationStopped();)u.fire(e,i,!1),u=u.parent();return i},on:function(e,t){var n=this,o,a,s,l;if(t===!1&&(t=function(){return!1}),t)for(s=e.toLowerCase().split(" "),l=s.length;l--;)e=s[l],o=n[r],o||(o=n[r]={}),a=o[e],a||(a=o[e]=[],n.bindNative&&i[e]&&n.bindNative(e)),a.push(t);return n},off:function(e,t){var n=this,o,a=n[r],s,l,c,d;if(a)if(e)for(c=e.toLowerCase().split(" "),o=c.length;o--;){if(e=c[o],s=a[e],!e){for(l in a)a[e].length=0;return n}if(s){if(t)for(d=s.length;d--;)s[d]===t&&s.splice(d,1);else s.length=0;!s.length&&n.unbindNative&&i[e]&&(n.unbindNative(e),delete a[e])}}else{if(n.unbindNative)for(e in a)n.unbindNative(e);n[r]=[]}return n},hasEventListeners:function(e){var t=this[r];return e=e.toLowerCase(),!(!t||!t[e]||0===t[e].length)}}}),r(nt,[f,h],function(e,t){var n=e.each,r=e.explode,i={f9:120,f10:121,f11:122};return function(o){var a=this,s={};o.on("keyup keypress keydown",function(e){(e.altKey||e.ctrlKey||e.metaKey)&&n(s,function(n){var r=t.mac?e.metaKey:e.ctrlKey;if(n.ctrl==r&&n.alt==e.altKey&&n.shift==e.shiftKey)return e.keyCode==n.keyCode||e.charCode&&e.charCode==n.charCode?(e.preventDefault(),"keydown"==e.type&&n.func.call(n.scope),!0):void 0})}),a.add=function(t,a,l,c){var d;return d=l,"string"==typeof l?l=function(){o.execCommand(d,!1,null)}:e.isArray(d)&&(l=function(){o.execCommand(d[0],d[1],d[2])}),n(r(t.toLowerCase()),function(e){var t={func:l,scope:c||o,desc:o.translate(a),alt:!1,ctrl:!1,shift:!1};n(r(e,"+"),function(e){switch(e){case"alt":case"ctrl":case"shift":t[e]=!0;break;default:t.charCode=e.charCodeAt(0),t.keyCode=i[e]||e.toUpperCase().charCodeAt(0)}}),s[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t}),!0}}}),r(rt,[g,y,b,E,N,R,B,L,H,D,M,P,v,d,Z,C,w,et,h,f,tt,nt],function(e,n,r,i,o,a,s,l,c,d,u,f,p,m,h,g,v,y,b,C,x,w){function _(e,t){return"selectionchange"==t||"drop"==t?e.getDoc():!e.inline&&/^mouse|click|contextmenu/.test(t)?e.getDoc():e.getBody()}function N(e,t,r){var i=this,o,a;o=i.documentBaseUrl=r.documentBaseURL,a=r.baseURI,i.settings=t=T({id:e,theme:"modern",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:o,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"",visual:!0,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",forced_root_block:"p",hidden_input:!0,padd_empty_editor:!0,render_ui:!0,indentation:"30px",inline_styles:!0,convert_fonts_to_spans:!0,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",validate:!0,entity_encoding:"named",url_converter:i.convertURL,url_converter_scope:i,ie7_compat:!0},t),n.language=t.language||"en",n.languageLoad=t.language_load,n.baseURL=r.baseURL,i.id=t.id=e,i.isNotDirty=!0,i.plugins={},i.documentBaseURI=new f(t.document_base_url||o,{base_uri:a}),i.baseURI=a,i.contentCSS=[],i.contentStyles=[],i.shortcuts=new w(i),i.execCommands={},i.queryStateCommands={},i.queryValueCommands={},i.loadedCSS={},i.suffix=r.suffix,i.editorManager=r,i.inline=t.inline,i.execCallback("setup",i),r.fire("SetupEditor",i)}var E=e.DOM,k=n.ThemeManager,S=n.PluginManager,T=C.extend,R=C.each,A=C.explode,B=C.inArray,L=C.trim,H=C.resolve,D=m.Event,M=b.gecko,P=b.ie;return N.prototype={render:function(){function e(){E.unbind(window,"ready",e),n.render()}function t(){var e=p.ScriptLoader;if(r.language&&"en"!=r.language&&(r.language_url=n.editorManager.baseURL+"/langs/"+r.language+".js"),r.language_url&&e.add(r.language_url),r.theme&&"function"!=typeof r.theme&&"-"!=r.theme.charAt(0)&&!k.urls[r.theme]){var t=r.theme_url;t=t?n.documentBaseURI.toAbsolute(t):"themes/"+r.theme+"/theme"+o+".js",k.load(r.theme,t)}C.isArray(r.plugins)&&(r.plugins=r.plugins.join(" ")),R(r.external_plugins,function(e,t){S.load(t,e),r.plugins+=" "+t}),R(r.plugins.split(/[ ,]/),function(e){if(e=L(e),e&&!S.urls[e])if("-"==e.charAt(0)){e=e.substr(1,e.length);var t=S.dependencies(e);R(t,function(e){var t={prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"};e=S.createUrl(t,e),S.load(e.resource,e)})}else S.load(e,{prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"})}),e.loadQueue(function(){n.removed||n.init()})}var n=this,r=n.settings,i=n.id,o=n.suffix;if(!D.domLoaded)return E.bind(window,"ready",e),void 0;if(n.getElement()&&b.contentEditable){r.inline?n.inline=!0:(n.orgVisibility=n.getElement().style.visibility,n.getElement().style.visibility="hidden");var a=n.getElement().form||E.getParent(i,"form");a&&(n.formElement=a,r.hidden_input&&!/TEXTAREA|INPUT/i.test(n.getElement().nodeName)&&(E.insertAfter(E.create("input",{type:"hidden",name:i}),i),n.hasHiddenInput=!0),n.formEventDelegate=function(e){n.fire(e.type,e)},E.bind(a,"submit reset",n.formEventDelegate),n.on("reset",function(){n.setContent(n.startContent,{format:"raw"})}),!r.submit_patch||a.submit.nodeType||a.submit.length||a._mceOldSubmit||(a._mceOldSubmit=a.submit,a.submit=function(){return n.editorManager.triggerSave(),n.isNotDirty=!0,a._mceOldSubmit(a)})),n.windowManager=new h(n),"xml"==r.encoding&&n.on("GetContent",function(e){e.save&&(e.content=E.encode(e.content))}),r.add_form_submit_trigger&&n.on("submit",function(){n.initialized&&n.save()}),r.add_unload_trigger&&(n._beforeUnload=function(){!n.initialized||n.destroyed||n.isHidden()||n.save({format:"raw",no_events:!0,set_dirty:!1})},n.editorManager.on("BeforeUnload",n._beforeUnload)),t()}},init:function(){function e(n){var r=S.get(n),i,o;i=S.urls[n]||t.documentBaseUrl.replace(/\/$/,""),n=L(n),r&&-1===B(m,n)&&(R(S.dependencies(n),function(t){e(t)}),o=new r(t,i),t.plugins[n]=o,o.init&&(o.init(t,i),m.push(n)))}var t=this,n=t.settings,r=t.getElement(),i,o,a,s,l,c,d,u,f,p,m=[];if(t.rtl=this.editorManager.i18n.rtl,t.editorManager.add(t),n.aria_label=n.aria_label||E.getAttrib(r,"aria-label",t.getLang("aria.rich_text_area")),n.theme&&("function"!=typeof n.theme?(n.theme=n.theme.replace(/-/,""),l=k.get(n.theme),t.theme=new l(t,k.urls[n.theme]),t.theme.init&&t.theme.init(t,k.urls[n.theme]||t.documentBaseUrl.replace(/\/$/,""))):t.theme=n.theme),R(n.plugins.replace(/\-/g,"").split(/[ ,]/),e),n.render_ui&&t.theme&&(t.orgDisplay=r.style.display,"function"!=typeof n.theme?(i=n.width||r.style.width||r.offsetWidth,o=n.height||r.style.height||r.offsetHeight,a=n.min_height||100,f=/^[0-9\.]+(|px)$/i,f.test(""+i)&&(i=Math.max(parseInt(i,10)+(l.deltaWidth||0),100)),f.test(""+o)&&(o=Math.max(parseInt(o,10)+(l.deltaHeight||0),a)),l=t.theme.renderUI({targetNode:r,width:i,height:o,deltaWidth:n.delta_width,deltaHeight:n.delta_height}),n.content_editable||(E.setStyles(l.sizeContainer||l.editorContainer,{wi2dth:i,h2eight:o}),o=(l.iframeHeight||o)+("number"==typeof o?l.deltaHeight||0:""),a>o&&(o=a))):(l=n.theme(t,r),l.editorContainer.nodeType&&(l.editorContainer=l.editorContainer.id=l.editorContainer.id||t.id+"_parent"),l.iframeContainer.nodeType&&(l.iframeContainer=l.iframeContainer.id=l.iframeContainer.id||t.id+"_iframecontainer"),o=l.iframeHeight||r.offsetHeight),t.editorContainer=l.editorContainer),n.content_css&&R(A(n.content_css),function(e){t.contentCSS.push(t.documentBaseURI.toAbsolute(e))}),n.content_style&&t.contentStyles.push(n.content_style),n.content_editable)return r=s=l=null,t.initContentBody();for(t.iframeHTML=n.doctype+"",n.document_base_url!=t.documentBaseUrl&&(t.iframeHTML+=''),!b.caretAfter&&n.ie7_compat&&(t.iframeHTML+=''),t.iframeHTML+='',p=0;p',t.loadedCSS[h]=!0}d=n.body_id||"tinymce",-1!=d.indexOf("=")&&(d=t.getParam("body_id","","hash"),d=d[t.id]||d),u=n.body_class||"",-1!=u.indexOf("=")&&(u=t.getParam("body_class","","hash"),u=u[t.id]||""),t.iframeHTML+='
";var g='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinymce.get("'+t.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody(true);})()';if(document.domain!=location.hostname&&(c=g),s=E.add(l.iframeContainer,"iframe",{id:t.id+"_ifr",src:c||'javascript:""',frameBorder:"0",allowTransparency:"true",title:t.editorManager.translate("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),style:{width:"100%",height:o,display:"block"}}),P)try{t.getDoc()}catch(v){s.src=c=g}t.contentAreaContainer=l.iframeContainer,l.editorContainer&&(E.get(l.editorContainer).style.display=t.orgDisplay),E.get(t.id).style.display="none",E.setAttrib(t.id,"aria-hidden",!0),c||t.initContentBody(),r=s=l=null},initContentBody:function(t){var n=this,o=n.settings,f=E.get(n.id),p=n.getDoc(),m,h;o.inline||(n.getElement().style.visibility=n.orgVisibility),t||o.content_editable||(p.open(),p.write(n.iframeHTML),p.close()),o.content_editable&&(n.on("remove",function(){var e=this.getBody();E.removeClass(e,"mce-content-body"),E.removeClass(e,"mce-edit-focus"),E.setAttrib(e,"tabIndex",null),E.setAttrib(e,"contentEditable",null) +}),E.addClass(f,"mce-content-body"),f.tabIndex=-1,n.contentDocument=p=o.content_document||document,n.contentWindow=o.content_window||window,n.bodyElement=f,o.content_document=o.content_window=null,o.root_name=f.nodeName.toLowerCase()),m=n.getBody(),m.disabled=!0,o.readonly||(n.inline&&"static"==E.getStyle(m,"position",!0)&&(m.style.position="relative"),m.contentEditable=n.getParam("content_editable_state",!0)),m.disabled=!1,n.schema=new g(o),n.dom=new e(p,{keep_values:!0,url_converter:n.convertURL,url_converter_scope:n,hex_colors:o.force_hex_style_colors,class_filter:o.class_filter,update_styles:!0,root_element:o.content_editable?n.id:null,collect:o.content_editable,schema:n.schema,onSetAttrib:function(e){n.fire("SetAttrib",e)}}),n.parser=new v(o,n.schema),n.parser.addAttributeFilter("src,href,style",function(e,t){for(var r=e.length,i,o=n.dom,a,s;r--;)i=e[r],a=i.attr(t),s="data-mce-"+t,i.attributes.map[s]||("style"===t?i.attr(s,o.serializeStyle(o.parseStyle(a),i.name)):i.attr(s,n.convertURL(a,t,i.name)))}),n.parser.addNodeFilter("script",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr("type","mce-"+(n.attr("type")||"text/javascript"))}),n.parser.addNodeFilter("#cdata",function(e){for(var t=e.length,n;t--;)n=e[t],n.type=8,n.name="#comment",n.value="[CDATA["+n.value+"]]"}),n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(e){for(var t=e.length,i,o=n.schema.getNonEmptyElements();t--;)i=e[t],i.isEmpty(o)&&(i.empty().append(new r("br",1)).shortEnded=!0)}),n.serializer=new i(o,n),n.selection=new a(n.dom,n.getWin(),n.serializer,n),n.formatter=new s(n),n.undoManager=new l(n),n.forceBlocks=new d(n),n.enterKey=new c(n),n.editorCommands=new u(n),n.fire("PreInit"),o.browser_spellcheck||o.gecko_spellcheck||(p.body.spellcheck=!1,E.setAttrib(m,"spellcheck","false")),n.fire("PostRender"),n.quirks=y(n),o.directionality&&(m.dir=o.directionality),o.nowrap&&(m.style.whiteSpace="nowrap"),o.protect&&n.on("BeforeSetContent",function(e){R(o.protect,function(t){e.content=e.content.replace(t,function(e){return""})})}),n.on("SetContent",function(){n.addVisual(n.getBody())}),o.padd_empty_editor&&n.on("PostProcess",function(e){e.content=e.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
[\r\n]*)$/,"")}),n.load({initial:!0,format:"html"}),n.startContent=n.getContent({format:"raw"}),n.initialized=!0,R(n._pendingNativeEvents,function(e){n.dom.bind(_(n,e),e,function(e){n.fire(e.type,e)})}),n.fire("init"),n.focus(!0),n.nodeChanged({initial:!0}),n.execCallback("init_instance_callback",n),n.contentStyles.length>0&&(h="",R(n.contentStyles,function(e){h+=e+"\r\n"}),n.dom.addStyle(h)),R(n.contentCSS,function(e){n.loadedCSS[e]||(n.dom.loadCSS(e),n.loadedCSS[e]=!0)}),o.auto_focus&&setTimeout(function(){var e=n.editorManager.get(o.auto_focus);e.selection.select(e.getBody(),1),e.selection.collapse(1),e.getBody().focus(),e.getWin().focus()},100),f=p=m=null},focus:function(e){var t,n=this,r=n.selection,i=n.settings.content_editable,o,a,s=n.getDoc(),l;e||(o=r.getRng(),o.item&&(a=o.item(0)),n._refreshContentEditable(),i||(b.opera||n.getBody().focus(),n.getWin().focus()),(M||i)&&(l=n.getBody(),l.setActive&&b.ie<11?l.setActive():l.focus(),i&&r.normalize()),a&&a.ownerDocument==s&&(o=s.body.createControlRange(),o.addElement(a),o.select())),n.editorManager.activeEditor!=n&&((t=n.editorManager.activeEditor)&&t.fire("deactivate",{relatedTarget:n}),n.fire("activate",{relatedTarget:t})),n.editorManager.activeEditor=n},execCallback:function(e){var t=this,n=t.settings[e],r;if(n)return t.callbackLookup&&(r=t.callbackLookup[e])&&(n=r.func,r=r.scope),"string"==typeof n&&(r=n.replace(/\.\w+$/,""),r=r?H(r):0,n=H(n),t.callbackLookup=t.callbackLookup||{},t.callbackLookup[e]={func:n,scope:r}),n.apply(r||t,Array.prototype.slice.call(arguments,1))},translate:function(e){var t=this.settings.language||"en",n=this.editorManager.i18n;return e?n.data[t+"."+e]||e.replace(/\{\#([^\}]+)\}/g,function(e,r){return n.data[t+"."+r]||"{#"+r+"}"}):""},getLang:function(e,n){return this.editorManager.i18n.data[(this.settings.language||"en")+"."+e]||(n!==t?n:"{#"+e+"}")},getParam:function(e,t,n){var r=e in this.settings?this.settings[e]:t,i;return"hash"===n?(i={},"string"==typeof r?R(r.indexOf("=")>0?r.split(/[;,](?![^=;,]*(?:[;,]|$))/):r.split(","),function(e){e=e.split("="),i[L(e[0])]=e.length>1?L(e[1]):L(e)}):i=r,i):r},nodeChanged:function(){var e=this,t=e.selection,n,r,i;e.initialized&&!e.settings.disable_nodechange&&(i=e.getBody(),n=t.getStart()||i,n=P&&n.ownerDocument!=e.getDoc()?e.getBody():n,"IMG"==n.nodeName&&t.isCollapsed()&&(n=n.parentNode),r=[],e.dom.getParent(n,function(e){return e===i?!0:(r.push(e),void 0)}),e.fire("NodeChange",{element:n,parents:r}))},addButton:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),t.text||t.icon||(t.icon=e),n.buttons=n.buttons||{},t.tooltip=t.tooltip||t.title,n.buttons[e]=t},addMenuItem:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),n.menuItems=n.menuItems||{},n.menuItems[e]=t},addCommand:function(e,t,n){this.execCommands[e]={func:t,scope:n||this}},addQueryStateHandler:function(e,t,n){this.queryStateCommands[e]={func:t,scope:n||this}},addQueryValueHandler:function(e,t,n){this.queryValueCommands[e]={func:t,scope:n||this}},addShortcut:function(e,t,n,r){this.shortcuts.add(e,t,n,r)},execCommand:function(e,t,n,r){var i=this,o=0,a;return/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(e)||r&&r.skip_focus||i.focus(),r=T({},r),r=i.fire("BeforeExecCommand",{command:e,ui:t,value:n}),r.isDefaultPrevented()?!1:(a=i.execCommands[e])&&a.func.call(a.scope,t,n)!==!0?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):(R(i.plugins,function(r){return r.execCommand&&r.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),o=!0,!1):void 0}),o?o:i.theme&&i.theme.execCommand&&i.theme.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):i.editorCommands.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):(i.getDoc().execCommand(e,t,n),i.fire("ExecCommand",{command:e,ui:t,value:n}),void 0))},queryCommandState:function(e){var t=this,n,r;if(!t._isHidden()){if((n=t.queryStateCommands[e])&&(r=n.func.call(n.scope),r!==!0))return r;if(r=t.editorCommands.queryCommandState(e),-1!==r)return r;try{return t.getDoc().queryCommandState(e)}catch(i){}}},queryCommandValue:function(e){var n=this,r,i;if(!n._isHidden()){if((r=n.queryValueCommands[e])&&(i=r.func.call(r.scope),i!==!0))return i;if(i=n.editorCommands.queryCommandValue(e),i!==t)return i;try{return n.getDoc().queryCommandValue(e)}catch(o){}}},show:function(){var e=this;E.show(e.getContainer()),E.hide(e.id),e.load(),e.fire("show")},hide:function(){var e=this,t=e.getDoc();P&&t&&!e.inline&&t.execCommand("SelectAll"),e.save(),E.hide(e.getContainer()),E.setStyle(e.id,"display",e.orgDisplay),e.fire("hide")},isHidden:function(){return!E.isHidden(this.id)},setProgressState:function(e,t){this.fire("ProgressState",{state:e,time:t})},load:function(e){var n=this,r=n.getElement(),i;return r?(e=e||{},e.load=!0,i=n.setContent(r.value!==t?r.value:r.innerHTML,e),e.element=r,e.no_events||n.fire("LoadContent",e),e.element=r=null,i):void 0},save:function(e){var t=this,n=t.getElement(),r,i;if(n&&t.initialized)return e=e||{},e.save=!0,e.element=n,r=e.content=t.getContent(e),e.no_events||t.fire("SaveContent",e),r=e.content,/TEXTAREA|INPUT/i.test(n.nodeName)?n.value=r:(n.innerHTML=r,(i=E.getParent(t.id,"form"))&&R(i.elements,function(e){return e.name==t.id?(e.value=r,!1):void 0})),e.element=n=null,e.set_dirty!==!1&&(t.isNotDirty=!0),r},setContent:function(e,t){var n=this,r=n.getBody(),i;return t=t||{},t.format=t.format||"html",t.set=!0,t.content=e,t.no_events||n.fire("BeforeSetContent",t),e=t.content,0===e.length||/^\s+$/.test(e)?(i=n.settings.forced_root_block,i&&n.schema.isValidChild(r.nodeName.toLowerCase(),i.toLowerCase())?(e=P&&11>P?"":'
',e=n.dom.createHTML(i,n.settings.forced_root_block_attrs,e)):(!P||11>P)&&(e='
'),r.innerHTML=e,n.fire("SetContent",t)):("raw"!==t.format&&(e=new o({},n.schema).serialize(n.parser.parse(e,{isRootContent:!0}))),t.content=L(e),n.dom.setHTML(r,t.content),t.no_events||n.fire("SetContent",t)),t.content},getContent:function(e){var t=this,n,r=t.getBody();return e=e||{},e.format=e.format||"html",e.get=!0,e.getInner=!0,e.no_events||t.fire("BeforeGetContent",e),n="raw"==e.format?r.innerHTML:"text"==e.format?r.innerText||r.textContent:t.serializer.serialize(r,e),e.content="text"!=e.format?L(n):n,e.no_events||t.fire("GetContent",e),e.content},insertContent:function(e){this.execCommand("mceInsertContent",!1,e)},isDirty:function(){return!this.isNotDirty},getContainer:function(){var e=this;return e.container||(e.container=E.get(e.editorContainer||e.id+"_parent")),e.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return E.get(this.settings.content_element||this.id)},getWin:function(){var e=this,t;return e.contentWindow||(t=E.get(e.id+"_ifr"),t&&(e.contentWindow=t.contentWindow)),e.contentWindow},getDoc:function(){var e=this,t;return e.contentDocument||(t=e.getWin(),t&&(e.contentDocument=t.document)),e.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(e,t,n){var r=this,i=r.settings;return i.urlconverter_callback?r.execCallback("urlconverter_callback",e,n,!0,t):!i.convert_urls||n&&"LINK"==n.nodeName||0===e.indexOf("file:")||0===e.length?e:i.relative_urls?r.documentBaseURI.toRelative(e):e=r.documentBaseURI.toAbsolute(e,i.remove_script_host)},addVisual:function(e){var n=this,r=n.settings,i=n.dom,o;e=e||n.getBody(),n.hasVisual===t&&(n.hasVisual=r.visual),R(i.select("table,a",e),function(e){var t;switch(e.nodeName){case"TABLE":return o=r.visual_table_class||"mce-item-table",t=i.getAttrib(e,"border"),t&&"0"!=t||(n.hasVisual?i.addClass(e,o):i.removeClass(e,o)),void 0;case"A":return i.getAttrib(e,"href",!1)||(t=i.getAttrib(e,"name")||e.id,o="mce-item-anchor",t&&(n.hasVisual?i.addClass(e,o):i.removeClass(e,o))),void 0}}),n.fire("VisualAid",{element:e,hasVisual:n.hasVisual})},remove:function(){var e=this;if(!e.removed){e.removed=1,e.hasHiddenInput&&E.remove(e.getElement().nextSibling);var t=e.getDoc();P&&t&&!e.inline&&t.execCommand("SelectAll"),e.save(),E.setStyle(e.id,"display",e.orgDisplay),e.settings.content_editable||(D.unbind(e.getWin()),D.unbind(e.getDoc()));var n=e.getContainer();D.unbind(e.getBody()),D.unbind(n),e.fire("remove"),e.editorManager.remove(e),E.remove(n),e.destroy()}},bindNative:function(e){var t=this;t.settings.readonly||(t.initialized?t.dom.bind(_(t,e),e,function(n){t.fire(e,n)}):t._pendingNativeEvents?t._pendingNativeEvents.push(e):t._pendingNativeEvents=[e])},unbindNative:function(e){var t=this;t.initialized&&t.dom.unbind(e)},destroy:function(e){var t=this,n;if(!t.destroyed){if(!e&&!t.removed)return t.remove(),void 0;e&&M&&(D.unbind(t.getDoc()),D.unbind(t.getWin()),D.unbind(t.getBody())),e||(t.editorManager.off("beforeunload",t._beforeUnload),t.theme&&t.theme.destroy&&t.theme.destroy(),t.selection.destroy(),t.dom.destroy()),n=t.formElement,n&&(n._mceOldSubmit&&(n.submit=n._mceOldSubmit,n._mceOldSubmit=null),E.unbind(n,"submit reset",t.formEventDelegate)),t.contentAreaContainer=t.formElement=t.container=null,t.settings.content_element=t.bodyElement=t.contentDocument=t.contentWindow=null,t.selection&&(t.selection=t.selection.win=t.selection.dom=t.selection.dom.doc=null),t.destroyed=1}},_refreshContentEditable:function(){var e=this,t,n;e._isHidden()&&(t=e.getBody(),n=t.parentNode,n.removeChild(t),n.appendChild(t),t.focus())},_isHidden:function(){var e;return M?(e=this.selection.getSel(),!e||!e.rangeCount||0===e.rangeCount):0}},T(N.prototype,x),N}),r(it,[],function(){var e={};return{rtl:!1,add:function(t,n){for(var r in n)e[r]=n[r];this.rtl=this.rtl||"rtl"===e._dir},translate:function(t){if("undefined"==typeof t)return t;if("string"!=typeof t&&t.raw)return t.raw;if(t.push){var n=t.slice(1);t=(e[t[0]]||t[0]).replace(/\{([^\}]+)\}/g,function(e,t){return n[t]})}return e[t]||t},data:e}}),r(ot,[g,h],function(e,t){function n(r){function i(){try{return document.activeElement}catch(e){return document.body}}function o(e){return e&&e.startContainer?{startContainer:e.startContainer,startOffset:e.startOffset,endContainer:e.endContainer,endOffset:e.endOffset}:e}function a(e,t){var n;return t.startContainer?(n=e.getDoc().createRange(),n.setStart(t.startContainer,t.startOffset),n.setEnd(t.endContainer,t.endOffset)):n=t,n}function s(t){return!!e.DOM.getParent(t,n.isEditorUIElement)}function l(e,t){for(var n=t.getBody();e;){if(e==n)return!0;e=e.parentNode}}function c(n){var c=n.editor,d;c.on("init",function(){"onbeforedeactivate"in document&&t.ie<11?c.dom.bind(c.getBody(),"beforedeactivate",function(){try{c.lastRng=c.selection.getRng()}catch(e){}c.selection.lastFocusBookmark=o(c.lastRng)}):(c.inline||t.ie>10)&&(c.on("nodechange keyup",function(){var e=document.activeElement;e&&e.id==c.id+"_ifr"&&(e=c.getBody()),l(e,c)&&(c.lastRng=c.selection.getRng())}),t.webkit&&(d=function(){var e=c.selection.getRng();e.collapsed||(c.lastRng=e)},e.DOM.bind(document,"selectionchange",d),c.on("remove",function(){e.DOM.unbind(document,"selectionchange",d)})))}),c.on("setcontent",function(){c.lastRng=null}),c.on("mousedown",function(){c.selection.lastFocusBookmark=null}),c.on("focusin",function(){var e=r.focusedEditor;c.selection.lastFocusBookmark&&(c.selection.setRng(a(c,c.selection.lastFocusBookmark)),c.selection.lastFocusBookmark=null),e!=c&&(e&&e.fire("blur",{focusedEditor:c}),r.activeEditor=c,r.focusedEditor=c,c.fire("focus",{blurredEditor:e}),c.focus(!1)),c.lastRng=null}),c.on("focusout",function(){window.setTimeout(function(){var e=r.focusedEditor;s(i())||e!=c||(c.fire("blur",{focusedEditor:null}),r.focusedEditor=null,c.selection.lastFocusBookmark=null)},0)})}e.DOM.bind(document,"focusin",function(e){var t=r.activeEditor;t&&e.target.ownerDocument==document&&(t.selection.lastFocusBookmark=o(t.lastRng),s(e.target)||r.focusedEditor!=t||(t.fire("blur",{focusedEditor:null}),r.focusedEditor=null))}),r.on("AddEditor",c)}return n.isEditorUIElement=function(e){return-1!==e.className.indexOf("mce-")},n}),r(at,[rt,g,P,h,f,tt,it,ot],function(e,n,r,i,o,a,s,l){var c=n.DOM,d=o.explode,u=o.each,f=o.extend,p=0,m,h={majorVersion:"4",minorVersion:"0.12",releaseDate:"2013-12-18",editors:[],i18n:s,activeEditor:null,setup:function(){var e=this,t,n,i="",o;if(n=document.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(n)||(n+="/"),o=window.tinymce||window.tinyMCEPreInit)t=o.base||o.baseURL,i=o.suffix;else for(var a=document.getElementsByTagName("script"),s=0;s0&&u(d(m),function(n){c.get(n)?(l=new e(n,t,a),s.push(l),l.render(!0)):u(document.forms,function(r){u(r.elements,function(r){r.name===n&&(n="mce_editor_"+p++,c.setAttrib(r,"id",n),l=new e(n,t,a),s.push(l),l.render(1))})})});break;case"textareas":case"specific_textareas":u(c.select("textarea"),function(r){t.editor_deselector&&i(r,t.editor_deselector)||(!t.editor_selector||i(r,t.editor_selector))&&(l=new e(n(r),t,a),s.push(l),l.render(!0))})}t.oninit&&(m=h=0,u(s,function(e){h++,e.initialized?m++:e.on("init",function(){m++,m==h&&r(t,"oninit")}),m==h&&r(t,"oninit")}))}var a=this,s=[],l;a.settings=t,c.bind(window,"ready",o)},get:function(e){return e===t?this.editors:this.editors[e]},add:function(e){var t=this,n=t.editors;return n[e.id]=e,n.push(e),t.activeEditor=e,t.fire("AddEditor",{editor:e}),m||(m=function(){t.fire("BeforeUnload")},c.bind(window,"beforeunload",m)),e},createEditor:function(t,n){return this.add(new e(t,n,this))},remove:function(e){var t=this,n,r=t.editors,i,o;{if(e){if("string"==typeof e)return e=e.selector||e,u(c.select(e),function(e){t.remove(r[e.id])}),void 0;if(i=e,!r[i.id])return null;for(delete r[i.id],n=0;n=0;n--)t.remove(r[n])}},execCommand:function(t,n,r){var i=this,o=i.get(r);switch(t){case"mceAddEditor":return i.get(r)||new e(r,i.settings,i).render(),!0;case"mceRemoveEditor":return o&&o.remove(),!0;case"mceToggleEditor":return o?(o.isHidden()?o.show():o.hide(),!0):(i.execCommand("mceAddEditor",0,r),!0)}return i.activeEditor?i.activeEditor.execCommand(t,n,r):!1},triggerSave:function(){u(this.editors,function(e){e.save()})},addI18n:function(e,t){s.add(e,t)},translate:function(e){return s.translate(e)}};return f(h,a),h.setup(),window.tinymce=window.tinyMCE=h,h}),r(st,[at,f],function(e,t){var n=t.each,r=t.explode;e.on("AddEditor",function(e){var t=e.editor;t.on("preInit",function(){function e(e,t){n(t,function(t,n){t&&s.setStyle(e,n,t)}),s.rename(e,"span")}function i(e){s=t.dom,l.convert_fonts_to_spans&&n(s.select("font,u,strike",e.node),function(e){o[e.nodeName.toLowerCase()](s,e)})}var o,a,s,l=t.settings;l.inline_styles&&(a=r(l.font_size_legacy_values),o={font:function(t,n){e(n,{backgroundColor:n.style.backgroundColor,color:n.color,fontFamily:n.face,fontSize:a[parseInt(n.size,10)-1]})},u:function(t,n){e(n,{textDecoration:"underline"})},strike:function(t,n){e(n,{textDecoration:"line-through"})}},t.on("PreProcess SetContent",i))})})}),r(lt,[],function(){return{send:function(e){function t(){!e.async||4==n.readyState||r++>1e4?(e.success&&1e4>r&&200==n.status?e.success.call(e.success_scope,""+n.responseText,n,e):e.error&&e.error.call(e.error_scope,r>1e4?"TIMED_OUT":"GENERAL",n,e),n=null):setTimeout(t,10)}var n,r=0;if(e.scope=e.scope||this,e.success_scope=e.success_scope||e.scope,e.error_scope=e.error_scope||e.scope,e.async=e.async===!1?!1:!0,e.data=e.data||"",n=new XMLHttpRequest){if(n.overrideMimeType&&n.overrideMimeType(e.content_type),n.open(e.type||(e.data?"POST":"GET"),e.url,e.async),e.content_type&&n.setRequestHeader("Content-Type",e.content_type),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),n.send(e.data),!e.async)return t();setTimeout(t,10)}}}}),r(ct,[],function(){function e(t,n){var r,i,o,a;if(n=n||'"',null===t)return"null";if(o=typeof t,"string"==o)return i="\bb t\nn\ff\rr\"\"''\\\\",n+t.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(e,t){return'"'===n&&"'"===e?e:(r=i.indexOf(t),r+1?"\\"+i.charAt(r+1):(e=t.charCodeAt().toString(16),"\\u"+"0000".substring(e.length)+e))})+n;if("object"==o){if(t.hasOwnProperty&&"[object Array]"===Object.prototype.toString.call(t)){for(r=0,i="[";r0?",":"")+e(t[r],n);return i+"]"}i="{";for(a in t)t.hasOwnProperty(a)&&(i+="function"!=typeof t[a]?(i.length>1?","+n:n)+a+n+":"+e(t[a],n):"");return i+"}"}return""+t}return{serialize:e,parse:function(e){try{return window[String.fromCharCode(101)+"val"]("("+e+")")}catch(t){}}}}),r(dt,[ct,lt,f],function(e,t,n){function r(e){this.settings=i({},e),this.count=0}var i=n.extend;return r.sendRPC=function(e){return(new r).send(e)},r.prototype={send:function(n){var r=n.error,o=n.success;n=i(this.settings,n),n.success=function(t,i){t=e.parse(t),"undefined"==typeof t&&(t={error:"JSON Parse error."}),t.error?r.call(n.error_scope||n.scope,t.error,i):o.call(n.success_scope||n.scope,t.result)},n.error=function(e,t){r&&r.call(n.error_scope||n.scope,e,t)},n.data=e.serialize({id:n.id||"c"+this.count++,method:n.method,params:n.params}),n.content_type="application/json",t.send(n)}},r}),r(ut,[g],function(e){return{callbacks:{},count:0,send:function(n){var r=this,i=e.DOM,o=n.count!==t?n.count:r.count,a="tinymce_jsonp_"+o;r.callbacks[o]=function(e){i.remove(a),delete r.callbacks[o],n.callback(e)},i.add(i.doc.body,"script",{id:a,src:n.url,type:"text/javascript"}),r.count++}}}),r(ft,[],function(){function e(){s=[];for(var e in a)s.push(e);i.length=s.length}function n(){function n(e){var n,r;return r=e!==t?d+e:i.indexOf(",",d),-1===r||r>i.length?null:(n=i.substring(d,r),d=r+1,n)}var r,i,s,d=0;if(a={},c){o.load(l),i=o.getAttribute(l)||"";do{var u=n();if(null===u)break;if(r=n(parseInt(u,32)||0),null!==r){if(u=n(),null===u)break;s=n(parseInt(u,32)||0),r&&(a[r]=s)}}while(null!==r);e()}}function r(){var t,n="";if(c){for(var r in a)t=a[r],n+=(n?",":"")+r.length.toString(32)+","+r+","+t.length.toString(32)+","+t;o.setAttribute(l,n);try{o.save(l)}catch(i){}e()}}var i,o,a,s,l,c;try{if(window.localStorage)return localStorage}catch(d){}return l="tinymce",o=document.documentElement,c=!!o.addBehavior,c&&o.addBehavior("#default#userData"),i={key:function(e){return s[e]},getItem:function(e){return e in a?a[e]:null},setItem:function(e,t){a[e]=""+t,r()},removeItem:function(e){delete a[e],r()},clear:function(){a={},r()}},n(),i}),r(pt,[g,d,v,y,f,h],function(e,t,n,r,i,o){var a=window.tinymce;return a.DOM=e.DOM,a.ScriptLoader=n.ScriptLoader,a.PluginManager=r.PluginManager,a.ThemeManager=r.ThemeManager,a.dom=a.dom||{},a.dom.Event=t.Event,i.each(i,function(e,t){a[t]=e}),i.each("isOpera isWebKit isIE isGecko isMac".split(" "),function(e){a[e]=o[e.substr(2).toLowerCase()]}),{}}),r(mt,[O,f],function(e,t){return e.extend({Defaults:{firstControlClass:"first",lastControlClass:"last"},init:function(e){this.settings=t.extend({},this.Defaults,e)},preRender:function(e){e.addClass(this.settings.containerClass,"body")},applyClasses:function(e){var t=this,n=t.settings,r,i,o;r=e.items().filter(":visible"),i=n.firstControlClass,o=n.lastControlClass,r.each(function(e){e.removeClass(i).removeClass(o),n.controlClass&&e.addClass(n.controlClass)}),r.eq(0).addClass(i),r.eq(-1).addClass(o)},renderHtml:function(e){var t=this,n=t.settings,r,i="";return r=e.items(),r.eq(0).addClass(n.firstControlClass),r.eq(-1).addClass(n.lastControlClass),r.each(function(e){n.controlClass&&e.addClass(n.controlClass),i+=e.renderHtml()}),i},recalc:function(){},postRender:function(){}})}),r(ht,[mt],function(e){return e.extend({Defaults:{containerClass:"abs-layout",controlClass:"abs-layout-item"},recalc:function(e){e.items().filter(":visible").each(function(e){var t=e.settings;e.layoutRect({x:t.x,y:t.y,w:t.w,h:t.h}),e.recalc&&e.recalc()})},renderHtml:function(e){return'
'+this._super(e)}})}),r(gt,[W,K],function(e,t){return e.extend({Mixins:[t],Defaults:{classes:"widget tooltip tooltip-n"},text:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t._rendered&&(t.getEl().lastChild.innerHTML=t.encode(e)),t):t._value},renderHtml:function(){var e=this,t=e.classPrefix;return'"},repaint:function(){var e=this,t,n;t=e.getEl().style,n=e._layoutRect,t.left=n.x+"px",t.top=n.y+"px",t.zIndex=131070}})}),r(vt,[W,gt],function(e,t){var n,r=e.extend({init:function(e){var t=this;t._super(e),t.canFocus=!0,e.tooltip&&r.tooltips!==!1&&(t.on("mouseenter",function(n){var r=t.tooltip().moveTo(-65535);if(n.control==t){var i=r.text(e.tooltip).show().testMoveRel(t.getEl(),["bc-tc","bc-tl","bc-tr"]);r.toggleClass("tooltip-n","bc-tc"==i),r.toggleClass("tooltip-nw","bc-tl"==i),r.toggleClass("tooltip-ne","bc-tr"==i),r.moveRel(t.getEl(),i)}else r.hide()}),t.on("mouseleave mousedown click",function(){t.tooltip().hide()})),t.aria("label",e.tooltip)},tooltip:function(){var e=this;return n||(n=new t({type:"tooltip"}),n.renderTo(e.getContainerElm())),n},active:function(e){var t=this,n;return e!==n&&(t.aria("pressed",e),t.toggleClass("active",e)),t._super(e)},disabled:function(e){var t=this,n;return e!==n&&(t.aria("disabled",e),t.toggleClass("disabled",e)),t._super(e)},postRender:function(){var e=this,t=e.settings;e._rendered=!0,e._super(),e.parent()||!t.width&&!t.height||(e.initLayoutRect(),e.repaint()),t.autofocus&&setTimeout(function(){e.focus()},0)},remove:function(){this._super(),n&&(n.remove(),n=null)}});return r}),r(yt,[vt],function(e){return e.extend({Defaults:{classes:"widget btn",role:"button"},init:function(e){var t=this,n;t.on("click mousedown",function(e){e.preventDefault()}),t._super(e),n=e.size,e.subtype&&t.addClass(e.subtype),n&&t.addClass("btn-"+n)},icon:function(e){var t=this,n=t.classPrefix;if("undefined"==typeof e)return t.settings.icon;if(t.settings.icon=e,e=e?n+"ico "+n+"i-"+t.settings.icon:"",t._rendered){var r=t.getEl().firstChild,i=r.getElementsByTagName("i")[0];e?(i&&i==r.firstChild||(i=document.createElement("i"),r.insertBefore(i,r.firstChild)),i.className=e):i&&r.removeChild(i),t.text(t._text)}return t},repaint:function(){var e=this.getEl().firstChild.style;e.width=e.height="100%",this._super()},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon,i="";return e.settings.image&&(r="none",i=" style=\"background-image: url('"+e.settings.image+"')\""),r=e.settings.icon?n+"ico "+n+"i-"+r:"",'
"}})}),r(bt,[U],function(e){return e.extend({Defaults:{defaultType:"button",role:"toolbar"},renderHtml:function(){var e=this,t=e._layout;return e.addClass("btn-group"),e.preRender(),t.preRender(e),'
'+(e.settings.html||"")+t.renderHtml(e)+"
"}})}),r(Ct,[vt],function(e){return e.extend({Defaults:{classes:"checkbox",role:"checkbox",checked:!1},init:function(e){var t=this;t._super(e),t.on("click mousedown",function(e){e.preventDefault()}),t.on("click",function(e){e.preventDefault(),t.disabled()||t.checked(!t.checked())}),t.checked(t.settings.checked)},checked:function(e){var t=this;return"undefined"!=typeof e?(e?t.addClass("checked"):t.removeClass("checked"),t._checked=e,t.aria("checked",e),t):t._checked},value:function(e){return this.checked(e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'
'+e.encode(e._text)+"
"}})}),r(xt,[yt,G],function(e,t){return e.extend({showPanel:function(){var e=this,n=e.settings;if(e.active(!0),e.panel)e.panel.show();else{var r=n.panel;r.type&&(r={layout:"grid",items:r}),r.popover=!0,r.autohide=!0,e.panel=new t(r).on("hide",function(){e.active(!1)}).parent(e).renderTo(e.getContainerElm()),e.panel.fire("show"),e.panel.reflow()}e.panel.moveRel(e.getEl(),n.popoverAlign||(e.isRtl()?["bc-tr","bc-tc"]:["bc-tl","bc-tc"]))},hidePanel:function(){var e=this;e.panel&&e.panel.hide()},postRender:function(){var e=this;return e.on("click",function(t){t.control===e&&(e.panel&&e.panel.visible()?e.hidePanel():e.showPanel())}),e._super()}})}),r(wt,[xt,g],function(e,t){var n=t.DOM;return e.extend({init:function(e){this._super(e),this.addClass("colorbutton")},color:function(e){return e?(this._color=e,this.getEl("preview").style.backgroundColor=e,this):this._color},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon?n+"ico "+n+"i-"+e.settings.icon:"",i=e.settings.image?" style=\"background-image: url('"+e.settings.image+"')\"":"";return'
'},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(r){r.control!=e||n.getParent(r.target,"."+e.classPrefix+"open")||(r.stopImmediatePropagation(),t.call(e,r))}),delete e.settings.onclick,e._super()}})}),r(_t,[vt,z],function(e,t){return e.extend({init:function(e){var n=this;n._super(e),n.addClass("combobox"),n.on("click",function(e){for(var t=e.target;t;)t.id&&-1!=t.id.indexOf("-open")&&n.fire("action"),t=t.parentNode}),n.on("keydown",function(e){"INPUT"==e.target.nodeName&&13==e.keyCode&&n.parents().reverse().each(function(t){return e.preventDefault(),n.fire("change"),t.hasEventListeners("submit")&&t.toJSON?(t.fire("submit",{data:t.toJSON()}),!1):void 0})}),e.placeholder&&(n.addClass("placeholder"),n.on("focusin",function(){n._hasOnChange||(t.on(n.getEl("inp"),"change",function(){n.fire("change")}),n._hasOnChange=!0),n.hasClass("placeholder")&&(n.getEl("inp").value="",n.removeClass("placeholder"))}),n.on("focusout",function(){0===n.value().length&&(n.getEl("inp").value=e.placeholder,n.addClass("placeholder"))}))},value:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t.removeClass("placeholder"),t._rendered&&(t.getEl("inp").value=e),t):t._rendered?(e=t.getEl("inp").value,e!=t.settings.placeholder?e:""):t._value},disabled:function(e){var t=this;return t._rendered&&"undefined"!=typeof e&&(t.getEl("inp").disabled=e),t._super(e)},focus:function(){this.getEl("inp").focus()},repaint:function(){var e=this,n=e.getEl(),r=e.getEl("open"),i=e.layoutRect(),o,a;o=r?i.w-t.getSize(r).width-10:i.w-10;var s=document;return s.all&&(!s.documentMode||s.documentMode<=8)&&(a=e.layoutRect().h-2+"px"),t.css(n.firstChild,{width:o,lineHeight:a}),e._super(),e},postRender:function(){var e=this;return t.on(this.getEl("inp"),"change",function(){e.fire("change")}),e._super()},remove:function(){t.off(this.getEl("inp")),this._super()},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.classPrefix,i=n.value||n.placeholder||"",o,a,s="";return o=n.icon?r+"ico "+r+"i-"+n.icon:"",a=e._text,(o||a)&&(s='
",e.addClass("has-open")),'
"+s+"
"}})}),r(Nt,[vt,X],function(e,t){return e.extend({init:function(e){var t=this;e.delimiter||(e.delimiter="\xbb"),t._super(e),t.addClass("path"),t.canFocus=!0,t.on("click",function(e){var n,r=e.target;(n=r.getAttribute("data-index"))&&t.fire("select",{value:t.data()[n],index:n})})},focus:function(){var e=this;return e.keyNav=new t({root:e,enableLeftRight:!0}),e.keyNav.focusFirst(),e},data:function(e){var t=this;return"undefined"!=typeof e?(t._data=e,t.update(),t):t._data},update:function(){this.innerHtml(this._getPathHtml())},postRender:function(){var e=this;e._super(),e.data(e.settings.data)},renderHtml:function(){var e=this;return'
'+e._getPathHtml()+"
"},_getPathHtml:function(){var e=this,t=e._data||[],n,r,i="",o=e.classPrefix;for(n=0,r=t.length;r>n;n++)i+=(n>0?'":"")+'
'+t[n].name+"
"; +return i||(i='
 
'),i}})}),r(Et,[Nt,at],function(e,t){return e.extend({postRender:function(){function e(e){if(1===e.nodeType){if("BR"==e.nodeName||e.getAttribute("data-mce-bogus"))return!0;if("bookmark"===e.getAttribute("data-mce-type"))return!0}return!1}var n=this,r=t.activeEditor;return n.on("select",function(t){var n=[],i,o=r.getBody();for(r.focus(),i=r.selection.getStart();i&&i!=o;)e(i)||n.push(i),i=i.parentNode;r.selection.select(n[n.length-1-t.index]),r.nodeChanged()}),r.on("nodeChange",function(t){for(var i=[],o=t.parents,a=o.length;a--;)if(1==o[a].nodeType&&!e(o[a])){var s=r.fire("ResolveName",{name:o[a].nodeName.toLowerCase(),target:o[a]});i.push({name:s.name})}n.data(i)}),n._super()}})}),r(kt,[U],function(e){return e.extend({Defaults:{layout:"flex",align:"center",defaults:{flex:1}},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.addClass("formitem"),t.preRender(e),'
'+(e.settings.title?'
'+e.settings.title+"
":"")+'
'+(e.settings.html||"")+t.renderHtml(e)+"
"}})}),r(St,[U,kt],function(e,t){return e.extend({Defaults:{containerCls:"form",layout:"flex",direction:"column",align:"stretch",flex:1,padding:20,labelGap:30,spacing:10,callbacks:{submit:function(){this.submit()}}},preRender:function(){var e=this,n=e.items();n.each(function(n){var r,i=n.settings.label;i&&(r=new t({layout:"flex",autoResize:"overflow",defaults:{flex:1},items:[{type:"label",text:i,flex:0,forId:n._id}]}),r.type="formitem","undefined"==typeof n.settings.flex&&(n.settings.flex=1),e.replace(n,r),r.add(n))})},recalcLabels:function(){var e=this,t=0,n=[],r,i;if(e.settings.labelGapCalc!==!1)for(e.items().filter("formitem").each(function(e){var r=e.items()[0],i=r.getEl().clientWidth;t=i>t?i:t,n.push(r)}),i=e.settings.labelGap||0,r=n.length;r--;)n[r].settings.minWidth=t+i},visible:function(e){var t=this._super(e);return e===!0&&this._rendered&&this.recalcLabels(),t},submit:function(){return this.fire("submit",{data:this.toJSON()})},postRender:function(){var e=this;e._super(),e.recalcLabels(),e.fromJSON(e.settings.data)}})}),r(Tt,[St],function(e){return e.extend({Defaults:{containerCls:"fieldset",layout:"flex",direction:"column",align:"stretch",flex:1,padding:"25 15 5 15",labelGap:30,spacing:10,border:1},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.preRender(),t.preRender(e),'
'+(e.settings.title?''+e.settings.title+"":"")+'
'+(e.settings.html||"")+t.renderHtml(e)+"
"}})}),r(Rt,[_t],function(e){return e.extend({init:function(e){var t=this,n=tinymce.activeEditor,r;e.spellcheck=!1,r=n.settings.file_browser_callback,r&&(e.icon="browse",e.onaction=function(){r(t.getEl("inp").id,t.getEl("inp").value,e.filetype,window)}),t._super(e)}})}),r(At,[ht],function(e){return e.extend({recalc:function(e){var t=e.layoutRect(),n=e.paddingBox();e.items().filter(":visible").each(function(e){e.layoutRect({x:n.left,y:n.top,w:t.innerW-n.right-n.left,h:t.innerH-n.top-n.bottom}),e.recalc&&e.recalc()})}})}),r(Bt,[ht],function(e){return e.extend({recalc:function(e){var t,n,r,i,o,a,s,l,c,d,u,f,p,m,h,g,v=[],y,b,C,x,w,_,N,E,k,S,T,R,A,B,L,H,D,M,P,O,I,F,z,W,V=Math.max,U=Math.min;for(r=e.items().filter(":visible"),i=e.layoutRect(),o=e._paddingBox,a=e.settings,f=e.isRtl()?a.direction||"row-reversed":a.direction,s=a.align,l=e.isRtl()?a.pack||"end":a.pack,c=a.spacing||0,("row-reversed"==f||"column-reverse"==f)&&(r=r.set(r.toArray().reverse()),f=f.split("-")[0]),"column"==f?(k="y",N="h",E="minH",S="maxH",R="innerH",T="top",A="bottom",B="deltaH",L="contentH",I="left",M="w",H="x",D="innerW",P="minW",O="maxW",F="right",z="deltaW",W="contentW"):(k="x",N="w",E="minW",S="maxW",R="innerW",T="left",A="right",B="deltaW",L="contentW",I="top",M="h",H="y",D="innerH",P="minH",O="maxH",F="bottom",z="deltaH",W="contentH"),u=i[R]-o[T]-o[T],_=d=0,t=0,n=r.length;n>t;t++)p=r[t],m=p.layoutRect(),h=p.settings,g=h.flex,u-=n-1>t?c:0,g>0&&(d+=g,m[S]&&v.push(p),m.flex=g),u-=m[E],y=o[I]+m[P]+o[F],y>_&&(_=y);if(x={},x[E]=0>u?i[E]-u+i[B]:i[R]-u+i[B],x[P]=_+i[z],x[L]=i[R]-u,x[W]=_,x.minW=U(x.minW,i.maxW),x.minH=U(x.minH,i.maxH),x.minW=V(x.minW,i.startMinWidth),x.minH=V(x.minH,i.startMinHeight),!i.autoResize||x.minW==i.minW&&x.minH==i.minH){for(C=u/d,t=0,n=v.length;n>t;t++)p=v[t],m=p.layoutRect(),b=m[S],y=m[E]+m.flex*C,y>b?(u-=m[S]-m[E],d-=m.flex,m.flex=0,m.maxFlexSize=b):m.maxFlexSize=0;for(C=u/d,w=o[T],x={},0===d&&("end"==l?w=u+o[T]:"center"==l?(w=Math.round(i[R]/2-(i[R]-u)/2)+o[T],0>w&&(w=o[T])):"justify"==l&&(w=o[T],c=Math.floor(u/(r.length-1)))),x[H]=o[I],t=0,n=r.length;n>t;t++)p=r[t],m=p.layoutRect(),y=m.maxFlexSize||m[E],"center"===s?x[H]=Math.round(i[D]/2-m[M]/2):"stretch"===s?(x[M]=V(m[P]||0,i[D]-o[I]-o[F]),x[H]=o[I]):"end"===s&&(x[H]=i[D]-m[M]-o.top),m.flex>0&&(y+=m.flex*C),x[N]=y,x[k]=w,p.layoutRect(x),p.recalc&&p.recalc(),w+=y+c}else if(x.w=x.minW,x.h=x.minH,e.layoutRect(x),this.recalc(e),null===e._lastRect){var q=e.parent();q&&(q._lastRect=null,q.recalc())}}})}),r(Lt,[mt],function(e){return e.extend({Defaults:{containerClass:"flow-layout",controlClass:"flow-layout-item",endClass:"break"},recalc:function(e){e.items().filter(":visible").each(function(e){e.recalc&&e.recalc()})}})}),r(Ht,[W,vt,G,f,at,h],function(e,t,n,r,i,o){function a(e){function t(t){function n(e){return e.replace(/%(\w+)/g,"")}var r,i,o=e.dom,a="",l,c;return c=e.settings.preview_styles,c===!1?"":(c||(c="font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius"),(t=e.formatter.get(t))?(t=t[0],r=t.block||t.inline||"span",i=o.create(r),s(t.styles,function(e,t){e=n(e),e&&o.setStyle(i,t,e)}),s(t.attributes,function(e,t){e=n(e),e&&o.setAttrib(i,t,e)}),s(t.classes,function(e){e=n(e),o.hasClass(i,e)||o.addClass(i,e)}),e.fire("PreviewFormats"),o.setStyles(i,{position:"absolute",left:-65535}),e.getBody().appendChild(i),l=o.getStyle(e.getBody(),"fontSize",!0),l=/px$/.test(l)?parseInt(l,10):0,s(c.split(" "),function(t){var n=o.getStyle(i,t,!0);if(!("background-color"==t&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(n)&&(n=o.getStyle(e.getBody(),t,!0),"#ffffff"==o.toHex(n).toLowerCase())||"color"==t&&"#000000"==o.toHex(n).toLowerCase())){if("font-size"==t&&/em|%$/.test(n)){if(0===l)return;n=parseFloat(n,10)/(/%$/.test(n)?100:1),n=n*l+"px"}"border"==t&&n&&(a+="padding:0 2px;"),a+=t+":"+n+";"}}),e.fire("AfterPreviewFormats"),o.remove(i),a):void 0)}function r(t,n){return function(){var r=this;e.on("nodeChange",function(i){var o=e.formatter,a=null;s(i.parents,function(e){return s(t,function(t){return n?o.matchNode(e,n,{value:t.value})&&(a=t.value):o.matchNode(e,t.value)&&(a=t.value),a?!1:void 0}),a?!1:void 0}),r.value(a)})}}function i(e){e=e.split(";");for(var t=e.length;t--;)e[t]=e[t].split("=");return e}function o(){function n(e){var t=[];if(e)return s(e,function(e){var o={text:e.title,icon:e.icon};if(e.items)o.menu=n(e.items);else{var a=e.format||"custom"+r++;e.format||(e.name=a,i.push(e)),o.format=a}t.push(o)}),t}var r=0,i=[],o=[{title:"Headers",items:[{title:"Header 1",format:"h1"},{title:"Header 2",format:"h2"},{title:"Header 3",format:"h3"},{title:"Header 4",format:"h4"},{title:"Header 5",format:"h5"},{title:"Header 6",format:"h6"}]},{title:"Inline",items:[{title:"Bold",icon:"bold",format:"bold"},{title:"Italic",icon:"italic",format:"italic"},{title:"Underline",icon:"underline",format:"underline"},{title:"Strikethrough",icon:"strikethrough",format:"strikethrough"},{title:"Superscript",icon:"superscript",format:"superscript"},{title:"Subscript",icon:"subscript",format:"subscript"},{title:"Code",icon:"code",format:"code"}]},{title:"Blocks",items:[{title:"Paragraph",format:"p"},{title:"Blockquote",format:"blockquote"},{title:"Div",format:"div"},{title:"Pre",format:"pre"}]},{title:"Alignment",items:[{title:"Left",icon:"alignleft",format:"alignleft"},{title:"Center",icon:"aligncenter",format:"aligncenter"},{title:"Right",icon:"alignright",format:"alignright"},{title:"Justify",icon:"alignjustify",format:"alignjustify"}]}];e.on("init",function(){s(i,function(t){e.formatter.register(t.name,t)})});var a=n(e.settings.style_formats||o);return a={type:"menu",items:a,onPostRender:function(t){e.fire("renderFormatsMenu",{control:t.control})},itemDefaults:{preview:!0,textStyle:function(){return this.settings.format?t(this.settings.format):void 0},onPostRender:function(){var t=this,n=this.settings.format;n&&t.parent().on("show",function(){t.disabled(!e.formatter.canApply(n)),t.active(e.formatter.match(n))})},onclick:function(){this.settings.format&&f(this.settings.format)}}}}function a(){return e.undoManager?e.undoManager.hasUndo():!1}function l(){return e.undoManager?e.undoManager.hasRedo():!1}function c(){var t=this;t.disabled(!a()),e.on("Undo Redo AddUndo TypingUndo",function(){t.disabled(!a())})}function d(){var t=this;t.disabled(!l()),e.on("Undo Redo AddUndo TypingUndo",function(){t.disabled(!l())})}function u(){var t=this;e.on("VisualAid",function(e){t.active(e.hasVisual)}),t.active(e.hasVisual)}function f(t){t.control&&(t=t.control.value()),t&&e.execCommand("mceToggleFormat",!1,t)}var p;p=o(),s({bold:"Bold",italic:"Italic",underline:"Underline",strikethrough:"Strikethrough",subscript:"Subscript",superscript:"Superscript"},function(t,n){e.addButton(n,{tooltip:t,onPostRender:function(){var t=this;e.formatter?e.formatter.formatChanged(n,function(e){t.active(e)}):e.on("init",function(){e.formatter.formatChanged(n,function(e){t.active(e)})})},onclick:function(){f(n)}})}),s({outdent:["Decrease indent","Outdent"],indent:["Increase indent","Indent"],cut:["Cut","Cut"],copy:["Copy","Copy"],paste:["Paste","Paste"],help:["Help","mceHelp"],selectall:["Select all","SelectAll"],hr:["Insert horizontal rule","InsertHorizontalRule"],removeformat:["Clear formatting","RemoveFormat"],visualaid:["Visual aids","mceToggleVisualAid"],newdocument:["New document","mceNewDocument"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1]})}),s({blockquote:["Toggle blockquote","mceBlockQuote"],numlist:["Numbered list","InsertOrderedList"],bullist:["Bullet list","InsertUnorderedList"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],alignleft:["Align left","JustifyLeft"],aligncenter:["Align center","JustifyCenter"],alignright:["Align right","JustifyRight"],alignjustify:["Justify","JustifyFull"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1],onPostRender:function(){var t=this;e.formatter?e.formatter.formatChanged(n,function(e){t.active(e)}):e.on("init",function(){e.formatter.formatChanged(n,function(e){t.active(e)})})}})}),e.addButton("undo",{tooltip:"Undo",onPostRender:c,cmd:"undo"}),e.addButton("redo",{tooltip:"Redo",onPostRender:d,cmd:"redo"}),e.addMenuItem("newdocument",{text:"New document",shortcut:"Ctrl+N",icon:"newdocument",cmd:"mceNewDocument"}),e.addMenuItem("undo",{text:"Undo",icon:"undo",shortcut:"Ctrl+Z",onPostRender:c,cmd:"undo"}),e.addMenuItem("redo",{text:"Redo",icon:"redo",shortcut:"Ctrl+Y",onPostRender:d,cmd:"redo"}),e.addMenuItem("visualaid",{text:"Visual aids",selectable:!0,onPostRender:u,cmd:"mceToggleVisualAid"}),s({cut:["Cut","Cut","Ctrl+X"],copy:["Copy","Copy","Ctrl+C"],paste:["Paste","Paste","Ctrl+V"],selectall:["Select all","SelectAll","Ctrl+A"],bold:["Bold","Bold","Ctrl+B"],italic:["Italic","Italic","Ctrl+I"],underline:["Underline","Underline"],strikethrough:["Strikethrough","Strikethrough"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],removeformat:["Clear formatting","RemoveFormat"]},function(t,n){e.addMenuItem(n,{text:t[0],icon:n,shortcut:t[2],cmd:t[1]})}),e.on("mousedown",function(){n.hideAll()}),e.addButton("styleselect",{type:"menubutton",text:"Formats",menu:p}),e.addButton("formatselect",function(){var n=[],o=i(e.settings.block_formats||"Paragraph=p;Address=address;Pre=pre;Header 1=h1;Header 2=h2;Header 3=h3;Header 4=h4;Header 5=h5;Header 6=h6");return s(o,function(e){n.push({text:e[0],value:e[1],textStyle:function(){return t(e[1])}})}),{type:"listbox",text:o[0][0],values:n,fixedWidth:!0,onselect:f,onPostRender:r(n)}}),e.addButton("fontselect",function(){var t="Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",n=[],o=i(e.settings.font_formats||t);return s(o,function(e){n.push({text:{raw:e[0]},value:e[1],textStyle:-1==e[1].indexOf("dings")?"font-family:"+e[1]:""})}),{type:"listbox",text:"Font Family",tooltip:"Font Family",values:n,fixedWidth:!0,onPostRender:r(n,"fontname"),onselect:function(t){t.control.settings.value&&e.execCommand("FontName",!1,t.control.settings.value)}}}),e.addButton("fontsizeselect",function(){var t=[],n="8pt 10pt 12pt 14pt 18pt 24pt 36pt",i=e.settings.fontsize_formats||n;return s(i.split(" "),function(e){t.push({text:e,value:e})}),{type:"listbox",text:"Font Sizes",tooltip:"Font Sizes",values:t,fixedWidth:!0,onPostRender:r(t,"fontsize"),onclick:function(t){t.control.settings.value&&e.execCommand("FontSize",!1,t.control.settings.value)}}}),e.addMenuItem("formats",{text:"Formats",menu:p})}var s=r.each;i.on("AddEditor",function(t){t.editor.rtl&&(e.rtl=!0),a(t.editor)}),e.translate=function(e){return i.translate(e)},t.tooltips=!o.iOS}),r(Dt,[ht],function(e){return e.extend({recalc:function(e){var t=e.settings,n,r,i,o,a,s,l,c,d,u,f,p,m,h,g,v,y,b,C,x,w,_,N=[],E=[],k,S,T,R,A,B;for(t=e.settings,i=e.items().filter(":visible"),o=e.layoutRect(),r=t.columns||Math.ceil(Math.sqrt(i.length)),n=Math.ceil(i.length/r),y=t.spacingH||t.spacing||0,b=t.spacingV||t.spacing||0,C=t.alignH||t.align,x=t.alignV||t.align,g=e._paddingBox,C&&"string"==typeof C&&(C=[C]),x&&"string"==typeof x&&(x=[x]),u=0;r>u;u++)N.push(0);for(f=0;n>f;f++)E.push(0);for(f=0;n>f;f++)for(u=0;r>u&&(d=i[f*r+u],d);u++)c=d.layoutRect(),k=c.minW,S=c.minH,N[u]=k>N[u]?k:N[u],E[f]=S>E[f]?S:E[f];for(A=o.innerW-g.left-g.right,w=0,u=0;r>u;u++)w+=N[u]+(u>0?y:0),A-=(u>0?y:0)+N[u];for(B=o.innerH-g.top-g.bottom,_=0,f=0;n>f;f++)_+=E[f]+(f>0?b:0),B-=(f>0?b:0)+E[f];if(w+=g.left+g.right,_+=g.top+g.bottom,l={},l.minW=w+(o.w-o.innerW),l.minH=_+(o.h-o.innerH),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH,l.minW=Math.min(l.minW,o.maxW),l.minH=Math.min(l.minH,o.maxH),l.minW=Math.max(l.minW,o.startMinWidth),l.minH=Math.max(l.minH,o.startMinHeight),!o.autoResize||l.minW==o.minW&&l.minH==o.minH){o.autoResize&&(l=e.layoutRect(l),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH);var L;L="start"==t.packV?0:B>0?Math.floor(B/n):0;var H=0,D=t.flexWidths;if(D)for(u=0;uu;u++)N[u]+=D?D[u]*M:M;for(m=g.top,f=0;n>f;f++){for(p=g.left,s=E[f]+L,u=0;r>u&&(d=i[f*r+u],d);u++)h=d.settings,c=d.layoutRect(),a=Math.max(N[u],c.startMinWidth),T=R=0,c.x=p,c.y=m,v=h.alignH||(C?C[u]||C[0]:null),"center"==v?c.x=p+a/2-c.w/2:"right"==v?c.x=p+a-c.w:"stretch"==v&&(c.w=a),v=h.alignV||(x?x[u]||x[0]:null),"center"==v?c.y=m+s/2-c.h/2:"bottom"==v?c.y=m+s-c.h:"stretch"==v&&(c.h=s),d.layoutRect(c),p+=a+y,d.recalc&&d.recalc();m+=s+b}}else if(l.w=l.minW,l.h=l.minH,e.layoutRect(l),this.recalc(e),null===e._lastRect){var P=e.parent();P&&(P._lastRect=null,P.recalc())}}})}),r(Mt,[vt],function(e){return e.extend({renderHtml:function(){var e=this;return e.addClass("iframe"),e.canFocus=!1,''},src:function(e){this.getEl().src=e},html:function(e,t){var n=this,r=this.getEl().contentWindow.document.body;return r?(r.innerHTML=e,t&&t()):setTimeout(function(){n.html(e)},0),this}})}),r(Pt,[vt,z],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t.addClass("widget"),t.addClass("label"),t.canFocus=!1,e.multiline&&t.addClass("autoscroll"),e.strong&&t.addClass("strong")},initLayoutRect:function(){var e=this,n=e._super();if(e.settings.multiline){var r=t.getSize(e.getEl());r.width>n.maxW&&(n.minW=n.maxW,e.addClass("multiline")),e.getEl().style.width=n.minW+"px",n.startMinH=n.h=n.minH=Math.min(n.maxH,t.getSize(e.getEl()).height)}return n},repaint:function(){var e=this;return e.settings.multiline||(e.getEl().style.lineHeight=e.layoutRect().h+"px"),e._super()},text:function(e){var t=this;return t._rendered&&e&&this.innerHtml(t.encode(e)),t._super(e)},renderHtml:function(){var e=this,t=e.settings.forId;return'"}})}),r(Ot,[U,X],function(e,t){return e.extend({Defaults:{role:"toolbar",layout:"flow"},init:function(e){var t=this;t._super(e),t.addClass("toolbar")},postRender:function(){var e=this;return e.items().addClass("toolbar-item"),e.keyNav=new t({root:e,enableLeftRight:!0}),e._super()}})}),r(It,[Ot],function(e){return e.extend({Defaults:{role:"menubar",containerCls:"menubar",defaults:{type:"menubutton"}}})}),r(Ft,[yt,V,It],function(e,t,n){function r(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1}var i=e.extend({init:function(e){var t=this;t._renderOpen=!0,t._super(e),t.addClass("menubtn"),e.fixedWidth&&t.addClass("fixed-width"),t.aria("haspopup",!0),t.hasPopup=!0},showMenu:function(){var e=this,n=e.settings,r;return e.menu&&e.menu.visible()?e.hideMenu():(e.menu||(r=n.menu||[],r.length?r={type:"menu",items:r}:r.type=r.type||"menu",e.menu=t.create(r).parent(e).renderTo(e.getContainerElm()),e.fire("createmenu"),e.menu.reflow(),e.menu.on("cancel",function(t){t.control===e.menu&&e.focus()}),e.menu.on("show hide",function(t){t.control==e.menu&&e.activeMenu("show"==t.type)}).fire("show"),e.aria("expanded",!0)),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),e.menu.moveRel(e.getEl(),e.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"]),void 0)},hideMenu:function(){var e=this;e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide(),e.aria("expanded",!1))},activeMenu:function(e){this.toggleClass("active",e)},renderHtml:function(){var e=this,t=e._id,r=e.classPrefix,i=e.settings.icon?r+"ico "+r+"i-"+e.settings.icon:"";return e.aria("role",e.parent()instanceof n?"menuitem":"button"),'
'},postRender:function(){var e=this;return e.on("click",function(t){t.control===e&&r(t.target,e.getEl())&&(e.showMenu(),t.keyboard&&e.menu.items()[0].focus())}),e.on("mouseenter",function(t){var n=t.control,r=e.parent(),o;n&&r&&n instanceof i&&n.parent()==r&&(r.items().filter("MenuButton").each(function(e){e.hideMenu&&e!=n&&(e.menu&&e.menu.visible()&&(o=!0),e.hideMenu())}),o&&(n.focus(),n.showMenu()))}),e._super()},text:function(e){var t=this,n,r;if(t._rendered)for(r=t.getEl("open").getElementsByTagName("span"),n=0;n'+("-"!==o?' ":"")+("-"!==o?''+o+"":"")+(l?'
'+l+"
":"")+(r.menu?'
':"")+"
"},postRender:function(){var e=this,t=e.settings,n=t.textStyle;if("function"==typeof n&&(n=n.call(this)),n){var r=e.getEl("text");r&&r.setAttribute("style",n)}return e._super()},remove:function(){this._super(),this.menu&&this.menu.remove()}})}),r(Vt,[G,X,Wt,f],function(e,t,n,r){var i=e.extend({Defaults:{defaultType:"menuitem",border:1,layout:"stack",role:"menu"},init:function(e){var i=this;if(e.autohide=!0,e.constrainToViewport=!0,e.itemDefaults)for(var o=e.items,a=o.length;a--;)o[a]=r.extend({},e.itemDefaults,o[a]);i._super(e),i.addClass("menu"),i.keyNav=new t({root:i,enableUpDown:!0,enableLeftRight:!0,leftAction:function(){i.parent()instanceof n&&i.keyNav.cancel()},onCancel:function(){i.fire("cancel",{},!1),i.hide()}})},repaint:function(){return this.toggleClass("menu-align",!0),this._super(),this.getEl().style.height="",this.getEl("body").style.height="",this},cancel:function(){var e=this;e.hideAll(),e.fire("cancel"),e.fire("select")},hideAll:function(){var e=this;return this.find("menuitem").exec("hideMenu"),e._super()},preRender:function(){var e=this;return e.items().each(function(t){var n=t.settings;return n.icon||n.selectable?(e._hasIcons=!0,!1):void 0}),e._super()}});return i}),r(Ut,[Ct],function(e){return e.extend({Defaults:{classes:"radio",role:"radio"}})}),r(qt,[vt,q],function(e,t){return e.extend({renderHtml:function(){var e=this,t=e.classPrefix;return e.addClass("resizehandle"),"both"==e.settings.direction&&e.addClass("resizehandle-both"),e.canFocus=!1,'
'},postRender:function(){var e=this;e._super(),e.resizeDragHelper=new t(this._id,{start:function(){e.fire("ResizeStart")},drag:function(t){"both"!=e.settings.direction&&(t.deltaX=0),e.fire("Resize",t)},end:function(){e.fire("ResizeEnd")}})},remove:function(){return this.resizeDragHelper&&this.resizeDragHelper.destroy(),this._super()}})}),r(jt,[vt],function(e){return e.extend({renderHtml:function(){var e=this;return e.addClass("spacer"),e.canFocus=!1,'
'}})}),r($t,[Ft,z],function(e,t){return e.extend({Defaults:{classes:"widget btn splitbtn",role:"splitbutton"},repaint:function(){var e=this,n=e.getEl(),r=e.layoutRect(),i,o;return e._super(),i=n.firstChild,o=n.lastChild,t.css(i,{width:r.w-t.getSize(o).width,height:r.h-2}),t.css(o,{height:r.h-2}),e},activeMenu:function(e){var n=this;t.toggleClass(n.getEl().lastChild,n.classPrefix+"active",e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon?n+"ico "+n+"i-"+e.settings.icon:"";return'
'},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(e){var n=e.target;if(e.control==this)for(;n;){if("BUTTON"==n.nodeName&&-1==n.className.indexOf("open"))return e.stopImmediatePropagation(),t.call(this,e),void 0;n=n.parentNode}}),delete e.settings.onclick,e._super()}})}),r(Kt,[Lt],function(e){return e.extend({Defaults:{containerClass:"stack-layout",controlClass:"stack-layout-item",endClass:"break"}})}),r(Yt,[$,z],function(e,t){return e.extend({lastIdx:0,Defaults:{layout:"absolute",defaults:{type:"panel"}},activateTab:function(e){this.activeTabId&&t.removeClass(this.getEl(this.activeTabId),this.classPrefix+"active"),this.activeTabId="t"+e,t.addClass(this.getEl("t"+e),this.classPrefix+"active"),e!=this.lastIdx&&(this.items()[this.lastIdx].hide(),this.lastIdx=e),this.items()[e].show().fire("showtab"),this.reflow()},renderHtml:function(){var e=this,t=e._layout,n="",r=e.classPrefix;return e.preRender(),t.preRender(e),e.items().each(function(t,i){n+='
'+e.encode(t.settings.title)+"
"}),'
'+n+'
'+t.renderHtml(e)+"
"},postRender:function(){var e=this;e._super(),e.settings.activeTab=e.settings.activeTab||0,e.activateTab(e.settings.activeTab),this.on("click",function(t){var n=t.target.parentNode;if(t.target.parentNode.id==e._id+"-head")for(var r=n.childNodes.length;r--;)n.childNodes[r]==t.target&&e.activateTab(r)})},initLayoutRect:function(){var e=this,n,r,i;r=t.getSize(e.getEl("head")).width,r=0>r?0:r,i=0,e.items().each(function(t,n){r=Math.max(r,t.layoutRect().minW),i=Math.max(i,t.layoutRect().minH),e.settings.activeTab!=n&&t.hide()}),e.items().each(function(e){e.settings.x=0,e.settings.y=0,e.settings.w=r,e.settings.h=i,e.layoutRect({x:0,y:0,w:r,h:i})});var o=t.getSize(e.getEl("head")).height;return e.settings.minWidth=r,e.settings.minHeight=i+o,n=e._super(),n.deltaH+=o,n.innerH=n.h-n.deltaH,n}})}),r(Gt,[vt,z],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t._value=e.value||"",t.addClass("textbox"),e.multiline?t.addClass("multiline"):t.on("keydown",function(e){13==e.keyCode&&t.parents().reverse().each(function(t){return e.preventDefault(),t.hasEventListeners("submit")&&t.toJSON?(t.fire("submit",{data:t.toJSON()}),!1):void 0})})},disabled:function(e){var t=this;return t._rendered&&"undefined"!=typeof e&&(t.getEl().disabled=e),t._super(e)},value:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t._rendered&&(t.getEl().value=e),t):t._rendered?t.getEl().value:t._value},repaint:function(){var e=this,t,n,r,i=0,o=0,a;t=e.getEl().style,n=e._layoutRect,a=e._lastRepaintRect||{};var s=document;return!e.settings.multiline&&s.all&&(!s.documentMode||s.documentMode<=8)&&(t.lineHeight=n.h-o+"px"),r=e._borderBox,i=r.left+r.right+8,o=r.top+r.bottom+(e.settings.multiline?8:0),n.x!==a.x&&(t.left=n.x+"px",a.x=n.x),n.y!==a.y&&(t.top=n.y+"px",a.y=n.y),n.w!==a.w&&(t.width=n.w-i+"px",a.w=n.w),n.h!==a.h&&(t.height=n.h-o+"px",a.h=n.h),e._lastRepaintRect=a,e.fire("repaint",{},!1),e},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.encode(e._value,!1),i="";return"spellcheck"in n&&(i+=' spellcheck="'+n.spellcheck+'"'),n.maxLength&&(i+=' maxlength="'+n.maxLength+'"'),n.size&&(i+=' size="'+n.size+'"'),n.subtype&&(i+=' type="'+n.subtype+'"'),e.disabled()&&(i+=' disabled="disabled"'),n.multiline?'":'"},postRender:function(){var e=this;return t.on(e.getEl(),"change",function(t){e.fire("change",t)}),e._super()},remove:function(){t.off(this.getEl()),this._super()}})}),r(Xt,[z],function(e){return function(t){var n=this,r;n.show=function(i){return n.hide(),r=!0,window.setTimeout(function(){r&&t.appendChild(e.createFragment('
'))},i||0),n},n.hide=function(){var e=t.lastChild;return e&&-1!=e.className.indexOf("throbber")&&e.parentNode.removeChild(e),r=!1,n}}}),a([l,c,d,u,f,p,m,h,g,v,y,b,C,x,w,_,N,E,k,S,T,R,A,B,L,H,D,M,P,O,I,F,z,W,V,U,q,j,$,K,Y,G,X,J,Q,Z,et,tt,nt,rt,it,ot,at,st,lt,ct,dt,ut,ft,pt,mt,ht,gt,vt,yt,bt,Ct,xt,wt,_t,Nt,Et,kt,St,Tt,Rt,At,Bt,Lt,Ht,Dt,Mt,Pt,Ot,It,Ft,zt,Wt,Vt,Ut,qt,jt,$t,Kt,Yt,Gt,Xt])}(this); \ No newline at end of file diff --git a/extensions/admin/resources/tmpl.js b/app-admin/resources/tmpl.js similarity index 95% rename from extensions/admin/resources/tmpl.js rename to app-admin/resources/tmpl.js index 8c72219d8..b05e2ca44 100644 --- a/extensions/admin/resources/tmpl.js +++ b/app-admin/resources/tmpl.js @@ -20,8 +20,6 @@ "use strict"; var tmpl = function (str, data) { -// alert('got here'); -// app.u.dump("GOT HERE!"); var f = !/[^\w\-\.:]/.test(str) ? tmpl.cache[str] = tmpl.cache[str] || tmpl(tmpl.load(str)) : new Function( @@ -81,12 +79,10 @@ tmpl.helper = ",print=function(s,e){_s+=e&&(s||'')||_e(s);}" + ",include=function(s,d){_s+=tmpl(s,d);}"; if (typeof define === "function" && define.amd) { - app.u.dump("not setting $.tmpl"); define(function () { return tmpl; }); } else { - app.u.dump("SETTING tmpl"); $.tmpl = tmpl; } }(this)); diff --git a/extensions/admin/resources/tmpl.min.js b/app-admin/resources/tmpl.min.js similarity index 100% rename from extensions/admin/resources/tmpl.min.js rename to app-admin/resources/tmpl.min.js diff --git a/app-admin/standard.css b/app-admin/standard.css index 4f528ae6c..1ed231584 100644 --- a/app-admin/standard.css +++ b/app-admin/standard.css @@ -19,9 +19,9 @@ a.file {background:url(/biz/images/trial/file_icon-17x17.png) no-repeat; padding div.zbutton_group {text-align:right;} -/* used in sitebuilder for category picture placeholder. +/* used in sitebuilder for category picture placeholder. */ .navcatThumbnailImagePlaceholder {background:url(images/camera_icon-26x21.gif) no-repeat; text-decoration:none; line-height:21px;} - */ + /* 'link selected' is used where you have a list of links and, once one is clicked, the selected link needs to highlight. An example of this would be in the sitebuilder when a layout or email template has DIV's present */ diff --git a/app-admin/styles.css b/app-admin/styles.css index 54dce4e4e..484326447 100644 --- a/app-admin/styles.css +++ b/app-admin/styles.css @@ -1,3 +1,16 @@ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'),local('PTSans-Regular'), url(fonts/ptsans.woff) format('woff'); + } +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(fonts/ptsans_bold.woff) format('woff'); + } + @font-face { font-family: barcode3of9; src: url('fonts/z3of9.ttf') /* will not work in IE9 w/out eot font file */ @@ -6,7 +19,7 @@ body {line-height: 1;} /* helps to reduce some errant whitespace issues */ body {margin:0; padding:0; background:#f1f1f1; } -body, html {font-size:100%; font-family:Tahoma, Geneva, sans-serif; color:#565656;height:100%; margin:0; padding:0;} /* height is for showLoading on body */ +body, html {font-size:100%; font-family:PT Sans, Tahoma, Geneva, sans-serif; color:#565656;height:100%; margin:0; padding:0;} /* height is for showLoading on body */ img {border:0px;} @@ -40,7 +53,7 @@ class can also be applied to a 1 item per row list. .displayInlineBlock {display:inline-block;} -.alignRight {text-align:right;} +.alignRight, .gridTable th.alignRight {text-align:right;} .alignLeft {text-align:left;} .alignCenter {text-align:center;} @@ -59,6 +72,7 @@ class can also be applied to a 1 item per row list. .minimalMode .hideInMinimalMode {display:none;} .isZoovy .showForZoovyOnly, .isAnyCommerce .showForAnyCommerceOnly {display:inherit;} +.isZoovy option.showForZoovyOnly {display:bloock;} /* otherwise the options go inline */ .conditionMet .conditionalHide {display:block;} .conditionMet span.conditionalHide {display:inline-block;} @@ -75,42 +89,54 @@ class can also be applied to a 1 item per row list. .ui-accordion .ui-accordion-header {padding-left:30px;} -a, .lookLikeLink {cursor:pointer; color:#7398a5;} /* apply to text that has an onClick but needs to look like an href. override ui style which isn't as noticeable. */ +a, .lookLikeLink, .ui-widget-content a {cursor:pointer; color:#7398a5; text-decoration:none; outline: 0;} /* apply to text that has an onClick but needs to look like an href. override ui style which isn't as noticeable. */ + a:hover, .lookLikeLink:hover {text-decoration:underline; color:#000000;} .pointer {cursor:pointer;} /* apply to anything that is clickable via an onClick. */ .opacity50 { - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; /* IE 8 */ -moz-opacity: 0.5; /* Netscape */ -khtml-opacity: 0.5; /* Safari 1.x */ opacity: 0.5; /* Good browsers */ } .width50 {width:50%;} - +.queryMatch {background-color:#f0f4f5;} /* text styling */ - +pre.prettyPre { + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + } .barcode {font-family: barcode3of9 !important;} + + /*section or page header. There should only be one of these per page and it should be at the very top.*/ -h1 {font-size: 1.4em; margin: 0px 0px 15px 0px;} +h1 {font-size: 1.4em; margin: .8em 0px; padding:0; font-weight:bold;} /* used for the heading of section of text blocks each with it's own sub heading. must be followed by 2+ h3's. can be directly followed by a P ONLY if it is introductory text, followed by a series of h3's */ -h2 {font-size: 1.3em; margin: 0px 0px 6px 0px;} +h2 {font-size: 1.3em; margin: .6em 0px; padding:0; font-weight:bold;} /* used for a subsection of a text block. Should be preceded by a h2, though not necessarily immediately. should be followed by a P , TABLE or LIST. */ -h3 {font-size: 1.2em; margin: 0px 0px 3px 0px; font-weight: bold;} +h3, legend {font-size: 1.2em; margin: .5em 0px; font-weight: bold; padding:0;} /* used in lists to denote sections. For instance, to separate DIV's in layouts and emails */ -h4 {font-size: 1.1em; margin: 0px 0px 3px 0px; font-weight: bold;} +h4 {font-size: 1.1em; margin: .4em 0px; font-weight: bold; padding:0;} -h5,h6 {font-size: 1em; margin: 0px 0px 3px 0px; font-weight: bold;} +h5,h6 {font-size: 1em; margin: .3em 0px; font-weight: bold; padding:0;} /* if you want to display a hint or tip, give it the hint class */ +fieldset {margin:0; padding:0; margin-bottom:1em; border:0;} +input.smallInput {max-width:6.2em;} /* will fit six chars plus a decimal. */ + + .hint, .helper {font-size:.75em;} /* NOTE - 'hint' is reserved. change these to help as you come across them */ .small {font-size:.85em;} .lowercase {text-transform:lowercase;} @@ -180,6 +206,7 @@ If less is needed, use increments of 4 .noPadOrMargin {padding:0; margin:0;} .paddingNone {padding:0;} +.borderNone {border:0;} /* @@ -194,13 +221,15 @@ using these shared margins will help make the UI more consistent. .marginRight {margin-right:12px;} .marginTop {margin-top:12px;} .marginBottom {margin-bottom:12px !important;} +.marginTopNone {margin-top:0;} .paddingRight {padding-right:12px;} /* used to create space between horizontally listed spans, among other things */ .stdMargin {margin:12px;} .stdPadding, .ui-widget .stdPadding {padding:12px;} -.smallPadding, .ui-widget .smallPadding {padding:4px !important;} -.ui-widget-header-padding {padding:3px 6px !important;} +.smallPadding, .ui-widget .smallPadding {padding:4px;} +.ui-widget-header {margin-bottom:0;} /* this mostly butts up next to a ui-widget-content and no bottom margin is wanted/necessary. it's applied to a header occassionally */ +.ui-widget-header-padding {padding:3px 6px;} section.marginBottom {margin-bottom:36px;} /* use on a section tag to divide portions of the page. */ .ui-corner-none { @@ -240,6 +269,8 @@ if you want the list responsive, apply the .fluidList class. /* for non-datagrid tables. ex: setup page. */ table.stdCellSpacing {border-spacing: 12px; border-collapse: separate;} td.width1 {width:1%;} +.width20 {width:20%;} +.width75 {width:75%;} /* 201336 -> removed limitations by type so any element could use this class */ /* table.fullWidth, iframe.fullWidth, textarea.fullWidth {width:100%;}*/ @@ -258,7 +289,7 @@ Use this in a table where you want clear separation between rows and cells. This .gridTable tr:nth-child(odd) {background:#ffffff;} .gridTable tr:nth-child(even) {background:#f0f0f0;} -.gridTable tr.ui-state-highlight {background: inherit !important;} +.gridTable tr.ui-state-highlight {background: inherit !important;} /* the important here is important. it overrides some odd/even and other classes. it's used conservatively */ .gridTable tr.ui-state-highlight {background: inherit !important;} .gridTable th, .gridTable .tf {background:#efefef; text-align:left;} @@ -268,8 +299,16 @@ Use this in a table where you want clear separation between rows and cells. This +/* floating panels, used for the setup and utilities landing pages */ - +.floatPanel { + width:100%; + margin:0 0 1% 0; + } +.floatPanel .helper {display:none;} /* condense the panels down to decrease scrolling */ +.floatPanel a {padding:5px 0; display:block;} /* add a little space around each link to accomodate a touch */ +.floatPanel .ui-widget-header h3 {margin:0; } +.floatPanel .ui-widget-header {border-bottom:0;} /* product/customer picker */ /* apply a max height for picker accordion content, but only when it's in a dialog. no constraints needed in the body (in general). */ @@ -313,15 +352,6 @@ li.loadingBG, tr.loadingBG {background:url(images/wait.gif) no-repeat center cen .ui-widget-buttonbar {padding:3px 1px;} /* only 1 px on sides because button margin will add 2px */ .ui-widget-buttonbar button {margin:0 2px;} -.ui-widget fieldset {border:0;} -.ui-widget h1 {font-size:1.6em; color:#000000; font-weight:bold; margin: 0; padding: 0;} /* Used for the page title element */ - -/* used for the wiki header 1 & 2 */ -.ui-widget h2 {font-size:1.4em; font-weight:bold; margin: 0; padding: 0;} -.ui-widget h3, .ui-widget legend {font-size:1.3em; font-weight:bold; margin: 0; padding: 0;} -.ui-widget h4 {font-size:1.2em; font-weight:bold; margin: 0; padding: 0;} -.ui-widget h5 {font-size:1.1em; font-weight:bold; margin: 0; padding: 0;} -.ui-widget h6 {font-size:1em; font-weight:bold; margin: 0; padding: 0;} #headerSearchFrm {float:right;} #headerSearchFrm legend {display:none;} @@ -402,15 +432,11 @@ STICKY TABS -/* two column panel layout. used in reports too. */ +/* two column panel layout. will go to two column @ 768. */ .twoColumn{ - width:48%; - min-height:200px; - float:left; + width:100%; } -.twoColumn.column2 {float:right;} - .twoColumn .placeholder{ background: #ffffff; } @@ -422,8 +448,7 @@ STICKY TABS .nwColumnW {width:60%;} -.width20 {width:20%;} -.width75 {width:75%;} + /* dual-level css menu. used for multipage 'pages' in prodlists (finder) */ @@ -540,11 +565,11 @@ NOTE - the overflow hidden on headerTop and the display inlineblock/width are to .mhTabsContainer .animator {left: 0px; width: 92px; height: 55px; position: absolute; z-index: 10;} .mhTabsContainer .setupTab .animIcon {bottom:0; right:0; height:55px; width:55px;} -.mhTabsContainer .sitesTab .animIcon {width:42px; height:32px; bottom: 10px; right: 6px;} +.mhTabsContainer .sitesTab .animIcon {width:42px; height:32px; bottom: 5px; right: 6px;} .mhTabsContainer .productTab .animIcon {width:45px; height:39px; bottom: 0px; right: 5px;} .mhTabsContainer .ordersTab .animIcon {width:61px; height:42px; bottom: 6px; right: 0px;} .mhTabsContainer .crmTab .animIcon {width:62px; height:36px; bottom: 10px; right: 0px;} -.mhTabsContainer .syndicationTab .animIcon {width:60px; height:39px; bottom: 8px; right: 0px;} +.mhTabsContainer .syndicationTab .animIcon {width:60px; height:39px; bottom: 3px; right: 0px;} .mhTabsContainer .reportsTab .animIcon {width:33px; height:39px; bottom: 10px; right: 6px;} .mhTabsContainer .kpiTab .animIcon {width:41px; height:42px; bottom: 6px; right: 6px;} .mhTabsContainer .utilitiesTab .animIcon {width:53px; height:53px; bottom: 1px; right: 1px;} @@ -612,10 +637,7 @@ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#990000', end #messagesContent .messageDetail {float:right; width:60%; margin-right:3%;} -@media screen and (max-width: 1000px) { -/* changing to 7% keeps list from line-wrapping. */ - .mhTabsContainer li {width:7.5%;} - } + .pageContentContainer {line-height:100%;} /* compensate for the body line-height1 */ @@ -634,7 +656,13 @@ LOGIN and preView */ -#appPreView, #appLogin, #createAccountContainer, #appPasswordRecover {font-size:1.2em; margin: auto; width:500px; position:relative; top:200px} /* top margin F's up FF and body/html 100% height */ +#appLogin {max-width:350px} +#appLogin input.textbox, #appLogin .loginbutton {width:100%; display:block; margin-bottom:6px;} +#appLogin .ui-button {margin-right:0;} + +#appPreView, #createAccountContainer, #appPasswordRecover {width:500px;} /* top margin F's up FF and body/html 100% height */ +#appPreView, #createAccountContainer, #appPasswordRecover, #appLogin {font-size:1.2em; margin: auto; position:relative; top:200px;} + #appLogin label {display:block; text-align:left; margin-bottom:12px;} #appLogin .hint {font-size:14px;} @@ -645,6 +673,16 @@ LOGIN and preView #appLogin .createAccount {border:1px solid #006600; background:#696; color:#ffffff;} +.treatAsthreePLSprite, .threePLSprite {height:30px; width:162px; display:inline-block; margin:4px; text-align:left;} +.threePLSprite {background-image:url(images/third_party_logins-176x276.png); background-repeat:no-repeat;} +.twitter {background-position:0 0;} +.facebook {background-position:0 -48px;} +.linkedin {background-position:0 -93px;} +.yahoo {background-position:0 -141px;} +.openid {background-position:0 -188px;} +.google {background-position:0 -235px;} + + /* @@ -814,7 +852,7 @@ PAGE STYLES /* this was a horrible idea. at some point, these should be removed */ .page section {display:block; padding:0; margin:0 0 24px 0} .page section.displayNone {display:none;} -.page fieldset {border:none; padding:0; margin-bottom:12px;} +.page fieldset {border:none; padding:0;} /* @@ -850,7 +888,7 @@ STYLES FOR SPECIFIC UI LAYOUTS (dualMode, soloMode, slimLeft, etc) h1.dualModeHeader {line-height:35px; height:35px;display:inline-block; margin:0; padding:0; text-indent:12px;} /* the text header */ .dualModeListThead th {text-align:left; padding:2px 4px;} /* the table headers */ -.dualModeListControls {padding:2px 12px; line-height:25px; min-height:25px;} +.dualModeListControls {padding:2px 12px; line-height:25px; min-height:25px;} /* any sort of 'clear' added here messes w/ panels. test. */ .dualModeDetail {float:right; display:none;} /* the container for the detail column. */ @@ -879,22 +917,15 @@ h1.dualModeHeader {line-height:35px; height:35px;display:inline-block; margin:0; .slimLeftNav {float: left; width:20%;} -.slimLeftContentSection {float: right; width:75%;} -.slimLeftContent {min-height:250px;} /* minheight here for showLoading */ - - -.slimLeftNav .roundedList li:first-child { - -moz-border-radius-topleft:8px;-webkit-border-top-left-radius:8px;-khtml-border-top-left-radius:8px;border-top-left-radius:8px; - -moz-border-radius-topright:8px;-webkit-border-top-right-radius:8px;-khtml-border-top-right-radius:8px;border-top-right-radius:8px; - } - -.slimLeftNav .roundedList li:last-child { - -moz-border-radius-bottomleft:8px;-webkit-border-bottom-left-radius:8px;-khtml-border-bottom-left-radius:8px;border-bottom-left-radius:8px; - -moz-border-radius-bottomright:8px;-webkit-border-bottom-right-radius:8px;-khtml-border-bottom-right-radius:8px;border-bottom-right-radius:8px; - } +/* the way accordion is used here, no left/right padding is desired. the padding is added to the inner elements so their focus state can go to the edges */ +.slimLeftNav .ui-accordion-content {padding:.3em 0;} +.slimLeftNav .ui-accordion-content li {padding:.2em 1em;} +.slimLeftContentSection {float: right; width:75%;} +.slimLeftContent {min-height:250px;} /* minheight here for showLoading */ +.slimLeftNav .ui-widget-header {margin:0; border-bottom:0;} .slimLeftNav .roundedList li, .slimLeftNav .paddedList li {margin-bottom:3px; padding:3px 6px;} /* @@ -915,7 +946,7 @@ put the prompt into a span */ -.labelsAsBreaks label, .labelsAsBreaks div.label {display:block; margin-bottom:6px; vertical-align:top; } /* left and right margin should NOT be forced to zero */ +.labelsAsBreaks label, .labelsAsBreaks div.label {display:block; margin-bottom:.4em; vertical-align:top; clear:both; } /* left and right margin should NOT be forced to zero */ .labelsAsBreaks label span:first-of-type {padding-right:12px; display:inline-block; vertical-align:top;} .labelsAsBreaks .subset {margin-left:36px;} @@ -927,16 +958,19 @@ see shipping panel in product editor for example */ .labelsAsBreaks div.label h4 {margin:0; padding-right:24px; float:left; width:160px;} -.labelsAsBreaks div.label label { margin:0 12px 0 0;} +.labelsAsBreaks div.label label, .labelsAsBreaks .prompt { margin-right:12px;} + + /* optional classes to put on same container that has labelsAsBreaks. Will make labels into a column and input into another, horizontally lined up. */ -.alignedLabels label span:first-of-type {width:30%;} +/* first of type was a HORRIBLE idea. started adding 'prompt' so that the first-of-type can be ditched */ +.alignedLabels label span:first-of-type, .alignedLabels .prompt {width:30%;display:inline-block;} .alignedInputs textarea, .alignedInputs input[type=email], .alignedInputs input[type=url], .alignedInputs input[type=password], .alignedInputs input[type=url], -.alignedInputs input[type=text] {width:55%; } /* slighly less than 100% is used for label/input so room for toolTip or linkDoc is available */ +.alignedInputs input[type=text]:not([size]) {width:55%; } /* slighly less than 100% is used for label/input so room for toolTip or linkDoc is available */ .alignedInputs input[type=number], .alignedInputs select {max-width:55%;} /* shrink to fit widest option, but stay under threshold */ @@ -967,36 +1001,36 @@ see shipping panel in product editor for example /* CAMPAIGN MANAGER */ .campaignPlatformIcons span {float:left; margin-right:4px;} -#templateEditor .ToolBar { +.templateEditor .ToolBar { position:relative; z-index:15; } /* this applies clearfix */ -#templateEditor .ToolBar:after { +.templateEditor .ToolBar:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -#wizardForm fieldset div {margin-bottom:12px;} +.wizardForm fieldset div {margin-bottom:12px;} -#templateEditor .templatePreviewContainer {position:relative;} -#templateEditor .device{position:absolute; top:0; left:0;} /* applied to all the 'device' backgrounds. */ +.templateEditor .templatePreviewContainer {position:relative;} +.templateEditor .device{position:absolute; top:0; left:0;} /* applied to all the 'device' backgrounds. */ /* device-specific class added to a 'device' div and also the parent container that holds both the iframe and the .device */ -#templateEditor .device {z-index:10;} -#templateEditor iframe {border:0px; z-index:21; position:relative;} /* in device specific mode, position is changed to absolute. */ +.templateEditor .device {z-index:10;} +.templateEditor iframe {border:0px; z-index:21; position:relative;} /* in device specific mode, position is changed to absolute. */ -#templateEditor .iphone5 .device {background:url(images/devices/iphone5.jpg) no-repeat; height:798px; width:385px;} -#templateEditor .iphone5 .device.landscape {top:-175px; left:180px;} /* correct device image placement */ +.templateEditor .iphone5 .device {background:url(images/devices/iphone5.jpg) no-repeat; height:798px; width:385px;} +.templateEditor .iphone5 .device.landscape {top:-175px; left:180px;} /* correct device image placement */ -#templateEditor .iphone5 iframe.portrait {top:134px; left:33px; position:absolute;} -#templateEditor .iphone5 iframe.landscape {top:60px; left:90px; position:absolute;} +.templateEditor .iphone5 iframe.portrait {top:134px; left:33px; position:absolute;} +.templateEditor .iphone5 iframe.landscape {top:60px; left:90px; position:absolute;} -#templateEditor .templatePreviewContainer div.landscape { +.templateEditor .templatePreviewContainer div.landscape { /* for firefox, safari, chrome, etc. */ -webkit-transform: rotate(-90deg); -moz-transform: rotate(-90deg); @@ -1126,17 +1160,53 @@ wasn't enough css to justify a separate .css file. If this content grows, move t .pageSyndication .market {border:1px solid #ffffff; padding:8px;} .pageSyndication .selectedMarket {border:1px solid #efefef;} + + + +/* batch jobs and manager */ + +.batchTimer:before {content:"Auto update in: "} + + + /* -http://codepad.co/s/7cca38#select -some pad (more or less)specific styles. +NOTIFICATIONS */ -@media screen and (max-width: 800px) { +.notificationDatatableInputs {min-width:40%;} + + +/* this is a phone in landscape mode */ +@media screen and (min-width: 400px) { + .floatPanel .helper { + display:block; + } + } + + +@media screen and (min-width: 760px) { + .floatPanel { + width:31%; + margin:0 1% 1% 1%; + float:left; + box-sizing:border-box; + -moz-box-sizing:border-box; + webkit-box-sizing:border-box; + } + .floatPanel .ui-widget-header h3 {font-size:1.0em;} .twoColumn{ - width:100%; - clear:both; + width:48%; + min-height:200px; + float:left; } - .twoColumn.column2 {clear:both;} - + .twoColumn.column2 {float:right;} + .slimLeftNav {width:30%;} + .slimLeftContentSection {float: right; width:68%;} } + + +@media screen and (max-width: 1024px) { +/* changing to 7% keeps list from line-wrapping. */ + .mhTabsContainer li {width:7.5%;} + } \ No newline at end of file diff --git a/app-analyzer-init.js b/app-analyzer-init.js index 87979f71e..65746172f 100644 --- a/app-analyzer-init.js +++ b/app-analyzer-init.js @@ -12,7 +12,7 @@ app.rq.push(['script',0,'resources/jquery.showloading-v1.0.jt.js']); app.rq.push(['script',0,'resources/jquery.ui.anyplugins.js']); //in zero pass in case product page is first page. -app.rq.push(['script',0,'model.js']); //'validator':function(){return (typeof zoovyModel == 'function') ? true : false;}} +app.rq.push(['script',0,'model.js']); //'validator':function(){return (typeof zModel == 'function') ? true : false;}} app.rq.push(['script',0,'includes.js']); //','validator':function(){return (typeof handlePogs == 'function') ? true : false;}}) app.rq.push(['script',0,'controller.js']); diff --git a/app-analyzer.html b/app-analyzer.html index a09f31eed..b98a49991 100644 --- a/app-analyzer.html +++ b/app-analyzer.html @@ -17,7 +17,7 @@ myCreole; var app = {vars:{ - "release":"201344.a", //increment this with each change. should solve caching issues. format: YYYYMMDDHHMMSS + "release":"201405.a", //increment this with each change. should solve caching issues. format: YYYYMMDDHHMMSS "_clientid":"zmvc" },u:{},rq:[]}; diff --git a/app-analyzer.js b/app-analyzer.js index 95ae1de99..bd7040245 100644 --- a/app-analyzer.js +++ b/app-analyzer.js @@ -88,7 +88,7 @@ $('#tabs-4').append(app.ext.analyzer.u.buildTagsList({'id':'tagList'})); showRootCategories : { onSuccess : function(tagObj) { - app.ext.store_navcats.u.getChildDataOf('.',{'parentID':'categoryTree','callback':'addCatToDom','templateID':'catInfoTemplate','extension':'store_navcats'},'appNavcatDetailMore'); //generate left nav. + app.ext.store_navcats.u.getChildDataOf('.',{'parentID':'categoryTree','callback':'addCatToDom','templateID':'catInfoTemplate','extension':'store_navcats'},'more'); //generate left nav. app.model.dispatchThis(); }, onError : function(responseData,uuid) { @@ -173,7 +173,7 @@ $('#tabs-4').append(app.ext.analyzer.u.buildTagsList({'id':'tagList'})); // app.u.dump(" -> size() = "+$('#'+parentID+' li').size()); //once the parentID has children, the subcats have already been loaded. don't load them twice. if($('#'+parentID+' li').size() == 0) { - app.ext.store_navcats.u.getChildDataOf(path,{'parentID':parentID,'callback':'addCatToDom','templateID':'catInfoTemplate','extension':'store_navcats'},'appNavcatDetailMore'); + app.ext.store_navcats.u.getChildDataOf(path,{'parentID':parentID,'callback':'addCatToDom','templateID':'catInfoTemplate','extension':'store_navcats'},'more'); app.model.dispatchThis(); } }, //showSubcats @@ -188,7 +188,7 @@ $('#tabs-4').append(app.ext.analyzer.u.buildTagsList({'id':'tagList'})); $('#tagList li').removeClass('ui-state-active'); //remove any previously active states from list item choiced. $('#'+tag).addClass('ui-state-active'); //add active state to list item now in focus. $('#tagProdlist').empty().addClass('loadingBG'); //empty results container so new list isn't appended to previous list, if present. - app.ext.store_search.calls.appPublicProductSearch.init({'size':250,'mode':'elastic-native','filter':{'term':{'tags':tag}}},{'callback':'handleElasticResults','extension':'analyzer','datapointer':'appPublicSearch|'+tag,'parentID':'tagProdlist'}); + app.ext.store_search.calls.appPublicProductSearch.init({'size':250,'mode':'elastic-search','filter':{'term':{'tags':tag}}},{'callback':'handleElasticResults','extension':'analyzer','datapointer':'appPublicSearch|'+tag,'parentID':'tagProdlist'}); app.model.dispatchThis(); }, //showItemsTaggedAs diff --git a/app-domainlookup.html b/app-domainlookup.html index c2e64f5eb..33a966946 100644 --- a/app-domainlookup.html +++ b/app-domainlookup.html @@ -26,7 +26,7 @@ var app = {vars:{ /////////////////////////////////\ - "release":"201344.a", ///|> Increment this with each change. model version followed by each deployed update getting a new letter in the alphabet. + "release":"201405.a", ///|> Increment this with each change. model version followed by each deployed update getting a new letter in the alphabet. ////////////////////////////////// "thisSessionIsAdmin": true, "_clientid":"admin", @@ -64,7 +64,7 @@ //instantiate wiki parser. myCreole = new Parse.Simple.Creole(); app.model.addExtensions([{'namespace':'lookup','filename':'app-login/extension.js','callback':'initExtension'}]); - app.u.handleEventDelegation($(document.body)); + _app.u.addEventDelegation($(document.body)); }); diff --git a/app-domainlookup/extension.js b/app-domainlookup/extension.js index eb29a9e7d..811854e8f 100644 --- a/app-domainlookup/extension.js +++ b/app-domainlookup/extension.js @@ -117,7 +117,7 @@ var lookup = function() { else { //kewl. found a match. now show them their logo, a link and a countdown till auto-redirect occurs. if(app.data[rd.datapointer].adminURL) { - window.location = app.data[rd.datapointer].adminURL+"?fromLookup="+app.u.unixNow(); //timestamp is passed so it can be used on landing page to determine if the user bookmarked w/ this param in the url + window.location = app.data[rd.datapointer].adminURL+"?fromLookup="+app.u.epochNow(); //timestamp is passed so it can be used on landing page to determine if the user bookmarked w/ this param in the url } else { $ele.prepend("
We found a match on the domain, but no admin URL. Please contact your provider for assistance.
"); diff --git a/app-quickstart-init.js b/app-quickstart-init.js index 7ae5238a4..2e900f5e9 100644 --- a/app-quickstart-init.js +++ b/app-quickstart-init.js @@ -1,163 +1,183 @@ -var app = app || {vars:{},u:{}}; //make sure app exists. -app.rq = app.rq || []; //ensure array is defined. rq = resource queue. +myApp.rq.push(['script',0,(document.location.protocol == 'file:') ? myApp.vars.testURL+'jsonapi/config.js' : myApp.vars.baseURL+'jsonapi/config.js',function(){ +//in some cases, such as the zoovy UI, zglobals may not be defined. If that's the case, certain vars, such as jqurl, must be passed in via P in initialize: +// myApp.u.dump(" ->>>>>>>>>>>>>>>>>>>>>>>>>>>>> zGlobals is an object"); + myApp.vars.username = zGlobals.appSettings.username.toLowerCase(); //used w/ image URL's. +//need to make sure the secureURL ends in a / always. doesn't seem to always come in that way via zGlobals + myApp.vars.secureURL = zGlobals.appSettings.https_app_url; + myApp.vars.domain = zGlobals.appSettings.sdomain; //passed in ajax requests. + myApp.vars.jqurl = (document.location.protocol === 'file:') ? myApp.vars.testURL+'jsonapi/' : '/jsonapi/'; + }]); //The config.js is dynamically generated. + +myApp.rq.push(['extension',0,'order_create','extensions/checkout/extension.js']); +myApp.rq.push(['extension',0,'cco','extensions/cart_checkout_order.js']); +myApp.rq.push(['extension',0,'store_routing','extensions/store_routing.js']); -app.rq.push(['extension',0,'orderCreate','extensions/checkout/extension.js']); -app.rq.push(['extension',0,'cco','extensions/cart_checkout_order.js']); +myApp.rq.push(['extension',0,'store_prodlist','extensions/store_prodlist.js']); +myApp.rq.push(['extension',0,'store_navcats','extensions/store_navcats.js']); +myApp.rq.push(['extension',0,'store_search','extensions/store_search.js']); +myApp.rq.push(['extension',0,'store_product','extensions/store_product.js']); +myApp.rq.push(['extension',0,'cart_message','extensions/cart_message/extension.js']); +myApp.rq.push(['extension',0,'store_crm','extensions/store_crm.js']); +myApp.rq.push(['extension',0,'store_tracking','extensions/store_tracking.js']); +myApp.rq.push(['extension',0,'quickstart','app-quickstart.js','startMyProgram']); +//myApp.rq.push(['extension',0,'entomologist','extensions/entomologist/extension.js']); +//myApp.rq.push(['extension',0,'tools_animation','extensions/tools_animation.js']); -app.rq.push(['extension',0,'store_prodlist','extensions/store_prodlist.js']); -app.rq.push(['extension',0,'store_navcats','extensions/store_navcats.js']); -app.rq.push(['extension',0,'store_search','extensions/store_search.js']); -app.rq.push(['extension',0,'store_product','extensions/store_product.js']); -app.rq.push(['extension',0,'store_cart','extensions/store_cart.js']); -app.rq.push(['extension',0,'store_crm','extensions/store_crm.js']); -app.rq.push(['extension',0,'myRIA','app-quickstart.js','startMyProgram']); +// 201405 - Deprecated for Universal Analytics +//myApp.rq.push(['extension',1,'google_analytics','extensions/partner_google_analytics.js','startExtension']); -app.rq.push(['extension',0,'entomologist','extensions/entomologist/extension.js']); -app.rq.push(['extension',0,'tools_animation','extensions/tools_animation.js']); +//myApp.rq.push(['extension',1,'tools_ab_testing','extensions/tools_ab_testing.js']); +//myApp.rq.push(['extension',0,'partner_addthis','extensions/partner_addthis.js']); +//myApp.rq.push(['extension',1,'resellerratings_survey','extensions/partner_buysafe_guarantee.js','startExtension']); /// !!! needs testing. +//myApp.rq.push(['extension',1,'buysafe_guarantee','extensions/partner_buysafe_guarantee.js','startExtension']); +//myApp.rq.push(['extension',1,'powerReviews_reviews','extensions/partner_powerreviews_reviews.js','startExtension']); +//myApp.rq.push(['extension',0,'magicToolBox_mzp','extensions/partner_magictoolbox_mzp.js','startExtension']); // (not working yet - ticket in to MTB) -//app.rq.push(['extension',1,'google_analytics','extensions/partner_google_analytics.js','startExtension']); -app.rq.push(['extension',1,'tools_ABtesting','extensions/tools_ABtesting.js']); -//app.rq.push(['extension',0,'partner_addthis','extensions/partner_addthis.js']); -//app.rq.push(['extension',1,'resellerratings_survey','extensions/partner_buysafe_guarantee.js','startExtension']); /// !!! needs testing. -//app.rq.push(['extension',1,'buysafe_guarantee','extensions/partner_buysafe_guarantee.js','startExtension']); -//app.rq.push(['extension',1,'powerReviews_reviews','extensions/partner_powerreviews_reviews.js','startExtension']); -//app.rq.push(['extension',0,'magicToolBox_mzp','extensions/partner_magictoolbox_mzp.js','startExtension']); // (not working yet - ticket in to MTB) -app.rq.push(['script',0,(document.location.protocol == 'file:') ? app.vars.testURL+'jsonapi/config.js' : app.vars.baseURL+'jsonapi/config.js']); //The config.js is dynamically generated. -app.rq.push(['script',0,app.vars.baseURL+'model.js']); //'validator':function(){return (typeof zoovyModel == 'function') ? true : false;}} -app.rq.push(['script',0,app.vars.baseURL+'includes.js']); //','validator':function(){return (typeof handlePogs == 'function') ? true : false;}}) +myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.showloading-v1.0.jt.js']); //used pretty early in process.. +myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.ui.anyplugins.js']); //in zero pass because it's essential to rendering and error handling. +myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/tlc.js']); //in zero pass cuz you can't render a page without it.. +myApp.rq.push(['css',1,myApp.vars.baseURL+'resources/anyplugins.css']); -app.rq.push(['script',0,app.vars.baseURL+'controller.js']); +myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jsonpath.0.8.0.js']); //used pretty early in process.. -app.rq.push(['script',0,app.vars.baseURL+'resources/jquery.showloading-v1.0.jt.js']); //used pretty early in process.. -app.rq.push(['script',0,app.vars.baseURL+'resources/jquery.ui.anyplugins.js']); //in zero pass in case product page is first page. -app.rq.push(['css',1,app.vars.baseURL+'resources/anyplugins.css']); +//once peg is loaded, need to retrieve the grammar file. Order is important there. This will validate the file too. +myApp.u.loadScript(myApp.vars.baseURL+'resources/peg-0.8.0.js',function(){ + myApp.model.getGrammar(myApp.vars.baseURL+"resources/pegjs-grammar-20140203.pegjs"); + }); // ### TODO -> callback on RQ.push wasn't getting executed. investigate. -//add tabs to product data. -//tabs are handled this way because jquery UI tabs REALLY wants an id and this ensures unique id's between product -app.rq.push(['templateFunction','productTemplate','onCompletes',function(P) { - var $context = $(app.u.jqSelector('#',P.parentID)); - var $tabContainer = $( ".tabbedProductContent",$context); - if($tabContainer.length) { - if($tabContainer.data("widget") == 'anytabs'){} //tabs have already been instantiated. no need to be redundant. - else { - $tabContainer.anytabs(); - } - } - else {} //couldn't find the tab to tabificate. - }]); - -//sample of an onDeparts. executed any time a user leaves this page/template type. -//app.rq.push(['templateFunction','homepageTemplate','onDeparts',function(P) {app.u.dump("just left the homepage")}]); +//gets executed from app-admin.html as part of controller init process. +//progress is an object that will get updated as the resources load. /* -app.rq.push(['templateFunction','productTemplate','onCompletes',function(P) { - if(app.data.cartDetail && app.data.cartDetail.ship && app.data.cartDetail.ship.postal) { - app.ext.myRIA.u.fetchTimeInTransit($(app.u.jqSelector('#',P.parentID)),new Array(P.pid)); - } - }]); -*/ - -//group any third party files together (regardless of pass) to make troubleshooting easier. +'passZeroResourcesLength' : [INT], +'passZeroResourcesLoaded' : [INT], +'passZeroTimeout' : null //the timeout instance running within loadResources that updates this object. it will run indef unless clearTimeout run here OR all resources are loaded. - -/* -This function is overwritten once the controller is instantiated. -Having a placeholder allows us to always reference the same messaging function, but not impede load time with a bulky error function. */ -app.u.throwMessage = function(m) { - alert(m); - } - -app.u.howManyPassZeroResourcesAreLoaded = function(debug) { - var L = app.vars.rq.length; - var r = 0; //what is returned. total # of scripts that have finished loading. - for(var i = 0; i < L; i++) { - if(app.vars.rq[i][app.vars.rq[i].length - 1] === true) { - r++; +myApp.u.showProgress = function(progress) { + function showProgress(attempt) { + if(progress.passZeroResourcesLength == progress.passZeroResourcesLoaded) { + //All pass zero resources have loaded. + //the app will handle hiding the loading screen. + myApp.u.appInitComplete(); + } + else if(attempt > 150) { + //hhhhmmm.... something must have gone wrong. + clearTimeout(progress.passZeroTimeout); //end the resource loading timeout. + $('.appMessaging','#appPreView').anymessage({'message':'Init failed to load all the resources within a reasonable number of attempts.','gMessage':true,'persistent':true}); + } + else { + var percentPerInclude = (100 / progress.passZeroResourcesLength); + var percentComplete = Math.round(progress.passZeroResourcesLength * percentPerInclude); //used to sum how many includes have successfully loaded. +// dump(" -> percentPerInclude: "+percentPerInclude+" and percentComplete: "+percentComplete); + $('#appPreViewProgressBar').val(percentComplete); + $('#appPreViewProgressText').empty().append(percentComplete+"% Complete"); + attempt++; + setTimeout(function(){showProgress(attempt);},250); } - if(debug) {app.u.dump(" -> "+i+": "+app.vars.rq[i][2]+": "+app.vars.rq[i][app.vars.rq[i].length -1]);} } - return r; + showProgress(0) } -//gets executed once controller.js is loaded. -//check dependencies and make sure all other .js files are done, then init controller. -//function will get re-executed if not all the scripts in app.vars.scripts pass 1 are done loading. -//the 'attempts' var is incremented each time the function is executed. - -app.u.initMVC = function(attempts){ -// app.u.dump("app.u.initMVC activated ["+attempts+"]"); - var includesAreDone = true, - percentPerInclude = (100 / app.vars.rq.length), //what percentage of completion a single include represents (if 10 includes, each is 10%). - resourcesLoaded = app.u.howManyPassZeroResourcesAreLoaded(), - percentComplete = Math.round(resourcesLoaded * percentPerInclude); //used to sum how many includes have successfully loaded. - -//make sure precentage is never over 100 - if(percentComplete > 100 ) { - percentComplete = 100; - } - - $('#appPreViewProgressBar','#appPreView').val(percentComplete); - $('#appPreViewProgressText','#appPreView').empty().append(percentComplete+"% Complete"); - - if(resourcesLoaded == app.vars.rq.length) { - var clickToLoad = false; - if(clickToLoad){ - $('#loader').fadeOut(1000); - $('#clickToLoad').delay(1000).fadeIn(1000).click(function() { - app.u.loadApp(); +//Any code that needs to be executed after the app init has occured can go here. +//will pass in the page info object. (pageType, templateID, pid/navcat/show and more) +myApp.u.appInitComplete = function() { +// myApp.u.dump("Executing myAppIsLoaded code..."); + + myApp.ext.order_create.checkoutCompletes.push(function(vars,$checkout){ + dump(" -> begin checkoutCOmpletes code: "); dump(vars); + + var cartContentsAsLinks = encodeURIComponent(myApp.ext.cco.u.cartContentsAsLinks(myApp.data[vars.datapointer].order)); + +//append this to + $("[data-app-role='thirdPartyContainer']",$checkout).append("

What next?

"); + $('.ocmTwitterComment',$checkout).click(function(){ + window.open('http://twitter.com/home?status='+cartContentsAsLinks,'twitter'); + window[myApp.vars.analyticsPointer]('send', 'event','Checkout','User Event','Tweeted about order'); }); - } else { - app.u.loadApp(); + //the fb code only works if an appID is set, so don't show banner if not present. + if(myApp.u.thisNestedExists("zGlobals.thirdParty.facebook.appId") && typeof FB == 'object') { + $('.ocmFacebookComment',$checkout).click(function(){ + myApp.ext.quickstart.thirdParty.fb.postToWall(cartContentsAsLinks); + _gaq.push(['_trackEvent','Checkout','User Event','FB message about order']); + window[myApp.vars.analyticsPointer]('send', 'event','Checkout','User Event','FB message about order'); + }); } - } -// *** 201324 -> increase # of attempts to reduce pre-timeout error reporting. will help to load app on slow connection/computer. - else if(attempts > 250) { - app.u.dump("WARNING! something went wrong in init.js"); - //this is 10 seconds of trying. something isn't going well. - $('#appPreView').empty().append("

Uh Oh. Something seems to have gone wrong.

Several attempts were made to load the store but some necessary files were not found or could not load. We apologize for the inconvenience. Please try 'refresh' and see if that helps.
If the error persists, please contact the site administrator
- dev: see console.

"); - app.u.howManyPassZeroResourcesAreLoaded(true); - } - else { - setTimeout("app.u.initMVC("+(attempts+1)+")",250); - } - - } + else {$('.ocmFacebookComment').hide()} + }); + + //Cart Messaging Responses. + myApp.cmr.push(['chat.join',function(message){ + if(message.FROM == 'ADMIN') { + var $ui = myApp.ext.quickstart.a.showBuyerCMUI(); + $("[data-app-role='messageInput']",$ui).show(); + $("[data-app-role='messageHistory']",$ui).append("

"+message.FROM+" has joined the chat.<\/p>"); + $('.show4ActiveChat',$ui).show(); + $('.hide4ActiveChat',$ui).hide(); + } + }]); + + myApp.cmr.push(['goto',function(message,$context){ + var $history = $("[data-app-role='messageHistory']",$context); + $P = $("

") + .addClass('chat_post') + .append(""+message.FROM+"<\/span> has sent over a "+(message.vars.pageType || "")+" link for you within this store. Click here<\/span> to view.") + .on('click',function(){ + showContent(myApp.ext.quickstart.u.whatAmIFor(message.vars),message.vars); + }); + $history.append($P); + $history.parent().scrollTop($history.height()); + }]); -app.u.loadApp = function() { -//instantiate controller. handles all logic and communication between model and view. -//passing in app will extend app so all previously declared functions will exist in addition to all the built in functions. -//tmp is a throw away variable. app is what should be used as is referenced within the mvc. - app.vars.rq = null; //to get here, all these resources have been loaded. nuke record to keep DOM clean and avoid any duplication. - var tmp = new zController(app); -//instantiate wiki parser. - myCreole = new Parse.Simple.Creole(); } -//Any code that needs to be executed after the app init has occured can go here. -//will pass in the page info object. (pageType, templateID, pid/navcat/show and more) -app.u.appInitComplete = function(P) { - app.u.dump("Executing myAppIsLoaded code..."); - } - -//don't execute script till both jquery AND the dom are ready. -$(document).ready(function(){ - app.u.handleRQ(0) +//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page. +//it'll also handle the old 'meta' uri params. +//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page. +//it'll also handle the old 'meta' uri params. +myApp.router.appendInit({ + 'type':'function', + 'route': function(v){ + return {'init':true} //returning anything but false triggers a match. + }, + 'callback':function(f,g){ + dump(" -> triggered callback for appendInit"); + g = g || {}; + if(g.uriParams.seoRequest){ + showContent(g.uriParams.pageType, g.uriParams); + } + else if (g.uriParams.marketplace){ + showContent("product",{"pid":g.uriParams.product}); + } + else if(document.location.hash) { + myApp.u.dump('triggering handleHash'); + myApp.router.handleHashChange(); + } + else { + //IE8 didn't like the shortcut to showContent here. + myApp.ext.quickstart.a.showContent('homepage'); + } + if(g.uriParams && g.uriParams.meta) { + myApp.ext.cco.calls.cartSet.init({'want/refer':infoObj.uriParams.meta,'cartID':_app.model.fetchCartID()},{},'passive'); + } + if(g.uriParams && g.uriParams.meta_src) { + myApp.ext.cco.calls.cartSet.init({'want/refer_src':infoObj.uriParams.meta_src,'cartID':_app.model.fetchCartID()},{},'passive'); + } + } }); - diff --git a/app-quickstart.css b/app-quickstart.css index 69c6b8765..9abf9b047 100644 --- a/app-quickstart.css +++ b/app-quickstart.css @@ -1,9 +1,28 @@ -body,html {font-size:100%;} +@charset "utf-8"; + +/* + +The css in this file is optimized for a mobile device, then uses media queries to tailor the experience for larger browsers. +That way, the mobile device (which typically has less power) can skip all the heavy lifting of dealing w/ the media queries. +The media queries are located at the bottom of this file. + +*/ + +body,html {font-size:85%;} /* increased for non mobile devices w/ a media query */ #appTemplates {display:none;} /* container for all templates. should be hidden */ -#appPreView {width:550px; margin:0 auto;} +#appPreView {width:50%; max-width:550px; margin:0 auto;} +section {display:block;} + +/* +*** 201338 -> here to fix a bug in jqueryUI. the dialogs, when attempting to move, would jump away from the cursor in FF. This fixed it. +Put this high in the doc as a reminder to occassionally re-check if it can be removed +*/ +.ui-dialog { + position: fixed; + } /* loading class. add class to your templates if you want a loading graphic to appear while data is requested. add only to the parent element. @@ -15,11 +34,18 @@ note - background- are use instead of background in case element this is applied li.loadingBG, .wait {background:url(wait.gif) no-repeat top center !important; min-height:20px !important; min-width:20px;} span.wait {display:inline-block;} -/******* global styles - added for cross-browser uniformity or usability ******/ +/* global styles - added for cross-browser uniformity or usability */ img {border:0; vertical-align: top; display:inline-block;} /* vertical-align: top; removes the whitespace sometimes added under an image. */ -button {display:inline-block; margin: 0; padding: 0; cursor:pointer !important;} -p {margin-bottom:12px;} +a:focus { outline: none; } /* disable the outline around links. it's unattactive */ +a.blockLink {text-decoration:none; cursor:pointer;} /* used for #! anchors. IE needs the cursor defined or it shows as an arrow instead of a hand. */ + +button {display:inline-block; margin: 0; padding: 0; cursor:pointer;} +/* for small buttons */ +.smallButton .ui-button-text {line-height:normal; font-size:.75em;} /* don't mess with padding. will effect icon buttons */ +.smallButton .ui-button-text-icon-primary .ui-button-icon-primary {left:.25em} + +p {margin-bottom:1em;} table { @@ -33,7 +59,20 @@ td.valignMiddle {vertical-align: middle;} /* feel free to delete these or override in your own .css file */ h1, h2, h3, h4, h5, h6 {padding:0; margin:0;} -p {margin:0 0 12px 0;} + +/* some optional form styling + w/ alignedForm class around it on form, fieldset, whatever + */ +.alignedForm label {display:block; clear:both; margin:0 0 .2em 0; padding:0; vertical-align:top;} /* remove padding/margin to ensure cross-browser consistency */ +.alignedForm label:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; + } +.alignedForm .prompt {text-align:right; float:left; width:35%; display:block; margin-right:2%;} +.alignedForm .alignInput {width:55%; float:right;} /* not enforcing width is common enough that it justifies using a class to enforce it. */ /* chrome and safari add an outer border/glow to the input in focus. this removes it. */ input:focus { @@ -41,11 +80,9 @@ input:focus { } input.numberInput {width:50px} - +label span.prompt {display:inline-block; width:20%; margin-right:2em; vertical-align:top;} button:focus {outline:none;} -.zform_number {width:50px;} - /* classes used on menus that are toggled on/off. wrap offMenu around the default buttons and onMenu around buttons that get turned on. for example, in /customer/myaccount, a 'change' button is displayed (wrapped in offMenu) for each address. onClick, 'onMenu' is toggled on, revealing save and cancel @@ -64,7 +101,7 @@ and offMenu is toggle off, hiding the change button. -/******* positioning *******/ +/* positioning */ .floatLeft {float:left;} .floatRight {float:right;} @@ -77,7 +114,7 @@ and offMenu is toggle off, hiding the change button. .center {margin:0 auto;} -/****** aesthetics/usability ******/ +/* aesthetics/usability */ /* added to buttons (such as place order) when they're disabled to clearly indicate they should not be clicked again. */ .disabled { @@ -111,13 +148,15 @@ and offMenu is toggle off, hiding the change button. -.marginLeft {margin-left:12px;} -.marginRight {margin-right:12px;} -.marginTop {margin-top:12px;} -.marginBottom {margin-bottom:12px;} -.stdMargin {margin:12px;} -.headerPadding {padding: 3px 6px;} /* for use in headings or legends that use the ui-state classes and need a little padding within. */ -.stdPadding {padding:12px;} +.marginLeft {margin-left:1em;} +.marginRight {margin-right:1em;} +.marginTop {margin-top:1em;} +.marginBottom {margin-bottom:1em;} + +.stdMargin {margin:1em;} +.headerPadding {padding: .2em .4em;} /* for use in headings or legends that use the ui-state classes and need a little padding within. */ +.stdPadding {padding:1em;} +.smallPadding {padding:.5em;} .fullWidth {width:100%;} @@ -130,46 +169,18 @@ and offMenu is toggle off, hiding the change button. .buyerLoggedIn .hideIfLoggedOut {display: block;} /* may be 'block' */ .buyerLoggedIn span.hideIfLoggedOut, .buyerLoggedIn a.hideIfLoggedOut {display: inline;} /* ensures inline on span elements */ - - - - -/****** APP specific styles ******/ - - -/* messaging css. some error css is defined in the jqueryui styles */ - -.appMessage P {padding:0; margin:0;} /* used in app messaging for warnings, alerts, successes, etc */ -.zMessage {margin:6px; 0} - -.appMessage {margin-bottom:12px; position:relative;} -.appMessage .stdMargin {padding:5px;} -.appMessage .ui-button {position:absolute; top:-3px; right:-3px; z-index:100;} -.appMessage .ui-icon {float:left; margin-right:12px;} - -/* some messages have a red bg. add a white circle around the icon in these cases. */ -.ui-state-z-ise .ui-icon, .ui-state-z-error .ui-icon, .ui-state-z-debug .ui-icon { - background-color:#ffffff; - -webkit-border-radius: 4px; - border-radius: 4px; - } - -.appMessage .appMessageTxt {float:left;} - -.ui-state-success, .ui-state-statusupdate {border:1px solid #aecdae !important; background:#e3f6e3 !important; color:#333333 !important;} -.ui-state-warning {border:1px solid #f58d48 !important; background:#ffdfc9 !important; color:#333333 !important;} - +.hint {font-weight:normal; font-size:.8em;} /* used in order history and faq (possibly other places) in a format similar to an accordian, but more than one panel can be open. */ -.appAccordianesque .ui-accordion-header {padding:3px 24px;} +.appAccordianesque .ui-accordion-header {padding:.5em 2em;} /* pages like company and/or customer are in a two column format. by default, a narrow right w/ nav and the main column w/ content. */ .mainColumn {width:75%;} -.sideline {float:right; width:20%; margin:0 0 24px 0px;} -.sideline a {padding:5px 0; text-decoration:none; display:block;} /* recommend at least 5px vert padding for mobile/pad */ +.sideline {float:right; width:20%; margin:0 0 2em 0;} +.sideline a {padding:.3em 0; text-decoration:none; display:block;} /* recommend at least 5px vert padding for mobile/pad */ @@ -182,25 +193,26 @@ and offMenu is toggle off, hiding the change button. -/*************************************************** +/* LISTS (product list and/or subcategory list) these get used just about everywhere. leave these fairly generic and override using classes or id's as needed. -***************************************************/ +*/ +a.blockLink {border:none; display:block;} .listStyleNone, .listStyleNone li {list-style:none;} /* apply to a ul or ol */ .noPadOrMargin {padding:0; margin:0;} -.fluidList li {float:left; margin:12px; padding:0; display:inline-block;} +.fluidList li {float:left; margin:1em; padding:0; display:inline-block;} .quickView {position:absolute; top:5px; right:5px; z-index:1001;} /* jqui modal has zindex 1002 */ /* over rides - height and width ensure each row is the same height. percentages could be used for width */ .productList > li {width:150px; height:250px; position:relative;} -.lineItemProdlist > li {position:relative; display:block; padding:12px 0; width:100% !important; height:auto !important; border-bottom:1px dotted #efefef;} /* single column product list - used in cart, checkout, etc. productList class is also defined in these cases. */ +.lineItemProdlist > li {position:relative; display:block; padding:1em 0; float:none; width:auto; height:auto !important; border-bottom:1px dotted #efefef;} /* single column product list - used in cart, checkout, etc. productList class is also defined in these cases. */ -.lineItemProdlist .prodThumb {margin-right:12px;} +.lineItemProdlist .prodThumb {margin-right:1em;} .categoryList > li {width:150px; height:200px;} @@ -215,10 +227,7 @@ and override using classes or id's as needed. /* multpage header for lists (product list) - most styling handled by jqueryUI */ -.mpControls {padding:2px 6px;} - - - +.mpControls {padding:.3em .8em;} /* used for the picture slider mouse over effect in some product lists */ @@ -232,25 +241,25 @@ and override using classes or id's as needed. /* for variations */ -.variation {margin-bottom:6px;} /* class applied to div containing a variation group */ -.pogType_radio span label {display:block; margin-bottom:4px; margin-left:12px;} +.variation {margin-bottom:.5em;} /* class applied to div containing a variation group */ +.variation_radio span label {display:block; margin-bottom:.5em; margin-left:1em;} -/*************************************************** +/* PRODUCT DETAIL PAGE (productTemplate) -***************************************************/ +*/ .prodViewerContainer {width:100%;} -.breadAndAddThisContainer {margin-bottom:8px; padding-bottom:8px; border-bottom:1px dotted #b6b6b6;} +.breadAndAddThisContainer {margin-bottom:.5em; padding-bottom:.5em; border-bottom:1px dotted #b6b6b6;} /* primary image and thumbnails */ -.imageContainer {width:10%; padding-right:24px;} -.prodViewerContainer .prodThumbs div {float:left; margin:12px 12px 0 0;} +.imageContainer {width:10%; padding-right:2em;} +.prodViewerContainer .prodThumbs div {float:left; margin:1em 1em 0 0;} .prodSummaryContainer {width:90%;} @@ -262,20 +271,20 @@ PRODUCT DETAIL PAGE (productTemplate) the child list and loading graphic should only show up IF the product is a parent. so the displayNone class is used, then a .grpType_PARENT class is added if the item is a parent. */ -.grpType_PARENT {display:block; margin-bottom:12px;} +.grpType_PARENT {display:block; margin-bottom:1em;} #prodlistChildren li {width:75px; height:120px; overflow:hidden; margin-left:0;} -.prodViewerAddToCartForm {margin-bottom:24px;} -.prodViewerAddToCartForm fieldset {margin:0 0 12px 0; padding:0;} -.variation > label:after {content:":"; padding-right:12px;} /* applies to first label in a group. so no impact on radio labels */ +.prodViewerAddToCartForm {margin-bottom:2em;} +.prodViewerAddToCartForm fieldset {margin-bottom: 1em; padding:0;} +.variation > label:after {content:":"; padding-right:1em;} /* applies to first label in a group. so no impact on radio labels */ -.CRMButtonMenu {margin:0; padding:0; margin-bottom:12px;} +.CRMButtonMenu {margin:0; padding:0; margin-bottom:1em;} -.pogType_attribs {display:none;} /* don't show finder attributes */ +.variation_attribs {display:none;} /* don't show finder attributes */ -/****** REVIEW GFX - used for review summary and in list of reviews on product detail page ******/ +/* REVIEW GFX - used for review summary and in list of reviews on product detail page */ -.reviewSummaryContainer .numReviews {line-height:21px; display:inline-block; height:21px; float:left; margin-left:4px; padding-right:6px;} +.reviewSummaryContainer .numReviews {line-height:21px; display:inline-block; height:21px; float:left; margin-left:.5em; padding-right:.5em;} .reviewSummaryContainer .numReviews:after {content:": "} .reviewSprite {background: url(qs_reviews_stars-124x324.png) no-repeat; width:124px; height:22px; display:none;} /* display none hides the reviews for the 'zero' reviews graphic */ @@ -294,103 +303,97 @@ so the displayNone class is used, then a .grpType_PARENT class is added if the i .prodlist .review_0 {display:none;} /* hide the stars for items with no reviews */ -/****** REVIEW LIST - on product detail page, used for product reviews. ******/ +/* REVIEW LIST - on product detail page, used for product reviews. */ #prodViewerReviews {margin:0; padding:0;} /* parent ul containing all reviews, each review as an li */ -.reviewLineItem {margin:0 0 12px 0; padding:0 0 12px 0; display:block; clear:both; border-bottom:1px #cccccc dotted;} /* on the li of an individual review */ -.prodReviewInfo {float:left; display:block; width:165px; list-style:none; margin:0 12px 0px 0; font-weight:normal; padding:0;} /* on the ul of the list containing the name, location, date, etc */ +.reviewLineItem {margin:0 0 1em 0; padding:0 0 1em 0; display:block; clear:both; border-bottom:1px #cccccc dotted;} /* on the li of an individual review */ +.prodReviewInfo {float:left; display:block; width:165px; list-style:none; margin:0 1em 0px 0; font-weight:normal; padding:0;} /* on the ul of the list containing the name, location, date, etc */ .prodReviewInfo li {display:block; clear:both;} /* applies to li for location, name, date, etc */ .prodReviewTemplate li p {font-weight:normal; margin:0; padding:0;} .reviewLineItem blockquote {margin:0 0 0 185px; padding:0;} -/****** WRITE REVIEW MODAL ******/ -#reviewFrm label {display:block; text-align:right; float:left; width:150px;} -#reviewsMessage {width:250px; height:250px;} -#reviewFrm input, #reviewFrm textarea, #reviewFrm select {margin-bottom:5px;} -#reviewFrm .ui-button {float:right;} -/*************************************************** + +/* BREADCRUMB -> used on product and category pages -***************************************************/ +*/ -.breadcrumb {margin-bottom:12px;} +.breadcrumb {margin-bottom:1em;} .breadcrumb li {padding:0; margin:0; cursor:pointer; padding-right:10px;} -.breadcrumb li:after {content:" \00BB "; padding-left:10px; font-size:10px; font-weight:bold; color:#999999;} +.breadcrumb li:after {content:" \00BB "; padding-left:1em; font-size:1em; font-weight:bold; color:#999999;} .breadcrumb li:last-child:after {content:"";} .breadcrumb li:last-child a {color:#666666; text-decoration:none; font-weight:bold; cursor:text;} -/*************************************************** +/* cartTemplate -***************************************************/ +*/ .cartContainer {width:100%;} - #mainContentArea_cart .continueShoppingButton {display:none;} /* used in modal cart only */ -/*************************************************** +.cartSummaryTotalsContainer .ui-widget .cartRefreshButton {margin: -4px 0 0 0; float:right;} +/* CUSTOMER PAGES -***************************************************/ - - - - -/****** LOGIN MODAL ******/ -#loginFormForModal fieldset {border:0} -.loginOption fieldset div {margin-bottom:12px;} -.loginOption label {width:120px; text-align:right; display:block; float:left; clear:left;} -.loginOption label:after {margin-right:12px; content:":"} +*/ -/****** NEWSLETTER SUBSCRIBE/ACCOUNT CREATE ******/ -#subscribeFormContainer .userInfo div {margin-bottom:6px;} +/* NEWSLETTER SUBSCRIBE/ACCOUNT CREATE */ +#subscribeFormContainer .userInfo div {margin-bottom:.5em;} #subscribeFormContainer li {list-style:none;} -#subscribeFormContainer .userInfo label, #changePasswordForm label {width:120px; display:inline-block; margin-right:10px;} +#subscribeFormContainer .userInfo label, #changePasswordForm label {width:120px; display:inline-block; margin-right:1em;} .subscribeListItem {display:block; height:30px;} -/****** ORDER HISTORY AND INVOICE ******/ +/* ORDER HISTORY AND INVOICE */ #ordersArticle .ui-accordion-content {padding:.4em} /* reduce padding here to make a little extra room */ #ordersArticle .orderContentsTable {width:100%} - +/* ### TODO -> find where this is used and make it responsive */ #orderInvoiceSoloPage table {width:700px;} .orderContentsProdlistContainer {width:500px;} -.orderContentsProdlistContainer .prodThumbContainer {float:left; margin:0 5px 5px 0;} +.orderContentsProdlistContainer .prodThumbContainer {float:left; margin:0 .5em .5em 0;} + +.invoiceAddressContainer .billAddress, .invoiceAddressContainer .shipAddress {margin-bottom:1em;} +/* MY ACCOUNT */ -/****** MY ACCOUNT ******/ +#buyerAddresses {margin-bottom:1em;} +#buyerAddresses h2 {margin:1em 0; clear:both;} +#buyerAddresses address {margin:0 0px 1em 0; float:left; width:90%; display:block; padding:1em;} -#buyerAddresses {margin-bottom:12px;} -#buyerAddresses h2 {margin:12px 0; clear:both;} -#buyerAddresses address {margin:0 0px 12px 0; float:left; width:90%; display:block; padding:5px;} +/* buyer lists */ +.smallButtonList .ui-button-icon-only {width:1.4em} +.smallButtonList .ui-button-icon-only .ui-button-text {height:1.4em; padding:0;} +.buyerList .prodThumbContainer {position:relative;} -/*************************************************** + +/* SEARCH RESULTS PAGE -***************************************************/ +*/ #mainContentArea_search {position:relative;} -.resultsHeader {position:relative; padding:3px 6px;} +.resultsHeader {position:relative; padding:.3em 1em;} .resultsMenuContainer {position:absolute; top:1px; left:3px;} -.resultsMenuContainer .resultsMenu {margin:3px 12px 0 0px;} /* used for sorting and pagination menus */ +.resultsMenuContainer .resultsMenu {margin:.3em 1em 0 0;} /* used for sorting and pagination menus */ .resultsMenuContainer ul.ui-menu ul {z-index:10000; width:150px;} .resultsHeader .nextPageButton, .resultsHeader .prevPageButton {float:right;} @@ -399,29 +402,21 @@ SEARCH RESULTS PAGE .minimalMode .hideInMinimalMode {display:none;} .minimalMode .searchResultsProduct { - height:120px; width:120px; overflow:hidden; margin:0 5px 5px 0; + height:120px; width:120px; overflow:hidden; margin:0 .5em .5em 0; -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */ -moz-box-sizing: border-box; /* Firefox, other Gecko */ box-sizing: border-box; } -/*************************************************** +/* HELP PAGES -***************************************************/ - -/***** CONTACT US ******/ -#contactForm {float:right; margin: 0 0 12px 12px;} -#contactForm fieldset {border:1px solid #cccccc; padding:10px;} -#contactForm div {margin-bottom:5px} -#contactForm label {width:105px; display:inline-block; margin-right:6px; vertical-align:top; text-align:right;} -#contactForm input, #contactForm textarea {width:145px;} -#contactForm textarea {height:125px;} - +*/ -/**** FAQ *****/ +/* FAQ / +### TODO -> why is this commented out? .faqQuestion:before, .faqAnswer:before {font-size:1.4em; font-weight:bold; padding-right:10px; color:#CCCCCC; display:inline-block;} .faqQuestion:before {content:"Q: ";} .faqAnswer:before {content:"A: ";} @@ -433,53 +428,21 @@ HELP PAGES -/*************************************************** +/* CART +*/ -***************************************************/ - -.cartSummaryTotalsContainer h2 {margin:0; border-top:0; border-left:0; border-right:0; padding:2px 12px; font-size:.8em;} /* header */ -.cartSummaryTotalsContainer .cartSummaryContainer {padding:12px;} -.cartZipCodeContainer, .cartAltButtonsContainer, .cartSummaryContainer {margin-bottom:12px; padding-bottom:12px; border-bottom:1px dotted #efefef;} - -.cartStuffContainer {width:60%; vertical-align:top; padding-right:12px;} -.cartSummaryTotalsContainer {width:40%; padding-left:12px; font-size:.8em;} /* by default, this is the right column */ - -.checkoutButtonsContainer > span {display:block; float:left; margin:0 12px 12px 0;} - -.cartShipMethods, .cartZipCodeContainer, .cartSummary {margin:12px 0;} - -.cartSummaryTotalsContainer h3 {margin:12px 0;} /* shipping methods prompt */ - -.checkoutButton {font-weight:bold !important;} /* probably want to customize this with a graphic or something that stands out much more */ - - - - - - -/*************************************************** - -CHECKOUT - -***************************************************/ - -#paybySupplemental_CREDIT .ui-icon-help {display:inline-block; margin-left:6px;} - - -.paybySupplemental {padding:12px; font-weight:normal; border-top-width:0;} -.paybySupplemental select {margin-right:12px;} - -.addressList address {float:left; margin:0 12px 12px 0;} +.cartStuffContainer {width:100%; margin:0 0 1em 0;} +#cartStuffList {list-style:none; margin:0; padding:0; font-size:.85em;} +#cartStuffList li {display:block; margin:0 0 1em 0;} +.cartButtons {text-align:center;} +.cartButtons .thisButton {display:block; margin-bottom:.5em;} +.cartSummaryTotalsContainer h2 {font-size:.8em;} -.creditCardCVVIcon {display:inline-block !important;} -.checkoutFormContainer input, checkoutFormContainer select {margin:2px 6px 2px 0;} -.checkoutFormContainer input[type='password'] {width:200px;} /* class affects both login password and create account passwords */ -.headerPadding label {padding:2px 6px;} /* Pure CSS3 Multi Level Drop Down Navigation Menu */ /* http://www.bloggermint.com/demos/darknavmenu/# */ @@ -506,7 +469,7 @@ CHECKOUT .ddUlMenu ul li a { float: left; text-decoration:none; - padding:0 12px; + padding:0 1em; cursor:pointer; } @@ -535,5 +498,34 @@ CHECKOUT } +.debug {position:fixed; bottom:0; left:0; right:0; background:#ffffff; color:#000000; border-top:1px solid #666666; padding:.5em;} -.debug {position:fixed; bottom:0; left:0; right:0; background:#ffffff; color:#000000; border-top:1px solid #666666; padding:5px;} \ No newline at end of file + + +/* cart product list */ +@media only screen and (min-width: 400px) { + body,html {font-size:100%;} + } + + + +@media only screen and (min-width: 750px) { + /* invoice address get aligned on the same row now that space allows for it. the container around the addresses will handle the margin now. */ + .invoiceAddressContainer .billAddress, .invoiceAddressContainer .shipAddress {float:left; margin-bottom:0;} + .invoiceAddressContainer .billAddress {margin-right:2em;} + /* shift cart totals to right side */ + .cartSummaryTotalsContainer, .cartStuffContainer {width:49%;} + .cartStuffContainer {float:left;} + .cartSummaryTotalsContainer {float:right;} + .cartButtons .thisButton {float:right; margin:0 0 .4em .4em;} + .cartButtons .continueShoppingSpan {float:left; margin:0;} + + .companyAddress {float:left; margin-right:2em; width:40%;} + .hint {font-weight:normal; font-size:.7em;} + } + +@media only screen and (min-width: 1024px) { + .cartTemplateShippingContainer {float:left; width:48%;} + .cartSummary {float:right; width:48%; text-align:right;} + } + diff --git a/app-quickstart.html b/app-quickstart.html index 654d46782..b8c0c1a7d 100644 --- a/app-quickstart.html +++ b/app-quickstart.html @@ -1,44 +1,56 @@ - + - + +Quickstart + + + + + - - - + + + @@ -114,7 +152,7 @@

One moment please.

@@ -137,6 +175,42 @@

One moment please.

+ + + + +
+
+
+
+
+
+ + +
+ +
+ + +
+
+
+ + + + + + + @@ -152,7 +226,18 @@

One moment please.

--> -
+
+ + + + + + + + + + + -
+
-
    +
      -
        -

        +
          - - - - +
            +
            @@ -204,21 +284,22 @@

            One moment please.

            each of the 'sections' are used to load another template. don't change the id. don't modify the 'data-templateid' unless you are changing template names and updating everywhere appropriate. --> -
            - - +
            + + + - + -

            +

            -

            +

            -
              +
                -
                  +
                    -

                    +

                    @@ -231,19 +312,19 @@

                    @@ -254,30 +335,30 @@

                    -
                  • +
                  • - - -
                    -
                    - + + + +
                    +
                    -
                    +
                    -
                    +
                    - + -
                    + -
                    - - + + +
                    - +
                  • @@ -285,63 +366,53 @@
                    -
                    +
                  • +
                    -
                    - +
                    +
                    -
                    +
                    -
                    +
                    - + -
                    + -
                    -
                    +
                    +
                    - +
                  • -
                  • -
                    - -
                    -
                    - -
                    - - +
                  • +
                    - + - + + -
                    +
                    -
                    +
                    @@ -358,34 +429,35 @@
                    if you change the height and width of this image, change the .minimalMode .searchResultsProduct in qs_styles.css to match --> -
                  • -
                    -
                    - +
                  • +
                    +
                    +
                    -
                    +
                    -
                    +
                    +
                    -
                    more details
                    + more details
                  • -
                  • -
                    -
                    - +
                  • + +
                    +
                    -
                    +
                    -
                    -
                  • -
                    more details
                    +
                    +
                    + more details @@ -414,202 +486,199 @@
                    - - - - - - - - - - - - -
                    - -
                    - -
                    - - -
                    - -
                    - -
                    - -
                    - -
                    - -
                    - -
                    -

                    - -
                    -
                    -
                    -
                    -
                    - -
                    -

                    -
                    - - - - -
                    - - - - - -
                    - - -
                    -
                    - -
                    - -
                    -
                    - - -
                    - -
                    -
                    - -
                    - - -
                    - - - - Write Review | - - Add to Wishlist - - - -
                    - -
                    - - - -
                    -
                    -
                    - -
                    -
                    -
                    - -
                    -
                    +
                    + + + + + + + + + + + + + +
                    + +
                    + +
                    + +
                    + +
                    + +
                    + +
                    + +
                    + +
                    + +
                    +

                    +
                    +
                    +
                    +
                    +
                    -
                    - -
                    - +
                    +

                    +
                    + + + + +
                    + + + + + +
                    + + +
                    +
                    + +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    + + +
                    + + + + Write Review | + + Add to Wishlist + + + +
                    + + +
                    + + +
                    +
                    +
                    + +
                    +
                    + +
                    +
                    +
                    + + +
                    + +
                    + +
                    -
                      +
                        +
                        + +
                        +
                        +
                        -
                        +
                        +
                          +
                          -
                          -
                          - -
                          -
                            + +
                            +
                            +
                              - - -
                              - -
                              -
                              -
                                -
                                - -
                                -
                                +
                                - - -
                                + + + - - -
                                -
                                -
                                +
                                +
                                -

                                -
                                +
                                +

                                +
                                -
                                -

                                -
                                - - - +
                                +

                                +
                                + + +
                                -
                                +
                                -
                                - - +
                                + +
                                -
                                +
                                + -
                                  +
                                    +
                                    @@ -631,7 +700,7 @@
                                    +

                                    Unable to find page...

                                    @@ -667,72 +736,72 @@

                                    Unable to find page...

                                      -
                                    - -
                                    +
                                    -
                                    -
                                    + +
                                    + + + + +
                                    + +
                                    + + +
                                    + + + + + + + + +
                                    + + + + +
                                    +
                                    + + + + + + + + + + + + +
                                    + + + + + + + + +
                                    + +
                                    + + + + +
                                    + + +
                                    + +
                                    + + + +
                                    +
                                    + + + +
                                    + +
                                    + + + +
                                    + + + + +
                                    +
                                    + +
                                    + + + + + + + + + + + +
                                    + + +
                                    + + +
                                    +
                                    
                                    +	
                                    + +
                                    +
                                    + + + +
                                    +
                                    + + + + + + +
                                    + Properties +
                                    + +
                                    + Partition Macros + + + + + + - - - -

                                    Values must be written as -%5 or +$5 to be valid.

                                    - - - - -
                                    -
                                    - - - - - - @@ -407,12 +259,14 @@
                                    Some things to remember:
                                    -
                                    + + +
                                    @@ -454,27 +308,27 @@
                                    Some things to remember:
                                    - - + +
                                    @@ -486,9 +340,11 @@
                                    Some things to remember:
                                    - - - + +
                                    @@ -504,12 +360,32 @@
                                    Some things to remember:
                                    - - +
                                    @@ -553,28 +450,20 @@
                                    Some things to remember:
                                    - - - - - - - - - + @@ -588,8 +477,8 @@
                                    Some things to remember:
                                    @@ -602,6 +491,123 @@
                                    Some things to remember:
                                    --> +
                                    - - + +
                                    - - + +
                                    + + + + + + + + + + + +
                                    + + +
                                    + + + + +
                                    + + + + + + + + + + + + +

                                    Values must be written as -%5 or +$5 to be valid.

                                    + + + + +
                                    +
                                    + +
                                    @@ -628,21 +634,20 @@

                                    Zone Based

                                    Flex Methods

                                    +
                                    -
                                    - - -
                                    -
                                    @@ -652,18 +657,19 @@

                                    Flex Methods

                                    +

                                    Edit:

                                    - - + + + +
                                    - - - +
                                    @@ -687,7 +693,7 @@

                                    Edit:

                                    - +
                                    @@ -703,7 +709,7 @@

                                    Edit:

                                    US Shipping Origin
                                    @@ -714,7 +720,7 @@

                                    Edit:

                                    -
                                    - Canada - +
                                    +

                                    International

                                    +
                                    - + - +
                                    SubtotalWeight Fee
                                    - +
                                    - - - + + +
                                    Subtotal:Fee:Up to weight:Fee:
                                    +
                                    + + +
                                    + + Price Based ? + + +
                                    +

                                    Domestic

                                    + + + + + + + + + + +
                                    SubtotalFee
                                    + + + + + + + + + +
                                    Subtotal:Fee:
                                    +
                                    -
                                    - International - - - - - - - - +
                                    +

                                    Canada

                                    +
                                    SubtotalFee
                                    + + + + + + + + + +
                                    SubtotalFee
                                    - - + + + + + + + + +
                                    Subtotal:Fee:
                                    +
                                    + +
                                    +

                                    International

                                    + + + + + + + + + + +
                                    SubtotalFee
                                    + + + + + + + + + +
                                    Subtotal:Fee:
                                    +
                                    - - - - - - - - -
                                    Subtotal:Fee:
                                    -
                                    - - - -

                                    -

                                    Special Handling Rules:
                                    - Use shipping rules to handle the "special cases" that come up from time to time.
                                    - -

                                    +
                                    + Special Insurance Rules: +

                                    Use rules to handle the "special cases" that come up from time to time.

                                    + +
                                    @@ -1100,155 +1096,160 @@
                                    Special Handling Rules:
                                    - - -

                                    Handling fees are applied to all shipping methods after the rules based shipping calculation. Handling fees are typically used to cover the packaging expenses and/or labor involved in assembling an order. You may enable as many handling calculations as you like, all methods will be summed together to arrive at the final handling total.

                                    - -
                                    - Handling fees for orders will be:
                                    - - - -

                                    *NOTE: If you combine handling as part of shipping - it cannot be reported on separately and may affect some aspects of reporting.

                                    -
                                    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                    DomesticCanadaInternational
                                    First Item:$$$
                                    Additional Items:$$$
                                    - - -

                                    Per Product ?

                                    - - - - - - - - - -

                                    Weight Based ?

                                    - - - - - -
                                    - Domestic - - - - - - - - + - -
                                    WeightFee
                                    +

                                    Handling fees are applied to all shipping methods after the rules based shipping calculation. Handling fees are typically used to cover the packaging expenses and/or labor involved in assembling an order. You may enable as many handling calculations as you like, all methods will be summed together to arrive at the final handling total.

                                    + +
                                    + Handling fees for orders will be:
                                    + + + +

                                    *NOTE: If you combine handling as part of shipping - it cannot be reported on separately and may affect some aspects of reporting.

                                    +
                                    - - - - - - - - -
                                    Up to weight:Fee:
                                    -
                                    -
                                    - Canada - - - - - - - - +
                                    + Per Product ? -
                                    -
                                    WeightFee
                                    - - - - - - - - - -
                                    Up to weight:Fee:
                                    -
                                    + + + + + + + + + +
                                    + + Flat Handling Per Item: ? + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                    DomesticCanadaInternational
                                    First Item:$$$
                                    Additional Items:$$$
                                    + +
                                    +
                                    + Weight Based ? -
                                    - International - - - - - - - - - - -
                                    WeightFee
                                    + - - - - - - - - -
                                    Up to weight:Fee:
                                    -
                                    -
                                    +
                                    +

                                    Domestic

                                    + + + + + + + + + + +
                                    WeightFee
                                    + + + + + + + + + +
                                    Up to weight:Fee:
                                    +
                                    + +
                                    +

                                    Canada

                                    + + + + + + + + + + +
                                    WeightFee
                                    + + + + + + + + + +
                                    Up to weight:Fee:
                                    +
                                    + +
                                    +

                                    International

                                    + + + + + + + + + + +
                                    WeightFee
                                    + + + + + + + + + +
                                    Up to weight:Fee:
                                    +
                                    -

                                    -

                                    Special Handling Rules:
                                    - Use shipping rules to handle the "special cases" that come up from time to time.
                                    - -

                                    +
                                    +
                                    + Special Handling Rules: +

                                    Use handling rules to handle the "special cases" that come up from time to time.

                                    + +
                                    @@ -1263,23 +1264,23 @@
                                    Special Handling Rules:
                                    - + - + - + - + @@ -1293,7 +1294,7 @@
                                    Special Handling Rules:

                                    Zoovy FedEx® Shipping Options

                                    - Re-Apply for FedEx Meter + Re-Apply for FedEx Meter

                                    Rating Configuration

                                    @@ -1319,52 +1320,52 @@

                                    Rating Configuration

                                    FedEx Domestic Settings - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
                                    FedEx First Overnight® (8:30am next day)
                                    FedEx Priority Overnight® (10:30am next day)
                                    FedEx Standard Overnight® (3pm next day)
                                    FedEx 2Day®
                                    FedEx Express Saver® (3 Days)
                                    FedEx® Ground
                                    FedEx® Home Delivery**
                                    FedEx® Home Delivery (w/Evening Delivery Surcharge)**
                                    @@ -1373,32 +1374,32 @@

                                    Rating Configuration

                                    FedEx International Settings - +

                                    The more of these shipping methods you allow, the slower the checkout page will be.

                                    - + - + - + - + - + - + - + - +
                                    FedEx International First®
                                    FedEx International Priority®
                                    FedEx International Economy®*
                                    FedEx International Ground®
                                    @@ -1436,7 +1437,7 @@

                                    Rating Configuration

                                    UPS Shipper Number:
                                    - Re-Apply for UPS OnLine® Tools / Change Shipper Number
                                    + Re-Apply for UPS OnLine® Tools / Change Shipper Number

                                    @@ -1452,10 +1453,9 @@

                                    Rating Configuration

                                    - - - - + + + @@ -1463,9 +1463,9 @@

                                    Rating Configuration

                                    UPS Domestic Settings -
                                    +
                                    - +
                                    @@ -2088,6 +2092,9 @@

                                    FedEx® API License Agreement for:

                                    + + + @@ -2096,6 +2103,9 @@

                                    FedEx® API License Agreement for:

                                    + + +
                                    @@ -2103,32 +2113,32 @@

                                    FedEx® API License Agreement for:

                                    Gateways

                                      -
                                    • Credit Card
                                    • -
                                    • eCheck
                                    • +
                                    • Credit Card
                                    • +
                                    • eCheck

                                    Wallets

                                      -
                                    • Amazon
                                    • -
                                    • Google
                                    • -
                                    • PayPal
                                    • +
                                    • Amazon
                                    • + +
                                    • PayPal

                                    Offline

                                      -
                                    • Cash (for P.O.S.)
                                    • -
                                    • Cashiers Check or Money Order by Mail
                                    • -
                                    • Cashiers Check or Money Order on Delivery
                                    • -
                                    • Check by Mail
                                    • -
                                    • Check on Delivery
                                    • -
                                    • Gift Cards
                                    • -
                                    • Pay at Pickup
                                    • -
                                    • Purchase Orders
                                    • -
                                    • Wire Transfer
                                    • +
                                    • Cash (for P.O.S.)
                                    • +
                                    • Cashiers Check or Money Order by Mail
                                    • +
                                    • Cashiers Check or Money Order on Delivery
                                    • +
                                    • Check by Mail
                                    • +
                                    • Check on Delivery
                                    • +
                                    • Gift Cards
                                    • +
                                    • Pay at Pickup
                                    • +
                                    • Purchase Orders
                                    • +
                                    • Wire Transfer
                                    @@ -2143,7 +2153,7 @@

                                    Edit:

                                    - +
                                    @@ -2168,7 +2178,7 @@

                                    Edit:

                                    @@ -2184,7 +2194,7 @@

                                    Edit:

                                    To access your Amazon Account: https://payments.amazon.com.
                                    -NOTE: the values below are configured in Setup | Amazon and are shared with your Amazon.com feed. +NOTE: the values below are are shared with your Amazon.com feed for marketplaces.

                                    @@ -2312,7 +2322,7 @@
                                    Checkout Button
                                    3rd party: where you give paypal_api1.zoovy.com access to your account (recommended, easier)

                                    -If you have already granted API access to paypal_api1.zoovy.com on PayPal.com, then leave all the fields below empty of the configuration will NOT work. +If you have already granted API access to paypal_api1.zoovy.com on PayPal.com, then leave all the fields below empty or the configuration will NOT work.

                                    @@ -2473,63 +2483,127 @@
                                    Checkout Button
                                    -
                                    -
                                    - Accepted Credit Cards & Fees: - - - - - - - +
                                    + Authorize.net Setup + + + +
                                    + +
                                    + Echo Setup + + + +
                                    + +
                                    + PayPal Website Payments Setup + +
                                    + To use website payments you MUST authorize "paypal_api1.zoovy.com" with access to authorize/charge credit cards. + ** NOTE: Paypal operates two competing gateways Payflow Pro and Website Payments (please make sure you configure the correct one). +
                                    +
                                    + +
                                    + PayPal Payflow Pro Setup +
                                    + ** NOTE: Paypal operates two competing gateways Payflow Pro and Website Payments (please make sure you configure the correct one). +
                                    + + + + +
                                    + +
                                    + Card Services/LinkPoint Setup + +
                                    + NOTE: Your cardservice account cannot be used until your signed certificate has been received from Cardservice, this may take up to 5 days from the time you request the certificate. +
                                    +
                                    + +
                                    + SkipJack Setup + +
                                    + +
                                    + Manual Setup + +
                                    + + + + + + + + + +
                                    + +
                                    + Accepted Credit Cards & Fees: +
                                    Accept/AllowTransaction TypeTransaction FeeDiscount Rate (%)
                                    + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + +
                                    Accept/AllowTransaction TypeTransaction FeeDiscount Rate (%)
                                      CC Fees$%$%
                                    Visa$%$%
                                    Mastercard$%$%
                                    American Express$%$%
                                    Discover/Novus$%$%
                                    @@ -2541,8 +2615,8 @@
                                    Checkout Button
                                    Capture Funds: @@ -2599,191 +2673,138 @@
                                    Checkout Button
                                    -
                                    - Authorize.net Setup - - - -
                                    - -
                                    - Echo Setup - - - -
                                    - -
                                    - PayPal Website Payments Setup - -
                                    - To use website payments you MUST authorize "paypal_api1.zoovy.com" with access to authorize/charge credit cards. - ** NOTE: Paypal operates two competing gateways Payflow Pro and Website Payments (please make sure you configure the correct one). -
                                    -
                                    - -
                                    - PayPal Payflow Pro Setup -
                                    - ** NOTE: Paypal operates two competing gateways Payflow Pro and Website Payments (please make sure you configure the correct one). -
                                    - - - - -
                                    - -
                                    - Card Services/LinkPoint Setup - -
                                    - NOTE: Your cardservice account cannot be used until your signed certificate has been received from Cardservice, this may take up to 5 days from the time you request the certificate. -
                                    -
                                    - -
                                    - SkipJack Setup - -
                                    - -
                                    - Manual Setup - -
                                    - -
                                    - -
                                    +
                                    + +

                                    Add a New Rule

                                    -
                                    -
                                    - +
                                    + +
                                    - -
                                    - -
                                    - -

                                    For State Rules use the two letter state abbreviation ex: "CA" for California

                                    -
                                    +
                                    + +

                                    For State Rules use the two letter state abbreviation ex: "CA" for California

                                    +
                                    -
                                    - - - - -

                                    For City, rules is an exact string match, you can also use wildcards. ex:
                                    - "Encinitas" could also be written as: "Encin*". Names are case insensitive.

                                    -

                                    WARNING: City rules are NOT fully-compatible with Google Checkout.

                                    -
                                    +
                                    + + + + +

                                    For City, rules is an exact string match, you can also use wildcards. ex:
                                    + "Encinitas" could also be written as: "Encin*". Names are case insensitive.

                                    +

                                    WARNING: City rules are NOT fully-compatible with Google Checkout.

                                    +
                                    -
                                    - - - - -

                                    For Zip Span rules you may either specific a zip code ex: "92024" or a zip-span ex: "92024-92050"

                                    +
                                    + + + + +

                                    For Zip Span rules you may either specific a zip code ex: "92024" or a zip-span ex: "92024-92050"

                                    -
                                    +
                                    -
                                    - -

                                    Enter the valid zip+4 digit code for a single zip code ex: "90210-1234"

                                    -

                                    WARNING: Zip+4 logic will NOT work unless you utilize address validation.

                                    -
                                    +
                                    + +

                                    Enter the valid zip+4 digit code for a single zip code ex: "90210-1234"

                                    +

                                    WARNING: Zip+4 logic will NOT work unless you utilize address validation.

                                    +
                                    -
                                    - -

                                    Enter the valid ISO Country Code e.g. "CA" for Canada

                                    -
                                    +
                                    + +

                                    Enter the valid ISO Country Code e.g. "CA" for Canada

                                    +
                                    -
                                    - -

                                    Enter the valid ISO Country Code e.g. "CA" for Canada

                                    - -

                                    Enter a province code, or province name for matching.

                                    -
                                    +
                                    + +

                                    Enter the valid ISO Country Code e.g. "CA" for Canada

                                    + +

                                    Enter a province code, or province name for matching.

                                    +
                                    -
                                    - -

                                    Enter the valid ISO Country Code e.g. "CA" for Canada

                                    - -

                                    Enter a valid zip code, or use a pattern such as "A*" to match any zip which starts with the letter A.

                                    -
                                    - -
                                    +
                                    + +

                                    Enter the valid ISO Country Code e.g. "CA" for Canada

                                    + +

                                    Enter a valid zip code, or use a pattern such as "A*" to match any zip which starts with the letter A.

                                    +
                                    - - + +
                                    Also applies to:
                                    - - - - + + + +
                                    @@ -2795,7 +2816,7 @@

                                    Add a New Ru @@ -2806,8 +2827,9 @@

                                    Add a New Ru

                                    -
                                    - +
                                    + +
                                    @@ -2832,10 +2854,10 @@

                                    Existing Rul - +
                                    - +

                                    @@ -2848,7 +2870,9 @@

                                    Existing Rul - + + + @@ -2923,7 +2947,7 @@

                                    Existing Rul
                                    - +
                                    @@ -2937,6 +2961,258 @@

                                    Existing Rul + + + +
                                    + +
                                    +
                                    +

                                    App

                                    +
                                    +
                                      +
                                      + +

                                      Enquiry

                                      +
                                      +
                                        +
                                        + +

                                        Market

                                        +
                                        +
                                          +
                                          + +

                                          Product

                                          +
                                          +
                                            +
                                            + +

                                            Order

                                            +
                                            +
                                              +
                                              + +

                                              Customer

                                              +
                                              +
                                                +
                                                + +

                                                Supplier

                                                +
                                                +
                                                  +
                                                  + +

                                                  Inventory

                                                  +
                                                  +
                                                    +
                                                    + +

                                                    API

                                                    +
                                                    +
                                                      +
                                                      + +

                                                      Error

                                                      +
                                                      +
                                                        +
                                                        + +

                                                        Alert

                                                        +
                                                        +
                                                          +
                                                          + +
                                                          + +
                                                          + +
                                                          +
                                                          + + +
                                                          +
                                                          + +
                                                          + + + +
                                                          + +
                                                          + + + + + + + +
                                                          +

                                                          Notifications

                                                          + +
                                                          + +
                                                          +
                                                          + + + + + + + + + + + + +
                                                          EventMethodMore
                                                          +
                                                          + +
                                                          + + + + + + +
                                                          + Enquiries
                                                          + + +
                                                          + + +
                                                          + +
                                                          + +
                                                          + +
                                                          + +
                                                          + Order
                                                          + + + +
                                                          + +
                                                          + Customer
                                                          + + +
                                                          + +
                                                          + +
                                                          + +
                                                          + Inventory
                                                          + + + +
                                                          + +
                                                          + +
                                                          + +
                                                          + Errors and Alerts
                                                          + +
                                                          + +
                                                          + +
                                                          + + +
                                                          + + +
                                                          + +
                                                          + +
                                                          + +
                                                          +
                                                          + + + +
                                                          + + +
                                                          + + + +
                                                          + + +
                                                          + + + + + + + + + + + + + +
                                                          + + +
                                                          + + + + @@ -2944,499 +3220,461 @@

                                                          Existing Rul + + + +
                                                          -
                                                          +
                                                          +

                                                          General

                                                          +
                                                            + +

                                                          Authentication

                                                            -
                                                          • Facebook
                                                          • -
                                                          • Google
                                                          • + +
                                                          - + +

                                                          Communication

                                                            -
                                                          • Android
                                                          • -
                                                          • Apple/iOS
                                                          • + + +
                                                          - -

                                                          Infrastructure

                                                          + + +

                                                          Shipping

                                                            -
                                                          • Coming soon
                                                          • + + +
                                                          - -

                                                          Native Platforms

                                                          + + +

                                                          Analytics

                                                            -
                                                          • Coming soon
                                                          • +
                                                          -

                                                          Payments

                                                          +

                                                          Tracking

                                                            -
                                                          • Coming soon
                                                          • + +
                                                          + +

                                                          Other

                                                          +
                                                            +
                                                          -
                                                          -
                                                          + +
                                                          -
                                                          -

                                                          Edit:

                                                          +
                                                          +

                                                          Edit:

                                                          -
                                                          -
                                                          - +
                                                          +
                                                          + + +
                                                          -
                                                          - - - +
                                                          -
                                                          + +
                                                          + +
                                                          + + +
                                                          +
                                                          + + + + + + + + + + + + + +
                                                          +

                                                          Roles

                                                          + + + + + + + + + + + + + + + + + + + + + +
                                                          TitleID
                                                          SupervisorSUPER
                                                          App/Web DeveloperAD1
                                                          Owner/OperatorBOSS
                                                          Customer Service: Call CenterCC1
                                                          Customer Service: TrustedCS1
                                                          Retail LeadRL1
                                                          Retail OperatorRO1
                                                          Vendor/Contractor (Read Only)TS1
                                                          Warehouse InventoryWI1
                                                          Warehouse ReturnsWR1
                                                          Warehouse ShipperWS1
                                                          Catalog ManagerXXX
                                                          Marketplace ManagerXYZ
                                                          +
                                                          + + +
                                                          - -

                                                          -
                                                          -
                                                          - - + +
                                                          +
                                                          + + +

                                                          Amazon Account Information

                                                          +

                                                          Amazon Simple Email Service (Amazon SES) is a highly scalable and cost-effective bulk and transactional email sending service for businesses and developers.
                                                          + Click here for signup / more details

                                                          + + - -
                                                          -
                                                          - + +

                                                          Email Addresses

                                                          +
                                                          -
                                                          - - - - - +
                                                          +
                                                          + + -
                                                          - + + + + + + + + + + +
                                                          HostEnableTracking #
                                                          -
                                                          - -Coming Soon +

                                                          The google tracking id will start with UA- followed by a series of numbers. ex: UA-12345678-1

                                                          - - - - - - - - - - - - - - - - - - - - - - + + - - - - - + - - - - - - - - -
                                                          - - - -
                                                          - + + +
                                                          -
                                                          -
                                                          -
                                                          - - - +
                                                          +
                                                          +
                                                          - -
                                                          -
                                                          - - - - - - - -
                                                          + -
                                                          -
                                                          - -
                                                          - -
                                                          -
                                                          - - - -
                                                          -
                                                          - - -
                                                          - - - +
                                                          +
                                                          + + + +

                                                          ShipWorks is a global setting, it is not partition specific

                                                          - -
                                                          - - - -
                                                          - +

                                                          ShipWorks will request a username and password so they can log into your store. Rather than provide them with your master password, use these:

                                                          +
                                                          Username shipworks
                                                          +
                                                          + Password + +
                                                          +
                                                          +
                                                          -
                                                          -
                                                          - -
                                                          - - +

                                                          ShipStation will request a username and password so they can log into your store. Rather than provide them with your master password, use these:

                                                          +
                                                          Username shipstation
                                                          +
                                                          + Password + +
                                                          -
                                                          + +
                                                          -
                                                          - Rewrite Rules - - - - - - - - - - - - - -
                                                          Incoming URLDestination URL
                                                          +
                                                          +
                                                          +
                                                          + + +

                                                          Zoovy Integrate Desktop is a global setting, it is not partition specific

                                                          + -
                                                          - +

                                                          Zoovy Desktop will request a username and password so it can access your store. + Use the username and password below: +

                                                          +
                                                          Username
                                                          +
                                                          + Password + +
                                                          +

                                                          Zoovy Integrated Desktop automatically downloads users from Setup > User Manager. Users can login with their username + PIN (personal identification number). If no PIN has been set then the user will not be able to login to software

                                                          +
                                                          +
                                                          +
                                                          + + - - -
                                                          + - -
                                                          - - - + + +
                                                          -
                                                          +
                                                          +
                                                          + + -
                                                          - + + -
                                                          -
                                                          - - - - - - - - +
                                                          -
                                                          - - -
                                                          -
                                                          - General -
                                                          -
                                                          - - +
                                                          +
                                                          + + - - - - - - - -
                                                          -
                                                          - -
                                                          - + -
                                                          - Hosts - - - - - - - - - - - -
                                                          NameTypeMore
                                                          - -
                                                          + +
                                                          - -
                                                          - -
                                                          - -
                                                          - -
                                                          - -
                                                          +
                                                          +
                                                          + + - - - - - - -
                                                          - Email - - - -
                                                          + - - -
                                                          -
                                                          - -
                                                          - + + + + -
                                                          - - - - - - - - - -
                                                          TypeMessage
                                                          - -
                                                          -
                                                          - - - - - - - - - - - - -
                                                          IDEventClassTime/Date
                                                          - -
                                                          -
                                                          + -
                                                          @@ -3491,7 +3729,7 @@
                                                          Required Billing Information @@ -3522,11 +3760,11 @@
                                                          --> -
                                                          +
                                                          Configured Billing Methods
                                                          - +
                                                          @@ -3536,14 +3774,14 @@
                                                          - +
                                                          Type
                                                          -
                                                          +
                                                          + +
                                                          + +
                                                          +
                                                          + Update Password +

                                                          New passwords must be a minimum of eight characters. It is recommended that you use mixed case, one number and one special character in your password. This will make it more secure.

                                                          + + + + + + +
                                                          +
                                                          + +
                                                          \ No newline at end of file diff --git a/extensions/admin/config.js b/extensions/admin/config.js index 024f7d6c2..6fd7a30c2 100644 --- a/extensions/admin/config.js +++ b/extensions/admin/config.js @@ -17,7 +17,7 @@ ************************************************************** */ -var admin_config = function() { +var admin_config = function(_app) { var theseTemplates = new Array( 'paymentManagerPageTemplate', /* @@ -81,7 +81,7 @@ var admin_config = function() { onSuccess : function() { var r = false; //return false if extension won't load for some reason (account config, dependencies, etc). //the list of templates in theseTemplate intentionally has a lot of the templates left off. This was done intentionally to keep the memory footprint low. They'll get loaded on the fly if/when they are needed. - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/config.html',theseTemplates); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/config.html',theseTemplates); r = true; return r; @@ -89,7 +89,7 @@ var admin_config = function() { onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } }, //callbacks @@ -101,25 +101,77 @@ var admin_config = function() { showEmailAuth : function($target) { //app vars is passed in so the email input can be prepopulated w/ the domain in focus. - $target.empty().append($("
                                                          ").anycontent({'templateID':'emailAuthenticationPageTemplate','data':app.vars}).anydelegate()); - app.u.handleButtons($target) + $target.empty().append(_app.u.addEventDelegation($("
                                                          ").anycontent({'templateID':'emailAuthenticationPageTemplate','data':_app.vars}))); + _app.u.handleButtons($target); }, - showBillingHistory : function($target) { - $target.empty() - $target.anycontent({'templateID':'billingHistoryTemplate','showLoading':false}); - app.u.handleCommonPlugins($target); - app.u.handleEventDelegation($target); - app.u.handleButtons($target); - $('form',$target).each(function(){ - app.ext.admin.u.handleFormConditionalDelegation($(this)); - app.ext.admin.u.applyEditTrackingToInputs($(this)); + passwordUpdate : function($target,P) { + $target.tlc({'templateid':'passwordUpdateTemplate','verb':'template'}); + _app.u.handleButtons($target); + _app.u.addEventDelegation($target); + }, + + + //shows the lists of all blast messages and the means to edit each one individually. + showNotifications : function($target,params) { + $target.showLoading({"message":"Fetching notifications"}); + $target.tlc({'templateid':'notificationPageTemplate','verb':'template'}); + _app.u.addEventDelegation($target); + _app.u.handleButtons($target); + $(".slimLeftNav .accordion",$target).accordion({ + heightStyle: "content" }); + _app.model.addDispatchToQ({'_cmd':'adminConfigDetail','notifications':1,'_tag':{'datapointer':'adminConfigDetail|'+_app.vars.partition+'|notifications',callback : function(rd){ + + $target.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $target.anymessage({'message':rd}); + } + else { + + var notes = _app.data[rd.datapointer]['@NOTIFICATIONS']; + + for(var i = 0, L = notes.length; i < L; i += 1) { + var e = (notes[i].event ? notes[i].event.split('.')[0] : ''); + if(e && notes[i]) { + $("[data-app-role='notifications_"+e+"']",$target).append("
                                                          @@ -455,7 +469,7 @@

                                                          Dropship

                                                          --> - +
                                                          @@ -523,7 +537,7 @@

                                                          Dropship

                                                          - +
                                                          @@ -533,13 +547,13 @@

                                                          Dropship

                                                          - + - @@ -644,12 +658,12 @@

                                                          History:

                                                          - + @@ -730,12 +744,12 @@

                                                          History:

                                                          - + - + @@ -763,14 +777,14 @@

                                                          History:

                                                          -
                                                          +
                                                          @@ -1070,7 +1083,7 @@

                                                          Log:

                                                          +
                                                          - - + +
                                                          @@ -1086,19 +1099,14 @@

                                                          Log:

                                                          + + +
                                                          - + - - - - -
                                                          -
                                                          +
                                                          @@ -1113,7 +1121,7 @@

                                                          Log:

                                                          @@ -1155,10 +1163,10 @@

                                                          - - - - + + + +
                                                          @@ -1269,4 +1277,97 @@
                                                          By CSV Upload
                                                          \ No newline at end of file + + + + + + +
                                                          +
                                                          + + + + + +
                                                          +
                                                          + + + + + + + + + + + + + +
                                                          First NameLast NameEmailPhonePartition
                                                          +
                                                          +
                                                          + + + + + + + + + +
                                                          + + + + + + + + + + + + + +
                                                          + + +
                                                          + +
                                                          +
                                                          + + + + + + + + +
                                                          +
                                                          \ No newline at end of file diff --git a/extensions/admin/customer.js b/extensions/admin/customer.js index e28e3e1e1..70eb1ba0e 100644 --- a/extensions/admin/customer.js +++ b/extensions/admin/customer.js @@ -26,7 +26,7 @@ Giftcards -var admin_customer = function() { +var admin_customer = function(_app) { var theseTemplates = new Array( 'customerManagerResultsRowTemplate', 'CustomerPageTemplate', @@ -64,8 +64,8 @@ var admin_customer = function() { onSuccess : function() { var r = true; //return false if extension won't load for some reason (account config, dependencies, etc). - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/customer.html',theseTemplates); -// app.rq.push(['css',0,app.vars.baseURL+'extensions/admin/customer.css','user_styles']); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/customer.html',theseTemplates); +// _app.rq.push(['css',0,_app.vars.baseURL+'extensions/admin/customer.css','user_styles']); var $modal = $("
                                                          ",{'id':'customerUpdateModal'}).appendTo('body'); //used for various update/add features. $modal.dialog({'autoOpen':false,'width':500,'height':500,'modal':true}); @@ -74,7 +74,7 @@ var admin_customer = function() { onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } }, //callbacks @@ -84,29 +84,115 @@ var admin_customer = function() { //////////////////////////////////// ACTION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ a : { -//This is how the task manager is opened. Just execute this function. -// later, we may add the ability to load directly into 'edit' mode and open a specific user. not supported just yet. +//This is how the customer manager is opened. Just execute this function. +// later, we may add the ability to load directly into 'edit' mode and open a specific customer. not supported just yet. showCustomerManager : function($target,vars) { vars = vars || {}; $target.intervaledEmpty(); $target.anycontent({'templateID':'CustomerPageTemplate','showLoading':false}); //clear contents and add help interface - app.ext.admin.u.handleAppEvents($target); + + _app.u.handleCommonPlugins($target); + _app.u.handleButtons($target); + _app.u.addEventDelegation($target.anyform()); + //must be after anyform or the 'trigger' won't do much. if(vars.scope && vars.searchfor) { $("[name='scope']",$target).val(vars.scope); $("[name='searchfor']",$target).val(vars.searchfor); - $("[data-app-event='admin_customer|execCustomerSearch']",$target).trigger('click'); + $("button[data-app-role='customerSearchButton']:first",$target).trigger('click'); } }, //showCustomerManager +//in obj, currently only CID and partition are required. + showCustomerEditor : function($custEditorTarget,obj) { + obj = obj || {}; + if($custEditorTarget && $custEditorTarget instanceof jQuery) { + $custEditorTarget.empty(); +// zero will be set as CID for orders w/out a CID. disallow it as a valid value. + if(Number(obj.CID) > 0) { + $custEditorTarget.showLoading({"message":"Fetching Customer Record"}); +//partition allows for editor to be linked from orders, where order/customer in focus may be on a different partition. + _app.ext.admin.calls.adminNewsletterList.init({},'mutable'); +// always obtain a new copy of the customer record. May have been updated by another process. + _app.model.destroy("adminCustomerDetail|"+obj.CID); + _app.ext.admin.calls.adminCustomerDetail.init({'CID':obj.CID,'rewards':1,'wallets':1,'tickets':1,'notes':1,'events':1,'orders':1,'giftcards':1,'organization':1},{'callback':function(rd){ + $custEditorTarget.hideLoading(); + + if(_app.model.responseHasErrors(rd)){ + _app.u.throwMessage(rd); + } + else { + $custEditorTarget.anycontent({'templateID':'customerEditorTemplate','data':_app.data[rd.datapointer],'dataAttribs':obj}); + + var panArr = _app.model.dpsGet('admin_customer','editorPanelOrder'); //panel Array for ordering. + + if(!$.isEmptyObject(panArr)) { + var L = panArr.length; +//yes, I know loops in loops are bad. But these are very small loops. +//this will re-sort the panels into the order specified in local storage. + for(var i = 0; i < L; i += 1) { + var $col = $("[data-app-column='"+(i+1)+"']",$custEditorTarget); + for(var index in panArr[i]) { + $("[data-app-role='"+panArr[i][index]+"']",$custEditorTarget).first().appendTo($col); + } + } + } + +//make into anypanels. + $("div.panel",$custEditorTarget).each(function(){ + var PC = $(this).data('app-role'); //panel content (general, wholesale, etc) + $(this).data('cid',obj.CID).anypanel({'wholeHeaderToggle':false,'showClose':false,'state':'persistent','extension':'admin_customer','name':PC,'persistent':true}); + }) + } + + var sortCols = $('.twoColumn').sortable({ + connectWith: '.twoColumn', + handle: 'h2', + cursor: 'move', + placeholder: 'placeholder', + forcePlaceholderSize: true, + opacity: 0.4, + //the 'stop' below is to stop panel content flicker during drag, caused by mouseover effect for configuration options. + stop: function(event, ui){ + $(ui.item).find('h2').click(); + var dataObj = new Array(); + sortCols.each(function(){ + var $col = $(this); + dataObj.push($col.sortable( "toArray",{'attribute':'data-app-role'} )); + }); + _app.model.dpsSet('admin_customer','editorPanelOrder',dataObj); //update the localStorage session var. + // _app.u.dump(' -> dataObj: '); _app.u.dump(dataObj); + } + }); + + _app.u.handleCommonPlugins($custEditorTarget); + _app.u.handleButtons($custEditorTarget); + _app.u.addEventDelegation($custEditorTarget); + _app.ext.admin_customer.u.handleAnypanelButtons($custEditorTarget,obj); //adds buttons to/for the various panels + $custEditorTarget.anyform({'trackEdits':true}); + + }},'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $custEditorTarget.anymessage({"message":"CID "+obj.CID+" is not valid. This may mean there is no record for this customer."}); + } + } + else { + $('#globalMessaging').anymessage({"message":"In admin_customer.a.showCustomerEditor, $custEditorTarget is blank or not an object."}); + } + }, //showCustomerEditor + showCRMManager : function($target) { $target.intervaledEmpty(); - var $DMI = app.ext.admin.i.DMICreate($target,{ + var $DMI = _app.ext.admin.i.DMICreate($target,{ 'header' : 'CRM Manager', 'className' : 'CRMManager', //applies a class on the DMI, which allows for css overriding for specific use cases. - 'thead' : ['','id','Status','Subject','Class','Created','Last Update',''], //leave blank at end if last row is buttons. + 'thead' : ['','ID','Status','Subject','Class','Created','Last Update',''], //leave blank at end if last row is buttons. 'tbodyDatabind' : "var: tickets(@TICKETS); format:processList; loadsTemplate:crmManagerResultsRowTemplate;", - 'buttons' : [""], - 'controls' : app.templates.crmManagerControls, + 'buttons' : [ + ""], + 'controls' : _app.templates.crmManagerControls, 'cmdVars' : { '_cmd' : 'adminAppTicketList', 'STATUS' : 'NEW', //update by changing $([data-app-role="dualModeContainer"]).data('cmdVars').STATUS @@ -116,17 +202,18 @@ var admin_customer = function() { } } }); - app.model.dispatchThis('mutable'); - app.u.handleButtons($DMI.closest("[data-app-role='dualModeContainer']").anydelegate()); + _app.u.handleButtons($target); + _app.model.dispatchThis('mutable'); }, - showCampaignManager : function($target) { - $target.empty(); - var $table = app.ext.admin.i.DMICreate($target,{ + var $table = _app.ext.admin.i.DMICreate($target,{ 'header' : 'Campaign Manager', 'className' : 'campaignManager', - 'buttons' : [""], + 'handleAppEvents' : false, + 'buttons' : [ + ""], 'thead' : ['ID','Subject','Status','Methods','Q Mode','Created','Expired',''], 'tbodyDatabind' : "var: campaign(@CAMPAIGNS); format:processList; loadsTemplate:campaignResultsRowTemplate;", 'cmdVars' : { @@ -134,20 +221,18 @@ var admin_customer = function() { '_tag' : {'datapointer' : 'adminCampaignList'} } }); -//get this handy. -// * 201336 -> moved this so templates are not requested till template chooser is opened. -// app.model.addDispatchToQ({'_cmd':'adminCampaignTemplateList','_tag':{'datapointer' : 'adminCampaignTemplateList'}},'mutable'); - app.model.dispatchThis(); - + _app.u.handleButtons($target.anyform()); + // do not fetch templates at this point. That's a heavy call and they may not be used. + _app.model.dispatchThis(); }, //showCampaignManager showCampaignEditor : function($target,CAMPAIGNID) { - app.u.dump("BEGING admin_customer.a.showCampaignEditor"); +// _app.u.dump("BEGING admin_customer.a.showCampaignEditor"); if($target && $target instanceof jQuery && CAMPAIGNID) { $target.empty() - var data = app.ext.admin_customer.u.getCampaignByCAMPAIGNID(CAMPAIGNID); - //app.u.dump(" -> campaign data:"); app.u.dump(data); + var data = _app.ext.admin_customer.u.getCampaignByCAMPAIGNID(CAMPAIGNID); + if(data) { //generate template instance and get some content in front of user. will be blocked by loading till template data available. @@ -163,14 +248,14 @@ var admin_customer = function() { showMinute : false, separator : '' //get rid of space between date and time. }); -// $('.ui_tpicker_second',$target).hide(); //don't show minute or second chooser, but have it so they're added to the input. -// $('.ui_tpicker_minute_label',$target).hide(); - - var $picker = $("[data-app-role='pickerContainer']:first",$target); - $picker.append(app.ext.admin.a.getPicker({'templateID':'customerPickerTemplate','mode':'customer'},data.RECIPIENTS)); - $picker.anycontent({data:data}); - app.u.handleAppEvents($target); + var $picker = $("[data-app-role='pickerContainer']:first",$target); + $picker.append(_app.ext.admin.a.getPicker({'templateID':'customerPickerTemplate','mode':'customer'},data.RECIPIENTS)); + $picker.anycontent({data:data}); + + _app.u.handleAppEvents($target); + _app.u.addEventDelegation($target); + _app.u.handleButtons($target.anyform()); } else if(data === false) { $('#globalMessaging').anymessage({"message":"In admin_customer.a.showCampaignEditor, unable to resolve campaign data from CAMPAIGNID: "+CAMPAIGNID,"gMessage":true}); @@ -185,29 +270,38 @@ var admin_customer = function() { showGiftcardManager : function($target) { $target.empty(); - var $table = app.ext.admin.i.DMICreate($target,{ + var $table = _app.ext.admin.i.DMICreate($target,{ 'header' : 'Giftcard Manager', 'className' : 'giftcardManager', - 'buttons' : [""], + 'handleAppEvents' : false, + 'buttons' : [ + "", + ""], 'thead' : ['Code','Created','Expires','Last Order','Customer','Balance','Txn #','Type','Series',''], - 'controls' : "
                                                          +
                                                          @@ -48,7 +48,7 @@

                                                          Network Database Installation/Deployment

                                                          Zoovy Network Sync Manager

                                                          A windows service that automatically synchronizes your local databases with Zoovy servers. This is intended for clients running network databases and manages the synchronization process automatically.

                                                          - +

                                                          If you do not currently have a supported database installed on your server, you will also need to select a database that fits your network environment. A discussion of network databases, and deployment options along with frequently asked questions is located in:

                                                          @@ -58,11 +58,11 @@

                                                          MySQL 5.1 Community Server

                                                          @@ -70,7 +70,7 @@

                                                          MySQL 5.1 Community Server

                                                          Microsoft SQL Server 2008

                                                          @@ -92,15 +92,15 @@

                                                          .Net Framework Required

                                                          All applications require the Windows Installer 3.1, and Microsoft .NET 3.5 sp1 framework to be installed for proper operation. Please use the links to download:

                                                          Network Database Installation

                                                          Installation documentation can be found:

                                                          • Webdoc #50491. -
                                                            Warning: Network Database installations are difficult multi-step processes with lots of room for mistakes. We encourage companies who do not employ a fulltime database administrator (which is different than a "Tech Guy") to consult with our Geek Services to deploy your database. In order to speed up the installation appointment, please view our Webdoc #51357 prior to your appointment.
                                                            +
                                                            Warning: Network Database installations are difficult multi-step processes with lots of room for mistakes. We encourage companies who do not employ a fulltime database administrator (which is different than a "Tech Guy") to consult with our Geek Services to deploy your database. In order to speed up the installation appointment, please view our Webdoc #51357 prior to your appointment.
                                                          @@ -108,8 +108,8 @@

                                                          Network Database Installation

                                                          Multi-Site Considerations

                                                          Only one database may be active per account. If you have multiple sites - or remote users you will need to use a VPN solution to connect them.
                                                          - Zoovy Geek Services + or remote users you will need to use a VPN solution to connect them.
                                                          + Zoovy Geek Services can assist you with multi-site VPN deployments.

                                                          @@ -120,7 +120,7 @@

                                                          Enterprise Support

                                                          Supported Operating Systems:

                                                          - Windows XP sp3, Vista sp2, Windows 7, Windows Server 2003 r2; Windows Server 2008. + Windows Vista sp2, Windows 7, Windows Server 2003 r2, Windows 8; Windows Server 2008, 2013. Requires .NET Framework 3.0.
                                                          64 Bit Considerations: Order Manager will run correctly on Vista/Windows 7 64 Bit Operating System. diff --git a/extensions/admin/extension.js b/extensions/admin/extension.js old mode 100755 new mode 100644 index 54d3e95c6..155640d5a --- a/extensions/admin/extension.js +++ b/extensions/admin/extension.js @@ -22,7 +22,7 @@ An extension for working within the Zoovy UI. */ -var admin = function() { +var admin = function(_app) { // theseTemplates is it's own var because it's loaded in multiple places. // here, only the most commonly used templates should be loaded. These get pre-loaded. Otherwise, load the templates when they're needed or in a separate extension (ex: admin_orders) var theseTemplates = new Array( @@ -34,8 +34,6 @@ var admin = function() { 'adminChooserElasticResult', 'productTemplateChooser', - 'domainPanelTemplate', - 'pageSetupTemplate', 'pageUtilitiesTemplate', // 'pageTemplateSetupAppchooser', @@ -46,13 +44,8 @@ var admin = function() { // 'achievementsListTemplate', 'messageListTemplate', - 'messageDetailTemplate', - - 'mailToolTemplate', - - 'pageTemplateSites', - 'domainListTemplate' - + 'messageDetailTemplate' + // 'projectsListTemplate', // 'projectDetailTemplate', // 'projectCreateTemplate', @@ -60,25 +53,28 @@ var admin = function() { // 'rssAddUpdateTemplate', // 'rssListTemplate' - ); + ); var r = { vars : { tab : null, //is set when switching between tabs. it outside 'state' because this doesn't get logged into local storage. - tabs : ['setup','sites','jt','product','orders','crm','syndication','reports','utilities','launchpad'], + tabs : ['setup','sites','home','product','orders','crm','syndication','reports','kpi','utilities','support','launchpad'], state : {}, tab : 'home', // YOUTUBE RELEASE VIDEO: - versionMetaData : { - 'youtubeVideoIDs' : { - '201342':'Zq8Ac5YzP3M', - '201338':'A8TNbpQtgas', - '201336':'UOfn6tiQqiw', - '201334':'FUO0NALw6sI', - '201332':'tKQ_SJzjbXI', - '201330':'fEWSsblLQ94' - } - }, + versionData : [ + {'branch' : '201402','youtubeVideoID' : ''}, + {'branch' : '201401','youtubeVideoID' : 'NHRNhI2AmG8'}, +// {'branch' : '201352','youtubeVideoID' : ''}, + {'branch' : '201346','youtubeVideoID' : 'cW_DvZ2HOy8'}, + {'branch' : '201344','youtubeVideoID' : 'cW_DvZ2HOy8'}, + {'branch' : '201338','youtubeVideoID' : 'A8TNbpQtgas'}, + {'branch' : '201336','youtubeVideoID' : 'UOfn6tiQqiw'}, + {'branch' : '201334','youtubeVideoID' : 'FUO0NALw6sI'}, + {'branch' : '201332','youtubeVideoID' : 'tKQ_SJzjbXI'}, + {'branch' : '201330','youtubeVideoID' : 'fEWSsblLQ94'} + ], + templates : theseTemplates, willFetchMyOwnTemplates : true, "tags" : ['IS_FRESH','IS_NEEDREVIEW','IS_HASERRORS','IS_CONFIGABLE','IS_COLORFUL','IS_SIZEABLE','IS_OPENBOX','IS_PREORDER','IS_DISCONTINUED','IS_SPECIALORDER','IS_BESTSELLER','IS_SALE','IS_SHIPFREE','IS_NEWARRIVAL','IS_CLEARANCE','IS_REFURB','IS_USER1','IS_USER2','IS_USER3','IS_USER4','IS_USER5','IS_USER6','IS_USER7','IS_USER8','IS_USER9'], @@ -91,7 +87,7 @@ var admin = function() { calls : { - +// ### FUTURE -> get rid of this call adminAppTicketMacro : { init : function(tktcode,macros,_tag,Q) { var r = 0; @@ -112,11 +108,10 @@ var admin = function() { obj['@updates'] = macros; obj._cmd = 'adminAppTicketMacro'; obj._tag = _tag; - app.model.addDispatchToQ(obj,Q || 'immutable'); + _app.model.addDispatchToQ(obj,Q || 'immutable'); } }, //adminAppTicketCreate - //for configDetail requests, no datapointer is set by default for shipmethod, payment, etc. It DOES accept a _tag.datapointer and, if set, will look for local. //That means if no datapointer is passed, no localstorage is used. //so for this call, you need to be particularly careful about setting a datapointer if you want to take advantage of localStorage. @@ -126,12 +121,12 @@ var admin = function() { var r = 0; if(!$.isEmptyObject(obj)) { if(_tag && _tag.datapointer) { - if(app.model.fetchData(_tag.datapointer) == false) { + if(_app.model.fetchData(_tag.datapointer) == false) { r = 1; this.dispatch(obj,_tag,Q); } else { - app.u.handleCallback(_tag); + _app.u.handleCallback(_tag); } } else { @@ -149,12 +144,10 @@ var admin = function() { dispatch : function(obj,_tag,Q) { obj._cmd = "adminConfigDetail" obj._tag = _tag; //tag will be set in this call for datapointer purposes. - app.model.addDispatchToQ(obj,Q || 'mutable'); + _app.model.addDispatchToQ(obj,Q || 'mutable'); } }, //adminConfigDetail - - adminConfigMacro : { init : function(macros,_tag,Q) { var r = 0; @@ -166,7 +159,7 @@ var admin = function() { obj['@updates'] = macros; obj._cmd = "adminConfigMacro" obj._tag = _tag; //tag will be set in this call for datapointer purposes. - app.model.addDispatchToQ(obj,Q || 'immutable'); + _app.model.addDispatchToQ(obj,Q || 'immutable'); } }, //adminConfigMacro @@ -178,94 +171,27 @@ var admin = function() { //if datapointer is fixed (set within call) it needs to be added prior to executing handleCallback (which needs datapointer to be set). _tag = _tag || {}; _tag.datapointer = "adminCustomerDetail|"+obj.CID; - if(app.model.fetchData(_tag.datapointer) == false) { + if(_app.model.fetchData(_tag.datapointer) == false) { r = 1; this.dispatch(obj,_tag,Q); } else { - app.u.handleCallback(_tag); + _app.u.handleCallback(_tag); } } else { - app.u.throwGMessage("In admin.calls.adminCustomerDetail, no CID specified in param object."); + _app.u.throwGMessage("In admin.calls.adminCustomerDetail, no CID specified in param object."); } return r; }, dispatch : function(obj,_tag,Q) { obj._cmd = "adminCustomerDetail"; obj._tag = _tag; - app.model.addDispatchToQ(obj,Q); - } - }, //adminCustomerDetail - - adminCustomerRemove : { - init : function(CID,_tag,Q) { - var r = 0; - if(CID) { -//if datapointer is fixed (set within call) it needs to be added prior to executing handleCallback (which needs datapointer to be set). - _tag = _tag || {}; - _tag.datapointer = "adminCustomerRemove"; - this.dispatch(CID,_tag); - } - else { - app.u.throwGMessage("In admin.calls.adminCustomerRemove, no CID specified."); - } - return r; - }, - dispatch : function(CID,_tag) { - var obj = {}; - obj.CID = CID; - obj._cmd = "adminCustomerRemove"; - obj._tag = _tag; - app.model.addDispatchToQ(obj,'immutable'); + _app.model.addDispatchToQ(obj,Q); } }, //adminCustomerDetail -//no local storage to ensure latest data always present. - adminCustomerSearch : { - init : function(obj,_tag,Q) { - var r = 0; - if(obj && obj.searchfor && obj.scope) { - this.dispatch(obj,_tag,Q); - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.adminCustomerSearch, no email specified."); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._tag = _tag || {}; - obj._cmd = "adminCustomerSearch"; - obj._tag.datapointer = "adminCustomerSearch"; //if changed, test order create for existing customer and customer manager. - app.model.addDispatchToQ(obj,Q || 'mutable'); - } - }, //adminCustomerSearch - -//email is required in macro - adminCustomerCreate : { - init : function(updates,_tag) { - var r = 0; - if(updates) { - this.dispatch(updates,_tag) - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.adminCustomerSet, macro not set or setObj was empty"); - } - return r; - }, - dispatch : function(updates,_tag) { - var obj = {}; - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminCustomerCreate'; - obj._cmd = "adminCustomerCreate"; - obj.CID = 0; //create wants a zero customer id - obj['@updates'] = updates; - app.model.addDispatchToQ(obj,'immutable'); - } - }, //adminCustomerSet - + adminCustomerUpdate : { init : function(CID,updates,_tag) { var r = 0; @@ -274,7 +200,7 @@ var admin = function() { r = 1; } else { - app.u.throwGMessage("In admin.calls.adminCustomerUpdate, CID ["+CID+"] or updates ["+updates+"] not set"); + _app.u.throwGMessage("In admin.calls.adminCustomerUpdate, CID ["+CID+"] or updates ["+updates+"] not set"); } return r; }, @@ -286,1019 +212,212 @@ var admin = function() { obj.CID = CID; obj['@updates'] = setObj; obj._tag = _tag; - app.model.addDispatchToQ(obj,'immutable'); + _app.model.addDispatchToQ(obj,'immutable'); } }, //adminCustomerSet - - - - adminCustomerOrganizationSearch : { - init : function(obj,_tag,Q) { -// app.u.dump("BEGIN admin.calls.adminCustomerOrganizationSearch"); app.u.dump(obj); - var r = 0; - if(obj) { - this.dispatch(obj,_tag,Q) - r = 1; - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminCustomerSet, no variables passed. some sort of search query needed.",'gMessage':true}); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminCustomerOrganizationSearch'; - obj._cmd = "adminCustomerOrganizationSearch"; - app.model.addDispatchToQ(obj,Q || 'mutable'); - } - }, //adminCustomerOrganizationSearch - adminCustomerOrganizationCreate : { - init : function(obj,_tag,Q) { - var r = 0; - if(obj) { - this.dispatch(obj,_tag,Q) - r = 1; - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminCustomerOrganizationCreate, no variables passed."}); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminCustomerOrganizationCreate'; - obj._cmd = "adminCustomerOrganizationCreate"; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - }, //adminCustomerOrganizationCreate - adminCustomerOrganizationUpdate : { - init : function(obj,_tag,Q) { - var r = 0; - if(obj && obj.ORGID) { - this.dispatch(obj,_tag,Q) - r = 1; - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminCustomerOrganizationUpdate, either obj is blank or obj.ORGID not set, which is required."}); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminCustomerOrganizationUpdate'; - obj._cmd = "adminCustomerOrganizationUpdate"; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - }, //adminCustomerOrganizationUpdate - adminCustomerOrganizationDetail : { - init : function(orgID,_tag,Q) { - var r = 0; - if(orgID) { - _tag = _tag || {}; - _tag.datapointer = 'adminCustomerOrganizationDetail|'+orgID; - - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(orgID,_tag,Q); - } - else { - app.u.handleCallback(_tag); - } - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminCustomerOrganizationDetail, either obj is blank or obj.ORGID not set, which is required."}); - } - return r; - }, - dispatch : function(orgID,_tag,Q) { - var obj = {} - obj._tag = _tag || {}; - - obj._cmd = "adminCustomerOrganizationDetail"; - obj.ORGID = orgID - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - }, //adminCustomerOrganizationDetail - adminCustomerOrganizationRemove : { - init : function(ORGID,_tag,Q) { - var r = 0; - if(ORGID) { - this.dispatch(ORGID,_tag,Q) - r = 1; - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminCustomerOrganizationRemove, ORGID not set, which is required."}); - } - return r; - }, - dispatch : function(ORGID,_tag,Q) { - var obj = {}; - obj.ORGID = ORGID; - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminCustomerOrganizationRemove'; - obj._cmd = "adminCustomerOrganizationRemove"; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - }, //adminCustomerOrganizationRemove - - adminDataQuery : { - init : function(obj,_tag,Q) { - var r = 0; - if(obj && obj.query) {this.dispatch(obj,_tag,Q); r = 1;} - else { - app.u.throwGMessage("In admin.calls.adminDataQuery, no object or no object.query object passed."); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = 'adminDataQuery'; - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminDataQuery'; - app.model.addDispatchToQ(obj,Q); - } - }, //adminDataQuery - -// {'_cmd':'adminDataQuery','query':'listing-active','since_gmt':app.u.unixNow() - (60*60*24*10)} adminDomainList : { init : function(_tag,Q) { _tag = _tag || {}; _tag.datapointer = "adminDomainList"; var r = 0; - if(app.model.fetchData(_tag.datapointer) == false) { + if(_app.model.fetchData(_tag.datapointer) == false) { r = 1; this.dispatch(_tag,Q); } else { - app.u.handleCallback(_tag); + _app.u.handleCallback(_tag); } return r; }, dispatch : function(_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminDomainList","_tag" : _tag},Q); + _app.model.addDispatchToQ({"_cmd":"adminDomainList","_tag" : _tag},Q); } }, //adminDomainList - //* 201324 -> though moving towards a non-defined call based approach, for calls that need/want local storage, we'll still declare them (like this one) adminEBAYCategory : { init : function(obj,_tag,Q) { obj = obj || {} _tag = _tag || {}; - _tag.datapointer = (obj.pid) ? "adminEBAYCategory|"+app.model.version+"|"+obj.pid+"|"+obj.categoryid : "adminEBAYCategory|"+app.model.version+"|"+obj.categoryid; + _tag.datapointer = (obj.pid) ? "adminEBAYCategory|"+_app.model.version+"|"+obj.pid+"|"+obj.categoryid : "adminEBAYCategory|"+_app.model.version+"|"+obj.categoryid; var r = 0; //if xsl is set, localstorage is NOT used. if(obj.xsl) { - app.u.dump(" -> XSL is set, do NOT use what is in memory or local storage"); + _app.u.dump(" -> XSL is set, do NOT use what is in memory or local storage"); r = 1; this.dispatch(obj,_tag,Q); } - else if(app.model.fetchData(_tag.datapointer) == false) { + else if(_app.model.fetchData(_tag.datapointer) == false) { r = 1; this.dispatch(obj,_tag,Q); } else { - app.u.handleCallback(_tag); + _app.u.handleCallback(_tag); } return r; }, dispatch : function(obj,_tag,Q) { obj._cmd = 'adminEBAYCategory'; obj._tag = _tag; - app.model.addDispatchToQ(obj,Q || 'mutable'); + _app.model.addDispatchToQ(obj,Q || 'mutable'); } }, //adminDomainList -//PRT and TYPE (ex: ORDER) are required params - adminEmailList : { - init : function(obj,_tag,Q) { - var r = 0; -// app.u.dump(" -> obj:"+Number(obj.PRT)); app.u.dump(obj); app.u.dump(_tag); - if(obj && (Number(obj.PRT) >= 0) && obj.TYPE) { - _tag = _tag || {}; - _tag.datapointer = "adminEmailList|"+obj.PRT+"|"+obj.TYPE; - - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(obj,_tag,Q); - } - else { - app.u.handleCallback(_tag); - } - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminEmailList, PRT ["+obj.PRT+"] and TYPE ["+obj.TYPE+"] are required and one was not set."}); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = "adminEmailList"; - obj._tag = _tag; - app.model.addDispatchToQ(obj,Q || 'mutable'); - } - }, //adminEmailList - - adminEmailSave : { - init : function(obj,_tag,Q) { - var r = 0; - if(obj && Number(obj.PRT) >= 0 && obj.MSGID && obj.TYPE) {this.dispatch(obj,_tag,Q); r = 1;} - else { - app.u.throwGMessage("In admin.calls.adminEmailSave, no object ["+typeof obj+"] or object.PRT ["+obj.PRT+"] or object.MSGID ["+obj.MSGID+"] not passed."); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = 'adminEmailSave'; - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminEmailSave'; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - }, //adminDataQuery - - -//obj requires title and uuid, priority and @GRAPHS are optional. - adminKPIDBCollectionCreate : { - init : function(obj,_tag,Q) { +//get a list of newsletter subscription lists. + adminNewsletterList : { + init : function(_tag,Q) { var r = 0; _tag = _tag || {}; - _tag.datapointer = "adminKPIDBCollectionCreate" - obj = obj || {}; - if(obj.title && obj.uuid) { + _tag.datapointer = "adminNewsletterList" + if(_app.model.fetchData('adminNewsletterList') == false) { r = 1; - this.dispatch(obj,_tag,Q); + this.dispatch(_tag,Q); } else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminKPIDBCollectionCreate, uuid or title not passed","gMessage":true}) +// _app.u.dump(' -> data is local'); + _app.u.handleCallback(_tag); } return r; }, - dispatch : function(obj,_tag,Q) { - obj._cmd = 'adminKPIDBCollectionCreate' - obj._tag = _tag; - app.model.addDispatchToQ(obj,Q || 'immutable'); + dispatch : function(_tag,Q) { + _app.model.addDispatchToQ({"_cmd":"adminNewsletterList","_tag" : _tag},Q || 'immutable'); } - }, //adminKPIDBUserDataSetsList - adminKPIDBCollectionDetail : { - init : function(uuid,_tag,Q) { + },//getNewsletters + +//never look locally for data. Always make sure to load latest from server to ensure it's up to date. +//order info is critial + adminOrderDetail : { + init : function(orderID,_tag,Q) { var r = 0; - if(uuid) { - _tag = _tag || {}; - _tag.datapointer = "adminKPIDBCollectionDetail|"+uuid - if(app.model.fetchData('adminKPIDBCollectionDetail|'+uuid) == false) { + if(orderID) { + _tag = _tag || {}; + _tag.datapointer = "adminOrderDetail|"+orderID; + if(_app.model.fetchData(_tag.datapointer) == false) { r = 1; - this.dispatch(uuid,_tag,Q); + this.dispatch(orderID,_tag,Q); } else { - app.u.handleCallback(_tag); + _app.u.handleCallback(_tag); } + r = 1; } else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminKPIDBCollectionDetail, uuid not passed","gMessage":true}) + _app.u.throwGMessage("In admin.calls.adminOrderDetail, orderID not passed."); } return r; }, - dispatch : function(uuid,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminKPIDBCollectionDetail","uuid":uuid,"_tag" : _tag},Q || 'mutable'); + dispatch : function(orderID,_tag,Q) { + var cmdObj = {}; + cmdObj.orderid = orderID; + cmdObj._tag = _tag; + cmdObj._cmd = "adminOrderDetail"; + _app.model.addDispatchToQ(cmdObj,Q); } - }, //adminKPIDBCollectionList - adminKPIDBCollectionList : { - init : function(_tag,Q) { + }, //adminOrderDetail + +//updating an order is a critical function and should ALWAYS be immutable. + adminOrderMacro : { + init : function(orderID,updates,_tag) { var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminKPIDBCollectionList" - if(app.model.fetchData('adminKPIDBCollectionList') == false) { + if(orderID) { + this.dispatch(orderID,updates,_tag); r = 1; - this.dispatch(_tag,Q); } else { - app.u.handleCallback(_tag); + _app.u.throwGMessage("In admin.calls.adminOrderMacro, orderID not passed."); } return r; }, - dispatch : function(_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminKPIDBCollectionList","_tag" : _tag},Q || 'mutable'); + dispatch : function(orderID,updates,_tag) { + cmdObj = {}; + cmdObj._cmd = 'adminOrderMacro'; + cmdObj.orderid = orderID; + cmdObj['@updates'] = updates; + cmdObj._tag = _tag || {}; + _app.model.addDispatchToQ(cmdObj,'immutable'); + } + }, //adminOrderMacro + + adminOrderSearch : { + init : function(elasticObj, _tag, Q) { + this.dispatch(elasticObj,_tag,Q); + return 1; + }, + dispatch : function(elasticObj,_tag,Q){ + var obj = {}; + obj._cmd = "adminOrderSearch"; + obj.DETAIL = '9'; + obj.ELASTIC = elasticObj; + obj._tag = _tag || {}; + obj._tag.datapointer = "adminOrderSearch"; + _app.model.addDispatchToQ(obj,Q || 'immutable'); } - }, //adminKPIDBCollectionList - adminKPIDBCollectionRemove : { - init : function(uuid,_tag,Q) { + }, //adminOrderSearch + + adminSyndicationMacro : { + init : function(DST, macros,_tag,Q) { var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminKPIDBCollectionRemove" - if(uuid) { + if(DST && macros && macros.length) { r = 1; - this.dispatch(uuid,_tag,Q); + _tag = _tag || {}; + _tag.datapointer = "adminSyndicationMacro"; + this.dispatch(DST,macros,_tag,Q); } else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminKPIDBCollectionRemove, uuid not passed","gMessage":true}) + $('#globalMessaging').anymessage({"message":"In admin.calls.adminSyndicationMacro, macros ["+typeof macros+"] and/or DST ["+DST+"] is empty or not passed","gMessage":true}); } return r; }, - dispatch : function(uuid,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminKPIDBCollectionRemove","uuid":uuid,"_tag" : _tag},Q || 'immutable'); + dispatch : function(DST,macros,_tag,Q) { + _app.model.addDispatchToQ({"_cmd":"adminSyndicationMacro","DST":DST,"@updates":macros,"_tag":_tag,'DST':DST},Q || 'mutable'); } - }, //adminKPIDBUserDataSetsList -//obj requires uuid, title, priority and @GRAPHS are optional. - adminKPIDBCollectionUpdate : { + }, //adminSyndicationDetail + + +//obj requires sub and sref. sub can be LOAD or SAVE +//reload is also supported. + adminUIBuilderPanelExecute : { init : function(obj,_tag,Q) { -// app.u.dump("BEGIN admin.calls.adminKPIDBCollectionUpdate"); - var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminKPIDBCollectionUpdate" - obj = obj || {}; - if(obj.uuid) { -// app.u.dump(" -> have UUID. proceed."); - r = 1; - this.dispatch(obj,_tag,Q); + _tag = _tag || {}; + if(obj['sub'] == 'EDIT') { + _tag.datapointer = "adminUIBuilderPanelExecute|edit"; + } + else if(obj['sub'] == 'SAVE') { + _tag.datapointer = "adminUIBuilderPanelExecute|save"; } else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminKPIDBCollectionUpdate, uuid not passed","gMessage":true}) + //catch. some new verb or a format that doesn't require localStorage. } - return r; + this.dispatch(obj,_tag,Q); }, dispatch : function(obj,_tag,Q) { - obj._cmd = 'adminKPIDBCollectionUpdate' - obj._tag = _tag; - app.model.addDispatchToQ(obj,Q || 'immutable'); + obj['_cmd'] = "adminUIBuilderPanelExecute"; + obj['_SREF'] = sref; + obj["_tag"] = _tag; + _app.model.addDispatchToQ(obj,Q); } - }, //adminKPIDBUserDataSetsList -/* - -day|dow|quarter|month|week|none -gms|distinct|total -a formula ex: months.1, weeks.1 -(not needed if period is passed) -(not needed if period is passed) -*/ -// obj required dataset, grupby, column, detail. period or starty/stop date range are needed. - adminKPIDBDataQuery : { - init : function(obj,_tag,Q) { - var r = 0; - if(!$.isEmptyObject(obj)) { - if(obj['@datasets'] && obj.grpby && obj.column && obj['function']) { - if(obj.period || (obj.startyyyymmdd && obj.stopyyyymmdd)) { - r = 1; - this.dispatch(obj,_tag,Q); - } - else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminKPIDBDataQuery, either period ["+obj.period+"] or start/stop ["+["+obj.startyyyymmdd+"]+"/"+obj.stopyyyymmdd+"] date range required.","gMessage":true}) - } - } - else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminKPIDBDataQuery; @datasets ["+typeof obj['@datasets']+"], grpby ["+obj.grpby+"], and column ["+obj.column+"] and function ["+obj['function']+"] are required","gMessage":true}) - } - } - else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminKPIDBDataQuery, no object passed","gMessage":true}) - } - - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = "adminKPIDBDataQuery"; - obj._tag = _tag || {}; - obj._tag.datapointer = "adminKPIDBDataQuery" - app.model.addDispatchToQ(obj,Q || 'mutable'); - } - }, //adminKPIDBDataQuery - adminKPIDBUserDataSetsList : { - init : function(_tag,Q) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminKPIDBUserDataSetsList" - if(app.model.fetchData('adminKPIDBUserDataSetsList') == false) { - r = 1; - this.dispatch(_tag,Q); - } - else { -// app.u.dump(' -> data is local'); - app.u.handleCallback(_tag); - } - return r; - }, - dispatch : function(_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminKPIDBUserDataSetsList","_tag" : _tag},Q || 'mutable'); - } - }, //adminKPIDBUserDataSetsList - - - - -//@head and @body in the response is the data I should use. -//guid comes from batch list. - adminReportDownload : { - init : function(batchGUID,_tag,Q) { - var r = 0; - if(batchGUID) { - this.dispatch(batchGUID,_tag,Q); - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.adminReportDownload, no batchGUID passed."); - } - return r; - }, - dispatch : function(batchGUID,_tag,Q) { - var obj = {}; - obj._cmd = 'adminReportDownload'; - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminReportDownload|'+batchGUID; - obj.GUID = batchGUID; - app.model.addDispatchToQ(obj,Q || 'passive'); - } - }, - - -//obj requires title and uuid, priority and @GRAPHS are optional. - adminRSSRemove : { - init : function(listID,_tag,Q) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminRSSRemove" - if(listID) { // !!! this validation needs updating. - r = 1; - this.dispatch(listID,_tag,Q); - } - else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminRSSRemove, listID not passed","gMessage":true}) - } - return r; - }, - dispatch : function(listID,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminRSSRemove","_tag":_tag,"ID":listID},Q || 'immutable'); - } - }, //adminRSSRemove - - adminRSSUpdate : { - init : function(obj,_tag,Q) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminRSSUpdate" - obj = obj || {}; - if(obj.CPG) { // !!! this validation needs updating. - r = 1; - this.dispatch(obj,_tag,Q); - } - else { - $('.appMessaging').anymessage({"message":"In admin.calls.adminRSSUpdate, CPG not passed","gMessage":true}) - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = 'adminRSSUpdate' - obj._tag = _tag; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - }, //adminRSSUpdate - - adminRSSDetail : { - init : function(cpg,_tag,Q) { - var r = 0; - if(cpg) { - _tag = _tag || {}; - _tag.datapointer = "adminRSSDetail|"+cpg - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(cpg,_tag,Q); - } - else { - app.u.handleCallback(_tag); - } - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminRSSDetail, cpg not passed","gMessage":true}) - } - return r; - }, - dispatch : function(cpg,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminRSSDetail","CPG":cpg,"_tag" : _tag},Q || 'mutable'); - } - }, //adminRSSDetail - - - adminMessagesList : { -//ID will be 0 to start. - init : function(msgid,_tag,Q) { - var r = 0; - if(msgid || msgid === 0) { - this.dispatch(msgid,_tag,Q); - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.adminMessagesList, MESSAGEID not passed and is required."); - } - return r; - }, - dispatch : function(msgid,_tag,Q) { - var obj = {}; - obj._cmd = 'adminMessagesList'; - obj.msgid = msgid; - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminMessagesList|'+msgid; - app.model.addDispatchToQ(obj,Q || 'passive'); - } - }, - - -//get a list of newsletter subscription lists. - adminNewsletterList : { - init : function(_tag,Q) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminNewsletterList" - if(app.model.fetchData('adminNewsletterList') == false) { - r = 1; - this.dispatch(_tag,Q); - } - else { -// app.u.dump(' -> data is local'); - app.u.handleCallback(_tag); - } - return r; - }, - dispatch : function(_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminNewsletterList","_tag" : _tag},Q || 'immutable'); - } - },//getNewsletters - - - adminPrivateSearch : { - init : function(obj,_tag,Q) { - var r = 0; - if(!$isEmptyObject(obj)) {this.dispatch(obj,_tag,Q); r = 1;} - else { - app.u.throwGMessage("In admin.calls.adminPrivateSearch, no query object passed."); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = 'adminPrivateSearch'; - obj.mode = 'elastic-native'; - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminPrivateSearch'; - app.model.addDispatchToQ(obj,Q); - } - }, //adminPrivateSearch - - - - - - - - - adminProjectList : { - init : function(_tag,Q) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminProjectList" - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(_tag,Q); - } - else { -// app.u.dump(' -> data is local'); - app.u.handleCallback(_tag); - } - return r; - }, - dispatch : function(_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminProjectList","_tag" : _tag},Q || 'immutable'); - } - },//adminProjectList - - - - adminProjectCreate : { - init : function(obj,_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = "adminProjectCreate"; - this.dispatch(obj,_tag,Q); - return 1; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = "adminProjectCreate"; - obj._tag = _tag || {}; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - },//adminProjectCreate - - adminProjectDetail : { - init : function(uuid,_tag,Q) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = "adminProjectDetail|"+uuid; - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(uuid,_tag,Q); - } - else { - app.u.handleCallback(_tag); - } - return r; - }, - dispatch : function(uuid,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminProjectDetail","files":true,"UUID":uuid,"_tag" : _tag},Q || 'immutable'); - } - },//adminProjectDetail - - - - - - - adminOrderList : { - init : function(obj,_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = "adminOrderList"; - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(obj,_tag,Q); - } - else { - app.u.handleCallback(_tag); - } - return 1; - }, - dispatch : function(obj,_tag,Q) { - obj._tag = _tag; - obj._cmd = "adminOrderList"; - app.model.addDispatchToQ(obj,Q); - } - }, //adminOrderList -//never look locally for data. Always make sure to load latest from server to ensure it's up to date. -//order info is critial - adminOrderDetail : { - init : function(orderID,_tag,Q) { - var r = 0; - if(orderID) { - _tag = _tag || {}; - _tag.datapointer = "adminOrderDetail|"+orderID; - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(orderID,_tag,Q); - } - else { - app.u.handleCallback(_tag); - } - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.adminOrderDetail, orderID not passed."); - } - return r; - }, - dispatch : function(orderID,_tag,Q) { - var cmdObj = {}; - cmdObj.orderid = orderID; - cmdObj._tag = _tag; - cmdObj._cmd = "adminOrderDetail"; - app.model.addDispatchToQ(cmdObj,Q); - } - }, //adminOrderDetail - -//do not store this. if you do, update order editor and be sure datapointer is orderid specific. -/* -This is also true for appPaymentMethods -if order total is zero, zero is only payment method. -if paypalEC is on order, only paypalEC shows up. (paypal restriction of payment and order MUST be equal) -if giftcard is on there, no paypal will appear. -*/ - adminOrderPaymentMethods : { - - init : function(obj,_tag,Q) { - this.dispatch(obj,_tag,Q); - return 1; - }, - - dispatch : function(obj,_tag,Q){ - obj._cmd = 'adminOrderPaymentMethods'; - obj._tag = _tag || {}; - obj._tag.datapointer = 'adminOrderPaymentMethods'; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - - }, //adminOrderPaymentMethods - -//updating an order is a critical function and should ALWAYS be immutable. - adminOrderMacro : { - init : function(orderID,updates,_tag) { - var r = 0; - if(orderID) { - this.dispatch(orderID,updates,_tag); - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.adminOrderMacro, orderID not passed."); - } - return r; - }, - dispatch : function(orderID,updates,_tag) { - cmdObj = {}; - cmdObj._cmd = 'adminOrderMacro'; - cmdObj.orderid = orderID; - cmdObj['@updates'] = updates; - cmdObj._tag = _tag || {}; - app.model.addDispatchToQ(cmdObj,'immutable'); - } - }, //adminOrderMacro - adminOrderSearch : { - init : function(elasticObj, _tag, Q) { - this.dispatch(elasticObj,_tag,Q); - return 1; - }, - dispatch : function(elasticObj,_tag,Q){ - var obj = {}; - obj._cmd = "adminOrderSearch"; - obj.DETAIL = '9'; - obj.ELASTIC = elasticObj; - obj._tag = _tag || {}; - obj._tag.datapointer = "adminOrderSearch"; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - }, //adminOrderSearch - adminOrderPaymentAction : { - init : function(cmdObj,_tag) { - this.dispatch(cmdObj,_tag) - return 1; - }, - dispatch : function(cmdObj,_tag) { - cmdObj._cmd = 'adminOrderPaymentAction'; - cmdObj._tag = _tag || {}; - app.model.addDispatchToQ(cmdObj,'immutable'); - } - }, //adminOrderPaymentAction - - - adminPartnerSet : { - init : function(obj,_tag) { - obj._cmd = 'adminPartnerSet' - obj._tag = _tag || {}; - obj._tag.datapointer = "adminPartnerSet"; - app.model.addDispatchToQ(obj,'immutable'); - } - }, - - - adminProductManagementCategoryList : { - init : function(_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = "adminProductManagementCategoryList"; - if(app.model.fetchData(_tag.datapointer) == false) { - this.dispatch(_tag,Q); - } - else { - app.u.handleCallback(_tag) - } - }, - dispatch : function(_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminProductManagementCategoriesComplete","_tag":_tag},Q); - } - }, //adminProductManagementCategoryList - - - - adminSyndicationDetail : { - init : function(DST,_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = "adminSyndicationDetail|"+DST; - this.dispatch(DST,_tag,Q); - return 1; - }, - dispatch : function(DST,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminSyndicationDetail","_tag":_tag,'DST':DST},Q || 'mutable'); - } - }, //adminSyndicationDetail - - - adminSyndicationMacro : { - init : function(DST, macros,_tag,Q) { - var r = 0; - if(DST && macros && macros.length) { - r = 1; - _tag = _tag || {}; - _tag.datapointer = "adminSyndicationMacro"; - this.dispatch(DST,macros,_tag,Q); - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminSyndicationMacro, macros ["+typeof macros+"] and/or DST ["+DST+"] is empty or not passed","gMessage":true}); - } - return r; - }, - dispatch : function(DST,macros,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminSyndicationMacro","DST":DST,"@updates":macros,"_tag":_tag,'DST':DST},Q || 'mutable'); - } - }, //adminSyndicationDetail - - - - adminSyndicationHistory : { - init : function(DST,_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = "adminSyndicationHistory"; - this.dispatch(DST,_tag,Q); - return 1; - }, - dispatch : function(DST,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminSyndicationHistory","_tag":_tag,'DST':DST},Q || 'mutable'); - } - }, //adminSyndicationHistory - - adminSyndicationFeedErrors : { - init : function(DST,_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = "adminSyndicationFeedErrors"; - this.dispatch(DST,_tag,Q); - return 1; - }, - dispatch : function(DST,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminSyndicationFeedErrors","_tag":_tag,'DST':DST},Q || 'mutable'); - } - }, //adminSyndicationFeedErrors - - adminSyndicationDebug : { - init : function(DST,obj,_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = "adminSyndicationDebug"; - this.dispatch(DST,obj,_tag,Q); - return 1; - }, - dispatch : function(DST,obj,_tag,Q) { - obj = obj || {}; - obj._cmd = "adminSyndicationDebug"; - obj._tag = _tag; - obj.DST = DST; - app.model.addDispatchToQ(obj,Q || 'mutable'); - } - }, //adminSyndicationDebug - - adminSyndicationListFiles : { - init : function(DST,_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = "adminSyndicationListFiles"; - this.dispatch(DST,_tag,Q); - return 1; - }, - dispatch : function(DST,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"adminSyndicationListFiles","_tag":_tag,'DST':DST},Q || 'mutable'); - } - }, //adminSyndicationListFiles - - -// @updates holds the macros. -// CLOSE -> no params -// APPEND -> pass note. -// leave this one as a call. - - adminTicketMacro : { - init : function(ticketid,macro,_tag,Q) { - var r = 0; - if(ticketid && typeof macro === 'object') { - r = 1; - this.dispatch(ticketid,macro,_tag,Q); - } - else { - $('#globalMessaging').anymessage({"message":"In admin.calls.adminTicketMacro, either ticketid ["+ticketid+"] or macro ["+typeof macro+"] not defined.","gMessage":true}); - } - return r; - }, - dispatch : function(ticketid,macro,_tag,Q) { - var obj = {}; - obj._cmd = "adminTicketMacro"; - obj.ticketid = ticketid; - obj['@updates'] = macro; - obj._tag = _tag || {}; - obj._tag.datapointer = "adminTicketMacro"; - app.model.addDispatchToQ(obj,Q || 'immutable'); - } - }, //adminTicketUpdate - -//obj could contain a 'detail' level. values are open, all or waiting. - adminTicketList : { - init : function(obj,_tag,Q) { - var r = 0; //what is returned. a 1 or a 0 based on # of dispatched entered into q. - _tag = _tag || {}; - _tag.datapointer = "adminTicketList"; - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(obj,_tag,Q); - } - else { - app.u.handleCallback(_tag); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj = obj || {}; - obj._tag = _tag; - obj._cmd = "adminTicketList"; - app.model.addDispatchToQ(obj,Q); - } - }, //adminTicketList - - -//obj requires panel and pid and sub. sub can be LOAD or SAVE - adminUIDomainPanelExecute : { - init : function(obj,_tag,Q) { - _tag = _tag || {}; -//save and load 'should' always have the same data, so the datapointer is shared. - _tag.datapointer = "adminUIDomainPanelExecute|"+obj.domain+"|"+obj.verb; - this.dispatch(obj,_tag,Q); - }, - dispatch : function(obj,_tag,Q) { - obj['_cmd'] = "adminUIDomainPanelExecute"; - obj["_tag"] = _tag; - app.model.addDispatchToQ(obj,Q); - } - }, //adminUIProductPanelList - - -//obj requires sub and sref. sub can be LOAD or SAVE -//reload is also supported. - adminUIBuilderPanelExecute : { - init : function(obj,_tag,Q) { - _tag = _tag || {}; - if(obj['sub'] == 'EDIT') { - _tag.datapointer = "adminUIBuilderPanelExecute|edit"; - } - else if(obj['sub'] == 'SAVE') { - _tag.datapointer = "adminUIBuilderPanelExecute|save"; - } - else { - //catch. some new verb or a format that doesn't require localStorage. - } - this.dispatch(obj,_tag,Q); - }, - dispatch : function(obj,_tag,Q) { - obj['_cmd'] = "adminUIBuilderPanelExecute"; - obj['_SREF'] = sref; - obj["_tag"] = _tag; - app.model.addDispatchToQ(obj,Q); - } - }, //adminUIProductPanelList - -//obj requires panel and pid and sub. sub can be LOAD or SAVE - adminUIProductPanelExecute : { - init : function(obj,_tag,Q) { - if(obj && obj.panel && obj.pid && obj.sub) { - _tag = _tag || {}; -//save and load 'should' always have the same data, so the datapointer is shared. - if(obj['sub']) { - _tag.datapointer = "adminUIProductPanelExecute|"+obj.pid+"|load|"+obj.panel; - } - this.dispatch(obj,_tag,Q); - } - else { - app.u.throwGMessage("In admin.calls.adminUIProductPanelExecute, required param (panel, pid or sub) left blank. see console."); app.u.dump(obj); - } - }, - dispatch : function(obj,_tag,Q) { - obj['_cmd'] = "adminUIProductPanelExecute"; - obj["_tag"] = _tag; - app.model.addDispatchToQ(obj,Q); - } - }, //adminUIProductPanelExecute - - + }, //adminUIBuilderPanelExecute adminPriceScheduleList : { init : function(_tag,q) { var r = 0; //what is returned. a 1 or a 0 based on # of dispatched entered into q. _tag = _tag || {}; _tag.datapointer = "adminPriceScheduleList"; - if(app.model.fetchData(_tag.datapointer) == false) { + if(_app.model.fetchData(_tag.datapointer) == false) { r = 1; this.dispatch(_tag,q); } else { - app.u.handleCallback(_tag); + _app.u.handleCallback(_tag); } return r; }, dispatch : function(_tag,q) { - app.model.addDispatchToQ({"_cmd":"adminPriceScheduleList","_tag":_tag},q); + _app.model.addDispatchToQ({"_cmd":"adminPriceScheduleList","_tag":_tag},q); } }, //adminPriceScheduleList - adminWholesaleScheduleDetail : { - init : function(scheduleID,_tag,q) { - var r = 0; //what is returned. a 1 or a 0 based on # of dispatched entered into q. - _tag = _tag || {}; - _tag.datapointer = "adminWholesaleScheduleDetail|"+scheduleID; - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(_tag,q); - } - else { - app.u.handleCallback(_tag); - } - return r; - }, - dispatch : function(scheduleID,_tag,q) { - app.model.addDispatchToQ({"_cmd":"adminWholesaleScheduleDetail","schedule":scheduleID,"_tag":_tag},q); - } - }, //adminPriceScheduleList - - //this call is duplicated inside the admin extension so that the datapointer can be partition specific, to reduce redundant calls. //the call is somewhat heavy and things like the rss tool, which needs a list of 'lists', use this to generate the list. @@ -1307,145 +426,67 @@ if giftcard is on there, no paypal will appear. _tag = _tag || {}; obj = obj || {}; obj.root = obj.root || '.'; - _tag.datapointer = obj.filter ? 'appCategoryList|'+app.vars.partition+'|'+obj.filter+'|'+obj.root : 'appCategoryList|'+app.vars.partition+'|'+obj.root + _tag.datapointer = obj.filter ? 'appCategoryList|'+_app.vars.partition+'|'+obj.filter+'|'+obj.root : 'appCategoryList|'+_app.vars.partition+'|'+obj.root var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. - if(app.model.fetchData(_tag.datapointer) == false) { + if(_app.model.fetchData(_tag.datapointer) == false) { r = 1; this.dispatch(obj,_tag,Q); } else { - app.u.handleCallback(_tag) + _app.u.handleCallback(_tag) } return r; }, dispatch : function(obj,_tag,Q) { obj['_cmd'] = "appCategoryList"; obj['_tag'] = _tag; - app.model.addDispatchToQ(obj,Q || mutable); + _app.model.addDispatchToQ(obj,Q || mutable); } }, //appCategoryList -//This will get a copy of the config.js file. - appConfig : { - init : function(_tag,Q) { - this.dispatch(_tag,Q); - return 1; - }, - dispatch : function(_tag,Q) { - app.model.addDispatchToQ({"_cmd":"appConfig","_tag" : _tag},Q); - } - }, //appConfig - - //obj.PATH = .cat.safe.id - appPageGet : { - init : function(obj,_tag,Q) { - var r = 0; - if(obj.PATH) { - _tag = _tag || {}; - _tag.datapointer = 'appPageGet|'+obj.PATH; //no local storage of this. ### need to explore solutions. - this.dispatch(obj,_tag,Q); - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.appPageGet, obj.path is required and was not specified."); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = "appPageGet"; - obj._tag = _tag; - app.model.addDispatchToQ(obj,Q); - } - }, //appPageGet - appPageSet : { - init : function(obj,_tag,Q) { - var r = 0; - if(!$.isEmptyObject(obj)) { - r = 1; - _tag = _tag || {}; - this.dispatch(obj,_tag,Q); - } - else { - app.u.throwGMessage("In admin.calls.appPageSet, obj is empty."); - } - return 1; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = 'appPageSet'; - obj._tag = _tag; - app.model.addDispatchToQ(obj,Q); - } - }, //appPageSet - - - appResource : { - init : function(filename,_tag,Q) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = "appResource|"+filename; - - if(app.model.fetchData(_tag.datapointer) == false) { - this.dispatch(filename,_tag,Q); - r = 1; - } - else { - app.u.handleCallback(_tag); - } - - return r; - }, - dispatch : function(filename,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"appResource","filename":filename,"_tag" : _tag},Q); - } - }, //appResource - - - authNewAccountCreate : { + appPageGet : { init : function(obj,_tag,Q) { var r = 0; - if(typeof obj == 'object' && obj.email && obj.domain && obj.phone && obj.firstname && obj.lastname && obj.company) { + if(obj.PATH) { + _tag = _tag || {}; + _tag.datapointer = 'appPageGet|'+obj.PATH; //no local storage of this. ### need to explore solutions. this.dispatch(obj,_tag,Q); r = 1; } else { - app.u.throwGMessage("In admin.calls.authNewAccountCreate, some required attributes were missing."); - app.u.dump(" -> All of the fields in the form must be populated. obj follows: "); app.u.dump(obj); + _app.u.throwGMessage("In admin.calls.appPageGet, obj.path is required and was not specified."); } return r; }, dispatch : function(obj,_tag,Q) { - obj._cmd = "authNewAccountCreate"; - obj._tag = _tag || {}; - _tag.datapointer = "authNewAccountCreate"; - app.model.addDispatchToQ(obj,Q); + obj._cmd = "appPageGet"; + obj._tag = _tag; + _app.model.addDispatchToQ(obj,Q); } - }, + }, //appPageGet - authPasswordReset : { - init : function(login,_tag,Q) { + appResource : { + init : function(filename,_tag,Q) { var r = 0; - if(login) { - this.dispatch(login,_tag,Q); + _tag = _tag || {}; + _tag.datapointer = "appResource|"+filename; + + if(_app.model.fetchData(_tag.datapointer) == false) { + this.dispatch(filename,_tag,Q); r = 1; } else { - app.u.throwGMessage("In admin.calls.authPasswordReset, login was not passed."); + _app.u.handleCallback(_tag); } + return r; }, - dispatch : function(login,_tag,Q) { - var obj = {}; - obj.login = login; - obj._cmd = "authPasswordReset"; - obj._tag = _tag || {}; - _tag.datapointer = "authPasswordReset"; - app.model.addDispatchToQ(obj,Q); + dispatch : function(filename,_tag,Q) { + _app.model.addDispatchToQ({"_cmd":"appResource","filename":filename,"_tag" : _tag},Q); } - }, - - + }, //appResource finder : { @@ -1463,7 +504,7 @@ if giftcard is on there, no paypal will appear. obj.path = path; obj.position = position; obj['_tag'].datapointer = "adminNavcatProductInsert|"+path+"|"+pid; - app.model.addDispatchToQ(obj,'immutable'); + _app.model.addDispatchToQ(obj,'immutable'); } }, //adminNavcatProductInsert @@ -1478,180 +519,16 @@ if giftcard is on there, no paypal will appear. obj.pid = pid; obj.path = path; obj['_tag'].datapointer = "adminNavcatProductDelete|"+path+"|"+pid; - app.model.addDispatchToQ(obj,'immutable'); + _app.model.addDispatchToQ(obj,'immutable'); } } //adminNavcatProductDelete - }, //finder - - - bossUserCreate : { - init : function(obj,_tag,Q) { - var r = 0; - Q = Q || 'immutable'; - if(!$.isEmptyObject(obj)) { - this.dispatch(obj,_tag,Q); - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.bossUserCreate, obj is empty."); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = 'bossUserCreate'; - obj._tag = _tag || {}; - obj._tag.datapointer = 'bossUserCreate'; - app.model.addDispatchToQ(obj,Q); - } - }, - - bossUserList : { - init : function(_tag,Q) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = 'bossUserList'; - if(app.model.fetchData(_tag.datapointer) == false) { - this.dispatch(_tag,Q); - r = 1; - } - else { - app.u.handleCallback(_tag); - } - return r; - }, - dispatch : function(_tag,Q) { - Q = Q || 'immutable'; - var obj = {_cmd : 'bossUserList'}; - obj._tag = _tag || {}; - obj._tag.datapointer = 'bossUserList'; - app.model.addDispatchToQ(obj,Q); - } - }, //bossUserList - - bossUserDetail : { - init : function(luser,_tag,Q) { - var r = 0; - Q = Q || 'immutable'; - _tag = _tag || {}; - _tag.datapointer = 'bossUserDetail|'+luser; - if(luser) { - if(app.model.fetchData(_tag.datapointer) == false) { - r = 1; - this.dispatch(luser,_tag,Q); - } - else { - app.u.handleCallback(_tag); - } - } - else { - app.u.throwGMessage("In admin.calls.bossUserDetail, L user is undefined and required."); - } - return r; - }, - dispatch : function(luser,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"bossUserDetail","login":luser,"_tag" : _tag},Q); - } - }, //bossUserDetail - - bossUserDelete : { - init : function(luser,_tag,Q) { - var r = 0; - Q = Q || 'immutable'; - if(luser) { - this.dispatch(luser,_tag,Q); - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.bossUserDelete, uid is undefined and required."); - } - return r; - }, - dispatch : function(luser,_tag,Q) { - _tag = _tag || {}; - _tag.datapointer = 'bossUserDelete|'+luser; - app.model.addDispatchToQ({"_cmd":"bossUserDelete","login":luser,"_tag" : _tag},Q); - } - }, //bossUserDelete - bossUserUpdate : { - init : function(obj,_tag,Q) { - var r = 0; - Q = Q || 'immutable'; - if(!$.isEmptyObject(obj) && obj.luser) { - this.dispatch(obj,_tag,Q); - r = 1; - } - else { - app.u.throwGMessage("In admin.calls.bossUserUpdate, obj is empty or obj.luser is not set."); - app.u.dump(obj); - } - return r; - }, - dispatch : function(obj,_tag,Q) { - obj._cmd = 'bossUserUpdate'; - obj._tag = _tag || {}; - obj._tag.datapointer = 'bossUserUpdate|'+obj.luser; - app.model.addDispatchToQ(obj,Q); - } - }, - - - - helpSearch : { - init : function(keywords,_tag,Q) { - app.u.dump("BEGIN admin.calls.helpSearch"); - app.u.dump(" -> keywords: "+keywords); - var r = 0; - if(keywords) { - _tag = _tag || {}; - _tag.datapointer = 'helpSearch|'+keywords; - if(app.model.fetchData(_tag.datapointer) == false) { - this.dispatch(keywords,_tag,Q); - r = 1; - } - else { - app.u.handleCallback(_tag); - } - } - else { - app.u.throwGMessage("In admin.calls.helpSearch, keywords not specified."); - } - return 1; - }, - dispatch : function(keywords,_tag,Q) { - app.model.addDispatchToQ({_cmd:'helpSearch','keywords':keywords,'_tag':_tag},Q || 'mutable'); - } - }, //helpSearch + } //finder - helpDocumentGet : { - init : function(docid,_tag,Q) { - if(docid) { - var r = 0; - _tag = _tag || {}; - _tag.datapointer = 'helpDocumentGet|'+docid; -// if(app.model.fetchData(_tag.datapointer) == false) { - this.dispatch(docid,_tag,Q); -// r = 1; -// } -// else { -// app.u.handleCallback(_tag); -// } - } - else { - app.u.throwGMessage("In admin.calls.helpDocumentGet, docid not specified."); - } - return r; - }, - dispatch : function(docid,_tag,Q) { - app.model.addDispatchToQ({_cmd : 'helpDocumentGet','_tag':_tag,'docid':docid},Q || 'immutable'); - } - } //helpDocumentGet }, //calls - - //////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ @@ -1663,31 +540,32 @@ if giftcard is on there, no paypal will appear. //the callback is auto-executed as part of the extensions loading process. init : { onSuccess : function() { - app.u.dump('BEGIN app.ext.admin.init.onSuccess '); +// _app.u.dump('BEGIN _app.ext.admin.init.onSuccess '); var r = true; //return false if extension can't load. (no permissions, wrong type of session, etc) -//app.u.dump("DEBUG - template url is changed for local testing. add: "); -$('title').append(" - release: "+app.vars.release).prepend(document.domain+' - '); -app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/templates.html',theseTemplates); -app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/downloads.html',['downloadsPageTemplate']); +//_app.u.dump("DEBUG - template url is changed for local testing. add: "); +$('title').append(" - release: "+_app.vars.release).prepend(document.domain+' - '); +_app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/templates.html',theseTemplates); +_app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/downloads.html',['downloadsPageTemplate']); //SANITY - loading this file async causes a slight pop. but loading it inline caused the text to not show up till the file was done. //this is the lesser of two weevils. -app.rq.push(['css',0,'https://fonts.googleapis.com/css?family=PT+Sans:400,700','google_pt_sans']); -app.rq.push(['script',0,app.vars.baseURL+'extensions/admin/resources/legacy_compat.js']); +//_app.rq.push(['css',0,'https://fonts.googleapis.com/css?family=PT+Sans:400,700','google_pt_sans']); +_app.rq.push(['script',0,_app.vars.baseURL+'app-admin/resources/legacy_compat.js']); +_app.rq.push(['script',0,_app.vars.baseURL+'app-admin/resources/tinymce-4.0.12/tinymce.min.js']); +_app.rq.push(['script',0,_app.vars.baseURL+'app-admin/resources/tinymce-4.0.12/jquery.tinymce.min.js']); -/* used for html editor. */ -app.rq.push(['css',0,app.vars.baseURL+'extensions/admin/resources/jHtmlArea-0.7.5.ExamplePlusSource/style/jHtmlArea.ColorPickerMenu.css','jHtmlArea_ColorPickerMenu']); -app.rq.push(['css',0,app.vars.baseURL+'extensions/admin/resources/jHtmlArea-0.7.5.ExamplePlusSource/style/jHtmlArea.css','jHtmlArea']); +/* used for html editor. +_app.rq.push(['css',0,_app.vars.baseURL+'app-admin/resources/jHtmlArea-0.8/style/jHtmlArea.ColorPickerMenu.css','jHtmlArea_ColorPickerMenu']); +_app.rq.push(['css',0,_app.vars.baseURL+'app-admin/resources/jHtmlArea-0.8/style/jHtmlArea.css','jHtmlArea']); //note - the editor.css file that comes with jhtmlarea is NOT needed. just sets the page bgcolor to black. // colorpicker isn't loaded until jhtmlarea is done to avoid a js error due to load order. -app.rq.push(['script',0,app.vars.baseURL+'extensions/admin/resources/jHtmlArea-0.7.5.ExamplePlusSource/scripts/jHtmlArea-0.7.5.js',function(){ - app.rq.push(['script',0,app.vars.baseURL+'extensions/admin/resources/jHtmlArea-0.7.5.ExamplePlusSource/scripts/jHtmlArea.ColorPickerMenu-0.7.0.min.js']) +_app.rq.push(['script',0,_app.vars.baseURL+'app-admin/resources/jHtmlArea-0.8/jHtmlArea-0.8.min.js',function(){ + _app.rq.push(['script',0,_app.vars.baseURL+'app-admin/resources/jHtmlArea-0.8/jHtmlArea.ColorPickerMenu-0.8.min.js']) }]); - - + */ return r; }, onError : function(d) { @@ -1700,161 +578,105 @@ app.rq.push(['script',0,app.vars.baseURL+'extensions/admin/resources/jHtmlArea-0 //executed when the extension loads initExtension : { onSuccess : function() { - app.u.dump('BEGIN app.ext.admin.initUserInterface.onSuccess '); - var L = app.rq.length-1; -//load any remaining resources into the app. +// _app.u.dump('BEGIN _app.ext.admin.initUserInterface.onSuccess '); + var L = _app.rq.length-1; +//load any remaining resources into the _app. for(var i = L; i >= 0; i -= 1) { - app.u.loadResourceFile(app.rq[i]); - app.rq.splice(i, 1); //remove once handled. + _app.u.loadResourceFile(_app.rq[i]); + _app.rq.splice(i, 1); //remove once handled. } - app.rq.push = app.u.loadResourceFile; //reassign push function to auto-add the resource. - -if(app.u.getBrowserInfo().substr(0,4) == 'msie' && parseFloat(navigator.appVersion.split("MSIE")[1]) < 10) { - app.u.throwMessage("

                                                          In an effort to provide the best user experience for you and to also keep our development team sane, we've opted to optimize our user interface for webkit based browsers. These include; Safari, Chrome and FireFox. Each of these are free and provide a better experience, including more diagnostics for us to maintain our own app framework.<\/p>

                                                          Our store apps support IE8+<\/b><\/p>"); - } - - -//get list of domains and show chooser. - var $domainChooser = $("

                                                          ").attr({'id':'domainChooserDialog','title':'Choose a domain to work on'}).addClass('displayNone').appendTo('body'); - $domainChooser.dialog({ - 'autoOpen':false, - 'modal':true, - 'width': '90%', - 'height': 500, - 'closeOnEscape': false, - open: function(event, ui) {$(".ui-dialog-titlebar-close", $(this).parent()).hide();} //hide 'close' icon. will close on domain selection - }); + _app.rq.push = _app.u.loadResourceFile; //reassign push function to auto-add the resource. -//** 201320 -> no more hunting and pecking for domain. stored in dps and if it isn't there, the user will be prompted (in showHeader) to select one. -//the domainChange will set these three vars in localStorage so they'll be there next time. -//all three of the vars are required. images require the https_domain and several configDetail calls require partition. -var adminObj = app.model.dpsGet('admin'); -if(!$.isEmptyObject(adminObj)) { - app.vars.domain = adminObj.domain; - app.vars.partition = adminObj.partition; - app.vars.https_domain = adminObj.https_domain; - } - - app.u.dump(" -> domain: "+app.vars.domain); - app.u.dump(" -> partition: "+app.vars.partition); - app.u.dump(" -> https_domain: "+app.vars.https_domain); - - if(!app.vars.domain || isNaN(app.vars.partition) || !app.vars.https_domain) { - app.u.dump(" -> either domain, partition or https_domain not set. set domain to blank to trigger domain chooser."); - app.vars.domain = false; // + if(_app.u.getBrowserInfo().substr(0,4) == 'msie' && parseFloat(navigator.appVersion.split("MSIE")[1]) < 10) { + _app.u.throwMessage("

                                                          In an effort to provide the best user experience for you and to also keep our development team sane, we've opted to optimize our user interface for webkit based browsers. These include; Safari, Chrome and FireFox. Each of these are free and provide a better experience, including more diagnostics for us to maintain our own app framework.<\/p>

                                                          Our store apps support IE8+<\/b><\/p>"); } -//make sure all the links in the header use the proper syntax. - $('.bindByAnchor','#mastHead').each(function(){ - // app.u.dump("BEGIN #mastHead rewriteLink"); - app.ext.admin.u.rewriteLink($(this)); - }) -//if supported, update hash while navigating. -// see handleHashState function for what this is and how it works. - if("onhashchange" in window) { // does the browser support the hashchange event? -// app.u.dump("WOOT! browser supports hashchange"); - _ignoreHashChange = false; //global var. when hash is changed from JS, set to true. see handleHashState for more info on this. - window.onhashchange = function () { -// app.u.dump("Hash has changed."); - app.ext.admin.u.handleHashState(); - } - } - //create shortcuts. these are used in backward compatibility areas where brian loads the content. - window.navigateTo = app.ext.admin.a.navigateTo; - window.showUI = app.ext.admin.a.showUI; - window.loadElement = app.ext.admin.a.loadElement; - window.prodlistEditorUpdate = app.ext.admin.a.uiProdlistEditorUpdate; - window.changeDomain = app.ext.admin.a.changeDomain; - window.linkOffSite = app.ext.admin.u.linkOffSite; - window.adminUIDomainPanelExecute = app.ext.admin.u.adminUIDomainPanelExecute; - window._ignoreHashChange = false; // see handleHashState to see what this does. - - -document.write = function(v){ - if(console && console.warn){ - console.warn("document.write was executed. That's bad mojo. Rewritten to $('body').append();"); - console.log("document.write contents: "+v); - } - $("body").append(v); - } + window.navigateTo = _app.ext.admin.a.navigateTo; + window.loadElement = _app.ext.admin.a.loadElement; + window.prodlistEditorUpdate = _app.ext.admin.a.uiProdlistEditorUpdate; + window.changeDomain = _app.ext.admin.a.changeDomain; + window.linkOffSite = _app.ext.admin.u.linkOffSite; -var uriParams = {}; -var ps = window.location.href; //param string. find a regex for this to clean it up. -if(ps.indexOf('?') >= 1) { - ps = ps.split('?')[1]; //ignore everything before the first questionmark. - if(ps.indexOf('#') == 0){} //'could' happen if uri is ...admin.html?#doSomething. no params, so do nothing. - else { - if(ps.indexOf('#') >= 1) {ps = ps.split('#')[0]} //uri params should be before the # -// app.u.dump(ps); - uriParams = app.u.kvp2Array(ps); - } -// app.u.dump(uriParams); - } +//a document.write and app are like dogs and cats. They don't get along. this is the workaround + document.write = function(v){ + _app.u.dump("document.write was executed. That's bad mojo. Rewritten to $('body').append();",'warn'); + _app.u.dump("document.write contents: "+v); + $("body").append(v); + } -// app.u.dump(" -> uriParams"); app.u.dump(uriParams); -if(uriParams.trigger == 'adminPartnerSet') { - app.u.dump(" -> execute adminPartnerSet call"); - //Merchant is most likely returning to the app from a partner site for some sort of verification - app.ext.admin.calls.adminPartnerSet.init(uriParams,{'callback':'showHeader','extension':'admin'}); - app.model.dispatchThis('immutable'); - } + var uriParams = {}; + var ps = window.location.href; //param string. find a regex for this to clean it up. + if(ps.indexOf('?') >= 1) { + ps = ps.split('?')[1]; //ignore everything before the first questionmark. + if(ps.indexOf('#') == 0){} //'could' happen if uri is ...admin.html?#doSomething. no params, so do nothing. + else { + if(ps.indexOf('#') >= 1) {ps = ps.split('#')[0]} //uri params should be before the # + // _app.u.dump(ps); + uriParams = _app.u.kvp2Array(ps); + } + // _app.u.dump(uriParams); + } + _app.vars.trigger = uriParams.trigger; +//Merchant is most likely returning to the app from a partner site for some sort of verification + if(_app.vars.trigger == 'adminPartnerSet') { + _app.u.dump(" -> execute adminPartnerSet call"); _app.u.dump(uriParams); + uriParams._cmd = 'adminPartnerSet'; + uriParams._tag = {'callback':'showHeader','extension':'admin','datapointer':'adminPartnerSet'}; + _app.model.addDispatchToQ(uriParams,"immutable"); + _app.model.dispatchThis('immutable'); + } -if(app.vars.debug) { -// $('button','#debugPanel').button(); - var $DP = $('#debugPanel'); - $DP.show().find('.debugMenu').menu() - $DP.append("

                                                          debug: "+app.vars.debug+"
                                                          v: "+app.vars.release+"

                                                          "); - $('').attr({'type':'text','placeholder':'destroy','size':'10'}).on('blur',function(){ - app.model.destroy($(this).val()); - app.u.dump("DEBUG: "+$(this).val()+" was just removed from memory and local storage"); - $(this).val(''); - }).appendTo($DP); - $('#jtSectionTab').show(); - } + if(_app.vars.debug) { + // $('button','#debugPanel').button(); + var $DP = $('#debugPanel'); + $DP.show().find('.debugMenu').menu() + $DP.append("
                                                          debug: "+_app.vars.debug+"
                                                          v: "+_app.vars.release+"

                                                          "); + $('').attr({'type':'text','placeholder':'destroy','size':'10'}).on('blur',function(){ + _app.model.destroy($(this).val()); + _app.u.dump("DEBUG: "+$(this).val()+" was just removed from memory and local storage"); + $(this).val(''); + }).appendTo($DP); + } -//app.u.dump("Is anycommerce? document.domain: "+document.domain+" and uriParams.anycommerce: ["+uriParams.anycommerce+"]"); //the zoovy branding is in place by default. override if on anycommerce.com OR if an anycommerce URI param is present (for debugging) -if(document.domain && document.domain.toLowerCase().indexOf('anycommerce') > -1) { - app.u.dump(" -> Treat as anycommerce"); - $('.logo img').attr('src','app-admin/images/anycommerce_logo-173x30.png'); - $('body').addClass('isAnyCommerce'); - } -else { - app.u.dump(" -> Treat as zoovy"); - $('body').addClass('isZoovy'); //displays all the Zoovy only content (will remain hidden for anyCommerce) - } - - -//if user is logged in already (persistent login), take them directly to the UI. otherwise, have them log in. -//the code for handling the support login is in the thisisanadminsession function (looking at uri) -if(app.u.thisIsAnAdminSession()) { - app.ext.admin.u.showHeader(); - } -else if(uriParams.show == 'acreate') { - app.ext.admin.u.handleAppEvents($('#createAccountContainer')); - $('#appPreView').css('position','relative').animate({right:($('body').width() + $("#appPreView").width() + 100)},'slow','',function(){ - $("#appPreView").hide(); - $('#createAccountContainer').css({'left':'1000px','position':'relative'}).removeClass('displayNone').animate({'left':'0'},'slow'); - }); - } -else { - app.ext.admin.u.handleAppEvents($('#appLogin')); - $('#appPreView').css('position','relative').animate({right:($('body').width() + $("#appPreView").width() + 100)},'slow','',function(){ - $("#appPreView").hide(); - $('#appLogin').css({'left':'1000px','position':'relative'}).removeClass('displayNone').animate({'left':'0'},'slow'); - }); - } - - - - + if(document.domain && document.domain.toLowerCase().indexOf('anycommerce') > -1) { + _app.u.dump(" -> Treat as anycommerce"); + $('.logo img').attr('src','app-admin/images/anycommerce_logo-173x30.png'); + $('body').addClass('isAnyCommerce'); + } + else { + _app.u.dump(" -> Treat as zoovy"); + $('body').addClass('isZoovy'); //displays all the Zoovy only content (will remain hidden for anyCommerce) + } + //if user is logged in already (persistent login), take them directly to the UI. otherwise, have them log in. + //the code for handling the support login is in the thisisanadminsession function (looking at uri) + if(_app.u.thisIsAnAdminSession()) { + _app.ext.admin.u.showHeader(); + } + else if(uriParams.show == 'acreate') { + _app.u.handleAppEvents($('#createAccountContainer')); + $('#appPreView').css('position','relative').animate({right:($('body').width() + $("#appPreView").width() + 100)},'slow','',function(){ + $("#appPreView").hide(); + $('#createAccountContainer').css({'left':'1000px','position':'relative'}).removeClass('displayNone').animate({'left':'0'},'slow'); + }); + } + else { + _app.u.handleAppEvents($('#appLogin')); + $('#appPreView').css('position','relative').animate({right:($('body').width() + $("#appPreView").width() + 100)},'slow','',function(){ + $("#appPreView").hide(); + $('#appLogin').css({'left':'1000px','position':'relative'}).removeClass('displayNone').animate({'left':'0'},'slow'); + }); + } + if(!$.support['localStorage']) { + $("#globalMessaging").anymessage({"message":"It appears you have localStorage disabled or are using a browser that does not support the feature. Please enable the feature or upgrade your browser","errtype":"youerr","persistent":true}); + } } }, //initExtension @@ -1881,21 +703,22 @@ SANITY -> jqObj should always be the data-app-role="dualModeContainer" var $DMI = _rtag.jqObj, $tbody = $DMI.find("[data-app-role='dualModeListTbody']:first"), - bindData = app.renderFunctions.parseDataBind($tbody.data('bind')), //creates an object of the data-bind params. - listpointer = app.renderFunctions.parseDataVar(bindData['var']), - data = app.data[_rtag.datapointer]; //shortcut. -// app.u.dump('listpointer: '+listpointer); -// app.u.dump('_rtag.datapointer: '+_rtag.datapointer); -// app.u.dump('data[listpointer]: '); app.u.dump(data[listpointer]); + bindData = _app.renderFunctions.parseDataBind($tbody.data('bind')), //creates an object of the data-bind params. + listpointer = _app.renderFunctions.parseDataVar(bindData['var']), + data = _app.data[_rtag.datapointer]; //shortcut. +// _app.u.dump('listpointer: '+listpointer); +// _app.u.dump('_rtag.datapointer: '+_rtag.datapointer); +// _app.u.dump('data[listpointer]: '); _app.u.dump(data[listpointer]); $DMI.hideLoading(); $tbody.empty(); //data[listpointer] check needs to be a !isemptyobject and NOT a .length check because value could be a hash OR an array. if(listpointer && data && data[listpointer] && !$.isEmptyObject(data[listpointer])) { //no errors have occured and results are present. $tbody.anycontent({'data':data}); - app.u.handleAppEvents($tbody); + _app.u.handleAppEvents($tbody); + _app.u.handleButtons($tbody); if(_rtag.message) { - $('.dualModeListMessaging',$DMI).anymessage(app.u.successMsgObject(_rtag.message)); + $('.dualModeListMessaging',$DMI).anymessage(_app.u.successMsgObject(_rtag.message)); } } else if(listpointer && !$.isEmptyObject(data) && data[listpointer]) { @@ -1910,13 +733,13 @@ SANITY -> jqObj should always be the data-app-role="dualModeContainer" else { //should never get here. $('.dualModeListMessaging',$DMI).anymessage({"message":"In admin.callbacks.DMIUpdateResults.onSuccess, an unknown error occured. DEV: see console for details.","gMessage":true}); - app.u.dump("$DMI.length: "+$DMI.length); - app.u.dump("$DMI instanceof jQuery: "+($DMI instanceof jQuery)); - app.u.dump("$tbody.length: "+$tbody.length); - app.u.dump("listpointer: "+listpointer); - app.u.dump("typeof data: "+typeof data); - app.u.dump("bindData: "); app.u.dump(bindData); -// app.u.dump("_rtag.jqObj"); app.u.dump(_rtag.jqObj); + _app.u.dump("$DMI.length: "+$DMI.length); + _app.u.dump("$DMI instanceof jQuery: "+($DMI instanceof jQuery)); + _app.u.dump("$tbody.length: "+$tbody.length); + _app.u.dump("listpointer: "+listpointer); + _app.u.dump("typeof data: "+typeof data); + _app.u.dump("bindData: "); _app.u.dump(bindData); +// _app.u.dump("_rtag.jqObj"); _app.u.dump(_rtag.jqObj); } @@ -1939,21 +762,20 @@ SANITY -> jqObj should always be the data-app-role="dualModeContainer" //the selector also gets run through jqSelector and hideLoading (if declared) is run. translateSelector : { onSuccess : function(tagObj) { - app.u.dump("BEGIN callbacks.translateSelector"); -// app.u.dump(" -> tagObj: "); app.u.dump(tagObj); - var selector = app.u.jqSelector(tagObj.selector[0],tagObj.selector.substring(1)); //this val is needed in string form for translateSelector. -// app.u.dump(" -> selector: "+selector); +// _app.u.dump(" -> tagObj: "); _app.u.dump(tagObj); + var selector = _app.u.jqSelector(tagObj.selector[0],tagObj.selector.substring(1)); //this val is needed in string form for translateSelector. +// _app.u.dump(" -> selector: "+selector); var $target = $(selector); -// app.u.dump(" -> $target.length: "+$target.length); +// _app.u.dump(" -> $target.length: "+$target.length); if(typeof jQuery().hideLoading == 'function'){$target.hideLoading();} $target.removeClass('loadingBG'); //try to get rid of anything that uses loadingBG (cept prodlists) in favor of show/hideLoading() - var data = app.data[tagObj.datapointer]; + var data = _app.data[tagObj.datapointer]; //merge allows for multiple datasets to be merged together prior to translation. use with caution. - if(tagObj.merge && app.data[tagObj.merge]) { - $.extend(data,app.data[tagObj.merge]); + if(tagObj.merge && _app.data[tagObj.merge]) { + $.extend(data,_app.data[tagObj.merge]); } - app.renderFunctions.translateSelector(selector,app.data[tagObj.datapointer]); - app.ext.admin.u.handleAppEvents($target); + _app.renderFunctions.translateSelector(selector,_app.data[tagObj.datapointer]); + _app.u.handleAppEvents($target); } }, //translateSelector @@ -1961,49 +783,48 @@ SANITY -> jqObj should always be the data-app-role="dualModeContainer" showDataHTML : { onSuccess : function(tagObj) { -// app.u.dump("SUCCESS!"); app.u.dump(tagObj); - $(app.u.jqSelector('#',tagObj.targetID)).removeClass('loadingBG').hideLoading().html(app.data[tagObj.datapointer].html); //.wrap("
                                                          "); +// _app.u.dump("SUCCESS!"); _app.u.dump(tagObj); + $(_app.u.jqSelector('#',tagObj.targetID)).removeClass('loadingBG').hideLoading().html(_app.data[tagObj.datapointer].html); //.wrap(""); } }, //showDataHTML - - +//this callback is called directly by the model when an error 10 occurs. +//no tagObj is passed into the function. test the model code after making changes here. handleLogout : { onSuccess : function(tagObj) { - document.location = 'admin_logout.html' + _app.ext.admin.u.selectivelyNukeLocalStorage(); //get rid of most local storage content. This will reduce issues for users with multiple accounts. + _app.model.destroy('authAdminLogin'); //clears this out of memory and local storage. This would get used during the controller init to validate the session. + if($.support['sessionStorage']) {sessionStorage.clear();} + document.location = 'admin_logout.html' + (tagObj.msg ? "?msg="+encodeURIComponent(tagObj.msg) : ""); } }, -//in cases where the content needs to be reloaded after making an API call, but when a showUI directly won't do (because of sequencing, perhaps) +//in cases where the content needs to be reloaded after making an API call, but when a navigateTo directly won't do (because of sequencing, perhaps) //For example, after new files are added to a ticket (comatability mode), this is executed on a ping to update the page behind the modal. - showUI : { + navigateTo : { onSuccess : function(tagObj) { - if(tagObj && tagObj.path){showUI(tagObj.path) + if(tagObj && tagObj.path){navigateTo(tagObj.path) } else { - app.u.throwGMessage("Warning! Invalid path specified in _rtag on admin.callbacks.showUI.onSuccess."); - app.u.dump("admin.callbacks.showUI.onSuccess tagObj (_rtag)"); - app.u.dump(tagObj); + _app.u.throwGMessage("Warning! Invalid path specified in _rtag on admin.callbacks.navigateTo.onSuccess."); + _app.u.dump("admin.callbacks.navigateTo.onSuccess tagObj (_rtag)"); + _app.u.dump(tagObj); } } - }, //showUI - showDomainConfig : { - onSuccess : function(){ - app.ext.admin.u.domainConfig(); - } - }, + }, //navigateTo + showElementEditorHTML : { onSuccess : function(tagObj) { -// app.u.dump("SUCCESS!"); app.u.dump(tagObj); - var $target = $(app.u.jqSelector('#',tagObj.targetID)) - $target.parent().find('.ui-dialog-title').text(app.data[tagObj.datapointer]['prompt']); //add title to dialog. +// _app.u.dump("SUCCESS!"); _app.u.dump(tagObj); + var $target = $(_app.u.jqSelector('#',tagObj.targetID)) + $target.parent().find('.ui-dialog-title').text(_app.data[tagObj.datapointer]['prompt']); //add title to dialog. var $form = $("").attr('id','editorForm'); //id used in product edit mode. $form.submit(function(event){ event.preventDefault(); //do not post form. - app.ext.admin.u.uiSaveBuilderElement($form,app.data[tagObj.datapointer].id,{'callback':'handleElementSave','extension':'admin','targetID':'elementEditorMessaging'}) - app.model.dispatchThis(); + _app.ext.admin.u.uiSaveBuilderElement($form,_app.data[tagObj.datapointer].id,{'callback':'handleElementSave','extension':'admin','targetID':'elementEditorMessaging'}) + _app.model.dispatchThis(); return false; - }).append(app.data[tagObj.datapointer].html); + }).append(_app.data[tagObj.datapointer].html); $form.append("
                                                          <\/div>"); $target.removeClass('loadingBG').html($form); } @@ -2014,32 +835,34 @@ SANITY -> jqObj should always be the data-app-role="dualModeContainer" onSuccess : function(tagObj) { //First, let the user know the changes are saved. - var msg = app.u.successMsgObject("Thank you, your changes are saved."); + var msg = _app.u.successMsgObject("Thank you, your changes are saved."); msg['_rtag'] = tagObj; //pass in tagObj as well, as that contains info for parentID. - app.u.throwMessage(msg); - if(app.ext.admin.vars.tab) { -// app.u.dump("GOT HERE! app.ext.admin.vars.tab: "+app.ext.admin.vars.tab); - $(app.u.jqSelector('#',app.ext.admin.vars.tab+'Content')).empty().append(app.data[tagObj.datapointer].html) + _app.u.throwMessage(msg); + if(_app.ext.admin.vars.tab) { +// _app.u.dump("GOT HERE! _app.ext.admin.vars.tab: "+_app.ext.admin.vars.tab); + $(_app.u.jqSelector('#',_app.ext.admin.vars.tab+'Content')).empty().append(_app.data[tagObj.datapointer].html) } } }, //handleElementSave showHeader : { onSuccess : function(_rtag){ -// app.u.dump("BEGIN admin.callbacks.showHeader"); -// app.u.dump(" -> app.data["+_rtag.datapointer+"]:"); app.u.dump(app.data[_rtag.datapointer]); + $('body').hideLoading(); +// _app.u.dump("BEGIN admin.callbacks.showHeader"); +// _app.u.dump(" -> _app.data["+_rtag.datapointer+"]:"); _app.u.dump(_app.data[_rtag.datapointer]); //account was just created, skip domain chooser. - if(app.data[_rtag.datapointer] && app.data[_rtag.datapointer].domain) { -// app.u.dump(" -> response contained a domain. use it to set the domain."); - app.ext.admin.a.changeDomain(app.data[_rtag.datapointer].domain,0,'#!dashboard'); + if(_app.data[_rtag.datapointer] && _app.data[_rtag.datapointer].domain) { +// _app.u.dump(" -> response contained a domain. use it to set the domain."); + _app.ext.admin.a.changeDomain(_app.data[_rtag.datapointer].domain); + navigateTo('#!dashboard'); } - app.ext.admin.u.showHeader(); + _app.ext.admin.u.showHeader(); }, onError : function(responseData){ - app.u.throwMessage(responseData); + _app.u.throwMessage(responseData); // if(responseData.errid == "100") { -// app.u.throwMessage("This is most typically due to your system clock not being set correctly. For security, it must be set to both the correct time and timezone."); +// _app.u.throwMessage("This is most typically due to your system clock not being set correctly. For security, it must be set to both the correct time and timezone."); // } //this is the clock issue. $('body').hideLoading(); } @@ -2047,10 +870,10 @@ SANITY -> jqObj should always be the data-app-role="dualModeContainer" handleDomainChooser : { onSuccess : function(tagObj){ - app.u.dump("BEGIN admin.callbacks.handleDomainChooser.onSuccess"); - var data = app.data[tagObj.datapointer]['@DOMAINS']; - var $target = $(app.u.jqSelector('#',tagObj.targetID)); - $target.empty().append("'); - if (options.previewPosition == 'after') { - iFrame.insertAfter(footer); - } else { - iFrame.insertBefore(header); - } - previewWindow = iFrame[iFrame.length - 1].contentWindow || frame[iFrame.length - 1]; - } - } else if (altKey === true) { - if (iFrame) { - iFrame.remove(); - } else { - previewWindow.close(); - } - previewWindow = iFrame = false; - } - if (!options.previewAutoRefresh) { - refreshPreview(); - } - if (options.previewInWindow) { - previewWindow.focus(); - } - } - - // refresh Preview window - function refreshPreview() { - renderPreview(); - } - - function renderPreview() { - var phtml; - if (options.previewHandler && typeof options.previewHandler === 'function') { - options.previewHandler( $$.val() ); - } else if (options.previewParser && typeof options.previewParser === 'function') { - var data = options.previewParser( $$.val() ); - writeInPreview(localize(data, 1) ); - } else if (options.previewParserPath !== '') { - $.ajax({ - type: 'POST', - dataType: 'text', - global: false, - url: options.previewParserPath, - data: options.previewParserVar+'='+encodeURIComponent($$.val()), - success: function(data) { - writeInPreview( localize(data, 1) ); - } - }); - } else { - if (!template) { - $.ajax({ - url: options.previewTemplatePath, - dataType: 'text', - global: false, - success: function(data) { - writeInPreview( localize(data, 1).replace(//g, $$.val()) ); - } - }); - } - } - return false; - } - - function writeInPreview(data) { - if (options.previewInElement) { - $(options.previewInElement).html(data); - } else if (previewWindow && previewWindow.document) { - try { - sp = previewWindow.document.documentElement.scrollTop - } catch(e) { - sp = 0; - } - previewWindow.document.open(); - previewWindow.document.write(data); - previewWindow.document.close(); - previewWindow.document.documentElement.scrollTop = sp; - } - } - - // set keys pressed - function keyPressed(e) { - shiftKey = e.shiftKey; - altKey = e.altKey; - ctrlKey = (!(e.altKey && e.ctrlKey)) ? (e.ctrlKey || e.metaKey) : false; - - if (e.type === 'keydown') { - if (ctrlKey === true) { - li = $('a[accesskey="'+((e.keyCode == 13) ? '\\n' : String.fromCharCode(e.keyCode))+'"]', header).parent('li'); - if (li.length !== 0) { - ctrlKey = false; - setTimeout(function() { - li.triggerHandler('mouseup'); - },1); - return false; - } - } - if (e.keyCode === 13 || e.keyCode === 10) { // Enter key - if (ctrlKey === true) { // Enter + Ctrl - ctrlKey = false; - markup(options.onCtrlEnter); - return options.onCtrlEnter.keepDefault; - } else if (shiftKey === true) { // Enter + Shift - shiftKey = false; - markup(options.onShiftEnter); - return options.onShiftEnter.keepDefault; - } else { // only Enter - markup(options.onEnter); - return options.onEnter.keepDefault; - } - } - if (e.keyCode === 9) { // Tab key - if (shiftKey == true || ctrlKey == true || altKey == true) { - return false; - } - if (caretOffset !== -1) { - get(); - caretOffset = $$.val().length - caretOffset; - set(caretOffset, 0); - caretOffset = -1; - return false; - } else { - markup(options.onTab); - return options.onTab.keepDefault; - } - } - } - } - - function remove() { - $$.unbind(".markItUp").removeClass('markItUpEditor'); - $$.parent('div').parent('div.markItUp').parent('div').replaceWith($$); - $$.data('markItUp', null); - } - - init(); - }); - }; - - $.fn.markItUpRemove = function() { - return this.each(function() { - $(this).markItUp('remove'); - } - ); - }; - - $.markItUp = function(settings) { - var options = { target:false }; - $.extend(options, settings); - if (options.target) { - return $(options.target).each(function() { - $(this).focus(); - $(this).trigger('insertion', [options]); - }); - } else { - $('textarea').trigger('insertion', [options]); - } - }; -})(jQuery); diff --git a/extensions/admin/resources/jquery.parsequery.js b/extensions/admin/resources/jquery.parsequery.js deleted file mode 100644 index 2e8f51ba0..000000000 --- a/extensions/admin/resources/jquery.parsequery.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2010 Conrad Irwin MIT license. - * Based loosely on original: Copyright (c) 2008 mkmanning MIT license. - * - * Parses CGI query strings into javascript objects. - * - * See the README for details. - **/ -(function ($) { - $.parseQuery = function (options) { - - var config = {query: window.location.search || ""}, - params = {}; - - if (typeof options === 'string') { - options = {query: options}; - } - $.extend(config, $.parseQuery, options); - config.query = config.query.replace(/^\?/, ''); - - $.each(config.query.split(config.separator), function (i, param) { - var pair = param.split('='), - key = config.decode(pair.shift(), null).toString(), - value = config.decode(pair.length ? pair.join('=') : null, key); - - if (config.array_keys(key)) { - params[key] = params[key] || []; - params[key].push(value); - } else { - params[key] = value; - } - }); - return params; - }; - $.parseQuery.decode = $.parseQuery.default_decode = function (string) { - return decodeURIComponent((string || "").replace('+', ' ')); - }; - $.parseQuery.array_keys = function () { - return false; - }; - $.parseQuery.separator = "&"; -}(jQuery)); diff --git a/extensions/admin/resources/jquery.parsequery.min.js b/extensions/admin/resources/jquery.parsequery.min.js deleted file mode 100644 index eff063a37..000000000 --- a/extensions/admin/resources/jquery.parsequery.min.js +++ /dev/null @@ -1,2 +0,0 @@ -(function($){$.parseQuery=function(options){var config={query:window.location.search||""},params={};if(typeof options==='string'){options={query:options};} -$.extend(config,$.parseQuery,options);config.query=config.query.replace(/^\?/,'');$.each(config.query.split(config.separator),function(i,param){var pair=param.split('='),key=config.decode(pair.shift(),null).toString(),value=config.decode(pair.length?pair.join('='):null,key);if(config.array_keys(key)){params[key]=params[key]||[];params[key].push(value);}else{params[key]=value;}});return params;};$.parseQuery.decode=$.parseQuery.default_decode=function(string){return decodeURIComponent((string||"").replace('+',' '));};$.parseQuery.array_keys=function(){return false;};$.parseQuery.separator="&";}(jQuery)); diff --git a/extensions/admin/resources/jquery.xslTransform.20071214.js b/extensions/admin/resources/jquery.xslTransform.20071214.js deleted file mode 100644 index 75365bad5..000000000 --- a/extensions/admin/resources/jquery.xslTransform.20071214.js +++ /dev/null @@ -1,435 +0,0 @@ -/** - * xslTransform - * Tools for XSLT transformations; jQuery wrapper for Sarissa . - * See jQuery.fn.log below for documentation on $.log(). - * See jQuery.fn.getTransform below for documention on the $.getTransform(). - * See var DEBUG below for turning debugging/logging on and off. - * - * @version 20071214 - * @since 2006-07-05 - * @copyright Copyright (c) 2006 Glyphix Studio, Inc. http://www.glyphix.com - * @author Brad Brizendine , Matt Antone - * @license MIT http://www.opensource.org/licenses/mit-license.php - * @requires >= jQuery 1.0.3 http://jquery.com/ - * @requires jquery.debug.js http://jquery.glyphix.com/ - * @requires >= sarissa.js 0.9.7.6 http://sarissa.sourceforge.net/ - * - * @example - * var r = $.xsl.transform('path-to-xsl.xsl','path-to-xml.xml'); - * @desc Perform a transformation and place the results in var r - * - * @example - * var r = $.xsl.transform('path-to-xsl.xsl','path-to-xml.xml'); - * var str = $.xsl.serialize( r ); - * @desc Perform a transformation, then turn the result into a string - * - * @example - * var doc = $.xsl.load('path-to-xml.xml'); - * @desc Load an xml file and return a parsed xml object - * - * @example - * var xml = 'bar'; - * var doc = $.xsl.load(xml); - * @desc Load an xml string and return a parsed xml object - */ - -(function($){ - - /* - * JQuery XSLT transformation plugin. - * Replaces all matched elements with the results of an XSLT transformation. - * See xslTransform above for more documentation. - * - * @example - * @desc See the xslTransform-example/index.html - * - * @param xsl String the url to the xsl file - * @param xml String the url to the xml file - * @param options Object various switches you can send to this function - * + params: an object of key/value pairs to be sent to xsl as parameters - * + xpath: defines the root node within the provided xml file - * + eval: if true, will attempt to eval javascript found in the transformed result - * + callback: if a Function, evaluate it when transformation is complete - * @returns - */ - - $.fn.getTransform = function( xsl, xml, options ){ - app.u.dump("getTransform being run."); - - var settings = { - params: {}, // object of key/value pairs ... parameters to send to the XSL stylesheet - xpath: '', // xpath, used to send only a portion of the XML file to the XSL stylesheet - eval: true, // evaluate script blocks found in the transformed result - callback: '' // callback function, to be run on completion of the transformation - }; - -// initialize options hash; override the defaults with supplied options - $.extend( settings, options ); - app.u.dump(" -> settings: "); app.u.dump(settings); - -// app.u.dump( 'getTransform: ' + xsl + '::' + xml + '::' + settings.toString() ); - //app.u.dump(xml); - // must have both xsl and xml - if( !xsl || !xml ){ - app.u.dump( 'getTransform: missing xsl or xml' ); - return; - } - - // run the jquery magic on all matched elements - return this.each( function(){ - // perform the transformation - var trans = $.xsl.transform( xsl, xml, settings ); - - // make sure we have something - if( !trans.string ){ - app.u.dump('Received nothing from the transformation'); - return false; - } - - // ie can fail if there's an xml declaration line in the returned result - var re = trans.string.match(/<\?xml.*?\?>/); - if( re ){ - trans.string = trans.string.replace( re, '' ); - app.u.dump( 'getTransform(): found an xml declaration and removed it' ); - } - - // place the result in the element - // 20070202: jquery 1.1.1 can get a "a.appendChild is not a function" error using html() sometimes ... - // no idea why yet, so adding a fallback to innerHTML - // ::warning:: ie6 has trouble with javascript events such as onclick assigned statically within the html when using innerHTML - try{ - $(this).html( trans.string ); - } - catch(e){ - app.u.dump( 'getTransform: error placing results of transform into element, falling back to innerHTML: ' + e.toString() ); - $(this)[0].innerHTML = trans.string; - } - - // there might not be a scripts property - if( settings.eval && trans.scripts ){ - if( trans.scripts.length > 0 ){ - app.u.dump( 'Found text/javascript in transformed result' ); - // use jquery's globaleval to avoid security issues in adobe air - $.globalEval( trans.scripts ); - } - } - - // run the callback if it's a native function - if( settings.callback && $.isFunction(settings.callback) ){ - app.u.dump(" -> settings.callback IS defined. run it."); - settings.callback.apply(); - } - }); //ends 'each' loop. - - }; //Ends $.fn.getTransform - - - - - - // xsl scope - $.xsl = { - - // version - version: 20071214, - - // init ... test for requirements - init: function(){ -// check for v1.0.4 / v1.1 or later of jQuery - try { - parseFloat($.fn.jquery) >= 1; - } - catch(e){ - alert('xslTransform requires jQuery 1.0.4 or greater ... please load it prior to xslTransform'); - } -// check for Sarissa - try { - Sarissa; - } - catch(e){ - alert('Missing Sarissa ... please load it prior to xslTransform'); - } -// log the version - app.u.dump( 'xslTransform:init(): version ' + this.version ); - }, - - // initialize Sarissa's serializer - XMLSerializer: new XMLSerializer(), - - /* - * serialize - * Turns the provided object into a string and returns it. - * - * @param data Mixed - * @returns String - */ - serialize: function( data ){ - app.u.dump( 'serialize(): received ' + typeof(data) ); - // if it's already a string, no further processing required - if( typeof(data) == 'string' ){ - app.u.dump( 'data is already a string: ' + data ); - return data; - } - return this.XMLSerializer.serializeToString( data ); - }, - - /* - * xmlize - * Turns the provided javascript object into an xml document and returns it. - * - * @param data Mixed - * @returns String - */ - xmlize: function( data, root ){ - app.u.dump( ' -> xmlize(): received ' + typeof(data) ); - root = root || 'root'; - return Sarissa.xmlize(data,root); - }, - - /* - * load - * Attempts to load xml data by automatically sensing the type of the provided data. - * - * @param xml Mixed the xml data - * @returns Object - */ - load: function( xml ){ -// app.u.dump( ' -> load(): received ' + typeof(xml) ); -// app.u.dump(xml); - // the result - var r; - - // if it's an object, assume it's already an XML object, so just return it - if(typeof(xml) == 'object'){ - return xml; - } - - // if it's a string, determine if it's xml data or a path - // assume that the first character is an opening caret if it's XML data - app.u.dump(" -> xml.substring(0,1): "+xml.substring(0,1)); - if(xml.substring(0,1) == '<' ){ - app.u.dump(" -> Use the XML/XSL that was passed instead of making an ajax request"); - r = this.loadString( xml ); - } - else{ - app.u.dump(" -> Fetch a remote XML/XSL file"); - r = this.loadFile( xml ); - } - - if( r ){ - // the following two lines are needed to get IE (msxml3) to run xpath ... set it on all xml data -// r.setProperty( 'SelectionNamespaces', 'xmlns:xsl="http://www.w3.org/1999/XSL/Transform"' ); -// r.setProperty( 'SelectionLanguage', 'XPath' ); - return r; - }else{ - app.u.dump( 'Unable to load ' + xml ); - return false; - } - }, - - /* - * loadString - * Parses an XML string and returns the result. - * - * @param str String the xml string to turn into a parsed XML object - * @returns Object - */ - loadString: function( str ){ -// app.u.dump( 'loadString(): ' + str + '::' + typeof(str) ); - - // use Sarissa to generate an XML doc - var p = new DOMParser(); - var xml = p.parseFromString( str, 'text/xml' ); - if( !xml ){ - app.u.dump( 'loadString(): parseFromString() failed' ); - return false; - } -// app.u.dump(" HERE AT LAST "); app.u.dump(xml); - return xml; - }, - - /* - * loadFile - * Attempts to retrieve the requested path, specified by url. - * If url is an object, it's assumed it's already loaded, and just returns it. - * - * @param url Mixed - * @returns Object - */ - loadFile: function( url ){ - app.u.dump( 'loadFile(): ' + url + '::' + typeof(url) ); - - if( !url ){ - app.u.dump( 'ERROR: loadFile() missing url' ); - return false; - } - - // variable to hold ajax results - var doc; - /* ajax functionality provided by jQuery is commented, since it can't handle file:/// - // function to receive data on successful download ... semicolon after brace is necessary for packing - this.xhrsuccess = function(data,str){ - app.u.dump( 'loadFile() completed successfully (' + str + ')' ); - doc = data; - return true; - }; - // function to handle downloading error ... semicolon after brace is necessary for packing - this.xhrerror = function(xhr,err){ - // set debugging to true in order to force the display of this error - window.DEBUG = true; - app.u.dump( 'loadFile() failed to load the requested file: (' + err + ') - xml: ' + xhr.responseXML + ' - text: ' + xhr.responseText ); - doc = null; - return false; - }; - - // make asynchronous ajax call and call functions defined above on success/error - $.ajax({ - type: 'GET', - url: url, - async: false, - success: this.xhrsuccess, - error: this.xhrerror - }); - */ - - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open('GET', url, false); - xmlhttp.send(''); - doc = xmlhttp.responseXML; - - // check for total failure - if( !doc ){ - app.u.dump( 'ERROR: document ' + url + ' not found (404), or unable to load' ); - return false; - } - // check for success but no data - if( doc.length == 0 ){ - app.u.dump( 'ERROR: document ' + url + ' loaded in loadFile() has no data' ); - return false; - } -// if(doc) {app.u.dump(doc)} - return doc; - }, - - /* - * transform - * Central transformation function: takes an xml doc and an xsl doc. - * - * @param xsl Mixed the xsl transformation document - * @param xml Mixed the xml document to be transformed - * @param options Object various switches you can send to this function - * + params: an object of key/value pairs to be sent to xsl as parameters - * + xpath: defines the root node within the provided xml file - * @returns Object the results of the transformation - * + xsl: the raw xsl doc - * + doc: the raw results of the transform - * + string: the serialized doc - */ - transform: function( xsl, xml, options ){ -// app.u.dump( 'transform(): ' + xsl + '::' + xml + '::' + (options ? options.toString() : 'no options provided') ); - - // set up request and result - var request = { - // the source and loaded object for xml - xsl: { - source: xsl, - doc: null - }, - // the source and loaded object for xsl - xml: { - source: xml, - doc: null - }, - // the options - options: options || {}, - // the result doc and string - result: { - doc: null, - string: '', - scripts: null, - error: '' - } - } - - // set up error handler - var err = function( what ){ - var docerr = '', srcerr = ''; - // build the src error string - app.u.dump(" -> Error for: "+what); // app.u.dump(request[what]); - srcerr = (typeof(request[what].source) == 'string') ? ' (' + what + ' loaded from provided path)' : ' (' + what + ' loaded from provided object)'; - // build the text error string - docerr = (typeof(request[what].doc) == 'object') ? '[success]' : '[failure]'; - // include the root node if we have a doc object and it's xml - if( what == 'xml' && request[what] && request[what].doc && typeof(request[what].doc) == 'object' ){ - docerr += ' root node of "' + request[what].doc.getElementsByTagName('*')[0].nodeName + '"'; - } - app.u.dump(docerr + ' ' + srcerr) - return docerr + ' ' + srcerr; - } - - // load the files - request.xsl.doc = this.load(xsl); - request.xml.doc = this.load(xml); - - if(request.xsl.doc && request.xml.doc){ - //proceed - } - else{ - app.u.dump('Unable to load either xsl or xml'); - err('xsl'); - err('xml'); - app.u.dump(request); - return false; - } - - // if we have an xpath, replace xml.doc with the results of running it - // as of 2007-12-03, IE throws a "msxml6: the parameter is incorrect" error, so removing this - if( request.options.xpath && request.xml.doc && !jQuery.browser.msie ){ - // run the xpath - request.xml.doc = request.xml.doc.selectSingleNode( request.options.xpath.toString() ); - app.u.dump( 'transform(): xpath has been run...resulting doc: ' + (this.serialize(request.xml.doc)) ); - } - - // attach the processor - var processor = new XSLTProcessor(); - // stylesheet must be imported before parameters can be added - processor.importStylesheet( request.xsl.doc ); - // add parameters to the processor - if( request.options.params && processor ){ - app.u.dump( 'transform(): received xsl params: '); app.u.dump(request.options.params); - for( key in request.options.params ){ - // name and value must be strings; first parameter is namespace - var p = request.options.params[key] ? request.options.params[key].toString() : request.options.params[key]; - try{ - processor.setParameter( null, key.toString(), p ); - }catch(e){ - app.u.dump('Unable to set parameter "' + key + '"'); - return false; - } - app.u.dump( 'set parameter "' + key.toString() + '" to "' + p + '"' ); - } - } - - // perform the transformation - request.result.doc = processor.transformToDocument( request.xml.doc ); - // handle transform error - request.result.error = Sarissa.getParseErrorText( request.result.doc ); - if( request.result.error != Sarissa.PARSED_OK ){ - // throw the error text - request.result.error = 'transform(): error in transformation: ' + request.result.error + ' :: using xsl: ' + err('xsl') + ' => xml: ' + err('xml'); - } - - - // if we made it this far, the transformation was successful - request.result.string = this.serialize( request.result.doc ); - // store reference to all scripts found in the doc (not result.string) - request.result.scripts = jQuery('script',request.result.doc).text(); - - return request.result; - } - }; - - // initialize the $.xsl object - $.xsl.init(); - -})(jQuery); diff --git a/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/images/table.png b/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/images/table.png deleted file mode 100644 index d09696a80..000000000 Binary files a/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/images/table.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/readme.txt b/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/readme.txt deleted file mode 100644 index f58621ea8..000000000 --- a/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/readme.txt +++ /dev/null @@ -1,12 +0,0 @@ -Markup language: -Wiki syntax - -Description: -Add a unic button to generate tables. - -Install: -- Download the zip file -- Unzip it -- Merge the style.css with your current markItUp! style.css -- Merge the set.js with your current markItUp! set.js -- Place the icon in your markItUp! images folder \ No newline at end of file diff --git a/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/set.js b/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/set.js deleted file mode 100644 index d02a1c56e..000000000 --- a/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/set.js +++ /dev/null @@ -1,32 +0,0 @@ -// ---------------------------------------------------------------------------- -// markItUp! -// ---------------------------------------------------------------------------- -// Copyright (C) 2008 Jay Salvat -// http://markitup.jaysalvat.com/ -// ---------------------------------------------------------------------------- -mySettings = { - markupSet: [ - { name:'Table generator', - className:'tablegenerator', - placeholder:"Your text here...", - replaceWith:function(h) { - var cols = prompt("How many cols?"), - rows = prompt("How many rows?"), - html = "{|\n"; - if (h.altKey) { - for (var c = 0; c < cols; c++) { - html += "! [![TH"+(c+1)+" text:]!]\n"; - } - } - for (var r = 0; r < rows; r++) { - html+= "|-\n"; - for (var c = 0; c < cols; c++) { - html += "| "+(h.placeholder||"")+"\n"; - } - } - html += "|}\n"; - return html; - } - } - ] -} \ No newline at end of file diff --git a/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/style.css b/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/style.css deleted file mode 100644 index c63481cb1..000000000 --- a/extensions/admin/resources/markitup/plugin-wiki-tablegenerator/style.css +++ /dev/null @@ -1,7 +0,0 @@ -/* ------------------------------------------------------------------- -// markItUp! -// By Jay Salvat - http://markitup.jaysalvat.com/ -// ------------------------------------------------------------------*/ -.markItUp .tablegenerator a { - background-image:url(images/table.png); -} \ No newline at end of file diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-container.png b/extensions/admin/resources/markitup/skin-jtageditor/images/bg-container.png deleted file mode 100644 index 9f4f56a9b..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-container.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-bbcode.png b/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-bbcode.png deleted file mode 100644 index 2a588fd3b..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-bbcode.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-dotclear.png b/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-dotclear.png deleted file mode 100644 index b3188dcd5..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-dotclear.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-html.png b/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-html.png deleted file mode 100644 index 439eef5f2..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-html.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-markdown.png b/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-markdown.png deleted file mode 100644 index 3293ccae1..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-markdown.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-textile.png b/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-textile.png deleted file mode 100644 index ac9f03b4a..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-textile.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-wiki.png b/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-wiki.png deleted file mode 100644 index e851f70a9..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor-wiki.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor.png b/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor.png deleted file mode 100644 index 439eef5f2..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/bg-editor.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/handle.png b/extensions/admin/resources/markitup/skin-jtageditor/images/handle.png deleted file mode 100644 index 3993b2033..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/handle.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/menu.png b/extensions/admin/resources/markitup/skin-jtageditor/images/menu.png deleted file mode 100644 index c817adc96..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/menu.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/images/submenu.png b/extensions/admin/resources/markitup/skin-jtageditor/images/submenu.png deleted file mode 100644 index 03d1977ae..000000000 Binary files a/extensions/admin/resources/markitup/skin-jtageditor/images/submenu.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-jtageditor/readme.txt b/extensions/admin/resources/markitup/skin-jtageditor/readme.txt deleted file mode 100644 index eecbf6358..000000000 --- a/extensions/admin/resources/markitup/skin-jtageditor/readme.txt +++ /dev/null @@ -1,7 +0,0 @@ -Skin: -Former jTagEditor Skin - -Install: -- Download the zip file -- Unzip it in your markItUp! skins folder -- Modify your CSS link to point at this skin \ No newline at end of file diff --git a/extensions/admin/resources/markitup/skin-jtageditor/style.css b/extensions/admin/resources/markitup/skin-jtageditor/style.css deleted file mode 100644 index 38a5f183c..000000000 --- a/extensions/admin/resources/markitup/skin-jtageditor/style.css +++ /dev/null @@ -1,144 +0,0 @@ -/* ------------------------------------------------------------------- -// markItUp! Universal MarkUp Engine, JQuery plugin -// By Jay Salvat - http://markitup.jaysalvat.com/ -// ------------------------------------------------------------------*/ -.markItUp * { - margin:0px; padding:0px; - outline:none; -} -.markItUp a:link, -.markItUp a:visited { - color:#000; - text-decoration:none; -} -.markItUp { - width:700px; - margin:5px 0 5px 0; -} -.markItUpContainer { - border:1px solid #3C769D; - background:#FFF url(images/bg-container.png) repeat-x top left; - padding:5px 5px 2px 5px; - font:11px Verdana, Arial, Helvetica, sans-serif; -} -.markItUpEditor { - font:12px 'Courier New', Courier, monospace; - padding:5px 5px 5px 35px; - border:3px solid #3C769D; - width:643px; - height:320px; - background-image:url(images/bg-editor-html.png); - background-repeat:no-repeat; - clear:both; display:block; - line-height:18px; - overflow:auto; -} -.markItUpPreviewFrame { - overflow:auto; - background-color:#FFFFFF; - border:1px solid #3C769D; - width:99.9%; - height:350px; - margin:5px 0; -} -.markItUpFooter { - width:100%; -} -.markItUpResizeHandle { - overflow:hidden; - width:22px; height:5px; - margin-left:auto; - margin-right:auto; - background-image:url(images/handle.png); - cursor:n-resize; -} -/***************************************************************************************/ -/* first row of buttons */ -.markItUpHeader ul li { - list-style:none; - float:left; - position:relative; -} -.markItUpHeader ul li ul{ - display:none; -} -.markItUpHeader ul li:hover > ul{ - display:block; -} -.markItUpHeader ul .markItUpDropMenu { - background:transparent url(images/menu.png) no-repeat 115% 50%; - margin-right:5px; -} -.markItUpHeader ul .markItUpDropMenu li { - margin-right:0px; -} -.markItUpHeader ul .markItUpSeparator { - margin:0 10px; - width:1px; - height:16px; - overflow:hidden; -} -.markItUpHeader ul ul .markItUpSeparator { - width:auto; height:1px; - margin:0px; -} -/* next rows of buttons */ -.markItUpHeader ul ul { - display:none; - position:absolute; - top:18px; left:0px; - background:#F5F5F5; - border:1px solid #3C769D; -} -.markItUpHeader ul ul li { - float:none; - border-bottom:1px solid #3C769D; -} -.markItUpHeader ul ul .markItUpDropMenu { - background:#F5F5F5 url(images/submenu.png) no-repeat 100% 50%; -} -/* next rows of buttons */ -.markItUpHeader ul ul ul { - position:absolute; - top:-1px; left:150px; -} -.markItUpHeader ul ul ul li { - float:none; -} -.markItUpHeader ul a { - display:block; - width:16px; height:16px; - text-indent:-10000px; - background-repeat:no-repeat; - padding:3px; - margin:0px; -} -.markItUpHeader ul ul a { - display:block; - padding-left:0px; - text-indent:0; - width:120px; - padding:5px 5px 5px 25px; - background-position:2px 50%; -} -.markItUpHeader ul ul a:hover { - color:#FFF; - background-color:#3C769D; -} -/***************************************************************************************/ -.html .markItUpEditor { - background-image:url(images/bg-editor-html.png); -} -.markdown .markItUpEditor { - background-image:url(images/bg-editor-markdown.png); -} -.textile .markItUpEditor { - background-image:url(images/bg-editor-textile.png); -} -.bbcode .markItUpEditor { - background-image:url(images/bg-editor-bbcode.png); -} -.wiki .markItUpEditor, -.dotclear .markItUpEditor { - background-image:url(images/bg-editor-wiki.png); -} \ No newline at end of file diff --git a/extensions/admin/resources/markitup/skin-markitup/images/handle.png b/extensions/admin/resources/markitup/skin-markitup/images/handle.png deleted file mode 100644 index 3993b2033..000000000 Binary files a/extensions/admin/resources/markitup/skin-markitup/images/handle.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-markitup/images/menu.png b/extensions/admin/resources/markitup/skin-markitup/images/menu.png deleted file mode 100644 index de337c88c..000000000 Binary files a/extensions/admin/resources/markitup/skin-markitup/images/menu.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-markitup/images/submenu.png b/extensions/admin/resources/markitup/skin-markitup/images/submenu.png deleted file mode 100644 index 03d1977ae..000000000 Binary files a/extensions/admin/resources/markitup/skin-markitup/images/submenu.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/skin-markitup/style.css b/extensions/admin/resources/markitup/skin-markitup/style.css deleted file mode 100644 index c11c2ea29..000000000 --- a/extensions/admin/resources/markitup/skin-markitup/style.css +++ /dev/null @@ -1,147 +0,0 @@ -/* ------------------------------------------------------------------- -// markItUp! Universal MarkUp Engine, JQuery plugin -// By Jay Salvat - http://markitup.jaysalvat.com/ -// ------------------------------------------------------------------*/ -.markItUp * { - margin:0px; padding:0px; - outline:none; -} -.markItUp a:link, -.markItUp a:visited { - color:#000; - text-decoration:none; -} -.markItUp { - width:700px; - margin:5px 0 5px 0; - border:5px solid #F5F5F5; -} -.markItUpContainer { - border:1px solid #3C769D; - background:#FFF url(images/bg-container.png) repeat-x top left; - padding:5px 5px 2px 5px; - font:11px Verdana, Arial, Helvetica, sans-serif; -} -.markItUpEditor { - font:12px 'Courier New', Courier, monospace; - padding:5px 5px 5px 35px; - border:3px solid #3C769D; - width:643px; - height:320px; - background:#FFF url(images/bg-editor.png) no-repeat; - clear:both; - line-height:18px; - overflow:auto; -} -.markItUpPreviewFrame { - overflow:auto; - background-color:#FFFFFF; - border:1px solid #3C769D; - width:99.9%; - height:300px; - margin:5px 0; -} -.markItUpFooter { - width:100%; - cursor:n-resize; -} -.markItUpResizeHandle { - overflow:hidden; - width:22px; height:5px; - margin-left:auto; - margin-right:auto; - background-image:url(images/handle.png); - cursor:n-resize; -} -/***************************************************************************************/ -/* first row of buttons */ -.markItUpHeader ul li { - list-style:none; - float:left; - position:relative; -} -.markItUpHeader ul li ul{ - display:none; -} -.markItUpHeader ul li:hover > ul{ - display:block; -} -.markItUpHeader ul .markItUpDropMenu { - background:transparent url(images/menu.png) no-repeat 115% 50%; - margin-right:5px; -} -.markItUpHeader ul .markItUpDropMenu li { - margin-right:0px; -} -.markItUpHeader ul .markItUpSeparator { - margin:0 10px; - width:1px; - height:16px; - overflow:hidden; - background-color:#CCC; -} -.markItUpHeader ul ul .markItUpSeparator { - width:auto; height:1px; - margin:0px; -} -/* next rows of buttons */ -.markItUpHeader ul ul { - display:none; - position:absolute; - top:18px; left:0px; - background:#F5F5F5; - border:1px solid #3C769D; - height:inherit; -} -.markItUpHeader ul ul li { - float:none; - border-bottom:1px solid #3C769D; -} -.markItUpHeader ul ul .markItUpDropMenu { - background:#F5F5F5 url(images/submenu.png) no-repeat 100% 50%; -} -/* next rows of buttons */ -.markItUpHeader ul ul ul { - position:absolute; - top:-1px; left:150px; -} -.markItUpHeader ul ul ul li { - float:none; -} -.markItUpHeader ul a { - display:block; - width:16px; height:16px; - text-indent:-10000px; - background-repeat:no-repeat; - padding:3px; - margin:0px; -} -.markItUpHeader ul ul a { - display:block; - padding-left:0px; - text-indent:0; - width:120px; - padding:5px 5px 5px 25px; - background-position:2px 50%; -} -.markItUpHeader ul ul a:hover { - color:#FFF; - background-color:#3C769D; -} -/***************************************************************************************/ -.html .markItUpEditor { - background-image:url(images/bg-editor-html.png); -} -.markdown .markItUpEditor { - background-image:url(images/bg-editor-markdown.png); -} -.textile .markItUpEditor { - background-image:url(images/bg-editor-textile.png); -} -.bbcode .markItUpEditor { - background-image:url(images/bg-editor-bbcode.png); -} -.wiki .markItUpEditor, -.dotclear .markItUpEditor { - background-image:url(images/bg-editor-wiki.png); -} \ No newline at end of file diff --git a/extensions/admin/resources/markitup/style-default/images/bold.png b/extensions/admin/resources/markitup/style-default/images/bold.png deleted file mode 100644 index 889ae80e3..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/bold.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/clean.png b/extensions/admin/resources/markitup/style-default/images/clean.png deleted file mode 100644 index 7e7cefb8e..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/clean.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/image.png b/extensions/admin/resources/markitup/style-default/images/image.png deleted file mode 100644 index fc3c393ca..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/image.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/italic.png b/extensions/admin/resources/markitup/style-default/images/italic.png deleted file mode 100644 index 8482ac8cb..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/italic.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/link.png b/extensions/admin/resources/markitup/style-default/images/link.png deleted file mode 100644 index 25eacb7c2..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/link.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/list-bullet.png b/extensions/admin/resources/markitup/style-default/images/list-bullet.png deleted file mode 100644 index 4a8672bde..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/list-bullet.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/list-numeric.png b/extensions/admin/resources/markitup/style-default/images/list-numeric.png deleted file mode 100644 index 33b0b8df3..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/list-numeric.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/picture.png b/extensions/admin/resources/markitup/style-default/images/picture.png deleted file mode 100644 index 4a158fef7..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/picture.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/preview.png b/extensions/admin/resources/markitup/style-default/images/preview.png deleted file mode 100644 index a9925a06a..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/preview.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/images/stroke.png b/extensions/admin/resources/markitup/style-default/images/stroke.png deleted file mode 100644 index 612058a78..000000000 Binary files a/extensions/admin/resources/markitup/style-default/images/stroke.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-default/set.js b/extensions/admin/resources/markitup/style-default/set.js deleted file mode 100644 index b7fdf8182..000000000 --- a/extensions/admin/resources/markitup/style-default/set.js +++ /dev/null @@ -1,30 +0,0 @@ -// ---------------------------------------------------------------------------- -// markItUp! -// ---------------------------------------------------------------------------- -// Copyright (C) 2011 Jay Salvat -// http://markitup.jaysalvat.com/ -// ---------------------------------------------------------------------------- -// Html tags -// http://en.wikipedia.org/wiki/html -// ---------------------------------------------------------------------------- -// Basic set. Feel free to add more tags -// ---------------------------------------------------------------------------- -var mySettings = { - onShiftEnter: {keepDefault:false, replaceWith:'
                                                          \n'}, - onCtrlEnter: {keepDefault:false, openWith:'\n

                                                          ', closeWith:'

                                                          '}, - onTab: {keepDefault:false, replaceWith:' '}, - markupSet: [ - {name:'Bold', key:'B', openWith:'(!(|!|)!)', closeWith:'(!(|!|)!)' }, - {name:'Italic', key:'I', openWith:'(!(|!|)!)', closeWith:'(!(|!|)!)' }, - {name:'Stroke through', key:'S', openWith:'', closeWith:'' }, - {separator:'---------------' }, - {name:'Bulleted List', openWith:'
                                                        • ', closeWith:'
                                                        • ', multiline:true, openBlockWith:'
                                                            \n', closeBlockWith:'\n
                                                          '}, - {name:'Numeric List', openWith:'
                                                        • ', closeWith:'
                                                        • ', multiline:true, openBlockWith:'
                                                            \n', closeBlockWith:'\n
                                                          '}, - {separator:'---------------' }, - {name:'Picture', key:'P', replaceWith:'[![Alternative text]!]' }, - {name:'Link', key:'L', openWith:'', closeWith:'', placeHolder:'Your text to link...' }, - {separator:'---------------' }, - {name:'Clean', className:'clean', replaceWith:function(markitup) { return markitup.selection.replace(/<(.*?)>/g, "") } }, - {name:'Preview', className:'preview', call:'preview'} - ] -} diff --git a/extensions/admin/resources/markitup/style-default/style.css b/extensions/admin/resources/markitup/style-default/style.css deleted file mode 100644 index 336b60eb0..000000000 --- a/extensions/admin/resources/markitup/style-default/style.css +++ /dev/null @@ -1,34 +0,0 @@ -/* ------------------------------------------------------------------- -// markItUp! -// By Jay Salvat - http://markitup.jaysalvat.com/ -// ------------------------------------------------------------------*/ -.markItUp .markItUpButton1 a { - background-image:url(images/bold.png); -} -.markItUp .markItUpButton2 a { - background-image:url(images/italic.png); -} -.markItUp .markItUpButton3 a { - background-image:url(images/stroke.png); -} - -.markItUp .markItUpButton4 a { - background-image:url(images/list-bullet.png); -} -.markItUp .markItUpButton5 a { - background-image:url(images/list-numeric.png); -} - -.markItUp .markItUpButton6 a { - background-image:url(images/picture.png); -} -.markItUp .markItUpButton7 a { - background-image:url(images/link.png); -} - -.markItUp .markItUpButton8 a { - background-image:url(images/clean.png); -} -.markItUp .preview a { - background-image:url(images/preview.png); -} diff --git a/extensions/admin/resources/markitup/style-html/images/bold.png b/extensions/admin/resources/markitup/style-html/images/bold.png deleted file mode 100644 index 889ae80e3..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/bold.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/clean.png b/extensions/admin/resources/markitup/style-html/images/clean.png deleted file mode 100644 index 7e7cefb8e..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/clean.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/h1.png b/extensions/admin/resources/markitup/style-html/images/h1.png deleted file mode 100644 index 9c122e91e..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/h1.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/h2.png b/extensions/admin/resources/markitup/style-html/images/h2.png deleted file mode 100644 index fbd87657f..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/h2.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/h3.png b/extensions/admin/resources/markitup/style-html/images/h3.png deleted file mode 100644 index c7836cf09..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/h3.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/h4.png b/extensions/admin/resources/markitup/style-html/images/h4.png deleted file mode 100644 index 4e929eaf5..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/h4.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/h5.png b/extensions/admin/resources/markitup/style-html/images/h5.png deleted file mode 100644 index 30cabebf7..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/h5.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/h6.png b/extensions/admin/resources/markitup/style-html/images/h6.png deleted file mode 100644 index 058170a20..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/h6.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/image.png b/extensions/admin/resources/markitup/style-html/images/image.png deleted file mode 100644 index fc3c393ca..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/image.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/italic.png b/extensions/admin/resources/markitup/style-html/images/italic.png deleted file mode 100644 index 8482ac8cb..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/italic.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/link.png b/extensions/admin/resources/markitup/style-html/images/link.png deleted file mode 100644 index 25eacb7c2..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/link.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/list-bullet.png b/extensions/admin/resources/markitup/style-html/images/list-bullet.png deleted file mode 100644 index 4a8672bde..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/list-bullet.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/list-item.png b/extensions/admin/resources/markitup/style-html/images/list-item.png deleted file mode 100644 index 8cb4d696b..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/list-item.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/list-numeric.png b/extensions/admin/resources/markitup/style-html/images/list-numeric.png deleted file mode 100644 index 33b0b8df3..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/list-numeric.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/paragraph.png b/extensions/admin/resources/markitup/style-html/images/paragraph.png deleted file mode 100644 index 95704fbab..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/paragraph.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/picture.png b/extensions/admin/resources/markitup/style-html/images/picture.png deleted file mode 100644 index 4a158fef7..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/picture.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/preview.png b/extensions/admin/resources/markitup/style-html/images/preview.png deleted file mode 100644 index a9925a06a..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/preview.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/images/stroke.png b/extensions/admin/resources/markitup/style-html/images/stroke.png deleted file mode 100644 index 612058a78..000000000 Binary files a/extensions/admin/resources/markitup/style-html/images/stroke.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-html/readme.txt b/extensions/admin/resources/markitup/style-html/readme.txt deleted file mode 100644 index 80dc7e782..000000000 --- a/extensions/admin/resources/markitup/style-html/readme.txt +++ /dev/null @@ -1,11 +0,0 @@ -Markup language: -Html - -Description: -A basic Html markup set with Headings, Paragraph, Bold, Italic, Stroke through, Picture, Link, List, Clean button, Preview button. - -Install: -- Download the zip file -- Unzip it in your markItUp! sets folder -- Modify your JS link to point at this set.js -- Modify your CSS link to point at this style.css \ No newline at end of file diff --git a/extensions/admin/resources/markitup/style-html/set.js b/extensions/admin/resources/markitup/style-html/set.js deleted file mode 100644 index 9f4856710..000000000 --- a/extensions/admin/resources/markitup/style-html/set.js +++ /dev/null @@ -1,39 +0,0 @@ -// ---------------------------------------------------------------------------- -// markItUp! -// ---------------------------------------------------------------------------- -// Copyright (C) 2008 Jay Salvat -// http://markitup.jaysalvat.com/ -// ---------------------------------------------------------------------------- -// Html tags -// http://en.wikipedia.org/wiki/html -// ---------------------------------------------------------------------------- -// Basic set. Feel free to add more tags -// ---------------------------------------------------------------------------- -mySettings = { - onShiftEnter: {keepDefault:false, replaceWith:'
                                                          \n'}, - onCtrlEnter: {keepDefault:false, openWith:'\n

                                                          ', closeWith:'

                                                          \n'}, - onTab: {keepDefault:false, openWith:' '}, - markupSet: [ - {name:'Heading 1', key:'1', openWith:'', closeWith:'', placeHolder:'Your title here...' }, - {name:'Heading 2', key:'2', openWith:'', closeWith:'', placeHolder:'Your title here...' }, - {name:'Heading 3', key:'3', openWith:'', closeWith:'', placeHolder:'Your title here...' }, - {name:'Heading 4', key:'4', openWith:'', closeWith:'', placeHolder:'Your title here...' }, - {name:'Heading 5', key:'5', openWith:'', closeWith:'', placeHolder:'Your title here...' }, - {name:'Heading 6', key:'6', openWith:'', closeWith:'', placeHolder:'Your title here...' }, - {name:'Paragraph', openWith:'', closeWith:'

                                                          ' }, - {separator:'---------------' }, - {name:'Bold', key:'B', openWith:'(!(|!|)!)', closeWith:'(!(|!|)!)' }, - {name:'Italic', key:'I', openWith:'(!(|!|)!)', closeWith:'(!(|!|)!)' }, - {name:'Stroke through', key:'S', openWith:'', closeWith:'' }, - {separator:'---------------' }, - {name:'Ul', openWith:'
                                                            \n', closeWith:'
                                                          \n' }, - {name:'Ol', openWith:'
                                                            \n', closeWith:'
                                                          \n' }, - {name:'Li', openWith:'
                                                        • ', closeWith:'
                                                        • ' }, - {separator:'---------------' }, - {name:'Picture', key:'P', replaceWith:'[![Alternative text]!]' }, - {name:'Link', key:'L', openWith:'', closeWith:'', placeHolder:'Your text to link...' }, - {separator:'---------------' }, - {name:'Clean', className:'clean', replaceWith:function(markitup) { return markitup.selection.replace(/<(.*?)>/g, "") } }, - {name:'Preview', className:'preview', call:'preview' } - ] -} \ No newline at end of file diff --git a/extensions/admin/resources/markitup/style-html/style.css b/extensions/admin/resources/markitup/style-html/style.css deleted file mode 100644 index 817e503eb..000000000 --- a/extensions/admin/resources/markitup/style-html/style.css +++ /dev/null @@ -1,59 +0,0 @@ -/* ------------------------------------------------------------------- -// markItUp! -// By Jay Salvat - http://markitup.jaysalvat.com/ -// ------------------------------------------------------------------*/ -.markItUp .markItUpButton1 a { - background-image:url(images/h1.png); -} -.markItUp .markItUpButton2 a { - background-image:url(images/h2.png); -} -.markItUp .markItUpButton3 a { - background-image:url(images/h3.png); -} -.markItUp .markItUpButton4 a { - background-image:url(images/h4.png); -} -.markItUp .markItUpButton5 a { - background-image:url(images/h5.png); -} -.markItUp .markItUpButton6 a { - background-image:url(images/h6.png); -} -.markItUp .markItUpButton7 a { - background-image:url(images/paragraph.png); -} - -.markItUp .markItUpButton8 a { - background-image:url(images/bold.png); -} -.markItUp .markItUpButton9 a { - background-image:url(images/italic.png); -} -.markItUp .markItUpButton10 a { - background-image:url(images/stroke.png); -} - -.markItUp .markItUpButton11 a { - background-image:url(images/list-bullet.png); -} -.markItUp .markItUpButton12 a { - background-image:url(images/list-numeric.png); -} -.markItUp .markItUpButton13 a { - background-image:url(images/list-item.png); -} - -.markItUp .markItUpButton14 a { - background-image:url(images/picture.png); -} -.markItUp .markItUpButton15 a { - background-image:url(images/link.png); -} - -.markItUp .clean a { - background-image:url(images/clean.png); -} -.markItUp .preview a { - background-image:url(images/preview.png); -} \ No newline at end of file diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-container.png b/extensions/admin/resources/markitup/style-simple/images/bg-container.png deleted file mode 100644 index ec38b8e18..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-container.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor-bbcode.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor-bbcode.png deleted file mode 100644 index 39cdbd832..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor-bbcode.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor-dotclear.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor-dotclear.png deleted file mode 100644 index b3188dcd5..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor-dotclear.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor-html.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor-html.png deleted file mode 100644 index 11bff4568..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor-html.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor-json.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor-json.png deleted file mode 100644 index e898c1d78..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor-json.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor-markdown.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor-markdown.png deleted file mode 100644 index c19971522..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor-markdown.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor-textile.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor-textile.png deleted file mode 100644 index 3ab1e9f6e..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor-textile.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor-wiki.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor-wiki.png deleted file mode 100644 index 7887181cc..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor-wiki.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor-xml.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor-xml.png deleted file mode 100644 index 33b1c5d83..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor-xml.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/bg-editor.png b/extensions/admin/resources/markitup/style-simple/images/bg-editor.png deleted file mode 100644 index ab7cde485..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/bg-editor.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/handle.png b/extensions/admin/resources/markitup/style-simple/images/handle.png deleted file mode 100644 index 3993b2033..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/handle.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/menu.png b/extensions/admin/resources/markitup/style-simple/images/menu.png deleted file mode 100644 index 44a07afd3..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/menu.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/images/submenu.png b/extensions/admin/resources/markitup/style-simple/images/submenu.png deleted file mode 100644 index 03d1977ae..000000000 Binary files a/extensions/admin/resources/markitup/style-simple/images/submenu.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-simple/style.css b/extensions/admin/resources/markitup/style-simple/style.css deleted file mode 100644 index fe3753c02..000000000 --- a/extensions/admin/resources/markitup/style-simple/style.css +++ /dev/null @@ -1,118 +0,0 @@ -/* ------------------------------------------------------------------- -// markItUp! Universal MarkUp Engine, JQuery plugin -// By Jay Salvat - http://markitup.jaysalvat.com/ -// ------------------------------------------------------------------*/ -.markItUp * { - margin:0px; padding:0px; - outline:none; -} -.markItUp a:link, -.markItUp a:visited { - color:#000; - text-decoration:none; -} -.markItUp { - width:700px; - margin:5px 0 5px 0; -} -.markItUpContainer { - font:11px Verdana, Arial, Helvetica, sans-serif; -} -.markItUpEditor { - font:12px 'Courier New', Courier, monospace; - padding:5px; - width:690px; - height:320px; - clear:both; - line-height:18px; - overflow:auto; -} -.markItUpPreviewFrame { - overflow:auto; - background-color:#FFF; - width:99.9%; - height:300px; - margin:5px 0; -} -.markItUpFooter { - width:100%; -} -.markItUpResizeHandle { - overflow:hidden; - width:22px; height:5px; - margin-left:auto; - margin-right:auto; - background-image:url(images/handle.png); - cursor:n-resize; -} -/***************************************************************************************/ -/* first row of buttons */ -.markItUpHeader ul li { - list-style:none; - float:left; - position:relative; -} -.markItUpHeader ul li:hover > ul{ - display:block; -} -.markItUpHeader ul .markItUpDropMenu { - background:transparent url(images/menu.png) no-repeat 115% 50%; - margin-right:5px; -} -.markItUpHeader ul .markItUpDropMenu li { - margin-right:0px; -} -/* next rows of buttons */ -.markItUpHeader ul ul { - display:none; - position:absolute; - top:18px; left:0px; - background:#FFF; - border:1px solid #000; -} -.markItUpHeader ul ul li { - float:none; - border-bottom:1px solid #000; -} -.markItUpHeader ul ul .markItUpDropMenu { - background:#FFF url(images/submenu.png) no-repeat 100% 50%; -} -.markItUpHeader ul .markItUpSeparator { - margin:0 10px; - width:1px; - height:16px; - overflow:hidden; - background-color:#CCC; -} -.markItUpHeader ul ul .markItUpSeparator { - width:auto; height:1px; - margin:0px; -} -/* next rows of buttons */ -.markItUpHeader ul ul ul { - position:absolute; - top:-1px; left:150px; -} -.markItUpHeader ul ul ul li { - float:none; -} -.markItUpHeader ul a { - display:block; - width:16px; height:16px; - text-indent:-10000px; - background-repeat:no-repeat; - padding:3px; - margin:0px; -} -.markItUpHeader ul ul a { - display:block; - padding-left:0px; - text-indent:0; - width:120px; - padding:5px 5px 5px 25px; - background-position:2px 50%; -} -.markItUpHeader ul ul a:hover { - color:#FFF; - background-color:#000; -} diff --git a/extensions/admin/resources/markitup/style-wiki/images/bold.png b/extensions/admin/resources/markitup/style-wiki/images/bold.png deleted file mode 100644 index 889ae80e3..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/bold.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/code.png b/extensions/admin/resources/markitup/style-wiki/images/code.png deleted file mode 100644 index 63fe6ceff..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/code.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/h1.png b/extensions/admin/resources/markitup/style-wiki/images/h1.png deleted file mode 100644 index 9c122e91e..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/h1.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/h2.png b/extensions/admin/resources/markitup/style-wiki/images/h2.png deleted file mode 100644 index fbd87657f..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/h2.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/h3.png b/extensions/admin/resources/markitup/style-wiki/images/h3.png deleted file mode 100644 index c7836cf09..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/h3.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/h4.png b/extensions/admin/resources/markitup/style-wiki/images/h4.png deleted file mode 100644 index 4e929eaf5..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/h4.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/h5.png b/extensions/admin/resources/markitup/style-wiki/images/h5.png deleted file mode 100644 index 30cabebf7..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/h5.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/h6.png b/extensions/admin/resources/markitup/style-wiki/images/h6.png deleted file mode 100644 index 058170a20..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/h6.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/italic.png b/extensions/admin/resources/markitup/style-wiki/images/italic.png deleted file mode 100644 index 8482ac8cb..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/italic.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/link.png b/extensions/admin/resources/markitup/style-wiki/images/link.png deleted file mode 100644 index 25eacb7c2..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/link.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/list-bullet.png b/extensions/admin/resources/markitup/style-wiki/images/list-bullet.png deleted file mode 100644 index 4a8672bde..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/list-bullet.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/list-numeric.png b/extensions/admin/resources/markitup/style-wiki/images/list-numeric.png deleted file mode 100644 index 33b0b8df3..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/list-numeric.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/picture.png b/extensions/admin/resources/markitup/style-wiki/images/picture.png deleted file mode 100644 index 4a158fef7..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/picture.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/preview.png b/extensions/admin/resources/markitup/style-wiki/images/preview.png deleted file mode 100644 index a9925a06a..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/preview.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/quotes.png b/extensions/admin/resources/markitup/style-wiki/images/quotes.png deleted file mode 100644 index e54ebebaf..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/quotes.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/stroke.png b/extensions/admin/resources/markitup/style-wiki/images/stroke.png deleted file mode 100644 index 612058a78..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/stroke.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/images/url.png b/extensions/admin/resources/markitup/style-wiki/images/url.png deleted file mode 100644 index b8edc1265..000000000 Binary files a/extensions/admin/resources/markitup/style-wiki/images/url.png and /dev/null differ diff --git a/extensions/admin/resources/markitup/style-wiki/readme.txt b/extensions/admin/resources/markitup/style-wiki/readme.txt deleted file mode 100644 index 98c313b79..000000000 --- a/extensions/admin/resources/markitup/style-wiki/readme.txt +++ /dev/null @@ -1,11 +0,0 @@ -Markup language: -Wiki - -Description: -A basic Wiki markup set with Headings, Bold, Italic, Stroke through, Picture, Link, List, Quotes, Code, Preview button. - -Install: -- Download the zip file -- Unzip it in your markItUp! sets folder -- Modify your JS link to point at this set.js -- Modify your CSS link to point at this style.css \ No newline at end of file diff --git a/extensions/admin/resources/markitup/style-wiki/set.js b/extensions/admin/resources/markitup/style-wiki/set.js deleted file mode 100644 index e97675c36..000000000 --- a/extensions/admin/resources/markitup/style-wiki/set.js +++ /dev/null @@ -1,37 +0,0 @@ -// ------------------------------------------------------------------- -// markItUp! -// ------------------------------------------------------------------- -// Copyright (C) 2008 Jay Salvat -// http://markitup.jaysalvat.com/ -// ------------------------------------------------------------------- -// Mediawiki Wiki tags example -// ------------------------------------------------------------------- -// Feel free to add more tags -// ------------------------------------------------------------------- -mySettings = { - previewParserPath: '', // path to your Wiki parser - onShiftEnter: {keepDefault:false, replaceWith:'\n\n'}, - markupSet: [ - {name:'Heading 1', key:'1', openWith:'== ', closeWith:' ==', placeHolder:'Your title here...' }, - {name:'Heading 2', key:'2', openWith:'=== ', closeWith:' ===', placeHolder:'Your title here...' }, - {name:'Heading 3', key:'3', openWith:'==== ', closeWith:' ====', placeHolder:'Your title here...' }, - {name:'Heading 4', key:'4', openWith:'===== ', closeWith:' =====', placeHolder:'Your title here...' }, - {name:'Heading 5', key:'5', openWith:'====== ', closeWith:' ======', placeHolder:'Your title here...' }, - {separator:'---------------' }, - {name:'Bold', key:'B', openWith:"'''", closeWith:"'''"}, - {name:'Italic', key:'I', openWith:"''", closeWith:"''"}, - {name:'Stroke through', key:'S', openWith:'', closeWith:''}, - {separator:'---------------' }, - {name:'Bulleted list', openWith:'(!(* |!|*)!)'}, - {name:'Numeric list', openWith:'(!(# |!|#)!)'}, - {separator:'---------------' }, - {name:'Picture', key:"P", replaceWith:'[[Image:[![Url:!:http://]!]|[![name]!]]]'}, - {name:'Link', key:"L", openWith:"[[![Link]!] ", closeWith:']', placeHolder:'Your text to link here...' }, - {name:'Url', openWith:"[[![Url:!:http://]!] ", closeWith:']', placeHolder:'Your text to link here...' }, - {separator:'---------------' }, - {name:'Quotes', openWith:'(!(> |!|>)!)', placeHolder:''}, - {name:'Code', openWith:'(!(|!|
                                                          )!)', closeWith:'(!(|!|
                                                          )!)'}, - {separator:'---------------' }, - {name:'Preview', call:'preview', className:'preview'} - ] -} \ No newline at end of file diff --git a/extensions/admin/resources/markitup/style-wiki/style.css b/extensions/admin/resources/markitup/style-wiki/style.css deleted file mode 100644 index 02bb923a8..000000000 --- a/extensions/admin/resources/markitup/style-wiki/style.css +++ /dev/null @@ -1,57 +0,0 @@ -/* ------------------------------------------------------------------- -// markItUp! -// By Jay Salvat - http://markitup.jaysalvat.com/ -// ------------------------------------------------------------------*/ -.markItUp .markItUpButton1 a { - background-image:url(images/h1.png); -} -.markItUp .markItUpButton2 a { - background-image:url(images/h2.png); -} -.markItUp .markItUpButton3 a { - background-image:url(images/h3.png); -} -.markItUp .markItUpButton4 a { - background-image:url(images/h4.png); -} -.markItUp .markItUpButton5 a { - background-image:url(images/h5.png); -} - -.markItUp .markItUpButton6 a { - background-image:url(images/bold.png); -} -.markItUp .markItUpButton7 a { - background-image:url(images/italic.png); -} -.markItUp .markItUpButton8 a { - background-image:url(images/stroke.png); -} - -.markItUp .markItUpButton9 a { - background-image:url(images/list-bullet.png); -} -.markItUp .markItUpButton10 a { - background-image:url(images/list-numeric.png); -} - -.markItUp .markItUpButton11 a { - background-image:url(images/picture.png); -} -.markItUp .markItUpButton12 a { - background-image:url(images/link.png); -} -.markItUp .markItUpButton13 a { - background-image:url(images/url.png); -} - -.markItUp .markItUpButton14 a { - background-image:url(images/quotes.png); -} -.markItUp .markItUpButton15 a { - background-image:url(images/code.png); -} - -.markItUp .preview a { - background-image:url(images/preview.png); -} \ No newline at end of file diff --git a/extensions/admin/resources/sarissa.0.9.9.6.js b/extensions/admin/resources/sarissa.0.9.9.6.js deleted file mode 100644 index 29621a197..000000000 --- a/extensions/admin/resources/sarissa.0.9.9.6.js +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * ==================================================================== - * About Sarissa: http://dev.abiss.gr/sarissa - * ==================================================================== - * Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs. - * The library supports Gecko based browsers like Mozilla and Firefox, - * Internet Explorer (5.5+ with MSXML3.0+), Konqueror, Safari and Opera - * @version 0.9.9.6 - * @author: Copyright 2004-2008 Emmanouil Batsis, mailto: mbatsis at users full stop sourceforge full stop net - * ==================================================================== - * Licence - * ==================================================================== - * Sarissa is free software distributed under the GNU GPL version 2 (see gpl.txt) or higher, - * GNU LGPL version 2.1 (see lgpl.txt) or higher and Apache Software License 2.0 or higher - * (see asl.txt). This means you can choose one of the three and use that if you like. If - * you make modifications under the ASL, i would appreciate it if you submitted those. - * In case your copy of Sarissa does not include the license texts, you may find - * them online in various formats at http://www.gnu.org and - * http://www.apache.org. - * - * 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. - */ -/** - *

                                                          Sarissa is a utility class. Provides "static" methods for DOMDocument, - * DOM Node serialization to XML strings and other utility goodies.

                                                          - * @constructor - * @static - */ -function Sarissa(){} -Sarissa.VERSION = "0.9.9.6"; -Sarissa.PARSED_OK = "Document contains no parsing errors"; -Sarissa.PARSED_EMPTY = "Document is empty"; -Sarissa.PARSED_UNKNOWN_ERROR = "Not well-formed or other error"; -Sarissa.IS_ENABLED_TRANSFORM_NODE = false; -Sarissa.REMOTE_CALL_FLAG = "gr.abiss.sarissa.REMOTE_CALL_FLAG"; -/** @private */ -Sarissa._lastUniqueSuffix = 0; -/** @private */ -Sarissa._getUniqueSuffix = function(){ - return Sarissa._lastUniqueSuffix++; -}; -/** @private */ -Sarissa._SARISSA_IEPREFIX4XSLPARAM = ""; -/** @private */ -Sarissa._SARISSA_HAS_DOM_IMPLEMENTATION = document.implementation && true; -/** @private */ -Sarissa._SARISSA_HAS_DOM_CREATE_DOCUMENT = Sarissa._SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.createDocument; -/** @private */ -Sarissa._SARISSA_HAS_DOM_FEATURE = Sarissa._SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.hasFeature; -/** @private */ -Sarissa._SARISSA_IS_MOZ = Sarissa._SARISSA_HAS_DOM_CREATE_DOCUMENT && Sarissa._SARISSA_HAS_DOM_FEATURE; -/** @private */ -Sarissa._SARISSA_IS_SAFARI = navigator.userAgent.toLowerCase().indexOf("safari") != -1 || navigator.userAgent.toLowerCase().indexOf("konqueror") != -1; -/** @private */ -Sarissa._SARISSA_IS_SAFARI_OLD = Sarissa._SARISSA_IS_SAFARI && (parseInt((navigator.userAgent.match(/AppleWebKit\/(\d+)/)||{})[1], 10) < 420); -/** @private */ -Sarissa._SARISSA_IS_IE = document.all && window.ActiveXObject && navigator.userAgent.toLowerCase().indexOf("msie") > -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1; -/** @private */ -Sarissa._SARISSA_IS_IE9 = Sarissa._SARISSA_IS_IE && navigator.userAgent.toLowerCase().indexOf("msie 9") > -1; -/** @private */ -Sarissa._SARISSA_IS_OPERA = navigator.userAgent.toLowerCase().indexOf("opera") != -1; -if(!window.Node || !Node.ELEMENT_NODE){ - Node = {ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12}; -} - -//This breaks for(x in o) loops in the old Safari -if(Sarissa._SARISSA_IS_SAFARI_OLD){ - HTMLHtmlElement = document.createElement("html").constructor; - Node = HTMLElement = {}; - HTMLElement.prototype = HTMLHtmlElement.__proto__.__proto__; - HTMLDocument = Document = document.constructor; - var x = new DOMParser(); - XMLDocument = x.constructor; - Element = x.parseFromString("", "text/xml").documentElement.constructor; - x = null; -} -if(typeof XMLDocument == "undefined" && typeof Document !="undefined"){ XMLDocument = Document; } - -// IE initialization -if(Sarissa._SARISSA_IS_IE){ - // for XSLT parameter names, prefix needed by IE - Sarissa._SARISSA_IEPREFIX4XSLPARAM = "xsl:"; - // used to store the most recent ProgID available out of the above - var _SARISSA_DOM_PROGID = ""; - var _SARISSA_XMLHTTP_PROGID = ""; - var _SARISSA_DOM_XMLWRITER = ""; - /** - * Called when the sarissa.js file is parsed, to pick most recent - * ProgIDs for IE, then gets destroyed. - * @memberOf Sarissa - * @private - * @param idList an array of MSXML PROGIDs from which the most recent will be picked for a given object - * @param enabledList an array of arrays where each array has two items; the index of the PROGID for which a certain feature is enabled - */ - Sarissa.pickRecentProgID = function (idList){ - // found progID flag - var bFound = false, e; - var o2Store; - for(var i=0; i < idList.length && !bFound; i++){ - try{ - var oDoc = new ActiveXObject(idList[i]); - o2Store = idList[i]; - bFound = true; - }catch (objException){ - // trap; try next progID - e = objException; - } - } - if (!bFound) { - throw "Could not retrieve a valid progID of Class: " + idList[idList.length-1]+". (original exception: "+e+")"; - } - idList = null; - return o2Store; - }; - // pick best available MSXML progIDs - _SARISSA_DOM_PROGID = null; - _SARISSA_THREADEDDOM_PROGID = null; - _SARISSA_XSLTEMPLATE_PROGID = null; - _SARISSA_XMLHTTP_PROGID = null; - // commenting the condition out; we need to redefine XMLHttpRequest - // anyway as IE7 hardcodes it to MSXML3.0 causing version problems - // between different activex controls - //if(!window.XMLHttpRequest){ - /** - * Emulate XMLHttpRequest - * @constructor - */ - XMLHttpRequest = function() { - if(!_SARISSA_XMLHTTP_PROGID){ - _SARISSA_XMLHTTP_PROGID = Sarissa.pickRecentProgID(["Msxml2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]); - } - return new ActiveXObject(_SARISSA_XMLHTTP_PROGID); - }; - //} - // we dont need this anymore - //============================================ - // Factory methods (IE) - //============================================ - // see non-IE version - Sarissa.getDomDocument = function(sUri, sName){ - if(!_SARISSA_DOM_PROGID){ - try{ - _SARISSA_DOM_PROGID = Sarissa.pickRecentProgID(["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]); - }catch(e){ - _SARISSA_DOM_PROGID = "noActiveX"; - } - } - - // Not sure how far IE can carry this but try to do something useful when ActiveX is disabled - var oDoc = _SARISSA_DOM_PROGID == "noActiveX" ? document.createElement("xml") : new ActiveXObject(_SARISSA_DOM_PROGID); - // set validation off, make sure older IEs dont choke (no time or IEs to test ;-) - try{ - oDoc.validateOnParse = false; - oDoc.resolveExternals = "false"; - oDoc.setProperty("ProhibitDTD", false); - }catch(e){} - - // if a root tag name was provided, we need to load it in the DOM object - if (sName){ - // create an artifical namespace prefix - // or reuse existing prefix if applicable - var prefix = ""; - if(sUri){ - if(sName.indexOf(":") > 1){ - prefix = sName.substring(0, sName.indexOf(":")); - sName = sName.substring(sName.indexOf(":")+1); - }else{ - prefix = "a" + Sarissa._getUniqueSuffix(); - } - } - // use namespaces if a namespace URI exists - if(sUri){ - oDoc.loadXML('<' + prefix+':'+sName + " xmlns:" + prefix + "=\"" + sUri + "\"" + " />"); - } else { - oDoc.loadXML('<' + sName + " />"); - } - } - return oDoc; - }; - // see non-IE version - Sarissa.getParseErrorText = function (oDoc) { - var parseErrorText = Sarissa.PARSED_OK; - if(oDoc && oDoc.parseError && oDoc.parseError.errorCode && oDoc.parseError.errorCode != 0){ - parseErrorText = "XML Parsing Error: " + oDoc.parseError.reason + - "\nLocation: " + oDoc.parseError.url + - "\nLine Number " + oDoc.parseError.line + ", Column " + - oDoc.parseError.linepos + - ":\n" + oDoc.parseError.srcText + - "\n"; - for(var i = 0; i < oDoc.parseError.linepos;i++){ - parseErrorText += "-"; - } - parseErrorText += "^\n"; - } - else if(oDoc.documentElement === null){ - parseErrorText = Sarissa.PARSED_EMPTY; - } - return parseErrorText; - }; - // see non-IE version - Sarissa.setXpathNamespaces = function(oDoc, sNsSet) { - oDoc.setProperty("SelectionLanguage", "XPath"); - oDoc.setProperty("SelectionNamespaces", sNsSet); - }; - /** - * A class that reuses the same XSLT stylesheet for multiple transforms. - * @constructor - */ - XSLTProcessor = function(){ - if(!_SARISSA_XSLTEMPLATE_PROGID){ - _SARISSA_XSLTEMPLATE_PROGID = Sarissa.pickRecentProgID(["Msxml2.XSLTemplate.6.0", "MSXML2.XSLTemplate.3.0"]); - } - this.template = new ActiveXObject(_SARISSA_XSLTEMPLATE_PROGID); - this.processor = null; - }; - /** - * Imports the given XSLT DOM and compiles it to a reusable transform - * Note: If the stylesheet was loaded from a URL and contains xsl:import or xsl:include elements,it will be reloaded to resolve those - * @param {DOMDocument} xslDoc The XSLT DOMDocument to import - */ - XSLTProcessor.prototype.importStylesheet = function(xslDoc){ - if(!_SARISSA_THREADEDDOM_PROGID){ - _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.6.0", "MSXML2.FreeThreadedDOMDocument.3.0"]); - } - xslDoc.setProperty("SelectionLanguage", "XPath"); - xslDoc.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'"); - // convert stylesheet to free threaded - var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID); - // make included/imported stylesheets work if exist and xsl was originally loaded from url - try{ - converted.resolveExternals = true; - converted.setProperty("AllowDocumentFunction", true); - converted.setProperty("AllowXsltScript", true); - } - catch(e){ - // Ignore. "AllowDocumentFunction" and "AllowXsltScript" is only supported in MSXML 3.0 SP4+ and 3.0 SP8+ respectively. - } - if(xslDoc.url && xslDoc.selectSingleNode("//xsl:*[local-name() = 'import' or local-name() = 'include']") != null){ - converted.async = false; - converted.load(xslDoc.url); - } - else { - converted.loadXML(xslDoc.xml); - } - converted.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'"); - var output = converted.selectSingleNode("//xsl:output"); - //this.outputMethod = output ? output.getAttribute("method") : "html"; - if(output) { - this.outputMethod = output.getAttribute("method"); - } - else { - delete this.outputMethod; - } - this.template.stylesheet = converted; - this.processor = this.template.createProcessor(); - // for getParameter and clearParameters - this.paramsSet = []; - }; - - /** - * Transform the given XML DOM and return the transformation result as a new DOM document - * @param {DOMDocument} sourceDoc The XML DOMDocument to transform - * @return {DOMDocument} The transformation result as a DOM Document - */ - XSLTProcessor.prototype.transformToDocument = function(sourceDoc){ - // fix for bug 1549749 - var outDoc; - if(_SARISSA_THREADEDDOM_PROGID){ - this.processor.input=sourceDoc; - outDoc=new ActiveXObject(_SARISSA_DOM_PROGID); - this.processor.output=outDoc; - this.processor.transform(); - return outDoc; - } - else{ - if(!_SARISSA_DOM_XMLWRITER){ - _SARISSA_DOM_XMLWRITER = Sarissa.pickRecentProgID(["Msxml2.MXXMLWriter.6.0", "Msxml2.MXXMLWriter.3.0", "MSXML2.MXXMLWriter", "MSXML.MXXMLWriter", "Microsoft.XMLDOM"]); - } - this.processor.input = sourceDoc; - outDoc = new ActiveXObject(_SARISSA_DOM_XMLWRITER); - this.processor.output = outDoc; - this.processor.transform(); - var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID); - oDoc.loadXML(outDoc.output+""); - return oDoc; - } - }; - - /** - * Transform the given XML DOM and return the transformation result as a new DOM fragment. - * Note: The xsl:output method must match the nature of the owner document (XML/HTML). - * @param {DOMDocument} sourceDoc The XML DOMDocument to transform - * @param {DOMDocument} ownerDoc The owner of the result fragment - * @return {DOMDocument} The transformation result as a DOM Document - */ - XSLTProcessor.prototype.transformToFragment = function (sourceDoc, ownerDoc) { - this.processor.input = sourceDoc; - this.processor.transform(); - var s = this.processor.output; - var f = ownerDoc.createDocumentFragment(); - var container; - if (this.outputMethod == 'text') { - f.appendChild(ownerDoc.createTextNode(s)); - } else if (ownerDoc.body && ownerDoc.body.innerHTML) { - container = ownerDoc.createElement('div'); - container.innerHTML = s; - while (container.hasChildNodes()) { - f.appendChild(container.firstChild); - } - } - else { - var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID); - if (s.substring(0, 5) == '') + 2); - } - var xml = ''.concat('', s, ''); - oDoc.loadXML(xml); - container = oDoc.documentElement; - while (container.hasChildNodes()) { - f.appendChild(container.firstChild); - } - } - return f; - }; - - /** - * Set global XSLT parameter of the imported stylesheet. This method should - * only be used after the importStylesheet method for the - * context XSLTProcessor instance. - * @param {String} nsURI The parameter namespace URI - * @param {String} name The parameter base name - * @param {String} value The new parameter value - */ - XSLTProcessor.prototype.setParameter = function(nsURI, name, value){ - // make value a zero length string if null to allow clearing - value = value ? value : ""; - // nsURI is optional but cannot be null - if(nsURI){ - this.processor.addParameter(name, value, nsURI); - }else{ - this.processor.addParameter(name, value); - } - // update updated params for getParameter - nsURI = "" + (nsURI || ""); - if(!this.paramsSet[nsURI]){ - this.paramsSet[nsURI] = []; - } - this.paramsSet[nsURI][name] = value; - }; - /** - * Gets a parameter if previously set by setParameter. Returns null - * otherwise - * @param {String} name The parameter base name - * @param {String} value The new parameter value - * @return {String} The parameter value if reviously set by setParameter, null otherwise - */ - XSLTProcessor.prototype.getParameter = function(nsURI, name){ - nsURI = "" + (nsURI || ""); - if(this.paramsSet[nsURI] && this.paramsSet[nsURI][name]){ - return this.paramsSet[nsURI][name]; - }else{ - return null; - } - }; - - /** - * Clear parameters (set them to default values as defined in the stylesheet itself) - */ - XSLTProcessor.prototype.clearParameters = function(){ - for(var nsURI in this.paramsSet){ - for(var name in this.paramsSet[nsURI]){ - if(nsURI!=""){ - this.processor.addParameter(name, "", nsURI); - }else{ - this.processor.addParameter(name, ""); - } - } - } - this.paramsSet = []; - }; -}else{ /* end IE initialization, try to deal with real browsers now ;-) */ - if(Sarissa._SARISSA_HAS_DOM_CREATE_DOCUMENT){ - /** - *

                                                          Ensures the document was loaded correctly, otherwise sets the - * parseError to -1 to indicate something went wrong. Internal use

                                                          - * @private - */ - Sarissa.__handleLoad__ = function(oDoc){ - Sarissa.__setReadyState__(oDoc, 4); - }; - /** - *

                                                          Attached by an event handler to the load event. Internal use.

                                                          - * @private - */ - _sarissa_XMLDocument_onload = function(){ - Sarissa.__handleLoad__(this); - }; - /** - *

                                                          Sets the readyState property of the given DOM Document object. - * Internal use.

                                                          - * @memberOf Sarissa - * @private - * @param oDoc the DOM Document object to fire the - * readystatechange event - * @param iReadyState the number to change the readystate property to - */ - Sarissa.__setReadyState__ = function(oDoc, iReadyState){ - oDoc.readyState = iReadyState; - oDoc.readystate = iReadyState; - if (oDoc.onreadystatechange != null && typeof oDoc.onreadystatechange == "function") { - oDoc.onreadystatechange(); - } - }; - - Sarissa.getDomDocument = function(sUri, sName){ - var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null); - if(!oDoc.onreadystatechange){ - - /** - *

                                                          Emulate IE's onreadystatechange attribute

                                                          - */ - oDoc.onreadystatechange = null; - } - if(!oDoc.readyState){ - /** - *

                                                          Emulates IE's readyState property, which always gives an integer from 0 to 4:

                                                          - *
                                                          • 1 == LOADING,
                                                          • - *
                                                          • 2 == LOADED,
                                                          • - *
                                                          • 3 == INTERACTIVE,
                                                          • - *
                                                          • 4 == COMPLETED
                                                          - */ - oDoc.readyState = 0; - } - oDoc.addEventListener("load", _sarissa_XMLDocument_onload, false); - return oDoc; - }; - if(window.XMLDocument){ - // do nothing - }// TODO: check if the new document has content before trying to copynodes, check for error handling in DOM 3 LS - else if(Sarissa._SARISSA_HAS_DOM_FEATURE && window.Document && !Document.prototype.load && document.implementation.hasFeature('LS', '3.0')){ - //Opera 9 may get the XPath branch which gives creates XMLDocument, therefore it doesn't reach here which is good - /** - *

                                                          Factory method to obtain a new DOM Document object

                                                          - * @memberOf Sarissa - * @param {String} sUri the namespace of the root node (if any) - * @param {String} sUri the local name of the root node (if any) - * @returns {DOMDOcument} a new DOM Document - */ - Sarissa.getDomDocument = function(sUri, sName){ - var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null); - return oDoc; - }; - } - else { - Sarissa.getDomDocument = function(sUri, sName){ - var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null); - // looks like safari does not create the root element for some unknown reason - if(oDoc && (sUri || sName) && !oDoc.documentElement){ - oDoc.appendChild(oDoc.createElementNS(sUri, sName)); - } - return oDoc; - }; - } - }//if(Sarissa._SARISSA_HAS_DOM_CREATE_DOCUMENT) -} -//========================================== -// Common stuff -//========================================== -if(!window.DOMParser || Sarissa._SARISSA_IS_IE9){ - if(Sarissa._SARISSA_IS_SAFARI){ - /** - * DOMParser is a utility class, used to construct DOMDocuments from XML strings - * @constructor - */ - DOMParser = function() { }; - /** - * Construct a new DOM Document from the given XMLstring - * @param {String} sXml the given XML string - * @param {String} contentType the content type of the document the given string represents (one of text/xml, application/xml, application/xhtml+xml). - * @return {DOMDocument} a new DOM Document from the given XML string - */ - DOMParser.prototype.parseFromString = function(sXml, contentType){ - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("GET", "data:text/xml;charset=utf-8," + encodeURIComponent(sXml), false); - xmlhttp.send(null); - return xmlhttp.responseXML; - }; - }else if(Sarissa.getDomDocument && Sarissa.getDomDocument() && Sarissa.getDomDocument(null, "bar").xml){ - DOMParser = function() { }; - DOMParser.prototype.parseFromString = function(sXml, contentType){ - var doc = Sarissa.getDomDocument(); - try{ - doc.validateOnParse = false; - doc.setProperty("ProhibitDTD", false); - }catch(e){} - doc.loadXML(sXml); - return doc; - }; - } -} - -if((typeof(document.importNode) == "undefined") && Sarissa._SARISSA_IS_IE){ - try{ - /** - * Implementation of importNode for the context window document in IE. - * If oNode is a TextNode, bChildren is ignored. - * @param {DOMNode} oNode the Node to import - * @param {boolean} bChildren whether to include the children of oNode - * @returns the imported node for further use - */ - document.importNode = function(oNode, bChildren){ - var tmp; - if (oNode.nodeName=='#text') { - return document.createTextNode(oNode.data); - } - else { - if(oNode.nodeName == "tbody" || oNode.nodeName == "tr"){ - tmp = document.createElement("table"); - } - else if(oNode.nodeName == "td"){ - tmp = document.createElement("tr"); - } - else if(oNode.nodeName == "option"){ - tmp = document.createElement("select"); - } - else{ - tmp = document.createElement("div"); - } - if(bChildren){ - tmp.innerHTML = oNode.xml ? oNode.xml : oNode.outerHTML; - }else{ - tmp.innerHTML = oNode.xml ? oNode.cloneNode(false).xml : oNode.cloneNode(false).outerHTML; - } - return tmp.getElementsByTagName("*")[0]; - } - }; - }catch(e){ } -} -if(!Sarissa.getParseErrorText){ - /** - *

                                                          Returns a human readable description of the parsing error. Usefull - * for debugging. Tip: append the returned error string in a <pre> - * element if you want to render it.

                                                          - *

                                                          Many thanks to Christian Stocker for the initial patch.

                                                          - * @memberOf Sarissa - * @param {DOMDocument} oDoc The target DOM document - * @returns {String} The parsing error description of the target Document in - * human readable form (preformated text) - */ - Sarissa.getParseErrorText = function (oDoc){ - var parseErrorText = Sarissa.PARSED_OK; - if((!oDoc) || (!oDoc.documentElement)){ - parseErrorText = Sarissa.PARSED_EMPTY; - } else if(oDoc.documentElement.tagName == "parsererror"){ - parseErrorText = oDoc.documentElement.firstChild.data; - parseErrorText += "\n" + oDoc.documentElement.firstChild.nextSibling.firstChild.data; - } else if(oDoc.getElementsByTagName("parsererror").length > 0){ - var parsererror = oDoc.getElementsByTagName("parsererror")[0]; - parseErrorText = Sarissa.getText(parsererror, true)+"\n"; - } else if(oDoc.parseError && oDoc.parseError.errorCode != 0){ - parseErrorText = Sarissa.PARSED_UNKNOWN_ERROR; - } - return parseErrorText; - }; -} -/** - * Get a string with the concatenated values of all string nodes under the given node - * @param {DOMNode} oNode the given DOM node - * @param {boolean} deep whether to recursively scan the children nodes of the given node for text as well. Default is false - * @memberOf Sarissa - */ -Sarissa.getText = function(oNode, deep){ - var s = ""; - var nodes = oNode.childNodes; - // opera fix, finds no child text node for attributes so we use .value - if (oNode.nodeType == Node.ATTRIBUTE_NODE && nodes.length == 0) { - return oNode.value; - } - // END opera fix - for(var i=0; i < nodes.length; i++){ - var node = nodes[i]; - var nodeType = node.nodeType; - if(nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE){ - s += node.data; - } else if(deep === true && (nodeType == Node.ELEMENT_NODE || nodeType == Node.DOCUMENT_NODE || nodeType == Node.DOCUMENT_FRAGMENT_NODE)){ - s += Sarissa.getText(node, true); - } - } - return s; -}; -if(!window.XMLSerializer && Sarissa.getDomDocument && Sarissa.getDomDocument("","foo", null).xml){ - /** - * Utility class to serialize DOM Node objects to XML strings - * @constructor - */ - XMLSerializer = function(){}; - /** - * Serialize the given DOM Node to an XML string - * @param {DOMNode} oNode the DOM Node to serialize - */ - XMLSerializer.prototype.serializeToString = function(oNode) { - return oNode.xml; - }; -} else if (Sarissa._SARISSA_IS_IE9 && window.XMLSerializer) { - // We save old object for any futur use with IE Document (not xml) - IE9XMLSerializer= XMLSerializer; - XMLSerializer = function(){ this._oldSerializer=new IE9XMLSerializer() }; - XMLSerializer.prototype.serializeToString = function(oNode) { - if (typeof(oNode)=='object' && 'xml' in oNode) { - return oNode.xml; - } else { - return this._oldSerializer.serializeToString(oNode); - } - }; -} - -/** - * Strips tags from the given markup string. If the given string is - * undefined, null or empty, it is returned as is. - * @memberOf Sarissa - * @param {String} s the string to strip the tags from - */ -Sarissa.stripTags = function (s) { - return s?s.replace(/<[^>]+>/g,""):s; -}; -/** - *

                                                          Deletes all child nodes of the given node

                                                          - * @memberOf Sarissa - * @param {DOMNode} oNode the Node to empty - */ -Sarissa.clearChildNodes = function(oNode) { - // need to check for firstChild due to opera 8 bug with hasChildNodes - while(oNode.firstChild) { - oNode.removeChild(oNode.firstChild); - } -}; -/** - *

                                                          Copies the childNodes of nodeFrom to nodeTo

                                                          - *

                                                          Note: The second object's original content is deleted before - * the copy operation, unless you supply a true third parameter

                                                          - * @memberOf Sarissa - * @param {DOMNode} nodeFrom the Node to copy the childNodes from - * @param {DOMNode} nodeTo the Node to copy the childNodes to - * @param {boolean} bPreserveExisting whether to preserve the original content of nodeTo, default is false - */ -Sarissa.copyChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) { - if(Sarissa._SARISSA_IS_SAFARI && nodeTo.nodeType == Node.DOCUMENT_NODE){ // SAFARI_OLD ?? - nodeTo = nodeTo.documentElement; //Apparently there's a bug in safari where you can't appendChild to a document node - } - - if((!nodeFrom) || (!nodeTo)){ - throw "Both source and destination nodes must be provided"; - } - if(!bPreserveExisting){ - Sarissa.clearChildNodes(nodeTo); - } - var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument; - var nodes = nodeFrom.childNodes; - var i; - if(typeof(ownerDoc.importNode) != "undefined") { - for(i=0;i < nodes.length;i++) { - nodeTo.appendChild(ownerDoc.importNode(nodes[i], true)); - } - } else { - for(i=0;i < nodes.length;i++) { - nodeTo.appendChild(nodes[i].cloneNode(true)); - } - } -}; - -/** - *

                                                          Moves the childNodes of nodeFrom to nodeTo

                                                          - *

                                                          Note: The second object's original content is deleted before - * the move operation, unless you supply a true third parameter

                                                          - * @memberOf Sarissa - * @param {DOMNode} nodeFrom the Node to copy the childNodes from - * @param {DOMNode} nodeTo the Node to copy the childNodes to - * @param {boolean} bPreserveExisting whether to preserve the original content of nodeTo, default is - */ -Sarissa.moveChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) { - if((!nodeFrom) || (!nodeTo)){ - throw "Both source and destination nodes must be provided"; - } - if(!bPreserveExisting){ - Sarissa.clearChildNodes(nodeTo); - } - var nodes = nodeFrom.childNodes; - // if within the same doc, just move, else copy and delete - if(nodeFrom.ownerDocument == nodeTo.ownerDocument){ - while(nodeFrom.firstChild){ - nodeTo.appendChild(nodeFrom.firstChild); - } - } else { - var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument; - var i; - if(typeof(ownerDoc.importNode) != "undefined") { - for(i=0;i < nodes.length;i++) { - nodeTo.appendChild(ownerDoc.importNode(nodes[i], true)); - } - }else{ - for(i=0;i < nodes.length;i++) { - nodeTo.appendChild(nodes[i].cloneNode(true)); - } - } - Sarissa.clearChildNodes(nodeFrom); - } -}; - -/** - *

                                                          Serialize any non DOM object to an XML string. All properties are serialized using the property name - * as the XML element name. Array elements are rendered as array-item elements, - * using their index/key as the value of the key attribute.

                                                          - * @memberOf Sarissa - * @param {Object} anyObject the object to serialize - * @param {String} objectName a name for that object, to be used as the root element name - * @param {String} indentSpace Optional, the indentation space to use, default is an empty - * string. A single space character is added in any recursive call. - * @param {noolean} skipEscape Optional, whether to skip escaping characters that map to the - * five predefined XML entities. Default is false. - * @return {String} the XML serialization of the given object as a string - */ -Sarissa.xmlize = function(anyObject, objectName, indentSpace, skipEscape){ - indentSpace = indentSpace?indentSpace:''; - var s = indentSpace + '<' + objectName + '>'; - var isLeaf = false; - if(!(anyObject instanceof Object) || anyObject instanceof Number || anyObject instanceof String || anyObject instanceof Boolean || anyObject instanceof Date){ - s += (skipEscape ? Sarissa.escape(anyObject) : anyObject); - isLeaf = true; - }else{ - s += "\n"; - var isArrayItem = anyObject instanceof Array; - for(var name in anyObject){ - // do not xmlize functions - if (anyObject[name] instanceof Function){ - continue; - } - s += Sarissa.xmlize(anyObject[name], (isArrayItem?"array-item key=\""+name+"\"":name), indentSpace + " "); - } - s += indentSpace; - } - return (s += (objectName.indexOf(' ')!=-1?"\n":"\n")); -}; - -/** - * Escape the given string chacters that correspond to the five predefined XML entities - * @memberOf Sarissa - * @param {String} sXml the string to escape - */ -Sarissa.escape = function(sXml){ - return sXml.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); -}; - -/** - * Unescape the given string. This turns the occurences of the predefined XML - * entities to become the characters they represent correspond to the five predefined XML entities - * @memberOf Sarissa - * @param {String}sXml the string to unescape - */ -Sarissa.unescape = function(sXml){ - return sXml.replace(/'/g,"'").replace(/"/g,"\"").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&"); -}; - -/** @private */ -Sarissa.updateCursor = function(oTargetElement, sValue) { - if(oTargetElement && oTargetElement.style && oTargetElement.style.cursor != undefined ){ - oTargetElement.style.cursor = sValue; - } -}; - -/** - * Asynchronously update an element with response of a GET request on the given URL. Passing a configured XSLT - * processor will result in transforming and updating oNode before using it to update oTargetElement. - * You can also pass a callback function to be executed when the update is finished. The function will be called as - * functionName(oNode, oTargetElement); - * @memberOf Sarissa - * @param {String} sFromUrl the URL to make the request to - * @param {DOMElement} oTargetElement the element to update - * @param {XSLTProcessor} xsltproc (optional) the transformer to use on the returned - * content before updating the target element with it - * @param {Function} callback (optional) a Function object to execute once the update is finished successfuly, called as callback(sFromUrl, oTargetElement). - * In case an exception is thrown during execution, the callback is called as called as callback(sFromUrl, oTargetElement, oException) - * @param {boolean} skipCache (optional) whether to skip any cache - */ -Sarissa.updateContentFromURI = function(sFromUrl, oTargetElement, xsltproc, callback, skipCache) { - try{ - Sarissa.updateCursor(oTargetElement, "wait"); - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("GET", sFromUrl, true); - xmlhttp.onreadystatechange = function() { - if (xmlhttp.readyState == 4) { - try{ - var oDomDoc = xmlhttp.responseXML; - if(oDomDoc && Sarissa.getParseErrorText(oDomDoc) == Sarissa.PARSED_OK){ - Sarissa.updateContentFromNode(xmlhttp.responseXML, oTargetElement, xsltproc); - if(callback){ - callback(sFromUrl, oTargetElement); - } - } - else{ - throw Sarissa.getParseErrorText(oDomDoc); - } - } - catch(e){ - if(callback){ - callback(sFromUrl, oTargetElement, e); - } - else{ - throw e; - } - } - } - }; - if (skipCache) { - var oldage = "Sat, 1 Jan 2000 00:00:00 GMT"; - xmlhttp.setRequestHeader("If-Modified-Since", oldage); - } - xmlhttp.send(""); - } - catch(e){ - Sarissa.updateCursor(oTargetElement, "auto"); - if(callback){ - callback(sFromUrl, oTargetElement, e); - } - else{ - throw e; - } - } -}; - -/** - * Update an element's content with the given DOM node. Passing a configured XSLT - * processor will result in transforming and updating oNode before using it to update oTargetElement. - * You can also pass a callback function to be executed when the update is finished. The function will be called as - * functionName(oNode, oTargetElement); - * @memberOf Sarissa - * @param {DOMNode} oNode the URL to make the request to - * @param {DOMElement} oTargetElement the element to update - * @param {XSLTProcessor} xsltproc (optional) the transformer to use on the given - * DOM node before updating the target element with it - */ -Sarissa.updateContentFromNode = function(oNode, oTargetElement, xsltproc) { - try { - Sarissa.updateCursor(oTargetElement, "wait"); - Sarissa.clearChildNodes(oTargetElement); - // check for parsing errors - var ownerDoc = oNode.nodeType == Node.DOCUMENT_NODE?oNode:oNode.ownerDocument; - if(ownerDoc.parseError && ownerDoc.parseError.errorCode != 0) { - var pre = document.createElement("pre"); - pre.appendChild(document.createTextNode(Sarissa.getParseErrorText(ownerDoc))); - oTargetElement.appendChild(pre); - } - else { - // transform if appropriate - if(xsltproc) { - oNode = xsltproc.transformToDocument(oNode); - } - // be smart, maybe the user wants to display the source instead - if(oTargetElement.tagName.toLowerCase() == "textarea" || oTargetElement.tagName.toLowerCase() == "input") { - oTargetElement.value = new XMLSerializer().serializeToString(oNode); - } - else { - // ok that was not smart; it was paranoid. Keep up the good work by trying to use DOM instead of innerHTML - try{ - oTargetElement.appendChild(oTargetElement.ownerDocument.importNode(oNode, true)); - } - catch(e){ - oTargetElement.innerHTML = new XMLSerializer().serializeToString(oNode); - } - } - } - } - catch(e) { - throw e; - } - finally{ - Sarissa.updateCursor(oTargetElement, "auto"); - } -}; - - -/** - * Creates an HTTP URL query string from the given HTML form data - * @memberOf Sarissa - * @param {HTMLFormElement} oForm the form to construct the query string from - */ -Sarissa.formToQueryString = function(oForm){ - var qs = ""; - for(var i = 0;i < oForm.elements.length;i++) { - var oField = oForm.elements[i]; - var sFieldName = oField.getAttribute("name") ? oField.getAttribute("name") : oField.getAttribute("id"); - // ensure we got a proper name/id and that the field is not disabled - if(sFieldName && - ((!oField.disabled) || oField.type == "hidden")) { - switch(oField.type) { - case "hidden": - case "text": - case "textarea": - case "password": - qs += sFieldName + "=" + encodeURIComponent(oField.value) + "&"; - break; - case "select-one": - qs += sFieldName + "=" + encodeURIComponent(oField.options[oField.selectedIndex].value) + "&"; - break; - case "select-multiple": - for (var j = 0; j < oField.length; j++) { - var optElem = oField.options[j]; - if (optElem.selected === true) { - qs += sFieldName + "[]" + "=" + encodeURIComponent(optElem.value) + "&"; - } - } - break; - case "checkbox": - case "radio": - if(oField.checked) { - qs += sFieldName + "=" + encodeURIComponent(oField.value) + "&"; - } - break; - } - } - } - // return after removing last '&' - return qs.substr(0, qs.length - 1); -}; - - -/** - * Asynchronously update an element with response of an XMLHttpRequest-based emulation of a form submission.

                                                          The form action and - * method attributess will be followed. Passing a configured XSLT processor will result in - * transforming and updating the server response before using it to update the target element. - * You can also pass a callback function to be executed when the update is finished. The function will be called as - * functionName(oNode, oTargetElement);

                                                          - *

                                                          Here is an example of using this in a form element:

                                                          - *
                                                          - * <div id="targetId"> this content will be updated</div>
                                                          - * <form action="/my/form/handler" method="post" 
                                                          - *     onbeforesubmit="return Sarissa.updateContentFromForm(this, document.getElementById('targetId'));">
                                                          - * 

                                                          If JavaScript is supported, the form will not be submitted. Instead, Sarissa will - * scan the form and make an appropriate AJAX request, also adding a parameter - * to signal to the server that this is an AJAX call. The parameter is - * constructed as Sarissa.REMOTE_CALL_FLAG = "=true" so you can change the name in your webpage - * simply by assigning another value to Sarissa.REMOTE_CALL_FLAG. If JavaScript is not supported - * the form will be submitted normally. - * @memberOf Sarissa - * @param {HTMLFormElement} oForm the form submition to emulate - * @param {DOMElement} oTargetElement the element to update - * @param {XSLTProcessor} xsltproc (optional) the transformer to use on the returned - * content before updating the target element with it - * @param {Function} callback (optional) a Function object to execute once the update is finished successfuly, called as callback(oNode, oTargetElement). - * In case an exception occurs during excecution and a callback function was provided, the exception is cought and the callback is called as - * callback(oForm, oTargetElement, exception) - */ -Sarissa.updateContentFromForm = function(oForm, oTargetElement, xsltproc, callback) { - try{ - Sarissa.updateCursor(oTargetElement, "wait"); - // build parameters from form fields - var params = Sarissa.formToQueryString(oForm) + "&" + Sarissa.REMOTE_CALL_FLAG + "=true"; - var xmlhttp = new XMLHttpRequest(); - var bUseGet = oForm.getAttribute("method") && oForm.getAttribute("method").toLowerCase() == "get"; - if(bUseGet) { - xmlhttp.open("GET", oForm.getAttribute("action")+"?"+params, true); - } - else{ - xmlhttp.open('POST', oForm.getAttribute("action"), true); - xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - xmlhttp.setRequestHeader("Content-length", params.length); - xmlhttp.setRequestHeader("Connection", "close"); - } - xmlhttp.onreadystatechange = function() { - try{ - if (xmlhttp.readyState == 4) { - var oDomDoc = xmlhttp.responseXML; - if(oDomDoc && Sarissa.getParseErrorText(oDomDoc) == Sarissa.PARSED_OK){ - Sarissa.updateContentFromNode(xmlhttp.responseXML, oTargetElement, xsltproc); - if(callback){ - callback(oForm, oTargetElement); - } - } - else{ - throw Sarissa.getParseErrorText(oDomDoc); - } - } - } - catch(e){ - if(callback){ - callback(oForm, oTargetElement, e); - } - else{ - throw e; - } - } - }; - xmlhttp.send(bUseGet?"":params); - } - catch(e){ - Sarissa.updateCursor(oTargetElement, "auto"); - if(callback){ - callback(oForm, oTargetElement, e); - } - else{ - throw e; - } - } - return false; -}; - -/** - * Get the name of a function created like: - *

                                                          function functionName(){}
                                                          - * If a name is not found, attach the function to - * the window object with a new name and return that - * @param {Function} oFunc the function object - */ -Sarissa.getFunctionName = function(oFunc){ - if(!oFunc || (typeof oFunc != 'function' )){ - throw "The value of parameter 'oFunc' must be a function"; - } - if(oFunc.name) { - return oFunc.name; - } - // try to parse the function name from the defintion - var sFunc = oFunc.toString(); - alert("sFunc: "+sFunc); - var name = sFunc.substring(sFunc.indexOf('function') + 8 , sFunc.indexOf('(')); - if(!name || name.length == 0 || name == " "){ - // attach to window object under a new name - name = "SarissaAnonymous" + Sarissa._getUniqueSuffix(); - window[name] = oFunc; - } - return name; -}; - -/** - * - */ -Sarissa.setRemoteJsonCallback = function(url, callback, callbackParam) { - if(!callbackParam){ - callbackParam = "callback"; - } - var callbackFunctionName = Sarissa.getFunctionName(callback); - //alert("callbackFunctionName: '" + callbackFunctionName+"', length: "+callbackFunctionName.length); - var id = "sarissa_json_script_id_" + Sarissa._getUniqueSuffix(); - var oHead = document.getElementsByTagName("head")[0]; - var scriptTag = document.createElement('script'); - scriptTag.type = 'text/javascript'; - scriptTag.id = id; - scriptTag.onload = function(){ - // cleanUp - // document.removeChild(scriptTag); - }; - if(url.indexOf("?") != -1){ - url += ("&" + callbackParam + "=" + callbackFunctionName); - } - else{ - url += ("?" + callbackParam + "=" + callbackFunctionName); - } - scriptTag.src = url; - oHead.appendChild(scriptTag); - return id; -}; - -// EOF diff --git a/extensions/admin/resources/syi_attributes.xsl b/extensions/admin/resources/syi_attributes.xsl deleted file mode 100644 index fd838d19e..000000000 --- a/extensions/admin/resources/syi_attributes.xsl +++ /dev/null @@ -1,4859 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - -
                                                          -
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - , - - - - - - - - - - - -   - - -    - - - - - - - - - - - - - - - - - - - - - - - - - - - , - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - Click Update below to see relevant choices -
                                                          - - - - -
                                                          - -
                                                          - - - - - - -
                                                          - - - - - 3 - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - -   -
                                                          -
                                                          - - - - - -
                                                          - - - - - -
                                                          - -
                                                          -
                                                          -
                                                          - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vvc_anyParent('attr','attr');vvsp_check('attr', this.value); - - - vvc_anyParent('attr','attr'); - - - api_check_on_other('attr',-6); - - - - - - checked - - - - - - _mvs - - checked - font: italic; color: Gray; background: Silver; - if(this.name.indexOf('_mvs')>0){this.style.background=document.bgColor;this.name=this.name.substring(0,this.name.length-4);} - if(this.name.indexOf('_mvs')>0){this.style.background=document.bgColor;this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vvc_anyParent('a','a'); - - - - - checked - - - - checked - - - - - - - - -   -
                                                          - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 01;02;03;04;05;06;07;08;09;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31; - 31;30;29;28;27;26;25;24;23;22;21;20;19;18;17;16;15;14;13;12;11;10;09;08;07;06;05;04;03;02;01; - Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec; - Dec;Nov;Oct;Sep;Aug;Jul;Jun;May;Apr;Mar;Feb;Jan; - - 01;02;03;04;05;06;07;08;09;10;11;12; - 12;11;10;09;08;07;06;05;04;03;02;01; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JanFebMarAprMayJunJulAugSepOctNovDec - - - - - - DecNovOctSepAugJulJunMayAprMarFebJan - - - - - - JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember - - - - - - DecemberNovemberOctoberSeptemberAugustJulyJuneMayAprilMarchFebruaryJanuary - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 01;02;03;04;05;06;07;08;09;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31; - 31;30;29;28;27;26;25;24;23;22;21;20;19;18;17;16;15;14;13;12;11;10;09;08;07;06;05;04;03;02;01; - - - - Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec; - - - - - - Dec;Nov;Oct;Sep;Aug;Jul;Jun;May;Apr;Mar;Feb;Jan; - - - - - - Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec; - - - - - - Dec;Nov;Oct;Sep;Aug;Jul;Jun;May;Apr;Mar;Feb;Jan; - - - 01;02;03;04;05;06;07;08;09;10;11;12; - 12;11;10;09;08;07;06;05;04;03;02;01; - 2001;2002;2003;2004;2005;2006; - 2006;2005;2004;2003;2002;2001; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - top - - - - - - - - - - - - - - - - - - - - - bottom - - - -
                                                           
                                                           
                                                           
                                                          -
                                                          - - - - - if(this.options[0].value=='mvs'){this.remove(0);this.style.color='black';this.style.fontStyle='normal';this.name=this.name.substring(0,this.name.length-4);}; - - - - - - - - - - sovcf__ - _ - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -var formName = ''; -var attr15 = 'attr15'; -var postInverse = 0; - - -vvpSelectedValue = { -"attr" : "", - -} - -vvpArray = { -"attr" : ["",], - -} - - - - - - -var attr = 1; - - - -vvsp_choices = { -"attr" : [ "", - ], - -} - -vvsp_choices2 = { - -"attr" : [ "", - ], - -} - - - - -aus_dependent_choices = { - - - - - , - - - , - "attr" : { - , - "attr" : [ ["","" ,"default"], - ] - } - -} - - -aus_influencers = { -"attr" : ["attr"], - -} - -aus_parent_child = { -"attr" : [], - -} - -aus_disabled_labels = { - -"attr" : -"" -" " - -, - -} -aus_allow_other = { - - -"" : 1, - - - -} - - -aus_disabled_if_empty = {} - - - - - - - - - - - - "attr","attr_hidden" - ,"attr","attr_hidden" - - - - - "a" - ,"a" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - -   - - - - - -   - - - - - - - - - - - - - - - - - - - - - - sovcf__ - _ - - - - - - - - - - - - - - - - 2 - - - - - - - - #000000 - - - - - - - - Verdana,Geneva,Arial,Helvetica - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - Error! Code: - -
                                                          - -
                                                          - - - -
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - -
                                                          - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - -
                                                          -
                                                          - - - - - -
                                                          - - - - - - - - - -
                                                          -
                                                          -
                                                          -
                                                          - - - 300 - 20 - - - - - - - - - - - - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal';this.name=this.name.substring(0,this.name.length-4);} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';this.name=this.name+'_mvs'} - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - 2 - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal'} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal'} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal'} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';;this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / - - / - - - - - - - / - - / - - - - - - - - - - - - - 20 - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal'} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - APIForm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - hidden - def_ - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                           
                                                          - - - - -
                                                           
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - January;February;March;April;May;June;July;August;September;October;November;December; - - - - - - - - - - - - -   - - - - - - . - - - - - - - - - - . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - -
                                                          - - - - - - - Additional Item Specifics - Item Specifics - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - " - - - - - - - - - - - - - - - - -
                                                          diff --git a/extensions/admin/resources/syi_attributes_orig.xsl b/extensions/admin/resources/syi_attributes_orig.xsl deleted file mode 100644 index 9f50952a5..000000000 --- a/extensions/admin/resources/syi_attributes_orig.xsl +++ /dev/null @@ -1,4892 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - -
                                                          -
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - , - - - - - - - - - - - -   - - -    - - - - - - - - - - - - - - - - - - - - - - - - - - - , - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - Click Update below to see relevant choices -
                                                          - - - - -
                                                          - -
                                                          - - - - - - -
                                                          - - - - - 3 - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - -   -
                                                          -
                                                          - - - - - -
                                                          - - - - - -
                                                          - -
                                                          -
                                                          -
                                                          - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vvc_anyParent('attr','attr');vvsp_check('attr', this.value); - - - vvc_anyParent('attr','attr'); - - - api_check_on_other('attr',-6); - - - - - - checked - - - - - - _mvs - - checked - font: italic; color: Gray; background: Silver; - if(this.name.indexOf('_mvs')>0){this.style.background=document.bgColor;this.name=this.name.substring(0,this.name.length-4);} - if(this.name.indexOf('_mvs')>0){this.style.background=document.bgColor;this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vvc_anyParent('a','a'); - - - - - checked - - - - checked - - - - - - - - -   -
                                                          - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 01;02;03;04;05;06;07;08;09;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31; - 31;30;29;28;27;26;25;24;23;22;21;20;19;18;17;16;15;14;13;12;11;10;09;08;07;06;05;04;03;02;01; - Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec; - Dec;Nov;Oct;Sep;Aug;Jul;Jun;May;Apr;Mar;Feb;Jan; - - 01;02;03;04;05;06;07;08;09;10;11;12; - 12;11;10;09;08;07;06;05;04;03;02;01; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JanFebMarAprMayJunJulAugSepOctNovDec - - - - - - DecNovOctSepAugJulJunMayAprMarFebJan - - - - - - JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember - - - - - - DecemberNovemberOctoberSeptemberAugustJulyJuneMayAprilMarchFebruaryJanuary - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 01;02;03;04;05;06;07;08;09;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31; - 31;30;29;28;27;26;25;24;23;22;21;20;19;18;17;16;15;14;13;12;11;10;09;08;07;06;05;04;03;02;01; - - - - Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec; - - - - - - Dec;Nov;Oct;Sep;Aug;Jul;Jun;May;Apr;Mar;Feb;Jan; - - - - - - Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec; - - - - - - Dec;Nov;Oct;Sep;Aug;Jul;Jun;May;Apr;Mar;Feb;Jan; - - - 01;02;03;04;05;06;07;08;09;10;11;12; - 12;11;10;09;08;07;06;05;04;03;02;01; - 2001;2002;2003;2004;2005;2006; - 2006;2005;2004;2003;2002;2001; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - top - - - - - - - - - - - - - - - - - - - - - bottom - - - -
                                                           
                                                           
                                                           
                                                          -
                                                          - - - - - if(this.options[0].value=='mvs'){this.remove(0);this.style.color='black';this.style.fontStyle='normal';this.name=this.name.substring(0,this.name.length-4);}; - - - - - - - - - - sovcf__ - _ - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -var formName = ''; -var attr15 = 'attr15'; -var postInverse = 0; - - -vvpSelectedValue = { -"attr" : "", - -} - -vvpArray = { -"attr" : ["",], - -} - - - - - - -var attr = 1; - - - -vvsp_choices = { -"attr" : [ "", - ], - -} - -vvsp_choices2 = { - -"attr" : [ "", - ], - -} - - - - -aus_dependent_choices = { - - - - - , - - - , - "attr" : { - , - "attr" : [ ["","" ,"default"], - ] - } - -} - - -aus_influencers = { -"attr" : ["attr"], - -} - -aus_parent_child = { -"attr" : [], - -} - -aus_disabled_labels = { - -"attr" : -"" -" " - -, - -} -aus_allow_other = { - - -"" : 1, - - - -} - - -aus_disabled_if_empty = {} - - - - - - - - - - - - "attr","attr_hidden" - ,"attr","attr_hidden" - - - - - "a" - ,"a" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - -   - - - - - -   - - - - - - - - - - - - - - - - - - - - - - sovcf__ - _ - - - - - - - - - - - - - - - - 2 - - - - - - - - #000000 - - - - - - - - Verdana,Geneva,Arial,Helvetica - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - Error! Code: - -
                                                          - -
                                                          - - - -
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - -
                                                          - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - -
                                                          -
                                                          - - - - - -
                                                          - - - - - - - - - -
                                                          -
                                                          -
                                                          -
                                                          - - - 300 - 20 - - - - - - - - - - - - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal';this.name=this.name.substring(0,this.name.length-4);} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';this.name=this.name+'_mvs'} - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - 2 - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal'} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal'} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal'} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';;this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / - - / - - - - - - - / - - / - - - - - - - - - - - - - 20 - - - - - _mvs - - - font: italic; color: gray; - if(this.value==''){this.value='';this.style.color='black';this.style.fontStyle='normal'} - if(this.value==''){this.value='';this.style.color='gray';this.style.fontStyle='italic';this.name=this.name.substring(0,this.name.length-4);} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - APIForm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - hidden - def_ - - - - - - - - - - - - - - - Select category: -
                                                          - -
                                                          -
                                                          -
                                                          - - - - - - - -
                                                           
                                                          - - - - -
                                                           
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - January;February;March;April;May;June;July;August;September;October;November;December; - - - - - - - - - - - - -   - - - - - - . - - - - - - - - - - . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          - - - - - - - - -
                                                          - - - - - - - Additional Item Specifics - Item Specifics - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                          -
                                                          -
                                                          - - - - - - - - - - - - - - - - - - - - - - <xsl:copy-of select="$API.Overrides/Styles/Head/node()"/> - </head> - <body bgcolor="white"> - <xsl:copy-of select="$API.Overrides/Styles/Background/@*"/> - <form action="AttrPage" name="{$formName}" id="{$formName}" method="post"> - <xsl:call-template name="ItemSpecifics"/> - </form> - </body> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - - <xsl:template name="escapeQuot"> - <xsl:param name="text" /> - <xsl:param name="quot">"</xsl:param> - - <xsl:choose> - <xsl:when test="contains($text, $quot)"> - <xsl:variable name="bufferBefore" select="substring-before($text,$quot)" /> - <xsl:variable name="newBuffer" select="substring-after($text,$quot)" /> - <xsl:value-of select="concat($bufferBefore,'\',$quot)" /> - <xsl:call-template name="escapeQuot"> - <xsl:with-param name="text" select="$newBuffer" /> - <xsl:with-param name="quot" select="$quot" /> - </xsl:call-template> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="$text" /> - </xsl:otherwise> - </xsl:choose> - </xsl:template> -</xsl:stylesheet> diff --git a/extensions/admin/sites.css b/extensions/admin/sites.css new file mode 100644 index 000000000..5a538ef2c --- /dev/null +++ b/extensions/admin/sites.css @@ -0,0 +1,21 @@ +.domainDetailLogoContainer {width:20%; float:left;} +.domainDetailTabsContainer {width:75%; float:right;} + +.logoWhiteness {margin:2px; background:#fff;} /* solid white behind logo, but a margin of 1 so 'edited' creates a border around the image */ + +.domainList th {text-align:left;} +.domainList th.alignRight {text-align:right;} + +.domainList {border-spacing:0 1px;} +.domainList th, .domainList tf {padding:2px 12px 2px 2px; vertical-align:top;} + +td.domainDetailRow {border-bottom:1px solid #efefef;} + + +.hostChooser {max-height:200px; overflow:auto;} +.hostChooserHostList {margin:.2 0 .5em .2em; padding:0; list-style:none;} +.hostChooserHostListItem {margin-bottom:.1em; padding:.2em .5em; cursor:pointer;} + +@media only screen and (min-height: 500px) { + .hostChooser {max-height:450px;} + } \ No newline at end of file diff --git a/extensions/admin/sites.html b/extensions/admin/sites.html new file mode 100644 index 000000000..547a34d8b --- /dev/null +++ b/extensions/admin/sites.html @@ -0,0 +1,675 @@ +<div id="pageTemplateSites" class="ui-widget"> + + <div data-tlc="bind $var '.*favorites'; if(is $var --notblank;) {{ apply --show; }};"> + <ul data-tlc="bind $var '.*favorites'; controller#loop --templateid='domainListFavoriteTemplate'; apply --append;" class="marginTop listStyleNone ui-widget noPadOrMargin clearfix" data-app-role="domainListFavorites"></ul> + </div> + + + <div class="ui-widget-content ui-corner-all stdPadding"> + <table data-tlc="bind $var '.@DOMAINS'; controller#loop --templateid='sitesDomainRowTemplate'; apply --append;" class="fullWidth gridTable marginTop" data-app-role="domainListNonFavorites"> + <thead> + <tr> + <th colspan="2">Domain</th> + <th>Partition</th> + <th></th> + </tr> + </thead> + <tbody></tbody> + </table> + </div> + +</div> + + + +<ul> + <li id="domainListFavoriteTemplate" class="ui-widget-content ui-corner-all domainPanel positionRelative smallButton"> + <div class="alignCenter"> + <img data-tlc="admin#companylogo --useParentData='1' --legacy ; apply --append;" src="blank.gif" class="prodThumb" data-bind="useParentData:1; format:companyLogo; extension:admin;" height="160" width="160"> + </div> + + <div data-tlc="bind $var '.DOMAINNAME'; apply --attrib='data-domain';" class="positionAbsolute positionTop positionRight stdPadding"><!-- stdPadding aligns this button w/ host-buttons --> + <button data-app-click="admin_sites|domainPutInFocus" data-text="false" data-icon-primary="ui-icon-check" class="applyButton">Use Domain</button> + </div> + + <h4 class="alignCenter smallPadding"> + <span data-tlc="bind $var '.DOMAINNAME'; apply --append;"></span> + <span data-tlc="bind $var '.PRT'; format --prepend='('; format --append=')'; apply --append;"></span> + </h4> + </li> +</ul> + +<table> +<!-- used in 'sites' tab for list of all domains --> +<tbody> +<tr id="sitesDomainRowTemplate"> + <td class="alignCenter width1"><img data-tlc="admin#companylogo --useParentData='1' --legacy ; apply --append;" src="blank.gif" class="prodThumb" data-bind="useParentData:1; format:companyLogo; extension:admin;" height="40" width="80"></td> + <td data-tlc="bind $var '.DOMAINNAME'; apply --append;"></td> + <td data-tlc="bind $var '.PRT'; apply --append;"></td> + <td class="alignRight"> + <button data-app-click="admin_sites|domainPutInFocus" class="applyButton" data-text="false" data-icon-primary="ui-icon-check">Use Domain</button> + <button data-app-click="admin_sites|adminDomainToggleFavoriteExec" class="applyButton" data-text="false" data-icon-primary="ui-icon-tag" data-tlc="bind $var '.IS_FAVORITE'; if (is $var --eq=1) {{ apply --add --class='ui-state-highlight'; }};">Tag as Favorite</button> + </td> +</tr> +</tbody> +</table> + + + + +<!-- +//////////// FOR THE DOMAINS AND APP CONFIG PAGE +--> + + +<div id="domainAndAppConfigTemplate" class="ui-widget smallButton"> + + + <section class="marginBottom" data-app-role="domainsAndHostsContainer" data-tablefilter-role="container"> + <div class="ui-widget-header ui-widget-header-padding ui-corner-top"> + + <button class="applyButton floatRight " data-app-click="admin_sites|adminDomainCreateShow" data-text="true" data-icon-primary="ui-icon-circle-plus">Add Domain</button> + + <span class="marginRight floatRight"> + <input name="tableSearchQuery" placeholder="filter value" x-webkit-speech="x-webkit-speech" data-app-keyup="admin|tableFilter" type="search"> + </span> + + <h2 class="smallPadding">Domain Configuration</h2> + </div> + <div class="ui-widget-content ui-corner-bottom stdPadding"> + <table data-tlc="bind $var '.@DOMAINS'; controller#loop --templateid='domainListTemplate'; apply --append;" class="fullWidth marginTop domainList" data-app-role="domainListNonFavorites" data-tablefilter-role="table" data-tablefilter-selector="tbody"> + <thead> + <tr> + <th>Domain</th> + <th>Partition</th> + <th></th> + <th data-anytable-nosort="true"></th> + </tr> + </thead> + </table> + </div> + </section> + + <section data-app-role="projectsContainer" data-tablefilter-role="container"> + <div class="ui-widget-header ui-widget-header-padding ui-corner-top"> + <button class="applyButton floatRight" data-icon-primary="ui-icon-circle-plus" data-app-click="admin_sites|projectCreateShow">Add Project</button> + <span class="marginRight floatRight"> + <input name="tableSearchQuery" placeholder="filter value" x-webkit-speech="x-webkit-speech" data-app-keyup="admin|tableFilter" type="search"> + </span> + <h2 class="smallPadding">Projects</h2> + </div> + <div class="ui-widget-content ui-corner-bottom stdPadding"> + <table data-tlc="bind $var '.@PROJECTS'; controller#loop --templateid='projectsListTemplate'; apply --append;" class="fullWidth gridTable marginTop" data-tablefilter-role="table" data-tablefilter-selector="tbody"> + <thead> + <tr> + <th>Title</th> + <th>Type</th> + <th data-anytable-nosort="true"></th> + </tr> + </thead> + </table> + </div> + + </section> + + +</div> + + + + + + + +<!-- used in domain config for each domain in the list. --> +<table> + +<tbody id="domainListTemplate" data-element="domain"> +<tr> + <td data-tlc="bind $var '.DOMAINNAME'; apply --append;" class="isSearchable"></td> + <td data-tlc="bind $var '.PRT'; apply --append;" class="isSearchable"></td> + <td></td> + <td class="alignRight"> + <button data-app-click="admin_sites|adminDomainRemoveConfirm" class="applyButton" data-text="false" data-icon-primary="ui-icon-trash">Remove Domain</button> + <button data-app-click="admin_batchjob|adminBatchJobExec" class="applyButton" data-text="false" data-icon-primary="ui-icon-refresh" data-type="UTILITY/SITEMAP" data-whitelist="DOMAINNAME,PRT">Update Sitemap</button> + <button data-app-click="admin_sites|domainPutInFocus" class="applyButton" data-text="false" data-icon-primary="ui-icon-check" title="Use this domain">Use Domain</button> + <button data-app-click="admin_sites|adminDomainDetailShow" class="applyButton" data-text="false" data-icon-primary="ui-icon-pencil" title="Edit this domain">Details</button> + </td> +</tr> +<tr> + <td colspan="4" class="domainDetailRow"> + <div class="displayNone" data-app-role="domainDetailContainer"> + + </div> + </td> +</tr> +</tbody> + + + + + + + + +<!-- used in domain config for each host per domain (in hosts tab) --> +<tbody><tr id="domainListHostsRowTemplate" data-element="host"> + <td data-tlc="bind $var '.HOSTNAME'; apply --append;"></td> + <td data-tlc="bind $var '.HOSTTYPE'; apply --append;"></td> + <td data-tlc="bind $var '.PROJECT'; if(is $var --notblank;){{admin_sites#projectidpretty --legacy ; apply --append;}};"></td> + <td class="alignRight width50"> + <span data-tlc="admin_sites#apphostbuttons --useParentData='true' --legacy ; apply --append;" data-bind="useParentData:true; format:appHostButtons; extension:admin_sites;"></span> + <button class="applyButton" data-app-click="admin|tagRow4Remove" data-text="false" data-icon-primary="ui-icon-close">Delete this Host</button> + <button class="applyButton" data-app-click="admin_sites|adminDomainCreateUpdateHostShow" data-mode="update" data-icon-primary="ui-icon-pencil" data-text="false">Edit Host</button> + <button class="applyButton" data-app-click="admin_sites|domainView" data-mode="host" data-text="false" data-icon-primary="ui-icon-newwin">View Site</button><!-- buttons that always show up should be on the right so they don't move --> + </td> +</tr> + + + + + + +<!-- used in the events tab of domain config --> +<tr id="domainManagerHistoryRowTemplate"> + <td data-tlc="bind $var '.DOMAINNAME'; apply --append;"></td> + <td data-tlc="bind $var '.TXT'; apply --append;"></td> + <td data-tlc="bind $var '.CLASS'; apply --append;"></td> + <td data-tlc="bind $var '.CREATED_GMT'; datetime --out='pretty'; apply --append;"></td> +</tr> + +<!-- used in host type VSTORE for rewrite rules --> +<tr id="domainManagerRewriteRowTemplate"> + <td data-tlc="bind $var '.PATH'; apply --append;"></td> + <td data-tlc="bind $var '.TARGETURL'; apply --append;"></td> + <td> + <button data-app-click="admin|tagRow4Remove" class='applyButton' data-text='false' data-icon-primary='ui-icon-close'>Delete Rule</button> + </td> +</tr> + + +<tr id="domainManagerDiagnosticsRowTemplate"> + <td data-tlc="bind $var '._'; apply --append;"></td> + <td data-tlc="bind $var '.+'; apply --append;"></td> + <td data-tlc="bind $var '.!'; apply --append;"></td> +</tr> + + +</tbody></table> + + + + + + + + + + + + +<div id='domainCreateTemplate'> +<!-- no validate is turned on because there are input flagged as 'required' that are conditionally required. validateForm handles these --> +<form action='#' onSubmit='return false' data-app-submit='admin_sites|adminDomainCreateExec' novalidate='novalidate'> + +<fieldset class='labelsAsBreaks alignedLabels'> + + <label> + <span>Type</span> + <select name='domaintype' required='required' data-panel-selector=".domainCreateDomaintype" data-input-change="panel-selector"> + <option value='DOMAIN-CREATE' data-show-panel='domainCreateDomaintypeCreate'>I have a domain</option> + <option value='DOMAIN-RESERVE' data-show-panel='domainCreateDomaintypeReserve'>Create a temporary domain</option> + </select> + </label> + + <div data-panel-id='domainCreateDomaintypeCreate' class='displayNone domainCreateDomaintype'> + <label> + <span>Domain</span> + <input type='text' required data-validation-rules='skipIfHidden' name='DOMAINNAME' value='' /> + </label> + </div> + <div data-panel-id='domainCreateDomaintypeReserve' class='displayNone hint domainCreateDomaintype'> + If you do not already have a domain or are evaluating the platform, this is a good place to start.<br /> + A temporary domain will be created and will expire after 90 days. + </div> + + + + +</fieldset> + +<div class='buttonset alignRight'> + <button class='applyButton'>Add Domain</button> +</div> + +</form> +</div> + + + +<div id='domainAddUpdateHostTemplate'> +<form action='#' onSubmit='return false' class='labelsAsBreaks alignedLabels'> + <input type="hidden" name="DOMAINNAME" data-bind="var:domain(DOMAINNAME); format:popVal;" /> + + <fieldset> + + <label> + <span>Host name</span> + <input type='text' name='HOSTNAME' data-bind="var: host(HOSTNAME); format:popVal;" required='required' /> + </label> +<!-- the save for this looks for specific host types to generate the macro. don't change these without updating admin_config.u.domainAddUpdateHost --> + <label> + <span>Host Type</span> + <select name='HOSTTYPE' data-input-change="panel-selector" data-panel-selector=".domainNewHostSelectType" required='required' data-bind="var: host(HOSTTYPE); format:popVal;"> + <option value=''>Please choose</option> + <option value='APPTIMIZER' data-show-panel='domainNewHostTypeSITEPTR,domainForceHTTPS'>Apptimizer</option> + <option value='REDIR' data-show-panel='domainNewHostTypeREDIR'>Redirect</option> + <option value='VSTORE' data-show-panel='domainNewHostTypeVSTORE' class='showForZoovyOnly'>V-Store</option> + <option value='VSTORE-APP' data-show-panel='domainNewHostTypeVSTORE' class='showForZoovyOnly' style='display:block;'>V-Store/App</option><!-- inline css to override a behavior w/ showforzoovyonly. ### FUTURE -> fix --> + <option value='CUSTOM'>Custom</option> + </select> + </label> + + </fieldset> + + +<!-- these are the 'panels' for the host type select list --> + <div data-panel-id='domainNewHostTypeSITEPTR' class='displayNone domainNewHostSelectType'> + + + + <label> + <span>Project Source: </span> + <select name='project_source' data-input-change="panel-selector" data-panel-selector=".domainNewHostProjectSource"> + <option value='project' data-show-panel='domainNewHostProjectSource_project'>Existing project</option> + <option value='template' data-show-panel='domainNewHostProjectSource_template'>New project from Template</option> + </select> + + </label> + + + <label class='domainNewHostProjectSource' data-panel-id='domainNewHostProjectSource_project'> + <span>Project Reference</span> + <select name='PROJECT' data-bind="var: project(@PROJECTS); format: optionsfromlist; value:UUID; text:TITLE;"> + <option value=''></option> + </select> + </label> + + <label data-app-role='hostTemplateListContainer' class='domainNewHostProjectSource' data-panel-id='domainNewHostProjectSource_template'> + <span>Template List</span> + <select name='TEMPLATE' data-bind="var: project(@TEMPLATES); format: optionsfromlist; value:SUBDIR; text:SUBDIR;"> + <option value=''></option> + </select> + </label> + </div> + + <div data-panel-id='domainForceHTTPS' class='displayNone domainNewHostSelectType'> + <label> + <input type='checkbox' name='force_https' class='applyAnycb' data-bind="var: host(force_https); format:popVal;" /> + Force https + </label> + + </div> + + <div data-panel-id='domainNewHostTypeREDIR' class='displayNone domainNewHostSelectType'> + <label> + <span>Redirect</span> + <input type='url' name='REDIR' value='' data-bind="var:host(REDIR); format:popVal;" /> + </label> + </div> + + <!-- + NOTE: this doesn't work, we'll just have people use CSV for vstore from now on. + + <div data-panel-id='domainNewHostTypeVSTORE' class='displayNone domainNewHostSelectType hint' data-table-role='container'> + <fieldset class='alignedInputs' data-table-role='inputs'> + <legend>Rewrite Rules</legend> + <label> + <span>Incoming URL</span> + <input type='url' required='required' name='PATH' value='' /> + </label> + <label> + <span>Rewrite to</span> + <input type='url' required='required' name='TARGETURL' value='' /> + </label> + <button data-app-click='admin_config|dataTableAddUpdate' class='applyButton' data-text='true' data-form-skipreset='true'>Apply</button><!-- needs to be within fieldset for taxTableUpdateExec --> + <!-- + <table class='marginTop applyAnytable gridTable fullWidth' data-app-role='dataTable'> + <thead> + <tr> + <td>Incoming URL</td> + <td>Destination URL</td> + <td></td> + </tr> + </thead> + <tbody data-bind="var: shipping(@REWRITES); format:processList; loadsTemplate:domainManagerRewriteRowTemplate;" data-app-role='domainRewriteRulesTbody' data-table-role='content'></tbody> + </table> + + </fieldset> + </div> + --> + + <fieldset data-app-role='sslInputsContainer' class='alignedInputs'> + <legend>SSL Certificate</legend> +<!-- +There are five components to SSL. + IP address (which 'may' no longer be necessary) + Private key -> basically a really long password. generated once typically, unless compromised. + csr -> generated from private key. given to Certificate Authority (CA) (authorizenet, verisign, etc). + certificate -> generated by certificate authority. loaded onto webserver. + chained (intermediate) certificate -> links root browser cert to end cert of CA. that way if CA gets comprimised, only intermediate needs to get replaced. +--> + <label> + <span>Certificate</span> + <textarea data-bind="var: host(CRT); format:popVal;" name='CRT' rows='6'></textarea> + + </label> + <label> + <span>Key</span> + <textarea data-bind="var: host(KEY); format:popVal;" name='KEY' rows='6'></textarea> + </label> + <button class='applyButton' data-text='true' data-icon-primary='ui-icon-key' data-app-click='admin_sites|cryptoToolMakeKeyShow'>Make Key</button> + </fieldset> + + + + + + + <div class='buttonset alignRight'></div><!-- save button added here w/ JS --> + +</form> +</div> + + + + + + +<!-- +this is opened in a dialog and appended to the parent fieldset so that cryptToolMakeKeyExec is within context of the parent form. +That's also why the template does not contain a form +--> +<div id="sslMakeKeyTemplate" data-app-role="sslMakeKeyContainer"> +<p class="hint">If you have an existing key set, this action will save over it.</p> +<label> + <span>Length</span> + <select name="length"> + <option value="1024">1024</option> + <option value="2048" selected="selected">2048</option> + <option value="4096">4096</option> + </select> +</label> +<button class="applyButton" data-text="true" data-icon-primary="ui-icon-key" data-app-click="admin_sites|cryptoToolMakeKeyExec">Make Key</button> +</div> + + + + +<div id="domainUpdateTemplate"> + + <form action="#" onsubmit="return false" class="labelsAsBreaks alignedLabels" data-cb_tf="true"> + <input name="_macrobuilder" value="admin_sites|adminDomainMacroGeneral" type="hidden"> + <input name="_tag/callback" value="showMessaging" type="hidden"> + <input name="_tag/restoreInputsFromTrackingState" value="1" type="hidden"> + <input name="_tag/removeFromDOMItemsTaggedForDelete" value="1" type="hidden"> + <input name="_tag/message" value="The domain has been successfully updated." type="hidden"> + <input data-tlc="bind $var '.DOMAINNAME'; apply --select=$var; apply --append;" name="DOMAINNAME" type="hidden"> + + <input data-tlc="bind $var '.LOGO'; apply --select=$var; apply --append;" name="LOGO" value="" type="hidden"> + + <div class="domainDetailLogoContainer"> + + <fieldset class="marginBottom labelsAsBreaks"> + + <div class="pointer marginBottom"><div class="logoWhiteness"><img data-tlc="admin#companylogo --useParentData='1' --legacy ; apply --append;" src="blank.gif" class="prodThumb" data-bind="useParentData:1; format:companyLogo; extension:admin;" onclick="mediaLibrary($(this),$(this).closest('form').find('input[name=\'LOGO\']').first(),'');" height="50" width="150"></div></div> + + <label> + <input data-tlc="bind $var '.IS_PRIMARY'; apply --select=$var; apply --append;" class="applyAnycb" name="IS_PRIMARY" type="checkbox"> + <span>Tag as primary</span> + <span class="toolTip" title="Only 1 primary domain per partition.">?</span> + </label> + + <label> + <input data-tlc="bind $var '.IS_FAVORITE'; apply --select=$var; apply --append;" class="applyAnycb" name="IS_FAVORITE" type="checkbox"> + <span>Tag as favorite</span> + <span class="toolTip" title="Will show domain at the top of some lists and enable it in the domain chooser.">?</span> + </label> + + <label> + <input data-tlc="bind $var '.IS_SYNDICATION'; apply --select=$var; apply --append;" class="applyAnycb" name="IS_SYNDICATION" type="checkbox"> + <span>Syndication</span> + </label> + + <label> + <span>Partition</span> + <select data-tlc="bind $var '.@PRTS'; controller#optionsfromlist --legacy --value='id' --text='id'; apply --append;" name="PRT"></select> + </label> + + </fieldset> + + </div> + + + + + + <div data-app-role="tabContainer" class="applyAnytabs domainDetailTabsContainer"> + <button data-app-role="saveButton" data-app-click="admin|submitForm" class="floatRight applyButton">Save <span class="numChanges"></span> Changes</button> + <ul> + <li><a href="#domainHosts">Hosts</a></li> + <li><a href="#domainEmail">Email</a></li> + <li><a href="#domainEvents">Events</a></li> + <li><a data-tlc="bind $var '.DOMAINNAME'; apply --attrib='data-domainname'; apply --append;" href="#domainDiagnostics" data-app-click="admin_sites|adminDomainDiagnosticsShow">Diagnostics </a></li> +<!-- <li><a href='#domainRewriteRules'>Rewrite Rules</a></li> --> + </ul> + + + <section data-anytab-content="domainHosts" class="clearfix"> + + <div class="buttonset alignRight marginBottom"> + <button class="applyButton" data-app-click="admin_sites|adminDomainCreateUpdateHostShow" data-mode="create" data-icon-primary="ui-icon-circle-plus" data-text="true">Add New Host</button> + </div> + <table class="gridTable fullWidth applyAnytable"> + <thead> + <tr> + <th>Host</th> + <th>Type</th> + <th>Project</th> + <th data-anytable-nosort="true"></th> + </tr> + </thead> + <tbody data-tlc="bind $var '.@HOSTS'; controller#loop --templateid='domainListHostsRowTemplate'; apply --append;" data-app-role="domainsHostsTbody"></tbody> + </table> + </section> + + <section data-anytab-content="domainEmail" class="clearfix"> + + <fieldset data-app-role="emailConfigContainer"> + + <label> + <span>Configuration</span> + <select data-tlc="bind $var '.%EMAIL.TYPE'; apply --select=$var; apply --append;" name="TYPE" data-input-change="panel-selector" data-panel-selector=".domainEmailConfiguration"> + <option value="">None</option> + <option value="MX" data-show-panel="domainEmailConfigurationMX">MX</option> + <option value="GOOGLE">Google</option> + <option value="FUSEMAIL">Fusemail</option> + </select> + </label> + + <div data-panel-id="domainEmailConfigurationMX" class="displayNone domainEmailConfiguration"> + + <label> + <span>MX1</span> + <input data-tlc="bind $var '.%EMAIL.MX1'; apply --select=$var; apply --append;" name="MX1" value="" size="25" type="text"> + </label> + <label> + <span>MX2</span> + <input data-tlc="bind $var '.%EMAIL.MX2'; apply --select=$var; apply --append;" name="MX2" value="" size="25" type="text"> + </label> + </div> + </fieldset> + </section> + + + + <section data-anytab-content="domainDiagnostics" class="clearfix"> + <table class="applyAnytable gridTable fullWidth"> + <thead> + <tr> + <td>Type</td> + <td>Message</td> + <td></td> + </tr> + </thead> + <tbody data-tlc="bind $var '.@MSGS'; controller#loop --templateid='domainManagerDiagnosticsRowTemplate'; apply --append;" data-app-role="domainDiagnosticsTbody"> + </tbody> + </table> + </section> + + + + <section data-anytab-content="domainEvents" class="clearfix displayNone"> + + <table class="applyAnytable gridTable fullWidth"> + <thead> + <tr> + <td>ID</td> + <td>Event</td> + <td>Class</td> + <td>Time/Date</td> + </tr> + </thead> + <tbody data-tlc="bind $var '.@HISTORY'; controller#loop --templateid='domainManagerHistoryRowTemplate'; apply --append;"> + </tbody> + </table> + + </section> + + </div> + </form> + +</div> + + + + + + + + + + + + + +<!-- +////////////////////////// PROJECTS \\\\\\\\\\\\\\\\\\\\\\\\\ +--> + + + + + + +<table> +<tbody id="projectsListTemplate" data-element='project'> +<tr> + <td data-tlc="bind $var '.TITLE'; apply --append;" class="isSearchable"></td> + <td data-tlc="bind $var '.TYPE'; apply --append;" class="isSearchable"></td> + <td class="alignRight"> + <span data-tlc="admin_sites#projectbuttons --useParentData='true' --legacy ; apply --append;" data-bind="useParentData:true; format:projectButtons; extension:admin_sites;"></span> + <button class="applyButton" data-app-click="admin_sites|projectDetailShow" data-icon-primary="ui-icon-info" data-text="false">View Details</button> + </td> +</tr> + + +<tr class="displayNone"> + <td colspan="3"> + <div class="marginLeft"> + <div data-tlc="bind $var '.ID'; format --prepend='ID: '; apply --append;"></div> + <div data-tlc="bind $var '.UUID'; format --prepend='Project ID: '; apply --append;"></div> + <div data-tlc="bind $var '.TYPE'; format --prepend='Type: '; apply --append;"></div> + <div data-tlc="bind $var '.CREATED_TS'; format --prepend='Created: '; apply --append;"></div> + <div data-tlc="bind $var '.UPDATED_TS'; format --prepend='Last update: '; apply --append;"></div> + <div data-tlc="bind $var '.APP_VERSION'; format --prepend='App version: '; apply --append;"></div> + <div data-tlc="bind $var '.APP_RELEASE'; format --prepend='App release: '; apply --append;"></div> + <div data-tlc="bind $var '.APP_ROOT'; format --prepend='App root: '; apply --append;"></div> + <div data-tlc="bind $var '.GITHUB_REPO'; format --prepend='GitHub repository: '; apply --append;"></div> + <div data-tlc="bind $var '.GITHUB_BRANCH'; format --prepend='GitHub branch: '; apply --append;"></div> + <div data-tlc="bind $var '.APP_EXPIRE'; format --prepend='Expiration: '; apply --append;"></div> + <div data-tlc="bind $var '.UPDATED_TS'; format --prepend='Last update: '; apply --append;"></div> + </div> + </td> +</tr> +</tbody> +</table> + + + + +<div id="projectCreateTemplate"> + +<form onsubmit="return false" novalidate> +<fieldset class="labelsAsBreaks alignedLabels alignedInputs"> + <label> + <span>Project title</span> + <input name="title" required type="text"> + <span class="toolTip" title="ex: domain.com master">?</span> + </label> + + + <label> + <span>Project type</span> + <select name="type"> + <option value="APP">Shopping App (index.html)</option> +<!-- <option value="VSTORE">Legacy vStore Project (beta)</option> --> + <option value="ADMIN">Hosted Admin App (beta)</option> + <option value="CHECKOUT">Checkout Intercept (beta)</option> + <option value="DSS">Decision Support System (beta)</option> + </select> + </label> + + <label> + <span>Project ID</span> + <input name="UUID" maxlength="40" data-minlength='10' type="text" required='required' data-input-keyup="format" data-input-format='pid, uppercase'> + <span class='toolTip' title="An alpha-numeric (plus dashes and underscores) project id with a minimum of ten characters. Should be informative as this is used for troubleshooting (maybe the domain and/or name of the git repo). The id should be unique.">?</span> + </label> + + <label> + <span>GitHub repo</span> + <input name="repo" maxlength="128" required type="url"> + </label> + <p class="hint">ex: https://github.com/yourname/project.git OR ssh://github.com/yourname/project.git<br> + You can find this link on the right side of the repo in a box that says 'https clone url'.</p> + + + + <label> + <span>GitHub branch</span> + <input name="branch" maxlength="20" type="text"> + </label> + +<!-- <label><input type="checkbox" name="domain"> Reserve a test domain for this project.</label> --> + <div class="buttonset"> + <button class="applyButton" data-app-click="admin_sites|projectCreateExec">Save</button> + </div> +</fieldset> +</form> + +</div> + + + +<!-- HOST CHOOSER --> + +<div id='hostChooserDomainListTemplate' data-tlc="bind $domains '.@DOMAINS'; controller#loop --templateid='hostChooserDomainTemplate'; apply --append;" class='hostChooser'></div> +<div id='hostChooserDomainTemplate'> + <h5 data-tlc="bind $domain '.DOMAINNAME'; apply --append;"></h5> + <ul data-tlc="bind $hosts '.@HOSTS'; controller#loop --templateid='hostChooserHostTemplate'; apply --append;" class='hostChooserHostList'></ul> +</div> + +<ul> + <li id='hostChooserHostTemplate' class='hostChooserHostListItem' data-tlc="bind $hostname '.HOSTNAME'; apply --append; bind $chkout '.CHKOUT'; if(is $chkout --notblank;) {{format --prepend=' - '; apply --append; }}; "></li> +</ul> + diff --git a/extensions/admin/sites.js b/extensions/admin/sites.js new file mode 100644 index 000000000..cece5af9f --- /dev/null +++ b/extensions/admin/sites.js @@ -0,0 +1,947 @@ +/* ************************************************************** + + Copyright 2013 Zoovy, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +************************************************************** */ + + + +var admin_sites = function(_app) { + + var theseTemplates = new Array( + "domainListTemplate", + "domainListHostsRowTemplate", + "sitesDomainRowTemplate" +/* +used, but not pre-loaded. + "domainAndAppConfigTemplate" + +*/ + ); + + var r = { + + +//////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + + + callbacks : { + //executed when extension is loaded. should include any validation that needs to occur. + init : { + onSuccess : function() { + var r = false; //return false if extension won't load for some reason (account config, dependencies, etc). + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/sites.html',theseTemplates); + _app.rq.push(['css',0,_app.vars.baseURL+'extensions/admin/sites.css','sites_styles']); + //if there is any functionality required for this extension to load, put it here. such as a check for async google, the FB object, etc. return false if dependencies are not present. don't check for other extensions. + r = true; + + return r; + }, + onError : function() { + //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. + //you may or may not need it. + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + } + } + }, //callbacks + + + +//////////////////////////////////// ACTION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + a : { + + +//The sites interface should always be opened in the sites tab. + showSitesTab : function() { + var $target = $("#sitesContent").intervaledEmpty().showLoading({'message':'Fetching List of Domains'}).anyform(); + _app.u.addEventDelegation($target); + if(_app.ext.admin.vars.tab != 'sites') { + _app.ext.admin.u.bringTabIntoFocus('sites'); + _app.ext.admin.u.bringTabContentIntoFocus($target); + } + +//if domains are not already in memory, get a new partition list too. that way the callback isn't executed before the domains are available. + _app.model.addDispatchToQ({ + '_cmd':'adminDomainList', + 'hosts' : 1, + '_tag': { + 'datapointer' : 'adminDomainList', + 'callback':function(rd) { + if(_app.model.responseHasErrors(rd)){ + $('#globalMessaging').anymessage({'message':rd}); + } + else { + $target.hideLoading(); + var domains = _app.data[rd.datapointer]['@DOMAINS']; + _app.data[rd.datapointer]['*favorites'] = new Array(); + var L = domains.length; + for(var i = 0; i < L; i += 1) { + if(domains[i].IS_FAVORITE == 1) { + _app.data[rd.datapointer]['*favorites'].push(domains[i]); + } + } + $target.tlc({'templateid':'pageTemplateSites','datapointer':rd.datapointer}); + _app.u.handleButtons($target); + } + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); + + + }, + +/* + showDomainConfig : function($target) { + $target.anycontent({'templateID':'domainAndAppConfigTemplate','showLoading':false}).anyform(); + _app.u.addEventDelegation($target); + _app.ext.admin_sites.u.fetchSiteTabData($target,'mutable'); + _app.u.handleButtons($target); + _app.model.dispatchThis('mutable'); + }, +*/ + showDomainConfig : function($target) { + $target.showLoading(); + _app.u.addEventDelegation($target); + + _app.model.addDispatchToQ({'_cmd':'adminDomainList','hosts' : true,'_tag': {'datapointer' : 'adminDomainList'}},'mutable'); + _app.model.addDispatchToQ({'_cmd':'adminProjectList','_tag': {'datapointer' : 'adminProjectList','callback':function(){ + $target.hideLoading().tlc({ + 'templateid' : 'domainAndAppConfigTemplate', + dataset : $.extend({},_app.data.adminDomainList,_app.data.adminProjectList) + }); + _app.u.handleButtons($target); + if(_app.vars.domain) { + $("[data-app-role='domainListNonFavorites']",$target).find("tbody[data-domainname='"+_app.vars.domain+"']").find("button[data-app-click='admin_sites|domainPutInFocus']").addClass('ui-state-focus'); + } + }}},'mutable'); + _app.model.dispatchThis('mutable'); + } + + }, //Actions + + + +//////////////////////////////////// RENDERFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +//renderFormats are what is used to actually output data. +//on a data-bind, format: is equal to a renderformat. extension: tells the rendering engine where to look for the renderFormat. +//that way, two render formats named the same (but in different extensions) don't overwrite each other. + renderFormats : { + projectidpretty : function($tag,data) { +// dump(" BEGIN projectidpretty"); + var o = data.value; //what will be Output into $tag. Defaults to project id (which is what should be in data.value + if(o) { + if(_app.data.adminProjectList && _app.data.adminProjectList['@PROJECTS']) { + dump(" projects ARE in memory"); + var index = _app.ext.admin.u.getIndexInArrayByObjValue(_app.data.adminProjectList['@PROJECTS'],'UUID',data.value); + // dump(" -> index: "+index); + if(index === 0 || index >= 1) { + if(_app.data.adminProjectList['@PROJECTS'][index].TITLE) { + o = _app.data.adminProjectList['@PROJECTS'][index].TITLE; + } + } + } + $tag.text(o); + } + }, + projectbuttons : function($tag,data) { + var $menu = $("<menu \/>").addClass('projectMenu').hide(); + $tag.css('position','relative'); //so menu appears where it should. + if(data.value.GITHUB_REPO) { + $menu.append("<li><a href='#' data-app-click='admin|linkOffSite' data-url='"+data.value.GITHUB_REPO+"'>Visit GitHub Repository<\/a><\/li>"); + $menu.append("<li><a href='#' data-app-click='admin_batchjob|adminBatchJobExec' data-whitelist='project' data-type='UTILITY/GITPULL'>Pull from GitHub</a></li>"); + } + if(data.value.LINK) { + $menu.append("<li><a href='#' data-app-click='admin|linkOffSite' data-url='"+data.value.LINK+"'>Visit GitHub Repository<\/a><\/li>"); +// -> Can't do a pull here because the 'pull' goes to a dir that is host/domain specific. it isn't 'stored' till it's tied to a host/domain. A pull is specific to that host/domain. + } + $menu.append("<li><a href='#' data-app-click='admin_sites|projectRemove'>Remove this Project<\/a><\/li>"); + + $menu.menu(); + $tag.append($menu); + $menu.css({'position':'absolute','width':200,'z-index':200,'top':25,'right':0}); + var $button = $("<button>").text("App Related Utilities").button({icons: {primary: "ui-icon-wrench",secondary: "ui-icon-triangle-1-s"},text: false}); + $button.on('click',function(){ + $menu.closest('table').find('menu.projectMenu').hide(); //close any open menus. + $menu.show(); + $( document ).one( "click", function() { + $menu.hide(); + }); + return false; + }) + $tag.append($button); + }, + + //pass in HOSTTYPE as data. + apphostbuttons : function($tag,data) { + var $menu = $("<menu \/>").addClass('appHostMenu').hide(); + $tag.css('position','relative'); //so menu appears where it should. + + if(data.value.HOSTTYPE == 'APPTIMIZER' || data.value.HOSTTYPE == 'VSTORE-APP') { + $menu.append("<li><a href='#' data-app-click='admin_sites|adminSEOInitExec'>Get SEO Token</a></li>"); + + if(data.value.PROJECT && data.value.PROJECT.indexOf(data.value.HOSTNAME.toLowerCase()) >= 0) { +// * 201401 -> currently, 'choose template' is in the host editor if host type == aptimizer and 'template' is selected. +// $menu.append("<li><a href='#' data-app-click='admin_template|templateChooserShow' data-mode='Site'>Choose a Template</a></li>"); + $menu.append("<li><a href='#' data-app-click='admin_template|templateEditorShow' data-mode='Site'>Edit Project</a></li>"); + $menu.append("<li data-app-click='admin_template|containerFileUploadShow' data-mode='Site'><a href='#'>Upload Template Files</a></li>"); + } + else { + $menu.append("<li><a href='#' data-app-click='admin_batchjob|adminBatchJobExec' data-whitelist='PROJECT' data-type='UTILITY/GITPULL'>Pull from GitHub</a></li>"); + $menu.append("<li><a href='#' data-app-click='admin_batchjob|adminBatchJobExec' data-type='EXPORT/PAGES' >Export Pages.json</a></li>"); + $menu.append("<li><a href='#' data-app-click='admin_batchjob|adminBatchJobExec' data-type='EXPORT/APPRESOURCE' >Export App Resource Zip</a></li>"); + } + } + if($menu.children().length) { + $menu.menu(); + $tag.append($menu); //so menu appears where it should. + $menu.css({'position':'absolute','width':200,'z-index':200,'top':25,'right':0}); + var $button = $("<button>").text("App Related Utilities").button({icons: {primary: "ui-icon-wrench",secondary: "ui-icon-triangle-1-s"},text: false}); + $button.on('click',function(){ + $menu.closest('table').find('menu.appHostMenu').hide(); //close any open menus. + $menu.show(); + $( document ).one( "click", function() { + $menu.hide(); + }); + return false; + }) + $tag.append($button); + } + else { + //host/domain isn't app based. + } + } + + }, //renderFormats + + + macrobuilders : { + + + //executed from within the 'create new domain' interface. + adminDomainMacroCreate : function(sfo,$form) { + sfo = sfo || {}; +//a new object, which is sanitized and returned. + var newSfo = { + '_cmd':'adminDomainMacro', + '_tag':sfo._tag, + '@updates':[] + }; + if(sfo.domaintype == 'DOMAIN-CREATE') { + newSfo.DOMAINNAME = sfo.DOMAINNAME; + newSfo['@updates'].push("DOMAIN-CREATE"); + newSfo['@updates'].push("HOST-ADD?HOSTNAME=www&HOSTTYPE=APPTIMIZER"); + } + else if(sfo.domaintype == 'DOMAIN-RESERVE') { + newSfo['@updates'].push("DOMAIN-RESERVE"); + newSfo['@updates'].push("HOST-ADD?HOSTNAME=www&HOSTTYPE=APPTIMIZER"); + } + else { + newSfo = false; + } + return newSfo; + }, + + + //executed when save is pressed within the general panel of editing a domain. + adminDomainMacroGeneral : function(sfo,$form) { + sfo = sfo || {}; +//a new object, which is sanitized and returned. + var newSfo = { + '_cmd':'adminDomainMacro', + 'DOMAINNAME':sfo.DOMAINNAME, + '_tag':sfo._tag, + '@updates': new Array() + }; + + newSfo['@updates'].push("DOMAIN-SET-PRIMARY?IS="+sfo.IS_PRIMARY); + newSfo['@updates'].push("DOMAIN-SET-SYNDICATION?IS="+sfo.IS_SYNDICATION); + + if($("[data-app-role='emailConfigContainer'] .edited",$form).length) { + newSfo['@updates'].push("EMAIL-SET?"+$.param(_app.u.getWhitelistedObject($("[data-app-role='emailConfigContainer']").serializeJSON(),['MX1','MX2','TYPE']))); + } + + + if($("input[name='LOGO']",$form).hasClass('edited')) { + newSfo['@updates'].push("DOMAIN-SET-LOGO?LOGO="+sfo.LOGO || ""); //set to value of LOGO. if not set, set to blank (so logo can be cleared). + } + + if($("input[name='IS_FAVORITE']",$form).hasClass('edited')) { + newSfo['@updates'].push("DOMAIN-SET-FAVORITE?IS="+sfo.IS_FAVORITE); + } + + if($("select[name='PRT']",$form).hasClass('edited')) { + newSfo['@updates'].push("DOMAIN-SET-PRT?PRT="+sfo.PRT); + } + + $("[data-app-role='domainsHostsTbody'] tr",$form).each(function(){ + if($(this).hasClass('rowTaggedForRemove')) { + newSfo['@updates'].push("HOST-KILL?HOSTNAME="+$(this).data('hostname')); + } + else {} //do nothing. new hosts are added in modal. + }); +// _app.u.dump(" -> new sfo for domain macro general: "); _app.u.dump(newSfo); + return newSfo; + } + + }, + + +//////////////////////////////////// UTIL [u] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +//utilities are typically functions that are exected by an event or action. +//any functions that are recycled should be here. + u : { + + hostChooser : function(opts) { + opts = opts || {}; + var $D = _app.ext.admin.i.dialogCreate({ + title : "Choose Host(s)", + anycontent : false, //the dialogCreate params are passed into anycontent + handleAppEvents : false //defaults to true + }); + $D.dialog('open'); + $D.showLoading({'message':'Fetching updated list of domains and hosts.'}); + _app.model.addDispatchToQ({ + '_cmd':'adminDomainList', + 'hosts' : true, + '_tag': { + 'datapointer' : 'adminDomainList', + 'callback':function(rd) { + $D.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + var dataset, templateid; + if(opts.filter) { + dataset = _app.ext.admin.u.getValueByKeyFromArray(_app.data[rd.datapointer]['@DOMAINS'],opts.filter.by,opts.filter.for); + templateid = 'hostChooserDomainTemplate'; + } + else { + dataset = _app.data[rd.datapointer]; + templateid = 'hostChooserDomainListTemplate'; + } + + $D.tlc({'templateid':templateid,'dataset':dataset}); + if(typeof opts.beforeSelectable === 'function') { + opts.before($D); + } + + $D.selectable({'filter' : 'li'}); + + if(typeof opts.afterSelectable === 'function') { + opts.before($D); + } + + if(typeof opts.saveAction === 'function') { + $("<button>").text('Save Hosts').button().on('click',function(){ + opts.saveAction($D); + }).appendTo($D); + } + } + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); + + + }, + +//mode is required and can be create or update. +//form is pretty self-explanatory. +//$domainEditor is the PARENT context of the original button clicked to open the host editor. ex: the anypanel. technically, this isn't required but will provide a better UX. + domainAddUpdateHost : function(mode,$form,$domainEditor) { + if(mode == 'create' || mode == 'update' && $form instanceof jQuery) { + + var sfo = $form.serializeJSON({'cb':true}); + $form.showLoading({"message":"Updating host..."}); + var cmdObj = { + _cmd : 'adminDomainMacro', + _tag : { + jqObj : $form, + message : 'Your changes have been saved', + callback : 'showMessaging', + persistent : true + }, + 'DOMAINNAME' : sfo.DOMAINNAME, + '@updates' : new Array() + } + + if(mode == 'create') { + cmdObj['@updates'].push("HOST-ADD?HOSTNAME="+encodeURIComponent(sfo.HOSTNAME)); + } + + var hostSet = "HOST-SET?"+$.param(_app.u.getWhitelistedObject(sfo,['HOSTNAME','HOSTTYPE'])); + +//The key and the CRT should only get updated if they've changed. + if($("textarea[name='KEY']",$form).hasClass('edited')) { + cmdObj['@updates'].push("HOST-SSL-UPDATE-KEY?HOSTNAME="+encodeURIComponent(sfo.HOSTNAME)+"&KEY="+encodeURIComponent(sfo.KEY)); + } + if($("textarea[name='CRT']",$form).hasClass('edited')) { + cmdObj['@updates'].push("HOST-SSL-UPDATE-CRT?HOSTNAME="+encodeURIComponent(sfo.HOSTNAME)+"&CRT="+encodeURIComponent(sfo.CRT)); + } + + if(sfo.HOSTTYPE == 'VSTORE' || sfo.HOSTTYPE == 'VSTORE-APP') { + $("[data-app-role='domainRewriteRulesTbody'] tr",$form).each(function(){ + var $tr = $(this); + if($tr.hasClass('rowTaggedForRemove')) { + cmdObj['@updates'].push("VSTORE-KILL-REWRITE?PATH="+encodeURIComponent($tr.data('path'))); + } + else if($tr.hasClass('isNewRow')) { + cmdObj['@updates'].push("VSTORE-ADD-REWRITE?PATH="+encodeURIComponent($tr.data('path'))+"&TARGETURL="+encodeURIComponent($tr.data('targeturl'))); + } + else {} //unchanged row. this is a non-destructive process, so existing rules don't need to be re-added. + }) + } + else if(sfo.HOSTTYPE == 'APPTIMIZER') { + hostSet += "&force_https="+encodeURIComponent(sfo.force_https); + if(sfo.project_source == 'template') { + hostSet += "&PROJECT="+encodeURIComponent(sfo.HOSTNAME.toLowerCase()+"."+sfo.DOMAINNAME); + _app.model.addDispatchToQ({ + "_cmd":"adminSiteTemplateInstall", + "SUBDIR" : sfo.TEMPLATE, + "PROJECTID" : "$SYSTEM", + "HOSTDOMAIN":sfo.HOSTNAME.toLowerCase()+"."+sfo.DOMAINNAME + },"immutable"); + } + else if(sfo.project_source == 'project') { + hostSet += "&PROJECT="+encodeURIComponent(sfo.PROJECT); + } + else { + + } + } + else if(sfo.HOSTTYPE == 'REDIR') { + hostSet += "&URI="+encodeURIComponent(sfo.URI)+"&REDIR="+encodeURIComponent(sfo.REDIR); + } + else if(sfo.HOSTTYPE == 'CUSTOM') { + //supported. no extra params needed. + } + else { + hostSet = false; + } //catch. some unsupported type. + + if(hostSet) { + cmdObj['@updates'].push(hostSet); + } + else { + $form.anymessage({'message':'The host type was not a recognized type. We are attempting to save the rest of your changes.'}); + } + + + _app.model.addDispatchToQ(cmdObj,'immutable'); //this handles the update cmd. +//This will update the hosts tbody. + if($domainEditor instanceof jQuery) { + $domainEditor.empty().showLoading({'message':'Updating '+sfo.HOSTNAME+'.'+sfo.DOMAINNAME+' and refreshing content...'}); + if($domainEditor.data('isTLC')) { + $domainEditor.tlc('destroy'); //ensures fresh data is used. + } + _app.model.addDispatchToQ({ + '_cmd':'adminDomainDetail', + 'DOMAINNAME':sfo.DOMAINNAME, + '_tag': { + 'datapointer' : 'adminDomainDetail|'+sfo.DOMAINNAME, + 'templateid' : 'domainUpdateTemplate', + 'jqObj' : $domainEditor, + 'callback' : 'tlc' + } + },'immutable'); + } + + _app.model.dispatchThis('immutable'); + + } + else if($form instanceof jQuery) { + $form.anymessage({"message":"In admin_sites.u.domainAddUpdateHost, mode ["+mode+"] was invalid. must be create or update.","gMessage":true}); + } + else { + $('#globalMessaging').anymessage({"message":"In admin_sites.u.domainAddUpdateHost, $form was not passed or is not a valid jquery instance.","gMessage":true}); + } + }, //domainAddUpdateHost + + fetchSiteTabData : function($target,Q) { + _app.model.addDispatchToQ({ + '_cmd':'adminDomainList', + 'hosts' : true, + '_tag': { + 'datapointer' : 'adminDomainList', + 'callback':'tlc', + 'jqObj' : $("[data-app-role='domainsAndHostsContainer']:first",$target) + } + },Q); + _app.model.addDispatchToQ({ + '_cmd':'adminProjectList', + '_tag': { + 'datapointer' : 'adminProjectList', + 'callback':'tlc', + 'jqObj' : $("[data-app-role='projectsContainer']:first",$target) + } + },Q); + } + }, //u [utilities] + + + e : { + + adminSEOInitExec : function($ele,P) { + var host = $ele.closest('tr').data('hostname'), domain = $ele.closest("[data-domain]").data('domain'); + if(host && domain) { + var $D = _app.ext.admin.i.dialogCreate({ + 'title':'Get SEO Token', + 'showLoading':false //will get passed into anycontent and disable showLoading. + }); + + $D.dialog('open').showLoading({"message":"Fetching SEO token"}); + _app.model.addDispatchToQ({"_cmd":"adminSEOInit","hostdomain":host+"."+domain,"_tag":{"datapointer":"adminSEOInit","callback":function(rd){ + $D.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + //sample action. success would go here. + $D.append("Your token is: "+_app.data[rd.datapointer].token); + } + }}},"mutable"); + _app.model.dispatchThis("mutable"); + } + else { + $("#globalMessaging").anymessage({"message":"In admin_sites.e.adminSEOInitExec, unable to determine either the host ["+host+"] and/or the domain ["+domain+"].","gMessage":true}); + } + }, + + adminDomainCreateExec : function($ele,p) { + + var $form = $ele.closest('form'); + if(_app.u.validateForm($form)) { + $form.showLoading({'message' : 'Adding Domain'}); + var sfo = $form.serializeJSON(); + sfo['@updates'] = new Array(); + + if(sfo.domaintype == 'DOMAIN-CREATE') { + sfo.DOMAINNAME = sfo.DOMAINNAME; + sfo['@updates'].push("DOMAIN-CREATE"); + sfo['@updates'].push("HOST-ADD?HOSTNAME=www&HOSTTYPE=APPTIMIZER"); + } + else if(sfo.domaintype == 'DOMAIN-RESERVE') { + sfo['@updates'].push("DOMAIN-RESERVE"); + sfo['@updates'].push("HOST-ADD?HOSTNAME=www&HOSTTYPE=APPTIMIZER"); + } + else { + + } + + if(sfo['@updates'].length) { + sfo._cmd = 'adminDomainMacro'; + sfo._tag = { + callback : function(rd) { + $form.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $form.anymessage({'message':rd}); + } + else { + //sample action. success would go here. + $('#globalMessaging').anymessage(_app.u.successMsgObject('Your domain has been added.')); + navigateTo("#!ext/admin_sites/showDomainConfig"); + $form.closest('.ui-dialog-content').dialog('close'); + } + } + } + _app.model.addDispatchToQ(sfo,"immutable"); + _app.model.dispatchThis("immutable"); + } + else { + $('#globalMessaging').anymessage({'message':'In adminDomainCreateExec, unrecognized domain type set in form.','gMessage':true}); + } + } + else {} //validateForm will handle error display. + + }, + + adminDomainCreateShow : function($ele,p) { + var $D = _app.ext.admin.i.dialogCreate({ + 'title':'Add New Domain', + 'templateID':'domainCreateTemplate', + 'showLoading':false //will get passed into anycontent and disable showLoading. + }); + _app.u.handleButtons($D); + _app.u.addEventDelegation($D); + $D.dialog('option','width',($(document.body).width() > 500 ? 500 : '90%')); + $D.dialog('open'); + $D.anyform(); + }, //adminDomainCreateShow + + + adminDomainRemoveConfirm : function($ele,p) { + p.preventDefault(); + var domain = $ele.closest("[data-element='domain']").data('domainname'); + if(domain) { + var $D = _app.ext.admin.i.dialogConfirmRemove({ + "message" : "Are you sure you wish to remove the domain "+domain+"? There is no undo for this action.", + "removeButtonText" : "Remove Domain", //will default if blank + "title" : "Remove Domain: "+domain, //will default if blank + "removeFunction" : function(p,$D){ + $D.parent().showLoading({"message":"Removing domain "+domain+"..."}); + _app.model.addDispatchToQ({ + '_cmd':'adminDomainMacro', + 'DOMAINNAME' : domain, + '@updates' : ["DOMAIN-REMOVE"], + '_tag': { + 'callback':function(rd){ + $D.parent().hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + $D.dialog('close'); + $('#globalMessaging').anymessage(_app.u.successMsgObject('The domain '+domain+' has been removed')); + $ele.closest('tbody').hide().intervaledEmpty(); + } + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); + } + }); + } + else { + $("#globalMessaging").anymessage({"message":"In admin_sites.e.adminDomainRemoveConfirm, unable to ascertain domain.","gMessage":true}); + } + + return false; + }, //adminDomainCreateShow + +//if(domain == _app.vars.domain) {$ele.addClass('ui-state-highlight')} + domainPutInFocus : function($ele,p) { + var domain = $ele.closest("[data-domainname]").data('domainname'); + if(domain) { + _app.ext.admin.a.changeDomain(domain,$ele.closest("[data-prt]").attr('data-prt')); + navigateTo(document.location.hash); + } + else { + $("#globalMessaging").anymessage({"message":"In admin_sites.e.domainPutInFocus, unable to ascertain domain.","gMessage":true}); + } + }, //domainPutInFocus + +// if($ele.closest("[data-is_favorite]").data('is_favorite') == 1) {$ele.addClass('ui-state-highlight')} + adminDomainToggleFavoriteExec : function($ele,p) { + $ele.toggleClass('ui-state-highlight'); + var domainname = $ele.closest("[data-domainname]").data('domainname'); + _app.model.addDispatchToQ({ + '_tag':{ + 'callback' : 'showMessaging', + 'message' : domainname+' has been '+($ele.hasClass('ui-state-highlight') ? 'tagged as a favorite. It will now show at the top of some domain lists.' : 'removed from your favorites') + }, + '_cmd':'adminDomainMacro', + 'DOMAINNAME':domainname, + '@updates':["DOMAIN-SET-FAVORITE?IS="+($ele.hasClass('ui-state-highlight') ? 1 : 0)] + },'passive'); + _app.model.dispatchThis('passive'); + }, //adminDomainToggleFavoriteExec + + adminDomainDiagnosticsShow : function($ele,p) { + if($ele.data('domainname')) { + _app.u.dump(" -> tabcontent.length: "+$ele.closest("[data-app-role='tabContainer']").find("tbody[data-app-role='domainDiagnosticsTbody']:first").length); + $ele.closest("[data-app-role='tabContainer']").find("tbody[data-app-role='domainDiagnosticsTbody']:first").intervaledEmpty(); + _app.model.addDispatchToQ({ + '_cmd':'adminDomainDiagnostics', + 'DOMAINNAME':$ele.data('domainname'), + '_tag':{ + 'datapointer':'adminDomainDiagnostics|'+$ele.data('domainname'), + 'callback':'tlc', + 'jqObj':$ele.closest("[data-app-role='tabContainer']").find("[data-anytab-content='domainDiagnostics']:first").showLoading({'message':'Fetching domain diagnostics'}) + } + },'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $ele.closest("[data-app-role='tabContainer']").anymessage({"message":"in admin_sites.e.adminDomainDiagnosticsShow, data-domainname not set on element.","gMessage":true}); + } + }, //adminDomainDiagnosticsShow + + adminDomainDetailShow : function($ele,p) { + + var $detail = $ele.closest('tr').next('tr').find("[data-app-role='domainDetailContainer']:first"); + var wasVisible = $detail.is(':visible'); //used to track state prior to all detail panels being closed. + $("[data-app-role='domainDetailContainer']:visible",$ele.closest('table')).each(function(){$(this).slideUp('slow','',function(){ + $(this).intervaledEmpty().tlc('destroy'); + });}); //close any open rows. interface gets VERY crowded if more than one editor is open. + + if(wasVisible) {}//was open and has already been closed + else { + $detail.show(); + var domainname = $ele.closest("[data-domainname]").data('domainname'); + if(domainname) { + $detail.showLoading({'message':'Fetching domain detail'}); + $detail.attr({'data-domainname':domainname,'data-domain':domainname}); + $("[data-app-role='domainsHostsTbody']",$detail).attr({'data-domainname':domainname,'data-domain':domainname}).addClass('buttonset'); //here for templateEditor. + _app.model.addDispatchToQ({'_cmd':'adminConfigDetail','prts':1,'_tag':{'datapointer':'adminConfigDetail|prts'}},'mutable'); + _app.model.addDispatchToQ({ + '_cmd':'adminDomainDetail', + 'DOMAINNAME':domainname, + '_tag': { + 'datapointer' : 'adminDomainDetail|'+domainname, + 'templateID':'domainUpdateTemplate', + 'extendByDatapointers' : ['adminConfigDetail|prts'], + 'jqObj' : $detail, + 'callback' : 'tlc', + onComplete : function(rd) { + $('form',$detail).anyform({'trackEdits':true}); //enable form 'tracking' so save button counts number of changes + $("select[name='PRT']",$detail).val(_app.data[rd.datapointer].PRT); //select the partition + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); + } + else {} + } + }, //adminDomainDetailShow + + domainView : function($ele,p) { + var domainname = $ele.closest("[data-domainname]").data('domainname'); + if(domainname) { + if($ele.data('mode') == 'host') { + var hostname = $ele.closest("[data-hostname]").data('hostname'); + if(hostname) { + linkOffSite("http://"+hostname+"."+domainname+"/",'',true); + } + else { + $('#globalMessaging').anymessage({"message":"In admin.e.domainView, unable to determine host.","gMessage":true}); + } + } + else { + linkOffSite("http://www."+domainname+"/",'',true); + } + } + else { + $('#globalMessaging').anymessage({"message":"In admin.e.domainView, unable to determine domain.","gMessage":true}); + } + }, + + adminDomainCreateUpdateHostShow : function($ele,p) { + var domain = $ele.closest('[data-domain]').data('domain'); + + if(domain) { + var data = {'DOMAINNAME':domain} + var title = $ele.data('mode') + ' host'; + if($ele.data('mode') == 'update') { +// ### FUTURE -> this is gonna get more love soon. When it does, for adding a template to a host, would be nice to remember which template was selected. + $.extend(data,_app.data['adminDomainDetail|'+domain]['@HOSTS'][$ele.closest('tr').data('obj_index')]); + title += ': '+(data.HOSTNAME.toString().toLowerCase()) + } + title += ' for '+domain + var $D = _app.ext.admin.i.dialogCreate({ + 'title': title, + 'data' : data, //passes in DOMAINNAME and anything else that might be necessary for anycontent translation. + 'templateID':'domainAddUpdateHostTemplate', + 'appendTo' : $ele.closest("[data-app-role='domainDetailContainer']"), + 'showLoading':false //will get passed into anycontent and disable showLoading. + }); + +//get the list of projects and populate the select list. If the host has a project set, select it in the list. + var _tag = {'datapointer' : 'adminProjectList','callback':function(rd){ + if(_app.model.responseHasErrors(rd)){ + $("[data-panel-id='domainNewHostTypeSITEPTR']",$D).anymessage({'message':rd}); + } + else { + //success content goes here. + $("[data-panel-id='domainNewHostTypeSITEPTR']",$D).anycontent({'datapointer':rd.datapointer}); + if($ele.data('mode') == 'update') { + $("select[name='PROJECT']",$D).val(_app.data['adminDomainDetail|'+domain]['@HOSTS'][$ele.closest('tr').data('obj_index')].PROJECT) + } + _app.u.handleButtons($D); + _app.u.handleCommonPlugins($D); + } + }}; + + if(_app.model.fetchData(_tag.datapointer) == false) { + _app.model.addDispatchToQ({'_cmd':'adminProjectList','_tag': _tag},'mutable'); //necessary for projects list in app based hosttypes. + _app.model.dispatchThis(); + } + else { + _app.u.handleCallback(_tag); + } + + if(_app.model.fetchData('adminSiteTemplateList') == false) { + _app.model.addDispatchToQ({'_cmd':'adminSiteTemplateList','_tag':{ + 'datapointer' : 'adminSiteTemplateList', + 'callback' : 'anycontent', + 'jqObj' : $("[data-app-role='hostTemplateListContainer']",$D) + }},'mutable'); //necessary for projects list in app based hosttypes. + _app.model.dispatchThis(); + } + else { + $("[data-app-role='hostTemplateListContainer']",$D).anycontent({'datapointer' : 'adminSiteTemplateList'}); + } + + _app.model.addDispatchToQ({'_cmd':'adminProjectList','_tag': _tag},'mutable'); //necessary for projects list in app based hosttypes. + +//hostname isn't editable once set. + if($ele.data('mode') == 'update') { + $("input[name='HOSTNAME']",$D).attr('disabled','disabled'); + } + + $("form",$D).append( + $("<button>Save<\/button>").button().addClass('floatRight').on('click',function(event){ + event.preventDefault(); + _app.ext.admin_sites.u.domainAddUpdateHost($ele.data('mode'),$('form',$D),$ele.closest("[data-app-role='domainDetailContainer']")); + }) + ) + _app.u.addEventDelegation($D); + $D.anyform({'trackEdits':true}).dialog('open'); + } + else { + $ele.closest('.ui-widget-content').anymessage({'message':'In admin_sites.e.adminDomainCreateUpdateHostShow, unable to ascertain domain.','gMessage':true}); + } + }, //adminDomainCreateUpdateHostShow + +/////////////////// PROJECTS \\\\\\\\\\\\\\\\\\\\ + + projectDetailShow : function($ele,p) { + var $detailRow = $ele.closest('tr').next('tr'); + $detailRow.toggle(); + if($detailRow.is(':visible')) { + $detailRow.showLoading({'message':'Fetching project details'}); + var projectUUID = $ele.closest("[data-uuid]").attr('data-uuid'); + if(projectUUID) { + //files are not currently fetched. slows things down and not really necessary since we link to github. set files=true in dispatch to get files. + _app.model.addDispatchToQ({ + "_cmd":"adminProjectDetail", + "UUID":projectUUID, + "_tag": { + 'callback':'tlc', + jqObj:$detailRow, + 'datapointer' : 'adminProjectDetail|'+projectUUID + } + },'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $('#globalMessaging').anymessage({"message":"In admin_sites.e.projectDetailShow, unable to ascertain project UUID.","gMessage":true}); + } + + } + return false; + }, //projectUpdateShow + + projectCreateShow : function($ele,p) { + var $D = _app.ext.admin.i.dialogCreate({ + 'title' : 'Create a New Project', + 'templateID' : 'projectCreateTemplate', + showLoading : false + }); + $D.dialog('open'); + $D.anyform(); + _app.u.handleButtons($D); + return false; + }, //projectCreateShow + + projectCreateExec : function($ele,p) { + var + $form = $ele.closest('form'), + sfo = $form.serializeJSON(); + + if(_app.u.validateForm($form)) { + $form.showLoading({'message':'Adding your new project. This may take a few moments as the repository is imported.'}); + _app.model.destroy('adminProjectList'); +//UUID is now set by merchant. +// sfo.UUID = _app.u.guidGenerator(); + sfo._cmd = 'adminProjectCreate'; + sfo._tag = {"callback":function(rd){ + $form.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $form.anymessage({'message':rd}); + } + else { + $('#globalMessaging').anymessage(_app.u.successMsgObject('Thank you, your project has been created.')); + $ele.closest('.ui-dialog-content').dialog('close'); + navigateTo("#!ext/admin_sites/showDomainConfig"); + } + }} + _app.model.addDispatchToQ(sfo,"immutable"); + _app.model.dispatchThis('immutable'); + } + else {} //validateForm handles error display. + + }, //projectCreateExec + + projectRemove : function($ele,p) { + var $D = _app.ext.admin.i.dialogConfirmRemove({ + "message" : "Are you sure you wish to remove this app/project? There is no undo for this action.", + "removeButtonText" : "Remove Project", //will default if blank + "title" : "Remove Project", //will default if blank + "removeFunction" : function(p,$D){ + $D.parent().showLoading({"message":"Deleting "}); + _app.model.addDispatchToQ({ + '_cmd':'adminProjectRemove', + 'UUID' : $ele.closest("[data-uuid]").attr('data-uuid'), + '_tag': { + 'callback':function(rd){ + $D.parent().hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + $D.dialog('close'); + $('#globalMessaging').anymessage(_app.u.successMsgObject('Your project has been removed')); + $ele.closest('tr').hide().intervaledEmpty(); + } + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); + } + }); + return false; + }, //projectRemove + + cryptoToolMakeKeyShow : function($ele,P) { + P.preventDefault(); + var $D = _app.ext.admin.i.dialogCreate({ + title : "Generate an SSL key", + templateID : "sslMakeKeyTemplate", + appendTo : $ele.closest('fieldset'), + showLoading : false, + anycontent : true, //the dialogCreate params are passed into anycontent + handleAppEvents : false //defaults to true + }); + _app.u.handleButtons($D); + $D.dialog('open'); + + }, + + cryptoToolMakeKeyExec : function($ele,P) { + P.preventDefault(); + var $D = $ele.closest('.ui-dialog-content'); //used for context. + _app.model.addDispatchToQ({"_cmd":"cryptoTool","verb":"make-key","length" : $("select[name='length']",$D).val(),"_tag":{"datapointer":"cryptoTool|make-key","callback":function(rd){ + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + $ele.closest('fieldset').find("textarea[name='KEY']").val(_app.data[rd.datapointer].key).trigger('change'); + $D.dialog('close'); + //_app.model.destroy("cryptTool|make-key"); // ### TODO -> uncomment this after testing. + } + }}},"immutable"); + _app.model.dispatchThis("immutable"); + } + + } //e [app Events] + } //r object. + return r; + } \ No newline at end of file diff --git a/extensions/admin/support.html b/extensions/admin/support.html index 97a77cbe9..169cde117 100644 --- a/extensions/admin/support.html +++ b/extensions/admin/support.html @@ -1,20 +1,35 @@ -<div id='platformInfoTemplate'> +<div id='platformInfoTemplate' data-app-role='platformInfoContainer'> <table> <tr> <td> - <div class='marginRight marginBottom floatLeft' data-bind='var:releaseMeta(youtubeVideoID); format:youtubeVideo;'></div> + <div class='marginRight marginBottom floatLeft' data-bind='var:releaseMeta(youtubeVideoID); format:youtubevideo;' data-app-role='platformInfoVideoContainer'></div> <!-- platformInfo will automatically be appended to the bottom of this --> </td> <td> - <div data-app-role='platformInfoContainer'></div> - </td> + <div data-app-role='platformInfoDetailsContainer' ></div> + <table class='fullWidth gridTable'> + <thead> + <tr> + <th><h3>Video History</h3></th> + <th><h3>Change log</h3></th> + </tr> + </thead> + <tbody data-bind="useParentData:true; format:processList; loadsTemplate:platformVideoItemTemplate;"> + + </tbody> + </table> </tr> </table> </div> - +<table> +<tr id='platformVideoItemTemplate'> + <td data-app-click='admin_support|platformInfoWatchVideo' data-bind='var:history(branch); format:text;' class='lookLikeLink'></td> + <td data-app-click='admin_support|platformInfoViewChangelog' class='lookLikeLink'>Change log</td> +</tr> +</table> @@ -95,14 +110,14 @@ <fieldset class='displayNone ticketTopic marginBottom' data-panel-id='ticketTopicStorefront'> <legend>Storefront</legend> - <label><span>Domain: </span><input type='url' name='storefront_domain' data-validation-rules='skipIfHidden' required='required' /></label> + <label><span>Domain: </span><input type='url' name='storefront_domain' data-bind="var: ticket(domain); format:popVal;" data-validation-rules='skipIfHidden' required='required' /></label> <label><span>Steps to reproduce: </span><textarea name='storefront_steps2reproduce' data-validation-rules='skipIfHidden' required='required'></textarea></label> </fieldset> <fieldset class='displayNone ticketTopic marginBottom' data-panel-id='ticketTopicDNS'> <legend>Domain/DNS</legend> - <label><span>Domain: </span><input type='url' name='DNS_domain' data-validation-rules='skipIfHidden' required='required' /></label> + <label><span>Domain: </span><input type='url' name='DNS_domain' data-bind="var: ticket(domain); format:popVal;" data-validation-rules='skipIfHidden' required='required' /></label> </fieldset> <fieldset class='displayNone ticketPriority' data-panel-id='ticketPriorityHigh'> @@ -129,10 +144,11 @@ </fieldset> <button class='floatRight ui-state-highlight applyButton' data-app-click="admin_support|adminTicketCreateExec" data-text='true' data-icon-primary='ui-icon-circle-plus'>Create Ticket</button> -<button class='floatRight marginRight applyButton' data-text='true' data-icon-primary='ui-icon-arrowthickstop-1-n' data-app-click="admin_support|fileAttach2TicketShow">Attach Files</button> +<!--<button class='floatRight marginRight applyButton' data-text='true' data-icon-primary='ui-icon-arrowthickstop-1-n' data-app-click="admin_support|fileAttach2TicketShow">Attach Files</button>--> <button data-app-click="admin|dialogCloseExec" class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-close'>Cancel</button> <p class='hint'>Please include one issue per ticket. This allows us to route the ticket appropriately.</p> +<p class='hint'>Once the ticket is created, you'll be able to attach files.</p> <p class='hint'>Also, remember that the more details you provide, the more likely we are to be able to reproduce and resolve.</p> </form> @@ -161,29 +177,29 @@ <h5 class='noPadOrMargin'>Original Message:</h5> <table class='fullWidth gridTable marginBottom'> - <tbody data-bind="var: ticket(@FOLLOWUPS); format:processList; loadsTemplate:supportTicketFollowupTemplate;"></tbody> + <tbody data-bind="var: ticket(@FOLLOWUPS); format:processList; loadsTemplate:supportTicketFollowupTemplate;" data-app-role='ticketFollowupList'></tbody> </table> <div class='labelsAsBreaks alignedLabels alignedInputs'> - <button data-app-click="admin_support|fileAttach2TicketShow" class='marginBottom applyButton' data-text='true' data-icon-primary='ui-icon-arrowthickstop-1-n'>Add File(s) To Ticket</button><!-- intentionally outside the form. form is emptied on update --> - <table class='gridTable fullWidth marginBottom'> - <thead> - <tr> - <th>Filename</th> - <th>Added</th> - <th></th> - </tr> - </thead> - <tbody data-bind="var: ticket(@FILES); format:processList; loadsTemplate:supportTicketFilesRowTemplate;"></tbody> - </table> + <div data-app-role='supportFileUploadContainer' class='clearfix marginBottom'></div><!-- intentionally outside the form. form is emptied on update --> + <table class='gridTable fullWidth marginBottom applyAnytable'> + <thead> + <tr> + <th>Filename</th> + <th>Added</th> + <th></th> + </tr> + </thead> + <tbody data-bind="var: ticket(@FILES); format:processList; loadsTemplate:supportTicketFilesRowTemplate;" data-app-role='ticketAttatchmentList'></tbody> + </table> - <form class='marginTop'> - <fieldset> - <legend>Provide Additional Information:</legend> - <label><span>Message: </span><textarea name='note' required='required'></textarea></label> - </fieldset> - <button data-app-click='admin_support|adminTicketMacroUpdateExec' class='applyButton' data-icon-secondary='ui-icon-circle-arrow-e'>Add Message To Ticket</button> - </form> + <form class='marginTop'> + <fieldset> + <legend>Provide Additional Information:</legend> + <label><span>Message: </span><textarea name='note' required='required'></textarea></label> + </fieldset> + <button data-app-click='admin_support|adminTicketMacroUpdateExec' class='applyButton' data-icon-secondary='ui-icon-circle-arrow-e'>Add Message To Ticket</button> + </form> </div> @@ -234,55 +250,15 @@ <h5 class='noPadOrMargin'>Original Message:</h5> -<div id='helpPageTemplate' class='page pageHelp' data-app-role='dualModeContainer' data-app-mode='list'> - - <section class='dualModeDetailContainer' data-app-role='dualModeDetail' data-dualmode-widthpercent='70'></section> - - <section class='dualModeListContainer' data-app-role='dualModeList'> - <div class='ui-widget-header ui-corner-top'> - - <div class='buttonSet'> - <form class='searchBar floatRight' action='#' data-app-role='helpSearch'> - <input type='text' name='keywords' class='hideInDetailMode' /> - <button data-app-event='admin_support|execHelpSearch' class='hideInDetailMode'>Search</button> - <button data-app-event='admin|toggleDualMode'>Toggle between list and detail view</button> - </form> - </div> - - - <h3 class='heading'>Documentation</h3> - </div> - - <div class='ui-widget-content ui-corner-bottom'> - - <div class='dualModeListMessaging stdPadding'>Please use the search above to find the docs you are looking for.</div> - - <table class='gridTable fullWidth displayNone marginBottom' > - <thead> - <tr> - <th class='alignLeft'>Title</th> - <th class='alignLeft hideInDetailMode'>Summary</th> - <th class='alignLeft hideInDetailMode'>Relevance</th> - <th ></th> - </tr> - </thead> - <tbody data-bind="var: users(@RESULTS); format:processList; loadsTemplate:helpSearchResultsTemplate;" class='dualModeList' data-app-role='dualModeListContents'></tbody> - </table> - </div> - </section> -</div> - - -<!-- onClick="app.ext.admin_support.a.showHelpDocInDialog($(this).data('docid'));" --> +<!-- onClick="adminApp.ext.admin_support.a.showHelpDocInDialog($(this).data('docid'));" --> <table> <tr id='helpSearchResultsTemplate' > - <td data-bind='var: help(title); format:text;' class='lookLikeLink' data-app-event="admin_support|showHelpDetail"></td> - <td class='hideInDetailMode' data-bind='var: help(summary); format:text;'></td> - <td class='hideInDetailMode' data-bind='var: help(score); format:text;'></td> + <td data-bind='var: help(title); format:text;' class='lookLikeLink' data-app-click="admin_support|showHelpDetail"></td> + <td class='hideInDetailMode' data-bind='var: help(snippet); format:text;'></td> <td class='alignRight'> <!-- showHelpInDialog only displayed when help opened within a tabContent --> - <span class='hideInDetailMode'><button data-app-event="admin_support|showHelpDetailInDialog" class='showInTabContent'>Open In Dialog</button></span> - <button data-app-event="admin_support|showHelpDetail">View</button> + <span class='hideInDetailMode'><button data-app-click="admin_support|showHelpDocInDialog" class='showInTabContent applyButton' data-text='false' data-icon-primary='ui-icon-newwin'>Open In Dialog</button></span> + <button data-app-click="admin_support|showHelpDetail" class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowthick-1-e'>View</button> </td> </tr> </table> @@ -294,11 +270,7 @@ <h3 class='heading'>Documentation</h3> <div id='helpDocumentTemplate' class='helpDetail'> - <div data-bind="var: help(body); format:text;"></div> - - <hr /> - <button data-app-event="admin_support|execHelpDetailEdit">Edit</button> - <button data-app-event="admin_support|execHelpDetailHistory">History</button> + <div data-bind="var: help(parse.text.*); format:text;"></div> </div> diff --git a/extensions/admin/support.js b/extensions/admin/support.js index 7f81e23d5..82cff973a 100644 --- a/extensions/admin/support.js +++ b/extensions/admin/support.js @@ -17,8 +17,8 @@ ************************************************************** */ -var admin_support = function() { - var theseTemplates = new Array('supportFileUploadTemplate','supportManagerControls','supportTicketRowTemplate','supportTicketCreateTemplate','supportTicketDetailTemplate','supportTicketFollowupTemplate','helpPageTemplate','helpDocumentTemplate','helpSearchResultsTemplate'); +var admin_support = function(_app) { + var theseTemplates = new Array('supportFileUploadTemplate','supportManagerControls','supportTicketRowTemplate','supportTicketCreateTemplate','supportTicketDetailTemplate','supportTicketFollowupTemplate','helpDocumentTemplate','helpSearchResultsTemplate'); var r = { //////////////////////////////////// CALLS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ @@ -34,7 +34,7 @@ var admin_support = function() { obj['_tag'] = tagObj || {}; obj._tag.datapointer = "adminTicketFileAttach|"+obj.ticket; obj['_cmd'] = "adminTicketFileAttach"; - app.model.addDispatchToQ(obj,'immutable'); + _app.model.addDispatchToQ(obj,'immutable'); } } //adminNavcatProductDelete @@ -53,14 +53,14 @@ var admin_support = function() { onSuccess : function() { var r = true; //return false if extension won't load for some reason (account config, dependencies, etc). - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/support.html',theseTemplates); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/support.html',theseTemplates); return r; }, onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } }, //init @@ -77,15 +77,23 @@ var admin_support = function() { a : { - showTicketManager : function($target) { -// app.u.dump("BEGIN admin_support.a.showTicketManager"); - var $DMI = app.ext.admin.i.DMICreate($target,{ + showTicketManager : function($target,P) { +// _app.u.dump("BEGIN admin_support.a.showTicketManager"); + $target.intervaledEmpty(); + _app.ext.admin_support.a.showHelpInterface($target,P); + + $target.append("<div class='clearfix'></div>"); + + var $DMI = _app.ext.admin.i.DMICreate($target,{ 'header' : 'Ticket Manager', 'className' : 'adminTicketList', //applies a class on the DMI, which allows for css overriding for specific use cases. 'thead' : ['Status','Ticket #','Opened','Last Update','Subject','User','Date Closed',''], //leave blank at end if last row is buttons. 'tbodyDatabind' : "var: tickets(@TICKETS); format:processList; loadsTemplate:supportTicketRowTemplate;", - 'buttons' : ["<button data-app-event='admin|refreshDMI'>Refresh<\/button><button data-app-click='admin_support|adminTicketCreateShow' class='applyButton hideInDetailMode' data-text='true' data-icon-primary='ui-icon-circle-plus'>Create A New Ticket</button>"], - 'controls' : app.templates.supportManagerControls, + "handleAppEvents" : false, + 'buttons' : [ + "<button data-app-click='admin|refreshDMI' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowrefresh-1-s'>Refresh<\/button>", + "<button data-app-click='admin_support|adminTicketCreateShow' class='applyButton hideInDetailMode' data-text='true' data-icon-primary='ui-icon-circle-plus'>Create A New Ticket</button>"], + 'controls' : _app.templates.supportManagerControls, 'cmdVars' : { '_cmd' : 'adminTicketList', 'disposition' : 'open', @@ -95,44 +103,40 @@ var admin_support = function() { } } }); - app.u.handleButtons($target); - $DMI.closest("[data-app-role='dualModeContainer']").anydelegate(); - app.model.dispatchThis('mutable'); + _app.u.handleButtons($target.anyform()); + _app.model.dispatchThis('mutable'); }, - showPlatformInfo : function() { //if the current release has a video, give it a special pointer so that it can be loaded inline. - if(app.ext.admin.vars.versionMetaData.youtubeVideoIDs[app.model.version]) { - app.ext.admin.vars.versionMetaData.youtubeVideoID = app.ext.admin.vars.versionMetaData.youtubeVideoIDs[app.model.version]; - } - - var $D = app.ext.admin.i.dialogCreate({ + + var $D = _app.ext.admin.i.dialogCreate({ 'title':'Platform Information', 'templateID':'platformInfoTemplate', - 'data' : app.ext.admin.vars.versionMetaData + 'data' : _app.ext.admin.vars.versionData }).addClass('objectInspector'); $D.attr('id','platformInformation'); +//populate the video section w/ the current release data. + $("[data-app-role='platformInfoVideoContainer']").anycontent({ + data : _app.ext.admin.vars.versionData[0] + }) + var $platInfo = $("[data-app-role='platformInfoContainer']",$D); $platInfo.showLoading({'message':'Fetching platform data'}); - app.model.addDispatchToQ({'_cmd':'platformInfo','_tag': {'datapointer' : 'info','callback':function(rd){ + _app.model.addDispatchToQ({'_cmd':'platformInfo','_tag': {'datapointer' : 'info','callback':function(rd){ $platInfo.hideLoading(); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $D.anymessage({'message':rd}); } else { + //add platform info to the top of the section. + $("[data-app-role='platformInfoDetailsContainer']",$platInfo).prepend(_app.ext.admin_tools.u.objExplore($.extend({},_app.u.getBlacklistedObject(_app.data[rd.datapointer],['ts','_uuid','_rtag','_rcmd']),{'app release':_app.vars.release}))).prepend("<h3>Platform Information<\/h3>"); - $platInfo.append("<h3>Platform Information<\/h3>"); - $platInfo.append(app.ext.admin_tools.u.objExplore($.extend({},app.u.getBlacklistedObject(app.data[rd.datapointer],['ts','_uuid','_rtag','_rcmd']),{'app release':app.vars.release}))); - $platInfo.append("<h3>Video History<\/h3>"); - for(var index in app.ext.admin.vars.versionMetaData.youtubeVideoIDs) { - $platInfo.append($("<div class='lookLikeLink' onclick='linkOffSite(\"http://www.youtube.com/watch?v="+app.ext.admin.vars.versionMetaData.youtubeVideoIDs[index]+"\"); return false;' title='http://www.youtube.com/watch?v="+app.ext.admin.vars.versionMetaData.youtubeVideoIDs[index]+"'> » "+index+"<\/div>")) - } - app.u.handleAppEvents($D); } }}},'mutable'); - app.model.dispatchThis('mutable'); + _app.model.dispatchThis('mutable'); $D.dialog('option','modal',false); + $D.anyform(); $D.dialog('open'); }, @@ -149,66 +153,51 @@ var admin_support = function() { }, //will open help interface within $target. - showHelpInterface : function($target){ - if($("[data-app-role='dualModeContainer']",$target).length) { - $target.show(); - } //already an instance of help open in this target. leave as is. - else { - $target.anycontent({'templateID':'helpPageTemplate','showLoading':false}); //clear contents and add help interface - app.ext.admin.u.handleAppEvents($target); - $('.gridTable',$target).anytable(); +// ### FUTURE -> vars.title support started but not finished/tested. add support for vars.title to be passed in and have a search performed. + showHelpInterface : function($target,vars){ + vars = vars || {}; + + var $DMI = _app.ext.admin.i.DMICreate($target,{ + 'header' : 'Search our Online Documentation', //left off because the interface is in a tab. + 'className' : 'helpDocumentation', + 'buttons' : [], + 'controls' : "<form class='searchBar' data-app-submit='admin_support|execHelpSearch' data-app-role='helpSearch'><input type='text' name='srsearch' value='"+( vars.title ? vars.title : '' )+"' class='hideInDetailMode' /><button class='hideInDetailMode applyButton' data-text='false' data-icon-primary='ui-icon-search'>Search</button></form>", + 'thead' : ['title','Snippet',''], + 'tbodyDatabind' : "var: users(query.search); format:processList; loadsTemplate:helpSearchResultsTemplate;", + 'skipInitialDispatch' : true, + 'showLoading' : false, + 'cmdVars' : { + '_cmd' : 'helpSearch', + '_tag' : {'datapointer' : 'adminConfigDetail|prts'} + } + }); + _app.u.handleButtons($target.anyform()); + if(vars.title) { + $('form:first',$DMI).trigger('submit'); } }, - - - //does everything. pass in a docid and this 'll handle the call, request and display. //will check to see if a dom element already exists and , if so, just open that and make it flash. - showHelpDocInDialog : function(docid) { - if(docid) { - var targetID = 'helpfile_'+docid - var $target = $(app.u.jqSelector('#',targetID)); -//already on the dom. just open it. - if($target.length) { - $target.dialog('open') - $target.effect("highlight", {}, 1500); - } - else { - $target = $("<div \/>",{'id':targetID,'title':'help doc: '+docid}).attr('docid',docid).addClass('helpDoc').appendTo('body'); - $target.dialog({width:500, height:500}); - $target.showLoading({'message':'Fetching help documentation...'}); - - app.ext.admin.calls.helpDocumentGet.init(docid,{'callback':function(rd){ - app.u.dump(" -> RD: "); app.u.dump(rd); - $target.hideLoading(); - if(app.model.responseHasErrors(rd)){ - $target.anymessage({'message':rd}); - } - else { - $target.anycontent({'templateID':'helpDocumentTemplate','datapointer':rd.datapointer}); - app.u.handleAppEvents($target); - app.ext.admin_support.u.handleHelpDocOverwrites($target); - } - }},'mutable'); - app.model.dispatchThis('mutable'); - } + showHelpDocInDialog : function(title) { + if(title) { + var $D = _app.ext.admin.i.dialogCreate({ + title : title, + 'templateID' : 'helpDocumentTemplate', + 'showLoading' : false, + anycontent : true, //the dialogCreate params are passed into anycontent + handleAppEvents : false //defaults to true + }); + $D.dialog('option','modal',false); + $D.prepend("<div class='hint alignRight marginBottom'>you can resize this window (drag a corner) or move it (drag the title bar).</div>"); + $D.dialog('open'); + _app.ext.admin_support.u.loadHelpDocInto($D,title); } else { - app.u.throwMessage("In admin.u.showHelpInModal, no docid specified."); + _app.u.throwMessage("In admin.u.showHelpInModal, no docid specified."); } }, - - addSupportFileUploadToID : function(id,ticketid,uuid) { - var $target = $(app.u.jqSelector('#',id)); - $target.empty(); //clear any previous instantiations of the uploader. (in case of doubleclick) - $target.append(app.renderFunctions.transmogrify({'ticketid':ticketid,'uuid':uuid},'supportFileUploadTemplate',{})); - $('#supportFileUploadForTicket').append("<input type='hidden' name='domain' value='"+app.vars.domain+"' \/>"); //file upload wants domain specified. - $('#supportFileUploadForTicket').append("<input type='hidden' name='ticketid' value='"+ticketid+"' \/>"); //file upload wants domain specified. - $('#supportFileUploadForTicket').append("<input type='hidden' name='uuid' value='"+uuid+"' \/>"); //file upload wants domain specified. - app.ext.admin_medialib.u.convertFormToJQFU('#supportFileUploadForTicket','adminTicketFileAttach'); - }, - + showFileUploadInModal : function(ticketid,uuid){ if((ticketid === 0 || ticketid) && uuid) { var $target = $('#ticketFileUploadModal'); @@ -220,15 +209,15 @@ var admin_support = function() { } $target.attr('data-ticketid',ticketid); $('.ui-dialog-title',$target.parent()).text("File upload for ticket "+ticketid); - $target.append(app.renderFunctions.transmogrify({},'supportFileUploadTemplate',{'ticketid':ticketid,'uuid':uuid})).dialog('open'); - $('#supportFileUploadForTicket').append("<input type='hidden' name='domain' value='"+app.vars.domain+"' \/>"); //file upload wants domain specified. + $target.append(_app.renderFunctions.transmogrify({},'supportFileUploadTemplate',{'ticketid':ticketid,'uuid':uuid})).dialog('open'); + $('#supportFileUploadForTicket').append("<input type='hidden' name='domain' value='"+_app.vars.domain+"' \/>"); //file upload wants domain specified. $('#supportFileUploadForTicket').append("<input type='hidden' name='ticketid' value='"+ticketid+"' \/>"); //file upload wants domain specified. $('#supportFileUploadForTicket').append("<input type='hidden' name='uuid' value='"+uuid+"' \/>"); //file upload wants domain specified. - app.ext.admin_medialib.u.convertFormToJQFU('#supportFileUploadForTicket','adminTicketFileAttach'); + _app.ext.admin_medialib.u.convertFormToJQFU('#supportFileUploadForTicket','adminTicketFileAttach'); } else { - app.u.throwGMessage("Warning! Either ticketid ["+ticketid+"] or uuid ["+uuid+"] not specified in admin_support.a.showFileUploadInModal. Both are required."); + _app.u.throwGMessage("Warning! Either ticketid ["+ticketid+"] or uuid ["+uuid+"] not specified in admin_support.a.showFileUploadInModal. Both are required."); } } @@ -259,19 +248,20 @@ var admin_support = function() { gatherIntel : function() { var r = "" //what is returned. r += "\n\n ##### The following information is for the admin interface and user computer, not necessarily what was used in the issue of the ticket\n"; - r += "MVC version: "+app.model.version; - r += "\nMVC release: "+app.vars.release; - r += "\ndevice id: "+app.vars.deviceid; - r += "\nuser id: "+app.vars.userid; - r += "\nlogged in to: "+app.vars.domain; - r += "\nbrowser and OS: "+app.vars.passInDispatchV; + r += "MVC version: "+_app.model.version; + r += "\nMVC release: "+_app.vars.release; + r += "\ndevice id: "+_app.vars.deviceid; + r += "\nuser id: "+_app.vars.userid; + r += "\nlogged in to: "+_app.vars.domain; + r += "\ndomain: "+location.domain; + r += "\nbrowser and OS: "+_app.vars.passInDispatchV; r += "\n\nuserAgent: "+navigator.userAgent; r += "\nappVersion: "+navigator.appVersion; r += "\noscpu: "+navigator.oscpu; r += "\nscreen size: "+screen.width+" X "+screen.height; r += "\nbrowser size: "+$('body').width()+" X "+$('body').height(); - var info = app.u.getBlacklistedObject(app.data.info,['server-time','ts','_uuid','_rtag','_rcmd']); + var info = _app.u.getBlacklistedObject(_app.data.info,['server-time','ts','_uuid','_rtag','_rcmd']); for(var index in info) {r+= index+": "+info[index]} return r; @@ -279,19 +269,76 @@ var admin_support = function() { //overwrite the linkdoc links. In the future, this will probably do more. handleHelpDocOverwrites : function($target) { - app.u.dump("BEGIN admin_support.u.handleHelpDocOverwrites"); - app.u.dump("$('.linkdoc',$target).length: "+$('.linkdoc',$target).length); + _app.u.dump("BEGIN admin_support.u.handleHelpDocOverwrites"); + _app.u.dump("$('.linkdoc',$target).length: "+$('.linkdoc',$target).length); //syllabus_product_basics -> good place to test linkdoc - // !!! link this to a search, not an individual docs. build in support for passing keywords in showUI obj var. set as val of keywords in put and submit form. + // !!! link this to a search, not an individual docs. build in support for passing keywords in navigateTo obj var. set as val of keywords in put and submit form. $('.linkdoc',$target).each(function(){ var $a = $(this), docID = $a.attr('href').split('=')[1]; $a.on('click',function(event){ event.preventDefault(); - app.u.dump(" -> Click got registered."); - app.ext.admin_support.a.showHelpDocInDialog(docID); + _app.u.dump(" -> Click got registered."); + _app.ext.admin_support.a.showHelpDocInDialog(docID); }); }); + }, + + +//is a separate function because it's called by both the ticket DMI and the media library. + loadTicketContent : function($context,ticketID,uuid,q) { + + if($context instanceof jQuery) { + if(ticketID && uuid) { + + $context.showLoading({'message':'Fetching ticket details'}).data({'ticketid':ticketID, 'uuid':uuid}); + +//Clear the follows and attachment lists, but not the rest of the panel. That way, anything in the message input is preserved. + $("[data-app-role='ticketAttatchmentList']",$context).empty(); + $("[data-app-role='ticketFollowupList']",$context).empty(); + + _app.model.addDispatchToQ({'_cmd':'adminTicketFileList','ticketid':ticketID,'_tag': {'datapointer' : 'adminTicketFileList|'+ticketID}},'mutable'); + _app.model.addDispatchToQ({ + '_cmd':'adminTicketDetail', + 'ticketid':ticketID, + '_tag': { + 'datapointer' : 'adminTicketDetail|'+ticketID, + 'callback': 'anycontent', + 'translateOnly' : true, + 'jqObj' : $context, + 'extendByDatapointers' : ['adminTicketFileList|'+ticketID] + } + },q); + +// $("[data-app-role='supportFileUploadContainer']",$context).anyupload({'filesChange' : function(files,ui) { +// _app.u.dump(" >>>>>>>"); +// }}); + + } + else { + $context.anymessage({"message":"In admin_support.e.adminTicketDetailShow, unable to ascertain ticketID ["+ticketID+"] and/or UUID ["+uuid+"], both of which are required.","gMessage":true}); + } + } + else { + $('#globalMessaging').anymessage({"message":"In admin_support.e.adminTicketDetailShow, $context in not a valid jquery instance.","gMessage":true}); + } + + }, + + loadHelpDocInto : function($target,title) { + if($target instanceof jQuery && title) { + $target.showLoading({"message":"Fetching help doc "+title}); + _app.model.addDispatchToQ({"_cmd":"helpWiki","format":"json","action":"parse","page":title,"_tag":{"datapointer":"helpWikiSearch",'callback':'anycontent','jqObj':$target}},"mutable"); + _app.model.dispatchThis('mutable'); + } + else if($target instanceof jQuery) { + $target.anymessage({"message":"In admin_support.u.loadHelpDocInto, no title specified.","gMessage":true}) + } + else { + $("#globalMessaging").anymessage({"message":"In admin_support.u.loadHelpDocInto, $target is not a valid jQuery instance.","gMessage":true}); + } +//action='parse','page':'title' + } }, //u @@ -299,23 +346,47 @@ var admin_support = function() { e : { + platformInfoWatchVideo : function($ele,p) { + var data = $ele.closest("[data-youtubevideoid]").data(); + if(data.youtubevideoid) { + $ele.closest("[data-app-role='platformInfoContainer']").find("[data-app-role='platformInfoVideoContainer']").empty().anycontent({ + data : data, + translateOnly: true + }); + } + else { + $ele.closest("[data-app-role='platformInfoContainer']").find("[data-app-role='platformInfoVideoContainer']").empty().show().anymessage({ + 'message' : 'No video present for this release', + 'errtype' : 'warn', + 'showCloseButton' : false, + 'persistent' : true + }) + } + }, + + platformInfoViewChangelog : function($ele,p) { + linkOffSite('https://raw.github.com/zoovy/AnyCommerce-Development/'+$ele.closest('tr').data('branch')+'/changelog.txt','',true) + }, + adminTicketCreateShow : function($ele,p) { - var $D = app.ext.admin.i.dialogCreate({ + var $D = _app.ext.admin.i.dialogCreate({ 'title' : 'Create a New Ticket', 'templateID' : 'supportTicketCreateTemplate', - 'data' : {}, + 'data' : { + 'domain' : 'http://'+_app.vars.domain + }, }); $('form',$D).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); $D.dialog('open'); - $D.data({'ticketid':'0','uuid':app.u.guidGenerator()}); //necessary for file attachment. - $D.anydelegate(); - app.u.handleButtons($D); + $D.data({'ticketid':'0','uuid':_app.u.guidGenerator()}); //necessary for file attachment. + $D.anyform(); + _app.u.handleButtons($D); }, adminTicketCreateExec : function($ele,p) { var $form = $ele.closest('form'); - if(app.u.validateForm($form)) { + if(_app.u.validateForm($form)) { $form.showLoading({'message':'Creating a new ticket'}); var sfo = $form.serializeJSON(); $form.append("<input type='hidden' name='UUID' value='"+$ele.closest('.ui-dialog-content').data('uuid')+"' \/>"); @@ -326,10 +397,12 @@ var admin_support = function() { //only pass populated fields and don't pass description again (see above). if(sfo[index] && index != 'description' && index.indexOf('_tag') < 0){messagebody += "\n"+index+": "+sfo[index]} } - messagebody += app.ext.admin_support.u.gatherIntel(); - $form.append("<input type='hidden' name='body' value='"+messagebody+"' \/>"); - app.ext.admin.a.processForm($form,'immutable'); - app.model.dispatchThis('immutable'); + messagebody += _app.ext.admin_support.u.gatherIntel(); +// ** 201346 -> w/ a hidden input, if an apostrophe is in messagebody, everything after it gets dropped. +// $form.append("<input type='hidden' name='body' value='"+messagebody+"' \/>"); + $form.append($("<textarea \/>").attr('name','body').val(messagebody).hide()); + _app.ext.admin.a.processForm($form,'immutable'); + _app.model.dispatchThis('immutable'); } else {} //validation handles error display @@ -341,7 +414,7 @@ var admin_support = function() { p.preventDefault(); var $panelContents = $ele.closest('.ui-widget-anypanel'); //in create, the dialog body get this same class, so the selector works in both places. if($panelContents instanceof jQuery && $panelContents.length && $panelContents.data('ticketid') && $panelContents.data('uuid')) { - app.ext.admin_support.a.showFileUploadInModal($panelContents.data('ticketid'),$panelContents.data('uuid')); + _app.ext.admin_support.a.showFileUploadInModal($panelContents.data('ticketid'),$panelContents.data('uuid')); } else if($panelContents) { $ele.parent().anymessage({'message':"In admin_support.e.showFileAttachmentModal, unable to determine ticketid ["+$panelContents.data('ticketid')+"] and/or uuid ["+$panelContents.data('uuid')+"]",'gMessage':true}); @@ -354,13 +427,13 @@ var admin_support = function() { adminTicketMacroCloseShow : function($ele,p){ var ticketID = $ele.closest("[data-id]").data('id'); p.preventDefault(); - var $D = app.ext.admin.i.dialogConfirmRemove({ + var $D = _app.ext.admin.i.dialogConfirmRemove({ 'message':'Are you sure you want to close this ticket?', 'removeButtonText' : 'Close Ticket', 'removeFunction':function(rd){ - app.ext.admin.calls.adminTicketMacro.init(ticketID,new Array('CLOSE'),{},'immutable'); - app.model.dispatchThis('immutable'); - $ele.closest("[data-app-role='dualModeContainer']").find("button[data-app-event='admin|refreshDMI']:first").trigger('click'); + _app.model.addDispatchToQ({"_cmd":"adminTicketMacro","ticketid":ticketID,"@updates":['CLOSE'],"_tag":{"datapointer":"adminTicketMacro"}},"immutable"); + _app.model.dispatchThis('immutable'); + $ele.closest("[data-app-role='dualModeContainer']").find("button[data-app-click='admin|refreshDMI']:first").trigger('click'); $D.dialog('close'); } }); @@ -370,20 +443,20 @@ var admin_support = function() { p.preventDefault(); var $form = $ele.closest('form'), - $panelContents = $ele.closest('.ui-widget-anypanel'); + $panel = $ele.closest('.ui-widget-anypanel'); - if(app.u.validateForm($form)) { - $panelContents.showLoading({'message':'Updating ticket'}); - app.ext.admin.calls.adminTicketMacro.init($panelContents.data('ticketid'),['APPEND?note='+encodeURIComponent($("[name='note']",$form).val())],{'callback':function(rd){ - $panelContents.hideLoading(); - if(app.model.responseHasErrors(rd)){ - $form.anymessage({'message':rd}); - } - else { - $form.empty().anymessage({'message':app.u.successMsgObject('Ticket '+$panelContents.data('ticketid')+' has been updated')}) - } - }},'immutable'); - app.model.dispatchThis('immutable'); + if(_app.u.validateForm($form)) { + $panel.showLoading({'message':'Updating ticket'}); + + _app.model.addDispatchToQ({"_cmd":"adminTicketMacro","ticketid":$panel.data('ticketid'),"@updates":['APPEND?note='+encodeURIComponent($("[name='note']",$form).val())],"_tag":{ + "datapointer":"adminTicketMacro", + "callback" : "showMessaging", + "message" : 'Ticket '+$panel.data('ticketid')+' has been updated', + "jqObj" : $form + }},"immutable"); + //refresh the ticket. + _app.ext.admin_support.u.loadTicketContent($panel,$panel.data('ticketid'),$panel.data('uuid'),'immutable'); + _app.model.dispatchThis('immutable'); } else {} //validateForm handles displaying errors. @@ -396,7 +469,7 @@ var admin_support = function() { $ele.button('disable'); if(ticketID) { $(document.body).showLoading({'message':'Fetching file contents'}); - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd':'adminTicketFileGet', 'ticketid' : ticketID, 'remote' : $ele.closest('tr').data('remote'), @@ -408,7 +481,7 @@ var admin_support = function() { 'button' : $ele //used to re-enable the download button } },'mutable'); - app.model.dispatchThis('mutable'); + _app.model.dispatchThis('mutable'); } else { $ele.parent().anymessage({"message":'In admin_support.e.admiNTicketFileGetExec, unable to ascertain ticket ID.','gMessage':true}); @@ -416,35 +489,32 @@ var admin_support = function() { }, adminTicketLastUpdateShow : function($ele,p) { - -var - $tr = $ele.closest('tr'), - ticketID = $tr.data('id'); - -$tr.closest('tbody').showLoading({'message':'Retrieving last message for ticket '+ticketID}); -app.model.addDispatchToQ({ - '_cmd':'adminTicketDetail', - 'ticketid':ticketID, - '_tag': { - 'datapointer' : 'adminTicketDetail|'+ticketID, - 'callback':function(rd){ - $tr.closest('tbody').hideLoading(); - if(app.model.responseHasErrors(rd)){ - $('#globalMessaging').anymessage({'message':rd}); - } - else { - $ele.off('click.showTicketLastUpdate').removeClass('lookLikeLink'); - if(app.data[rd.datapointer] && app.data[rd.datapointer]['@FOLLOWUPS'] && app.data[rd.datapointer]['@FOLLOWUPS'].length) { - $tr.after("<tr class='hideInMinimalMode'><td class='alignRight'><span class='ui-icon ui-icon-arrowreturnthick-1-e'><\/span><\/td><td colspan='7'><pre class='preformatted'>"+app.data[rd.datapointer]['@FOLLOWUPS'][(app.data[rd.datapointer]['@FOLLOWUPS'].length - 1)].txt+"<\/pre><\/td><\/tr>"); //responses are in chronological order, so zero is always the first post. - } - else {} //no followups. "shouldn't" get here cuz link won't appear if there an update hasn't occured. - } - } - } - },'mutable'); -app.model.dispatchThis('mutable'); - + var + $tr = $ele.closest('tr'), + ticketID = $tr.data('id'); + $tr.closest('tbody').showLoading({'message':'Retrieving last message for ticket '+ticketID}); + _app.model.addDispatchToQ({ + '_cmd':'adminTicketDetail', + 'ticketid':ticketID, + '_tag': { + 'datapointer' : 'adminTicketDetail|'+ticketID, + 'callback':function(rd){ + $tr.closest('tbody').hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $('#globalMessaging').anymessage({'message':rd}); + } + else { + $ele.off('click.showTicketLastUpdate').removeClass('lookLikeLink'); + if(_app.data[rd.datapointer] && _app.data[rd.datapointer]['@FOLLOWUPS'] && _app.data[rd.datapointer]['@FOLLOWUPS'].length) { + $tr.after("<tr class='hideInMinimalMode'><td class='alignRight'><span class='ui-icon ui-icon-arrowreturnthick-1-e'><\/span><\/td><td colspan='7'><pre class='preformatted'>"+_app.data[rd.datapointer]['@FOLLOWUPS'][(_app.data[rd.datapointer]['@FOLLOWUPS'].length - 1)].txt+"<\/pre><\/td><\/tr>"); //responses are in chronological order, so zero is always the first post. + } + else {} //no followups. "shouldn't" get here cuz link won't appear if there an update hasn't occured. + } + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); }, adminTicketDetailShow : function($ele,p) { @@ -454,26 +524,42 @@ app.model.dispatchThis('mutable'); uuid = $ele.closest("[data-id]").data('uuid'); if(ticketID && uuid) { - $panel = app.ext.admin.i.DMIPanelOpen($ele,{ + $panel = _app.ext.admin.i.DMIPanelOpen($ele,{ 'templateID' : 'supportTicketDetailTemplate', - 'panelID' : 'task_'+ticketID, + 'panelID' : 'ticket_'+ticketID, + 'showLoading' : false, 'header' : 'Edit Ticket: '+ticketID }); - $panel.showLoading({'message':'Fetching ticket details'}).data({'ticketid':ticketID, 'uuid':uuid}) - app.model.addDispatchToQ({'_cmd':'adminTicketFileList','ticketid':ticketID,'_tag': {'datapointer' : 'adminTicketFileList|'+ticketID}},'mutable'); - app.model.addDispatchToQ({ - '_cmd':'adminTicketDetail', - 'ticketid':ticketID, - '_tag': { - 'datapointer' : 'adminTicketDetail|'+ticketID, - 'callback': 'anycontent', - 'translateOnly' : true, - 'jqObj' : $panel, - 'extendByDatapointers' : ['adminTicketFileList|'+ticketID] - } - },'mutable'); - app.model.dispatchThis('mutable'); + _app.ext.admin_support.u.loadTicketContent($panel,ticketID,uuid,'mutable'); + $("[data-app-role='supportFileUploadContainer']",$panel).anyupload({ + autoUpload : false, + encode : 'base64', //if this is disabled, change enctype in the dispatch to null. + ajaxRequest : function(vars,$ele) { +// _app.u.dump(vars); + var $fUpload = $("[data-app-role='supportFileUploadContainer']",$panel); + $fUpload.showLoading({"message":"uploading files"}); + _app.model.addDispatchToQ({ + "_cmd":"adminTicketFileAttach", + "filename" : vars.filename, + "enctype" : "base64", //must be set if data passed as base64. + "ticketid" : ticketID, + "body" : vars.filecontents, + "_tag":{ + "callback":"showMessaging", + "jqObj" : $fUpload, + "onComplete" : function(){ + $(".fileUpload_default",$fUpload).slideUp(); //hide the items that were just uploaded. They'll be in the newly generated filename table. + _app.model.dispatchThis('mutable'); + }, + "message":"File "+vars.filename+" attached to ticket "+ticketID + } + },"mutable"); + _app.model.addDispatchToQ({'_cmd':'adminTicketDetail','ticketid':ticketID,'_tag': {'datapointer' : 'adminTicketFileList|'+ticketID,'callback':'anycontent','jqObj':$("[data-app-role='ticketAttatchmentList']",$panel).empty()}},'mutable'); + _app.model.dispatchThis("mutable"); + } + }); + _app.model.dispatchThis('mutable'); } else { @@ -483,26 +569,23 @@ app.model.dispatchThis('mutable'); //used in the support utilites. - ping : function($btn) { - $btn.button(); - $btn.off('click.ping').on('click.ping',function(){ - var start = new Date().getTime(); -app.model.addDispatchToQ({ - '_cmd':'ping', - '_tag': { - 'callback':function(rd){ -if(app.model.responseHasErrors(rd)){ - $('#platformInformation').anymessage({'message':rd}); - } -else { - var end = new Date().getTime(); - alert("Pong! took "+(end - start) / 1000+" seconds") - } - } - } - },'mutable'); -app.model.dispatchThis('mutable'); - }); + ping : function($ele,P) { + var start = new Date().getTime(); + _app.model.addDispatchToQ({ + '_cmd':'ping', + '_tag': { + 'callback':function(rd){ + if(_app.model.responseHasErrors(rd)){ + $('#platformInformation').anymessage({'message':rd}); + } + else { + var end = new Date().getTime(); + alert("Pong! took "+(end - start) / 1000+" seconds") + } + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); }, @@ -511,158 +594,62 @@ app.model.dispatchThis('mutable'); /*************** WEBDOC ******************/ - - execHelpDetailEdit : function($btn) { - $btn.button(); - $btn.off('click.execHelpDetailEdit').on('click.execHelpDetailEdit',function(){ - var docID = $btn.closest("[data-docid]").data('docid'); - if(docID) { - window.open('https://github.com/zoovy/documentation/blob/master/'+docID+'.html'); - } - else { - $btn.parent().after().anymessage({'message':'In admin_support.e.execHelpDetailHistory, unable to determine docid','gMessage':true}); - } - }); - }, //execHelpDetailEdit - - execHelpDetailHistory : function($btn) { - $btn.button(); - $btn.off('click.execHelpDetailHistory').on('click.execHelpDetailHistory',function(){ - var docID = $btn.closest("[data-docid]").data('docid'); - if(docID) { - window.open('https://github.com/zoovy/documentation/commits/master/'+docID+'.html'); - } - else { - $btn.parent().after().anymessage({'message':'In admin_support.e.execHelpDetailHistory, unable to determine docid','gMessage':true}); - } - }); - }, //execHelpDetailHistory - - execHelpSearch : function($btn) { - $btn.button({icons: {primary: "ui-icon-search"},text: false}); - $btn.off('click.helpSearch').on('click.helpSearch',function(event){ - - var $parent = $btn.closest("[data-app-role='dualModeContainer']"), + execHelpSearch : function($ele,P) { + + var $parent = $ele.closest("[data-app-role='dualModeContainer']"), $form = $("[data-app-role='helpSearch']",$parent).first(), - keywords = $("[name='keywords']",$parent).val(); - -// app.u.dump(" -> $parent.length: "+$parent.length); -// app.u.dump(" -> $form.length: "+$form.length); -// app.u.dump(" -> formObj: "); app.u.dump(formObj); -// app.u.dump(" -> keywords: "+keywords); + srsearch = $("[name='srsearch']",$parent).val(); - if(keywords) { + if(srsearch) { $('.dualModeListMessaging',$parent).first().empty().hide(); var $contentArea = $('.gridTable',$parent).first(); $contentArea.show().find('tbody').empty(); //empty any previous search results. $contentArea.showLoading({"message":"Searching for help files"}); - app.ext.admin.calls.helpSearch.init(keywords,{'callback':'anycontent','jqObj':$contentArea},'mutable'); - app.model.dispatchThis('mutable'); +//docs on the media wiki API can be found here: http://wiki.commercerack.com/wiki/api.php + _app.model.addDispatchToQ({"_cmd":"helpWiki","format":"json","list":"search","action":"query","srwhat":"text","srsearch":srsearch,"_tag":{"datapointer":"helpWikiSearch",'callback':'anycontent','jqObj':$contentArea}},"mutable"); + _app.model.dispatchThis('mutable'); } else { $('.dualModeListMessaging',$parent).first().empty().show().anymessage({'message':'Please enter some keywords into the form input above to search for.'}); $("[data-app-role='dualModeListContents']",$parent).first().hide(); } - event.preventDefault(); - }); - }, //execHelpSearch + P.preventDefault(); + }, //execHelpSearch +//<button data-app-click="admin_support|showHelpDocInDialog" class='applyButton' data-title='some_helpdoc_id' data-icon-primary='ui-icon-lightbulb'>Help</button> //uses new delegated events model. showHelpDocInDialog : function($ele,p) { - var docID = $ele.data('docid'); - if(docID) { - app.ext.admin_support.a.showHelpDocInDialog(docID); + var title = $ele.closest('[data-title]').data('title'); + if(title) { + _app.ext.admin_support.a.showHelpDocInDialog(title); } else { - $('#globalMessaging').anymessage({'message':'In admin_support.e.showHelpDetailInDialog, unable to determine docID.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In admin_support.e.showHelpDocInDialog, unable to determine data-title from trigger element.','gMessage':true}); } }, - -//used on a button in the search interface. allows merchant to open the doc in a dialog, for portability. -//button should be hidden when webdoc itself opened in dialog. - showHelpDetailInDialog : function($ele) { - if($ele.is('button')) {$ele.button({icons: {primary: "ui-icon-newwin"}});} - $ele.off('click.showHelpDetailInDialog').on('click.showHelpDetailInDialog',function(event){ - event.preventDefault(); - var docID = $ele.closest('tr').data('docid'); - if(docID) { - app.ext.admin_support.a.showHelpDocInDialog(docID); - } - else { - $('#globalMessaging').anymessage({'message':'In admin_support.e.showHelpDetailInDialog, unable to determine docID.','gMessage':true}); - } - }); - }, //showHelpDetailInDialog - -//in this case, the event may be applied to a btn OR some text. - showHelpDetail : function($ele) { - - if($ele.is('button')) {$ele.button({icons: {primary: "ui-icon-circle-arrow-e"}});} - $ele.off('click.showHelpDetail').on('click.showHelpDetail',function(event){ - event.preventDefault(); - var docID = $ele.closest('tr').data('docid'); - if(docID) { - -var $dualModeDetail = $ele.closest("[data-app-role='dualModeContainer']").find("[data-app-role='dualModeDetail']").first(), -panelID = app.u.jqSelector('','helpDetail_'+docID), -$panel = $("<div\/>").data('docid',docID).hide().anypanel({ - 'header':'Help file: '+docID, - 'templateID':'helpDocumentTemplate', - 'dataAttribs': {'id':panelID,'docid':docID} - }).prependTo($dualModeDetail); - -app.ext.admin.u.toggleDualMode($dualModeDetail.closest("[data-app-role='dualModeContainer']"),'detail'); - -app.ext.admin.calls.helpDocumentGet.init(docID,{ - 'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ - app.u.throwMessage(rd); - } - else { - $panel.anycontent({'datapointer':rd.datapointer}); - app.u.handleAppEvents($panel); - app.ext.admin_support.u.handleHelpDocOverwrites($panel); - } - } - },'mutable'); - -$panel.slideDown('fast',function(){$panel.showLoading({'message':'Fetching Help Document.'});}); -app.model.dispatchThis('mutable'); - - - } - else { - $('#globalMessaging').anymessage({'message':'In admin_support.e.showHelpDetail, unable to determine docID.','gMessage':true}); - } - }); - - } - - - - - -/* -not needed in support 2 - tagAsPriority : function($ele) { - - $ele.off('change.tagAsPriorityHigh').on('change.tagAsPriorityHigh',function(){ - var $phoneFieldset = $ele.closest('form').find("[data-app-role='phoneFieldset']"); +//used in the DMI help interface to open a panel and popupate it w/ contents. + showHelpDetail : function($ele,P) { + P.preventDefault(); + var title = $ele.closest('tr').data('title'); + if(title) { + $panel = _app.ext.admin.i.DMIPanelOpen($ele,{ + 'templateID' : 'helpDocumentTemplate', + 'panelID' : 'helpdoc_'+title, + 'showLoading' : false, + 'header' : title + }); - app.u.dump(" -> got into change code"); - - if($ele.val() == 'HIGH') { - $phoneFieldset.show(); - } - else { - $phoneFieldset.hide(); - } - }); - } //tagAsPriority -*/ + _app.ext.admin_support.u.loadHelpDocInto($(".ui-anypanel-content",$panel),title); + _app.u.handleButtons($panel); + } + else { + $('#globalMessaging').anymessage({'message':'In admin_support.e.showHelpDetail, unable to determine title.','gMessage':true}); + } + } + } } //r object. diff --git a/extensions/admin/task.html b/extensions/admin/task.html index bab1fe07b..1305a61bb 100644 --- a/extensions/admin/task.html +++ b/extensions/admin/task.html @@ -6,13 +6,13 @@ <table> <!-- tr will be assigned all key/value pairs in data- attributes (keys will be all lowercase) --> <tr id='taskListRowTemplate' class='taskRow'> - <td class='hideInMinifyMode'><input type='checkbox' /></td><!-- bind a change event that adds/remves ui-selected class on tr --> - <td class='hideInMinifyMode' data-bind="var: task(created_gmt); format:unix2mdy;"></td> + <td class='hideInMinifyMode'><input class='allowBulkCheck' type='checkbox' /></td><!-- bind a change event that adds/remves ui-selected class on tr --> + <td class='hideInMinifyMode' data-bind="var: task(created_gmt); format:epoch2mdy;"></td> <td data-bind="var: task(completed_gmt); format:addClass; className: lineThrough gmt_; hideZero:true;"><span data-bind="var: task(title); format:text;"></span></td> - <td class='hideInMinifyMode' data-bind="var: task(due_gmt); format:unix2mdy; hideZero:true;"></td> + <td class='hideInMinifyMode' data-bind="var: task(due_gmt); format:epoch2mdy; hideZero:true;"></td> <td class='hideInMinifyMode' data-bind="var: task(priority); format:text;"></td> <td class='hideInMinifyMode lowercase' data-bind="var: task(class); format:text;"></td> -<!-- <td class='hideInMinifyMode lookLikeLink' onClick="app.u.dump($(this).parent().data()); alert($(this).parent().data('link'))">Do it to it</td> --> +<!-- <td class='hideInMinifyMode lookLikeLink' onClick="adminApp.u.dump($(this).parent().data()); alert($(this).parent().data('link'))">Do it to it</td> --> <td class='hideInMinifyMode' data-bind="var: task(luser); format:text;"></td> <td > <button data-app-click="admin_task|adminTaskUpdateShow" class='applyButton' data-text='false' data-icon-primary='ui-icon-pencil'>Edit Task</button> diff --git a/extensions/admin/task.js b/extensions/admin/task.js index 612272733..98d6e54d6 100644 --- a/extensions/admin/task.js +++ b/extensions/admin/task.js @@ -40,7 +40,7 @@ Planned Features/UI enhancements: -var admin_task = function() { +var admin_task = function(_app) { var theseTemplates = new Array('taskListRowTemplate','taskListCreateEditTemplate','taskListEditPanelTemplate','taskListCreateTemplate'); var r = { @@ -55,10 +55,7 @@ var admin_task = function() { onSuccess : function() { var r = true; //return false if extension won't load for some reason (account config, dependencies, etc). - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/task.html',theseTemplates); - -//used for the delete confirmation dialog. -$('body').append("<div id='removeTaskConfirmModal' class='displayNone' title='Please confirm delete'><p><span class='ui-icon ui-icon-alert floatLeft marginRight marginBottom'></span>These tasks will be permanently deleted and cannot be recovered. Are you sure?</p></div>"); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/task.html',theseTemplates); //used for the add new modal. $('body').append("<div id='createTaskModal' class='displayNone' title='Create a new task'></div>"); @@ -69,7 +66,7 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } }, @@ -77,12 +74,12 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); onSuccess : function(tagObj){ //hideLoading is handled by the updateTaskList call $('#createTaskModal').dialog('close'); - app.u.throwMessage(app.u.successMsgObject("Your task has been created.")); + _app.u.throwMessage(_app.u.successMsgObject("Your task has been created.")); }, onError : function(tagObj){ //hideLoading is handled by the updateTaskList call tagObj.targetID = 'createTaskModal'; //sets where to put the error messages. - app.u.throwMessage(app.data[tagObj.datapointer]); + _app.u.throwMessage(_app.data[tagObj.datapointer]); } }, //adminTaskCreate @@ -91,16 +88,16 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); // this code will empty the table, so no need to do it before (means previous results will still show if an error occurs). updateTaskList : { onSuccess : function(tagObj){ - app.u.dump("BEGIN admin_task.callbacks.updateTaskList.onSuccess"); + _app.u.dump("BEGIN admin_task.callbacks.updateTaskList.onSuccess"); //limit the number of results. This is to keep the browser from crashing on HUGE tasks lists. var inc = 0; - var tasks = app.data[tagObj.datapointer]['@TASKS']; + var tasks = _app.data[tagObj.datapointer]['@TASKS']; var filteredTasks = new Array(); var L = tasks.length; for(var i = (L-1); i >= 0; i--) { - if(Number(tasks[i].completed_gmt) > 0 && (app.u.unixNow() - Number(tasks[i].completed_gmt)) > (60*60*24*3)){ - app.u.dump("completed more than three days ago"); + if(Number(tasks[i].completed_gmt) > 0 && (_app.u.epochNow() - Number(tasks[i].completed_gmt)) > (60*60*24*3)){ + _app.u.dump("completed more than three days ago"); } //don't include tasks completed more than a few days ago else { //tasks completed in the last 3 days do not count against the 100 task max. so the user gets 100 active tasks. @@ -114,11 +111,12 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); } tagObj.jqObj.hideLoading(); $("[data-app-role='dualModeListTbody']",tagObj.jqObj).empty().anycontent({'translateOnly':true,'data':{'@TASKS':filteredTasks}}); - app.u.handleButtons(tagObj.jqObj); + _app.u.handleButtons(tagObj.jqObj); + tagObj.jqObj.find("[data-app-click='admin|checkAllCheckboxesExec']").data('selected',false); }, onError : function(responseData, uuid) { - app.u.throwMessage(responseData); - $(app.u.jqSelector('#',app.ext.admin.vars.tab+"Content")).hideLoading(); + _app.u.throwMessage(responseData); + $(_app.u.jqSelector('#',_app.ext.admin.vars.tab+"Content")).hideLoading(); } } //updateTaskList @@ -132,16 +130,16 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); //This is how the task manager is opened. Just execute this function. // later, we may add the ability to load directly into 'edit' mode and open a specific task. not supported just yet. showTaskManager : function($target) { -// app.u.dump("BEGIN admin_task.a.showTaskManager"); - - $target.intervaledEmpty(); - var $DMI = app.ext.admin.i.DMICreate($target,{ +// _app.u.dump("BEGIN admin_task.a.showTaskManager"); + var $DMI = _app.ext.admin.i.DMICreate($target,{ 'header' : 'Task Manager', 'className' : 'taskManager', //applies a class on the DMI, which allows for css overriding for specific use cases. 'thead' : ['','Created','Task','Due Date','Priority','Type','Assigned To',''], //leave blank at end if last row is buttons. 'tbodyDatabind' : "var: tasks(@TASKS); format:processList; loadsTemplate:taskListRowTemplate;", - 'buttons' : ["<button data-app-event='admin|refreshDMI'>Refresh<\/button><button class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-plus' data-app-click='admin_task|adminTaskCreateShow'>Add Task<\/button>"], - 'controls' : "<span class='applyButtonset smallButton'>Modify Selected: <button data-app-click='admin_task|adminTaskCompletedBulkExec'>Tag as Completed</button><button data-app-click='admin_task|adminTaskRemoveBulkConfirm'>Deleted</button><\/span>", + 'buttons' : [ + "<button data-app-click='admin|refreshDMI' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowrefresh-1-s'>Refresh<\/button>", + "<button class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-plus' data-app-click='admin_task|adminTaskCreateShow'>Add Task<\/button>"], + 'controls' : "<button data-app-click='admin|checkAllCheckboxesExec' class='applyButton marginRight'>Select All<\/button><span class='applyButtonset smallButton'>Modify Selected: <button data-app-click='admin_task|adminTaskCompletedBulkExec'>Tag as Completed</button><button data-app-click='admin_task|adminTaskRemoveBulkConfirm'>Deleted</button><\/span>", 'cmdVars' : { '_cmd' : 'adminTaskList', 'limit' : '50', //not supported for every call yet. @@ -152,11 +150,10 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); } } }); - $("[data-app-role='dualModeContainer']:first",$target).anydelegate(); - app.model.dispatchThis('mutable'); - app.u.handleButtons($target); + _app.model.dispatchThis('mutable'); + _app.u.handleButtons($target.anyform()); $('.applyButtonset',$target).buttonset().off('change.handleModifyTasks').on('change.handleModifyTasks',function(){ - app.ext.admin_task.u.handleModifyTasks(this); + _app.ext.admin_task.u.handleModifyTasks(this); }); }, //showTaskManager @@ -168,13 +165,13 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); renderFormats : { taskClass : function($tag,data) { if(Number(data.value.completed_gmt)) { - if((app.u.unixNow() - Number(data.value.completed_gmt)) > (60*60*24*7)){$tag.addClass('displayNone')} //hide tasks that were completed more than a week ago. + if((_app.u.epochNow() - Number(data.value.completed_gmt)) > (60*60*24*7)){$tag.addClass('displayNone')} //hide tasks that were completed more than a week ago. else {} //do nothing. } else if(Number(data.value.due_gmt)) { - app.u.dump(" -> has a due date. Number(data.value.due_gmt) - app.u.unixNow(): "+(Number(data.value.due_gmt) - app.u.unixNow())); - if(app.u.unixNow() > Number(data.value.due_gmt)) {$tag.addClass('red');} //past due date. - else if ((Number(data.value.due_gmt) - app.u.unixNow()) < (60*60*24*2)){$tag.addClass('orange')} //due within 2 days. highlight. + _app.u.dump(" -> has a due date. Number(data.value.due_gmt) - _app.u.epochNow(): "+(Number(data.value.due_gmt) - _app.u.epochNow())); + if(_app.u.epochNow() > Number(data.value.due_gmt)) {$tag.addClass('red');} //past due date. + else if ((Number(data.value.due_gmt) - _app.u.epochNow()) < (60*60*24*2)){$tag.addClass('orange')} //due within 2 days. highlight. else {} //not past due or too close to due date. } else {} // no due data and not completed. do nothing. @@ -192,7 +189,8 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); e : { - + + adminTaskCreateShow : function($ele,p) { var $target = $('#createTaskModal'); //created as part of init process. @@ -201,11 +199,12 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); 'data' : {}, //pass empty data set so translation occurs and the loadsTemplate within this template gets run. 'showLoading' : false }); - $('form',$target).anydelegate({'trackEdits':true}).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); + _app.u.addEventDelegation($target); + $('form',$target).anyform({'trackEdits':true}).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); $('.datepicker',$target).datepicker({ 'dateFormat':'@', 'onClose' : function(dateText,object) { -// app.u.dump(" -> this:"); app.u.dump(this); +// _app.u.dump(" -> this:"); _app.u.dump(this); if(this.defaultValue == this.value) { //value did not change. } @@ -214,7 +213,7 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); } } }); //@ sets the format to epoch. - app.u.handleButtons($target); + _app.u.handleButtons($target); $target.dialog('open'); }, //adminTaskCreateShow @@ -222,7 +221,7 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); var $checked = $ele.closest("[data-app-role='dualModeContainer']").find(':checkbox:checked'); if($checked.length) { - app.ext.admin.i.dialogConfirmRemove({ + _app.ext.admin.i.dialogConfirmRemove({ "message" : "Are you sure you wish to delete "+$checked.length+" task(s)? There is no undo for this action.", "removeButtonText" : "Remove Tasks", //will default if blank "title" : "Remove "+$checked.length+" Task(s)", //will default if blank @@ -230,8 +229,8 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); $D.showLoading({"message":"Deleting "}); $checked.each(function(index){ var taskID = $(this).closest('[data-id]').data('id'); - if($(app.u.jqSelector('#','task_'+taskID).length)) { - var $panel = $(app.u.jqSelector('#','task_'+taskID)); + if($(_app.u.jqSelector('#','task_'+taskID).length)) { + var $panel = $(_app.u.jqSelector('#','task_'+taskID)); if($panel.is(':visible')) { $panel.slideUp('fast',function(){ $panel.remove(); @@ -241,7 +240,7 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); $panel.remove(); } } - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd':'adminTaskRemove', "taskid":taskID, "_tag" : { @@ -249,18 +248,19 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); //have a negative check here because having the function at the end of the line reads easier. callback : (index != ($checked.length - 1)) ? '' : function(rd){ $D.hideLoading(); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $D.anymessage({'message':rd}); } else { - $D.dialog('close') + $D.dialog('close'); + $ele.closest(".dualModeContainer").find("[data-app-click='admin|checkAllCheckboxesExec']").data('selected',false); //resets 'select all' button to false so a click selects everything. } } } },'immutable'); }); - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd' : 'adminTaskList', 'limit' : '50', //not supported for every call yet. '_tag' : { @@ -270,7 +270,7 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); 'jqObj' : $ele.closest("[data-app-role='dualModeContainer']") } },'immutable'); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); } }) @@ -286,9 +286,9 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); var $checked = $ele.closest("[data-app-role='dualModeContainer']").find(':checkbox:checked'); if($checked.length) { $checked.each(function(){ - app.model.addDispatchToQ({'_cmd':'adminTaskComplete',"taskid":$(this).closest('[data-id]').data('id')},'immutable'); + _app.model.addDispatchToQ({'_cmd':'adminTaskComplete',"taskid":$(this).closest('[data-id]').data('id')},'immutable'); }); - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd' : 'adminTaskList', 'limit' : '50', //not supported for every call yet. '_tag' : { @@ -298,7 +298,8 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); 'jqObj' : $ele.closest("[data-app-role='dualModeContainer']") } },'immutable'); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); + } else { $('#globalMessaging').anymessage({"message":"Please select at least on task from the list below for modification.",'errtype':'youerr'}); @@ -308,28 +309,28 @@ $('#createTaskModal').dialog({'autoOpen':false,'modal':true,'width':500}); adminTaskUpdateShow : function($ele,p) { var taskID = $ele.closest("[data-id]").data('id'); - $panel = app.ext.admin.i.DMIPanelOpen($ele,{ + $panel = _app.ext.admin.i.DMIPanelOpen($ele,{ 'templateID' : 'taskListEditPanelTemplate', 'panelID' : 'task_'+taskID, 'header' : 'Edit Task: '+taskID, 'data' : $ele.closest("[data-id]").data(), 'showLoading':false }); - $('form',$panel).anydelegate({'trackEdits':true}).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); + $('form',$panel).anyform({'trackEdits':true}).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); $('.datepicker',$panel).datepicker({ 'dateFormat':'@', 'onClose' : function(dateText,object) { -// app.u.dump(" -> this:"); app.u.dump(this); +// _app.u.dump(" -> this:"); _app.u.dump(this); if(this.defaultValue == this.value) { //value did not change. } else { this.value = (parseInt(this.value) / 1000); - $(this).addClass('edited').closest('form').anydelegate('updateChangeCounts'); + $(this).addClass('edited').closest('form').anyform('updateChangeCounts'); } } }); //@ sets the format to epoch. - app.u.handleButtons($panel); + _app.u.handleButtons($panel); } //adminTaskUpdateShow } //events diff --git a/extensions/admin/template_editor.html b/extensions/admin/template_editor.html index dcd2c915b..ee985404d 100644 --- a/extensions/admin/template_editor.html +++ b/extensions/admin/template_editor.html @@ -1,59 +1,43 @@ -<table id='templateEditorTemplate' class='fullWidth'> +<table id='templateEditorTemplate' class='fullWidth smallButton templateEditor'> <tr> - <td class='valignTop width75 ui-widget ui-widget-content ui-corner-all'> + <td class='valignTop width75 ui-widget ui-widget-content ui-corner-all'> <div class='stdPadding'> - <label class='site displayNone'> - <span>Choose Template</span> - <select name='templateSelector' class='site' data-app-role='siteTemplateSelect' data-app-event='admin_templateEditor|adminSiteTemplateEdit'> - <option value='' disabled="disabled" selected="selected">Choose Template</option> - </select> - </label> + + <div data-app-role='templateEditorSupplementalContent'></div><!-- used for the template editor to add mode specific content, if necessary. Site uses this. --> - <div data-app-role="ebayTemplateEditorIframeContainer"> - <textarea id='ebayTemplateHTMLTextarea' rows='10' class='fullWidth'></textarea> + <div data-app-role="templateEditorTextareaContainer"> + <textarea rows='10' data-app-role='templateEditorTextarea'></textarea> </div> + </div> </td> <td class='valignTop width20'> <div class='marginLeft'> <div class='buttonset ui-widget-content smallPadding alignRight marginBottom ui-corner-all'> - <!-- <button data-app-event="admin_templateEditor|adminTemplateCampaignExit">Exit</button> --> - - <button data-app-event="admin_templateEditor|adminTemplateCampaignTestShow" class='campaign'>Send Test</button> - <button data-app-event='admin_templateEditor|adminTemplateSaveExec' data-app-role='saveButton' class='ui-state-focus'>Save</button> + <button data-app-click="admin_template|adminTemplateEditorExit" title="Exit and do NOT save changes" class='applyButton' data-text='true' data-icon-primary='ui-icon-triangle-1-w'>Exit</button> + <button data-app-click="admin_template|adminTemplateCampaignTestShow" title="Save changes and send test." class='campaign applyButton' data-text='true' data-icon-primary='ui-icon-mail-closed'>Send Test</button> + <button data-app-click='admin_template|adminTemplateSaveExec' title="Save changes" data-app-role='saveButton' class='ui-state-focus applyButton' data-text='true'>Save</button> </div> <section class='ui-widget marginBottom' data-app-role='templateObjectInspectorContainer'> <h4>Object Inspector</h4> <!-- class='smallPadding ui-widget-header ui-corner-top' --> <div class=' labelsAsBreaks small clearfix'><!-- ui-widget-content ui-corner-bottom stdPadding clearfix --> - <div data-app-role='templateObjectInspectorContent'></div> - - <div class='ui-corner-none ui-widget-content marginTop marginBottom clearfix'></div> - - <h5>Highlight Elements</h5> - <!-- labels are in divs because the .show() applies a display:inline class. --> - <div class='marginTop clearfix ebay'><label data-app-role='highlightContainer_product'><input data-app-event="admin_templateEditor|templateHighlightToggle" type='checkbox' name='highlightProductAttributes' data-objecttype='PRODUCT' />Product<span class='toolTip' title="Toggle this on/off to enable/disable a highlight around the fields that will be dynamically populated with product data. Any content added inside these areas is likely to be lost when the product data is added.">?</span></label></div> - - <div class='clearfix campaign'><label data-app-role='highlightContainer_buyer'><input data-app-event="admin_templateEditor|templateHighlightToggle" type='checkbox' name='highlightBuyerAttributes' data-objecttype='BUYER' />Buyer<span class='toolTip' title="Toggle this on/off to enable/disable a highlight around the fields that will be dynamically populated with buyer data. Any content added inside these areas is likely to be lost when the buyer data is added.">?</span></label></div> - - <div class='clearfix'><label data-app-role='highlightContainer_wizard'><input data-app-event="admin_templateEditor|templateHighlightToggle" type='checkbox' name='highlightKISSAttributes' data-objecttype='KISS' />Wizard<span class='toolTip' title="Toggle this on/off to enable/disable a highlight around the fields that are editable through the Wizard. To edit, you can use the wizard or edit them directly in the HTML. Editing them in the HTML may cause the wizard to not work properly or save over your changes next time it loads.">?</span></label></div> - </div> </section> - <section class='ui-widget marginBottom'> + <section class='ui-widget marginBottom' data-templateeditor-role='wizardContainer'> <h4 class='smallPadding ui-widget-header ui-corner-top'>Wizard</h4> <div class='ui-widget-content ui-corner-bottom stdPadding'> <div data-app-role='wizardMessaging' class='small'></div> - <form id='wizardForm' action='#' onSubmit='return false;'> - <button data-app-event='admin_templateEditor|startWizardExec'>Start Wizard</button> + <form action='#' onSubmit='return false;' data-templateeditor-role='wizardForm' class='wizardForm'> + <button data-app-click='admin_template|startWizardExec' disabled='disabled' data-app-role='startWizardButton' class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-triangle-e'>Start Wizard</button> </form> @@ -61,12 +45,13 @@ <h4 class='smallPadding ui-widget-header ui-corner-top'>Wizard</h4> </section> - + <!-- + disabled for now due to tinymce integration <section class='ui-widget marginBottom campaign' data-app-role='templateEditorViewportChooser'> <h4 class='smallPadding ui-widget-header ui-corner-top'>Viewport Size</h4> <div class='ui-widget-content ui-corner-bottom stdPadding'> - <select name='viewport' class='small' data-app-event='admin_templateEditor|templateEditorIframeResizeExec'> + <select name='viewport' class='small' data-app-event='admin_template|templateEditorIframeResizeExec'> <option value='default'>default</option> <optgroup label='Amazon'> <option value='600x1024'>Kindle Fire 600x1024</option> @@ -75,7 +60,7 @@ <h4 class='smallPadding ui-widget-header ui-corner-top'>Viewport Size</h4> <optgroup label='Apple'> <option value='320x480'>iPhone, iPod Touch 320x480</option> - <option value='320x568' data-deviceclass='iphone5'>iPhone 5 320x568</option><!-- -19px for clock/battery bar --> + <option value='320x568' data-deviceclass='iphone5'>iPhone 5 320x568</option> <option value='768x1024'>iPad/Mini 768x1024</option> </optgroup> @@ -142,18 +127,18 @@ <h4 class='smallPadding ui-widget-header ui-corner-top'>Viewport Size</h4> <span class='toolTip' title="This feature is available to give you an idea of what your message will look like on a specific device. There may be device-specific display differences. Also, the pixel density on phones is higher than a computer, so the phone around your content is enlarged to reflect this.">?</span> - <button data-app-event='admin_templateEditor|templateEditorIframeRotateExec'>Rotate Orientation</button> + <button data-app-click='admin_template|templateEditorIframeRotateExec' class='applyButton'>Rotate Orientation</button> </div> </section> - + --> <section class='ui-widget marginBottom' data-app-role='templateEditorSaveAsTemplate'> <h4 class='smallPadding ui-widget-header ui-corner-top'>Save as Template</h4> <div class='ui-widget-content ui-corner-bottom stdPadding'> <p class='hint'>This will make a new template for use on other profiles</p> - <input name='template' id='templateName' value='' placeholder='template name' /> - <button data-app-event="admin_templateEditor|adminSaveAsTemplateExec">Save As New Template</button> + <input name='template' value='' placeholder='template name' /> + <button data-app-click="admin_template|adminSaveAsTemplateExec" class='applyButton' data-text='true' data-icon-primary='ui-icon-plus'>Save As New Template</button> </div> </section> @@ -175,14 +160,12 @@ <h4 class='smallPadding ui-widget-header ui-corner-top'>Save as Template</h4> <div id='templateChooserDetailTemplate'> <div class='marginBottom clearfix'> <div class='floatRight alignRight'> - <button class='smallButton' data-app-event='admin_templateEditor|templateChooserExec'>Choose</button><!-- - <button class='smallButton' data-app-event="admin|appChooserFork">Fork</button> - <button class='smallButton' data-app-event="admin|appChooserAppDownload">Download</button>--> + <button class='smallButton applyButton' data-app-click='admin_template|templateChooserExec' >Choose</button> </div> <h2 data-bind="var:template(SUBDIR); format:text;"></h2> </div> <div class='clearfix'> -<img border="0" src="" data-bind='var: template(@PREVIEWS); format:templateThumb; extension:admin_templateEditor;'> +<img border="0" src="" data-bind='var: template(@PREVIEWS); format:templateThumb; extension:admin_template;'> <p data-bind="var:template(%info.about); format:text;"></p> </div> </div> @@ -195,12 +178,6 @@ <h1>Choose a Template</h1> <ul data-bind="var: ebay(@TEMPLATES); format:processList; loadsTemplate:templateChooserItemTemplate;" class='listStyleNone clearfix'></ul> -<!-- -<li class='floatLeft marginRight ui-state-default ui-corner-bottom pointer' data-appid='b2b'> - <img src='app-b2b/preview-120x120.jpg' width='120' height='100' alt='Shadow' /> - <div>B 2 B</div> - </li> ---> </section> <section class='ui-widget ui-widget-content ui-corner-all stdPadding' id='appChooserDetailPanel' data-app-role='appPreviewPanel'> @@ -220,8 +197,8 @@ <h1>Choose a Template</h1> <ul> - <li id='templateChooserItemTemplate' class='floatLeft stdMargin small pointer' data-app-event='admin_templateEditor|templateChooserPreview'> - <img src='blank.gif' height='120' width='120' alt='' data-bind='var: template(@PREVIEWS); format:templateThumb; extension:admin_templateEditor;' /> + <li id='templateChooserItemTemplate' class='floatLeft stdMargin small pointer' data-app-click='admin_template|templateChooserPreview'> + <img src='blank.gif' height='120' width='120' alt='' data-bind='var: template(@PREVIEWS); format:templateThumb; extension:admin_template;' /> <div data-bind="var: template(SUBDIR); format:text;" class='lookLikeLink'></div> </li> </ul> @@ -263,7 +240,7 @@ <h1>Choose a Template</h1> <b>OR</b> <label> # Days - <input type='number' step='1' min='1' size='4' max='365' name='EXPIREDAYS' data-bind="var: campaign(EXPIREDAYS); format:popVal;" /> + <input type='number' class='smallInput' step='1' min='1' size='4' max='365' name='EXPIREDAYS' data-bind="var: campaign(EXPIREDAYS); format:popVal;" /> <span class='toolTip' title="The number of days this campaign is valid for.">?</span> </label> <p>Set either date/time OR # days</p> @@ -307,34 +284,6 @@ <h1>Choose a Template</h1> -<!-- - -EBAY SPECIFIC TEMPLATES - - ---> - - -<!-- used in the ebay template editor --> -<div id='ebayTemplateEditorImageUpload'> -<form id="ebayTemplateEditorImageUpload" class='clearfix marginBottom' name="ebayTemplateEditorImageUpload" action='#' method='post' enctype='multipart/form-data'> -<input type='hidden' name='filetype' value='IMAGES'> -<!-- adds the file upload area, which is in the media library templates --> -<h1 class='floatLeft'>Upload images for use in this template</h1> -<div data-bind="loadsTemplate: fileUploadTemplate; format: loadsTemplate;" class='marginTop'></div> -</form> -</div> - - - - -<ul> - <li id='ebayTemplateEditorMediaFileTemplate' class='lookLikeLink small floatLeft stdMargin'> - <img src='blank.gif' data-bind='var: media(path); format:publicURL; extension:admin;' width='75' height='75' alt='' /><br /> - <span data-bind="var:media(Name); format:text;" class='small' data-app-event="admin_syndication|ebayHTMLEditorAddImage"></span> - </li> -</ul> - diff --git a/extensions/admin/template_editor.js b/extensions/admin/template_editor.js index d732159c2..f950e6382 100644 --- a/extensions/admin/template_editor.js +++ b/extensions/admin/template_editor.js @@ -17,7 +17,7 @@ ************************************************************** */ -var admin_templateEditor = function() { +var admin_template = function(_app) { var theseTemplates = new Array('templateEditorTemplate'); @@ -37,14 +37,14 @@ var admin_templateEditor = function() { onSuccess : function() { var r = true; //return false if extension won't load for some reason (account config, dependencies, etc). //the list of templates in theseTemplate intentionally has a lot of the templates left off. This was done intentionally to keep the memory footprint low. They'll get loaded on the fly if/when they are needed. - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/template_editor.html',theseTemplates); - app.ext.admin_templateEditor.u.declareMagicFunctions(); //adds some global functions to the dom. shortcuts for template editing. + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/template_editor.html',theseTemplates); + _app.ext.admin_template.u.declareMagicFunctions(); //adds some global functions to the dom. shortcuts for template editing. return r; }, onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } //init }, //callbacks @@ -56,198 +56,154 @@ var admin_templateEditor = function() { a : { -//for mode = ebay, vars.profile is required. - showTemplateEditor : function(mode,vars) { + showTemplateEditor : function($target, vars){ vars = vars || {}; -// app.u.dump(" -> vars: "); app.u.dump(vars); - //will be false if it is not missing params - if(!app.ext.admin_templateEditor.u.missingParamsByMode(mode,vars)) { -//By here, we know that we have a valid mode and that any requirements in 'vars' based on the mode ARE present. + if($target instanceof jQuery) { + if(vars.mode) { + if(!_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars)) { +//everything that is necessary is now confirmed to be present. - var $D = $('#templateEditor'); - - if($D.length) { - $('#globalMessaging').anymessage({'message':'The template editor was already open for '+$D.data('mode')+'. That editor was closed'}) - //template editor has been opened before. nuke the template vars so nothing carries over. - $D.removeData('profile'); - $D.removeData('campaignid'); - $D.removeData('domain'); - $D.removeData('mode'); - $D.empty().remove(); - } - - - $D = $("<div \/>",{'id':'templateEditor','title':'Edit '+mode+' template'}).attr('data-app-role','templateEditor'); - +//make sure that no previous template editor data is on the target. + $target.removeData('profile campaignid domain mode'); + + var taID = 'textarea_'+_app.ext.admin_template.u.buildTemplateEditorID(vars); //added to textarea dynamically. if already on DOM, do no open another instance of editor. - vars.editor = 'inline'; //hard coded for now. may change later. support for dialog, fullscreen are also present. - var iframeHeight = 'auto'; - - if(vars.editor == 'inline') { - $(app.u.jqSelector('#',app.ext.admin.vars.tab+'Content')).empty().append($D); - iframeHeight = $(window).height() - $('#mastHead').height() - 100; - } - else if(vars.editor == 'fullscreen') { - $D.appendTo('body'); - $('#templateEditor').fullScreen({ - 'background' : '#ffffff', - 'callback' : function(state) {} - }); - iframeHeight = $(window).height() - 100; - } - else if (vars.editor == 'dialog') { -//must scroll to top of body/html first or issues with modal placement and lack of browser scrollbars. - $('html, body').animate({scrollTop:0}, 'fast'); - - $D.dialog({ - 'modal':true, - 'autoOpen':false, - 'width':'96%', - close: function(event, ui) { - $('body').css({'height':'auto','overflow':'auto'}) //bring browser scrollbars back. -//if the css editor was opened, close it. - if($('#templateEditorCSSDialog').length && $('#templateEditorCSSDialog').hasClass('ui-dialog-content')) { - $('#templateEditorCSSDialog').dialog('close'); + if(taID) { + var $textarea = $(_app.u.jqSelector('#',taID)); + if($textarea.length) { + $target.anymessage({"message":"You are attempting to open an instance of a template which is already open ("+_app.ext.admin_template.u.buildTemplateEditorTitle+") in "+($textarea.closest('.tabContent').data('section'))+". To reduce the likelyhood of inadvertantly saving over changes, only one copy of a template may be edited at a time.","errtype":"halt","persistent":true}); } - }, - open : function(event,ui) { - $('body').css({'height':'100%','overflow':'hidden'}) //get rid of browser scrollbars. - } - }); - $D.dialog("option", "position", "center"); - $D.dialog('option','height',($(window).height() - 100)); - - $D.dialog('open'); - + else { + //check to see if this editor has already been opened and, if so, remove instance. + //if a tinymce instance is opened and not properly removed, opening it again will not work. the 'exit' button in the editor does properly remove. + if(_app.u.thisNestedExists("tinymce.editors."+taID)){ + delete tinymce.editors[taID]; + }; + $target.prepend("<h1>"+_app.ext.admin_template.u.buildTemplateEditorTitle(vars)+"<\/h1>"); + $target.attr({'data-app-role':'templateEditor','data-templateeditor-role':'container','id':'TE_'+_app.ext.admin_template.u.buildTemplateEditorID(vars)}); + + $target.data(vars); //vars.profile is used in the media lib to get the profile. don't change it. + + $target.showLoading({"message":"Fetching template HTML"}); + var callback = function(rd){ + $target.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $target.anymessage({'message':rd}); + } + else { + _app.u.dump(' -> template contents obtained'); + //this is in the callback so that if the call fails, a blank/broken editor doesn't show up. + $target.anycontent({'templateID':'templateEditorTemplate','showLoading':false,'data':{}}); //pass in a blank data so that translation occurs for loads-template + $target.anyform(); + _app.u.addEventDelegation($target); + _app.u.handleCommonPlugins($target); + _app.u.handleButtons($target); + + var $objectInspector = $("[data-app-role='templateObjectInspectorContent']",$target), $textarea = $("textarea[data-app-role='templateEditorTextarea']:first",$target); + + $("[data-app-role='templateObjectInspectorContainer']",$target).anypanel({ + 'state' : 'persistent', + showClose : false, //set to false to disable close (X) button. + wholeHeaderToggle : true, //set to false if only the expand/collapse button should toggle panel (important if panel is draggable) + extension : 'template_editor', //used in conjunction w/ persist. + name : 'templateEditorObjectInspector', //used in conjunction w/ persist. + persistentStateDefault : 'collapse', + persistent : true + }); + + $textarea.attr('id',taID); + + // ### TODO -> here, if mode == site, a modified version of the editor needs to get run. each 'template' within the site get's it's own editor. Prob. put all these in an accordion. + // old. _app.ext.admin_template.u.handleTemplateModeSpecifics(vars.mode,vars,$iframeBody,$target); //needs to be after iframe is added to the DOM. + if(vars.mode == 'Site') { + $textarea.hide(); //the default text area isn't used. + _app.ext.admin_template.u.buildSupplementalSiteEditors($target,$(_app.ext.admin_template.u.preprocessTemplate(vars.mode,vars,_app.data[rd.datapointer]['body']))); + } + else { + $textarea.val(_app.ext.admin_template.u.preprocessTemplate(vars.mode,vars,_app.data[rd.datapointer]['body']).html()); + $textarea.show(); + $textarea.tinymce({ + init_instance_callback : function(editor) { + var $iframe = $("iframe:first",$(editor.getContentAreaContainer())); + var $iframeBody = $iframe.contents().find('body'); + var $meta = $iframeBody.find("meta[name='wizard']"); + if($meta.length >- 1) { + $("button[data-app-role='startWizardButton']:first").data('wizardContent',$meta.attr('content')).button('enable'); + } + else { + $("button[data-app-role='startWizardButton']:first").button('disable'); + } + _app.ext.admin_template.u.handleWizardObjects($iframeBody,$objectInspector); + }, + valid_children : "head[style|meta|base],+body[style|meta|base]", //,body[style|meta|base] -> this seems to cause some dropped lines after an inline 'style' + valid_elements: "*[*]", + esxtended_valid_elements : "@[class]", + menubar : 'edit insert view format table tools', + height : ($(document.body).height() - $('#mastHead').outerHeight() - 200), + visual: false, //turn off visual aids by default. menu choice will still show up. + keep_styles : true, + image_list: [], + plugins: [ + "_image _wizblocks advlist autolink lists link charmap print preview anchor", + "searchreplace visualblocks code fullscreen fullpage", //fullpage is what allows for the doctype, head, body tags, etc. + "media table contextmenu paste" + ], + toolbar: "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link _image | code" + }); + } - } - else { - $('#globalMessaging').anymessage({'message':'No editor mode passed.'}); - } + } + } //ends callback. - if(vars.editor) { - - - $D.data(vars); //vars.profile is used in the media lib to get the profile. don't change it. - $D.data('mode',mode); - - $D.showLoading({"message":"Fetching template HTML"}); - app.u.dump(' -> go get template contents '); - var callback = function(rd){ - $D.hideLoading(); - if(app.model.responseHasErrors(rd)){ - $D.anymessage({'message':rd}) - } - else { - app.u.dump(' -> template contents obtained'); - //this is in the callback so that if the call fails, a blank/broken editor doesn't show up. -// app.u.dump(" -> $D.length: "+$D.length); - $D.anycontent({'templateID':'templateEditorTemplate','showLoading':false,'data':{}}); //pass in a blank data so that translation occurs for loads-template -// app.u.dump(" -> $D.children().length: "+$D.children().length); app.u.dump($D); - - $("[data-app-role='templateObjectInspectorContainer']",$D).anypanel({ - 'state' : 'persistent', - showClose : false, //set to false to disable close (X) button. - wholeHeaderToggle : true, //set to false if only the expand/collapse button should toggle panel (important if panel is draggable) - extension : 'template_editor', //used in conjunction w/ persist. - name : 'templateEditorObjectInspector', //used in conjunction w/ persist. - persistentStateDefault : 'collapse', - persistent : true - }); - var $objectInspector = $("[data-app-role='templateObjectInspectorContent']",$D); + var cmdObj = { + '_cmd':'admin'+vars.mode+'FileContents', + 'FILENAME' : 'index.html', + '_tag' : { + 'callback' : callback + } + } + + if(vars.mode == 'EBAYProfile') { + cmdObj.PROFILE = vars.profile; + cmdObj._tag.datapointer = 'adminEBAYProfileFileContents|'+vars.profile; + } + else if(vars.mode == 'Campaign') { + cmdObj.CAMPAIGNID = vars.campaignid; + cmdObj._tag.datapointer = 'adminCampaignFileContents|'+vars.campaignid; + } + else if(vars.mode == 'Site') { + cmdObj.DOMAIN = vars.domain; + cmdObj._tag.datapointer = 'adminSiteFileContents|'+vars.domain; + } + else { + } //should never get this far. the if check at the top verifies valid mode. This is just a catch all. - var toolbarButtons = app.ext.admin.u.buildToolbarForEditor([ - "|", - app.ext.admin_templateEditor.u.getEditorButton_imageadd(), - app.ext.admin_templateEditor.u.getEditorButton_image() - ]); - -//handle some mode specifics. - $('.ebay, .campaign, .site').hide(); // hide all 'specifics' by default. show as needed. - if(mode == 'EBAYProfile') { - toolbarButtons.push("|"); - toolbarButtons.push(app.ext.admin_templateEditor.u.getEditorButton_prodattributeadd()) - $(".ebay",$D).show(); - } - if(mode == 'Site') { - toolbarButtons.push("|"); - $(".site",$D).show(); - } - else if(mode == 'Campaign') { - toolbarButtons.push("|"); - toolbarButtons.push(app.ext.admin_templateEditor.u.getEditorButton_style()); - toolbarButtons.push("|"); - toolbarButtons.push(app.ext.admin_templateEditor.u.getEditorButton_buyerattributeadd()); - toolbarButtons.push("|"); - toolbarButtons.push(app.ext.admin_templateEditor.u.getEditorButtonNativeApp()); - $(".campaign",$D).show(); + _app.model.addDispatchToQ(cmdObj,'mutable'); + _app.model.dispatchThis('mutable'); + } - else {} -// app.u.dump(" -> toolbarButtons: "); app.u.dump(toolbarButtons); - - - $("textarea:first",$D) - .show() - .width('95%') - .height($D.height() - 100) - .css('width','95%') - .val(app.ext.admin_templateEditor.u.preprocessTemplate(mode,vars,app.data[rd.datapointer]['body'])) - .htmlarea({ - // Override/Specify the Toolbar buttons to show - toolbar: toolbarButtons // - }); - - - // event needs to be delegated to the body so that toggling between html and design mode don't drop events and so that newly created events are eventful. - $("div.jHtmlArea, div.ToolBar",$D).width('97%'); //having issue with toolbar collapsing. - var $iframeBody = $('iframe',$D).width('97%').height(iframeHeight).contents().find('body'); - app.ext.admin_templateEditor.u.handleWizardObjects($iframeBody,$objectInspector); - - app.ext.admin_templateEditor.u.handleTemplateModeSpecifics(mode,vars,$iframeBody); //needs to be after iframe is added to the DOM. - - app.u.handleAppEvents($D); - $('.toolTip',$D).tooltip(); } - } - - var cmdObj = { - '_cmd':'admin'+mode+'FileContents', - 'FILENAME' : 'index.html', - '_tag' : { - 'callback' : callback + else { + //to get here, taID is false. buildTemplateEditorID will handle the error display. } } - - if(mode == 'EBAYProfile') { - cmdObj.PROFILE = vars.profile; - cmdObj._tag.datapointer = 'adminEBAYProfileFileContents|'+vars.profile; - } - else if(mode == 'Campaign') { - cmdObj.CAMPAIGNID = vars.campaignid; - cmdObj._tag.datapointer = 'adminCampaignFileContents|'+vars.campaignid; - } - else if(mode == 'Site') { - cmdObj.DOMAIN = vars.domain; - cmdObj._tag.datapointer = 'adminSiteFileContents|'+vars.domain; - } - else { - } //should never get this far. the if check at the top verifies valid mode. This is just a catch all. - - app.model.addDispatchToQ(cmdObj,'mutable'); - app.model.dispatchThis('mutable'); + else { + $target.anymessage({"message":"In admin_template.a.showTemplateEditor, "+_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars),"gMessage":true}); + } + } + else { + $target.anymessage({"message":"In admin_template.a.showNewTemplateEditor, vars.mode was not set and it is required","gMessage":true}) } - } else { - $('#globalMessaging').anymessage({"message":"In admin_templateEditor.a.showTemplateEditor, "+app.ext.admin_templateEditor.u.missingParamsByMode(mode,vars),"gMessage":true}); - } - - }, //showTemplateEditor + $('#globalMessaging').anymessage({"message":"In admin_template.a.showNewTemplateEditor, $target was not a valid jquery instance.","gMessage":true}) + } + }, showTemplateChooserInModal : function(vars) { vars = vars || {}; - if(!app.ext.admin_templateEditor.u.missingParamsByMode(vars.mode,vars)) { + if(!_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars)) { var dialogObject = {'showLoading':false}; vars._cmd = 'admin'+vars.mode+'TemplateList'; @@ -265,9 +221,8 @@ var admin_templateEditor = function() { } else {} //shouldn't get here. - var $D = app.ext.admin.i.dialogCreate(dialogObject); //using dialogCreate ensures that the div is 'removed' on close, clearing all previously set data(). - $D.attr('id','templateChooser').data(vars); - $D.dialog('open'); + var $D = _app.ext.admin.i.dialogCreate(dialogObject); //using dialogCreate ensures that the div is 'removed' on close, clearing all previously set data(). + $D.attr('id','templateChooser').data(vars).anyform().dialog('open'); $D.showLoading(); vars._tag = { @@ -277,39 +232,31 @@ var admin_templateEditor = function() { 'jqObj' : $D } - if(app.model.fetchData(vars._tag.datapointer)) { - app.u.handleCallback(vars._tag); + if(_app.model.fetchData(vars._tag.datapointer)) { + _app.u.handleCallback(vars._tag); } else { -// app.u.dump(" vars: "); app.u.dump(vars); - app.model.addDispatchToQ(vars,'mutable'); - app.model.dispatchThis('mutable'); +// _app.u.dump(" vars: "); _app.u.dump(vars); + _app.model.addDispatchToQ(vars,'mutable'); + _app.model.dispatchThis('mutable'); } -/* $D.imagegallery({ - selector: 'a[data-gallery="gallery"]', - show: 'fade', - hide: 'fade', - fullscreen: false, - slideshow: false - }); -*/ -// app.u.dump(" -> $D.data()"); app.u.dump($D.data()); - app.u.handleAppEvents($D); + + } else { - $('#globalMessaging').anymessage({"message":"In admin_syndication.a.showTemplateChooserInModal, "+app.ext.admin_templateEditor.u.missingParamsByMode(vars.mode,vars)+".","gMessage":true}); + $('#globalMessaging').anymessage({"message":"In admin_marketplace.a.showTemplateChooserInModal, "+_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars)+".","gMessage":true}); } }, //showTemplateChooserInModal - initWizard : function() { - var $wizardForm = $('#wizardForm'); + initWizard : function($wizardForm) { + //the success fieldset, which is last in the list. $wizardForm.find('fieldset:last').after("<fieldset class='wizardCompleted' class='displayNone'>Congrats! You have completed the wizard for this template.<\/fieldset>"); var $fieldsets = $('fieldset',$wizardForm), - $templateEditor = $('#templateEditor'), //referenced for context on multiple occasions. + $templateEditor = $wizardForm.closest("[data-templateeditor-role='container']"), //referenced for context on multiple occasions. $iframeBody = $('iframe',$templateEditor).contents().find('body'); @@ -340,12 +287,12 @@ var admin_templateEditor = function() { //handles the wizard nav button click events (and any other buttons we add later will get controlled here too) $wizardForm.off('click.templatewizard').on('click.templatewizard',function(e){ -// app.u.dump("Click registered in the wizard panel"); +// _app.u.dump("Click registered in the wizard panel"); var $target = $(e.target); //the element that was clicked. -// app.u.dump(" -> $target.is('button'): "+$target.is('button')); -// app.u.dump(" -> $target.data('button-action'): "+$target.data('button-action')); -// app.u.dump(" -> e.target.nodeNam: "+e.target.nodeNam); +// _app.u.dump(" -> $target.is('button'): "+$target.is('button')); +// _app.u.dump(" -> $target.data('button-action'): "+$target.data('button-action')); +// _app.u.dump(" -> e.target.nodeNam: "+e.target.nodeNam); //in chrome, the click event is triggered on the child span of the button, not the button itself. if(e.target.nodeName.toLowerCase() == 'span' && $target.parent().hasClass('ui-button')) { @@ -353,17 +300,17 @@ var admin_templateEditor = function() { } if($target.is('button') && $target.data('button-action')) { -// app.u.dump(" -> click is on a button"); +// _app.u.dump(" -> click is on a button"); e.preventDefault(); //disable the default action. -// app.u.dump(" -> $target.data('button-action'): "+$target.data('button-action')); +// _app.u.dump(" -> $target.data('button-action'): "+$target.data('button-action')); $target.data('button-action') == 'previous' ? $('fieldset:visible',$wizardForm).hide().prev('fieldset').show() : $('fieldset:visible',$wizardForm).hide().next('fieldset').show(); var $focusFieldset = $('fieldset:visible',$wizardForm); fieldsetVerifyAndExecOnfocus($focusFieldset); -app.u.dump(" -> $focusFieldset.index(): "+$focusFieldset.index()); +_app.u.dump(" -> $focusFieldset.index(): "+$focusFieldset.index()); //SANITY -> index() starts at 1, not zero. if($focusFieldset.index() == 1) { $("[data-button-action='next']",$wizardForm).button('enable'); @@ -384,11 +331,45 @@ app.u.dump(" -> $focusFieldset.index(): "+$focusFieldset.index()); }, 'complete' : function(){} }).parent().css({top:'-13px','position':'relative'}); - app.ext.admin_templateEditor.u.handleWizardProgressBar($("[data-app-role='progressBar']",$templateEditor)); + _app.ext.admin_template.u.handleWizardProgressBar($("[data-app-role='progressBar']",$templateEditor)); } }); - } //initWizard - + }, //initWizard + + invoiceEditor : function($target,params) { + $target.addClass('ui-widget'); + var $textarea = $("<textarea \/>").val("<b>Some Content</b>").appendTo($target); + //will need to make a resource call here and then load this as the callback, putting the body of the resource into the textarea. + var $buttonset = $("<div \/>").addClass('buttonset alignRight smallPadding ui-widget-content'); + $("<button \/>").text('Cancel Changes').button().on('click',function(){ + navigateTo("#!ext.admin_template.invoiceEditor"); + }).appendTo($buttonset); + + $("<button \/>").text('Save Changes').button().on('click',function(){ + // ### TODO -> + }).appendTo($buttonset); + + $buttonset.prependTo($target); //add this to DOM after all the buttons have been added. minimized DOM updates. + + $textarea.tinymce({ + valid_children : "head[style|meta|base],+body[style|meta|base]", //,body[style|meta|base] -> this seems to cause some dropped lines after an inline 'style' + valid_elements: "*[*]", + extended_valid_elements : "@[class]", + menubar : 'edit insert view format table tools', + height : ($(document.body).height() - $('#mastHead').outerHeight() - 200), + visual: false, //turn off visual aids by default. menu choice will still show up. + keep_styles : true, + image_list: [], + plugins: [ + "_image advlist autolink lists link charmap print preview anchor", + "searchreplace visualblocks code fullscreen fullpage", //fullpage is what allows for the doctype, head, body tags, etc. + "media table contextmenu paste" + ], + toolbar: "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link _image | code" + }); + + } + }, //Actions //////////////////////////////////// RENDERFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ @@ -397,10 +378,11 @@ app.u.dump(" -> $focusFieldset.index(): "+$focusFieldset.index()); //on a data-bind, format: is equal to a renderformat. extension: tells the rendering engine where to look for the renderFormat. //that way, two render formats named the same (but in different extensions) don't overwrite each other. renderFormats : { - templateThumb : function($tag,data) { - $tag.attr('src',"data:"+data.value[0].type+";base64,"+data.value[0].base64); - $tag.wrap("<a href='data:"+data.value[0].type+";base64,"+data.value[0].base64+"' >"); //data-gallery='gallery' - } + templateThumb : function($tag,data) { + $tag.attr('src',"data:"+data.value[0].type+";base64,"+data.value[0].base64); + $tag.wrap("<a href='data:"+data.value[0].type+";base64,"+data.value[0].base64+"' >"); //data-gallery='gallery' + } + }, //renderFormats @@ -419,49 +401,57 @@ app.u.dump(" -> $focusFieldset.index(): "+$focusFieldset.index()); missingParamsByMode : function(mode,data) { var r = false; if(mode && !$.isEmptyObject(data)) { - if($.inArray(mode,app.ext.admin_templateEditor.vars.templateModes) > -1) { + if($.inArray(mode,_app.ext.admin_template.vars.templateModes) > -1) { if(mode == 'EBAYProfile' && !data.profile) { - r = "In admin_templateEditor.u.missingParamsByMode, mode set to EBAYProfile but no profile passed." + r = "In admin_template.u.missingParamsByMode, mode set to EBAYProfile but no profile passed." } else if(mode == 'Site' && !data.domain) { - r = "In admin_templateEditor.u.missingParamsByMode, mode set to Site but no domain passed." + r = "In admin_template.u.missingParamsByMode, mode set to Site but no domain passed." } else if(mode == 'Campaign' && !data.campaignid) { - r = "In admin_templateEditor.u.missingParamsByMode, mode set to Campaign but no campaignid passed." + r = "In admin_template.u.missingParamsByMode, mode set to Campaign but no campaignid passed." } else { //Success. } } else { - r = "In admin_templateEditor.u.missingParamsByMode, Invalid mode ["+mode+"] passed." + r = "In admin_template.u.missingParamsByMode, Invalid mode ["+mode+"] passed." } } else { - r = "In admin_templateEditor.u.missingParamsByMode, no mode passed or data was empty." + r = "In admin_template.u.missingParamsByMode, no mode passed or data was empty." } return r; }, //adds some global functions for easy reference from the supporting html file for the wizard declareMagicFunctions : function() { - + +// NOTE -> the way the magic functions were originally written there was only one instance open at a time, so 'instance' was not pertinent, there was only 1. +// now, however, there are (potentially) more than one open at a time, so we get the instance within the tab in focus. If a dialog or 'full screen' version of this are ever available, we'll need to rethink magic. +// getContext was created so that, down the road, when a better method is available, it'll be easy to search and replace or to update. +//also, media library (search for kissTemplate) uses a selector similar to this. + function getContext() { + return $("[data-templateeditor-role='container']",_app.u.jqSelector('#',_app.ext.admin.vars.tab+'Content')); + } function getTarget(selector,functionName){ -// app.u.dump("getTarget selector: "+selector); +// _app.u.dump("getTarget selector: "+selector); var r = false if(selector) { + var $templateEditor = getContext(); //jqSelector doesn't play well using : or [ as first param. - var $target = $('iframe',$('#templateEditor')).contents().find((selector.indexOf('#') == 0 || selector.indexOf('.') == 0) ? app.u.jqSelector(selector.charAt(0),selector.substring(1)) : app.u.jqSelector("",selector)); + var $target = $('iframe',$templateEditor).contents().find((selector.indexOf('#') == 0 || selector.indexOf('.') == 0) ? _app.u.jqSelector(selector.charAt(0),selector.substring(1)) : _app.u.jqSelector("",selector)); if($target.length) { r = $target; } else { - $("[data-app-role='wizardMessaging']",$('#templateEditor')).anymessage({'message':'The element selector ['+selector+'] passed into '+functionName+' does not exist within the template. This is likely the result of an error in the wizard.js file.'}); + $("[data-app-role='wizardMessaging']",$templateEditor).anymessage({'message':'The element selector ['+selector+'] passed into '+functionName+' does not exist within the template. This is likely the result of an error in the wizard.js file.'}); } } else { - $("[data-app-role='wizardMessaging']",$('#templateEditor')).anymessage({'message':'No element selector passed into '+functionName+'. This is likely the result of an error in the wizard.js file.'}); + $("[data-app-role='wizardMessaging']",$templateEditor).anymessage({'message':'No element selector passed into '+functionName+'. This is likely the result of an error in the wizard.js file.'}); } return r; } @@ -474,30 +464,30 @@ app.u.dump(" -> $focusFieldset.index(): "+$focusFieldset.index()); //This function will populate the hidden input with a csv of product once the 'apply' button in the picker is pushed. window.magic.conjureProduct = function(ID){ -var $D = app.ext.admin.i.dialogCreate({ +var $D = _app.ext.admin.i.dialogCreate({ 'title' : 'Select Product' }); -var $input = $(app.u.jqSelector('#',ID)); -//app.u.dump(" -> app.u.jqSelector('#',ID): "+app.u.jqSelector('#',ID)); -//app.u.dump(" -> $input.length: "+$input.length); +var $input = $(_app.u.jqSelector('#',ID)); +//_app.u.dump(" -> _app.u.jqSelector('#',ID): "+_app.u.jqSelector('#',ID)); +//_app.u.dump(" -> $input.length: "+$input.length); - $("<form>").append($("<fieldset data-app-role='pickerContainer'>").append(app.ext.admin.a.getPicker({'templateID':'pickerTemplate','mode':'product'}))).appendTo($D); + $("<form>").append($("<fieldset data-app-role='pickerContainer'>").append(_app.ext.admin.a.getPicker({'templateID':'pickerTemplate','mode':'product'}))).appendTo($D); $D.dialog({ buttons: [ { text: "Apply Product", click: function() { $D.showLoading({'message':'Fetching product list'}); - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd':'appProductSelect', - 'product_selectors' : app.ext.admin_tools.u.pickerSelection2KVP($('form:first',$D)), + 'product_selectors' : _app.ext.admin_tools.u.pickerSelection2KVP($('form:first',$D)), '_tag': { 'datapointer' : 'appProductSelect', 'callback' : function(rd) { $D.hideLoading(); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $D.anymessage({'message':rd}); } else { - if(app.data[rd.datapointer] && app.data[rd.datapointer]['@products'] && app.data[rd.datapointer]['@products'].length) { - $input.val(app.data[rd.datapointer]['@products'].join()); + if(_app.data[rd.datapointer] && _app.data[rd.datapointer]['@products'] && _app.data[rd.datapointer]['@products'].length) { + $input.val(_app.data[rd.datapointer]['@products'].join()); $input.triggerHandler("change"); //runs focus event w/out bringing 'focus' to input. $D.dialog('close'); } @@ -508,7 +498,7 @@ var $input = $(app.u.jqSelector('#',ID)); } } },'mutable'); - app.model.dispatchThis('mutable'); + _app.model.dispatchThis('mutable'); }}]}); $D.dialog('open'); @@ -522,38 +512,31 @@ var $input = $(app.u.jqSelector('#',ID)); if(vars.templateID) { // $target.append("<br><h2>JT WAS HERE</h2><br>"); - var $prodlistTemplate = $(app.u.jqSelector('#',vars.templateID)); + var $prodlistTemplate = $(_app.u.jqSelector('#',vars.templateID)); if($prodlistTemplate.length) { - - - //success content goes here. - $target = getTarget(selector,'magic.prodlist'); //have to redeclare target. 'focus' of target in iframe was getting lost. for expediency's sake, this was quickest solution. -// app.u.dump("$target.length: "+$target.length); + //success content goes here. + $target = getTarget(selector,'magic.prodlist'); //have to redeclare target. 'focus' of target in iframe was getting lost. for expediency's sake, this was quickest solution. +// _app.u.dump("$target.length: "+$target.length); // $target.append("<br><h2>And Here Too!</h2><br>"); - if(prodlist) { - - var $prodlistContainer = $prodlistTemplate.clone(); -// app.u.dump(" -> $prodlistContainer.length: "+$prodlistContainer.length); - $prodlistContainer.attr('id','WIZ_PL_'+app.u.guidGenerator().substring(0,10)); //change the ID so it's unique. - $prodlistContainer.appendTo($target); - - $prodlistContainer.anycontent({'data':{'@products':prodlist}}); - } - else { - $D.anymessage({'message':'Your selectors returned zero product.'}); - } - - - - + if(prodlist) { + var $prodlistContainer = $prodlistTemplate.clone(); +// _app.u.dump(" -> $prodlistContainer.length: "+$prodlistContainer.length); + $prodlistContainer.attr('id','WIZ_PL_'+_app.u.guidGenerator().substring(0,10)); //change the ID so it's unique. + $prodlistContainer.appendTo($target); + + $prodlistContainer.anycontent({'data':{'@products':prodlist}}); + } + else { + $D.anymessage({'message':'Your selectors returned zero product.'}); + } } else { - $("[data-app-role='wizardMessaging']",$('#templateEditor')).anymessage({'message':'vars.templateID was passed into magic.prodlist but element does not exist on the DOM.'}); + $('#globalMessaging').anymessage({'message':'vars.templateID was passed into magic.prodlist but element does not exist on the DOM.'}); } } else { - $("[data-app-role='wizardMessaging']",$('#templateEditor')).anymessage({'message':'vars.templateID was not passed into magic.prodlist.'}); + $('#globalMessaging').anymessage({'message':'vars.templateID was not passed into magic.prodlist.'}); } } //magic.prodlist @@ -579,9 +562,10 @@ var $input = $(app.u.jqSelector('#',ID)); //selector is an element within the wizard itself. window.magic.inspect = function(selector) { var $target = getTarget(selector,'magic.inspect'); + var $templateEditor = getContext(); r = null; if($target) { - app.ext.admin_templateEditor.u.showObjectInInspector($target,$("[data-app-role='templateObjectInspectorContent']",$('#templateEditor'))); + _app.ext.admin_template.u.showObjectInInspector($target,$("[data-app-role='templateObjectInspectorContent']",$templateEditor)); r = $target; } else {} //getTarget handles error display. @@ -591,8 +575,8 @@ var $input = $(app.u.jqSelector('#',ID)); window.magic.medialib = function(ID) { var $target = getTarget(ID,'magic.medialib'); if($target) { - app.ext.admin_medialib.a.showMediaLib({ - 'imageID':app.u.jqSelector('#',ID.substring(1)), + _app.ext.admin_medialib.a.showMediaLib({ + 'imageID':_app.u.jqSelector('#',ID.substring(1)), 'mode':'kissTemplate'//, // 'src':$target.data('filepath') //doesn't work like we want. uses some legacy UI code. }); //filepath is the path of currently selected image. oldfilepath may also be set. @@ -603,11 +587,11 @@ var $input = $(app.u.jqSelector('#',ID)); //gets run when a fieldset in the wizard is loaded. Will check the value on all fieldset inputs for data-target (which should be a selector) and will check to make sure it exists in the template itself. //if one failure occurs, the entire panel is locked. The user can still proceed forward and backward through the rest of the editor. window.magic.fieldset_verify = function($fieldset) { - app.u.dump("BEGIN fieldset_verify"); + _app.u.dump("BEGIN fieldset_verify"); var numMatchedSelectors = 0; //what is returned if pass is false. will increment w/ the length of each data-target.length var pass = true; if($fieldset instanceof jQuery) { -// app.u.dump(" -> $('[data-target]',$fieldset).length: "+$("[data-target]",$fieldset).length); +// _app.u.dump(" -> $('[data-target]',$fieldset).length: "+$("[data-target]",$fieldset).length); $("[data-target]",$fieldset).each(function(){ var $target = getTarget($(this).data('target'),'magic.exists'); if($target) { @@ -623,16 +607,16 @@ var $input = $(app.u.jqSelector('#',ID)); } } //woot! all elements are in the template. else { - app.u.dump(" -> a fail occurd in magic.verify"); + _app.u.dump(" -> a fail occurd in magic.verify"); $('select, textarea, input',$fieldset).attr('disabled','disabled'); //unable to find all selectors, so disable entire panel. $('button',$fieldset).prop('disabled','disabled'); //expand later to check for ui-button and handle them differently. } //do nothing, } else { pass = false; - $("[data-app-role='wizardMessaging']",$('#templateEditor')).anymessage({'message':'Invalid fieldset ['+($fieldset instanceof jQuery)+'] not passed into magic.exists.'}); + $("#globalMessaging").anymessage({'message':'Invalid fieldset ['+($fieldset instanceof jQuery)+'] not passed into magic.exists.'}); } - app.u.dump(" -> verify pass: "+pass); + _app.u.dump(" -> verify pass: "+pass); return (pass === true) ? r : 0; } @@ -673,7 +657,7 @@ var $input = $(app.u.jqSelector('#',ID)); break; default: - $("[data-app-role='wizardMessaging']",$('#templateEditor')).anymessage({'message':'Method ['+method+'] passed into magic.modify passed validation but is not declared in switch.','gMessage':true}); + $("#globalMessaging").anymessage({'message':'Method ['+method+'] passed into magic.modify passed validation but is not declared in switch.','gMessage':true}); } @@ -681,20 +665,22 @@ var $input = $(app.u.jqSelector('#',ID)); else {} //getTarget handles error display. } else { - $("[data-app-role='wizardMessaging']",$('#templateEditor')).anymessage({'message':'Invalid or blank method ['+method+'] passed into magic.modify. This is likely the result of an error in the wizard.js file.'}); + $("#globalMessaging").anymessage({'message':'Invalid or blank method ['+method+'] passed into magic.modify. This is likely the result of an error in the wizard.js file.'}); } } } - }, + + }, //declareMagicFunctions //updates the progress bar based on the number of fieldsets and the index of the fieldset in view (yes, going backwards means progress bar regresses) handleWizardProgressBar : function($pbar) { if($pbar instanceof jQuery) { - var $fieldsets = $("fieldset",'#wizardForm'); + var $wizardForm = $pbar.closest("[data-templateeditor-role='wizardContainer']").find("form[data-templateeditor-role='wizardForm']"); + var $fieldsets = $("fieldset",$wizardForm); if($fieldsets.length) { // * 201334 -> better handling if animation is in progress. //if the animation is in progress already, don't mess w/ it. let it wrap up, but adjust the progress. - var progress = Math.round((($("fieldset:visible",'#wizardForm').index() / $fieldsets.length ) * 100)); + var progress = Math.round((($("fieldset:visible",$wizardForm).index() / $fieldsets.length ) * 100)); if($pbar.is(':animated')) { $pbar.progressbar('option','value',progress); } @@ -710,56 +696,49 @@ var $input = $(app.u.jqSelector('#',ID)); } } else { - $('#globalMessaging').anymessage({'message':"In admin_templateEditor.u.handleWizardProgressBar, pbar ["+$pbar instanceof jQuery+"] is not a valid jquery object.",'gMessage':true}); + $('#globalMessaging').anymessage({'message':"In admin_template.u.handleWizardProgressBar, pbar ["+$pbar instanceof jQuery+"] is not a valid jquery object.",'gMessage':true}); } }, //delegates a click event on the template container which updates the object inspector w/ information about the clicked element. handleWizardObjects : function($iframeBody,$objectInspector) { +// _app.u.dump("$iframeBody.length: "+$iframeBody.length+" and $objectInspector.length: "+$objectInspector.length); if($iframeBody instanceof jQuery && $objectInspector instanceof jQuery) { - $iframeBody.on('click',function(e){ + $iframeBody.on('click.objectInspector',function(e){ var $target = $(e.target); - // app.u.dump(" -> $target.id: "+$target.attr('id')); - app.ext.admin_templateEditor.u.showObjectInInspector($target,$objectInspector); //updates object inspector when any element is clicked. + // _app.u.dump(" -> $target.id: "+$target.attr('id')); + _app.ext.admin_template.u.showObjectInInspector($target,$objectInspector); //updates object inspector when any element is clicked. }); } else { - $('#globalMessaging').anymessage({'message':"In admin_templateEditor.u.handleWizardProgressBar, either iframeBody ["+$iframeBody instanceof jQuery+"] or objectInspector ["+$objectInspector instanceof jQuery+"] were not valid jquery objects.",'gMessage':true}); + $('#globalMessaging').anymessage({'message':"In admin_template.u.handleWizardProgressBar, either iframeBody ["+$iframeBody instanceof jQuery+"] or objectInspector ["+$objectInspector instanceof jQuery+"] were not valid jquery objects.",'gMessage':true}); } }, -//adds some classes to the template. These classes are removed on save. - buildTemplateStyleSheet : function() { - var r = "<div id='templateBuilderCSS'>\n<style type='text/css'>\n" - + " .showHighlights_PRODUCT .attributeContainer_PRODUCT {background-color:#efefef; border:1px dashed #cccccc;}\n" //used on all non-href product elements -// + " .showHighlights_PRODUCT .actbHref {background-color:#00cc00; border:1px solid #cccccc;}\n" //used on product href elements. - + " .showHighlights_BUYER .attributeContainer_BUYER {background-color:#cee1cc; border:1px dashed #abc2a8;}\n" //used on all non-href product elements -// + " .showHighlights_BUYER .actbHref {background-color:#abc2a8; border:1px solid #abc2a8;}\n" //used on product href elements. - + " .showHighlights_KISS .wizardificated {background-color:#e2eee1; border:1px dashed #bdd1bd;}\n" - + " .showHighlights_KISS .unwizardificated {background-color:#f0f5fb; border:1px dashed #b9d6fc;}\n" - + "<\/style></div>" - return r; - }, //buildTemplateStyleSheet //removes the editor classes from the template. executed on save. postprocessTemplate : function(template,mode) { var $template = $("<html>"); //need a parent container. $template.append(template); - $('#templateBuilderCSS',$template).empty().remove(); + var $head = $("head",$template); + //move all meta and style tags from the body to the head where they belong. + $("body meta, body style",$template).each(function(){ + $(this).appendTo($head); + }) return $template.html(); }, //postprocessTemplate //This will add a style tag (classes) used by the editor. They're added to the template (stripped on save). // it will also add some classes on data-object elements. These stay (they do no harm) preprocessTemplate : function(mode,vars,template) { - app.u.dump("BEGIN admin_templateEditor.u.preprocessTemplate"); -// app.u.dump(" -> mode: "+mode); app.u.dump(" -> vars: "); app.u.dump(vars); + _app.u.dump("BEGIN admin_template.u.preprocessTemplate"); +// _app.u.dump(" -> mode: "+mode); _app.u.dump(" -> vars: "); _app.u.dump(vars); var $template = $("<html>"); //need a parent container. $template.append(template); if(mode == 'Site') { -// app.u.dump(" -> Is a Site template"); - $('base',$template).attr('href','http://www.'+vars.domain); //!!! this is temporary. Need a good solution for protocol and domain prefix/host. +// _app.u.dump(" -> Is a Site template"); + $('base',$template).attr('href','http://www.'+vars.domain); //### TODO -> this is temporary. Need a good solution for protocol and domain prefix/host. $('script',$template).remove(); //make sure the app template doesn't instantiate itself. } @@ -777,78 +756,126 @@ var $input = $(app.u.jqSelector('#',ID)); else {} //class has already been added. } }) - - $template.append(app.ext.admin_templateEditor.u.buildTemplateStyleSheet()) - return $template.html(); + + return $template; }, //preprocessTemplate - handleTemplateModeSpecifics : function(mode,vars,$iframeContents) { - if(!app.ext.admin_templateEditor.u.missingParamsByMode(mode,vars)) { - if($iframeContents instanceof jQuery) { - if(mode == 'Site') { - $("[data-app-role='saveButton']",$("#templateEditor")).text("Save Templates"); - $("[data-app-role='templateEditorSaveAsTemplate']",$('#templateEditor')).hide(); - $iframeContents.children().hide(); -//build the list of templates that are editable and update the select list. -// app.u.dump("# of wizards: "+$("[data-wizard]",$template).length); - var $select = $("[data-app-role='siteTemplateSelect']",$('#templateEditor')); - $("[data-wizard]",$iframeContents).each(function(){ - var $ele = $(this); - //create an MD5 for the contents of the element which can be used to compare later to see if any changes occured. - $select.append($("<option \/>").text($ele.data('wizard')).val($ele.data('wizard')).attr({'data-md5':Crypto.MD5($(app.u.jqSelector('#',$ele.attr('id')),$iframeContents).html()),'data-elementid':$ele.attr('id')})); - }) + +//$template is a jquery instance of the original template, BEFORE it's been added a text area. + buildSupplementalSiteEditors : function($templateEditor,$template) { + if($templateEditor instanceof jQuery && $template instanceof jQuery) { + var + $supp = $("[data-app-role='templateEditorSupplementalContent']:first",$templateEditor), + taID = 'textarea_'+_app.ext.admin_template.u.buildTemplateEditorID($templateEditor.data()); + if(taID) { + $("[data-wizard]",$template).each(function(){ + var $wizele = $(this); + $supp.append($("<h3 \/>").text($wizele.attr('data-wizard-title') || $wizele.data('wizard')).data('wizard',$wizele.data('wizard'))); + //create an MD5 for the contents of the element which can be used to compare later to see if any changes occured. + var $textarea = $("<textarea \/>",{'id':taID+"_"+$wizele.data('wizard')}).attr({ + 'data-md5':Crypto.MD5($wizele.html()), + 'data-elementid':$wizele.attr('id') + }).addClass('isTinymceTextarea').val($wizele.html()); //isTinymceTextarea is used as selector in 'exit'. + $supp.append($("<div \/>").append($textarea)); + }); + + if($supp.children().length) { + // #### TODO -> this needs to trigger the wizard. + //note -> could use tinymce.FocusEvent if need be. http://www.tinymce.com/wiki.php/api4:class.tinymce.FocusEvent + $supp.accordion({ + heightStyle: "content", + beforeActivate : function(event,ui) { + _app.u.dump("accordian beforeActivate. wizard: "+ui.newHeader.data('wizard')); + $("button[data-app-role='startWizardButton']:first",$(_app.u.jqSelector('#',_app.ext.admin.vars.tab+'Content'))).data('wizardContent','wizard-'+ui.newHeader.data('wizard')+'.html').button('enable'); + } + }); +// ### TODO -> need to trigger the beforeActivate code on the first header to enable the wizard button. + $("textarea",$supp).tinymce({ + init_instance_callback : function(editor) { + var $iframe = $("iframe:first",$(editor.getContentAreaContainer())); + var $iframeBody = $iframe.contents().find('body'); + _app.ext.admin_template.u.handleWizardObjects($iframeBody,$("[data-app-role='templateObjectInspectorContent']",$templateEditor)); + }, +// setup : function(editor) {editor.on('focus', function(e) {});editor.on('change', function(e) {});}, + valid_elements: "*[*]", +// extended_valid_elements : "@[class]", + menubar : 'edit insert view format table tools', + height : 200, + visual: false, //turn off visual aids by default. menu choice will still show up. + keep_styles : false, //for sites, no inline styles are allowed. + image_list: [], + plugins: [ + "_image _wizblocks advlist autolink lists link charmap print preview anchor", + "searchreplace visualblocks code fullscreen", + "media table contextmenu paste" + ], + toolbar: "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link _image | code" + }); + } + else { + $supp.anymessage({"message":"","errtype":"halt","persistent":true}); + } + } else { - $('#globalMessaging').anymessage({'message':'In admin_templateEditor.u.handleTemplateModeSpecifics, $iframeContents is not a valid jQuery instance ['+($iframeContents instanceof jQuery)+'].','gMessage':true}); + //taID didn't generate. builderTemplateEditorID will throw the error. } } else { - $('#globalMessaging').anymessage({'message':'In admin_templateEditor.u.handleTemplateModeSpecifics, '+app.ext.admin_templateEditor.u.missingParamsByMode(mode,vars),'gMessage':true}); + $('#globalMessaging').anymessage({'message':'In admin_template.u.handleSiteTemplateEditor, either $templateEditor ['+($templateEditor instanceof jQuery)+'] or $template ['+($template instanceof jQuery)+'] were not valid instances of jQuery.','gMessage':true}); } - //data-app-role='siteTemplateSelect' }, - summonWizard : function(filename) { - - $('#wizardForm').showLoading({"message":"Summoning Wizard..."}); - - var editorData = $('#templateEditor').data(); - var cmdObj = { - 'FILENAME':filename, - '_tag': { - 'datapointer' : 'admin'+editorData.mode+'FileContents|'+filename, - 'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ - $("[data-app-role='wizardMessaging']",$('#templateEditor')).anymessage({'message':rd}); - } - else { - $('#wizardForm').html(app.data[rd.datapointer].body) - app.ext.admin_templateEditor.a.initWizard(); + summonWizard : function($context,filename) { + if($context instanceof jQuery && filename) { + var $wizardForm = $("[data-templateeditor-role='wizardForm']",$context); + $wizardForm.showLoading({"message":"Summoning Wizard..."}); + + var editorData = $context.data(); + if(!_app.ext.admin_template.u.missingParamsByMode(editorData.mode,editorData)) { + var cmdObj = { + 'FILENAME':filename, + '_tag': { + 'datapointer' : 'admin'+editorData.mode+'FileContents|'+filename, + 'callback':function(rd){ + if(_app.model.responseHasErrors(rd)){ + $("[data-app-role='wizardMessaging']",$context).anymessage({'message':rd}); + } + else { + $wizardForm.html(_app.data[rd.datapointer].body) + _app.ext.admin_template.a.initWizard($wizardForm); + } + } } } + + if(editorData.mode == 'EBAYProfile') { + cmdObj._cmd = 'adminEBAYProfileFileContents' + cmdObj.PROFILE = editorData.profile + } + else if(editorData.mode == 'Campaign') { + cmdObj._cmd = 'adminCampaignFileContents' + cmdObj.CAMPAIGNID = editorData.campaignid + } + else if(editorData.mode == 'Site') { + cmdObj._cmd = 'adminSiteFileContents' + cmdObj.DOMAIN = editorData.domain + } + else { + //throw error. + } + + _app.model.addDispatchToQ(cmdObj,'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $context.anymessage({'message':'In admin_template.u.summonWizard, '+_app.ext.admin_template.u.missingParamsByMode(editorData.mode,editorData),'gMessage':true}); } - } - - if(editorData.mode == 'EBAYProfile') { - cmdObj._cmd = 'adminEBAYProfileFileContents' - cmdObj.PROFILE = editorData.profile - } - else if(editorData.mode == 'Campaign') { - cmdObj._cmd = 'adminCampaignFileContents' - cmdObj.CAMPAIGNID = editorData.campaignid - } - else if(editorData.mode == 'Site') { - cmdObj._cmd = 'adminSiteFileContents' - cmdObj.DOMAIN = editorData.domain } else { - //throw error. + $('#globalMessaging').anymessage({'message':'In admin_template.a.summonWizard, either $context is not a jquery instance ['+($context instanceof jQuery)+'] or filename ['+filename+'] was not passed.','gMessage':true}); } - - app.model.addDispatchToQ(cmdObj,'mutable'); - app.model.dispatchThis('mutable'); - }, @@ -887,7 +914,7 @@ var $input = $(app.u.jqSelector('#',ID)); else { //find closest parent data-object and display it's info. var $parentDataObject = $object.closest("[data-object]"); -// app.u.dump(" -> $parentDataObject.length: "+$parentDataObject.length); +// _app.u.dump(" -> $parentDataObject.length: "+$parentDataObject.length); if($parentDataObject.length) { $objectInspector.append("<h2>Parent Dynamic Element</h2>"); $objectInspector.append(getObjectData($parentDataObject)); @@ -896,39 +923,39 @@ var $input = $(app.u.jqSelector('#',ID)); } else { - $('#globalMessaging').anymessage({'message':"In admin_templateEditor.u.handleWizardProgressBar, either object ["+$object instanceof jQuery+"] or objectInspector ["+$objectInspector instanceof jQuery+"] were not valid jquery objects.",'gMessage':true}); + $('#globalMessaging').anymessage({'message':"In admin_template.u.handleWizardProgressBar, either object ["+$object instanceof jQuery+"] or objectInspector ["+$objectInspector instanceof jQuery+"] were not valid jquery objects.",'gMessage':true}); } }, //does not and SHOULD not dispatch. Allows this to be used w/ test in campaigns. - handleTemplateSave : function($D) { + handleTemplateSave : function($templateEditor) { - if($D instanceof jQuery) { - var mode = $D.data('mode'); - if(!app.ext.admin_templateEditor.u.missingParamsByMode(mode,$D.data())) { + if($templateEditor instanceof jQuery) { + var mode = $templateEditor.data('mode'); + if(!_app.ext.admin_template.u.missingParamsByMode(mode,$templateEditor.data())) { - $D.showLoading({'message':'Saving changes'}); + $templateEditor.showLoading({'message':'Saving changes'}); var docBody; if(mode == 'Site') { - var dp = 'adminSiteFileContents|'+$D.data('domain') - if(app.data[dp] && app.data[dp].body) { - var $oTemplate = $("<html>").html(app.data[dp].body); //the original instance of the template. + var dp = 'adminSiteFileContents|'+$templateEditor.data('domain') + if(_app.data[dp] && _app.data[dp].body) { + var $oTemplate = $("<html>").html(_app.data[dp].body); //the original instance of the template. - $("[data-app-role='siteTemplateSelect']",$('#templateEditor')).first().find('option').each(function(){ - var $option = $(this); - if($option.data('md5') && $option.data('elementid')) { - var $thisTemplate = magic.inspect(app.u.jqSelector('#',$option.data('elementid'))); -// app.u.dump(" -> $thisTemplate.length: "+$thisTemplate.length); -// app.u.dump(" -> old md5 : "+$option.data('md5')); -// app.u.dump(" -> new md5 : "+Crypto.MD5($thisTemplate.html())); + $("[data-app-role='templateEditorSupplementalContent']:first",$templateEditor).find('textarea').each(function(){ + var $te = $(this); + if($te.data('md5') && $te.data('elementid')) { + var $thisTemplate = magic.inspect(_app.u.jqSelector('#',$te.data('elementid'))); +// _app.u.dump(" -> $thisTemplate.length: "+$thisTemplate.length); +// _app.u.dump(" -> old md5 : "+$option.data('md5')); +// _app.u.dump(" -> new md5 : "+Crypto.MD5($thisTemplate.html())); $thisTemplate.css('display',''); //the editor uses show/hide which adds inline styles. These need to be removed. if(!$thisTemplate.attr('style')) { $thisTemplate.removeAttr('style'); //if no styles are set, remove the empty tag. that way the md5 'should' match if no change occured. } - if(Crypto.MD5($thisTemplate.html()) != $option.data('md5')) { - app.u.dump(" -> save occuring for element "+$option.data('elementid')); - $(app.u.jqSelector('#',$option.data('elementid')),$oTemplate).replaceWith($thisTemplate); + if(Crypto.MD5($thisTemplate.html()) != $te.data('md5')) { + _app.u.dump(" -> save occuring for element "+$option.data('elementid')); + $(_app.u.jqSelector('#',$option.data('elementid')),$oTemplate).replaceWith($thisTemplate); } } else {} //no md5 set. probably the default 'choose'; @@ -938,24 +965,27 @@ var $input = $(app.u.jqSelector('#',ID)); docBody = "<html>\n<!DOCTYPE html>\n"+$.trim($oTemplate.html())+"/n</html>"; //putting the template body into a jquery object strips the html and doctype tags. } else { - $D.anymessage({'message':'In admin_templateEditor.u.handleTemplateSave, unable to obtain original template body in app.data'+dp,'gMessage':true}); + $templateEditor.anymessage({'message':'In admin_template.u.handleTemplateSave, unable to obtain original template body in _app.data'+dp,'gMessage':true}); } } else { - docBody = app.ext.admin_templateEditor.u.postprocessTemplate($('.jHtmlArea iframe:first',$D).contents().find('html').html(),mode); + var $textarea = $("textarea[data-app-role='templateEditorTextarea']:first",$templateEditor) + docBody = _app.ext.admin_template.u.postprocessTemplate($textarea.tinymce().getContent()); +// var taID = "textarea_"+_app.ext.admin_template.u.buildTemplateEditorID($templateEditor.data('mode')); +// $textarea = $(_app.u.jqSelector('#',taID)) +// docBody = _app.ext.admin_template.u.postprocessTemplate($('iframe:first',$templateEditor).contents().find('html').html(),mode); } var dObj = { '_cmd' : 'admin'+mode+'FileSave', 'FILENAME' : 'index.html', '_tag' : { 'callback' : function(responseData) { - $D.hideLoading(); - if(app.model.responseHasErrors(responseData)){ - $D.anymessage({'message':responseData}) + $templateEditor.hideLoading(); + if(_app.model.responseHasErrors(responseData)){ + $templateEditor.anymessage({'message':responseData}) } else { - if($D.data('editor') == 'dialog') {$D.dialog('close');} - $('#globalMessaging').anymessage(app.u.successMsgObject('Your changes have been saved.')); + $templateEditor.anymessage(_app.u.successMsgObject('Your changes have been saved.')); } } }, @@ -963,54 +993,51 @@ var $input = $(app.u.jqSelector('#',ID)); } if(mode == 'EBAYProfile') { - dObj.PROFILE = $D.data('profile'); + dObj.PROFILE = $templateEditor.data('profile'); } else if(mode == 'Campaign') { - dObj.CAMPAIGNID = $D.data('campaignid'); + dObj.CAMPAIGNID = $templateEditor.data('campaignid'); } else if(mode == 'Site') { - dObj.DOMAIN = $D.data('domain'); + dObj.DOMAIN = $templateEditor.data('domain'); } else {} //shouldn't get here. mode is verified earlier to be a supported mode. -// app.u.dump(" -> cmd: "); app.u.dump(dObj); - app.model.addDispatchToQ(dObj,'immutable'); +// _app.u.dump(" -> cmd: "); _app.u.dump(dObj); + _app.model.addDispatchToQ(dObj,'immutable'); } else { - $D.anymessage({'message':app.ext.admin_templateEditor.u.missingParamsByMode(mode,$D.data())}); + $templateEditor.anymessage({'message':_app.ext.admin_template.u.missingParamsByMode(mode,$templateEditor.data())}); } } else { - $('#globalMessaging').anymessage({'message':'In admin_templateEditor.u.handleTemplateSave, object passed in not a valid jquery object.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In admin_template.u.handleTemplateSave, object passed in not a valid jquery object.','gMessage':true}); } }, -//Used to copy a template into a profile or campaign (or whatever as more get added). +//Copies a template into a profile or campaign (or whatever as more get added). //vars needs to include SUBDIR and PROJECTID. Vars is most likely passed from an li.data(), but doesn't have to be. handleTemplateSelect : function(vars) { vars = vars || {}; var $TC = $('#templateChooser'); var mode = $TC.data('mode'); //should never get changed through this code. - if(!app.ext.admin_templateEditor.u.missingParamsByMode(mode,vars)) { + if(!_app.ext.admin_template.u.missingParamsByMode(mode,vars)) { if(vars.SUBDIR) { + vars.mode = mode; //used when passed into navigateTo //all is well at this point. proceed. $TC.showLoading({'message':'One moment please. Copying files into directory.'}); var dObj = { _tag : { 'callback' : function(rd) { $TC.hideLoading(); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $TC.anymessage({'message':rd}) } else { $TC.dialog('close'); - $('#globalMessaging').anymessage(app.u.successMsgObject("Thank you, the template "+vars.SUBDIR+" has been copied.")); -// $(app.u.jqSelector('#',app.ext.admin.vars.tab+'Content')).find("[data-app-role='templateOrigin']:first").text(vars.SUBDIR); -//app.u.dump("vars: "); app.u.dump(vars); -//app.u.dump("whitelist: "); app.u.dump(app.u.getWhitelistedObject(vars,['domain','templateid','profile'])); - - app.ext.admin_templateEditor.a.showTemplateEditor(mode,app.u.getWhitelistedObject(vars,['domain','campaignid','profile'])); + $('#globalMessaging').anymessage(_app.u.successMsgObject("Thank you, the template "+vars.SUBDIR+" has been copied.")); + navigateTo('#!ext/admin_template/showTemplateEditor',_app.u.getWhitelistedObject(vars,['domain','campaignid','profile','mode'])); } } } @@ -1023,7 +1050,7 @@ var $input = $(app.u.jqSelector('#',ID)); if(mode == 'EBAYProfile') { dObj._cmd = 'adminEBAYTemplateInstall'; dObj.PROFILE = $TC.data('profile'); - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd':'adminEBAYProfileUpdate', 'template_origin':vars.SUBDIR, 'PROFILE' : $TC.data('profile') @@ -1039,142 +1066,42 @@ var $input = $(app.u.jqSelector('#',ID)); } else {} //should never get here. - app.model.addDispatchToQ(dObj,'immutable'); //app.model.dispatchThis('immutable'); - app.model.dispatchThis('immutable'); + _app.model.addDispatchToQ(dObj,'immutable'); //_app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); } else { - $TC.anymessage({"message":"In admin_templateEditor.u.handleTemplateSelect, SUBDIR not passed in.","gMessage":true}); + $TC.anymessage({"message":"In admin_template.u.handleTemplateSelect, SUBDIR not passed in.","gMessage":true}); } } else { - $TC.anymessage({"message":"In admin_templateEditor.u.handleTemplateSelect, "+app.ext.admin_templateEditor.u.missingParamsByMode(mode,vars),"gMessage":true}); + $TC.anymessage({"message":"In admin_template.u.handleTemplateSelect, "+_app.ext.admin_template.u.missingParamsByMode(mode,vars),"gMessage":true}); } }, //handleTemplateSelect - - getEditorButton_imageadd : function() { - return { - css : 'imageadd', - 'text' : 'Upload New Image to Profile', - action: function (btn) { - var $D = $("<div \/>"); - $D.dialog({ - 'modal':true, - 'width':500, - height : 500, - 'autoOpen' : false - }); - $D.anycontent({'templateID':'ebayTemplateEditorImageUpload',data : {}}); - $D.dialog('open'); - app.ext.admin_medialib.u.convertFormToJQFU($('form',$D),'ebayTemplateMediaUpload'); - } - } - }, //getEditorButton_imageadd - - getEditorButton_image : function() { - return { - css: 'image', - text: 'Place Image', - action: function (btn) { - var - $D = $('#ebayTemplateEditorImageListModal'), - profile = $('#templateEditor').data('profile'), - jhtmlobject = this; //'this' is set by jhtmlarea to the iframe. - if($D.length) { - $D.empty(); //clear contents - } - else { - $D = $("<div \/>",{'id':'ebayTemplateEditorImageListModal'}); - $D.dialog({ - 'title' : 'Select Media', - 'modal':true, - 'width':'60%', - 'autoOpen' : false - }); - } - $D.append("<ul class='listStyleNone' data-bind='var: media(@images); format:processList; loadsTemplate:ebayTemplateEditorMediaFileTemplate;' \/>"); - $D.dialog('open'); - $D.showLoading({'message':'Updating File List'}); - app.ext.admin_medialib.calls.adminImageFolderDetail.init('_ebay/'+profile,{'callback' : function(rd){ - if(app.model.responseHasErrors(rd)){ - $('#globalMessaging').anymessage({'message':rd}); - } - else { - //success content goes here. - var L = app.data[rd.datapointer]['@images'].length; - //need a 'path' set for the data-bind to render. - for(var i = 0; i < L; i += 1) { - app.data[rd.datapointer]['@images'][i]['path'] = "_ebay/"+profile+"/"+app.data[rd.datapointer]['@images'][i]['Name'] - } - $D.anycontent({'datapointer':rd.datapointer}); - app.u.handleAppEvents($D,{'btn':btn,'jhtmlobject':jhtmlobject}); - $D.imagegallery({ - selector: 'a[data-gallery="gallery"]', - show: 'fade', - hide: 'fade', - fullscreen: false, - slideshow: false - }); - $D.dialog("option", "position", "center"); - } - }},'mutable'); - app.model.dispatchThis('mutable'); - } - } - }, //getEditorButton_image +/* +### FUTURE -> these will need to be brought forward. + for the product one, consider some form of integration w/ flexedit. - - getEditorButton_style : function(){ - return { - css : 'styletagedit', - 'text' : 'Style Tags', - action: function (btn) { - var jhtml = this; //the jhtml object. - var $D = app.ext.admin.i.dialogCreate({ - 'title' : 'Add/Update CSS Classes' - }); - $D.attr('id','templateEditorCSSDialog'); - - $D.dialog('option','width','500'); -// $D.dialog('option','modal',false); warning - toggling between css editor as a dialog caused template iframe body to empty. odd. - - var $style = $('.jHtmlArea iframe:first',$('#templateEditor')).contents().find("style:first"); -//templatebuildercss is not editable. it's what the app adds for highlighting classes and it is nuked on save. -//if that's the first style on the page, append a new style tag to the head of the template for future use. - if($style.parent().attr('id') == 'templateBuilderCSS') { - app.u.dump("First style tag is the templateBuilderCSS. Don't use it."); - $style = $("<style \/>"); - $('.jHtmlArea iframe:first',$('#templateEditor')).contents().find("head").append($style); - } - - $("<textarea \/>").width('100%').height('350px').on('blur',function(){ - $style.text($(this).val()) - }).val($style.html()).appendTo($D); - $D.dialog('open'); - } - } - }, //getEditorButton_style - - getEditorButtonNativeApp : function(){ + getEditorButtonNativeApp : function(vars,$templateEditor){ return { css : 'nativeappinputsshow', 'text' : 'Native App Settings', action: function () { - var $metaTags = app.ext.admin_templateEditor.u.pluckObjectFromTemplate('meta') + var $metaTags = _app.ext.admin_template.u.pluckObjectFromTemplate('meta',$templateEditor); var data = {}; -// app.u.dump(" -> $metaTags.length: "+$metaTags.length); app.u.dump($metaTags instanceof jQuery); +// _app.u.dump(" -> $metaTags.length: "+$metaTags.length); _app.u.dump($metaTags instanceof jQuery); $metaTags.each(function(){ data[$(this).attr('name')] = $(this).attr('content'); }) -// app.u.dump("meta data: "); app.u.dump(data); +// _app.u.dump("meta data: "); _app.u.dump(data); - var $D = app.ext.admin.i.dialogCreate({ + var $D = _app.ext.admin.i.dialogCreate({ 'title' : 'Native App Settings (iOS and Android)', 'templateID' : 'nativeAppCampaignSettingsTemplate', 'data' : data @@ -1184,26 +1111,26 @@ var $input = $(app.u.jqSelector('#',ID)); { text: "Close", click: function() { $( this ).dialog( "close" ); } }, { text: "Apply", click: function() { var sfo = $('form',$D).serializeJSON(); - var $templateHead = app.ext.admin_templateEditor.u.pluckObjectFromTemplate('head'); -// app.u.dump(" -> sfo: "); app.u.dump(sfo); + var $templateHead = _app.ext.admin_template.u.pluckObjectFromTemplate('head',$templateEditor); +// _app.u.dump(" -> sfo: "); _app.u.dump(sfo); $D.showLoading({"message":"Applying Changes"}); for(index in sfo) { - var $meta = app.ext.admin_templateEditor.u.pluckObjectFromTemplate("meta[name='"+index+"']"); + var $meta = _app.ext.admin_template.u.pluckObjectFromTemplate("meta[name='"+index+"']",$templateEditor); //update meta if it already exists. if($meta.length) { //data is a list of meta tags that existed at the outset of this operation. if it's here, it exists as a meta in the template already. -// app.u.dump(" --> MATCH!"); +// _app.u.dump(" --> MATCH!"); $meta.attr('content',sfo[index]); } //add meta if it doesn't already exist. else { -// app.u.dump(" --> NO match!"); +// _app.u.dump(" --> NO match!"); $templateHead.prepend("<meta name='"+index+"' content='"+sfo[index]+"' />"); } } $D.hideLoading(); $( this ).dialog( "close" ); -// $D.anymessage(app.u.successMsgObject('Changes applied.')); +// $D.anymessage(_app.u.successMsgObject('Changes applied.')); } } ] }); $('.applyDatetimepicker',$D).datetimepicker({ @@ -1230,7 +1157,7 @@ var $input = $(app.u.jqSelector('#',ID)); 'text' : 'Add a Product Attribute', action: function (btn) { var jhtml = this; //the jhtml object. - var $D = app.ext.admin.i.dialogCreate({ + var $D = _app.ext.admin.i.dialogCreate({ 'title' : 'Add Product Attribute' }); $D.dialog('open'); @@ -1248,7 +1175,7 @@ var $input = $(app.u.jqSelector('#',ID)); attributes.push({attribute:'zoovy:prod_image'+i, data : {'label':'Image '+i,'object':'PRODUCT','format':'img'},'id':'PROD_IMAGE'+i }); } - app.ext.admin_templateEditor.u.appendAttributeListTo($D,jhtml,attributes); + _app.ext.admin_template.u.appendAttributeListTo($D,jhtml,attributes); } } }, //getEditorButton_prodattributeadd @@ -1261,7 +1188,7 @@ var $input = $(app.u.jqSelector('#',ID)); 'text' : 'Add a Buyer Attribute', action: function (btn) { var jhtml = this; //the jhtml object. - var $D = app.ext.admin.i.dialogCreate({ + var $D = _app.ext.admin.i.dialogCreate({ 'title' : 'Add Buyer Attribute' }); $D.dialog('open'); @@ -1271,11 +1198,20 @@ var $input = $(app.u.jqSelector('#',ID)); {attribute: 'buyer:email', data : {'input-cols':'50','input-type':'TEXTBOX','label':'Email address','object':'BUYER'},'id':'PROD_EMAIL' } ] - app.ext.admin_templateEditor.u.appendAttributeListTo($D,jhtml,attributes); + _app.ext.admin_template.u.appendAttributeListTo($D,jhtml,attributes); } } }, //getEditorButton_prodattributeadd + + //only used in the now dead getEditorButton functions. + pluckObjectFromTemplate : function(selector,$templateEditor) { + return $('.jHtmlArea iframe:first',$templateEditor).contents().find(selector); + }, + + +*/ + appendAttributeListTo : function($D,jhtml,attributes) { var r = true; //set to false if error occurs. Otherwise true. I used to determine what is returned. if($D && jhtml && attributes) { @@ -1288,8 +1224,8 @@ var $input = $(app.u.jqSelector('#',ID)); $ul.appendTo($D); $ul.on('click',function(e){ var $target = $(e.target); //the element that was clicked. - // app.u.dump(" -> attributes[i]"); app.u.dump(attributes[$target.data('attributeIndex')]); - if(app.ext.admin_templateEditor.u.applyElementToTemplate(jhtml,attributes[$target.data('attributeIndex')])) { + // _app.u.dump(" -> attributes[i]"); _app.u.dump(attributes[$target.data('attributeIndex')]); + if(_app.ext.admin_template.u.applyElementToTemplate(jhtml,attributes[$target.data('attributeIndex')])) { $D.dialog('close'); } else { @@ -1299,20 +1235,15 @@ var $input = $(app.u.jqSelector('#',ID)); } else if(!jhtml) { r = false; - app.u.dump("In admin_templateEditor.u.applyElementToTemplate, jhtml was not defined and it is required."); + _app.u.dump("In admin_template.u.applyElementToTemplate, jhtml was not defined and it is required."); } else { r = false; - app.u.dump("In admin_templateEditor.u.applyElementToTemplate, attObj was empty/missing vars. attObj requires data, attribute and data.object. attObj: "); app.u.dump(attObj); + _app.u.dump("In admin_template.u.applyElementToTemplate, attObj was empty/missing vars. attObj requires data, attribute and data.object. attObj: "); _app.u.dump(attObj); } return (r === true) ? $ul : false; }, -//this function does NOT escape the selector, so any selector that is a variable and needs escaping should be escaped before it's dumped in. - pluckObjectFromTemplate : function(selector) { - return $('.jHtmlArea iframe:first',$('#templateEditor')).contents().find(selector); - }, - applyElementToTemplate : function(jhtml,attObj){ var r = true; //what is returned. true or false if element inserted successfully. if(jhtml && attObj && attObj.data && attObj.attribute && attObj.data.object && (attObj.data['input-type'] || attObj.data.format)) { @@ -1360,7 +1291,7 @@ var $input = $(app.u.jqSelector('#',ID)); html += "</span>" } else { - app.u.dump("In admin_templateEditor.u.applyElementToTemplate, either data-type ["+attObj.data['input-type']+"] is invalid or data-format ["+attObj.data.format+"] is invalid. attObj:"); app.u.dump(attObj); + _app.u.dump("In admin_template.u.applyElementToTemplate, either data-type ["+attObj.data['input-type']+"] is invalid or data-format ["+attObj.data.format+"] is invalid. attObj:"); _app.u.dump(attObj); r = false; } @@ -1368,13 +1299,99 @@ var $input = $(app.u.jqSelector('#',ID)); } else if(!jhtml) { - app.u.dump("In admin_templateEditor.u.applyElementToTemplate, jhtml was not defined and it is required."); + _app.u.dump("In admin_template.u.applyElementToTemplate, jhtml was not defined and it is required."); } else { - app.u.dump("In admin_templateEditor.u.applyElementToTemplate, attObj was empty/missing vars. attObj requires data, attribute and data.object. attObj: "); app.u.dump(attObj); + _app.u.dump("In admin_template.u.applyElementToTemplate, attObj was empty/missing vars. attObj requires data, attribute and data.object. attObj: "); _app.u.dump(attObj); r = false; } return r; + }, + //vars should contain mode and any mode-specific vars (campaignid if mode is Campaign) + //will concatonate mode and mode specific vars. + buildTemplateEditorID : function(vars) { + var r = ""; + if(!_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars)) { + r += vars.mode+"_"; + switch(vars.mode) { + case 'Campaign': + r += vars.campaignid; + break; + case 'EBAYProfile': + r += vars.profile; + break; + case 'Site': + r += vars.domain; + break; + default: + $('#globalMessaging').anymessage({"message":"In admin_templates.u.buildTemplateEditorID, vars passed 'missingParamsByMode' but failed to find a valid case in the switch statement.","gMessage":true}); + //shouldn't get here. missingParamsByMode should validate mode. + r = false; + break; + } + } + else { + $('#globalMessaging').anymessage({"message":"In admin_templates.u.buildTemplateEditorID, "+_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars),"gMessage":true}); + } + + return r; + }, + + buildTemplateEditorMediaFolderName : function(vars) { + var r = ""; + if(!_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars)) { + r += "_"+(vars.mode == 'EBAYProfile' ? 'ebay' : vars.mode.toLowerCase())+"/"; + switch(vars.mode) { + case 'Campaign': + r += vars.campaignid; + break; + case 'EBAYProfile': + r += vars.profile; + break; + case 'Site': + r += vars.domain; + break; + default: + $('#globalMessaging').anymessage({"message":"In admin_templates.u.buildTemplateEditorID, vars passed 'missingParamsByMode' but failed to find a valid case in the switch statement.","gMessage":true}); + //shouldn't get here. missingParamsByMode should validate mode. + r = false; + break; + } + } + else { + $('#globalMessaging').anymessage({"message":"In admin_templates.u.buildTemplateEditorID, "+_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars),"gMessage":true}); + } + + return r; + }, + //vars should contain mode and any mode-specific vars (campaignid if mode is Campaign) + //will concatonate mode and mode specific vars. + buildTemplateEditorTitle : function(vars) { + var r = ''; + if(!_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars)) { + r += "Template Editor for "; + switch(vars.mode) { + case 'Campaign': + r += 'Campaign '+vars.campaignid; + break; + case 'EBAYProfile': + r += 'eBay Profile ' + vars.profile; + break; + case 'Site': + r += 'Site/Domain '+vars.domain; + break; + default: + $('#globalMessaging').anymessage({"message":"In admin_templates.u.buildTemplateEditorTitle, vars passed 'missingParamsByMode' but failed to find a valid case in the switch statement.","gMessage":true}); + //shouldn't get here. missingParamsByMode should validate mode. + r = false; + break; + } + } + else { + $('#globalMessaging').anymessage({"message":"In admin_templates.u.buildTemplateEditorTitle, "+_app.ext.admin_template.u.missingParamsByMode(vars.mode,vars),"gMessage":true}); + } + + return r; } }, //u [utilities] @@ -1386,101 +1403,76 @@ var $input = $(app.u.jqSelector('#',ID)); e : { -//a site index.html file may contain several editable 'templates', each with their own wizard. -//a dropdown is added to the template editor to allow the user to select a given template. The wizard file is then loaded. - adminSiteTemplateEdit : function($ele) { - - $ele.off('change.adminSiteTemplateEdit').on('change.adminSiteTemplateEdit',function(){ - //when a template is changed, all that needs to be done is to load the wizard. the wizard should take care of everything. - app.ext.admin_templateEditor.u.summonWizard("wizard-"+$(this).val()+".html") - }); - - }, - adminSaveAsTemplateExec : function($btn) { - $btn.button(); - $btn.off('click.adminSaveAsTemplateExec').on('click.adminSaveAsTemplateExec',function(){ - var - templateName = $('#templateName').val(), - $D = $('#templateEditor'); - var mode = $D.data('mode'); - - if(!app.ext.admin_templateEditor.u.missingParamsByMode(mode,$D.data())) { + adminSaveAsTemplateExec : function($ele) { + var + $D = $ele.closest("[data-templateeditor-role='container']"), + templateName = $("[input[name='template']",$D).val(), + mode = $D.data('mode'); + + if(!_app.ext.admin_template.u.missingParamsByMode(mode,$D.data())) { - $D.showLoading({'message':'Saving as new template: '+templateName}); - var dObj = { - 'SUBDIR' : templateName, + $D.showLoading({'message':'Saving as new template: '+templateName}); + var dObj = { + 'SUBDIR' : templateName, // 'PROJECTID' : $D.data('PROJECTID'), //not passed cuz the user doesnt 'choose' the projectid. it'll be set to TEMPLATES - '_tag' : { - 'callback' : function(responseData) { - $D.hideLoading(); - if(app.model.responseHasErrors(responseData)){ - $D.anymessage({'message':responseData}) - } - else { - $D.anymessage(app.u.successMsgObject('The contents have been saved as a template.')); - } + '_tag' : { + 'callback' : function(responseData) { + $D.hideLoading(); + if(_app.model.responseHasErrors(responseData)){ + $D.anymessage({'message':responseData}) + } + else { + $D.anymessage(_app.u.successMsgObject('The contents have been saved as a template.')); } } } + } - dObj._cmd = (mode == 'EBAYProfile') ? 'adminEBAYTemplateCreateFrom' : 'admin'+mode+'TemplateCreateFrom'; + dObj._cmd = (mode == 'EBAYProfile') ? 'adminEBAYTemplateCreateFrom' : 'admin'+mode+'TemplateCreateFrom'; - if(mode == 'EBAYProfile') {dObj.PROFILE = $D.data('profile');} - else if(mode == 'Campaign') {dObj.CAMPAIGNID = $D.data('campaignid');} - else {} //shouldn't ever get here. + if(mode == 'EBAYProfile') {dObj.PROFILE = $D.data('profile');} + else if(mode == 'Campaign') {dObj.CAMPAIGNID = $D.data('campaignid');} + else {} //shouldn't ever get here. - app.model.addDispatchToQ(dObj,'immutable'); - app.model.dispatchThis('immutable'); + _app.model.addDispatchToQ(dObj,'immutable'); + _app.model.dispatchThis('immutable'); - } - else { - $D.anymessage({'message':app.ext.admin_templateEditor.u.missingParamsByMode(mode,$D.data())}); - } - }); + } + else { + $D.anymessage({'message':_app.ext.admin_template.u.missingParamsByMode(mode,$D.data())}); + } }, //executed when a template is selected. - templateChooserExec : function($ele) { - if($ele.is('button')) {$ele.button();} - $ele.off('click.templateChooserExec').on('click.templateChooserExec',function(event){ - event.preventDefault(); - app.ext.admin_templateEditor.u.handleTemplateSelect($.extend(true,{},$('#templateChooser').data(),$ele.closest("[data-app-role='templateDetail']").data())); - }); + templateChooserExec : function($ele,P) { + P.preventDefault(); + _app.ext.admin_template.u.handleTemplateSelect($.extend(true,{},$('#templateChooser').data(),$ele.closest("[data-app-role='templateDetail']").data())); }, - - //$ele is probably an li. This is exectued when a template preview is clicked. It'll open a detail template. //a 'choose' button will be present within the detail pane. - templateChooserPreview : function($ele) { - $ele.off('click.appChooserAppChoose').on('click.appChooserAppChoose',function(event){ - - event.preventDefault(); - app.u.dump("BEGIN admin_templateEditor.e.templateChooserPreview"); + templateChooserPreview : function($ele,P) { + P.preventDefault(); +// _app.u.dump("BEGIN admin_template.e.templateChooserPreview"); var $chooser = $("#templateChooser"); var $panelContainer = $("[data-app-role='appPreviewPanel']",$chooser); var mode = $chooser.data('mode'); if(mode) { - app.u.dump(" --> mode is set ("+mode+")"); +// _app.u.dump(" --> mode is set ("+mode+")"); var listDP = (mode == 'EBAYProfile') ? 'adminEBAYTemplateList' : 'admin'+mode+'TemplateList'; //ebay is ebayprofile most of the time, but sometimes just ebay. handy. - if(app.data[listDP] && app.data[listDP]['@TEMPLATES'] && app.data[listDP]['@TEMPLATES'][$ele.data('obj_index')]) { - var templateData = app.data[listDP]['@TEMPLATES'][$ele.data('obj_index')]; + if(_app.data[listDP] && _app.data[listDP]['@TEMPLATES'] && _app.data[listDP]['@TEMPLATES'][$ele.data('obj_index')]) { + var templateData = _app.data[listDP]['@TEMPLATES'][$ele.data('obj_index')]; var $panel = $("[data-subdir='"+templateData.SUBDIR+"']",$panelContainer); - -// app.u.dump(" -> $chooser.length: "+$chooser.length); -// app.u.dump(" -> $panelContainer.length: "+$panelContainer.length); -// app.u.dump(" -> $panel already exists: "+$panel.length); - if($panel.length) {} //panel is already on the dom (li already clicked once). do nothing just yet. else { - app.u.dump(" --> panel is NOT generated (first time click). build new panel"); +// _app.u.dump(" --> panel is NOT generated (first time click). build new panel"); $panel = $("<div \/>").hide().attr('data-app-role','templateDetail').anycontent({'templateID':'templateChooserDetailTemplate','data':templateData}); $panel.attr('data-subdir',templateData.SUBDIR); - $panel.data(app.u.getBlacklistedObject(templateData,['@PREVIEWS','%info','MID'])); + $panel.data(_app.u.getBlacklistedObject(templateData,['@PREVIEWS','%info','MID'])); $panel.appendTo($panelContainer); - app.u.handleAppEvents($panel); + _app.u.handleButtons($panel); } //set all preview li's to default state then the new active one to active. @@ -1488,16 +1480,16 @@ var $input = $(app.u.jqSelector('#',ID)); $ele.addClass('ui-state-active').removeClass('ui-state-default'); if($panel.is(':visible')) {} //panel already in focus. do nothing. else if($panelContainer.children().length > 1) { - app.u.dump(" --> more than 1 child. transition between them"); + _app.u.dump(" --> more than 1 child. transition between them"); //hide the current preview and show the new one. $("[data-app-role='templateDetail']:visible",$panelContainer).first().hide('scale',function(){ $panel.show('scale'); }); } else { - app.u.dump(" --> only 1 panel. just expand."); + _app.u.dump(" --> only 1 panel. just expand."); $panel.show('scale',function(){ - app.u.dump(' --> now recenter the dialog'); + _app.u.dump(' --> now recenter the dialog'); //after the first preview is displayed, resize and recenter the modal. $chooser.dialog("option", "position", "center"); $chooser.dialog('option','height',($('body').height() - 100)); @@ -1505,191 +1497,108 @@ var $input = $(app.u.jqSelector('#',ID)); } } else { - $chooser.anymessage({'message':'In admin_templateEditor.e.templateChooserPreview, could not obtain data (app.data.admin'+mode+'TemplateList or @TEMPLATES within that or ['+$ele.data('obj_index')+'] within that was unavailable.','gMessage':true}) + $chooser.anymessage({'message':'In admin_template.e.templateChooserPreview, could not obtain data (_app.data.admin'+mode+'TemplateList or @TEMPLATES within that or ['+$ele.data('obj_index')+'] within that was unavailable.','gMessage':true}) } } else { - $chooser.anymessage({'message':'In admin_templateEditor.e.templateChooserPreview, unable to ascertain mode from templateChooser.','gMessage':true}) + $chooser.anymessage({'message':'In admin_template.e.templateChooserPreview, unable to ascertain mode from templateChooser.','gMessage':true}) } - }); - }, - - -//used to upload a file (img, zip, .html, etc) into a profile or campaign. - containerFileUploadShow : function($btn){ - $btn.button({icons: {primary: "ui-icon-arrowthickstop-1-n"},text: ($btn.data('hidebuttontext')) ? false : true}); - - if($btn.data('mode') == 'Site') { - var domainname = $btn.closest("[data-domainname]").data('domainname'); - if(app.data['adminDomainDetail|'+domainname]) { - if(app.data['adminDomainDetail|'+domainname].PROJECTID) { - //this domain has a project. open the editor. that occurs later as long as pass=true. - } - else { - $btn.button('disable').attr('title','Upload not available because no project exists for this domain.'); + }, + +// used to download a zip file of a 'container' (which is a template saved into a profile or campaign). + containerZipDownloadExec : function($ele,P) { + P.preventDefault(); + var mode = $ele.data('mode'), data = $ele.closest('.buttonset').data(); + if(!_app.ext.admin_template.u.missingParamsByMode(mode,data)) { + $(_app.u.jqSelector('#',_app.ext.admin.vars.tab+'Content')).showLoading({'message':'Building a zip file. One moment please...'}); + var dObj = { + '_cmd' : 'admin'+mode+'ZipDownload', + 'base64' : true, + '_tag' : { + 'callback':'fileDownloadInModal', + 'datapointer':'templateZipDownload', + 'jqObj' : $(_app.u.jqSelector('#',_app.ext.admin.vars.tab+'Content')) } } - else { - $btn.button('disable').attr('title','Upload not available because domain ['+domainname+'] data not in memory.'); - } - } - - $btn.off('click.containerFileUploadShow').on('click.containerFileUploadShow',function(){ - var mode = $btn.data('mode'); - var data = $btn.closest('.buttonset').data(); - - var $D = app.ext.admin.i.dialogCreate({ - 'title' : 'Template File Upload', - 'templateID' : 'templateFileUploadTemplate', - data : {} //blank data because translation needs to occur (template calls another template) - }); - $D.dialog('option','height','400'); - $D.dialog('open'); - if(!app.ext.admin_templateEditor.u.missingParamsByMode(mode,data)) { - $('form',$D).append("<input type='hidden' name='mode' value='"+mode+"' \/>"); - if(mode == 'EBAYProfile') { - $('form',$D).append("<input type='hidden' name='profile' value='"+data.profile+"' \/>"); - } - else if(mode == 'Campaign') { - $('form',$D).append("<input type='hidden' name='campaignid' value='"+data.campaignid+"' \/>"); - } - else if(mode == 'Site') { - $('form',$D).append("<input type='hidden' name='domain' value='"+data.domainname+"' \/>"); - } - else {} - - app.ext.admin_medialib.u.convertFormToJQFU($('form',$D),'adminFileUpload'); + if(mode == 'EBAYProfile') { + dObj.PROFILE = data.profile; } - else { - $D.anymessage({'message':app.ext.admin_templateEditor.u.missingParamsByMode(mode,data)}); + else if(mode == 'Campaign') { + dObj.CAMPAIGNID = data.campaignid; } - }); - }, //containerFileUploadShow - -// used to download a zip file of a 'container' (which is a template saved into a profile or campaign). - containerZipDownloadExec : function($btn) { - $btn.button({icons: {primary: "ui-icon-arrowthickstop-1-s"},text: ($btn.data('hidebuttontext')) ? false : true}); -//lock button for 'site' if no projectid is set or it's unavailable. - if($btn.data('mode') == 'Site') { - var domainname = $btn.closest(".buttonset").data('domain'); - if(app.data['adminDomainDetail|'+domainname]) { - if(app.data['adminDomainDetail|'+domainname].PROJECTID) { - //this domain has a project. do nothing to the button. - } - else { - $btn.button('disable').attr('title','Download not available because no project exists for this domain.'); - } + else if(mode == 'Site') { + dObj.DOMAIN = data.domain; } - else { - $btn.button('disable').attr('title','Download not available because domain ['+domainname+'] data not in memory.'); - } + else {} //shouldn't get here. + + _app.model.addDispatchToQ(dObj,'immutable'); + _app.model.dispatchThis('immutable'); + + } + else { + $('#globalMessaging').anymessage({'message':"In admin_template.e.containerZipDownloadExec, "+_app.ext.admin_template.u.missingParamsByMode(mode,data)+". The required params should be on the .buttonset around the download button"}); } - - - $btn.off('click.containerZipDownloadExec').on('click.containerZipDownloadExec',function(){ - - var mode = $btn.data('mode'); - var data = $btn.closest('.buttonset').data(); -app.u.dump(" -> data: "); app.u.dump(data); - if(!app.ext.admin_templateEditor.u.missingParamsByMode(mode,data)) { - $(app.u.jqSelector('#',app.ext.admin.vars.tab+'Content')).showLoading({'message':'Building a zip file. One moment please...'}); - var dObj = { - '_cmd' : 'admin'+mode+'ZipDownload', - 'base64' : true, - '_tag' : { - 'callback':'fileDownloadInModal', - 'datapointer':'templateZipDownload', - 'jqObj' : $(app.u.jqSelector('#',app.ext.admin.vars.tab+'Content')) - } - } - - if(mode == 'EBAYProfile') { - dObj.PROFILE = data.profile; - } - else if(mode == 'Campaign') { - dObj.CAMPAIGNID = data.campaignid; - } - else if(mode == 'Site') { - dObj.DOMAIN = data.domain; - } - else {} //shouldn't get here. - - app.model.addDispatchToQ(dObj,'immutable'); - app.model.dispatchThis('immutable'); - - } - else { - $('#globalMessaging').anymessage({'message':"In admin_templateEditor.e.containerZipDownloadExec, "+app.ext.admin_templateEditor.u.missingParamsByMode(mode,data)+". The required params should be on the .buttonset around the download button"}); - } - }); }, //containerZipDownloadExec - adminTemplateCampaignExit : function($btn) { - $btn.button(); - $btn.off('click.adminTemplateCampaignExit').on('click.adminTemplateCampaignExit',function(){ -var data = $btn.closest("[data-app-role='templateEditor']").data(); -if(data.editor='dialog') { - //we're in a dialog, just close it. - $btn.closest('.ui-content-dialog').dialog('close'); - } -else { - if(data.mode == 'Campaign') { - app.ext.admin_customer.a.showCampaignEditor($(app.u.jqSelector('#',app.ext.admin.vars.tab+"Content")),data.campaignid); - } - else if(data.mode == 'EBAYProfile') { - app.ext.admin_syndication.a.showEBAYLaunchProfileEditor($(app.u.jqSelector('#',app.ext.admin.vars.tab+'Content')),data.profile); - } - else { - - } - } - }) - + adminTemplateEditorExit : function($ele,P) { + var $templateEditor = $ele.closest("[data-app-role='templateEditor']"), data = $templateEditor.data(); + if(data.mode == 'Campaign') { + $("textarea[data-app-role='templateEditorTextarea']:first",$templateEditor).tinymce().remove(); + navigateTo('#!ext/admin_customer/showCampaignManager',{'campaignid':data.campaignid}); + } + else if(data.mode == 'EBAYProfile') { + $("textarea[data-app-role='templateEditorTextarea']:first",$templateEditor).tinymce().remove(); + navigateTo('#!syndication',{'mkt':'EBF','profile':data.profile}); + } + else if(data.mode == 'Site') { + $(".isTinymceTextarea",$templateEditor).tinymce().remove(); + navigateTo('#!ext/admin_sites/showDomainConfig',{'domain':data.domain}); + } + else { + $("#globalMessaging").anymessage({"message":"In admin_template.e.adminTemplateEditorExit, unrecognize or missing mode ["+data.mode+"] set on template editor.","gMessage":true}); + } }, //adminTemplateCampaignExit - adminTemplateCampaignTestShow : function($btn) { - $btn.button(); - - $btn.off('click.adminTemplateCampaignTestShow').on('click.adminTemplateCampaignTestShow',function(){ - var $D = app.ext.admin.i.dialogCreate({"title":"Send a Test Email for this Campaign"}); - var $input = $("<input \/>",{'name':'email','type':'email','placeholder':'email address'}).appendTo($D); - - $D.dialog('option','width','350'); - $D.dialog({ buttons: [ { text: "Send Test", click: function() { - if(app.u.isValidEmail($input.val())) { - $D.showLoading({'message':'Sending Test Email'}); - app.ext.admin_templateEditor.u.handleTemplateSave($('#templateEditor')); - app.model.addDispatchToQ({ - '_cmd':'adminCampaignTest', - 'CAMPAIGNID' : $('#templateEditor').data('campaignid'), - 'RECIPIENTS' : "emails="+$input.val()+"\n", - '_tag': { - 'callback':function(rd) { - $D.hideLoading(); - if(app.model.responseHasErrors(rd)){ - $D.anymessage({'message':rd}); - } - else { - $D.anymessage(app.u.successMsgObject('Test email has been sent')); - $D.dialog({ buttons: [ { text: "Close", click: function() {$D.dialog('close')}}]}); - } + adminTemplateCampaignTestShow : function($ele,P) { + var $D = _app.ext.admin.i.dialogCreate({"title":"Send a Test Email for this Campaign"}); + var $input = $("<input \/>",{'name':'email','type':'email','placeholder':'email address'}).appendTo($D); + + $D.dialog('option','width','350'); + $D.dialog({ buttons: [ { text: "Send Test", click: function() { + if(_app.u.isValidEmail($input.val())) { + $D.showLoading({'message':'Sending Test Email'}); + var $templateEditor = $ele.closest("[data-templateeditor-role='container']"); + _app.ext.admin_template.u.handleTemplateSave($templateEditor); + _app.model.addDispatchToQ({ + '_cmd':'adminCampaignTest', + 'CAMPAIGNID' : $templateEditor.data('campaignid'), + 'RECIPIENTS' : "emails="+$input.val()+"\n", + '_tag': { + 'callback':function(rd) { + $D.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + $D.anymessage(_app.u.successMsgObject('Test email has been sent')); + $D.dialog({ buttons: [ { text: "Close", click: function() {$D.dialog('close')}}]}); } } - },'immutable'); - app.model.dispatchThis('immutable'); - } - else { - $D.anymessage({'message':'Please enter a valid email address.'}); - } - } } ] }); - $D.dialog('open'); - }); - + } + },'immutable'); + _app.model.dispatchThis('immutable'); + } + else { + $D.anymessage({'message':'Please enter a valid email address.'}); + } + } } ] }); + $D.dialog('open'); }, -//USES DELEGATED EVENTS + adminEBAYProfilePreviewShow : function($ele,p) { - var $D = app.ext.admin.i.dialogCreate({"title":"HTML Listing Preview"}); + p.preventDefault(); + var $D = _app.ext.admin.i.dialogCreate({"title":"HTML Listing Preview"}); $D.dialog('open'); //this is used in the product editor var pid = $ele.closest("[data-pid]").data('pid'); @@ -1697,7 +1606,7 @@ var profile = $ele.closest('form').find("[name='zoovy:profile']").val(); if(profile && pid) { - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd':'adminEBAYProfilePreview', 'pid' : pid, 'PROFILE' : profile, @@ -1705,27 +1614,28 @@ if(profile && pid) { 'datapointer' : 'adminEBAYProfilePreview', 'callback':function(rd) { $D.hideLoading(); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $D.anymessage({'message':rd}); } else { - $D.append(app.data[rd.datapointer].html); + $D.append(_app.data[rd.datapointer].html); $D.dialog('option', 'height', ($('body').height() - 100)); $D.dialog('option', 'position', 'center'); } } } },'immutable'); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); } else { - $('#globalMessaging').anymessage({"message":"In admin_templateEditor.e.adminEBAYProfilePreviewShow, either pid ["+pid+"] or profile ["+profile+"] not set. Both are required.","gMessage":true}); + $('#globalMessaging').anymessage({"message":"In admin_template.e.adminEBAYProfilePreviewShow, either pid ["+pid+"] or profile ["+profile+"] not set. Both are required.","gMessage":true}); } }, templateEditorIframeResizeExec : function($ele) { - var $iframe = $('.jHtmlArea iframe:first',$('#templateEditor')); + var $templateEditor = $ele.closest("[data-templateeditor-role='container']"); + var $iframe = $('.jHtmlArea iframe:first',$templateEditor); $iframe.data('originalHeight',$iframe.height()); $iframe.parent().removeClass() $iframe.parent().find('.device').remove(); //remove all css classes from parent, then any 'device' elements used for bg's @@ -1749,118 +1659,123 @@ else { }); }, - templateEditorIframeRotateExec : function($btn) { - $btn.button(); - var $iframe = $('.jHtmlArea iframe:first',$('#templateEditor')); - $btn.off('click.templateEditorIframeResizeExec').on('click.templateEditorIframeResizeExec',function(){ -// app.u.dump("rotate click event triggered. iframe.length: "+$iframe.length); - var W = $iframe.width(); - $iframe.width($iframe.height()).height(W); - $iframe.parent().find('.device ,iframe').toggleClass('portrait landscape'); - }); + templateEditorIframeRotateExec : function($ele,P) { + var $templateEditor = $ele.closest("[data-templateeditor-role='container']"); + var $iframe = $('.jHtmlArea iframe:first',$templateEditor); + var W = $iframe.width(); + $iframe.width($iframe.height()).height(W); + $iframe.parent().find('.device ,iframe').toggleClass('portrait landscape'); }, -//opens the template chooser interface. - templateChooserShow : function($btn) { - $btn.button({icons: {primary: "ui-icon-power"},text: ($btn.data('hidebuttontext')) ? false : true}); //text defaults to on. - $btn.off('click.templateChooserShow').on('click.templateChooserShow',function(){ - - if($btn.data('mode') == 'Campaign') { - app.ext.admin_templateEditor.a.showTemplateChooserInModal({"mode":"Campaign","campaignid":$btn.closest("[data-campaignid]").data('campaignid')}); - } - else if ($btn.data('mode') == 'Site') { - var domainname = $btn.closest("[data-domainname]").data('domainname'); - var hostname = $btn.closest("[data-hostname]").attr('data-hostname'); - if(hostname && domainname) { - app.ext.admin_templateEditor.a.showTemplateChooserInModal({"mode":"Site","domain":hostname.toLowerCase()+'.'+domainname}); - } - else { - $('#globalMessaging').anymessage({'message':'In admin_templateEditor.e.templateEditorShow, unable to resolve domain name ['+domainname+'] and/or host name ['+hostname+'].','gMessage':true}); - } - } - else if ($btn.data('mode') == 'EBAYProfile') { - app.ext.admin_templateEditor.a.showTemplateChooserInModal({"mode":"EBAYProfile","profile":$btn.closest("[data-profile]").data('profile')}); + templateChooserShow : function($ele,p) { + p.preventDefault(); + if($ele.data('mode') == 'Campaign') { + _app.ext.admin_template.a.showTemplateChooserInModal({"mode":"Campaign","campaignid":$ele.closest("[data-campaignid]").data('campaignid')}); + } + else if ($ele.data('mode') == 'Site') { + var domainname = $ele.closest("[data-domainname]").data('domainname'); + var hostname = $ele.closest("[data-hostname]").attr('data-hostname'); + if(hostname && domainname) { + _app.ext.admin_template.a.showTemplateChooserInModal({"mode":"Site","domain":hostname.toLowerCase()+'.'+domainname}); } else { - //invalid mode set. - $('#globalMessaging').anymessage({"message":"In admin_templateEditor.e.templateChooserShow, invalid mode ["+$btn.data('mode')+"] set on button.","gMessage":true}); + $('#globalMessaging').anymessage({'message':'In admin_template.e.templateChooserShow, unable to resolve domain name ['+domainname+'] and/or host name ['+hostname+'].','gMessage':true}); } - }); + } + else if ($ele.data('mode') == 'EBAYProfile') { + _app.ext.admin_template.a.showTemplateChooserInModal({"mode":"EBAYProfile","profile":$ele.closest("[data-profile]").data('profile')}); + } + else { + //invalid mode set. + $('#globalMessaging').anymessage({"message":"In admin_template.e.templateChooserShow, invalid mode ["+$ele.data('mode')+"] set on button.","gMessage":true}); + } }, //templateChooserShow - templateEditorShow : function($btn) { -// app.u.dump(" -> $btn.data('buttontext'): "+$btn.data('buttontext')); - $btn.button({icons: {primary: "ui-icon-wrench"},text: ($btn.data('hidebuttontext')) ? false : true}); //text defaults to on. - - - $btn.off('click.templateEditorShow').on('click.templateEditorShow',function(){ - var pass = true; - if($btn.data('mode') == 'Campaign') { - app.ext.admin_templateEditor.a.showTemplateEditor('Campaign',{"campaignid":$btn.closest("[data-campaignid]").data('campaignid')}); - } - else if ($btn.data('mode') == 'EBAYProfile') { - app.ext.admin_templateEditor.a.showTemplateEditor('EBAYProfile',{"profile":$btn.closest("[data-profile]").data('profile')}); - } - else if ($btn.data('mode') == 'Site') { - - var domainname = $btn.closest("[data-domainname]").data('domainname'); - var hostname = $btn.closest("[data-hostname]").attr('data-hostname'); - - if(hostname && domainname) { - app.ext.admin_templateEditor.a.showTemplateEditor('Site',{"domain":hostname.toLowerCase()+'.'+domainname}); - } - else { - $('#globalMessaging').anymessage({'message':'In admin_templateEditor.e.templateEditorShow, unable to resolve domain name ['+domainname+'] and/or host name ['+hostname+'].','gMessage':true}); - } + templateEditorShow : function($ele,p) { + p.preventDefault(); + var pass = true; + if($ele.data('mode') == 'Campaign') { + navigateTo('#!ext/admin_template/showTemplateEditor',{'campaignid':$ele.closest("[data-campaignid]").data('campaignid'),'mode':'Campaign'}); + } + else if ($ele.data('mode') == 'EBAYProfile') { + navigateTo('#!ext/admin_template/showTemplateEditor',{'profile':$ele.closest("[data-profile]").data('profile'),'mode':'EBAYProfile'}); + } + else if ($ele.data('mode') == 'Site') { + + var domainname = $ele.closest("[data-domainname]").data('domainname'); + var hostname = $ele.closest("[data-hostname]").attr('data-hostname'); + + if(hostname && domainname) { + navigateTo('#!ext/admin_template/showTemplateEditor',{'domain':hostname.toLowerCase()+'.'+domainname,'mode':'Site'}); } else { - //invalid mode set. - $('#globalMessaging').anymessage({"message":"In admin_templateEditor.e.templateEditorShow, invalid mode ["+$btn.data('mode')+"] set on button.","gMessage":true}); + $('#globalMessaging').anymessage({'message':'In admin_template.e.templateEditorShow, unable to resolve domain name ['+domainname+'] and/or host name ['+hostname+'].','gMessage':true}); } - }); + } + else { + //invalid mode set. + $('#globalMessaging').anymessage({"message":"In admin_template.e.templateEditorShow, invalid mode ["+$ele.data('mode')+"] set on button.","gMessage":true}); + } }, //templateEditorShow - - startWizardExec : function($btn) { - $btn.button(); - var $meta = $('.jHtmlArea iframe:first',$('#templateEditor')).contents().find("meta[name='wizard']"); - var editorData = $('#templateEditor').data(); - if($meta.length == 0) {$btn.button('disable')} + containerFileUploadShow : function($ele,p) { + p.preventDefault(); + var mode = $ele.data('mode'); + var data = $ele.closest('.buttonset').data(); + + var $D = _app.ext.admin.i.dialogCreate({ + 'title' : 'Template File Upload', + 'templateID' : 'templateFileUploadTemplate', + data : {} //blank data because translation needs to occur (template calls another template) + }); + $D.dialog('option','height','400'); + $D.dialog('open'); + + if(!_app.ext.admin_template.u.missingParamsByMode(mode,data)) { + $('form',$D).append("<input type='hidden' name='mode' value='"+mode+"' \/>"); + if(mode == 'EBAYProfile') { + $('form',$D).append("<input type='hidden' name='profile' value='"+data.profile+"' \/>"); + } + else if(mode == 'Campaign') { + $('form',$D).append("<input type='hidden' name='campaignid' value='"+data.campaignid+"' \/>"); + } + else if(mode == 'Site') { + $('form',$D).append("<input type='hidden' name='domain' value='"+data.domainname+"' \/>"); + } + else {} + + _app.ext.admin_medialib.u.convertFormToJQFU($('form',$D),'adminFileUpload'); + } else { -// app.u.dump(" -> $meta.attr('content'): "+$meta.attr('content')); - $btn.off('click.startWizardExec').on('click.startWizardExec',function(event){ - $btn.button('disable').hide(); - event.preventDefault(); - app.ext.admin_templateEditor.u.summonWizard($meta.attr('content')); - }); + $D.anymessage({'message':_app.ext.admin_template.u.missingParamsByMode(mode,data)}); } - }, + }, //containerFileUploadShow - templateHighlightToggle : function($cb) { - $cb.anycb(); - $cb.on('change',function(){ - if($cb.is(':checked')) { - $('iframe',$cb.closest("[data-app-role='templateEditor']")).contents().find('body').addClass('showHighlights_'+$cb.data('objecttype')); - } - else { - $('iframe',$cb.closest("[data-app-role='templateEditor']")).contents().find('body').removeClass('showHighlights_'+$cb.data('objecttype')); - } - }); + startWizardExec : function($ele,P) { + P.preventDefault(); + var + $templateEditor = $ele.closest("[data-templateeditor-role='container']"), + editorData = $templateEditor.data(); + + if($ele.data('wizardContent')) { + _app.u.dump(" -> $ele.data()"); _app.u.dump($ele.data()); + _app.ext.admin_template.u.summonWizard($ele.closest("[data-templateeditor-role='container']"),$ele.data('wizardContent')); + } + else { + $templateEditor.anymessage({"message":"In admin_template.e.startWizardExec, trigger element did not have data('wizardContent') set on it.","gMessage":true}); + } }, - adminTemplateSaveExec : function($btn) { - $btn.button(); - $btn.off('click.adminTemplateSaveExec').on('click.adminTemplateSaveExec',function(){ - var $D = $('#templateEditor'); - if(!app.ext.admin_templateEditor.u.missingParamsByMode($D.data('mode'),$D.data())) { - app.ext.admin_templateEditor.u.handleTemplateSave($D); - app.model.dispatchThis('immutable'); - } - else { - $D.anymessage({'message':app.ext.admin_templateEditor.u.missingParamsByMode(mode,$D.data())}); - } - }); - + adminTemplateSaveExec : function($ele,P) { + _app.u.dump("GOT HERE"); + var $templateEditor = $ele.closest("[data-templateeditor-role='container']"); + if(!_app.ext.admin_template.u.missingParamsByMode($templateEditor.data('mode'),$templateEditor.data())) { + _app.ext.admin_template.u.handleTemplateSave($templateEditor); + _app.model.dispatchThis('immutable'); + } + else { + $templateEditor.anymessage({'message':_app.ext.admin_template.u.missingParamsByMode(mode,$templateEditor.data())}); + } }, //executed on click in file chooser portion of the template editor (in jhtml toolbar add image) diff --git a/extensions/admin/templates.html b/extensions/admin/templates.html old mode 100755 new mode 100644 index 3ce4f5522..3f2dda9d2 --- a/extensions/admin/templates.html +++ b/extensions/admin/templates.html @@ -4,7 +4,8 @@ <td class='valignTop'> <h5 data-bind="var:message(origin); format:text;"></h5> <h6 data-bind="var:message(msg); format:text;"></h6> - <p data-bind="var:message(note); format:truncText; numCharacters: 75;"></p> + <h6 data-bind="var:message(verb); format:text;"></h6> + <p data-bind="var:message(note); format:trunctext; numCharacters: 75;"></p> <button data-app-click='admin|messageDetailShow' data-icon-primary="ui-icon-arrowthick-1-e" data-text='true' class='applyButton'>Details</button> </td> <td class='valignTop'> @@ -33,22 +34,22 @@ <h5 data-bind="var:message(origin); format:text; pretext:Origin: ;"></h5> <ul> <li class='clearfix loadingBG stdListItem' id='adminProdStdForList'> - <div class='removeProd' onClick='app.ext.admin.u.removePidFromFinder($(this).closest("[data-pid]"));'><span class='ui-icon ui-icon-closethick'></span></div> - <div class='handle'><span class='ui-icon ui-icon-grip-dotted-vertical'></span></div> - <img class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL;' width='50' height='50' /> - <div data-bind='var:product(zoovy:prod_name); format:text;' class='prodName'></div> - <div class='pid' data-bind='var:product(pid); format:text;'></div> + <div class="removeProd" onclick="adminApp.ext.admin.u.removePidFromFinder($(this).closest("[data-pid]"));"><span class="ui-icon ui-icon-closethick"></span></div> + <div class="handle"><span class="ui-icon ui-icon-grip-dotted-vertical"></span></div> + <img data-tlc="bind $var '.%attribs.zoovy:prod_image1'; if (is $var --notblank;) {{ apply --img --media=$var --width=50 --height=50 --bgcolor='#ffffff' --replace;}};" class="prodThumb" height="50" width="50"> + <div data-tlc="bind $var '.%attribs.zoovy:prod_name'; if (is $var --notblank;) {{apply --append;}};" class="prodName"></div> + <div data-tlc="bind $var '.pid'; if (is $var --notblank;) {{apply --append;}};" class="pid"></div> </li> <li class='clearfix loadingBG simpleListItem' id='adminProdSimpleForList'> - <div class='removeProd' onClick='app.ext.admin.u.removePidFromFinder($(this).closest("[data-pid]"));'><span class='ui-icon ui-icon-closethick'></span></div> - <div class='handle'><span class='ui-icon ui-icon-grip-dotted-vertical'></span></div> - <div data-bind='var:product(zoovy:prod_name); format:text;' class='prodName'></div> - <div class='pid' data-bind='var:product(pid); format:text;'></div> + <div class="removeProd" onclick="adminApp.ext.admin.u.removePidFromFinder($(this).closest("[data-pid]"));"><span class="ui-icon ui-icon-closethick"></span></div> + <div class="handle"><span class="ui-icon ui-icon-grip-dotted-vertical"></span></div> + <div data-tlc="bind $var '.%attribs.zoovy:prod_name'; if (is $var --notblank;) {{apply --append;}};" class="prodName"></div> + <div data-tlc="bind $var '.pid'; if (is $var --notblank;) {{apply --append;}};" class="pid"></div> </li> <li class='clearfix loadingBG stdListItem' id='adminElasticResult'> - <div class='removeProd' onClick='app.ext.admin.u.removePidFromFinder($(this).closest("[data-pid]"));'><span class='ui-icon ui-icon-closethick'></span></div> + <div class='removeProd' onClick='adminApp.ext.admin.u.removePidFromFinder($(this).closest("[data-pid]"));'><span class='ui-icon ui-icon-closethick'></span></div> <div class='handle'><span class='ui-icon ui-icon-grip-dotted-vertical'></span></div> <img class='prodThumb' data-bind='var: product(images); format:imageURL; isElastic:1; extension:admin;' width='50' height='50' /> <div data-bind='var:product(prod_name); format:text;' class='prodName'></div> @@ -57,7 +58,7 @@ <h5 data-bind="var:message(origin); format:text; pretext:Origin: ;"></h5> - <li class='clearfix loadingBG stdListItem pointer' id='adminChooserElasticResult' onClick="$('#chooserResultContainer').empty(); app.ext.store_product.u.showProductDataIn('chooserResultContainer',{'pid':$(this).data('pid'),'templateID':'productTemplateChooser'});"> + <li class='clearfix loadingBG stdListItem pointer' id='adminChooserElasticResult' onClick="adminApp.ext.admin.u.handleChooserResultsClick($(this));"> <img class='prodThumb' data-bind='var: product(images); format:imageURL;isElastic:1;extension:admin;' width='50' height='50' /> <div data-bind='var:product(prod_name); format:text;' class='prodName'></div> <div class='pid' data-bind='var:product(pid); format:text;'></div> @@ -143,33 +144,33 @@ <h5 data-bind="var:message(origin); format:text; pretext:Origin: ;"></h5> <div id='productTemplateChooser'> -<table> -<tr> - <td> -<img src='blank.gif' class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL;' width='120' height='120' /> - </td> - <td> - <h1 data-bind='var: product(zoovy:prod_name); format:text;'></h1> - - <h5 class='stid' data-bind='var: product(pid); format:text; pretext: Sku: ;'></h5> - <h5 data-bind='var: product(zoovy:prod_mfg); format:text; pretext: Mfg: ;'></h5> - <h5 data-bind='var: product(zoovy:prod_mfgid); format:text; pretext: Mfg ID: ;'></h5> - <h4 class='basePrice' data-bind='var: product(zoovy:base_price); format:money; currencySign: $; hideZero:true; pretext: Our Price: ;'></h4> - <h5 class='prodMSRP' data-bind='var: product(zoovy:prod_msrp); format:money; currencySign: $; hideZero:true; pretext: MSRP: ;'></h5> - - - - </td> -</tr> -</table> -<div data-bind='useParentData:true; format:detailedInvDisplay; extension:store_product;' class='inventory'></div> - <form action='#' onSubmit="return false;"> + <table> + <tr> + <td> + <img src='blank.gif' class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL;' width='120' height='120' /> + </td> + <td> + <h1 data-bind='var: product(zoovy:prod_name); format:text;'></h1> + + <h5 class='stid' data-bind='var: product(pid); format:text; pretext: Sku: ;'></h5> + <h5 data-bind='var: product(zoovy:prod_mfg); format:text; pretext: Mfg: ;'></h5> + <h5 data-bind='var: product(zoovy:prod_mfgid); format:text; pretext: Mfg ID: ;'></h5> + <h4 class='basePrice' data-bind='var: product(zoovy:base_price); format:money; currencySign: $; hideZero:true; pretext: Our Price: ;'></h4> + <h5 class='prodMSRP' data-bind='var: product(zoovy:prod_msrp); format:money; currencySign: $; hideZero:true; pretext: MSRP: ;'></h5> + + + + </td> + </tr> + </table> + <div data-bind='useParentData:true; format:detailedinvdisplay; extension:store_product;' class='inventory stdPadding'></div> + <form action='#' onSubmit="return false;" class='chooserAddToCartForm stdPadding'> <input type='hidden' data-bind='var: product(pid); format:popVal;' name='sku' /> - <fieldset data-bind='var: product(pid); format:atcVariations; extension:store_product;' class='borderNone'></fieldset> + <fieldset data-bind='var: product(pid); format:atcvariations; extension:store_product;' class='borderNone'></fieldset> <fieldset class='labelsAsBreaks'> - <label>Quantity: <input type='number' value='1' name='qty' /></label> - <label>Price: <input type='number' name='price' data-bind='var: product(zoovy:base_price); format:popVal;' /></label> + <label>Quantity: <input type='number' class='smallInput' value='1' name='qty' /></label> + <label>Price: <input type='number' class='smallInput' name='price' data-bind='var: product(zoovy:base_price); format:popVal;' /></label> </fieldset> </form> @@ -233,9 +234,9 @@ <h2>Recent News</h2> <div class='recentNewsContainer' data-bind='var:news(contents); format:processList; loadsTemplate:recentNewsItemTemplate;'></div> </div> <div class="lpColumn" id="dashboardColumn2"> - <div class='marginBottom alignCenter'> +<!-- <div class='marginBottom alignCenter'> <iframe src='https://s3-us-west-1.amazonaws.com/admin-ui/ads/ad_300x250.html' class='fullWidth noBorders ad-300x250'></iframe> - </div> + </div> --> </div> </div> @@ -248,37 +249,6 @@ <h2>Recent News</h2> </tr> </table> -<!-- -######################## - - -DOMAIN CONFIG - - -######################## ---> - - - - -<div id='domainPanelTemplate' class='panel domainPanel stackedPanels' data-app-role='domainPanel'> - <h3 data-bind="var: domain(id); format: assignAttribute; attribute:data-domain;" data-verb="LOAD" onClick="adminUIDomainPanelExecute($(this));" class='panelHeader ui-accordion-header ui-helper-reset ui-state-default ui-accordion-header-default ui-state-default ui-corner-top ui-accordion-icons pointer clearfix'> - <span class="ui-accordion-header-icon ui-icon ui-icon-circle-arrow-e"></span> - <span data-bind="var: domain(id); format:text;"></span> - </h3> - - <div class='panelContents displayNone ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content-active marginBottom' > - - - <form action="#" onSubmit="return false;"> - <fieldset data-app-role='domainEditorContents'></fieldset> - </form> - - </div> - -</div> - - @@ -299,351 +269,182 @@ <h3 data-bind="var: domain(id); format: assignAttribute; attribute:data-domain;" <div id='pageSetupTemplate' class='page pageSetup'> - -<table class='noPadOrMargin fullWidth stdCellSpacing'> -<tbody> -<tr> - - <td width="33%" valign="top"> - - - +<div class='floatPanel'> <div id="manage" class='ui-widget marginBottom'> <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Manage Apps/Website</h3> + <h3 class='smallPadding'>Manage Apps/Website</h3> </div> <div class='stdPadding ui-widget-content ui-corner-bottom'> - <a href="#" onClick="navigateTo('#!domainConfigPanel'); return false;">Domain Hosting</a><br /> - <div class="helper marginBottom">Register and Link Domains.</div> - - <a href="#" onClick="navigateTo('#!projects'); return false;">App Hosting </a><br /> - <div class="helper marginBottom">Manage Hosted Application Projects</div> - - - <a href="#" onClick="navigateTo('#!mediaLibraryManageMode'); return false;" title="#!mediaLibraryManageMode">Media Library</a><br /> + <a href="#" onClick="navigateTo('#!mediaLibraryManageMode'); return false;" title="#!mediaLibraryManageMode">Media Library</a> <div class="helper">Upload and manage your images, sounds, movies, documents and flash.</div> - <div class="helper marginBottom"> - - <a href="#" onClick="navigateTo('#!mediaLibraryManageMode'); return false;" title="#!mediaLibraryManageMode">Upload New Image</a><br /> - - <a href="#" onClick="navigateTo('#!publicFiles'); return false;">Public Files Library</a><br /> + <div class="helper marginLeft"> + <a href="#" onClick="navigateTo('#!mediaLibraryManageMode'); return false;" title="#!mediaLibraryManageMode"> » Upload New Image</a> + <a href="#" onClick="navigateTo('#!ext/admin_medialib/publicFiles'); return false;"> » Public Files Library</a> </div> + + <a href="#" onClick="navigateTo('#!ext/admin_sites/showDomainConfig'); return false;">Domain and App Config</a> + <div class="helper marginBottom">Add, update or remove domains, hosts and app projects.</div> - - <a href="#" onClick="navigateTo('#!rss'); return false;">RSS Feeds</a><br /> + <a href="#" onClick="navigateTo('#!ext/admin/showRSS'); return false;">RSS Feeds</a> <div class="helper marginBottom">Create RSS Feeds to easily share your product lists with affiliate sites.</div> - <a href="#" onClick="navigateTo('#!categoriesAndLists'); return false;">Categories & Lists</a><br /> - <div class="helper marginBottom">Create RSS Feeds to easily share your product lists with affiliate sites.</div> + <a href="#" onClick="navigateTo('#!ext/admin_navcats/showCategoriesAndLists'); return false;">Categories & Lists</a> + <div class="helper marginBottom">Create and assign product to categories.</div> </div> </div><!-- /manage --> - - - - <div id="vstore" class='ui-widget marginBottom showForZoovyOnly'> + <div id="developer" class='ui-widget'> <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>vStore</h3> + <h3 class='smallPadding'>Developer Tools</h3> </div> <div class='stdPadding ui-widget-content ui-corner-bottom'> + <a href="#" onClick="navigateTo('#!ext/admin_tools/showPrivateFiles'); return false;">Private Files <!-- (beta) --></a> + <div class="helper marginBottom">Private files include diagnostic logs, reports, and ticket attachments.</div> + + <a href="https://github.com/zoovy/AnyCommerce-Development/" target='_blank'>Developer SDK</a> + <div class="helper marginBottom">Use this to easily custom integrations or apps.</div> + + <a href="https://github.com/zoovy/AnyCommerce-Development/wiki" target='_blank'>Dev Wiki</a> + <div class="helper marginBottom">Learn more about what is possible, and what is included in the SDK.</div> + </div> + </div><!-- /developer --> + +</div> +<div class='floatPanel'> + <div id="properties" class='ui-widget marginBottom'> + <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> + <h3 class='smallPadding'>Store Properties</h3> + </div> + + <div class='stdPadding ui-widget-content ui-corner-bottom'> + <a href="#" onClick="navigateTo('#!ext/admin_config/showShippingManager'); return false;">Shipping</a> + <div class="helper marginBottom">Determine how shipping will be calculated for your products.</div> - <a href="#" onClick="navigateTo('/biz/vstore/billing/index.cgi'); return false;" title="/biz/setup/billing/index.cgi">Billing History</a><br /> - <div class="helper marginBottom">View your billing history, update payment information.</div> + <a href="#" onClick="navigateTo('#!ext/admin_config/showPaymentManager'); return false;">Payment Methods</a> + <div class="helper marginBottom">Configure which payment methods you will accept from customers.</div> + <a href="#" onClick="navigateTo('#!ext/admin_config/showTaxConfig'); return false;">Sales Tax</a> + <div class="helper marginBottom">Configure state and local tax collection amounts.</div> + <a href="#" onClick="navigateTo('#!ext/admin_config/showCouponManager'); return false;">Coupons</a> + <div class="helper marginBottom">Create discounts for special purchases.</div> - <a href="#" onClick="navigateTo('/biz/vstore/builder/index.cgi?ACTION=COMPANYEDIT&NS=DEFAULT'); return false;" title="/biz/vstore/builder/index.cgi?ACTION=COMPANYEDIT&NS=DEFAULT">Company Information</a><br /> - <div class="helper">Put in Logo, Address, Policies, etc.</div> + <a href="#" onClick="navigateTo('#!ext/admin_blast/blastMessagesList'); return false;">Email Config and Messages</a> + <div class="helper marginBottom">Update messaging used in automated outbound emails (order create, password recover, etc) and/or configure some message based settings.</div> - <a href="#" onClick="navigateTo('/biz/vstore/builder/index.cgi'); return false;" title="/biz/vstore/builder/index.cgi">Site Builder</a><br /> - <div class="helper">Build the content for your storefront. Select page layouts and add product to categories and lists.</div> + <a href="#" onClick="navigateTo('#!ext/admin_config/showPluginManager'); return false;">Integrations</a> + <div class="helper marginBottom">Provide third party username/passwords for app mashups.</div> + + <a href="#" onClick="navigateTo('#!ext/admin_prodedit/showStoreVariationsManager'); return false;">Global Variations</a> + <div class="helper marginBottom">Manage your global product variations.</div> + </div> + </div><!-- /properties --> + + <div id="vstore" class='ui-widget showForZoovyOnly'> + <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> + <h3 class='smallPadding'>vStore</h3> + </div> + + <div class='stdPadding ui-widget-content ui-corner-bottom'> + + + <a href="#" onClick="navigateTo('#!/biz/vstore/builder/index.cgi?ACTION=COMPANYEDIT&NS=DEFAULT'); return false;" title="/biz/vstore/builder/index.cgi?ACTION=COMPANYEDIT&NS=DEFAULT">Company Information</a> + <div class="helper marginBottom">Put in Logo, Address, Policies, etc.</div> + + <a href="#" onClick="navigateTo('#!/biz/vstore/builder/index.cgi'); return false;" title="/biz/vstore/builder/index.cgi">Site Builder</a> + <div class="helper marginBottom">Build the content for your storefront. Select page layouts and add product to categories and lists.</div> - - <a href="#" onClick="navigateTo('/biz/vstore/builder/themes/index.cgi?NS=DEFAULT'); return false;" title="/biz/vstore/builder/themes/index.cgi?NS=DEFAULT">Pick Site Theme</a><br /> + <a href="#" onClick="navigateTo('#!/biz/vstore/builder/themes/index.cgi?NS=DEFAULT'); return false;" title="/biz/vstore/builder/themes/index.cgi?NS=DEFAULT"> » Pick Site Theme</a> <div class="helper">Select the graphics, buttons and navigation which will be used for this site.</div> - - <a href="#" onClick="navigateTo('/biz/vstore/builder/index.cgi?ACTION=EDIT-WRAPPER'); return false;" title="/biz/vstore/builder/index.cgi?ACTION=EDIT-WRAPPER">Customize Site Theme</a><br /> + <a href="#" onClick="navigateTo('#!/biz/vstore/builder/index.cgi?ACTION=EDIT-WRAPPER'); return false;" title="/biz/vstore/builder/index.cgi?ACTION=EDIT-WRAPPER"> » Customize Site Theme</a> <div class="helper">Tune customizable features in the selected theme.</div> - - <a href="#" onClick="navigateTo('/biz/vstore/builder/index.cgi?ACTION=DECALS&NS=DEFAULT'); return false;" title="/biz/vstore/builder/index.cgi?ACTION=DECALS&NS=DEFAULT">Customize Site Decals</a><br /> + <a href="#" onClick="navigateTo('#!/biz/vstore/builder/index.cgi?ACTION=DECALS&NS=DEFAULT'); return false;" title="/biz/vstore/builder/index.cgi?ACTION=DECALS&NS=DEFAULT"> » Customize Site Decals</a> <div class="helper">Enhance your site with 3rd party logos.</div> - - <a href="#" onClick="navigateTo('/biz/vstore/builder/themes/index.cgi?NS=DEFAULT&SUBTYPE=E'); return false;" title="/biz/vstore/builder/themes/index.cgi?NS=DEFAULT&SUBTYPE=E">Select Email Theme</a><br /> - <div class="helper">Pick a style for a header and footer for an email.</div> - - - <a href="#" onClick="navigateTo('/biz/vstore/builder/emails/index.cgi?VERB=EDIT&NS=DEFAULT'); return false;" title="/biz/vstore/builder/emails/index.cgi?VERB=EDIT&NS=DEFAULT">Edit Email Messages</a><br /> - <div class="helper">Customize the emails that are sent to customers.</div> - - - <!-- - <div > - <a href="#" onClick="navigateTo('/biz/vstore/navcats/index.cgi'); return false;" title="/biz/vstore/navcats/index.cgi">Categories & Lists</a><br /> - <div class="helper">Build your store category tree or add product lists.</div> - </div> - --> - <div > - <a href="#" onClick="navigateTo('/biz/vstore/analytics/index.cgi'); return false;" title="/biz/vstore/analytics/index.cgi">Analytics & Plugins</a><br /> - <div class="helper">Integrate approved 3rd party applications with your site.</div> - </div> + <a href="#" onClick="navigateTo('#!/biz/vstore/analytics/index.cgi'); return false;" title="/biz/vstore/analytics/index.cgi">Analytics & Plugins</a> + <div class="helper marginBottom">Integrate approved 3rd party applications with your site.</div> - <a href="#" onClick="navigateTo('/biz/vstore/checkout/index.cgi?MODE=GENERAL'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=GENERAL">Checkout Setup</a><br /> - <div class="helper">Specify what info is optional/required during checkout.</div> + <a href="#" onClick="navigateTo('#!/biz/vstore/checkout/index.cgi?MODE=GENERAL'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=GENERAL">Checkout Setup</a> + <div class="helper marginBottom">Specify what info is optional/required during checkout.</div> - <a href="#" onClick="navigateTo('/biz/vstore/checkout/index.cgi?MODE=CUSTOMERADMIN'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=CUSTOMERADMIN">Customer Admin Config</a><br /> - <div class="helper">Configure what options customers have when they login to their accounts on your store.</div> + <a href="#" onClick="navigateTo('#!/biz/vstore/checkout/index.cgi?MODE=CUSTOMERADMIN'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=CUSTOMERADMIN">Customer Admin Config</a> + <div class="helper marginBottom">Configure what options customers have when they login to their accounts on your store.</div> - <div > - <a href="#" onClick="navigateTo('/biz/vstore/checkout/index.cgi?MODE=SYS-MESSAGES'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=SYS-MESSAGES">System Messages</a><br /> - <div class="helper">Customize System Messages used throughout the site</div> - - <a href="#" onClick="navigateTo('/biz/vstore/checkout/index.cgi?MODE=CHK-MESSAGES'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=CHK-MESSAGES">Checkout Messages</a><br /> - <div class="helper">Customize Checkout Messaging used during checkout.</div> - </div> - - <a href="#" onClick="navigateTo('/biz/vstore/checkout/index.cgi?MODE=INTERNATIONAL'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=INTERNATIONAL">Languages & Currencies</a><br /> - <div class="helper">Configure which languages and currencies are available.</div> - - - -<!-- -* 201338 -> doesn't work w/ new inventory system. WHIM is new version. - <a href="#" onClick="navigateTo('/biz/vstore/custom/zephyrsports.cgi'); return false;">Inventory Lookup</a> - <div class="helper marginBottom"></div> ---> - <a href="#" onClick="navigateTo('/biz/vstore/search/index.cgi'); return false;" title="/biz/vstore/search/index.cgi">Manage Search Catalogs</a><br /> - <div class="helper">Create custom searchable indexes of your product database.</div> - + <a href="#" onClick="navigateTo('#!/biz/vstore/checkout/index.cgi?MODE=SYS-MESSAGES'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=SYS-MESSAGES">System Messages</a> + <div class="helper marginBottom">Customize System Messages used throughout the site.</div> <!-- - <div > - <a href="#" onClick="navigateTo('/biz/vstore/configurator/index.cgi'); return false;" title="/biz/configurator/index.cgi">Add/Remove Features</a><br /> - <div class="helper">Manage feature bundles installed on this account.</div> - </div> + * 201404 -> this interface doesn't exist anymore. + <a href="#" onClick="navigateTo('#!/biz/vstore/checkout/index.cgi?MODE=CHK-MESSAGES'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=CHK-MESSAGES">Checkout Messages</a> + <div class="helper marginBottom">Customize Checkout Messaging used during checkout.</div> --> - <div > - <a href="#" onClick="navigateTo('/biz/vstore/toxml/index.cgi?ACTION=HELP'); return false;" title="/biz/vstore/toxml/index.cgi?ACTION=HELP">Legacy toxml edit</a><br /> - <div class="helper">Mange Legacy Custom VSTORE Templates for your site, emails, auctions,etc.</div> - - - - - - </div> - </div> - </div><!-- /utility --> - + <a href="#" onClick="navigateTo('#!/biz/vstore/checkout/index.cgi?MODE=INTERNATIONAL'); return false;" title="/biz/vstore/checkout/index.cgi?MODE=INTERNATIONAL">Languages & Currencies</a> + <div class="helper marginBottom">Configure which languages and currencies are available.</div> + <a href="#" onClick="navigateTo('#!/biz/vstore/search/index.cgi'); return false;" title="/biz/vstore/search/index.cgi">Manage Search Catalogs</a> + <div class="helper marginBottom">Create custom searchable indexes of your product database.</div> - </td> - - - <td width="33%" valign="top"> - - <div id="properties" class='ui-widget marginBottom'> - <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Store Properties</h3> - </div> - - <div class='stdPadding ui-widget-content ui-corner-bottom'> - <a href="#" onClick="navigateTo('#!shippingManager'); return false;">Shipping</a><br /> - <div class="helper marginBottom">Determine how shipping will be calculated for your products.</div> + <a href="#" onClick="navigateTo('#!/biz/vstore/toxml/index.cgi?ACTION=HELP'); return false;" title="/biz/vstore/toxml/index.cgi?ACTION=HELP">Legacy toxml edit</a> + <div class="helper marginBottom">Mange Legacy Custom VSTORE Templates for your site, emails, auctions,etc.</div> - <a href="#" onClick="navigateTo('#!paymentManager'); return false;">Payment Methods</a><br /> - <div class="helper marginBottom">Configure which payment methods you will accept from customers.</div> - - <a href="#" onClick="navigateTo('#!taxConfig'); return false;">Sales Tax</a><br /> - <div class="helper marginBottom">Configure state and local tax collection amounts.</div> + <a href='#!downloads'>Downloads</a> + <div class="helper marginBottom">Use our windows clients for managing orders and product</div> - <a href="#" onClick="navigateTo('#!couponManager'); return false;">Coupons</a><br /> - <div class="helper marginBottom">Create discounts for special purchases</div> - <a href="#" onClick="navigateTo('#!pluginManager'); return false;">Plugins</a><br /> - <div class="helper marginBottom">Provide third party username/passwords for app mashups.</div> - - <a href="#" onClick="navigateTo('#!globalVariations'); return false;">Global Variations</a><br /> - <div class="helper marginBottom">Manage your global product variations</div> - -<!-- - - <a href="#" onClick="navigateTo('/biz/crm/index.cgi?VERB=CONFIG'); return false;" title="/biz/crm/index.cgi?VERB=CONFIG">CRM Behaviors</a><br /> - <div class="helper marginBottom">Configure preferences in the CRM area.</div> ---> </div> - </div><!-- /properties --> - + </div> + </div><!-- /vstore --> - </td> - <td width="33%" valign="top"> - <div id="account" class='ui-widget marginBottom'> +</div> +<div class='floatPanel'> + + <div id="account" class='ui-widget'> <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Account Settings</h3> + <h3 class='smallPadding'>Account Settings</h3> </div> <div class='stdPadding ui-widget-content ui-corner-bottom'> - <a href="#" onClick="navigateTo('#!contactInformation'); return false;">Contact Information</a><br /> - <div class="helper marginBottom">Change Administrative/Billing Information</div> + <a href="#" onClick="navigateTo('#!ext/admin_config/showContactInformation'); return false;">Contact Information</a> + <div class="helper marginBottom">Change Administrative/Billing Information.</div> - <a href="#" onClick="navigateTo('#!billingHistory'); return false;">Billing History</a><br /> + <a href="#" onClick="navigateTo('#!ext/admin_config/showBillingHistory'); return false;">Billing History</a> <div class="helper marginBottom">View your billing history, update payment information.</div> - <a href="#" onClick="navigateTo('#!globalSettings'); return false;">Global Settings</a><br /> + <a href="#" onClick="navigateTo('#!ext/admin_config/showGlobalSettings'); return false;">Global Settings</a> <div class="helper marginBottom">Inventory & Order settings in this area affect all sites managed from this account.</div> - <a href="#" onClick="navigateTo('#!partitionManager'); return false;">Partitions</a><br /> + <a href="#" onClick="navigateTo('#!ext/admin_config/showNotifications'); return false;">Notifications</a> + <div class="helper marginBottom">Configure notifications based on system events.</div> + + <a href="#" onClick="navigateTo('#!ext/admin_config/showPartitionManager'); return false;">Partitions</a> <div class="helper marginBottom">The ability to segment your settings, and databases for each site associated with this account.</div> - <a href="#" onClick="navigateTo('#!userManager'); return false;" title="add, remove and edit users, permissions and devices">Manage Users/Devices</a><br /> + <a href="#" onClick="navigateTo('#!ext/admin_user/showUserManager'); return false;" title="add, remove and edit users, permissions and devices">Manage Users/Devices</a> <div class="helper marginBottom">Manage which users and devices can access your account.</div> - <a href="#" onClick="navigateTo('/biz/setup/password/index.cgi'); return false;" title="/biz/setup/password/index.cgi">Change Password</a><br /> - <div class="helper marginBottom">You should change your password every 60 days.</div> + <a href="#" onClick="navigateTo('#!ext/admin_config/passwordUpdate'); return false;">Change Password</a> + <div class="helper marginBottom">Change the password for the user you are logged in as. You should change your password every 60 days.</div> </div> </div><!-- /account --> - - - <div id="developer" class='ui-widget marginBottom'> - <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Developer Tools</h3> - </div> - - <div class='stdPadding ui-widget-content ui-corner-bottom'> - <a href="#" onClick="navigateTo('#!privateFiles'); return false;">Private Files <!-- (beta) --></a><br /> - <div class="helper marginBottom">Private files include diagnostic logs, reports, and ticket attachments.</div> - - <a href="https://github.com/zoovy/AnyCommerce-Development/" target='_blank'>Developer SDK</a><br /> - <div class="helper marginBottom">Use this to easily custom integrations or apps</div> - - <a href="https://github.com/zoovy/AnyCommerce-Development/wiki" target='_blank'>Dev Wiki</a><br /> - <div class="helper marginBottom">Learn more about what is possible, and what is included in the SDK.</div> - - - - </div> - </div><!-- /developer --> - - </td> -</tr> -</tbody> -</table> - - -</div> - - - -<div id='pageTemplateSites' class='ui-widget'> - - <div data-bind="var: domains(*favorites); format:showIfSet;"> -<!-- <h2>Favorite Domains</h2>--> - <ul data-bind="var: domains(*favorites); format:processList; loadsTemplate:domainListFavoriteTemplate;" class='marginTop listStyleNone ui-widget noPadOrMargin clearfix' data-app-role='domainListFavorites'></ul> - </div> - - - <div class='ui-widget-content ui-corner-all stdPadding'> - <table class='fullWidth gridTable marginTop' data-app-role='domainListNonFavorites' data-bind="var: domains(@DOMAINS); format:processList; loadsTemplate:domainListTemplate;"> - <thead> - <tr> - <th colspan='2'>Domain</th> - <th>Partition</th> - <th></th> - </tr> - </thead> - </table> - </div> - </div> -<ul> - - <li id='domainListFavoriteTemplate' class='ui-widget-content ui-corner-all domainPanel positionRelative smallButton'> - <div class='alignCenter'> - <img src='blank.gif' class='prodThumb' data-bind='useParentData:1; format:companyLogo; extension:admin;' width='160' height='160' /> - </div> - - <div class='positionAbsolute positionTop positionRight stdPadding' data-bind="var:domain(DOMAINNAME); format:assignAttribute; attribute:data-domain;"><!-- stdPadding aligns this button w/ host-buttons --> - <button data-app-event="admin|domainPutInFocus">Use Domain</button> - </div> - - <h4 class='alignCenter smallPadding'> - <span data-bind="var: domain(DOMAINNAME); format:text;"></span> - <span data-bind="var: domain(PRT); format:text; pretext:(;posttext:);"></span> - </h4> - - - - <table class='fullWidth'> - <tbody data-bind="var: domain(@HOSTS); format:processList; loadsTemplate:domainListHostsRowTemplate;" data-app-role='domainHostsTbody'> - </tbody> - </table> - - </li> -</ul> - -<table> - -<tbody id='domainListTemplate' data-bind="var: domain(@HOSTS); format:processList; loadsTemplate:domainListHostsRowTemplate;" data-element='domain'> -<tr> - <td colspan='2'><h6 data-bind="var: domain(DOMAINNAME); format:text;"></h6></td> - <td data-bind="var: domain(PRT); format:text; hideZero:false;"></td> - <td class='alignRight width50'> - <button data-app-event='admin_batchJob|batchJobExec' data-whitelist='DOMAINNAME,PRT' data-type='UTILITY/SITEMAP'>Update Sitemap</button> - <button data-app-event="admin|domainPutInFocus">Use Domain</button> - <button data-app-event="admin_config|adminDomainToggleFavoriteExec">Tag as Favorite</button> - <button data-app-event="admin_config|adminDomainDetailShow" data-mode='dialog'>Edit Domain Settings</button> - </td> -</tr> -</tbody> - - -<tr id='domainListHostsRowTemplate' data-element='host'> - <td class='width1'><span class="ui-icon ui-icon-arrow-1-e marginLeft"></span></td> - <td> - <span data-bind="var: host(HOSTNAME); format:text;"></span> - <span data-bind="var: host(HOSTTYPE); format:text; pretext:(; posttext:);"></span> - </td> - <td></td> - <td class='alignRight width50'> -<!-- <button data-app-event='admin_config|adminDomainCreateUpdateHostShow' data-mode='update'>Edit Host</button> --> - <span class='displayNone' data-bind="var: host(HOSTTYPE); format:showIfMatch; matchValue:SITE;"><!-- buttons not working yet. --> - <button data-app-event='admin_templateEditor|templateChooserShow' data-hidebuttontext='1' data-mode='Site'>Choose a Template</button> - <button data-app-event='admin_templateEditor|templateEditorShow' data-hidebuttontext='1' data-mode='Site'>Edit Project</button> -<!-- buttons locked UNLESS a project is in place --> - <button data-app-event='admin_templateEditor|containerZipDownloadExec' data-mode='Site' data-hidebuttontext='true'>Download Zip of Template</button> - <button data-app-event='admin_templateEditor|containerFileUploadShow' data-mode='Site' data-hidebuttontext='true'>Upload Template Files</button> -<!-- end project dependant buttons --> - </span> - - - <!-- ### when this is upgraded to delegated events, change the two buttons below to one custom render format w/ a button in it --> - <span class='displayNone' data-bind="var: host(HOSTTYPE); format:showIfMatch; matchValue:SITE;"> - <button data-app-event='admin_batchJob|batchJobExec' data-whitelist='PROJECT' data-type='UTILITY/GITPULL' data-icon-primary="ui-icon-transferthick-e-w">Pull from GitHub</button> - </span> - - <span class='displayNone' data-bind="var: host(HOSTTYPE); format:showIfMatch; matchValue:SITEPTR;"> - <button data-app-event='admin_batchJob|batchJobExec' data-whitelist='PROJECT' data-type='UTILITY/GITPULL' data-icon-primary="ui-icon-transferthick-e-w">Pull from GitHub</button> - </span> - - <span class='displayNone' data-bind="var: host(HOSTTYPE); format:showIfMatch; matchValue:APP;"> - <button data-app-event='admin_batchJob|batchJobExec' data-whitelist='PROJECT' data-type='UTILITY/GITPULL' data-icon-primary="ui-icon-transferthick-e-w">Pull from GitHub</button> - </span> - - <button data-app-event="admin|domainView" data-mode='host'>View Site</button><!-- buttons that always show up should be on the right so they don't move --> - </td> -</tr> - - -</table> +</div> @@ -666,165 +467,110 @@ <h4 class='alignCenter smallPadding'> <div id='pageUtilitiesTemplate' class='page pageUtilities'> - -<table class='noPadOrMargin fullWidth stdCellSpacing'> -<tbody> -<tr> - - <td width="33%" valign="top"> + <div class='floatPanel'> + <div class='ui-widget marginBottom'> + <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> + <h3 class='smallPadding'>Customers</h3> + </div> + + <div class='stdPadding ui-widget-content ui-corner-bottom'> + + <a href="#" onClick="navigateTo('#!ext/admin_customer/showCustomerManager'); return false;">Customer Manager</a> + <div class="helper marginBottom">Find or create a customer record for your website</div> - <div class='ui-widget marginBottom'> + <a href="#" onClick="navigateTo('#!ext/cart_message/showCartManager'); return false;">Cart Manager</a> + <div class="helper marginBottom">Modify carts and communicate directly with buyers.</div> + + <a href="#" onClick="navigateTo('#!ext/admin_wholesale/showPriceSchedules'); return false;">Wholesale Pricing Schedules <!-- (beta) --></a> + <div class="helper marginBottom">Create separate price lists for your wholesale customers</div> + + <a href="#" onClick="navigateTo('#!ext/admin_wholesale/showOrganizationManager'); return false;">Organization Manager</a> + <div class="helper marginBottom">Create / Manage Organizations for wholesale/b2b/resale</div> + + <a href="#" onClick="navigateTo('#!ext/admin_customer/showGiftcardManager'); return false;">GiftCard Manager</a> + <div class="helper marginBottom">Create / Manage GiftCards</div> + + </div> + </div> + <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Customers</h3> + <h3 class='smallPadding'>Manage Apps/Website</h3> </div> <div class='stdPadding ui-widget-content ui-corner-bottom'> - - <a href="#" onClick="navigateTo('#!customerManager'); return false;">Customer Manager</a><br /> - <div class="helper marginBottom">Find or create a customer record for your website</div> - - <a href="#" onClick="navigateTo('#!priceSchedules'); return false;">Wholesale Pricing Schedules <!-- (beta) --></a> - <div class="helper marginBottom">Create separate price lists for your wholesale customers</div> - - <a href="#" onClick="navigateTo('#!organizationManager'); return false;">Organization Manager</a> - <div class="helper marginBottom">Create / Manage Organizations for wholesale/b2b/resale</div> - - <a href="#" onClick="navigateTo('#!giftcardManager'); return false;">GiftCard Manager</a> - <div class="helper marginBottom">Create / Manage GiftCards</div> + <a href="#" onClick="navigateTo('#!ext/admin_tools/showProductExport'); return false;">Product Export</a> + <div class="helper marginBottom">Exports products into a CSV file</div> + + <a href="#" onClick="navigateTo('#!ext/admin_tools/showPPT'); return false;">Product Power Tool</a> + <div class="helper marginBottom">Modify multiple product attributes in mass</div> + + <a href="#" onClick="navigateTo('#!ext/admin_tools/showManageFlexedit'); return false;">Manage Flexedit Fields</a> + <div class="helper marginBottom">Set what fields show in the flexedit panel of the product editor</div> + <a href="#" onClick="navigateTo('#!ext/admin_tools/showAccountUtilities'); return false;">Tech Support Utils</a> + <div class="helper marginBottom">The jundland wastes are not to be traveled lightly.</div> - </div> - </div> - - <div id="tools" class='ui-widget marginBottom'> + </div> + + <div class='ui-widget floatPanel'> <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Tools</h3> + <h3 class='smallPadding'>Social & Communications</h3> </div> + <div class='stdPadding ui-widget-content ui-corner-bottom'> - <a href="#" onClick="navigateTo('#!batchManager'); return false;">Batch Manager</a><br /> - <div class="helper marginBottom">A list of recently run batches, including reports and syndication published files</div> + <a href="#" onClick="navigateTo('#!ext/admin_customer/showCampaignManager'); return false;">Campaigns</a> + <div class="helper marginBottom">Setup campaigns to send newsletters, push notifications, sms, etc</div> - - - <a href="#" onClick="navigateTo('/biz/setup/import/index.cgi?verb=product'); return false;">CSV Import Utility</a><br /> - <div class="helper marginBottom">Import data from a variety of formats</div> -<!-- - <a href="#" onClick="navigateTo('#!ciEngineAgentManager'); return false;">Agent Manager</a><br /> - <div class="helper marginBottom">Manage repricing agents.</div> ---> </div> - </div> + <a href="#" onClick="navigateTo('#!ext/admin_customer/showReviewsManager'); return false;">Reviews</a> + <div class="helper marginBottom">Approve customer reviews of your products</div> + + <a href="#" onClick="navigateTo('#!ext/admin_customer/faqManager'); return false;">Frequently Asked Questions</a> + <div class="helper marginBottom">Help shoppers by answering common questions</div> + + </div> + </div> - </td> - - <td width="33%" valign="top"> - <div class='ui-widget marginBottom'> + + <div class='ui-widget floatPanel'> <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Inventory & Supply Chain</h3> + <h3 class='smallPadding'>Inventory & Supply Chain</h3> </div> <div class='stdPadding ui-widget-content ui-corner-bottom'> - <a href="#" onClick="navigateTo('#!supplierManager'); return false;">Suppliers & Third Party Logistics</a> -<!-- <a href="#" onClick="navigateTo('/biz/manage/suppliers/index.cgi'); return false;">Supply Chain</a> --> + <a href="#" onClick="navigateTo('#!ext/admin_wholesale/showSupplierManager'); return false;">Suppliers & Third Party Logistics</a> <div class="helper marginBottom">Track inventory, pricing and orders with your suppliers or 3PL</div> - <a href="#" onClick="navigateTo('#!warehouseManager'); return false;">Warehouse(s)</a> + <a href="#" onClick="navigateTo('#!ext/admin_wholesale/showWarehouseManager'); return false;">Warehouse(s)</a> <div class="helper marginBottom">Configure Warehouse geo locations and wms zones</div> - <a href="#" onClick="navigateTo('#!warehouseUtilities'); return false;">WHIM: <b>W</b>are<b>H</b>ouse <b>I</b>nventory <b>M</b>anagement</a><br /> - <div class="helper marginBottom">Utility intended for day-to-day use by warehouse employees equipped with a - barcode scanner attached to a tablet, or notebook pc</div> + <a href="#" onClick="navigateTo('#!ext/admin_wholesale/showWarehouseUtilities'); return false;">WHIM: <b>W</b>are<b>H</b>ouse <b>I</b>nventory <b>M</b>anagement</a> + <div class="helper marginBottom">For warehouse employees equipped with a barcode scanner and a tablet or notebook</div> - </div> - </div> - <div class='ui-widget marginBottom'> - <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Marketplace</h3> - </div> - - <div class='stdPadding ui-widget-content ui-corner-bottom'> - <!-- - <a href="#" onClick="navigateTo('/biz/manage/powerlister/index.cgi'); return false;">Powerlister Manager</a> - <div class="helper marginBottom">Track, and update your eBay PowerLister Channels.</div> - --> - <!-- - <a href="#" onClick="navigateTo('/biz/manage/repricing/index.cgi'); return false;">Dynamic Repricing <span class='new'>alpha</span></a> - <div class="helper marginBottom">Automatically raise/lower amazon prices based on competitors pricing.</div> - --> - <a href="#" onClick="navigateTo('#!eBayListingsReport'); return false;">Listing & Event Reports</a> - <div class="helper marginBottom">Listing Events are created anytime a listing is created, modified, or implicitly ended</div> - </div> </div> - <td width="33%" valign="top"> - <div class='ui-widget marginBottom'> - <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Social & Communications</h3> - </div> - - <div class='stdPadding ui-widget-content ui-corner-bottom'> - - <a href="#" onClick="navigateTo('#!campaignManager'); return false;">Campaigns</a> - <div class="helper marginBottom">Setup campaigns to send newsletters, push notifications, sms, etc</div> - - <a href="#" onClick="navigateTo('#!reviewsManager'); return false;">Reviews</a> - <div class="helper marginBottom">Approve customer reviews of your products</div> - - <a href="#" onClick="navigateTo('/biz/manage/faqs/index.cgi'); return false;">Frequently Asked Questions</a> - <div class="helper marginBottom">Help shoppers by answering common questions</div> - - </div> - </div> - - <div class='ui-widget marginBottom'> + <div id="tools" class='ui-widget floatPanel'> <div class='ui-widget-header ui-widget-header-padding ui-corner-top'> - <h3>Manage Apps/Website</h3> + <h3 class='smallPadding'>Tools</h3> </div> - <div class='stdPadding ui-widget-content ui-corner-bottom'> + <a href="#" onClick="navigateTo('#!ext/admin_batchjob/showBatchJobManager'); return false;">Batch Manager</a> + <div class="helper marginBottom">A list of recently run batches, including reports and syndication published files</div> + + <a href="#" onClick="navigateTo('#!ext/admin_medialib/showFileImportPage'); return false;">CSV Import Utility</a> + <div class="helper marginBottom">Import data from a variety of formats</div> <!-- -yoink! - <a href="#" onClick="navigateTo('/biz/manage/snapshots/index.cgi'); return false;">Snapshots</a> - <div class="helper marginBottom">Create snapshots of your product database for backups, and faster performance</div> ---> - -<!-- <a href="#" onClick="navigateTo('/biz/manage/csvexport/index.cgi'); return false;">Product Export</a><br /> --> - <a href="#" onClick="navigateTo('#!productExport'); return false;">Product Export</a><br /> - <div class="helper marginBottom">Exports products into a CSV file</div> - - <a href="#" onClick="navigateTo('#!productPowerTool'); return false;">Product Power Tool</a><br /> - <div class="helper marginBottom">Modify multiple product attributes in mass</div> -<!-- -broke. - <a href="#" onClick="navigateTo('/biz/manage/archive/index.cgi'); return false;">Archive Orders</a><br /> - <div class="helper marginBottom">Hide completed orders</div> - - <a href="#" onClick="navigateTo('/biz/manage/diskspace/index.cgi'); return false;">Disk Space Manager</a><br /> - <div class="helper marginBottom">Manage the amount of disk space in use by your account</div> - - <a href="#" onClick="navigateTo('/biz/syndication/sitemap/index.cgi'); return false;">Static Google SiteMap</a><br /> - <div class="helper marginBottom">Configure nightly generation of a static sitemap file</div> ---> - <a href="#" onClick="navigateTo('#!manageFlexedit'); return false;">Manage Flexedit Fields (beta)</a><br /> - <div class="helper marginBottom">Set what fields show in the flexedit panel of the product editor</div> - - <a href="#" onClick="navigateTo('#!accountUtilities'); return false;">Tech Support Utils <!-- (beta) --></a> - <div class="helper marginBottom"></div> + <a href="#" onClick="navigateTo('#!ext/admin_tools/showciEngineAgentManager'); return false;">Agent Manager</a> + <div class="helper marginBottom">Manage repricing agents.</div> +--> </div> + </div> - </div> - </div> - </td> - -</tr> -</tbody> - -</table> </div> @@ -862,7 +608,7 @@ <h3>Website Statistics</h3> <div class='stdPadding ui-widget-content ui-corner-bottom'> <p class='helper'>Learn what are visitors are doing on your site.</p> <a href="http://www.google.com/analytics" target='_blank'>Google Analytics</a><br> - <a href="#" onClick="navigateTo('/biz/setup/search/index.cgi?ACTION=LOGS');">Website Search Logs</a> + <a href="#" onClick="navigateTo('#!/biz/setup/search/index.cgi?ACTION=LOGS');">Website Search Logs</a> </div> </div> @@ -902,7 +648,7 @@ <h3>Website Statistics</h3> <ul> - <li><a href='#' onClick="app.ext.admin.a.showCreateProductDialog(); return false;">New Product</a></li> + <li><a href='#' onClick="adminApp.ext.admin.a.showCreateProductDialog(); return false;">New Product</a></li> <li><a href='#' onClick="$(this).parent().find('ul').toggle();">Filter Product</a> <ul class='displayNone tagFilterList'> <li>IS_FRESH</li> @@ -938,7 +684,7 @@ <h3>Website Statistics</h3> <li data-mktid="EBS">eBay Store</li> </ul> </li> - <li><a href='#' onClick="return showUI('/biz/product/options2/index.cgi?product=',{'targetID':'productTabMainContent'});">Store Option Groups</a></li> + <li><a href='#' onClick="return navigateTo('#!/biz/product/options2/index.cgi?product=',{'targetID':'productTabMainContent'});">Store Option Groups</a></li> <li class='displayNone' id='manCatsParent'><a href='#' onClick="$(this).parent().find('ul').toggle();">Management Categories:</a> <ul id='manCats' class='displayNone'> </ul> @@ -985,14 +731,14 @@ <h3>Website Statistics</h3> <div id='prodCreateMessaging'></div> -<form name="createNewProductForm" action="#" method="POST" onSubmit="app.ext.admin.u.handleCreateNewProduct($(this).serializeJSON()); return false;"> +<form name="createNewProductForm" action="#" method="POST" onSubmit="adminApp.ext.admin.u.handleCreateNewProduct($(this).serializeJSON()); return false;"> <fieldset class='marginBottom'> <legend>Required Fields</legend> <div class='marginBottom'><label>Product ID/SKU:</label> <input type="text" name="pid" SIZE="20" MAXLENGTH="20" VALUE="" required='required' /></div> <div class='marginBottom'><label >Product Name:</label> <INPUT TYPE="text" NAME="zoovy:prod_name" SIZE="55" maxlength="55" VALUE="" required='required' /></div> - <div class='marginBottom'><label >Sell For Price:</label> $<INPUT TYPE="number" NAME="zoovy:base_price" VALUE="" SIZE="15" required='required'></div> + <div class='marginBottom'><label >Sell For Price:</label> $<INPUT type='number' class='smallInput' NAME="zoovy:base_price" VALUE="" SIZE="15" required='required'></div> </fieldset> @@ -1078,138 +824,6 @@ <h3>Website Statistics</h3> -<!-- -////////////////////////// EMAIL TOOL \\\\\\\\\\\\\\\\\\\\\\\\\ ---> - - - - -<div id='mailToolTemplate'> -<form action='#'> -<fieldset class='labelsAsBreaks alignedLabels alignedInputs marginBottom'> -<label> - <span>Message source:</span> - <select name='MSGID' data-bind="var: emailList(@MSGS); format: emailMessagesListOptions; extension:admin;" data-app-event="admin_orders|orderEmailCustomChangeSource"> - <option value='BLANK'>blank</option> - </select> -</label> - -<label> - <span>Subject:</span> - <input type='text' name='SUBJECT' required='required' maxlength="100" /> -</label> - -<label> - <span>Message:</span> - <textarea name='BODY' rows='10' required='required'></textarea> -</label> -</fieldset> - - -<fieldset class='updateSystemMessageContainer marginBottom'> -<label> - <input type='checkbox' name='updateSystemMessage' disabled='disabled' /> - Save these changes to the message <span class='msgType'></span> for all future emails<!-- the .msgType is used to populate the message ID in focus. --> -</label> -</fieldset> - -<button data-app-event="admin|execMailToolSend">send email</button> - -</form> -</div> - - - - - -<!-- -////////////////////////// PROJECTS \\\\\\\\\\\\\\\\\\\\\\\\\ ---> - - - - - - -<table> -<tr id='projectsListTemplate'> - <td data-bind="var: projects(ID); format:text;"></td> - <td data-bind="var: projects(TITLE); format:text;"></td> - <td data-bind="var: projects(TYPE); format:text;"></td> - <td data-bind="var: projects(CREATED_TS); format:text;" class='hideInDetailMode'></td> - <td data-bind="var: projects(UPDATED_TS); format:text;" class='hideInDetailMode'></td> - <td class='alignRight'> - <button data-app-event='admin|projectRemove'>Remove this Project</button> - <button data-app-event='admin|projectGitRepoOpen'>Visit GitHub Repo</button> - <button data-app-event='admin|projectLinkOpen'>Update Project From Repo</button> - <button data-app-event='admin|projectUpdateShow'>View Details</button><!-- this will eventually be 'edit' --> - </td> -</tr> -</table> - - -<div id='projectDetailTemplate' class='labelsAsBreaks clearfix'> - - <h3 class='label' data-bind="var: project(TITLE); format:text;"></h3> - <div class='label' data-bind="var: project(ID); format:text; pretext:ID: ;"></div> - <div class='label' data-bind="var: project(TYPE); format:text; pretext:Type: ;"></div> - <div class='label' data-bind="var: project(CREATED_TS); format:text; pretext:Created: ;"></div> - <div class='label' data-bind="var: project(APP_VERSION); format:text; pretext:App version: ;"></div> - <div class='label' data-bind="var: project(APP_RELEASE); format:text; pretext:App release: ;"></div> - <div class='label' data-bind="var: project(APP_ROOT); format:text; pretext:App root: ;"></div> - <div class='label' data-bind="var: project(GITHUB_REPO); format:text; pretext:GitHub repository: ;"></div> - <div class='label' data-bind="var: project(GITHUB_BRANCH); format:text; pretext:GitHub branch: ;"></div> - <div class='label' data-bind="var: project(APP_EXPIRE); format:text; pretext:Expiration: ;"></div> - <div class='label' data-bind="var: project(UPDATED_TS); format:text; pretext:Last update: ;"></div> - -</div> - - -<div id='projectCreateTemplate'> - -<form onSubmit='return false'> -<fieldset class='labelsAsBreaks alignedLabels alignedInputs'> - <label> - <span>Project title</span> - <input type="text" name="title" required='required' /> - <span class='toolTip' title="ex: domain.com master">?</span> - </label> - - - <label> - <span>Project type</span> - <select name="type" > - <option value="APP">Shopping App (index.html)</option> -<!-- <option value="VSTORE">Legacy vStore Project (beta)</option> --> - <option value="ADMIN">Hosted Admin App (beta)</option> - <option value="CHECKOUT">Checkout Intercept (beta)</option> - <option value="DSS">Decision Support System (beta)</option> - </select> - </label> - - - <label> - <span>GitHub repo</span> - <input type="url" name="repo" maxlength="128" required='required' /> - </label> - <p class="hint">ex: http://github.com/yourname/project.git<br /> - At this time only GITHUB hosted projects with public http urls are supported. - </p> - - <label> - <span>GitHub branch</span> - <input type="text" name="branch"maxlength="20" /> - </label> - -<!-- <label><input type="checkbox" name="domain"> Reserve a test domain for this project.</label> --> - <div class='buttonset'> - <button data-app-event="admin|projectCreateExec">Save</button> - </div> -</fieldset> -</form> - -</div> @@ -1233,9 +847,8 @@ <h3 class='label' data-bind="var: project(TITLE); format:text;"></h3> <td data-bind="var: projects(PROFILE); format:text;"></td> <td data-bind="var: projects(SCHEDULE); format:text;"></td> <td class='alignRight'> - <button data-app-event="admin|adminRSSRemove">Delete Feed</button> -<!-- <button >Clone Feed</button>--> - <button data-app-event="admin|adminRSSUpdateShow">Edit Feed</button> + <button data-app-click="admin|adminRSSRemove" class='applyButton' data-text='false' data-icon-primary='ui-icon-trash'>Delete Feed</button> + <button data-app-click="admin|adminRSSUpdateShow" class='applyButton' data-text='false' data-icon-primary='ui-icon-pencil'>Edit Feed</button> </td> </tr> </table> @@ -1247,7 +860,7 @@ <h3 class='label' data-bind="var: project(TITLE); format:text;"></h3> <legend>General Properties</legend> <label> <span>Domain/Profile:</span> - <select name="profile" required='required' data-bind="var: rss(@DOMAINS); format:optionsFromList; text:DOMAINNAME; value:DOMAINNAME;" /> + <select name="profile" required='required' data-bind="var: rss(@DOMAINS); format:optionsfromlist; text:DOMAINNAME; value:DOMAINNAME;" /> <option></option> </select> </label> @@ -1260,8 +873,8 @@ <h3 class='label' data-bind="var: project(TITLE); format:text;"></h3> </label> <label> <span>Image WxH</span> - <input type="number" step='1' min='1' name="image_w" required='required' value="75" size='4' data-bind="var: rss(image_w); format: popVal;" /> x - <input type="number" step='1' min='1' name="image_h" required='required' value="75" size='4' data-bind="var: rss(image_h); format: popVal;" /> + <input type='number' class='smallInput' step='1' min='1' name="image_w" required='required' value="75" size='4' data-bind="var: rss(image_w); format: popVal;" /> x + <input type='number' class='smallInput' step='1' min='1' name="image_h" required='required' value="75" size='4' data-bind="var: rss(image_h); format: popVal;" /> </label> <label> @@ -1272,7 +885,7 @@ <h3 class='label' data-bind="var: project(TITLE); format:text;"></h3> <label> <span>Feed Link</span> - <input type="url" name="feed_link" value="" data-bind="var: rss(feed_link); format: popVal;" /> + <input type="text" name="LINK" value="" data-bind="var: rss(LINK); format: popVal;" readonly /> <span class="toolTip" title="The URL to your store, or for this promotion.">?</span> </label> <label> @@ -1300,7 +913,7 @@ <h3 class='label' data-bind="var: project(TITLE); format:text;"></h3> <label> <span>Source List:</span> - <select name="list" required='required' data-bind="var: rss(@paths); format:optionsFromList;"> + <select name="list" required='required' data-bind="var: rss(@paths); format:optionsfromlist;"> <option></option> </select> <span class="toolTip" title="The list from which this RSS feed is built (where the product come from).">?</span> @@ -1313,7 +926,7 @@ <h3 class='label' data-bind="var: project(TITLE); format:text;"></h3> <label> <span>Pricing Schedule:</span> - <select name='schedule' data-bind="var: rss(@SCHEDULES);format:optionsFromList; text:SID; value:SID;"> + <select name='schedule' data-bind="var: rss(@SCHEDULES);format:optionsfromlist; text:SID; value:SID;"> <option>none</option> </select> </label> @@ -1384,14 +997,14 @@ <h3 class='label' data-bind="var: project(TITLE); format:text;"></h3> -<div id='dualModeTemplate' class='dualModeContainer' data-app-role='dualModeContainer' data-app-mode='list'> +<div id='dualModeTemplate' class='dualModeContainer marginBottom' data-app-role='dualModeContainer' data-app-mode='list'> <section class='dualModeDetail' data-app-role='dualModeDetail'></section> <section class='dualModeList' data-app-role='dualModeList'> <div class='ui-widget-header ui-corner-top'><!-- do NOT add clearfix to this. screws up right column of panels --> <div class='floatRight smallPadding smallButton' data-app-role='dualModeListButtons'> - <button data-app-event='admin|toggleDualMode'>Toggle between list and detail view</button> + <button data-app-click='admin|toggleDMI' class='applyButton displayNone' data-text='false' data-icon-primary='ui-icon-seek-next'>Toggle between list and detail view</button> </div> <h1 class='dualModeHeader' data-app-role='dualModeListHeader'><!-- title will go here --></h1> @@ -1470,9 +1083,10 @@ <h6 data-pickmethod='SUPPLIER'>By Supplier</h6> <div data-bind="var: list(@SUPPLIERS); format: processList; loadsTemplate:pickerSupplierRowTemplate;"></div> <h6 data-pickmethod='MCAT'>By Management Category</h6> - <div data-bind="var: list(%CATEGORIES); format: manageCatsList; extension:admin_prodEdit; loadsTemplate:pickerManageCatsRowTemplate;"></div> + <div data-bind="var: list(%CATEGORIES); format: manageCatsList; extension:admin_prodedit; loadsTemplate:pickerManageCatsRowTemplate;"></div> <h6 data-pickmethod='CUSTOM'>Comma Separated List</h6> + <div data-contentloaded='true'> <textarea name='csv' rows='10' class='fullWidth'></textarea> <span class='hint'>use commas or linebreaks to separate each product</span> @@ -1496,3 +1110,36 @@ <h6 data-pickmethod='CUSTOM'>Comma Separated List</h6> <label id='pickerLaunchProfileRowTemplate'> <input type='checkbox' name='' data-bind="var:list(PROFILE); format:assignAttribute; attribute:name; valuePretext:PROFILE+;" /><span data-bind="var: list(PROFILE); format:text;"></span> </label> + + + + + + + + +<div id='tlctest'> +<h1>Some TLC for testing. execute this with #!/ext/admin/tlcTest</h1> +<h2>Data src is adminDomainList. pretty much can guarantee it's in memory.</h2> +<br><br> +<!-- +templateidexist -> part of an IS. +--> +<h3 data-tlc="bind $var '.media-host'; if(is $tlclisttest --templateidexists;){{ apply --append;}};">media host: </h3> +<table> +<tbody data-tlc="bind $items '.@DOMAINS'; foreach $item in $items {{ transmogrify --templateid='tlclisttest' --dataset=$item; apply --append;}};"></tbody> +</table> +</div> + +<table> + <tr id='tlclisttest'> + <td> + <img data-tlc="bind $var '.LOGO'; if(is $var --notblank;){{apply --img --bob='was here' --media=$var --width=25 --height=25 --bgcolor='#ffffff' --replace;}};" src="blank.gif" class="prodThumb" alt=""> + </td> + <td> + <img data-tlc="bind $var '.LOGO'; if(is $var --notblank;){{apply --img --bob='was here' --media=$var --imgdefault --replace;}};" width='50' height='50' data-bgcolor='#fffff' src="blank.gif" class="prodThumb" alt=""> + </td> + <td data-tlc="bind $var '.DOMAINNAME'; format --truncate='20' apply --append;"></td> + <td data-tlc="bind $var '.LOGO'; if(is $var --notblank;){{apply --imageurl --media=$var --width=25 --height=25 --bgcolor='#ffffff' --append;}};"></td> + </tr> +</table> \ No newline at end of file diff --git a/extensions/admin/tools.html b/extensions/admin/tools.html index 55faae5e4..04c9bf89f 100644 --- a/extensions/admin/tools.html +++ b/extensions/admin/tools.html @@ -2,7 +2,7 @@ <div id='productPowerToolTemplate'> -<form action='#' onSubmit="return false" class='labelsAsBreaks' id='productPowerToolForm'> +<form action='#' onSubmit="return false" class='labelsAsBreaks' id='productPowerToolForm' novalidate> <input type="hidden" value="0" name="JOBID" /> @@ -171,7 +171,7 @@ <h2>Which attribute to Change</h2> <label class='displayNone'> <span>Custom Attribute:</span> - <input type="text" name='attrib_custom'> + <input type="text" name='attrib_custom' /> </label> @@ -322,14 +322,18 @@ <h4>Review Actions</h4> </table> </div> - <!-- + <label class='marginBottom marginTop'> - <input type="text" name="jobtitle" placeholder='Job Title (optional)' value="" size="30" /> - <span class='toolTip' title="Job title is optional, but is very useful if you plan to use this again.">?</span> + <input type="text" name="jobtitle" placeholder='Job Title (optional)' value="" size="20" maxlength="20" /> + <span class='toolTip' title="if job title is set, the job will be saved for future re-use.">?</span> </label> - --> - <button data-app-role='saveButton' data-app-event='admin_tools|powerToolBatchJobExec' class='ui-state-focus'>Git er Done</button> - + + <button data-app-role='saveButton' data-app-event='admin_tools|powerToolBatchJobExec' class='ui-state-focus'>Engage</button> + <hr /> + + <div data-bind="forceRender:true; format:batchJobParametersList; extension:admin_batchjob; batch_exec:UTILITY/PRODUCT_POWERTOOL;"></div> + + </div> </div> </td> @@ -403,7 +407,7 @@ <h4>Review Actions</h4> <div id='CIE_DSA_AddUpdateTemplate'> -<form action='#' onsubmit="return false" class='labelsAsBreaks alignedLabels alignedInputs'> +<form action='#' onsubmit="return false" class='labelsAsBreaks alignedLabels alignedInputs' data-app-submit="admin|submitForm"> <input type='hidden' name='GUID' value='' data-bind='var: agent(GUID); format:popVal;' /> @@ -411,7 +415,7 @@ <h4>Review Actions</h4> <label> <span>Name</span> - <input name='AGENTID' value='' data-bind='var: agent(AGENTID); format:popVal;' data-app-event='admin|alphaNumeric' /> + <input name='AGENTID' value='' data-bind='var: agent(AGENTID); format:popVal;' data-input-keyup="format" data-input-format='alphanumeric' /> </label> <label> @@ -420,7 +424,7 @@ <h4>Review Actions</h4> </label> -<button data-app-event="admin|processForm">Save</button> +<button class='applyButton'>Save</button> </fieldset> </form> @@ -456,8 +460,8 @@ <h4>Review Actions</h4> <td data-bind="var: file(EXPIRES); format:text;" class='hideInDetailMode'></td> <td data-bind="var: file(CREATEDBY); format:text;" class='hideInDetailMode'></td> <td class='alignRight'> - <button data-app-event="admin|tagRowForRemove">Delete</button> - <button data-app-event="admin_tools|adminPrivateFileDownloadExec">Download</button> + <button data-app-click="admin|tagRow4Remove" class='applyButton' data-text='false' data-icon-primary='ui-icon-close'>Delete</button> + <button data-app-click="admin_tools|adminPrivateFileDownloadExec" class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowthickstop-1-s'>Download</button> </td> </tr> </table> @@ -479,7 +483,7 @@ <h4>Review Actions</h4> <form action='#' onSubmit="return false" class='labelsAsBreaks' name='productExportToolForm'> <input type="hidden" value="0" name="JOBID" /> -<input type="hidden" value="PRODUCT" name="EXPORT" /> +<input type="hidden" value="PRODUCTS" name="EXPORT" /> <h1>Product Export Tool</h1> @@ -599,10 +603,11 @@ <h1>Account Utilities</h1> <p class="hint marginTop marginBottom clearfix">Please make sure all users are logged out of your account, and all sync processes are disabled while using utilities in this area. They are *very* resource intensive and can cause outages if concurrent use is attempted.</p> - <section class='floatRight marginBottom marginLeft' data-app-role='accountUtilityLogContainer'> + <section class='floatRight marginBottom marginLeft' data-app-role='accountUtilityLogContainer' data-tablefilter-role='container'> + <input name='tableSearchQuery' type='search' placeholder='filter logs' data-app-keyup="admin|tableFilter" class='floatRight' /> <h2>Logs</h2> - <table class='gridTable applyAnytable marginTop'> + <table class='gridTable applyAnytable marginTop' data-tablefilter-role='table'> <thead> <tr> <th>Filename</th> @@ -619,47 +624,61 @@ <h2>Product/Inventory</h2> <table class='marginTop'> <tbody> <tr> - <td class='valignTop'><button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/INVENTORY_RESUMMARIZE','%vars':{}}); return false;">Inventory Resummarize</button></td> + <td class='valignTop'><button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/INVENTORY_RESUMMARIZE','%vars':{}}); return false;">Inventory Resummarize</button></td> <td class='valignTop small'> Forces the system to recompute the summary inventory for all SKU's. This should not be necessary unless you have encountered a bug which caused inventory summaries to not match inventory detail. </td> </tr> <tr> - <td class='valignTop'><button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/PRODUCT_CLEANUP','%vars':{}}); return false;">Product Cleanup</button></td> + <td class='valignTop'><button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/PRODUCT_CLEANUP','%vars':{}}); return false;">Product Cleanup</button></td> <td class='valignTop small'> Resets/Rebuilds Product Index, clears out deleted items, and source pid from zoovy:related_products, and zoovy:accessory_products. Removes unicode characters. </td> </tr> <tr> - <td class='valignTop'><button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/INVENTORY_CLEANUP','%vars':{}}); return false; ">Inventory Cleanup</button></td> + <td class='valignTop'><button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/INVENTORY_CLEANUP','%vars':{}}); return false; ">Inventory Cleanup</button></td> <td class='valignTop small'> Removes orphan inventory records which are not associated with a sku, creates records w/0 qty for pids which don't have inv. records. </td> </tr> <tr> - <td class='valignTop'><button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/INVENTORY_UPDATE_RESERVES','%vars':{}}); return false; ">Inventory Update Reserves</button></td> + <td class='valignTop'><button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/INVENTORY_UPDATE_RESERVES','%vars':{}}); return false; ">Inventory Update Reserves</button></td> <td class='valignTop small'> Removes orphaned inventory reservations / verifies reserves. </td> </tr> <tr> <td class='valignTop'> - <button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/IMAGE_REINDEX','%vars':{}}); return false; ">Image Reindex</button></td> + <button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/IMAGE_REINDEX','%vars':{}}); return false; ">Image Reindex</button></td> <td class='valignTop small'> Image Reindex </td> </tr> <tr> <td class='valignTop'> - <button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/ELASTIC_REBUILD','%vars':{}}); return false; ">Elastic Rebuild</button></td> + <button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/ELASTIC_REBUILD','%vars':{'index':'public'}}); return false; ">Elastic Rebuild (Public)</button></td> <td class='valignTop small'> - Elastic Search Rebuild (note: will be offline/unavailable during rebuild) + Elastic Product Search Rebuild (note: will be offline/unavailable during rebuild) </td> </tr> <tr> <td class='valignTop'> - <button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/PRODUCT_SALESRANK','%vars':{}}); return false; ">Update SalesRanks</button></td> + <button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/ELASTIC_REBUILD','%vars':{'index':'private'}}); return false; ">Elastic Rebuild (Private)</button></td> + <td class='valignTop small'> + Elastic Private Search Rebuild (note: will be offline/unavailable during rebuild) + </td> + </tr> + <tr> + <td class='valignTop'> + <button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/EBAY_LISTING_DOWNLOAD','%vars':{}}); return false; ">eBay Listing Download</button></td> + <td class='valignTop small'> + eBay Listing Complete Download (note: do not launch any new listings while this is running, eBay limits this to once per day per token) + </td> + </tr> + <tr> + <td class='valignTop'> + <button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/PRODUCT_SALESRANK','%vars':{}}); return false; ">Update SalesRanks</button></td> <td class='valignTop small'> Goes through all products which have customer reviews and updates zoovy:prod_salesrank <p class="warning ui-corner-all stdPadding">Notice about Sales Rank:<br /> @@ -679,23 +698,31 @@ <h2>App</h2> <table class='marginTop'> <tbody> <tr> - <td class='valignTop'><button onClick="showUI('#!showPlatformInfo'); return false;">App/Server Details</button></td> + <td class='valignTop'><button class='applyButton' onClick="navigateTo('#!ext/admin_support/showPlatformInfo'); return false;">App/Server Details</button></td> <td>Some details about the server you are on, app version, etc.</td> </tr> <tr> - <td class='valignTop'><button onclick="app.ext.admin.u.selectivelyNukeLocalStorage();">Clear Some Localstorage</button></td> + <td class='valignTop'><button class='applyButton' onclick="adminApp.ext.admin.u.selectivelyNukeLocalStorage();">Clear Some localStorage</button></td> + <td class='valignTop small'> + This will selectively clear local storage for the admin interface. Clear all data but login and device specific preferences from localStorage. + </td> + </tr> + <tr> + <td class='valignTop'><button class='applyButton' onclick="localStorage.clear(); location.reload(); ">Clear localStorage</button></td> <td class='valignTop small'> - This will selectively clear local storage for the admin interface. It will clear data such as product, category ,etc, but leave preferences such as panel sequence , panel state (open/closed) etc. It will not impact local storage for other domains. This action is browser-specific. + This will clear all local storage for the admin interface/domain. It will not impact local storage for other domains. This action is browser-specific. You will need to log in again. All device specific preferences (what panels are open/closed by default) will reset.<br /> + <b>This action will refresh your browser</b>. </td> </tr> <tr> - <td class='valignTop'><button onclick="localStorage.clear();">Clear Localstorage</button></td> + <td class='valignTop'><button class='applyButton' onclick="sessionStorage.clear(); location.reload(); ">Clear sessionStorage</button></td> <td class='valignTop small'> - This will clear all local storage for the admin interface/domain. It will not impact local storage for other domains. This action is browser-specific. + This will clear all session storage for the admin interface/domain. Some data, such as customer or product, is only retrieved once per session. Session storage is where it's kept. This action will not impact session storage for other domains. This action is browser-specific.<br /> + <b>This action will refresh your browser</b>. </td> </tr> <tr> - <td class='valignTop'><button data-app-event='admin_support|ping'>Ping!</button></td> + <td class='valignTop'><button class='applyButton' data-app-click='admin_support|ping'>Ping!</button></td> <td>The simplest of calls on our API. Hit this and get a report of how long it took to make. For accurate results, make sure entire page is done loading prior to running this.</td> </tr> </tbody> @@ -705,13 +732,29 @@ <h2>App</h2> </section> + <section class='marginTop marginBottom'> + <h2>Customer/CRM</h2> + <table class='marginTop'> + <tbody> + <tr> + <td class='valignTop'><button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'guid' : adminApp.u.guidGenerator(),'type' : 'UTILITY/CUSTOMER_SCRUB'}); return false; ">Clean Subscriber Lists</button></td> + <td class='valignTop small'> + Remove all duplicates and clear invalid emails. + </td> + </tr> + </tbody> + </table> + </section><!-- /ebay --> + + + <section class='marginTop marginBottom'> <h2>eBay</h2> <table class='marginTop'> <tbody> <tr> - <td class='valignTop'><button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/EBAY_UPDATE','%vars':{'f':'end-all'}}); return false; ">Close All Listings</button></td> + <td class='valignTop'><button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/EBAY_UPDATE','%vars':{'f':'end-all'}}); return false; ">Close All Listings</button></td> <td class='valignTop small'> Ends all active listings on eBay. </td> @@ -728,7 +771,7 @@ <h2>Reporting</h2> <tbody> <tr> <td class='valignTop'> - <button onclick="app.ext.admin_batchJob.a.adminBatchJobCreate({'type':'UTILITY/KPIBI_RESET','%vars':{}}); return false; ">Reset KPIBI</button> + <button class='applyButton' onclick="adminApp.ext.admin_batchjob.a.adminBatchJobCreate({'type':'UTILITY/KPIBI_RESET','%vars':{}}); return false; ">Reset KPIBI</button> </td> <td class='valignTop'> Rebuilds all KPIBI data for the last year @@ -741,17 +784,17 @@ <h2>Reporting</h2> <section class='marginTop marginBottom'> <h2>Inspectors & More</h2> - <form class='marginTop'><label><span>Order</span><input type='text' name='orderid' class='marginLeft marginRight' /></label><button data-app-event='admin_tools|inspectorExec' data-inspect='order'>Go</button></form> + <form class='marginTop'><label><span>Order</span><input type='text' name='orderid' class='marginLeft marginRight' /></label><button data-app-click='admin_tools|inspectorExec' data-inspect='order'>Go</button></form> <form action='#' onSubmit='return false'><label><span>Product ID</span><input type='text' name='pid' class='marginLeft marginRight' /></label> - <button data-app-event='admin_tools|inspectorExec' data-inspect='product'>Inspect</button> + <button data-app-click='admin_tools|inspectorExec' data-inspect='product'>Inspect</button> <button data-app-click='admin_tools|forcePIDIntoPTL' class='applyButton' title="This will add the sku in question to the product task list">Force into Product Task</button> </form> - <form><label><span>Shipping Methods/Rules</span><span class='toolTip' title="This will list the ship methods and their rules for the partition in focus.">?</span></label><button class='marginLeft' data-app-event='admin_tools|inspectorExec' data-inspect='shipmethods'>Go</button></form> + <form><label><span>Shipping Methods/Rules</span><span class='toolTip' title="This will list the ship methods and their rules for the partition in focus.">?</span></label><button class='marginLeft' data-app-click='admin_tools|inspectorExec' data-inspect='shipmethods'>Go</button></form> <!-- - started, but not done yet. - <form><label><span>Site Debug</span><span class='toolTip' title="A variety of site debuggging tools (shipping, tax, promotions, etc)">?</span></label><button class='marginLeft' onClick='app.ext.admin_tools.a.siteDebugger(); return false;'>Go</button></form> --> + started, but not done yet. --> + <form><label><span>Site Debug</span><span class='toolTip' title="A variety of site debuggging tools (shipping, tax, promotions, etc)">?</span></label><button class='marginLeft' data-app-click='admin_tools|siteDebugDialog'>Go</button></form> </section> @@ -760,9 +803,9 @@ <h2>Raw API Request</h2> <form action='#' onSubmit='return false' class='labelsAsBreaks alignedInputs marginTop'> <label> <span>Query</span> - <textarea name='JSON' rows='10'></textarea> + <textarea name='JSON' rows='10' class='fullWidth'></textarea> </label> - <button data-app-event="admin_tools|rawJSONRequestExec">Make Request</button> + <button data-app-click="admin_tools|rawJSONRequestExec" class='applyButton'>Make Request</button> <ul> <li>There is no 'undo' for this. Use with extreme caution.</li> <li>https://github.com/zoovy/AnyCommerce-Development/wiki/API_Call_Reference</li> @@ -772,22 +815,11 @@ <h2>Raw API Request</h2> </div><!-- /accountUtilitiesTemplate --> -<!-- - -<h2>Desktop Client</h2> - <div class="hint">reset the changed to 0 (will cause orders to resync)</div> - From YYYYMMDDHHMMSS:<input type="textbox" value="" name="FROMYYYYMMDDHHMMSS" id="FROM" class='applyDatepicker'><br> - Till YYYYMMDDHHMMSS:<input type="textbox" value="" name="TILLYYYYMMDDHHMMSS" id="TILL" class='applyDatepicker'><br> - <button onclick="navigateTo('/biz/manage/support/index.cgi?VERB=RESET-ORDER-CHANGED&FROM='+jQuery('#FROM').val()+'&TILL='.jQuery('#TO').val());">Reset</button> - -</div> - ---> <table> <tr id='accountUtilityLogRowTemplate'> - <td data-bind="var: log(TITLE); format:text;"></td> - <td><button data-app-event='admin_tools|adminPlatformLogDownloadExec'>download</button></td> + <td data-bind="var: log(TITLE); format:text;" class='isSearchable'></td> + <td><button data-app-click='admin_tools|adminPlatformLogDownloadExec' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowthickstop-1-s'>download</button></td> </tr> </table> @@ -799,57 +831,70 @@ <h1>Product Flexedit Manager</h1> <div class='ui-widget twoColumn'> <h3 class='stdPadding ui-widget-header ui-corner-top'>Enabled Attributes</h3> <form class='ui-widget-content ui-corner-bottom stdPadding' data-app-role='flexeditEnabledListContainer' action='#' onSubmit='return false'> - - <fieldset> + + <fieldset data-table-role='container'> <table data-app-role='dataTable' class=' fullWidth gridTable flexeditEnabledListContainer'> - <tbody data-bind="var: flexedit(%flexedit); format:processList; loadsTemplate:flexeditAttributeRowTemplate;" class='connectMe' data-app-role='flexeditEnabledListTbody' > - - </tbody> + <tbody data-table-role='content' data-bind="var: flexedit(%flexedit); format:processList; loadsTemplate:flexeditAttributeRowTemplate;" class='connectMe' data-app-role='flexeditEnabledListTbody' ></tbody> </table> <div class='buttonset marginTop alignRight'> - <button data-app-event='admin_tools|flexeditAttributeCreateUpdateShow' data-mode='create'>Add Custom</button> - <button data-app-event='admin_tools|flexeditSaveExec'>Save Changes</button> + <button data-app-click='admin_tools|flexeditAttributeCreateUpdateShow' data-mode='create' class='applyButton'>Add Custom</button> + <button data-app-click='admin_tools|flexeditSaveExec' class='applyButton'>Save Changes</button> </div> <!-- the list of fields that save per flex attribute is whitelisted. see admin_tools.e.flexeditSaveExec --> - <div class='labelsAsBreaks displayNone' data-app-role='flexeditAttributeAddUpdateContainer'> - <label><span>Attribute ID </span><input name='id' value='' type='text' data-bind='var: flexedit(id); format:popVal;' /></label> + <div class='labelsAsBreaks displayNone marginTop' data-app-role='flexeditAttributeAddUpdateContainer' data-table-role='inputs'> + <label><span>Attribute ID </span><input name='id' value='' type='text' required='required' data-bind='var: flexedit(id); format:popVal;' data-input-keyup="format" data-input-format='lowercase,flex' /></label> <input name='guid' value='' type='hidden' data-bind='var: flexedit(guid); format:popVal;' /><!-- needed for data table. if guid is already in table, will do an update instead of an add --> <label><span>Title</span><input name='title' type='text' maxlength="25" data-bind='var: flexedit(title); format:popVal;' /></label> - <label><span>Index</span><input name='index' type='text' maxlength="20" data-bind='var: flexedit(index); format:popVal;' /> <span title="If set, field will be indexed by elastic. value should be same as attribute ID without zoovy: prefix (ex: zoovy:prod_msrp index should be prod_msrp)" class='toolTip'>?</span></label> + <label><span>Index</span><input name='index' type='text' maxlength="20" data-bind='var: flexedit(index); format:popVal;' data-input-keyup="format" data-input-format='lowercase,alphanumeric' /> <span title="If set, field will be indexed by elastic. value should be same as attribute ID without zoovy: prefix (ex: zoovy:prod_msrp index should be prod_msrp)" class='toolTip'>?</span></label> <label> <span>Type</span> - <select name='type' data-bind='var: flexedit(type); format:popVal;'> + <select name='type' data-bind='var: flexedit(type); format:popVal;' required='required' data-panel-selector=".flexEditTypeInputs" data-input-change='show-panel'> + <option value='boolean'>Boolean (checkbox)</option> <option value='checkbox'>Checkbox</option> <option value='currency'>Currency</option> <option value='image'>Image</option> <option value='keyword'>Keyword</option> + <option value='keywordlist'>Keyword list</option> <option value='number'>Number</option> - <option value='select'>Select</option> - <option value='textbox'>Text (small block)</option> - <option value='textarea'>Text (big block)</option> + <option value='select' data-show-panel='flexEditOptionsInput'>Select</option> + <option value='textbox'>Text (single line)</option> + <option value='textarea'>Text (multi line)</option> <option value='weight'>Weight</option> </select> </label> + + <!-- add this to your select list. make the class very specific. anything with this class will get toggled off onChange --> + + +<!-- add this to each option that 'reveals' something. make the value very specific --> + + +<!-- add one of these for each matching 'option' that reveals content. Class should match panel-selector. panel-id should match show-panel value in corresponding option --> + <div data-panel-id='flexEditOptionsInput' class='displayNone flexEditTypeInputs'> <label> <span>Options</span> - <textarea data-stringify='true' name='options' data-bind='var: flexedit(options); format:popVal;'></textarea> + <textarea required='required' class='skipIfHidden fullWidth' rows='10' data-format-rules='validateJSON' data-stringify='true' name='options' data-bind='var: flexedit(options); format:popVal;'></textarea> </label> -<!-- <button data-app-event="admin_tools|flexDataTableAddEditCancel">Cancel</button> --> - <button data-app-event="admin_config|dataTableAddExec">Apply Attribute</button> + </div> + <button data-app-click="admin_tools|flexDataTableAddEditCancel" class='applyButton'>Cancel</button> + <button data-app-click="admin_config|dataTableAddUpdate" class='applyButton' data-hide-inputs-onapply='true'>Apply Attribute</button> </div> </fieldset> </form> </div> - <section class='ui-widget twoColumn column2'> + <section class='ui-widget twoColumn column2' data-tablefilter-role='container'> <h3 class='stdPadding ui-widget-header ui-corner-top'>Popular Attributes</h3> <div class='ui-widget-content ui-corner-bottom stdPadding flexeditMasterListContainer' data-app-role='flexeditMasterListContainer'> - <div class='buttonset alignRight'><button data-app-event="admin_tools|flexeditAttributesFullListShow">Full Attribute List</button></div> + <div class='buttonset'> + <input name='tableSearchQuery' type='search' placeholder='filter attributes' x-webkit-speech="x-webkit-speech" data-app-keyup="admin|tableFilter" /> + <button data-app-click="admin_tools|flexeditAttributesFullListShow" class='applyButton floatRight'>Full Attribute List</button> + </div> <p>To enable a new attribute, simply drag it to the 'enabled' list on the left</p> - <table class='fullWidth gridTable'> + <table class='fullWidth gridTable' data-tablefilter-role='table' data-tablefilter-selector='tr'> <tbody data-bind="var: flexedit(contents); format:processList; loadsTemplate:flexeditAttributeRowTemplate;" data-app-role='flexeditAttributeListTbody'> </tbody> </table> @@ -867,7 +912,7 @@ <h3 class='stdPadding ui-widget-header ui-corner-top'>Popular Attributes</h3> <table> <tr id='flexeditAttributeRowTemplate'> <td class='width1 hideInMasterList'><span class="ui-icon ui-icon-arrowthick-2-n-s"></span></td> - <td class='alignLeft'> + <td class='alignLeft isSearchable'> <div data-bind='var:flexedit(id); format:text;'></div> <div> <span data-bind='var:flexedit(title); defaultVar:flexedit(tag); format:text;'></span> @@ -875,9 +920,9 @@ <h3 class='stdPadding ui-widget-header ui-corner-top'>Popular Attributes</h3> </div> </td> <td class='alignRight'> -<!-- <button data-app-event="admin_tools|flexeditAttributeAdd2EnabledList" class='hideInEnabledList applyButton'>Add to Enabled List</button> --> - <button data-app-event="admin|tagRowForRemove" class='hideInMasterList'>Remove Field</button> - <button data-app-event='admin_tools|flexeditAttributeCreateUpdateShow' data-mode='update' class='hideInMasterList'>Update Attribute</button> + <span data-app-click="admin_tools|flexeditAttributeAdd2EnabledList" class='hideInEnabledList ui-icon ui-icon-circle-arrow-w pointer' title="Add to Enabled List"></span> + <button data-app-click="admin|tagRow4Remove" class='hideInMasterList applyButton' data-text='false' data-icon-primary='ui-icon-closethick'>Remove Field</button> + <button data-app-click='admin_tools|flexeditAttributeCreateUpdateShow' data-mode='update' class='hideInMasterList applyButton' data-text='false' data-icon-primary="ui-icon-pencil">Update Attribute</button> </td> </tr> @@ -908,7 +953,7 @@ <h3 class='stdPadding ui-widget-header ui-corner-top'>Popular Attributes</h3> <fieldset class='marginBottom labelsAsBreaks'> <label> <span>Service</span> - <select name='_cmd' data-input-change="panel-selector" data-panel-selector=".debugCMDSpecifics"> + <select name='_cmd' data-input-change="panel-selector" data-panel-selector=".debugCMDSpecifics" data-tlc="bind $var '.verb'; apply --select=$var;"> <option value=''>please choose</option> <option value='adminDebugProduct' data-show-panel='debugCMDSpecificsProduct'>Product</option> <option value='adminDebugPromotion' data-show-panel='debugCMDSpecificsCommon'>Promotion</option> @@ -984,5 +1029,8 @@ <h3 class='stdPadding ui-widget-header ui-corner-top'>Popular Attributes</h3> <button data-app-click="admin_tools|siteDebugExec" data-icon-primary='ui-icon-wrench' class='applyButton'>Go</button> </div> + <div data-app-role='siteDebugContent'></div> </form> + + </div> \ No newline at end of file diff --git a/extensions/admin/tools.js b/extensions/admin/tools.js index 096bd6fa7..f20897bff 100644 --- a/extensions/admin/tools.js +++ b/extensions/admin/tools.js @@ -17,7 +17,7 @@ ************************************************************** */ -var admin_tools = function() { +var admin_tools = function(_app) { var theseTemplates = new Array('productPowerToolTemplate'); var r = { @@ -31,7 +31,21 @@ var admin_tools = function() { init : { onSuccess : function() { var r = false; //return false if extension won't load for some reason (account config, dependencies, etc). - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/tools.html',theseTemplates); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/tools.html',theseTemplates); + + _app.formatRules.validateJSON = function($input,$err){ + var valid = true; + try { + jQuery.parseJSON($input.val()); + } + catch(e) { + valid = false; + $err.append('Invalid JSON. error: '+e); + } + return valid; + } + + //if there is any functionality required for this extension to load, put it here. such as a check for async google, the FB object, etc. return false if dependencies are not present. don't check for other extensions. r = true; @@ -40,7 +54,7 @@ var admin_tools = function() { onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } }, //callbacks @@ -53,38 +67,32 @@ var admin_tools = function() { //these are going the way of the do do, in favor of app events. new extensions should have few (if any) actions. a : { showPPT : function($target) { - $target.empty().anycontent({'templateID':'productPowerToolTemplate','showLoading':false}); + $target.empty().anycontent({'templateID':'productPowerToolTemplate','showLoading':false,data:{}}); //empty data passed to ensure translate occurs (for includes et all) $('.toolTip',$target).tooltip(); var $picker = $("[data-app-role='pickerContainer']:first",$target); - $picker.append(app.ext.admin.a.getPicker({'templateID':'pickerTemplate','mode':'product'})); + $picker.append(_app.ext.admin.a.getPicker({'templateID':'pickerTemplate','mode':'product'})); $('.applyDatepicker',$picker).datepicker({ changeMonth: true, changeYear: true, maxDate : 0, dateFormat : 'yymmdd' }); - app.u.handleAppEvents($target,{'$form':$('#productPowerToolForm'),'$dataTbody':$("[data-app-role='powertoolSelectedActionsContainer'] tbody",$target)}); + _app.u.handleAppEvents($target,{'$form':$('#productPowerToolForm'),'$dataTbody':$("[data-app-role='powertoolSelectedActionsContainer'] tbody",$target)}); // $("input",$picker).each(function(){}); }, - siteDebugger : function() { - var $SD = $('#storeDebugger'); - if($SD.length) { - $SD.dialog('open'); - } - else { - $SD = $("<div \/>").attr('title','Site Debug Tools').anycontent({'templateID':'siteDebugTemplate','showLoading':false}).dialog(); - app.u.handleButtons($SD); - app.u.handleCommonPlugins($SD); - app.u.handleEventDelegation($SD); - app.ext.admin.u.handleFormConditionalDelegation($('form',$SD)); - } + siteDebugger : function($target,P) { + P = P || {}; + $target.tlc({'templateid':'siteDebugTemplate','dataset':P}) + _app.u.handleButtons($target); + _app.u.handleCommonPlugins($target); + _app.u.addEventDelegation($target); + $target.anyform(); }, - + showManageFlexedit : function($target) { - $target.empty(); - $target.append($("<div \/>").anycontent({'templateID':'manageFlexeditTemplate',data:{}})); - + $target.anycontent({'templateID':'manageFlexeditTemplate',data:{}}).anyform(); + _app.u.addEventDelegation($target); var $enabled = $("[data-app-role='flexeditEnabledListContainer']",$target); $enabled.showLoading({'message':'Fetching your list of enabled fields'}) @@ -99,51 +107,48 @@ var admin_tools = function() { stop : function(event,ui) { //if the item ends up in the enabled list, change from left/right arrows to up/down. also tag row to denote it's new (for save later). if($(ui.item).closest('tbody').hasClass('connectMe')) { - $(ui.item).addClass('edited isNewRow').data({'isFromMaster':true}).attr({'data-guid':app.u.guidGenerator(),'data-id':$(ui.item).data('obj_index')}) - app.u.handleAppEvents($(ui.item)); //handled here instead of when right list is generated for efficiency. + $(ui.item).addClass('edited isNewRow').data({'isFromMaster':true}).attr({'data-guid':_app.u.guidGenerator(),'data-id':$(ui.item).data('obj_index')}); + _app.u.handleButtons($(ui.item)); } } }); - app.model.addDispatchToQ({'_cmd':'adminConfigDetail','flexedit':'1','_tag':{'callback':'anycontent','datapointer':'adminConfigDetail|flexedit','jqObj':$enabled}},'mutable'); - app.ext.admin.calls.appResource.init('product_attribs_all.json',{},'immutable'); //have these handy for editor. - app.model.addDispatchToQ({'_cmd':'appResource','filename':'product_attribs_popular.json','_tag':{'callback':function(rd){ + _app.ext.admin.calls.appResource.init('product_attribs_all.json',{},'mutable'); //have these handy for editor. ### TODO -> don't call these till necessary + _app.model.addDispatchToQ({'_cmd':'adminConfigDetail','flexedit':'1','_tag':{'callback':'anycontent','datapointer':'adminConfigDetail|flexedit','jqObj':$enabled}},'mutable'); + _app.model.addDispatchToQ({'_cmd':'appResource','filename':'product_attribs_popular.json','_tag':{'callback':function(rd){ $master.hideLoading(); - $('tr',$enabled).each(function(){$(this).attr('data-guid',app.u.guidGenerator())}); //has to be an attribute (as opposed to data()) so that dataTable update see's the row exists already. - if(app.model.responseHasErrors(rd)){ + $('tr',$enabled).each(function(){$(this).attr('data-guid',_app.u.guidGenerator())}); //has to be an attribute (as opposed to data()) so that dataTable update see's the row exists already. + if(_app.model.responseHasErrors(rd)){ $('#globalMessaging').anymessage({'message':rd}); } else { $master.anycontent({'datapointer':rd.datapointer}); - app.u.handleAppEvents($master); + _app.u.handleButtons($master); } },'datapointer':'appResource|product_attribs_popular.json'}},'mutable'); -// app.u.handleAppEvents($target); - app.model.dispatchThis('mutable'); -//manageFlexeditorTemplate - - }, + _app.model.dispatchThis('mutable'); + }, //showManageFlexedit showProductExport : function($target) { $target.empty().anycontent({'templateID':'productExportToolTemplate','showLoading':false}); - $(':checkbox',$target).anycb(); //run before picker added to dom so that picker isn't affected. + _app.u.handleCommonPlugins($target); //run before picker added to dom so that picker isn't affected by anycb. var $picker = $("[data-app-role='pickerContainer']:first",$target); - $picker.append(app.ext.admin.a.getPicker({'templateID':'pickerTemplate','mode':'product'})); + $picker.append(_app.ext.admin.a.getPicker({'templateID':'pickerTemplate','mode':'product'})); $('.toolTip',$target).tooltip(); - app.u.handleAppEvents($target); + _app.u.handleAppEvents($target); }, showAccountUtilities : function($target) { $target.empty().anycontent({'templateID':'accountUtilitiesTemplate','showLoading':false,'datapointer':'info'}); //need to apply datepicker to date inputs. $('button',$target).button(); - app.u.handleAppEvents($target); - $target.anydelegate(); + _app.u.addEventDelegation($target); + _app.u.handleButtons($target.anyform()); - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd':'adminPlatformLogList', '_tag' : { 'callback':'anycontent', @@ -151,18 +156,17 @@ var admin_tools = function() { 'jqObj' : $("[data-app-role='accountUtilityLogContainer']:first",$target) } },'mutable'); - app.model.dispatchThis('mutable'); + _app.model.dispatchThis('mutable'); }, showPrivateFiles : function($target) { - - $target.empty(); - app.ext.admin.i.DMICreate($target,{ + _app.ext.admin.i.DMICreate($target,{ 'header' : 'Private Files', 'className' : 'privatefiles', //applies a class on the DMI, which allows for css overriding for specific use cases. 'thead' : ['Created','Filename','Type','Expiration','Creator',''], + 'handleAppEvents' : false, 'tbodyDatabind' : "var: users(@files); format:processList; loadsTemplate:privateFilesRowTemplate;", - 'controls' : "<button data-app-event='admin_tools|adminPrivateFileRemoveConfirm' class='floatRight'>Delete Selected</button><form class='floatLeft'><label>Filter<\/label> <select name='type' class='marginLeft marginRight'><option value=''>none<\/option><option value='REPORT'>Report<\/option><option value='SYNDICATION'>Syndication<\/option><option value='CSV'>CSV<\/option><\/select><button data-app-event='admin|refreshDMI' data-serializeform='1'><\/button><\/form>", + 'controls' : "<button data-app-click='admin_tools|adminPrivateFileRemoveConfirm' class='floatRight applyButton' data-icon-primary='ui-icon-trash'>Delete Selected</button><form class='floatLeft'><label>Filter<\/label> <select name='type' class='marginLeft marginRight'><option value=''>none<\/option><option value='REPORT'>Report<\/option><option value='SYNDICATION'>Syndication<\/option><option value='CSV'>CSV<\/option><\/select><button data-app-click='admin|refreshDMI' data-serializeform='1' class='applyButton'>Filter<\/button><\/form>", 'cmdVars' : { '_cmd' : 'adminPrivateFileList', 'limit' : '50', @@ -171,63 +175,17 @@ var admin_tools = function() { } } }); - app.model.dispatchThis('mutable'); + _app.u.handleButtons($target.anyform()); + _app.model.dispatchThis('mutable'); }, - showBillingHistory : function($target) { - - $target.empty(); - - app.ext.admin.i.DMICreate($target,{ - 'header' : 'Billing History', - 'className' : 'billingHistory', //applies a class on the DMI, which allows for css overriding for specific use cases. - 'buttons' : [ - "<button data-app-event='admin|refreshDMI'>Refresh List<\/button>", - "<button>Add Payment<\/button>" - ], - 'thead' : ['Invoice #','Created','Payment','Amount',''], //the blank at the end is for the th tag for the buttons. - 'tbodyDatabind' : "var: users(@INVOICES); format:processList; loadsTemplate:billingHistoryInvoiceRowTemplate;", - 'cmdVars' : { - '_cmd' : 'billingInvoiceList', - '_tag' : { - 'datapointer':'billingInvoiceList' - } - } - }); - -$target.append("<br \/>"); - - app.ext.admin.i.DMICreate($target,{ - 'header' : 'Pending Transactions', - 'className' : 'billingTransactions', //applies a class on the DMI, which allows for css overriding for specific use cases. - 'buttons' : [ - "<button data-app-event='admin|refreshDMI'>Refresh List<\/button>" - ], - 'thead' : ['Date','Class','Type','Description','amount',''], //the blank at the end is for the th tag for the buttons. - 'tbodyDatabind' : "var: users(@TRANSACTIONS); format:processList; loadsTemplate:billingHistoryInvoiceRowTemplate;", - 'cmdVars' : { - '_cmd' : 'billingTransactions', - '_tag' : { - 'datapointer':'billingTransactions' - } - } - }); - - - - app.model.dispatchThis('mutable'); - }, - - showciEngineAgentManager : function($target) { - - $target.empty(); - app.ext.admin.i.DMICreate($target,{ + _app.ext.admin.i.DMICreate($target,{ 'header' : 'Agent Manager', 'className' : 'agentsManager', //applies a class on the DMI, which allows for css overriding for specific use cases. 'buttons' : [ - "<button data-app-event='admin|refreshDMI'>Refresh Coupon List<\/button>", - "<button data-app-event='admin_tools|agentCreateShow'>Add Agent<\/button>" + "<button data-app-click='admin|refreshDMI' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowrefresh-1-s'>Refresh<\/button>", + "<button data-app-click='admin_tools|agentCreateShow' class='applyButton' data-text='true' data-icon-primary='ui-icon-cicle-plus'>Add Agent<\/button>" ], 'thead' : ['ID','Revision#','Lines','Interface','Created',''], //the blank at the end is for the th tag for the buttons. 'tbodyDatabind' : "var: users(@AGENTS); format:processList; loadsTemplate:CIE_DSA_rowTemplate;", @@ -238,7 +196,8 @@ $target.append("<br \/>"); } } }); - app.model.dispatchThis('mutable'); + _app.u.handleButtons($target.anyform()); + _app.model.dispatchThis('mutable'); } }, //Actions @@ -251,7 +210,7 @@ $target.append("<br \/>"); renderFormats : { objExplore : function($tag,data) { - $tag.append(app.ext.admin_tools.u.objExplore(objExplore)); + $tag.append(_app.ext.admin_tools.u.objExplore(objExplore)); } @@ -261,9 +220,10 @@ $target.append("<br \/>"); //utilities are typically functions that are exected by an event or action. //any functions that are recycled should be here. u : { - - objExplore : function(obj) { -// app.u.dump("BEGIN analyzer.u.objExplore"); +//depth should never be passed. it's defaulted to 0 (zero) and incremented w/ each nested object. + objExplore : function(obj,depth) { +// _app.u.dump("BEGIN analyzer.u.objExplore"); + depth = depth || 0; var keys = new Array(); for (var n in obj) { keys.push(n); @@ -274,11 +234,12 @@ $target.append("<br \/>"); for(var i = 0; i < L; i += 1) { var $li = $('<li>'); + $li.addClass('objExplore_'+depth) var $value; $('<span>').addClass('prompt').text(keys[i]).appendTo($li); if(typeof obj[keys[i]] == 'object') { - $value = app.ext.admin_tools.u.objExplore(obj[keys[i]]); + $value = _app.ext.admin_tools.u.objExplore(obj[keys[i]],depth++); } else { $value = $('<span>').addClass('value').text(obj[keys[i]]); @@ -291,16 +252,16 @@ $target.append("<br \/>"); }, pickerSelection2KVP : function($context) { -// app.u.dump("BEGIN admin_tools.u.pickerSelection2KVP"); +// _app.u.dump("BEGIN admin_tools.u.pickerSelection2KVP"); var r = ""; //what is returned. line separated w/ each line as 'navcat=.safe.name' or 'vendor=XYZ' var sfo = $context.serializeJSON({'cb':true}); -// app.u.dump(" -> sfo: "); app.u.dump(sfo); +// _app.u.dump(" -> sfo: "); _app.u.dump(sfo); if(Number(sfo.SELECTALL) === 1) { r = 'all' } else { function handleIt(type) { -// app.u.dump(" -> handle it for "+type); +// _app.u.dump(" -> handle it for "+type); if(Number(sfo[index]) === 1) { r += index.replace('+','=')+"\n"; // input name is navcat+.something, so simply changing + to = makes it macroesque-ready. } @@ -322,23 +283,24 @@ $target.append("<br \/>"); if(sfo.createstart && sfo.createend) { r += "created="+sfo.createstart+"|"+sfo.createend+"\n"; } - + if(sfo.csv) { - r += "csv="+sfo.csv.replace(/\n/gm,",")+"\n"; //linebreaks instead of commas are acceptable for the input, but the API wants commas. + r += "csv="+sfo.csv.replace(/[\s\t\r\n]+/g,",")+"\n"; //strip out all whitespace of any kind and replace with a comma. adjacent whitespace will only get 1 comma +// _app.u.dump(" -> r: "); _app.u.dump(r); } } -// app.u.dump(" -> r: "+r); +// _app.u.dump(" -> r: "+r); return r; }, //will return an array of macro-esque values //context could be the fieldset or the parent form. pickerSelection2Array : function($context) { - app.u.dump("BEGIN admin_tools.u.pickerSelection2Array"); + _app.u.dump("BEGIN admin_tools.u.pickerSelection2Array"); var r = new Array(); //what is returned. array w/ each entry formatted as: 'navcat=.safe.name' or 'vendor=XYZ' var sfo = $context.serializeJSON({'cb':true}); -// app.u.dump(" -> sfo: "); app.u.dump(sfo); +// _app.u.dump(" -> sfo: "); _app.u.dump(sfo); function handleIt(type) { if(Number(sfo[index]) === 1) { r.push(index.replace('+','=')); // input name is navcat+.something, so simply changing + to = makes it macroesque-ready. @@ -353,7 +315,7 @@ $target.append("<br \/>"); for(index in sfo) { if(index.indexOf('navcat') === 0) {handleIt('navcat');} else if(index.indexOf('supplier') === 0) {handleIt('supplier');} - else if(index.indexOf('managecat') === 0) {app.u.dump(" -> managecat");handleIt('managecat');} + else if(index.indexOf('managecat') === 0) {_app.u.dump(" -> managecat");handleIt('managecat');} else if(index.indexOf('launchprofile') === 0) {handleIt('mancat');} else {} //do nada. isn't a checkbox list. } @@ -371,18 +333,6 @@ $target.append("<br \/>"); return r; }, - powertoolActions2Array : function($tbody) { - var r = new Array(); - $('tr',$tbody).each(function(){ - var - data = $(this).data(), - verb = data.verb; - delete data.verb; - r.push(verb+"?"+app.ext.admin.u.getSanitizedKVPFromObject(data)); - }); - return r; - }, - powertoolActions2KVP : function($tbody) { var r = ""; $('tr',$tbody).not('.rowTaggedForRemove').each(function(){ @@ -402,7 +352,7 @@ $target.append("<br \/>"); data['when-attrib-contains'] = data.whenAttribContains; } - r += verb+"?"+$.param(app.u.getWhitelistedObject(data,['attrib','when','when-attrib','when-attrib-operator','when-attrib-contains'])); //verb not passed because it is macro + r += verb+"?"+$.param(_app.u.getWhitelistedObject(data,['attrib','when','when-attrib','when-attrib-operator','when-attrib-contains'])); //verb not passed because it is macro switch(verb) { case 'replace': @@ -433,130 +383,144 @@ $target.append("<br \/>"); //while no naming convention is stricly forced, //when adding an event, be sure to do off('click.appEventName') and then on('click.appEventName') to ensure the same event is not double-added if app events were to get run again over the same template. e : { - - rawJSONRequestExec : function($btn) { - $btn.button(); - $btn.off('click.rawJSONRequestExec').on('click.rawJSONRequestExec',function(event){ - event.preventDefault(); - var JSONString = $btn.closest('form').find("[name='JSON']").val(); - app.u.dump(" -> myJSON: "+JSONString); - var validJSON = false; - try { -// app.u.dump(" -> attempting to validate json"); - app.u.dump(" -> JSON.parse(JSONString): "+JSON.parse(JSONString)); - //Run some code here - validJSON = JSON.parse(JSONString); - } - catch(err) { - //Handle errors here - } -// app.u.dump(" -> jsonParse(myJSON): "); app.u.dump(validJSON); - if(typeof validJSON === 'object') { - if(app.model.addDispatchToQ(validJSON,'mutable')) { - app.model.dispatchThis('mutable'); - } - else { - $btn.closest('form').anymessage({"message":"The query could not be dispatched. Be sure you have a _cmd set in your query."}) - } - + + rawJSONRequestExec : function($ele,P) { + P.preventDefault(); + var JSONString = $ele.closest('form').find("[name='JSON']").val(); + _app.u.dump(" -> myJSON: "+JSONString); + var validJSON = false; + try { +// _app.u.dump(" -> attempting to validate json"); + _app.u.dump(" -> JSON.parse(JSONString): "+JSON.parse(JSONString)); + //Run some code here + validJSON = JSON.parse(JSONString); + } + catch(err) { + //Handle errors here + } +// _app.u.dump(" -> jsonParse(myJSON): "); _app.u.dump(validJSON); + if(typeof validJSON === 'object') { + // ### TODO -> this should set a callback of showMessaging and pass a message of 'success' and put it into the parent form but ONLY if no callback is set. got interupted. + validJSON._tag = validJSON._tag || {}; + if(validJSON._tag.callback) {} + else { + validJSON._tag.callback = 'showMessaging'; + validJSON._tag.message = "API request was successful."; + validJSON._tag.jqObj = $ele.closest('form'); + } + + if(_app.model.addDispatchToQ(validJSON,'mutable')) { + _app.model.dispatchThis('mutable'); } else { - $btn.closest('form').anymessage({"message":"The query is not a valid json object. Use a service like jsonLint to validate your JSON if necessary.<br>hint: You must use double quotes around your values."}) + $ele.closest('form').anymessage({"message":"The query could not be dispatched. Be sure you have a _cmd set in your query."}) } - }); + + } + else { + $ele.closest('form').anymessage({"message":"The query is not a valid json object. Use a service like jsonLint to validate your JSON if necessary.<br>hint: You must use double quotes around your values."}) + } }, - - inspectorExec : function($btn) { - $btn.button(); - $btn.off('click.inspectorExec').on('click.inspectorExec',function(event){ - event.preventDefault(); - if(app.u.validateForm($btn.closest('form'))) { - var - cmdObj = $btn.closest('form').serializeJSON({'cb':true}), - valid = true; - - cmdObj._tag = {}; - - if($btn.data('inspect') == 'order' && cmdObj.orderid) { - cmdObj._cmd = "adminOrderDetail"; - cmdObj._tag.datapointer = "adminOrderDetail|"+cmdObj.orderid; - } - else if($btn.data('inspect') == 'product' && cmdObj.pid) { - cmdObj._cmd = "appProductGet"; - cmdObj.withVariations = 1; - cmdObj.withInventory = 1; - cmdObj._tag.datapointer = "appProductGet|"+cmdObj.pid; - } - else if($btn.data('inspect') == 'shipmethods') { - cmdObj._cmd = "adminConfigDetail"; - cmdObj.shipmethods = true; - cmdObj._tag.datapointer = "adminConfigDetail|shipmethods|"+app.vars.partition; - } - else if($btn.data('inspect') == 'cart' && cmdObj.cartid) { - cmdObj._cmd = "cartDetail"; - cmdObj._tag.datapointer = "cartDetail|"+cmdObj.cartid; - } - else { - valid = false; - $('#globalMessaging').anymessage({"message":"In admin_tools.e.inspectExec, either inspect ["+$btn.data('inspect')+"] was invalid (only product, order and cart are valid) or inspect was valid, but was missing corresponding data (ex: inspect=order but no orderid specified in form);","gMessage":true}); - } + + inspectorExec : function($ele,P) { + P.preventDefault(); + if(_app.u.validateForm($ele.closest('form'))) { + var + cmdObj = $ele.closest('form').serializeJSON({'cb':true}), + valid = true; + cmdObj._tag = {}; - if(valid) { - var $D = app.ext.admin.i.dialogCreate({ - 'title':'Inspector' - }) - $D.dialog('open'); - cmdObj._tag.callback = function(rd) { - $D.hideLoading(); - if(app.model.responseHasErrors(rd)){ - $D.anymessage({'message':rd}); - } - else { - //sanitize a little... - delete app.data[rd.datapointer]._rcmd; - delete app.data[rd.datapointer]._msgs; - delete app.data[rd.datapointer]._msg_1_id; - delete app.data[rd.datapointer]._msg_1_txt; - delete app.data[rd.datapointer]._msg_1_type; - delete app.data[rd.datapointer]._rtag; - delete app.data[rd.datapointer]._uuid; - delete app.data[rd.datapointer].ts - - $D.append(app.ext.admin_tools.u.objExplore(app.data[rd.datapointer])); - } + if($ele.data('inspect') == 'order' && cmdObj.orderid) { + cmdObj._cmd = "adminOrderDetail"; + cmdObj._tag.datapointer = "adminOrderDetail|"+cmdObj.orderid; + } + else if($ele.data('inspect') == 'product' && cmdObj.pid) { + cmdObj._cmd = "appProductGet"; + cmdObj.withVariations = 1; + cmdObj.withInventory = 1; + cmdObj._tag.datapointer = "appProductGet|"+cmdObj.pid; + } + else if($ele.data('inspect') == 'shipmethods') { + cmdObj._cmd = "adminConfigDetail"; + cmdObj.shipmethods = true; + cmdObj._tag.datapointer = "adminConfigDetail|shipmethods|"+_app.vars.partition; + } + else if($ele.data('inspect') == 'cart' && cmdObj.cartid) { + cmdObj._cmd = "cartDetail"; + cmdObj._tag.datapointer = "cartDetail|"+cmdObj.cartid; + } + else { + valid = false; + $('#globalMessaging').anymessage({"message":"In admin_tools.e.inspectExec, either inspect ["+$ele.data('inspect')+"] was invalid (only product, order and cart are valid) or inspect was valid, but was missing corresponding data (ex: inspect=order but no orderid specified in form);","gMessage":true}); + } + + + if(valid) { + var $D = _app.ext.admin.i.dialogCreate({ + 'title':'Inspector' + }) + $D.dialog('open'); + cmdObj._tag.callback = function(rd) { + $D.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + //sanitize a little... + delete _app.data[rd.datapointer]._rcmd; + delete _app.data[rd.datapointer]._msgs; + delete _app.data[rd.datapointer]._msg_1_id; + delete _app.data[rd.datapointer]._msg_1_txt; + delete _app.data[rd.datapointer]._msg_1_type; + delete _app.data[rd.datapointer]._rtag; + delete _app.data[rd.datapointer]._uuid; + delete _app.data[rd.datapointer].ts + + $D.append(_app.ext.admin_tools.u.objExplore(_app.data[rd.datapointer])); } - app.model.addDispatchToQ(cmdObj,'mutable'); - app.model.dispatchThis('mutable'); } - else {} //error messaging already handled. - + _app.model.addDispatchToQ(cmdObj,'mutable'); + _app.model.dispatchThis('mutable'); } - else {} - }); + else {} //error messaging already handled. + + } + else {} + }, - + powerToolBatchJobExec : function($btn) { $btn.button(); $btn.off('click.powerToolAttribChange').on('click.powerToolAttribChange',function(event){ event.preventDefault(); -// app.u.dump("BEGIN powerToolBatchJobExec click event."); +// _app.u.dump("BEGIN powerToolBatchJobExec click event."); var $form = $btn.closest('form'); - if(app.ext.admin.u.validatePicker($form)) { + if(_app.ext.admin.u.validatePicker($form)) { if($('#powerToolActionListTbody tr').not('.rowTaggedForRemove').length) { obj = { '%vars' : { - 'GUID' : app.u.guidGenerator(), - 'product_selectors' : app.ext.admin_tools.u.pickerSelection2KVP($("[data-app-role='pickerContainer']",$form)), - 'actions' : app.ext.admin_tools.u.powertoolActions2KVP($('#powerToolActionListTbody')) + 'GUID' : _app.u.guidGenerator(), + 'product_selectors' : _app.ext.admin_tools.u.pickerSelection2KVP($("[data-app-role='pickerContainer']",$form)), + 'actions' : _app.ext.admin_tools.u.powertoolActions2KVP($('#powerToolActionListTbody')) }, 'type' : 'UTILITY/PRODUCT_POWERTOOL' } // console.clear(); -// app.u.dump(" -> actions: "+obj['%vars'].actions); -// app.u.dump(" -> obj: "); app.u.dump(obj); - app.ext.admin_batchJob.a.adminBatchJobCreate(obj); +// _app.u.dump(" -> actions: "+obj['%vars'].actions); +// _app.u.dump(" -> obj: "); _app.u.dump(obj); + var batchOptions = {}; + if($("[name='jobtitle']",$form).val()) { + batchOptions = { + 'jobCreate' : true, + 'TITLE' : $("[name='jobtitle']",$form).val(), + 'PRIVATE' : 0, + 'BATCH_EXEC' : 'UTILITY/PRODUCT_POWERTOOL' + } + } + + _app.ext.admin_batchjob.a.adminBatchJobCreate(obj,batchOptions); } else { $form.anymessage({'message':'Please specify at least one attribute/action in step 2.'}) @@ -569,7 +533,7 @@ $target.append("<br \/>"); }) }, - + powerToolAttribChange : function($ele) { $ele.off('change.powerToolAttribChange').on('change.powerToolAttribChange',function(){ var $fieldset = $ele.closest('fieldset'); @@ -594,7 +558,6 @@ $target.append("<br \/>"); }); }, //powerToolConditionalChange - powerToolVerbChange : function($radio) { $radio.off('click.powerToolVerbChange').on('click.powerToolVerbChange',function(){ var $fieldset = $radio.closest('fieldset'); @@ -605,19 +568,18 @@ $target.append("<br \/>"); }); }, //powerToolVerbChange - productExportBatchJobCreateExec : function($btn) { $btn.button(); $btn.off('click.productExportBatchJobCreateExec').on('click.productExportBatchJobCreateExec',function(){ var $form = $btn.closest('form'); - if(app.ext.admin.u.validatePicker($form)) { + if(_app.ext.admin.u.validatePicker($form)) { var sfo = $("[data-app-role='exportConfiguration']",$form).serializeJSON(); - sfo.product_selectors = app.ext.admin_tools.u.pickerSelection2KVP($("[data-app-role='pickerContainer']",$form)); + sfo.product_selectors = _app.ext.admin_tools.u.pickerSelection2KVP($("[data-app-role='pickerContainer']",$form)); if(sfo.attributes == 'specify' && !sfo.fields) { $form.anymessage({"message":"For attributes, you selected 'specify', which requires at least one attribute in the attribute list textarea."}); } else { - app.ext.admin_batchJob.a.adminBatchJobCreate({'%vars':sfo,'guid':app.u.guidGenerator(),'type':'EXPORT/'+$form['EXPORT']}); + _app.ext.admin_batchjob.a.adminBatchJobCreate({'%vars':sfo,'guid':_app.u.guidGenerator(),'type':'EXPORT/PRODUCTS'}); } } else { @@ -646,11 +608,12 @@ $target.append("<br \/>"); var data = $btn.closest('tr').data() - var $panel = app.ext.admin.i.DMIPanelOpen($btn,{ + var $panel = _app.ext.admin.i.DMIPanelOpen($btn,{ 'templateID' : 'CIE_DSA_AddUpdateTemplate', 'panelID' : 'agent_'+data.agentid, + 'showLoading' : false, 'header' : 'Edit agent: '+data.agentid, - 'handleAppEvents' : true + 'handleAppEvents' : false }); // $panel.showLoading({'message':'Fetching Agent Details'}); @@ -659,248 +622,199 @@ $target.append("<br \/>"); .find("[name='AGENTID']") .closest('label').hide(); //agent id is not editable, once set. - app.model.addDispatchToQ({'AGENTID':data.agentid,'_cmd':'adminCIEngineAgentDetail','_tag':{'callback':'anycontent','jqObj':$panel,'datapointer':'adminCIEngineAgentDetail|'+data.agentid}},'mutable'); - app.model.dispatchThis('mutable'); + _app.model.addDispatchToQ({'AGENTID':data.agentid,'_cmd':'adminCIEngineAgentDetail','_tag':{'callback':'anycontent','jqObj':$panel,'datapointer':'adminCIEngineAgentDetail|'+data.agentid}},'mutable'); + _app.model.dispatchThis('mutable'); }); }, //agentDetailDMIPanel - agentCreateShow : function($btn) { - - $btn.button(); - $btn.off('click.agentCreateShow').on('click.agentCreateShow',function(event){ - - event.preventDefault(); - var $D = app.ext.admin.i.dialogCreate({ - 'title':'Add New Agent', - 'templateID':'CIE_DSA_AddUpdateTemplate', - 'data' : {'GUID':app.u.guidGenerator()}, - 'showLoading':false //will get passed into anycontent and disable showLoading. - }); - $D.dialog('open'); + agentCreateShow : function($ele,P) { + P.preventDefault(); + var $D = _app.ext.admin.i.dialogCreate({ + 'title':'Add New Agent', + 'templateID':'CIE_DSA_AddUpdateTemplate', + 'data' : {'GUID':_app.u.guidGenerator()}, + 'showLoading':false //will get passed into anycontent and disable showLoading. + }); + $D.dialog('open'); //These fields are used for processForm on save. - $('form',$D).first().append("<input type='hidden' name='_cmd' value='adminCIEngineAgentCreate' /><input type='hidden' name='_tag/jqObjEmpty' value='true' /><input type='hidden' name='_tag/updateDMIList' value='"+$btn.closest("[data-app-role='dualModeContainer']").attr('id')+"' /><input type='hidden' name='_tag/callback' value='showMessaging' /><input type='hidden' name='_tag/message' value='Thank you, your agent has been created.' />"); + $('form',$D).first().append("<input type='hidden' name='_cmd' value='adminCIEngineAgentCreate' /><input type='hidden' name='_tag/jqObjEmpty' value='true' /><input type='hidden' name='_tag/updateDMIList' value='"+$btn.closest("[data-app-role='dualModeContainer']").attr('id')+"' /><input type='hidden' name='_tag/callback' value='showMessaging' /><input type='hidden' name='_tag/message' value='Thank you, your agent has been created.' />"); - }); }, //agentCreateShow + flexeditAttributesFullListShow : function($ele,P) { + var $tbody = $ele.closest("[data-app-role='flexeditMasterListContainer']").find("[data-app-role='flexeditAttributeListTbody']"); + $tbody.empty() + $tbody.parent().showLoading({'message':'Fetching full attribute list'}); - flexeditAttributesFullListShow : function($btn) { - $btn.button(); - $btn.off('click.flexeditAttributesFullListShow').on('click.flexeditAttributesFullListShow',function(event){ - event.preventDefault(); - var $tbody = $btn.closest("[data-app-role='flexeditMasterListContainer']").find("[data-app-role='flexeditAttributeListTbody']"); - $tbody.empty() - $tbody.parent().showLoading({'message':'Fetching full attribute list'}); - - app.ext.admin.calls.appResource.init('product_attribs_all.json',{ - 'callback' : function(rd){ - $tbody.parent().hideLoading(); - - if(app.model.responseHasErrors(rd)){ - $('#globalMessaging').anymessage({'message':rd}); - } - else { - $tbody.anycontent({'datapointer':rd.datapointer}); - $('tr',$tbody).each(function(){ - $(this).attr('data-guid',app.u.guidGenerator()) - }); //has to be an attribute (as opposed to data()) so that dataTable update see's the row exists already. -//started implementing a button for 'move this to enabled list'. Worked fine on the short list of attribs. dies on the full list. -//the issue is handleAppEvents. Once this uses delegated events, it should work fine (handlebuttons did run w/out dying). -//however, can't migrate this yet because the data-table format uses app events, not delegated, and I don't want two copies of that. -// app.u.handleButtons($tbody); - } - }, - 'datapointer':'appResource|product_attribs_all.json' - },'mutable'); //total sales - app.model.dispatchThis('mutable'); - - - }); + _app.ext.admin.calls.appResource.init('product_attribs_all.json',{ + 'callback' : function(rd){ + $tbody.parent().hideLoading(); + + if(_app.model.responseHasErrors(rd)){ + $('#globalMessaging').anymessage({'message':rd}); + } + else { + $tbody.anycontent({'datapointer':rd.datapointer}); + $('tr',$tbody).each(function(){ + $(this).attr('data-guid',_app.u.guidGenerator()); + //this list is too big for running the handleButton script. + }); //has to be an attribute (as opposed to data()) so that dataTable update see's the row exists already. + } + }, + 'datapointer':'appResource|product_attribs_all.json' + },'mutable'); //total sales + _app.model.dispatchThis('mutable'); }, - flexeditAttributeAdd2EnabledList : function($btn) { - $btn.button({icons: {primary: "ui-icon-arrowthick-1-w"},text: false}).off('click.flexeditAttributeUpdateShow').on('click.flexeditAttributeUpdateShow',function(event){ - event.preventDefault(); - var $tr = $btn.closest('tr'); -// app.u.dump(" -> $btn.closest('form').find(tbody[data-app-role='flexeditEnabledListTbody']:first): "+$btn.closest('form').find("[data-app-role='flexeditEnabledListTbody']:first").length); - $btn.closest("[data-app-role='flexeditManager']").find("tbody[data-app-role='flexeditEnabledListTbody']:first").append($tr) - }); + flexeditAttributeAdd2EnabledList : function($ele,P) { + var $tr = $ele.closest('tr'); + $ele.closest("[data-app-role='flexeditManager']").find("tbody[data-app-role='flexeditEnabledListTbody']:first").append($tr); + $tr.attr('data-id',$tr.attr('data-obj_index')).find('.queryMatch').removeClass('queryMatch'); //if a filter was used in the attributes list, queryMatch is added which changes the bg color. + _app.u.handleButtons($tr); }, -/* -till events support multiple actions, can't implement this. -need the 'apply' button to run both the apply code AND this code. -uncomment this, the two lines in flexeditAttributeCreateUpdateShow for button(disable) and the cancel button to proceed w/ this. -OR, since old app events are still in play, could use data-app-click to trigger this and the app event code to trigger the data-table save. could be good temporary work around. - flexDataTableAddEditCancel : function($btn) { - $btn.button().off('click.flexDataTableAddEditCancel').on('click.flexDataTableAddEditCancel',function(event){ - event.preventDefault(); - $btn.closest('[data-app-role="flexeditManager"]').find("[data-app-event='admin_tools|flexeditAttributeCreateUpdateShow'], [data-app-event='admin_tools|flexeditAttributeCreateUpdateShow']").button('enable'); - $btn.closest("[data-app-role='flexeditAttributeAddUpdateContainer']").slideUp(); - }) + + flexDataTableAddEditCancel : function($ele,P) { + $ele.closest("[data-table-role='container']").find(":input").val(""); + $ele.closest("[data-table-role='inputs']").slideUp(); }, -*/ flexeditAttributeCreateUpdateShow : function($btn) { - - if($btn.data('mode') == 'update') { - $btn.button({icons: {primary: "ui-icon-pencil"},text: false}); - } - - $btn.button().off('click.flexeditAttributeUpdateShow').on('click.flexeditAttributeUpdateShow',function(){ - var $inputContainer = $btn.closest('form').find("[data-app-role='flexeditAttributeAddUpdateContainer']"); + + flexeditAttributeCreateUpdateShow : function($ele,p) { + var $inputContainer = $ele.closest('form').find("[data-app-role='flexeditAttributeAddUpdateContainer']"); //disable the add and edit buttons so as to not accidentally lose data while it's being entered (form would clear or populate w/ 'edit' contents ) // $btn.button('disable'); // $btn.closest('[data-app-role="flexeditManager"]').find("[data-app-event='admin_tools|flexeditAttributeCreateUpdateShow']").button('disable'); - + //need to make sure form input area is 'on screen'. scroll to it. - $('html, body').animate({ - scrollTop: $inputContainer.offset().top - }, 1000); - - if($btn.data('mode') == 'update') { - $inputContainer.show(); - $inputContainer.anycontent({'data':$.extend({},$btn.closest('tr').data(),app.data["appResource|product_attribs_all.json"].contents[$btn.closest('tr').data('id')])}) - app.u.dump(" -> bunch o data: "); app.u.dump($.extend({},$btn.closest('tr').data(),app.data["appResource|product_attribs_all.json"].contents[$btn.closest('tr').data('id')])) - } - else if($btn.data('mode') == 'create') { - $('input, select',$inputContainer).val(''); //clear all the inputs - $inputContainer.show(); + $('html, body').animate({scrollTop: $inputContainer.offset().top}, 1000); + $(':input',$inputContainer).val(''); //clear all the inputs. important even if in 'edit' cuz anycontent will NOT clear and if a field is not set for this item, it'll leave the previously edited attributes content. + $inputContainer.slideDown(); + + if($ele.data('mode') == 'update') { + $inputContainer.anycontent({'data':$.extend({},$ele.closest('tr').data(),_app.data["appResource|product_attribs_all.json"].contents[$ele.closest('tr').data('id')])}); + $("[name='type']",$inputContainer).trigger('change'); //will conditionally show 'options' input if necessary. + } + else if($ele.data('mode') == 'create') { + //valid mode + } + else { + $inputContainer.hide(); + $ele.closest('form').anymessage({"message":"In admin_tools.e.flexeditAttributeAddUpdateShow, mode not valid. only create or update are accepted.","gMessage":true}); + } + }, + + flexeditSaveExec : function($ele,P) { + var json = new Array(); + var keys = new Array(); + $ele.closest('form').find('tbody tr').not('.rowTaggedForRemove').each(function(){ + if($.inArray($(this).data('id'),keys) >= 0) { + //if an id is already in keys, it's already added to the flex json. This keeps duplicate id's from being added. } else { - $btn.closest('form').anymessage({"message":"In admin_tools.e.flexeditAttributeAddUpdateShow, mode not valid. only create or update are accepted.","gMessage":true}); + keys.push($(this).data('id')); + json.push(_app.u.getWhitelistedObject($(this).data(),['id','title','index','type','options'])); } - - }); - }, - - flexeditSaveExec : function($btn) { - $btn.button(); - $btn.off('click.flexeditSaveExec').on('click.flexeditSaveExec',function(event){ - event.preventDefault(); - var json = new Array(); - var keys = new Array(); - $btn.closest('form').find('tbody tr').not('.rowTaggedForRemove').each(function(){ - - if($.inArray($(this).data('id'),keys) >= 0) { - //if an id is already in keys, it's already added to the flex json. This keeps duplicate id's from being added. - } - else { - keys.push($(this).data('id')); - json.push(app.u.getWhitelistedObject($(this).data(),['id','title','index','type','options'])); - } - }) - app.model.addDispatchToQ({ - '_cmd':'adminConfigMacro', - '@updates':["GLOBAL/FLEXEDIT-SAVE?json="+encodeURIComponent(JSON.stringify(json))], - '_tag': { - 'callback' : 'showMessaging', - 'jqObj' : $btn.closest('form'), - 'removeFromDOMItemsTaggedForDelete' : true, - 'restoreInputsFromTrackingState' : true, - 'message':'Your changes have been saved' - } - },'immutable'); - app.model.addDispatchToQ({'_cmd':'adminConfigDetail','flexedit':'1','_tag':{'datapointer':'adminConfigDetail|flexedit'}},'immutable'); - app.model.dispatchThis('immutable'); - - }); - //FLEXEDIT-SAVE + }) + _app.model.addDispatchToQ({ + '_cmd':'adminConfigMacro', + '@updates':["GLOBAL/FLEXEDIT-SAVE?json="+encodeURIComponent(JSON.stringify(json))], + '_tag': { + 'callback' : 'showMessaging', + 'jqObj' : $ele.closest('form'), + 'removeFromDOMItemsTaggedForDelete' : true, + 'restoreInputsFromTrackingState' : true, + 'message':'Your changes have been saved' + } + },'immutable'); + _app.model.addDispatchToQ({'_cmd':'adminConfigDetail','flexedit':'1','_tag':{'datapointer':'adminConfigDetail|flexedit'}},'immutable'); + _app.model.dispatchThis('immutable'); }, - adminPrivateFileDownloadExec : function($btn) { - $btn.button({text: false,icons: {primary: "ui-icon-arrowthickstop-1-s"}}); - $btn.off('click.adminPrivateFileDownloadExec').on('click.adminPrivateFileDownloadExec',function(event){ - event.preventDefault(); - app.model.addDispatchToQ({ - '_cmd':'adminPrivateFileDownload', - 'GUID':$btn.closest('tr').data('guid'), - '_tag': { - 'datapointer' : 'adminPrivateFileDownload', //big dataset returned. only keep on in memory. - 'callback' : 'fileDownloadInModal', - 'skipDecode' : true //contents are not base64 encoded (feature not supported on this call) - } - },'mutable'); - app.model.dispatchThis('mutable'); - }); - }, + adminPrivateFileDownloadExec : function($ele,P) { + P.preventDefault(); + _app.model.addDispatchToQ({ + '_cmd':'adminPrivateFileDownload', + 'GUID':$ele.closest('tr').data('guid'), + '_tag': { + 'datapointer' : 'adminPrivateFileDownload', //big dataset returned. only keep on in memory. + 'callback' : 'fileDownloadInModal', + 'skipDecode' : true //contents are not base64 encoded (feature not supported on this call) + } + },'mutable'); + _app.model.dispatchThis('mutable'); + }, //adminPrivateFileDownloadExec - adminPlatformLogDownloadExec : function($btn) { - $btn.button({text: false,icons: {primary: "ui-icon-arrowthickstop-1-s"}}); - $btn.off('click.adminPlatformLogDownloadExec').on('click.adminPlatformLogDownloadExec',function(event){ - event.preventDefault(); - app.model.addDispatchToQ({ - '_cmd':'adminPlatformLogDownload', - 'GUID':$btn.closest('tr').data('guid'), - '_tag': { - 'datapointer' : 'adminPlatformLogDownload', //big dataset returned. only keep on in memory. - 'callback' : 'fileDownloadInModal', - 'skipDecode' : true //contents are not base64 encoded (feature not supported on this call) - } - },'mutable'); - app.model.dispatchThis('mutable'); - }); - }, - - - adminPrivateFileRemoveConfirm : function($btn) { - $btn.button({icons: {primary: "ui-icon-trash"},text: true}); - $btn.off('click.adminPrivateFileRemoveConfirm').on('click.adminPrivateFileRemoveConfirm',function(event){ - event.preventDefault(); - var $rows = $btn.closest('.dualModeContainer').find("[data-app-role='dualModeListTbody'] tr.rowTaggedForRemove"); - if($rows.length) { - - var $D = app.ext.admin.i.dialogConfirmRemove({ - 'message':'Are you sure you want to remove '+$rows.length+' file(s)? There is no undo for this action.', - 'removeButtonText' : 'Remove', - 'removeFunction':function(rd){ - $D.parent().showLoading({"message":"Deleting "+$rows.length+" file(s)"}); - $rows.each(function(){ - app.model.addDispatchToQ({ - '_cmd':'adminPrivateFileRemove', - 'GUID':$(this).data('guid'), - '_tag': { - 'datapointer' : 'adminPrivateFileRemove', //big dataset returned. only keep on in memory. - 'callback' : function(rd){ - if(app.model.responseHasErrors(rd)){ - $D.anymessage({'message':rd}); - } - else { - //only report failures. - } - } - } - },'immutable'); - $(this).empty().remove(); //at the end so the dispatch can use data off of <tr>. - }); - - app.model.addDispatchToQ({ - '_cmd':'ping', + adminPlatformLogDownloadExec : function($ele,P) { + P.preventDefault(); + _app.model.addDispatchToQ({ + '_cmd':'adminPlatformLogDownload', + 'GUID':$ele.closest('tr').data('guid'), + '_tag': { + 'datapointer' : 'adminPlatformLogDownload', //big dataset returned. only keep on in memory. + 'callback' : 'fileDownloadInModal', + 'skipDecode' : true //contents are not base64 encoded (feature not supported on this call) + } + },'mutable'); + _app.model.dispatchThis('mutable'); + }, //adminPlatformLogDownloadExec + + adminPrivateFileRemoveConfirm : function($ele,P) { + P.preventDefault(); + var $rows = $ele.closest('.dualModeContainer').find("[data-app-role='dualModeListTbody'] tr.rowTaggedForRemove"); + if($rows.length) { + + var $D = _app.ext.admin.i.dialogConfirmRemove({ + 'message':'Are you sure you want to remove '+$rows.length+' file(s)? There is no undo for this action.', + 'removeButtonText' : 'Remove', + 'removeFunction':function(rd){ + $D.parent().showLoading({"message":"Deleting "+$rows.length+" file(s)"}); + $rows.each(function(){ + _app.model.addDispatchToQ({ + '_cmd':'adminPrivateFileRemove', + 'GUID':$(this).data('guid'), '_tag': { 'datapointer' : 'adminPrivateFileRemove', //big dataset returned. only keep on in memory. 'callback' : function(rd){ - $D.parent().hideLoading(); - $D.empty(); - $D.dialog({ buttons: [ { text: "Close", click: function() { $( this ).dialog( "close" ); } } ] }); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $D.anymessage({'message':rd}); } else { - $D.anymessage({"message":"Removal process completed."}); //only report failures. } } } },'immutable'); - - app.model.dispatchThis('immutable'); - - } - }); + $(this).empty().remove(); //at the end so the dispatch can use data off of <tr>. + }); + + _app.model.addDispatchToQ({ + '_cmd':'ping', + '_tag': { + 'datapointer' : 'adminPrivateFileRemove', //big dataset returned. only keep on in memory. + 'callback' : function(rd){ + $D.parent().hideLoading(); + $D.empty(); + $D.dialog({ buttons: [ { text: "Close", click: function() { $( this ).dialog( "close" ); } } ] }); + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + $D.anymessage({"message":"Removal process completed."}); + //only report failures. + } + } + } + },'immutable'); + + _app.model.dispatchThis('immutable'); + + } + }); - } - else { - $('#globalMessaging').anymessage({"message":"Please tag at least one file for removal (click the trash can icon)."}); - } - }) - }, //agentRemoveConfirm, + } + else { + $('#globalMessaging').anymessage({"message":"Please tag at least one file for removal (click the trash can icon)."}); + } + }, //adminPrivateFileRemoveConfirm agentRemoveConfirm : function($btn) { @@ -912,26 +826,26 @@ OR, since old app events are still in play, could use data-app-click to trigger data = $tr.data(), $D; - $D = app.ext.admin.i.dialogConfirmRemove({'removeFunction':function(){ + $D = _app.ext.admin.i.dialogConfirmRemove({'removeFunction':function(){ $D.showLoading({"message":"Deleting Agent"}); - app.model.addDispatchToQ({'AGENTID':data.agentid,'_cmd':'adminCIEngineAgentRemove','_tag':{'callback':function(rd){ + _app.model.addDispatchToQ({'AGENTID':data.agentid,'_cmd':'adminCIEngineAgentRemove','_tag':{'callback':function(rd){ $D.hideLoading(); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $('#globalMessaging').anymessage({'message':rd}); } else { $D.dialog('close'); - $('#globalMessaging').anymessage(app.u.successMsgObject('Agent '+data.agentid+' has been removed.')); + $('#globalMessaging').anymessage(_app.u.successMsgObject('Agent '+data.agentid+' has been removed.')); $tr.empty().remove(); //removes row from list. no need to refetch entire list. - var $panel = $(app.u.jqSelector('#','agent_'+data.agentid)); + var $panel = $(_app.u.jqSelector('#','agent_'+data.agentid)); if($panel.length) { $panel.anypanel('destroy'); } } }}},'immutable'); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); }}); }) }, //agentRemoveConfirm @@ -939,16 +853,44 @@ OR, since old app events are still in play, could use data-app-click to trigger siteDebugExec : function($ele,p) { var cmdObj = $ele.closest('form').serializeJSON(); cmdObj._tag = { - 'datapointer' : cmdObj.siteDebug + 'datapointer' : cmdObj._cmd, + 'callback' : function(rd) { + var data = _app.data[rd.datapointer], $target = $ele.closest('form').find("[data-app-role='siteDebugContent']").empty(); + if(_app.model.responseHasErrors(rd)){ + $target.anymessage({'message':rd}); + } + + if(!$.isEmptyObject(data['@MSGS'])) { + data.persistent = true; + $target.anymessage(data); + } + if(!$.isEmptyObject(data['@RESULTS'])) { + $("<div \/>").css({'max-height':'300px','overflow':'auto'}).append(_app.ext.admin_tools.u.objExplore(data['@RESULTS'])).appendTo($target); + } + } }; - app.u.dump(cmdObj); - app.model.addDispatchToQ(cmdObj,'mutable'); - app.model.dispatchThis('mutable'); + _app.model.addDispatchToQ(cmdObj,'mutable'); + _app.model.dispatchThis('mutable'); }, //for forcing a product into the product task list forcePIDIntoPTL : function($ele,p) { - app.ext.admin_prodEdit.u.addProductAsTask({'pid':$ele.closest('form').find("[name='pid']").val(),'tab':'product','mode':'add'}); + _app.ext.admin_prodedit.u.addProductAsTask({'pid':$ele.closest('form').find("[name='pid']").val(),'tab':'product','mode':'add'}); + }, + + siteDebugDialog : function($ele,p) { + p.preventDefault(); + var $SD = $('#siteDebugger'); + if($SD.length) { + $SD.empty().dialog('open'); + } + else { + $SD = $("<div \/>").attr({'id':'siteDebugger','title':'Site Debug Tools'}).dialog({ + width : '50%' + }); + } + adminApp.ext.admin_tools.a.siteDebugger($SD,{'verb':$ele.data('verb')}); + return false; } } //e [app Events] diff --git a/extensions/admin/trainer.js b/extensions/admin/trainer.js index 168f04a4e..ed96d054a 100644 --- a/extensions/admin/trainer.js +++ b/extensions/admin/trainer.js @@ -17,7 +17,7 @@ ************************************************************** */ -var admin_trainer = function() { +var admin_trainer = function(_app) { var theseTemplates = new Array(); var r = { @@ -30,14 +30,14 @@ var admin_trainer = function() { //executed when extension is loaded. should include any validation that needs to occur. init : { onSuccess : function() { - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/trainer.html',theseTemplates); - app.rq.push(['css',0,app.vars.baseURL+'extensions/admin/trainer.css','trainer']); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/trainer.html',theseTemplates); + _app.rq.push(['css',0,_app.vars.baseURL+'extensions/admin/trainer.css','trainer']); return true; }, onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } }, //callbacks @@ -55,16 +55,17 @@ var admin_trainer = function() { var $trainer = $("<div \/>").appendTo($target); //put trainer into a div so that the delegation et all is NOT added to a tabContent $trainer.data('slides',slidesArr).attr('data-app-role','trainerContainer'); for(var i = 0,L = slidesArr.length; i < L; i += 1) { - app.u.dump(i+"). "+slidesArr[i]); + _app.u.dump(i+"). "+slidesArr[i]); $("<div \/>").addClass((i == 0 ? "marginBottom" : "marginBottom displayNone")).attr("data-trainerid",slidesArr[i]).anycontent({ 'templateID':slidesArr[i], - 'data' : app.model.dpsGet('trainer',slidesArr[i]) || {}, + 'data' : _app.model.dpsGet('trainer',slidesArr[i]) || {}, 'showLoading':false }).appendTo($trainer); } - app.ext.admin_trainer.u.handleTrainerArticles($trainer); - $trainer.anydelegate(); - app.u.handleButtons($trainer); + _app.ext.admin_trainer.u.handleTrainerArticles($trainer); + _app.u.addEventDelegation($target); + $trainer.anyform(); + _app.u.handleButtons($trainer); if(slidesArr.length == 1) { $("[data-app-role='trainerNavigation']").hide(); @@ -132,8 +133,8 @@ var admin_trainer = function() { } else { //no article type? uh oh. - app.u.dump("An article in the trainer had no data-article-type set. here's what we do know: ","warn"); - app.u.dump($article.data()); + _app.u.dump("An article in the trainer had no data-article-type set. here's what we do know: ","warn"); + _app.u.dump($article.data()); } }); } @@ -148,7 +149,7 @@ var admin_trainer = function() { handleUpdate : function($ele,p) { /* -app.model.addDispatchToQ({ +_app.model.addDispatchToQ({ '_cmd':'', '_tag': { 'datapointer' : '', @@ -160,7 +161,7 @@ app.model.addDispatchToQ({ }, navigate : function($ele,p) { -app.u.dump("Navigate!"); +_app.u.dump("Navigate!"); var $trainer = $ele.closest("[data-app-role='trainerContainer']"); slidesArr = $trainer.data('slides'); @@ -180,7 +181,6 @@ if($trainer instanceof jQuery && $trainer.length) { //disable the 'next' button in the last trainer slide. if( (thisTrainerIndex + 2) == slidesArr.length){ - app.u.dump(" --------> got here. length: "+$("button[data-app-click]",$trainer2Show).length); $("button[data-verb='next']",$trainer2Show).button('disable'); } } diff --git a/extensions/admin/user.html b/extensions/admin/user.html index ef3ec1ac4..ea76663f0 100644 --- a/extensions/admin/user.html +++ b/extensions/admin/user.html @@ -1,60 +1,29 @@ -<div id='userManagerPageTemplate' class='page pageUser' data-app-role='dualModeContainer' data-app-mode='list'> - - <section class='dualModeDetailContainer' data-app-role='dualModeDetail'></section> - - <section class='dualModeListContainer' data-app-role='dualModeList'> - <div class='ui-widget-header ui-corner-top'> - <div class='buttonSet'> - <button data-app-event='admin_user|bossUserCreate'>Create A New User</button> - <button data-app-event='admin|toggleDualMode'>Toggle between list and detail view</button> - </div> - <h3 class='heading'>User List</h3> - </div> - - <div class='ui-widget-content ui-corner-bottom'> - <table class='gridTable fullWidth' > - <!-- thead is needed, whether visible or not, so that the data-name attributes can be used to look up column # --> - <thead> - <tr> - <th>ID</th> - <th>Username</th> - <th class='hideInDetailMode'>Name</th> - <th class='hideInDetailMode'>Email</th> - <th>Roles</th> - <th class='hideInDetailMode'>Created</th> - <th></th> - </tr> - </thead> - <tbody data-bind="var: users(@USERS); format:processList; loadsTemplate:userManagerUserRowTemplate;" class='dualModeList' data-app-role='dualModeListContents'></tbody> - </table> - </div> - </section> -</div> - - <table> <tr id='userManagerUserRowTemplate'> - <td data-bind="var: user(uid); format:text;"></td> + <td data-bind="var: user(uid); format:text;" data-app-click="admin_user|bossUserDetailShow" class='lookLikeLink'></td> <td data-bind="var: user(luser); format:text;"></td> <td class='hideInDetailMode' data-bind="var: user(fullname); format:text;"></td> <td class='hideInDetailMode' data-bind="var: user(email); format:text;"></td> <td><ul data-bind="var: user(@roles); format:array2ListItems; extension:admin;" class='ulAsCSV'></ul></td> - <td class='hideInDetailMode' data-bind="var: user(created_gmt); format:unix2mdy;"></td> - <td> - <button data-app-event="admin_user|bossUserDetail">edit</button> - <button data-app-event="admin_user|bossUserDelete" class='marginLeft hideInDetailMode'>delete</button> + <td class='hideInDetailMode' data-bind="var: user(created_gmt); format:epoch2mdy;"></td> + <td class='alignRight'> + <button data-app-click="admin_user|bossUserDeleteConfirm" class='marginLeft applyButton' data-text='false' data-icon-primary='ui-icon-trash'>delete</button> + <button data-app-click="admin_user|bossUserDetailShow" class='applyButton' data-text='false' data-icon-primary='ui-icon-pencil'>edit</button> </td> </tr> <tr id='userManagerRoleRowTemplate'> <td><input type='checkbox' name='' data-bind='var:role(id);format:assignAttribute; attribute:name;' /></td> - <td data-bind="var: role(title); format:text;"></td> + <td> + <span data-bind="var: role(title); format:text;"></span> + <span data-bind='var:role(detail);format:assignAttribute; attribute:title;' class='toolTip'>?</span> + </td> <td class='roleDetail' data-bind="var: role(detail); format:text;"></td> <td data-bind="var: role(id); format:text;"></td> - <td> + <td class='width1'> <div class="handle"><span class="ui-icon ui-icon-grip-dotted-vertical"></span></div> </td> </tr> @@ -69,16 +38,17 @@ <h3 class='heading'>User List</h3> <div id='userManagerUserCreateUpdateTemplate' title='User' class='createUpdateUserContainer'> -<form action='#'> +<form action='#' onSubmit='return false;'> <fieldset class='labelsAsBreaks alignedLabels alignedInputs marginBottom'> <legend>User Information</legend> - <label><span>Full Name:</span> <input type='text' name='fullname' value='' required='required' data-bind="var:user(fullname);format:popVal;" /></label> - <label><span>Email:</span> <input type='email' name='email' value='' required='required' data-bind="var:user(email);format:popVal;" /></label> - <label><span>Login:</span> <input type='text' name='login' value='' required='required' data-bind="var:user(luser);format:popVal;" /></label> - <label><span>Job Title:</span> <input type='text' name='jobtitle' value='' data-bind="var:user(jobtitle);format:popVal;" /></label> - <label><span>Phone:</span> <input type='tel' name='phone' value='' data-bind="var:user(phone);format:popVal;" /></label> - <label class='passwordContainer'><span>Password:</span> <input type='password' name='password' value='' data-bind="var:user(password);format:popVal;" /></label> + <label><span class='prompt'>Full Name:</span> <input type='text' name='fullname' value='' required='required' data-bind="var:user(fullname);format:popVal;" /></label> + <label><span class='prompt'>Email:</span> <input type='email' name='email' value='' required='required' data-bind="var:user(email);format:popVal;" /></label> + <label><span class='prompt'>Login:</span> <input type='text' name='login' value='' required='required' data-bind="var:user(luser);format:popVal;" /></label> + <label><span class='prompt'>Job Title:</span> <input type='text' name='jobtitle' value='' data-bind="var:user(jobtitle);format:popVal;" /></label> + <label><span class='prompt'>Phone:</span> <input type='tel' name='phone' value='' data-bind="var:user(phone);format:popVal;" /></label> + <label><span class='prompt'>PIN:</span> <input type='text' name='passpin' value='' data-bind="var:user(passpin);format:popVal;" data-input-keyup="format" data-input-format='alphanumeric' maxlength="5" size='5' /></label> + <label class='passwordContainer'><span class='prompt'>Password:</span> <input type='password' name='password' required='required' value='' data-bind="var:user(password);format:popVal;" /></label> </fieldset> @@ -92,9 +62,10 @@ <h3 class='heading'>User List</h3> <th>Title</th> <th class='roleDetail'>Detail</th> <th>ID</th> + <th></th> </tr> </thead> - <tbody data-bind="var: roles(@ROLES); format:processList; loadsTemplate:userManagerRoleRowTemplate;" data-app-event="admin_user|roleListEdit"></tbody> + <tbody data-bind="var: roles(@ROLES); format:processList; loadsTemplate:userManagerRoleRowTemplate;" data-app-role='roleListTbody'></tbody> </table> <p>Use drag handles to sort role list in order of priority for this user.</p> </fieldset> diff --git a/extensions/admin/user.js b/extensions/admin/user.js index 9786ca88c..247e8075d 100644 --- a/extensions/admin/user.js +++ b/extensions/admin/user.js @@ -20,8 +20,8 @@ -var admin_user = function() { - var theseTemplates = new Array('userManagerPageTemplate','userManagerUserRowTemplate','userManagerRoleRowTemplate','userManagerUserCreateUpdateTemplate'); +var admin_user = function(_app) { + var theseTemplates = new Array('userManagerUserRowTemplate','userManagerRoleRowTemplate','userManagerUserCreateUpdateTemplate'); var r = { @@ -35,15 +35,15 @@ var admin_user = function() { onSuccess : function() { var r = true; //return false if extension won't load for some reason (account config, dependencies, etc). - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/user.html',theseTemplates); - app.rq.push(['css',0,app.vars.baseURL+'extensions/admin/user.css','user_styles']); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/user.html',theseTemplates); + _app.rq.push(['css',0,_app.vars.baseURL+'extensions/admin/user.css','user_styles']); return r; }, onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } }, //callbacks @@ -53,40 +53,46 @@ var admin_user = function() { //////////////////////////////////// ACTION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ a : { -//This is how the task manager is opened. Just execute this function. -// later, we may add the ability to load directly into 'edit' mode and open a specific user. not supported just yet. - showUserManager : function($target) { - app.u.dump("BEGIN admin_user.a.showUserManager"); - -//generate some of the task list content right away so the user knows something is happening. - $target.empty(); - $target.append(app.renderFunctions.createTemplateInstance('userManagerPageTemplate',{'id':'userManagerContent'})); //placeholder - $('#userManagerContent').showLoading({'message':'Fetching your user list.'}); - - app.model.addDispatchToQ({'_cmd':'bossRoleList','_tag': {'datapointer' : 'bossRoleList'}},'mutable'); //have this handy. - app.ext.admin.calls.bossUserList.init({'callback':'translateSelector','extension':'admin','selector':'#userManagerContent'},'mutable'); - app.model.dispatchThis('mutable'); - } //showTaskManager + + showUserManager : function($target) { + _app.u.dump("BEGIN admin_user.a.showUserManager 2.0"); + var $DMI = _app.ext.admin.i.DMICreate($target,{ + 'header' : 'User Manager', + 'className' : 'userManager', //applies a class on the DMI, which allows for css overriding for specific use cases. + 'thead' : ['id','Username','Name','Email','Roles','Created',''], //leave blank at end if last row is buttons. + 'tbodyDatabind' : "var: tickets(@USERS); format:processList; loadsTemplate:userManagerUserRowTemplate;", + 'buttons' : [ + "<button data-app-click='admin|refreshDMI' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowrefresh-1-s'>Refresh<\/button>", + "<button class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-plus' data-app-click='admin_user|bossUserCreateShow'>Create A New User</button>"], + 'cmdVars' : { + '_cmd' : 'bossUserList', + 'limit' : '50', //not supported for every call yet. + '_tag' : { + 'datapointer':'bossUserList' + } + } + }); + //only need to fetch the boss role list once. Doesn't change much. + if(_app.data.bossRoleList) {} + else { + _app.model.addDispatchToQ({'_cmd':'bossRoleList','_tag': {'datapointer' : 'bossRoleList'}},'mutable'); //have this handy. + } + _app.u.handleButtons($target.anyform({'trackEdits':true})); + _app.model.dispatchThis('mutable'); + } + }, //Actions //////////////////////////////////// RENDERFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ renderFormats : {}, //renderFormats + //////////////////////////////////// UTIL [u] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ u : { - resetUsersTable : function() { - var $table = $("[data-app-role='dualModeListContents']","#userManagerContent") - $table.empty(); - app.renderFunctions.translateSelector("#userManagerContent [data-app-role='dualModeList']",app.data.bossUserList); - app.ext.admin.u.handleAppEvents($table); - app.ext.admin.u.toggleDualMode($('#userManagerContent'),$('#userManagerContent').data('app-mode')); - - }, - getRoleCheckboxesAsArray : function($parent) { var roles = new Array(); if($parent && $parent.length) { @@ -98,300 +104,145 @@ var admin_user = function() { } else { roles = false; - app.u.throwGMessage("In admin_users,u.getRoleCheckboxesAsArray, $parent not specified or does not exist on the DOM."); + _app.u.throwGMessage("In admin_users,u.getRoleCheckboxesAsArray, $parent not specified or does not exist on the DOM."); } return roles; } - }, //u - e : { + }, //u + macrobuilders : { - "roleListEdit" : function($this) { - app.u.dump("BEGIN admin_users.e.roleListEdit"); - $this.sortable({ handle: ".handle" }); - }, //roleListEdit - -//on a user update, only the fields that have changed are sent and roles are always sent. -// so the form object is serialized for validation, but not sent. - "bossUserUpdateSave" : function($btn) { - $btn.button(); - $btn.off('click.bossUserUpdateSave').on('click.bossUserUpdateSave',function(event){ - event.preventDefault(); - app.u.dump("BEGIN admin_user.e.bossUserUpdateSave"); - var $panel = $btn.closest('.ui-widget-anypanel'), - frmObj = $btn.closest('form').serializeJSON(); - - if($panel.length == 0) {app.u.throwGMessage("In admin_user.e.bossUserUpdateSave, unable to determine $panel [$panel.length = "+$panel.length+"].");} - else if($.isEmptyObject(frmObj)) {app.u.throwGMessage("In admin_user.e.bossUserUpdateSave, the serialized form object was empty.");} - else if(!frmObj.email || !frmObj.fullname ) { - var msg = 'Please populate the following fields:<ol>'; - if(!frmObj.email) {msg += "<li>email<\/li>"} - if(!frmObj.fullname) {msg += "<li>fullname<\/li>"} - msg += "<\/ol>"; - var msgObj = app.u.errMsgObject(msg); - app.u.throwMessage(msgObj,true); - } - else { -// app.u.dump(" -> frmObj: "); app.u.dump(frmObj); - var update = {}; - update.login = frmObj.login; //for now, set both luser and login. Eventually, we'll use one or the other. - update.luser = frmObj.login; - - update['@roles'] = app.ext.admin_user.u.getRoleCheckboxesAsArray($panel); -//add all CHANGED attributes to the update object. - $(".edited",$panel).each(function(){ - update[$(this).attr('name')] = $(this).val(); - }); - -//the call will return a 1 if it's going to request and a zero if an error occured. only proceed if no errors. - if(app.ext.admin.calls.bossUserUpdate.init(update,{},'immutable')) { - $('body').showLoading({'message':'Saving your changes for '+update.login}); - -//to ensure new copies of the data, destroy the old. - app.model.destroy('bossUserList'); - app.model.destroy('bossUserDetail|'+update.luser); - - app.ext.admin.calls.bossUserDetail.init(update.luser,{},'immutable'); - app.ext.admin.calls.bossUserList.init({ - 'callback': function(rd) { - $('body').hideLoading(); - if(app.model.responseHasErrors(rd)){ - app.u.throwMessage(rd); - } - else { - app.ext.admin_user.u.resetUsersTable(); //empty list of users so that changes are reflected. - $panel.anypanel('destroy'); - $("[data-luser='"+update.luser+"'] .editUser",'#userManagerContent').trigger('click'); - } - }},'immutable'); - app.model.dispatchThis('immutable'); - } - else {} //error handling handled by call in if statement. - } - - }); - }, //bossUserUpdateSave - -/* -the create and update template is recycled. the button has the same app event, but performs a different action based on whether or not a save or update is being perfomed. -Whether it's a create or update is based on the data-usermode on the parent. -*/ - "bossUserCreateSave" : function($btn){ - $btn.button(); - $btn.off('click.bossUserCreateUpdateSave').on('click.bossUserCreateUpdateSave',function(event){ - event.preventDefault(); - app.u.dump("BEGIN admin_user.e.bossUserCreateUpdateSave"); - var $parent = $('#bossUserCreateModal'), - frmObj = $(this).closest("form").serializeJSON(); //used to generate roles array and also sent directly as part of create. not used in update. - - $(".appMessage",$parent).empty().remove(); //clean any existing errors. - - if($.isEmptyObject(frmObj)) { - app.u.throwGMessage('In admin_user.e.bossUserCreateUpdateSave, unable to locate form object for serialization or serialized object is empty.'); - } - else if(!frmObj.email || !frmObj.password || !frmObj.fullname || !frmObj.login) { - - var msg = 'Please populate the following fields:<ol>'; - - if(!frmObj.email) {msg += "<li>email<\/li>"} - if(!frmObj.password) {msg += "<li>password<\/li>"} - if(!frmObj.fullname) {msg += "<li>fullname<\/li>"} - if(!frmObj.login) {msg += "<li>login<\/li>"} - msg += "<\/ol>"; - - var msgObj = app.u.errMsgObject(msg); - msgObj.parentID = 'bossUserCreateModal'; - app.u.throwMessage(msgObj,true); - $parent.animate({scrollTop: 0}, 'fast'); - } - else { - $parent.showLoading({'message':'Creating user '+frmObj.login}); - -//build an array of the roles that are checked. order is important. - frmObj['@roles'] = app.ext.admin_user.u.getRoleCheckboxesAsArray($parent); - $(":checkbox",$parent).each(function(){ - delete frmObj[$(this).attr('name')]; //remove from serialized form object. params are/may be whitelisted. - }); - - app.model.destroy('bossUserList'); - app.ext.admin.calls.bossUserCreate.init(frmObj,{'callback':function(rd){ //rd is responseData. - if(app.model.responseHasErrors(rd)){ - $parent.animate({scrollTop: 0}, 'slow'); //scroll to top of modal div to messaging appears. not an issue on success cuz content is emptied. - rd.parentID = 'bossUserCreateModal'; //set so errors appear in modal. - app.u.throwMessage(rd); - $parent.dialog({buttons: {"Close": function() {$( this ).dialog( "close" ).empty().remove();}}}); //adds a 'close' button. - } - else { - var msg = app.u.successMsgObject("User has been created!"); - msg.parentID = 'bossUserCreateModal'; - $parent.empty(); //only empty if no error occurs. That way user can correct and re-submit. - app.u.throwMessage(msg,true); - $( ".selector" ).dialog( "option", "buttons", [ { text: "Close", click: function() { $( this ).dialog( "close" ); }} ] ); - } - $parent.hideLoading(); - }},'immutable'); - app.ext.admin.calls.bossUserDetail.init(frmObj.login,{},'immutable'); //get this local. better UX if merchant goes straight to edit mode. - app.ext.admin.calls.bossUserList.init({'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ - app.u.throwMessage(rd); - } - else { - app.ext.admin_user.u.resetUsersTable(); //empty list of users so that changes are reflected. - } - $('body').hideLoading(); - }},'immutable'); - app.model.dispatchThis('immutable'); - } + 'bossUserCreateUpdate' : function(sfo,$form) { + _app.u.dump("BEGIN admin_support.macrobuilders.bossUserCreate"); + sfo['@roles'] = _app.ext.admin_user.u.getRoleCheckboxesAsArray($form); +//asdf sfo._cmd = "bossUserCreate" +//clean up sfo to minimize the request. + $(":checkbox",$form).each(function(){ + delete sfo[$(this).attr('name')]; //remove from serialized form object. params are/may be whitelisted. }); - }, //bossUserCreateUpdateSave + return sfo; + } //adminGiftcardMacro - "bossUserDetail" : function($btn){ - $btn.button({icons: {primary: "ui-icon-pencil"},text: false}); //ui-icon-pencil - $btn.addClass('editUser'); //used for triggering click after user update. - $btn.off('click.bossUserUpdate').on('click.bossUserUpdate',function(event){ - event.preventDefault(); -// app.u.dump("BEGIN admin_user.e.bossUserUpdate click event"); - - var $target = $("[data-app-role='dualModeDetail']","#userManagerContent"), - index = $(this).closest('tr').data('obj_index'); - user = app.data.bossUserList['@USERS'][index]; - user['@ROLES'] = {}; - - $.extend(user['@ROLES'],app.data.bossRoleList['@ROLES']); - -// app.u.dump(" -> user object["+index+"]: "); app.u.dump(user); - if(!$.isEmptyObject(user)) { - //see bossUserCreateUpdateSave app event to see what usermode is used for. - -var panelID = app.u.jqSelector('','userDetail_'+user.luser), -$panel = $("<div\/>").data('luser',user.luser).hide().anypanel({ - 'header':'Edit: '+user.luser, - 'templateID':'userManagerUserCreateUpdateTemplate', -// 'data':user, //data not passed because it needs req and manipulation prior to translation. - 'dataAttribs': {'id':panelID,'luser':user.luser,'usermode':'update'} - }).prependTo($target); - -$('.passwordContainer',$panel).append("<div class='hint'>leave password blank for no change<\/div>"); //password not editable from here. + }, -//adds the save button to the bottom of the form. not part of the template because the template is shared w/ create. -var $saveButton = $("<button \/>").attr('data-app-event','admin_user|bossUserUpdateSave').html("Save <span class='numChanges'></span> Changes").button({'disabled':true}); + e : { -$('form',$panel).append($saveButton); -app.ext.admin.u.handleAppEvents($panel); - $panel.showLoading({'message':'Gathering nuts, berries and user details.'}); - $panel.slideDown('fast'); + bossUserCreateShow : function($ele,p){ -if(app.ext.admin.calls.bossUserDetail.init(user.luser,{ - 'callback':function(rd){ -// app.u.dump("BEGIN admin_user.e.bossUserUpdate anonymous callback"); -// app.u.dump(" -> panelID: "+panelID); -// app.u.dump(" -> user.luser: "+user.luser); - if(app.model.responseHasErrors(rd)){ - app.u.throwMessage(rd); - } - else { - - var userData = $.extend(app.data[rd.datapointer],app.data.bossRoleList); - -// app.u.dump(" -> userData:"); app.u.dump(userData); - app.renderFunctions.translateSelector('#'+panelID,userData); -//the list is already sortable by an app event. this just makes sure a change in role order increments # of changes and allows a save. - $("[data-app-role='roleList']",$panel).on("sortupdate",function(evt,ui){ - ui.item.find(':checkbox').addClass('edited'); - $('.numChanges',$panel).text($(".edited",$panel).length); - $saveButton.button('enable').addClass('ui-state-highlight'); - }); - - $(":input",$panel).off('change.trackChange').on('change.trackChange',function(){ - $(this).addClass('edited'); - $('.numChanges',$panel).text($(".edited",$panel).length); - $saveButton.button('enable').addClass('ui-state-highlight'); - }); - $("[name='login']",$panel).attr('readonly','readonly').css({'border':'none','background':'none'}); //NOTE - if attr disabled is set, serializeJSON does NOT include that field. - var L = userData['@roles'].length; -//loop backwards so that each row can be moved to the top but the original order will be preserved. - for(var i = (L-1); i >= 0; i -= 1) { -// app.u.dump(" -> userData['@roles'][i]: "+userData['@roles'][i]); - $("[name='"+userData['@roles'][i]+"']",$panel).attr('checked','checked'); - $("[name='"+userData['@roles'][i]+"']",$panel).closest('tr').insertBefore($("[data-app-role='roleList'] > tbody > tr:first",$panel)); //move checked roles to top of list. - } - $panel.hideLoading(); - } - } - },'mutable')) { -//showloading is run AFTER the animation so that it places itself correctly over the target. - app.model.dispatchThis('mutable'); - } - else { -//no dispatch is occuring. Don't do a showLoading cuz the data will be added immediately. - $panel.slideDown('fast'); - } + var $D = _app.ext.admin.i.dialogCreate({ + 'title' : 'Create New User', + 'templateID':'userManagerUserCreateUpdateTemplate', + 'data':$ele.data(), + 'extendByDatapointers' : ['bossRoleList'] + }); +//create and update share a template. The inputs below are for the callback. + $('form',$D).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' /><input type='hidden' name='_cmd' value='bossUserCreate' /><input type='hidden' name='_tag/callback' value='showMessaging' /><input type='hidden' name='_tag/restoreInputsFromTrackingState' value='1' /><input type='hidden' name='_tag/jqObjEmpty' value='true' /><input type='hidden' name='_tag/message' value='The user has been created.' /><input type='hidden' name='_macrobuilder' value='admin_user|bossUserCreateUpdate' />"); - } -//append detail children before changing modes. descreases 'popping'. - app.ext.admin.u.toggleDualMode($('#userManagerContent'),'detail'); + $('form',$D).append("<div class='buttonset alignRight'><button data-app-click='admin|submitForm' class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-plus'>Create User</button></div>"); - }); + _app.u.handleButtons($D.anyform()); + $D.dialog('open'); + $("[data-app-role='roleListTbody']",$D).sortable(); }, - - "bossUserDelete" : function($btn) { - $btn.button({icons: {primary: "ui-icon-trash"},text: false}); - $btn.off('click.bossUserCreate').on('click.bossUserCreate',function(event){ - event.preventDefault(); - var data = $(this).closest('tr').data(), - $D = $("<div \/>").attr('title','Delete User').append("Are you sure you want to delete user <b>"+(data.fullname || data.luser)+"<\/b>? This action can not be undone."); - - $D.dialog({ -resizable: false, -modal: true, -buttons: { - "Delete User": function() { - $D.dialog('close'); - $('body').showLoading({'message':'Deleting User'}); - app.model.destroy('bossUserList'); //clear local so a dispatch occurs. - app.ext.admin.calls.bossUserDelete.init(data.luser,{},'immutable'); - app.ext.admin.calls.bossUserList.init({'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ - app.u.throwMessage(rd); - } - else { - app.ext.admin_user.u.resetUsersTable(); //empty list of users so that changes are reflected. - } - $('body').hideLoading(); - }},'immutable'); - app.model.dispatchThis('immutable'); - }, - Cancel: function() {$( this ).dialog( "close" ).empty().remove();} - } - }); - }); + + + bossUserDetailShow : function($ele,p) { - }, + var + userID = $ele.closest("[data-uid]").data('uid'), + luser = $ele.closest("[data-luser]").data('luser'); + + if(userID && luser) { + + var $panel = _app.ext.admin.i.DMIPanelOpen($ele,{ + 'templateID' : 'userManagerUserCreateUpdateTemplate', + 'showLoading' : false, + 'panelID' : 'user_'+userID, + 'header' : 'Edit User: '+luser + }); + $panel.showLoading({'message':'Fetching user details'}).attr({'data-uid':userID,'data-luser':luser}); + + $('form',$panel).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' /><input type='hidden' name='_cmd' value='bossUserUpdate' /><input type='hidden' name='_tag/callback' value='showMessaging' /><input type='hidden' name='_tag/restoreInputsFromTrackingState' value='1' /><input type='hidden' name='_tag/message' value='The user has been updated.' /><input type='hidden' name='_macrobuilder' value='admin_user|bossUserCreateUpdate' />"); + + _app.model.addDispatchToQ({ + '_cmd':'bossUserDetail', + 'login':luser, + '_tag': { + 'callback' : 'anycontent', + 'datapointer' : 'bossUserDetail|'+userID, + 'onComplete': function(rd){ + //now handle role checkboxes. + var userData = _app.data[rd.datapointer]; + var L = userData['@roles'].length; + //loop backwards so that each row can be moved to the top but the original order will be preserved. + for(var i = (L-1); i >= 0; i -= 1) { + $("[name='"+userData['@roles'][i]+"']",$panel).prop('checked','checked'); + $("[name='"+userData['@roles'][i]+"']",$panel).closest('tr').insertBefore($("[data-app-role='roleList'] > tbody > tr:first",$panel)); //move checked roles to top of list. + } +//adds the save button to the bottom of the form. not part of the template because the template is shared w/ create. + $("<button \/>").attr({'data-app-click':'admin|submitForm','data-app-role':'saveButton'}).append("Save <span class='numChanges'></span> Changes").button({'disabled':'disabled'}).appendTo($('form',$panel)); - "bossUserCreate" : function($btn){ - $btn.button(); - $btn.off('click.bossUserCreate').on('click.bossUserCreate',function(event){ - event.preventDefault(); - var $target = $('#bossUserCreateModal'); - if($target.length) {$target.empty();} - else { - $target = $("<div \/>").attr({'id':'bossUserCreateModal','title':'Create User'}); - $target.appendTo("body"); - $target.dialog({width:500,height:600,autoOpen:false,modal:true}); - } - $target.dialog('open'); - //see bossUserCreateUpdateSave app event to see what usermode is used for. - $target.append(app.renderFunctions.transmogrify({'id':'bossUserCreateContent','usermode':'create'},'userManagerUserCreateUpdateTemplate',app.data.bossRoleList)); //populate content. - //adds the save button to the bottom of the form. not part of the template because the template is shared w/ create. - $('form',$target).append("<button data-app-event='admin_user|bossUserCreateSave' class='alignCenter'>Create User</button>"); + $("[data-app-role='roleListTbody']",$panel).sortable({ + stop : function(event,ui) { + $(":checkbox",ui.item).addClass('edited'); + _app.u.dump(" -> ui.item.closest('.anyformEnabled').length: "+ui.item.closest('.anyformEnabled').length); + ui.item.closest('.anyformEnabled').anyform('updateChangeCounts'); + } + }); + + $("[name='login']",$panel).attr('readonly','readonly').css({'border':'none','background':'none'}); //NOTE - if attr disabled is set, serializeJSON does NOT include that field. + $("[name='password']",$panel).prop('required','').removeProp('required'); + $('.passwordContainer',$panel).append("<div class='hint'>leave password blank for no change<\/div>"); //password not editable from here. + }, + 'translateOnly' : true, + 'jqObj' : $panel, + 'extendByDatapointers' : ['bossRoleList'] + } + },'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + //missing some required params. throw error. + $('#globalMessaging').anymessage({"message":"In admin_user.e.bossUserDetailShow, either user "+luser+" or uid "+userID+" not found and both are required.","gMessage":true}); + } + }, - app.ext.admin.u.handleAppEvents($target); - }); - } - } + bossUserDeleteConfirm : function($ele,p) { + var luser = $ele.closest("[data-luser]").data('luser'); + if(luser) { + var $D = _app.ext.admin.i.dialogConfirmRemove({ + "message" : "Are you sure you wish to delete user "+luser+"? There is no undo for this action.", + "removeButtonText" : "Remove User", //will default if blank + "title" : "Remove user: "+luser, //will default if blank + "removeFunction" : function(vars,$D){ + $D.showLoading({"message":"Deleting user "+luser}); + _app.model.addDispatchToQ({ + '_cmd':'bossUserDelete', + 'login' : luser, + '_tag': { + 'callback':function(rd){ + $D.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else { + $D.dialog('close'); + $ele.closest("[data-app-role='dualModeContainer']").find("[data-app-click='admin|refreshDMI']").trigger('click'); + } + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); + } + }) + } + else { + $('#globalMessaging').anymessage({"message":"In admin_users.e.bossUserDeleteConfirm, unable to ascertain L-user name.","gMessage":true});} + } //bossUserDeleteConfirm + } //E/events } //r object. return r; } \ No newline at end of file diff --git a/extensions/admin/wholesale.html b/extensions/admin/wholesale.html index 5eecb14b4..a60d280fa 100644 --- a/extensions/admin/wholesale.html +++ b/extensions/admin/wholesale.html @@ -2,67 +2,26 @@ <!-- //////////////// ORGANIZATION \\\\\\\\\\\\\\\\\\ --> +<div id='orgManagerControls' class='floatRight'> +<form action='#' onSubmit='return false' data-app-submit='admin_wholesale|execOrganizationSearch'> + <select name='searchby'> + <option value='CONTACT'>contact</option> + <option value='DOMAIN'>domain</option> + <option value='COMPANY'>company</option> + <option value='EMAIL'>email</option> + <option value='ORGID'>organization id</option> + <option value='PHONE' selected="selected">phone</option> + <option value='SCHEDULE'>schedule</option> + <option value='ACCOUNT_MANAGER'>account manager</option> + <option value='ACCOUNT_TYPE'>account type</option> - -<div id='organizationManagerPageTemplate' class='page pageOrganization' data-app-role='dualModeContainer' data-app-mode='list'> - - <section class='dualModeDetailContainer' data-app-role='dualModeDetail'></section> - - <section class='dualModeListContainer' data-app-role='dualModeList'> - <div class='ui-widget-header ui-corner-top'> - <div class='buttonSet'> - <button data-app-event='admin_wholesale|showOrganizationCreate' class='floatRight'>New Organization</button> - </div> - <h3 class='heading'>Organization Manager</h3> - </div> - <div class='ui-state-default smallPadding alignRight'> - <form action='#' onSubmit='return false'> - <select name='searchby'> - <option value='CONTACT'>contact</option> - <option value='DOMAIN'>domain</option> - <option value='COMPANY'>company</option> - <option value='EMAIL'>email</option> - <option value='ORGID'>organization id</option> - <option value='PHONE' selected="selected">phone</option> - <option value='SCHEDULE'>schedule</option> - <option value='ACCOUNT_MANAGER'>account manager</option> - <option value='ACCOUNT_TYPE'>account type</option> - - </select> - <input type='search' name='keywords' size='20' /> - <label class='marginRight'><input type='checkbox' name="IS_LOCKED" />locked only</label> - <button data-app-event='admin_wholesale|execOrganizationSearch'>Search</button> - </form> - </div> - - <div class='ui-widget-content ui-corner-bottom'> - <div class="dualModeListMessaging marginBottom">Please use the search above to find the organization(s) you are looking for.</div> - <table class='gridTable fullWidth displayNone marginBottom' data-app-role='dualModeResultsTable'> - <!-- thead is needed, whether visible or not, so that the data-name attributes can be used to look up column # --> - <thead> - <tr> - <th data-anytable-nosort='true'></th> - <th class='alignLeft'>ID</th> - <th class='alignLeft'>Company</th> - <th class='alignLeft'>Domain</th> - <th class='alignLeft'>Email</th> - <th class='alignLeft'>Account Manager</th> - <th class='alignLeft'>Billing Phone</th> - <th class='alignLeft'>Billing Contact</th> - <th data-anytable-nosort='true'></th> - </tr> - </thead> - <tbody data-bind="var: users(@ORGANIZATIONS); format:processList; loadsTemplate:organizationManagerOrgRowTemplate;" class='dualModeList' data-app-role='dualModeListContents'></tbody> - </table> - - <div data-app-role='dualModeDetailContainer' class='displayNone stdPadding'></div> - - </div> - </section> + </select> + <input type='search' name='keywords' size='20' /> + <label class='marginRight'><input type='checkbox' name="IS_LOCKED" />locked only</label> + <button class='applyButton' data-text='false' data-icon-primary='ui-icon-search'>Search</button> +</form> </div> - - <table> <tr id='organizationManagerOrgRowTemplate'> <td><span data-bind="var: organization(IS_LOCKED); format:showIfSet;" class='displayNone'><span data-bind="var: organization(IS_LOCKED); format:text;" class='ui-icon ui-icon-locked'></span></span></td> @@ -74,8 +33,8 @@ <h3 class='heading'>Organization Manager</h3> <td data-bind="var: organization(BILLING_PHONE); format:text;"></td> <td data-bind="var: organization(BILLING_CONTACT); format:text;"></td> <td class='alignRight'> - <button data-app-event="admin_wholesale|execOrganizationRemove">remove</button> - <button data-app-event="admin_wholesale|showOrganizationUpdate">edit</button> + <button data-app-click="admin_wholesale|execOrganizationRemove" class='applyButton' data-text='false' data-icon-primary='ui-icon-trash'>remove</button> + <button data-app-click="admin_wholesale|showOrganizationUpdate" class='applyButton' data-text='false' data-icon-primary='ui-icon-pencil'>edit</button> </td> </tr> @@ -87,69 +46,69 @@ <h3 class='heading'>Organization Manager</h3> -<div id='organizationManagerOrgCreateUpdateTemplate' title='User' class='createUpdateOrganizationContainer'> - -<form action='#' onSubmit='return false'> - -<fieldset class='alignedInputs labelsAsBreaks floatLeft threeColumn'> - <legend>Organization Information</legend> - - <div class='label'><input type='text' placeholder='first name' name='firstname' value='' data-bind='var: org(ORG.firstname); format:popVal;' /></div> - <div class='label'><input type='text' placeholder='last name' name='lastname' value='' data-bind='var: org(ORG.lastname); format:popVal;' /></div> - - <div class='label'><input type='text' name='company' placeholder='company' required='required' value='' data-bind='var: org(ORG.company); format:popVal;' /></div> - <div class='label'><input type='text' name='DOMAIN' placeholder='domain' value='' data-bind='var: org(ORG.DOMAIN); format:popVal;' /></div><!-- do NOT use url as input type, only the domain is desired --> - <div class='label'><input type='tel' name='phone' placeholder='phone' value='' data-bind='var: org(ORG.phone); format:popVal;' onKeyPress='return app.u.numbersOnly(event);' /></div><!-- phone is numbers only --> - <div class='label'><input type='text' name='address1' placeholder='address' value='' data-bind='var: org(ORG.address1); format:popVal;' /></div> - <div class='label'><input type='text' name='address2' placeholder='address 2' value='' data-bind='var: org(ORG.address2); format:popVal;' /></div> - <div class='label'><input type='text' name='city' placeholder='city' value='' data-bind='var: org(ORG.city); format:popVal;' /></div> - <div class='label'><input type='text' name='region' placeholder='state/region' size='5' value='' data-bind='var: org(ORG.region); format:popVal;' maxlength='20' /></div> - - <!-- postal not required for international. don't add it. --> - <div class='label'><input type='text' name='postal' placeholder='zip/postal code' size='14' value='' data-bind='var: org(ORG.postal); format:popVal;' maxlength='10' /></div> - - <div class='label'><input name='countrycode' size='9' maxlength="9" data-minlength='2' plceholder='country code' data-bind='var: org(ORG.countrycode); format:popVal;' /></div> - -</fieldset> - -<fieldset class='alignedInputs floatLeft labelsAsBreaks threeColumn'> - <legend>Billing</legend> - <div class='label'><input type='text' name='BILLING_CONTACT' placeholder='billing contact' value='' data-bind='var: org(ORG.BILLING_CONTACT); format:popVal;' /></div> - <div class='label'><input type='tel' name='BILLING_PHONE' placeholder='billing phone' value='' data-bind='var: org(ORG.BILLING_PHONE); format:popVal;' onKeyPress='return app.u.numbersOnly(event);' /></div> - <div class='label'> - <label data-bind="useParentData:true; format:wholesaleScheduleSelect; extension:admin_wholesale;">Schedule: </label> +<div id='organizationManagerOrgCreateUpdateTemplate' title='User' class='createUpdateOrganizationContainer ui-widget'> + <div class='ui-widget-content stdPadding'> + <form action='#' onSubmit='return false'> + + <fieldset class='alignedInputs labelsAsBreaks floatLeft threeColumn'> + <legend>Organization Information</legend> + + <div class='label'><input type='text' placeholder='first name' name='firstname' value='' data-bind='var: org(ORG.firstname); format:popVal;' /></div> + <div class='label'><input type='text' placeholder='last name' name='lastname' value='' data-bind='var: org(ORG.lastname); format:popVal;' /></div> + + <div class='label'><input type='text' name='company' placeholder='company' required='required' value='' data-bind='var: org(ORG.company); format:popVal;' /></div> + <div class='label'><input type='text' name='DOMAIN' placeholder='domain' value='' data-bind='var: org(ORG.DOMAIN); format:popVal;' /></div><!-- do NOT use url as input type, only the domain is desired --> + <div class='label'><input type='tel' name='phone' placeholder='phone' value='' data-bind='var: org(ORG.phone); format:popVal;' onKeyPress='return adminApp.u.numbersOnly(event);' /></div><!-- phone is numbers only --> + <div class='label'><input type='text' name='address1' placeholder='address' value='' data-bind='var: org(ORG.address1); format:popVal;' /></div> + <div class='label'><input type='text' name='address2' placeholder='address 2' value='' data-bind='var: org(ORG.address2); format:popVal;' /></div> + <div class='label'><input type='text' name='city' placeholder='city' value='' data-bind='var: org(ORG.city); format:popVal;' /></div> + <div class='label'><input type='text' name='region' placeholder='state/region' size='5' value='' data-bind='var: org(ORG.region); format:popVal;' maxlength='20' /></div> + + <!-- postal not required for international. don't add it. --> + <div class='label'><input type='text' name='postal' placeholder='zip/postal code' size='14' value='' data-bind='var: org(ORG.postal); format:popVal;' maxlength='10' /></div> + + <div class='label'><input name='countrycode' size='9' maxlength="9" data-minlength='2' placeholder='country code' data-bind='var: org(ORG.countrycode); format:popVal;' /></div> + + </fieldset> + + <fieldset class='alignedInputs floatLeft labelsAsBreaks threeColumn'> + <legend>Billing</legend> + <div class='label'><input type='text' name='BILLING_CONTACT' placeholder='billing contact' value='' data-bind='var: org(ORG.BILLING_CONTACT); format:popVal;' /></div> + <div class='label'><input type='tel' name='BILLING_PHONE' placeholder='billing phone' value='' data-bind='var: org(ORG.BILLING_PHONE); format:popVal;' onKeyPress='return adminApp.u.numbersOnly(event);' /></div> + <div class='label'> + <label data-bind="var: org(ORG.SCHEDULE); forceRender:true; format:wholesaleScheduleSelect; extension:admin_wholesale;">Schedule: </label> + </div> + <label><input class='applyAnycb' type='checkbox' name='ALLOW_PO' data-bind='var: org(ORG.ALLOW_PO); format:popVal;' />Allow Purchase Orders</label> + <label><input class='applyAnycb' type='checkbox' name='RESALE' data-bind='var: org(ORG.RESALE); format:popVal;' />Allow Resale/Tax Exempt</label> + <label><input class='applyAnycb' type='checkbox' name='IS_LOCKED' data-bind='var: org(ORG.IS_LOCKED); format:popVal;' />Is Locked</label> + <div class='label'><input type='text' name='RESALE_PERMIT' placeholder='resale permit' value='' data-bind='var: org(ORG.RESALE_PERMIT); format:popVal;' /></div> + <div class='label'><input type='number' class='smallInput' name='CREDIT_LIMIT' placeholder='credit limit' value='' data-bind='var: org(ORG.CREDIT_LIMIT); format:popVal;' /></div> + <div class='label'><input type='number' class='smallInput' name='CREDIT_BALANCE' placeholder='credit balance' value='' data-bind='var: org(ORG.CREDIT_BALANCE); format:popVal;' /></div> + <div class='label'><input type='number' class='smallInput' name='CREDIT_TERMS' placeholder='credit terms' value='' data-bind='var: org(ORG.CREDIT_TERMS); format:popVal;' /></div> + </fieldset> + + <div class='alignedInputs labelsAsBreaks floatLeft threeColumn'> + <fieldset class='marginBottom'> + <legend>Company Logo</legend> + <img width="160" height="70" src="app-admin/images/blank.gif" data-app-role='organizationLogo' data-bind='var: org(ORG.LOGO); format:imageURL;bgcolor:TTTTTT; defaultValue: i/imagenotfound;' > + <a data-app-click="admin_wholesale|showMediaLib4OrganizationLogo" href="#"><b>[Edit]</b></a> + <input type='text' name='LOGO' class='displayNone' /><!-- use text input cuz hidden inputs don't support change events --> + </fieldset> + + <fieldset class='marginTop'> + <legend>Account Information</legend> + <div class='label'><input type='text' name='ACCOUNT_MANAGER' placeholder='account manager' value='' data-bind='var: org(ORG.ACCOUNT_MANAGER); format:popVal;' /></div> + <div class='label'><input type='text' name='ACCOUNT_TYPE' placeholder='account type' value='' data-bind='var: org(ORG.ACCOUNT_TYPE); format:popVal;' /></div> + <div class='label'><input type='text' name='ACCOUNT_REFID' placeholder='account reference id' value='' data-bind='var: org(ORG.ACCOUNT_REFID); format:popVal;' /></div> + </fieldset> + </div> + + <div class='clearfix'></div> + + <div class='buttonset clearfix marginTop alignRight'></div><!-- buttons will be automatically added to this thru the buttonset class --> + + </form> </div> - <label><input type='checkbox' name='ALLOW_PO' data-bind='var: org(ORG.ALLOW_PO); format:popVal;' />Allow Purchase Orders</label> - <label><input type='checkbox' name='RESALE' data-bind='var: org(ORG.RESALE); format:popVal;' />Allow Resale/Tax Exempt</label> - <label><input type='checkbox' name='IS_LOCKED' data-bind='var: org(ORG.IS_LOCKED); format:popVal;' />Is Locked</label> - <div class='label'><input type='text' name='RESALE_PERMIT' placeholder='resale permit' value='' data-bind='var: org(ORG.RESALE_PERMIT); format:popVal;' /></div> - <div class='label'><input type='number' name='CREDIT_LIMIT' placeholder='credit limit' value='' data-bind='var: org(ORG.CREDIT_LIMIT); format:popVal;' /></div> - <div class='label'><input type='number' name='CREDIT_BALANCE' placeholder='credit balance' value='' data-bind='var: org(ORG.CREDIT_BALANCE); format:popVal;' /></div> - <div class='label'><input type='number' name='CREDIT_TERMS' placeholder='credit terms' value='' data-bind='var: org(ORG.CREDIT_TERMS); format:popVal;' /></div> -</fieldset> - -<div class='alignedInputs labelsAsBreaks floatLeft threeColumn'> - <fieldset class='marginBottom'> - <legend>Company Logo</legend> - <img width="160" height="70" src="app-admin/images/blank.gif" data-app-role='organizationLogo' data-bind='var: org(ORG.LOGO); format:imageURL;bgcolor:TTTTTT; defaultValue: i/imagenotfound;' > - <a data-app-event="admin_wholesale|showMediaLib4OrganizationLogo" href="#"><b>[Edit]</b></a> - <input type='text' name='LOGO' class='displayNone' /><!-- use text input cuz hidden inputs don't support change events --> - </fieldset> - - <fieldset class='marginTop'> - <legend>Account Information</legend> - <div class='label'><input type='text' name='ACCOUNT_MANAGER' placeholder='account manager' value='' data-bind='var: org(ORG.ACCOUNT_MANAGER); format:popVal;' /></div> - <div class='label'><input type='text' name='ACCOUNT_TYPE' placeholder='account type' value='' data-bind='var: org(ORG.ACCOUNT_TYPE); format:popVal;' /></div> - <div class='label'><input type='text' name='ACCOUNT_REFID' placeholder='account reference id' value='' data-bind='var: org(ORG.ACCOUNT_REFID); format:popVal;' /></div> - </fieldset> -</div> - -<div class='clearfix'></div> - -<div class='buttonset clearfix marginTop alignRight'></div><!-- buttons will be automatically added to this by buttonset class --> - -</form> - </div> @@ -174,24 +133,27 @@ <h3 class='heading'>Organization Manager</h3> <!-- used in the list mode for each supplier --> <table> <tr id='supplierListItemTemplate'> - <td class='lookLikeLink' data-bind="var:supplier(NAME); format:text;" data-app-event='admin_wholesale|showSupplierEditor'></td> + <td class='hideInMinifyMode'><input class='allowBulkCheck' type='checkbox' /></td><!-- bind a change event that adds/remves ui-selected class on tr --> + <td class='lookLikeLink' data-bind="var:supplier(NAME); format:text;" data-app-click='admin_wholesale|showSupplierEditor'></td> <td data-bind="var:supplier(CODE); format:text;"></td> <td data-bind="var:supplier(FORMAT); format:text;"></td> - <td data-bind="var:supplier(MODE); format:text;" class='hideInMinimalMode'></td> <td class='alignRight'> - <button class='marginRight hideInMinimalMode' data-app-event='admin_wholesale|adminSupplierRemoveExec'>Remove this Supplier</button> - <button class='marginLeft hideInMinimalMode' data-app-event='admin_wholesale|adminSupplierProdOrderListShow' data-mode='product'>Inventory</button> - <button class='marginLeft hideInMinimalMode' data-app-event='admin_wholesale|adminSupplierInventoryAddShow'>Add Inventory</button> -<!-- <button class='marginLeft hideInMinimalMode' data-app-event='admin_wholesale|adminSupplierProdOrderListShow' data-mode='product'>Products</button> --> - <button class='marginLeft hideInMinimalMode' data-app-event='admin_wholesale|adminSupplierProdOrderListShow' data-mode='order'>Orders</button> - <button class='marginLeft hideInMinimalMode' data-app-event='admin_wholesale|adminSupplierUnorderedItemListShow' data-mode='vendor'>Unordered Items</button> - <button class='marginLeft' data-app-event='admin_wholesale|showSupplierEditor'>Edit this Supplier</button> + <button class='hideInMinimalMode applyButton' data-app-click='admin_wholesale|adminSupplierRemoveExec' data-text='false' data-icon-primary='ui-icon-trash'>Remove this Supplier</button> + <button class='marginLeft hideInMinimalMode applyButton' data-app-click='admin|showMenu' data-text='false' data-icon-primary='ui-icon-wrench' data-icon-secondary='ui-icon-triangle-1-s'>Tools</button> + <menu class='displayNone' data-bind='var:order(CODE);format:assignAttribute; attribute:data-code;'> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierUnorderedItemListShow' data-mode='vendor'>Unordered Items</a></li> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierProdOrderListShow' data-mode='order'>Order List</a></li> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierProdOrderListShow' data-mode='product'>Product List</a></li> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierProdOrderListShow' data-mode='product'>Inventory</a></li> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierInventoryAddShow' data-icon-primary='ui-icon-plus' data-text='true'>Add Inventory</a></li> + </menu> + <button class='marginLeft applyButton' data-text='false' data-icon-primary='ui-icon-pencil' data-app-click='admin_wholesale|showSupplierEditor'>Edit this Supplier</button> </td> </tr> <tr id='supplierOrderListItemTemplate'> <td><input type='checkbox' data-bind='var:order(OUR_ORDERID);format:assignAttribute; attribute:name; valuePretext:orderid_;' /></td> - <td data-app-event='admin_orders|showOrderEditorInDialog' data-bind='var:order(OUR_ORDERID);format:assignAttribute; attribute:data-orderid;'> + <td data-app-click='admin_orders|showOrderEditorInDialog' data-bind='var:order(OUR_ORDERID);format:assignAttribute; attribute:data-orderid;'> <span data-bind="var:supplier(OUR_ORDERID); format:text;"></span> </td> <td data-bind="var:order(VENDOR_REFID); format:text;"></td> @@ -209,7 +171,7 @@ <h3 class='heading'>Organization Manager</h3> <td data-bind="var:detail(COST_I); format:money; isElastic:true;"></td><!-- stored in the same manner as elastic --> <td data-bind="var:detail(NOTE); defaultVal:Never; format:text;"></td> <td> - <button class='applyButton' data-app-click='admin_prodEdit|productTaskPidToggle' data-bind="var: detail(PID); format:assignAttribute; attribute:data-pid;" data-icon-primary='ui-icon-circle-plus' data-text='false' data-clone='true'>Add as Product Task</button> + <button class='applyButton' data-app-click='admin_prodedit|productTaskPidToggle' data-bind="var: detail(PID); format:assignAttribute; attribute:data-pid;" data-icon-primary='ui-icon-circle-plus' data-text='false' data-clone='true'>Add as Product Task</button> </td> </tr> @@ -234,10 +196,10 @@ <h3 class='heading'>Organization Manager</h3> <label> <span>Quantity</span> - <input type='number' step='1' min='0' name='QTY' value='0' class='number resetMeOnComplete' /> + <input type='number' step='1' min='0' name='QTY' value='0' class='number resetMeOnComplete smallInput' /> </label> - <button data-app-event="admin_wholesale|adminSupplierInventoryAddExec">Add</button> + <button class='applyButton' data-text='true' data-icon-primary='ui-icon-plus' data-app-click="admin_wholesale|adminSupplierInventoryAddExec">Add</button> </fieldset> </form> @@ -280,7 +242,7 @@ <h3 class='heading'>Organization Manager</h3> <tr id='supplierUnorderedItemRowTemplate'> <td data-bind="var:supplier(CREATED_TS); format:text;"></td> <td data-bind="var:supplier(ID); format:text;"></td> - <td data-app-event='admin_orders|showOrderEditorInDialog' data-bind='var:order(OUR_ORDERID);format:assignAttribute; attribute:data-orderid;'> + <td data-app-click='admin_orders|showOrderEditorInDialog' data-bind='var:order(OUR_ORDERID);format:assignAttribute; attribute:data-orderid;'> <span data-bind="var:supplier(OUR_ORDERID); format:text;"></span> </td> <td data-bind="var:supplier(QTY); format:text;"></td> @@ -379,21 +341,21 @@ <h3 class='heading'>Organization Manager</h3> <option value='STOCK' data-show-panel='supplierFormatVendorID'>Stock/Vendor : orders are shipped from vendor to your warehouse(s)</option> <option value='DROPSHIP' data-show-panel='supplierFormatVendorID'>Dropship : orders will be shipped to customer out of vendors inventory</option> <option value='FULFILL' data-show-panel='supplierFormatVendorID'>Fulfillment/3PL : outsourced warehouse/logistics services</option> - <option value='FBA' data-change-input='VENDORID' data-change-newval='FBA'>FBA: fulfillment by amazon</option> + <option value='FBA' >FBA: fulfillment by amazon</option> <option value='RIVER' data-show-panel='supplierFormatVendorID'>River : transmits wire-speed copies of all orders for integrations</option> </select> </label> - + <input type='hidden' name='INIT-DEFAULTS' value='1' /><!-- if set, API will set some sane defaults --> <label class='label displayNone supplierFormatPanel' data-panel-id='supplierFormatVendorID' > <span>Supplier ID</span> - <input type="text" name="VENDORID" value="" maxlength="6" data-minlength='6' size="6" required='required' data-input-format="alphanumeric,uppercase" data-validation-rules='skipIfHidden' /> + <input type="text" name="VENDORID" value="" maxlength="6" data-minlength='6' size="6" required='required' data-input-keyup='input-format' data-input-format="alphanumeric,uppercase" data-validation-rules='skipIfHidden' /> <span class='toolTip' title="A unique 6 character alphanumeric code used for this supplier.">?</span> </label> - <div class='alignCenter'><button data-app-event='admin_wholesale|adminSupplierCreateExec'>Add Supplier</button></div> + <div class='alignCenter'><button data-app-click='admin_wholesale|adminSupplierCreateExec' class='applyButton'>Save Supplier</button></div> </fieldset> </form> @@ -411,7 +373,7 @@ <h3 class='heading'>Organization Manager</h3> <div id='supplierUpdateTemplate' class='clearfix'> -<form autocomplete="on" action='#' onsubmit="return false;"> +<form autocomplete="on" action='#' onsubmit="return false;" data-cb_tf='true'> <input type='hidden' name='_macrobuilder' value='admin_wholesale|adminSupplierMacro' /> <input type='hidden' name='_tag/callback' value='showMessaging' /> @@ -422,16 +384,22 @@ <h3 class='heading'>Organization Manager</h3> - <div class='buttonBar clearfix marginBottom ui-widget ui-widget-content ui-corner-all smallPadding' data-bind='var:order(CODE);format:assignAttribute; attribute:data-code;'> - <button class='floatRight marginLeft' data-app-event='admin|processForm' data-app-role='saveButton' disabled="disabled">Save <span class='numChanges'></span> Changes</button> - <button class='floatRight marginRight marginLeft' data-app-event='admin_wholesale|adminSupplierUnorderedItemListShow' data-mode='vendor'>Unordered Items</button> - <button class='floatRight marginLeft' data-app-event='admin_wholesale|adminSupplierProdOrderListShow' data-mode='order'>Order List</button> - <button class='floatRight' data-app-event='admin_wholesale|adminSupplierProdOrderListShow' data-mode='product'>Product List</button> -<!-- <button class='floatRight'>Add Product</button> add when time permits. --> + <div class='buttonBar clearfix marginBottom ui-widget ui-widget-content ui-corner-all smallPadding'> + <button class='floatRight marginLeft applyButton' data-app-click='admin|submitForm' data-app-role='saveButton' disabled="disabled">Save <span class='numChanges'></span> Changes</button> + <button class='floatRight marginLeft applyButton' data-app-click='admin|showMenu' data-text='true' data-icon-primary='ui-icon-wrench' data-icon-secondary='ui-icon-triangle-1-s'>Tools</button> + <menu class='displayNone' data-bind='var:order(CODE);format:assignAttribute; attribute:data-code;'> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierUnorderedItemListShow' data-mode='vendor'>Unordered Items</a></li> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierProdOrderListShow' data-mode='order'>Order List</a></li> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierProdOrderListShow' data-mode='product'>Product List</a></li> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierProdOrderListShow' data-mode='product'>Inventory</a></li> + <li><a href='#' data-app-click='admin_wholesale|adminSupplierInventoryAddShow' data-icon-primary='ui-icon-plus' data-text='true'>Add Inventory</a></li> + </menu> + + <h2 class='floatLeft ui-widget-header-padding'> Supplier: <span data-bind="var:supplier(CODE); format:text;"></span> - (created on <span data-bind="var:supplier(CREATED_GMT); format:unix2mdy;"></span>) + (created on <span data-bind="var:supplier(CREATED_GMT); format:epoch2mdy;"></span>) </h2> </div> @@ -606,7 +574,7 @@ <h2>Setup: Shipping Calculations</h2> <option value='FIXED' data-show-panel='supplierShippingConnectorFixed,supplierShippingConnectorHandling'>Fixed</option> <option value='ZONE' data-show-panel='supplierShippingConnectorZone,supplierShippingConnectorHandling'>Zone</option> <option value='FBA' data-show-panel='supplierOurFBAConfig'>Amazon FBA</option> - </select /> + </select> </label> <div data-panel-id='supplierShippingConnectorNone' class='supplierShippingConnector'>Will use your store configuration</div> @@ -624,18 +592,12 @@ <h2>Setup: Shipping Calculations</h2> <input type="text" name="%SHIP.origstate" value="" size="2" data-bind="var:vendor(%SHIP.origstate); format:popVal;" /> </label> -<button data-app-event='admin_config|shipMeterDetailInModal' data-provider='FEDEX'>Configure FedEx Meter</button> -<button data-app-event='admin_config|shipMeterDetailInModal' data-provider='UPS'>Configure UPS Meter</button> +<button class='applyButton' data-app-click='admin_config|shipMeterDetailInModal' data-provider='FEDEX'>Configure FedEx Meter</button> +<button class='applyButton' data-app-click='admin_config|shipMeterDetailInModal' data-provider='UPS'>Configure UPS Meter</button> </div> <div data-panel-id='supplierShippingConnectorFixed' class='displayNone supplierShippingConnector'></div> -<!-- -<b>Current Shipping Meter</b><br> - None confirmed at this time...<br> -<input type="button" name="BUTTON" value="Configure UPS Meter Number" class="button" onclick="navigateTo('/biz/setup/shipping/upsapi.cgi?mode=apply&SUPPLIER_ID=JOEBOB');"> -<input type="button" name="BUTTON" value="Configure Fedex Meter Number" class="button" onclick="navigateTo('/biz/setup/shipping/index.cgi?VERB=FEDEX-SUPPLIER-REGISTER&SUPPLIER_ID=JOEBOB');"> ---> <div data-panel-id='supplierShippingConnectorHandling' class='displayNone supplierShippingConnector'> @@ -647,17 +609,17 @@ <h2 class='marginTop'>Handling Fees</h2> <label class='marginLeft'> <span>Per Order</span> $ - <input type="number" step='.01' min='0' name="hnd_perorder" value="" size="5" data-bind="var:vendor(%SHIP.hnd_perorder); format:popVal;" /> + <input type='number' class='smallInput' step='.01' min='0' name="hnd_perorder" value="" size="5" data-bind="var:vendor(%SHIP.hnd_perorder); format:popVal;" /> </label> <label class='marginLeft'> <span>Per Item</span> $ - <input type="number" step='.01' min='0' name="hnd_peritem" value="" size="5" data-bind="var:vendor(%SHIP.hnd_peritem); format:popVal;" /> + <input type='number' class='smallInput' step='.01' min='0' name="hnd_peritem" value="" size="5" data-bind="var:vendor(%SHIP.hnd_peritem); format:popVal;" /> </label> <label class='marginLeft'> <span>Per Unique Item</span> $ - <input type="number" step='.01' min='0' name="hnd_perunititem" value="" size="5" data-bind="var:vendor(%SHIP.hnd_perunititem); format:popVal;" /> + <input type='number' class='smallInput' step='.01' min='0' name="hnd_perunititem" value="" size="5" data-bind="var:vendor(%SHIP.hnd_perunititem); format:popVal;" /> </label> </div> @@ -674,7 +636,7 @@ <h2 class='marginTop'>Handling Fees</h2> <div class='twoColumn column2' data-app-column='2' data-bind='var:order(CODE);format:assignAttribute; attribute:data-code;'> - <div class='panel labelsAsBreaks alignedLabels supplierOurFBAConfig displayNone' data-panel-id='supplierOurFBAConfig'> + <div class='panel labelsAsBreaks alignedLabels supplierShippingConnector displayNone' data-panel-id='supplierOurFBAConfig'> <h2>FBA Configuration</h2> <div class='clearfix'> <p class='hint'>To use FBA your supplier code MUST be named "FBA"</p> @@ -701,7 +663,8 @@ <h2>Setup: Inventory Preferences & Download</h2> <label> <span>Preference</span> - <input type='number' name='PREFERENCE' value='' data-bind="var:vendor(PREFERENCE); format:popVal;" max='100' step='1' min='1' size='3' /> + <input type='number' class='smallInput' name='PREFERENCE' value='' data-bind="var:vendor(PREFERENCE); format:popVal;" max='100' step='1' min='1' size='3' /> + <span class='toolTip' title="A numerical value between 1 and 99 to indicate what 'preference' this source should be given for a sku if multiple sources are available. The higher the number, the more likely it is to be auto-assigned as the source.">?</span> </label> </fieldset> @@ -710,7 +673,7 @@ <h2>Setup: Inventory Preferences & Download</h2> <fieldset data-app-role='INVENTORYSET'> <label> <span>Connector:</span> - <select name='INVENTORY_CONNECTOR' data-bind="var:vendor(INVENTORY_CONNECTOR); format:popVal;" data-input-change="panel-selector" data-panel-selector=".supplierInventoryConnector" data-trigger='click'> + <select name='INVENTORY_CONNECTOR' data-bind="var:vendor(INVENTORY_CONNECTOR); format:popVal;" data-input-change="panel-selector" data-panel-selector=".supplierInventoryConnector"> <option value='NONE'>None</option> <option value='GENERIC' data-show-panel='supplierInventoryConnectorGeneric'>Generic</option> <option value='FBA' data-show-panel='supplierOurFBAConfig'>Amazon FBA</option> @@ -737,7 +700,7 @@ <h2>Setup: Inventory Preferences & Download</h2> <textarea name='header' data-bind="var:vendor(%INVENTORY.header); format:popVal;" required='required' data-validation-rules='skipIfHidden'></textarea> </label> - <button data-app-event='admin_wholesale|adminSupplierAction' data-action="INVENTORY:UPDATE">Start Import</button> + <button data-app-click='admin_wholesale|adminSupplierAction' class='applyButton' data-text='true' data-icon-primary='ui-icon-arrowreturnthick-1-s' data-action="INVENTORY:UPDATE">Start Import</button> </div> </fieldset> @@ -764,7 +727,7 @@ <h2>Setup: Automatic Ordering</h2> </label> <label><span>Version</span> - <select name='export_format' data-bind="var: supplier(%ORDER.export_format); format:popVal;" data-input-change="panel-selector" data-input-change="panel-selector" data-panel-selector=".supplierExportFormat"> + <select name='export_format' data-bind="var: supplier(%ORDER.export_format); format:popVal;" data-input-change="panel-selector" data-panel-selector=".supplierExportFormat"> <option value=''>-</option> <option value='XML#201240'>v.201240 XML - valid until: 2015-10-15</option> <option value='XSLT#201240' data-show-panel='supplierExportFormatXSLT'>v.201240 XML w/XSLT- valid until: 2015-10-15</option> @@ -788,9 +751,6 @@ <h2>Setup: Automatic Ordering</h2> <label><input type='checkbox' class='applyAnycb' name='notes' data-bind="var: supplier(%ORDER.notes); format:popVal;" />Include order notes</label> <label><input type='checkbox' class='applyAnycb' name='field_cost' data-bind="var: supplier(%ORDER.field_cost); format:popVal;" />Show cost field</label> <label><input type='checkbox' class='applyAnycb' name='dont_show_zezro_qtys' data-bind="var: supplier(%ORDER.notes); format:popVal;" />Hide zero quantity items</label> -<!-- -* 201338 -> not supported as of 201338 - <label><input type='checkbox' class='applyAnycb' name='dispatch_on_create' data-bind="var: supplier(%ORDER.dispatch_on_create); format:popVal;" />Dispatch on create (off recommended)</label>--> <label><input type='checkbox' class='applyAnycb' name='dispatch_full_order' data-bind="var: supplier(%ORDER.dispatch_full_order); format:popVal;" />Transmit full order contents (off recommended)</label> @@ -924,7 +884,7 @@ <h2>Setup: Tracking/Confirmation</h2> </label> <label> <span>Warehouse Code:</span> - <input type="text" value="" name="GEO" size="3" maxlength="3" data-minlength='3' data-app-event='admin|alphaNumeric' data-bind='var:warehouse(GEO); format:popVal;' /> + <input type="text" value="" name="GEO" size="3" maxlength="3" data-minlength='3' data-input-keyup='input-format' data-input-format="alphanumeric,uppercase" data-bind='var:warehouse(GEO); format:popVal;' /> <span class='toolTip' title="A 3 digit code consisting of letters A-Z and 0-9. Warehouse code will usually be the three digit code for the nearest airport.">?</span> </label> @@ -945,13 +905,13 @@ <h2>Setup: Tracking/Confirmation</h2> <label> <span>Shipping Latency (in Days):</span> - <input type="number" value="" name="SHIPPING_LATENCY_IN_DAYS" maxlength="2" size="2" min='0' step='1' data-bind='var:warehouse(SHIPPING_LATENCY_IN_DAYS); format:popVal;' /> + <input type='number' class='smallInput' value="" name="SHIPPING_LATENCY_IN_DAYS" maxlength="2" size="2" min='0' step='1' data-bind='var:warehouse(SHIPPING_LATENCY_IN_DAYS); format:popVal;' /> <span class='toolTip' title="The maximum number of days before an order is processed.">?</span> </label> <label> <span>Shipping Cutoff Hour:</span> - <input type="number" value="" name="SHIPPING_CUTOFF_HOUR_PST" maxlength="2" size="2" min='0' step='1' max="24" data-bind='var:warehouse(SHIPPING_CUTOFF_HOUR_PST); format:popVal;' /> + <input type='number' class='smallInput' value="" name="SHIPPING_CUTOFF_HOUR_PST" maxlength="2" size="2" min='0' step='1' max="24" data-bind='var:warehouse(SHIPPING_CUTOFF_HOUR_PST); format:popVal;' /> <span class='toolTip' title="Use 24 hour format, PST time zone (ex: '16' is 4:00pm PST).">?</span> </label> @@ -959,18 +919,17 @@ <h2>Setup: Tracking/Confirmation</h2> <div class='buttonset '> - <button data-app-event='admin_wholesale|warehouseZoneCreateShow' class='hideForCreate'>Add New Zone</button><!-- hidden in 'create' mode --> - <button class='floatRight' data-app-event="admin|processForm">Save</button> + <button data-app-click='admin_wholesale|warehouseZoneCreateShow' class='hideForCreate applyButton' data-text='true' data-icon-primary='ui-icon-plus'>Add New Zone</button><!-- hidden in 'create' mode --> + <button class='floatRight applyButton' data-app-click="admin|submitForm">Save</button> </div> </form> </div> - <div id='warehouseZoneStandardTemplate'> -<form action='#' onSubmit='return false'> +<form action='#' onSubmit='return false' data-table-role='container'> <input type='hidden' name='_macrobuilder' value='admin_wholesale|ZONE-POSITIONS' /> <input type='hidden' name='_tag/restoreInputsFromTrackingState' value='true' /> <input type='hidden' name='_tag/removeFromDOMItemsTaggedForDelete' value='true' /> @@ -981,7 +940,7 @@ <h2>Setup: Tracking/Confirmation</h2> <fieldset class='clearfix'> <div class='twoColumn'> - <table data-app-role='dataTable' data-table='ZONE_STANDARD' class='gridTable fullWidth'> + <table data-app-role='dataTable' data-table='ZONE_STANDARD' class='gridTable fullWidth applyAnytable'> <thead> <tr> <th>Row</th> @@ -992,22 +951,22 @@ <h2>Setup: Tracking/Confirmation</h2> <th></th> </tr> </thead> - <tbody data-bind="var: shipment(@POSITIONS); format:processList; loadsTemplate:zonePositionRowTemplate_STANDARD;"></tbody> + <tbody data-table-role='content' data-bind="var: shipment(@POSITIONS); format:processList; loadsTemplate:zonePositionRowTemplate_STANDARD;"></tbody> </table> </div> - <div class='twoColumn column2 labelsAsBreaks alignedLabels'> + <div class='twoColumn column2 labelsAsBreaks alignedLabels' data-table-role='inputs'> <input type='hidden' name='uuid' value='' /><!-- if an editor is introduced, populate this field w/ the rest of the form --> - <label><span>Row</span><input type='number' name='row' value='' size='5' data-bind="var: location(row); format:popVal;" class='skipTrack' /></label> - <label><span>Shelf begin</span><input type='text' name='shelf' value='' size='5' data-bind="var: location(shelf); format:popVal;" class='skipTrack' /></label> - <label><span>Shelf end</span><input type='text' name='shelf_end' value='' size='5' data-bind="var: location(shelf_end); format:popVal;" class='skipTrack' /></label> - <label><span>Slot begin</span><input type='text' name='slot' value='' size='5' data-bind="var: location(slot); format:popVal;" class='skipTrack' /></label> - <label><span>Slot end</span><input type='text' name='slot_end' value='' size='5' data-bind="var: location(slot_end); format:popVal;" class='skipTrack' /></label> - <button data-app-event="admin_config|dataTableAddExec">Apply Position</button> + <label><span>Row</span><input type='number' name='row' value='' size='5' data-bind="var: location(row); format:popVal;" class='skipTrack smallInput' /></label> + <label><span>Shelf begin</span><input type='text' name='shelf' value='' size='5' data-bind="var: location(shelf); format:popVal;" class='skipTrack smallInput' /></label> + <label><span>Shelf end</span><input type='text' name='shelf_end' value='' size='5' data-bind="var: location(shelf_end); format:popVal;" class='skipTrack smallInput' /></label> + <label><span>Slot begin</span><input type='text' name='slot' value='' size='5' data-bind="var: location(slot); format:popVal;" class='skipTrack smallInput' /></label> + <label><span>Slot end</span><input type='text' name='slot_end' value='' size='5' data-bind="var: location(slot_end); format:popVal;" class='skipTrack smallInput' /></label> + <button data-app-click='admin_config|dataTableAddUpdate' class='applyButton' data-icon-primary='ui-icon-plus'>Apply</button> </div> </fieldset> -<button data-app-event='admin|processForm'>Save Changes</button> +<button data-app-click='admin|submitForm' class='applyButton'>Save Changes</button> </form> @@ -1026,7 +985,7 @@ <h2>Setup: Tracking/Confirmation</h2> <td data-bind="var: location(shelf_end); format:text;"></td> <td data-bind="var: location(slot); format:text;"></td> <td data-bind="var: location(slot_end); format:text;"></td> - <td><button data-app-event="admin|tagRowForRemove">Delete Zone</button></td> + <td><button data-app-click="admin|tagRow4Remove" class='applyButton' data-text='false' data-icon-primary='ui-icon-close'>Delete Zone</button></td> </tr> @@ -1040,8 +999,8 @@ <h2>Setup: Tracking/Confirmation</h2> <td data-bind="var: warehouse(ZONE_PREFERENCE); format:text;"></td> <td data-bind="var: warehouse(@POSITIONS.length); format:text;"></td> <td class='alignRight'> -<button data-app-event="admin_wholesale|warehouseRemoveConfirm">Remove</button> -<button data-app-event="admin_wholesale|warehouseDetailDMIPanel">Edit</button> +<button data-app-click="admin_wholesale|warehouseRemoveConfirm" class='applyButton' data-text='false' data-icon-primary='ui-icon-trash'>Remove</button> +<button data-app-click="admin_wholesale|warehouseDetailDMIPanel" class='applyButton' data-text='false' data-icon-primary='ui-icon-pencil'>Edit</button> </td> </tr> @@ -1050,7 +1009,7 @@ <h2>Setup: Tracking/Confirmation</h2> <td data-bind="var: location(ZONE); format:text;"></td> <td data-bind="var: location(ZONE_TITLE); format:text;" /></td> <td data-bind="var: location(ZONE_TYPE); format:text;" /></td> - <td><button data-app-event="admin|tagRowForRemove">Delete Zone</button></td> + <td><button data-app-click="admin|tagRow4Remove" class='applyButton' data-text='false' data-icon-primary='ui-icon-close'>Delete Zone</button></td> </tr> @@ -1097,14 +1056,14 @@ <h1>Add a New Warehouse Location</h1> </label> <label> <span>Zone preference</span> - <input type="number" step='1' min='0' size="3" maxlength="3" name="ZONE_PREFERENCE" value="" /> + <input type='number' class='smallInput' step='1' min='0' size="3" maxlength="3" name="ZONE_PREFERENCE" value="" /> <span class='toolTip' title="Zones with a higher preference are picked from first.">?</span> </label> </fieldset> <div class='buttonset'> - <button data-app-event='admin|processForm'>Save Location</button> + <button data-app-click='admin|submitForm' class='applyButton'>Save Location</button> </div> </form> @@ -1131,10 +1090,10 @@ <h1>Add a New Warehouse Location</h1> <td data-bind="var: schedule(currency); format:text;"></td> <td data-bind="var: schedule(discount_amount); format:text;"></td> <td class='alignRight'> -<button data-app-event="admin_wholesale|priceScheduleRemoveConfirm">Remove Schedule</button> -<button data-app-event="admin_customer|adminCustomerSearchShowUI" data-scope='SCHEDULE' data-bind='var:schedule(SID);format:assignAttribute; attribute:data-searchfor;'>Customers</button> -<button data-app-event="admin_wholesale|adminOrganizationSearchShowUI" data-searchby='SCHEDULE' data-bind='var:schedule(SID);format:assignAttribute; attribute:data-keywords;'>Organizations</button> -<button data-app-event="admin_wholesale|priceScheduleUpdateShow">Edit Schedule</button> +<button data-app-click="admin_wholesale|priceScheduleRemoveConfirm" class='applyButton' data-text='false' data-icon-primary='ui-icon-trash'>Remove Schedule</button> +<button data-app-click="admin_customer|adminCustomerSearchShowUI" class='applyButton' data-text='false' data-icon-primary='ui-icon-person' data-scope='SCHEDULE' data-bind='var:schedule(SID);format:assignAttribute; attribute:data-searchfor;'>Customers</button> +<button data-app-click="admin_wholesale|adminOrganizationSearchShowUI" class='applyButton' data-text='false' data-icon-primary='ui-icon-contact' data-searchby='SCHEDULE' data-bind='var:schedule(SID);format:assignAttribute; attribute:data-keywords;'>Organizations</button> +<button data-app-click="admin_wholesale|priceScheduleUpdateShow" class='applyButton' data-text='false' data-icon-primary='ui-icon-pencil'>Edit Schedule</button> </td> </tr> @@ -1168,47 +1127,38 @@ <h1>Add a New Warehouse Location</h1> </fieldset> <fieldset class='marginBottom'> - <legend>Price</legend> - <p class='hint'> - You will have the opportunity to enter a unique price and/or discount for each product that will affect the base price (but not options) - if you leave this field blank then the base price will be used. - </p> - - <label>DEFAULT PRICING FORMULA</label> + <legend>Price <span class='toolTip' title="You will have the opportunity to enter a unique price and/or discount for each product that will affect the base price (but not options) - if you leave this field blank then the base price will be used.">?</span></legend> + <label>Default Pricing Formula</label> <!-- -<input type="checkbox" name="chk_discount_default"> Default Pricing Formula: <input type="text" name="discount_amount" value="" size="20"> (only used if no unique formula is set)<br> +<input type="checkbox" name="discount_default"> Default Pricing Formula: <input type="text" name="discount_amount" value="" size="20"> (only used if no unique formula is set)<br> <font color="red">Warning: Without a default pricing formula, the price of each item must be set individually. HINT: You probably don't want to do this. Try using "BASE"</font><br> --> <label> - <input type="checkbox" name="chk_incomplete" data-bind="var: schedule(chk_incomplete); format:popVal; hideZero:false; defaultVal: 1;" /> + <input type="checkbox" name="incomplete" data-bind="var: schedule(incomplete); format:popVal; hideZero:false; defaultVal: 1;" /> Ignore/Disable Special pricing for incomplete items. </label> <label> - <input type="checkbox" name="chk_rewards" data-bind="var: schedule(chk_rewards); format:popVal;" /> Allow participation in rewards program. + <input type="checkbox" name="rewards" data-bind="var: schedule(rewards); format:popVal;" /> Allow participation in rewards program. </label> </fieldset> <fieldset class='marginBottom'> - <legend>Promotions</legend> - + <legend>Promotions <span class='toolTip' title="Promotions can selectively have different behaviors per schedule, based on the the rules logic within them. Promotions and Coupons are DIFFERENT merchandising strategies. If you do not want a coupon to be enabled for one or more wholesale schedules you must Disable each coupon individually.">?</span></legend> <div class='label'><input type="radio" value="1" name="promotion_mode" data-bind="var: schedule(promotion_mode); format:popVal; hideZero:false; defaultVal: 1;" /> Use default store promotions. (RECOMMENDED)</div> <div class='label'><input type="radio" value="0" name="promotion_mode" data-bind="var: schedule(promotion_mode); format:popVal;" /> Disable Promotions</div> - <p class='hint'> -Promotions can selectively have different behaviors per schedule, based on the the rules logic within them.<br /> -Promotions and Coupons are DIFFERENT merchandising strategies. If you do not want a coupon to be enabled for one or more wholesale schedules you must Disable each coupon individually. - </p> </fieldset> <fieldset class='marginBottom'> - <legend>Shipping</legend> + <legend>Shipping <span class='toolTip' title='You can configure shipping rules so they only apply to certain schedules.'>?</span></legend> <div class='label'><input type="radio" value="1" name="shiprule_mode" data-bind="var: schedule(shiprule_mode); format:popVal; hideZero:false; defaultVal: 1;" /> Apply rules based on how they are configured. (RECOMMENDED)</div> <div class='label'><input type="radio" value="0" name="shiprule_mode" data-bind="var: schedule(shiprule_mode); format:popVal;" /> Disable/Skip all shipping rules.</div> - <p class='hint'>You can configure shipping rules so they only apply to certain schedules.</p> + </fieldset> @@ -1216,12 +1166,12 @@ <h1>Add a New Warehouse Location</h1> <fieldset class='marginBottom'> <legend>Customer Access</legend> -<label><input type="checkbox" name="chk_realtime_orders" data-bind="var: schedule(chk_realtime_orders); format:popVal; hideZero:false; defaultVal: 1;" /> Accept EDI/XML Orders from customers.</label> -<label><input type="checkbox" name="chk_realtime_products" data-bind="var: schedule(chk_realtime_products); format:popVal; hideZero:false; defaultVal: 1;" /> Give customers EDI/XML product download access.</label> -<label><input type="checkbox" name="chk_realtime_inventory" data-bind="var: schedule(chk_realtime_inventory); format:popVal; hideZero:false; defaultVal: 1;" /> Give customers EDI/XML inventory download access.</label> -<label><input type="checkbox" name="chk_dropship_invoice" data-bind="var: schedule(chk_dropship_invoice); format:popVal; hideZero:false; defaultVal: 1;" /> Allow customers to provide their own packing slip/invoice and logo information for dropship orders.</label> -<label><input type="checkbox" name="chk_export_inventory" data-bind="var: schedule(chk_export_inventory); format:popVal; hideZero:false; defaultVal: 1;" /> Allow customers to export/print out a complete inventory list.</label> -<label><input type="checkbox" name="chk_inventory_ignore" data-bind="var: schedule(chk_inventory_ignore); format:popVal;" /> Ignore Inventory: Allow customers to purchase unlimited quantities.</label> +<label><input type="checkbox" name="realtime_orders" data-bind="var: schedule(realtime_orders); format:popVal; hideZero:false; defaultVal: 1;" /> Accept EDI/XML Orders from customers.</label> +<label><input type="checkbox" name="realtime_products" data-bind="var: schedule(realtime_products); format:popVal; hideZero:false; defaultVal: 1;" /> Give customers EDI/XML product download access.</label> +<label><input type="checkbox" name="realtime_inventory" data-bind="var: schedule(realtime_inventory); format:popVal; hideZero:false; defaultVal: 1;" /> Give customers EDI/XML inventory download access.</label> +<label><input type="checkbox" name="dropship_invoice" data-bind="var: schedule(dropship_invoice); format:popVal; hideZero:false; defaultVal: 1;" /> Allow customers to provide their own packing slip/invoice and logo information for dropship orders.</label> +<label><input type="checkbox" name="export_inventory" data-bind="var: schedule(export_inventory); format:popVal; hideZero:false; defaultVal: 1;" /> Allow customers to export/print out a complete inventory list.</label> +<label><input type="checkbox" name="inventory_ignore" data-bind="var: schedule(inventory_ignore); format:popVal;" /> Ignore Inventory: Allow customers to purchase unlimited quantities.</label> </fieldset> @@ -1231,14 +1181,14 @@ <h1>Add a New Warehouse Location</h1> <legend>Internationalization</legend> <label> - <span>Currency</span> + <span>Currency <span class='toolTip' title="This feature allows you to specify an alternate price list in another currency. Not compatible with pricing formulas, fixed price promotions, or option based price modifiers. We recommend naming these schedules CXXX where XXX is the currency code. for example CEUR (currency euro) or CCAD (currency canadian dollars). +">?</span></span> <select name="currency"> <option value="">-</option> <option value="USD">USD: US Dollars</option> <option value="EUR">EUR: Euro</option> </select> - <span class='toolTip' title="This feature allows you to specify an alternate price list in another currency. Not compatible with pricing formulas, fixed price promotions, or option based price modifiers. We recommend naming these schedules CXXX where XXX is the currency code. for example CEUR (currency euro) or CCAD (currency canadian dollars). -">?</span> + </label> </fieldset> @@ -1252,7 +1202,7 @@ <h1>Add a New Warehouse Location</h1> - <button data-app-event='admin|processForm'>Save</button> + <button data-app-click='admin|submitForm' data-text='false' class='applyButton'>Save</button> </form> </div> @@ -1418,7 +1368,7 @@ <h1>Add Inventory to Location by SKU</h1> <td>Zone*Position</td> <td><input type='text' name='LOC' value='' size='25' required='required' /></td> <td>Qty</td> - <td>+<input type='number' min='0' step='1' name='QTY' value='' size='25' required='required' /></td> + <td>+<input type='number' min='0' step='1' name='QTY' value='' size='10' required='required' /></td> <td><button class='applyButton' data-app-click="admin_wholesale|whimSetSKULocation">Set as a Location</button></td> </tr> diff --git a/extensions/admin/wholesale.js b/extensions/admin/wholesale.js index 44638c0d0..2e1049fe9 100644 --- a/extensions/admin/wholesale.js +++ b/extensions/admin/wholesale.js @@ -19,9 +19,9 @@ -var admin_wholesale = function() { +var admin_wholesale = function(_app) { var theseTemplates = new Array( - 'organizationManagerPageTemplate', + 'orgManagerControls', //needs to be defined for orgManager DMI 'organizationManagerOrgCreateUpdateTemplate', 'organizationManagerOrgRowTemplate' /* @@ -45,7 +45,7 @@ var admin_wholesale = function() { init : { onSuccess : function() { var r = true; //return false if extension won't load for some reason (account config, dependencies, etc). - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/wholesale.html',theseTemplates); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/admin/wholesale.html',theseTemplates); var $wm = $("<div \/>",{'id':'wholesaleModal'}).appendTo('body'); //a recycleable element for modals. $wm.dialog({'autoOpen':false,'modal':true,'width':500,'height':500}); @@ -54,24 +54,25 @@ var admin_wholesale = function() { onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_wholesale.callbacks.init.onError'); + _app.u.dump('BEGIN admin_wholesale.callbacks.init.onError'); } }, //INIT - +//used for WHIM wholesaleSearchResults: { onSuccess : function(_rtag) { if(_rtag.jqObj) { - if(_rtag.datapointer && app.data[_rtag.datapointer]) { - if(app.data[_rtag.datapointer]['@ROWS'].length) { + if(_rtag.datapointer && _app.data[_rtag.datapointer]) { + if(_app.data[_rtag.datapointer]['@ROWS'].length) { _rtag.jqObj.anycontent(_rtag); + _app.u.handleButtons(_rtag.jqObj); } else { $('#globalMessaging').anymessage({"message":"There were zero items returns in your search of warehouse "+_rtag.jqObj.closest("[data-app-role='slimLeftContainer']").data("geo")+"."}); } } else { - $('#globalMessaging').anymessage({"message":"In admin_wholesale.callbacks.wholesaleSearchResults, either _rtag.datapointer ["+_rtag.datapointer+"] is empty or app.data[rd.datapointer] [typeof: "+typeof app.data[rd.datapointer]+"] is empty.","gMessage":true}); + $('#globalMessaging').anymessage({"message":"In admin_wholesale.callbacks.wholesaleSearchResults, either _rtag.datapointer ["+_rtag.datapointer+"] is empty or _app.data[rd.datapointer] [typeof: "+typeof _app.data[rd.datapointer]+"] is empty.","gMessage":true}); } } else { @@ -88,15 +89,13 @@ var admin_wholesale = function() { a : { showWarehouseManager : function($target) { - $target.empty(); - - app.ext.admin.i.DMICreate($target,{ + _app.ext.admin.i.DMICreate($target,{ 'header' : 'Warehouse Manager', 'className' : 'warehouseManager', //add button doesn't use admin|createDialog because extra inputs are needed for cmd/tag and the template is shared w/ update. 'buttons' : [ - "<button data-app-event='admin|refreshDMI'>Refresh Coupon List<\/button>", - "<button data-app-event='admin_wholesale|warehouseCreateShow' data-title='Create a New Warehouse'>Add Warehouse</button>" + "<button data-app-click='admin|refreshDMI' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowrefresh-1-s'>Refresh<\/button>", + "<button data-app-click='admin_wholesale|warehouseCreateShow' data-title='Create a New Warehouse' class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-plus'>Add Warehouse</button>" ], 'thead' : ['Code','Zone','Title','Zone Type','Preference','# Positions',''], 'tbodyDatabind' : "var: users(@ROWS); format:processList; loadsTemplate:warehouseResultsRowTemplate;", @@ -108,52 +107,53 @@ var admin_wholesale = function() { } } }); - app.model.dispatchThis('mutable'); + _app.u.handleButtons($target.anyform()); + _app.model.dispatchThis('mutable'); }, //showWarehouseManager showWarehouseUtilities : function($target){ $target.intervaledEmpty(); $target.anycontent({'templateID':'whimInterfaceTemplate','data':{}}); - $target.showLoading({'message':'Fetching list of warehouses'}) - app.model.addDispatchToQ({ + $target.showLoading({'message':'Fetching list of warehouses'}); + _app.model.addDispatchToQ({ '_cmd' : 'adminWarehouseList', '_tag' : { 'datapointer':'adminWarehouseList', 'callback': function(rd) { -if(app.model.responseHasErrors(rd)){ - $target.anymessage({'message':rd}); - } -else { - $target.anycontent(rd); - var whim = app.model.dpsGet('admin_wholesale','whim') || {}; -// app.u.dump(" -> dps.whim: "); app.u.dump(whim); - if(whim.geo) { - $("[data-geo='666']",$target).trigger('click',{'skipDPSUpdate':true}) - } - } + if(_app.model.responseHasErrors(rd)){ + $target.anymessage({'message':rd}); + } + else { + $target.anycontent(rd); + var whim = _app.model.dpsGet('admin_wholesale','whim') || {}; + // _app.u.dump(" -> dps.whim: "); _app.u.dump(whim); + if(whim.geo) { + $("[data-geo='666']",$target).trigger('click',{'skipDPSUpdate':true}) + } + } }, 'translateOnly' : true, 'jqObj' : $target } },'mutable'); - app.model.dispatchThis('mutable'); + _app.model.dispatchThis('mutable'); $("[data-app-role='slimLeftNav']",$target).accordion(); //target is likely a tab and I don't want to delegate to a tab at this time. - app.u.handleEventDelegation($("[data-app-role='slimLeftNav']",$target)); - app.u.handleEventDelegation($("[data-app-role='slimLeftContentSection']",$target)); + _app.u.addEventDelegation($("[data-app-role='slimLeftNav']",$target).anyform()); + _app.u.addEventDelegation($("[data-app-role='slimLeftContentSection']",$target).anyform()); }, showPriceSchedules : function($target) { $target.empty(); - app.ext.admin.i.DMICreate($target,{ + _app.ext.admin.i.DMICreate($target,{ 'header' : 'Price Schedules', 'className' : 'priceSchedules', //add button doesn't use admin|createDialog because extra inputs are needed for cmd/tag and the template is shared w/ update. 'buttons' : [ - "<button data-app-event='admin|refreshDMI'>Refresh Coupon List<\/button>", - "<button data-app-event='admin_wholesale|priceScheduleCreateShow' data-title='Create a New Price Schedule'>Add New Schedule</button>" + "<button data-app-click='admin|refreshDMI' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowrefresh-1-s'>Refresh<\/button>", + "<button data-app-click='admin_wholesale|priceScheduleCreateShow' data-title='Create a New Price Schedule' class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-plus'>Add New Schedule</button>" ], 'thead' : ['ID','Name','Currency','Discount',''], 'tbodyDatabind' : "var: users(@SCHEDULES); format:processList; loadsTemplate:priceScheduleResultsRowTemplate;", @@ -164,53 +164,59 @@ else { } } }); - app.model.dispatchThis('mutable'); + _app.u.handleButtons($target.anyform()); + _app.model.dispatchThis('mutable'); }, showOrganizationManager : function($target,vars) { -// app.u.dump("BEGIN admin_wholesale.a.showOrganizationManager"); - vars = vars || {}; - app.ext.admin.calls.adminPriceScheduleList.init({},'mutable'); //need this for add and edit. - if($target && $target.length) { - $target.empty(); - $target.anycontent({'templateID':'organizationManagerPageTemplate','data':{}}); - app.u.handleAppEvents($target); - if(vars.searchby && vars.keywords) { - $("[name='searchby']",$target).val(vars.searchby); - $("[name='keywords']",$target).val(vars.keywords); - $("[data-app-event='admin_wholesale|execOrganizationSearch']",$target).trigger('click'); +// _app.u.dump("BEGIN admin_wholesale.a.showOrganizationManager"); + _app.ext.admin.calls.adminPriceScheduleList.init({},'mutable'); //need this for add and edit. + dump(" -> vars: "); dump(vars); + var $DMI = _app.ext.admin.i.DMICreate($target,{ + 'header' : 'Organization Manager', + 'handleAppEvents' : false, + 'className' : 'organizationManager', //applies a class on the DMI, which allows for css overriding for specific use cases. + 'thead' : ['','ID','Company','Domain','Email','Account Manager','Billing Phone','Billing Contact',''], //leave blank at end if last row is buttons. + 'tbodyDatabind' : "var: tickets(@ORGANIZATIONS); format:processList; loadsTemplate:organizationManagerOrgRowTemplate;", + 'buttons' : [ + "<button data-app-click='admin|refreshDMI' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowrefresh-1-s'>Refresh<\/button>", + "<button data-app-click='admin_wholesale|showOrganizationCreate' class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-plus'>Add Organization</button>"], + 'controls' : _app.templates.orgManagerControls, + data : vars, + 'cmdVars' : { + '_cmd' : 'adminCustomerOrganizationSearch', + searchby : vars.searchby, + keywords : vars.keywords, + 'PHONE' : '', //update by changing $([data-app-role="dualModeContainer"]).data('cmdVars').STATUS + 'limit' : '50', //not supported for every call yet. + '_tag' : { + 'datapointer':'adminCustomerOrganizationSearch' + } } - } - else { - $('#globalMessaging').anymessage({'message':'In admin_wholesale.a.showOrganizationManager, $target either not specified or has not length.','gMessage':true}); - } - + }); + _app.u.handleButtons($target.anyform()); + // do not fetch templates at this point. That's a heavy call and they may not be used. + _app.model.dispatchThis(); }, //showOrganizationManager showOrganizationEditor : function($target,vars) { - app.u.dump("BEGIN admin_wholesale.a.showOrganizationEditor"); + _app.u.dump("BEGIN admin_wholesale.a.showOrganizationEditor"); if($target && vars && vars.orgID) { - $target.empty(); - $target.showLoading({'message':'Fetching Data for Organization '+vars.orgID}); - app.ext.admin.calls.adminPriceScheduleList.init({},'mutable'); - app.ext.admin.calls.adminCustomerOrganizationDetail.init(vars.orgID,{'callback':function(rd){ - $target.hideLoading(); - if(app.model.responseHasErrors(rd)){$target.anymessage({'message':rd})} - else { - $target.anycontent({'templateID':'organizationManagerOrgCreateUpdateTemplate',datapointer:rd.datapointer}); - $('form',$target).data('orgid',vars.orgID); - $("input",$target).each(function(){ - var $input = $(this); - $input.attr('title',$input.attr('placeholder')); //add the placeholder of the input as the title so mouseover is indicative of what the field wants. - if($input.is(':checkbox')) { - $input.anycb(); - } - }); - $('.buttonset',$target).append("<button data-app-event='admin_wholesale|execOrganizationUpdate' data-app-role='saveButton'>Save Changes</button>"); - app.u.handleAppEvents($target); - } + + $target.anycontent({'templateID':'organizationManagerOrgCreateUpdateTemplate'}).anyform({'trackEdits':true}); //.showLoading({'message':'Fetching Data for Organization '+vars.orgID}); + _app.u.addEventDelegation($target); + $('.buttonset',$target).append("<button data-app-click='admin_wholesale|adminCustomerOrganizationUpdateExec' disabled='disabled' class='applyButton' data-app-role='saveButton'>Save <span class='numChanges'></span> Changes</button>"); + $('form',$target).append("<input type='hidden' name='ORGID' value='"+vars.orgID+"' />"); + _app.u.handleButtons($target); + _app.u.handleCommonPlugins($target); + _app.ext.admin.calls.adminPriceScheduleList.init({},'mutable'); + _app.model.addDispatchToQ({'_cmd':'adminCustomerOrganizationDetail','ORGID' : vars.orgID,'_tag': { + 'datapointer' : 'adminCustomerOrganizationDetail|'+vars.orgID, + 'callback': 'anycontent', + 'translateOnly' : true, + 'jqObj' : $target }},'mutable'); - app.model.dispatchThis('mutable'); + _app.model.dispatchThis('mutable'); } else { $('#globalMessaging').anymessage({'message':'In admin_wholesale.e.showOrganizationUpdate, unable to determine orgID.','gMessage':true}); @@ -219,17 +225,19 @@ else { //smTarget (supply manager target) is the jquery object of where it should be placed, ususally a tab. showSupplierManager : function($target) { - app.ext.admin.calls.adminPriceScheduleList.init({},'mutable'); //need this for create and update. - app.ext.admin.i.DMICreate($target,{ + _app.ext.admin.calls.adminPriceScheduleList.init({},'mutable'); //need this for create and update. + var $DMI = _app.ext.admin.i.DMICreate($target,{ 'header' : 'Supplier Manager', 'className' : 'supplierManager', + 'handleAppEvents' : false, //add button doesn't use admin|createDialog because extra inputs are needed for cmd/tag and the template is shared w/ update. 'buttons' : [ - "<button data-app-event='admin|refreshDMI'>Refresh Supplier List<\/button>", - "<button class='marginLeft' data-app-event='admin_wholesale|adminSupplierUnorderedItemListShow' data-mode='all'>Unordered Items</button>", - "<button class='marginLeft' data-app-event='admin_wholesale|adminSupplierCreateShow'>Add Supplier</button>" + "<button data-app-click='admin|refreshDMI' class='applyButton' data-text='false' data-icon-primary='ui-icon-arrowrefresh-1-s'>Refresh<\/button>", + "<button data-app-click='admin_wholesale|adminSupplierUnorderedItemListShow' data-mode='all' class='applyButton' data-text='true'>Unordered Items</button>", + "<button data-app-click='admin_wholesale|adminSupplierCreateShow' class='applyButton' data-text='true' data-icon-primary='ui-icon-circle-plus'>Add Supplier</button>" ], - 'thead' : ['Name','ID','Type','Mode',''], + 'thead' : ['','Name','ID','Type',''], + 'controls' : "<button data-app-click='admin|checkAllCheckboxesExec' class='applyButton marginRight'>Select All<\/button><span class='applyButtonset smallButton'>Modify Selected: <button data-app-click='admin_wholesale|supplierBatchExec' data-verb='INVENTORY'>Get Inventory</button><button data-app-click='admin_wholesale|supplierBatchExec' data-verb='PROCESS' title='Will cause any pending orders to be set to a supplier'>Process Orders</button><button data-app-click='admin_wholesale|supplierBatchExec' data-verb='TRACKING'>Update Tracking</button><\/span>", 'tbodyDatabind' : "var: users(@SUPPLIERS); format:processList; loadsTemplate:supplierListItemTemplate;", 'cmdVars' : { '_cmd' : 'adminSupplierList', @@ -238,45 +246,53 @@ else { } } }); - app.model.dispatchThis('mutable'); + _app.u.handleButtons($target.anyform()); + + _app.model.dispatchThis('mutable'); }, //showSupplierManager showSupplierEditor : function($editorContainer,VENDORID) { + _app.u.dump("BEGIN admin_wholesale.a.showSupplierEditor"); if($editorContainer instanceof jQuery && VENDORID) { + $editorContainer.showLoading({"message":"Fetching supplier details"}); - app.model.addDispatchToQ({ + + _app.model.addDispatchToQ({ '_cmd':'adminSupplierDetail', 'VENDORID' : VENDORID, '_tag': { 'datapointer' : 'adminSupplierDetail|'+VENDORID, 'callback':function(rd) { $editorContainer.hideLoading(); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $editorContainer.anymessage({'message':rd}) } else { $editorContainer.anycontent({'templateID':'supplierUpdateTemplate','datapointer':rd.datapointer,'showLoading':false,'dataAttribs':{'vendorid':VENDORID}}); - app.ext.admin.u.handleAppEvents($editorContainer); - $(".applyAnycb",$editorContainer).parent().anycb(); //anycb gets executed on the labels, not the checkbox. + _app.u.handleButtons($editorContainer); + _app.u.addEventDelegation($editorContainer); + $editorContainer.anyform({'trackEdits':true}); //for FBA, most panel inputs get 'locked' - if(app.data[rd.datapointer].FORMAT == 'FBA' || app.data[rd.datapointer].CODE == 'FBA') { + if(_app.data[rd.datapointer].FORMAT == 'FBA' || _app.data[rd.datapointer].CODE == 'FBA') { $(".panel[data-panel-id='supplierOurFBAConfig']",$editorContainer).show() $('.panel',$editorContainer).not("[data-panel-id='supplierOurFBAConfig']").find(":input").attr('disabled','disabled'); $("select[name='FORMAT']",$editorContainer).val('FBA'); - $("input[name='PREFERENCE']",$editorContainer).prop('disabled','').removeAttr('disabled'); + $('select[name="INVENTORY_CONNECTOR"]',$editorContainer).prop('disabled','').removeProp('disabled').find("option[value='GENERIC']").hide(); + + $("input[name='PREFERENCE']",$editorContainer).prop('disabled','').removeProp('disabled'); //to compensate for a bug where FORMAT was getting dropped. //if code is FBA, force format to FBA. this is a reserved name (user formats are more characters). - if(!app.data[rd.datapointer].FORMAT) { + if(!_app.data[rd.datapointer].FORMAT) { $("select[name='FORMAT']",$editorContainer).val('FBA').addClass('edited'); } } //format can not change once set. - else if(app.data[rd.datapointer].FORMAT) { + else if(_app.data[rd.datapointer].FORMAT) { $("select[name='FORMAT']",$editorContainer).prop('disabled','disabled'); } //disallow FBA except for the reserved code. - else if(app.data[rd.datapointer].CODE != 'FBA') { + else if(_app.data[rd.datapointer].CODE != 'FBA') { $("select[name='FORMAT'] option[value='FBA']",$editorContainer).prop('disabled','disabled'); } else {} @@ -288,11 +304,9 @@ else { }); //### the panels are sortable, BUT this code doesn't allow for persistance. address when time permits. - //make inputs 'know' when they've been added and update the button. - app.ext.admin.u.applyEditTrackingToInputs($editorContainer); - - - + //run after the FBA code so that if the cb's are disabled, the aesthetic is right. + _app.u.handleCommonPlugins($editorContainer); + //make panels draggable var sortCols = $('.twoColumn').sortable({ connectWith: '.twoColumn', @@ -309,20 +323,17 @@ else { var $col = $(this); dataObj.push($col.sortable( "toArray",{'attribute':'data-app-role'} )); }); - app.model.dpsSet('admin_wholesale','editorPanelOrder',dataObj); //update the localStorage session var. - // app.u.dump(' -> dataObj: '); app.u.dump(dataObj); + _app.model.dpsSet('admin_wholesale','editorPanelOrder',dataObj); //update the localStorage session var. + // _app.u.dump(' -> dataObj: '); _app.u.dump(dataObj); } }); - - - app.ext.admin.u.handleFormConditionalDelegation($('form',$editorContainer)); } } } },'mutable'); - app.model.dispatchThis('mutable'); + _app.model.dispatchThis('mutable'); } else { $("#globalMessaging").anymessage({'message':'In admin_wholesale.a.showSupplierEditor, either $editorContainer ['+typeof $editorContainer+'] or VENDORID ['+VENDORID+'] undefined','gMessage':true}); @@ -335,15 +346,16 @@ else { renderFormats : { wholesaleScheduleSelect : function($tag,data) { - if(!app.data.adminPriceScheduleList) {$tag.anymessage({'message':'Unable to fetch wholesale list'})} - else if(!app.data.adminPriceScheduleList['@SCHEDULES']) { - $tag.anymessage({'message':'You have not created any schedules yet.'}) + if(!_app.data.adminPriceScheduleList) {$tag.closest('label').anymessage({'message':'Unable to fetch wholesale list'})} + else if(!_app.data.adminPriceScheduleList['@SCHEDULES']) { + $tag.closest('label').anymessage({'message':'You have not created any schedules yet.'}) } - else if(!data.value) {$tag.anymessage({'message':'No data passed into wholesaleScheduleSelect renderFormat'})} +//* 201402 -> if data.value isn't set (ex: a merchant hasn't selected one for the marketplace) then the list wouldn't generate. +// else if(!data.value) {$tag.closest('label').anymessage({'message':'No data passed into wholesaleScheduleSelect renderFormat'})} else { var $select = $("<select \/>",{'name':'SCHEDULE'}), - schedules =app.data.adminPriceScheduleList['@SCHEDULES'], //shortcut - L = app.data.adminPriceScheduleList['@SCHEDULES'].length + schedules =_app.data.adminPriceScheduleList['@SCHEDULES'], //shortcut + L = _app.data.adminPriceScheduleList['@SCHEDULES'].length list = null; $select.append($("<option \/>",{'value':''}).text('none')); for(var i = 0; i < L; i += 1) { @@ -351,13 +363,14 @@ else { } $select.appendTo($tag); - if(data.value.ORG && data.value.ORG.SCHEDULE) {$select.val(data.value.ORG.SCHEDULE)} //preselect schedule, if set. + if(data.value) {$select.val(data.value)} +// if(data.value.ORG && data.value.ORG.SCHEDULE) {$select.val(data.value.ORG.SCHEDULE)} //preselect schedule, if set. } }, //wholesaleScheduleSelect warehouseCodeOrZone : function($tag,data) { -// app.u.dump(data.value); die(); +// _app.u.dump(data.value); if(data.value._OBJECT == 'GEO') { $tag.text(data.value.GEO); } @@ -378,7 +391,7 @@ else { 'WAREHOUSE-CREATE' : function(sfo) { - app.u.dump("BEGIN admin_wholesale.macrobuilders.warehouse-create"); + _app.u.dump("BEGIN admin_wholesale.macrobuilders.warehouse-create"); sfo = sfo || {}; //a new object, which is sanitized and returned. var newSfo = { @@ -390,7 +403,7 @@ else { delete sfo._tag; //removed from original object so serialization into key value pair string doesn't include it. delete sfo._macrobuilder; newSfo['@updates'].push('WAREHOUSE-CREATE?'+$.param(sfo)); // 'code/warehouse' is passed on the outer level. -// app.u.dump(" -> newSfo:"); app.u.dump(newSfo); +// _app.u.dump(" -> newSfo:"); _app.u.dump(newSfo); return newSfo; }, //adminWarehouseMacroCreate @@ -430,21 +443,21 @@ else { //is a new row that is tagged for delete. don't do anything with it. } else if($tr.hasClass('rowTaggedForRemove')) { - newSfo['@updates'].push('ZONE-POSITIONS-DELETE?'+$.param(app.u.getWhitelistedObject($tr.data(),['uuid']))); + newSfo['@updates'].push('ZONE-POSITIONS-DELETE?'+$.param(_app.u.getWhitelistedObject($tr.data(),['uuid']))); } else { - if(!$tr.data('uuid')){$tr.data('uuid',app.u.guidGenerator())} - newSfo['@updates'].push('ZONE-POSITIONS-ADD?'+$.param(app.u.getWhitelistedObject($tr.data(),['row','shelf','shelf_end','slot','slot_end','uuid']))); + if(!$tr.data('uuid')){$tr.data('uuid',_app.u.guidGenerator())} + newSfo['@updates'].push('ZONE-POSITIONS-ADD?'+$.param(_app.u.getWhitelistedObject($tr.data(),['row','shelf','shelf_end','slot','slot_end','uuid']))); } }); -// app.u.dump(" -> newSfo:"); app.u.dump(newSfo); +// _app.u.dump(" -> newSfo:"); _app.u.dump(newSfo); return newSfo; }, 'WAREHOUSE-UPDATE' : function(sfo) { - app.u.dump("BEGIN admin_wholesale.macrobuilders.warehouse-update"); + _app.u.dump("BEGIN admin_wholesale.macrobuilders.warehouse-update"); sfo = sfo || {}; //a new object, which is sanitized and returned. var newSfo = { @@ -456,7 +469,7 @@ else { delete sfo._tag; //removed from original object so serialization into key value pair string doesn't include it. delete sfo._macrobuilder; newSfo['@updates'].push('WAREHOUSE-UPDATE?'+$.param(sfo)); -// app.u.dump(" -> newSfo:"); app.u.dump(newSfo); +// _app.u.dump(" -> newSfo:"); _app.u.dump(newSfo); return newSfo; }, //WAREHOUSE-UPDATE @@ -479,7 +492,8 @@ else { if($('.edited',$fieldset).length) { $('.edited',$fieldset).each(function(){ //connectors are 'set' for macro. all other fields are what's set in cmd array. - newSfo['@updates'].push((($(this).attr('name').indexOf('CONNECTOR') > -1) ? 'SET' : cmds[i])+"?"+$(this).attr('name')+"="+encodeURIComponent($(this).val())); //encodeURIComponent($.param($fieldset.serializeJSON({'cb':true}))) + //SANITY!!! -> MUST pull value from SFO, not from val(), so that checkboxes are saves as 1/0 not on/off. If the line below changes, compensate for that. + newSfo['@updates'].push((($(this).attr('name').indexOf('CONNECTOR') > -1) ? 'SET' : cmds[i])+"?"+$(this).attr('name')+"="+encodeURIComponent(sfo[$(this).attr('name')])); //encodeURIComponent($.param($fieldset.serializeJSON({'cb':true}))) }) } @@ -492,7 +506,7 @@ else { } else {} //no changes. -// app.u.dump(newSfo['@updates']); +// _app.u.dump(newSfo['@updates']); return newSfo } //adminSupplierMacro }, //macroBuilders @@ -501,186 +515,149 @@ else { e : { -//can't use defualt createDialog app event because we need to add a few params to the form. - warehouseCreateShow : function($btn,vars) { - $btn.button(); - $btn.off('click.warehouseCreateShow').on('click.warehouseCreateShow',function(event){ - event.preventDefault(); - var $D = app.ext.admin.i.dialogCreate({ - 'title':'Add New Warehouse', - 'templateID':'warehouseAddUpdateTemplate', - 'showLoading':false //will get passed into anycontent and disable showLoading. - }); - $(".hideForCreate",$D).hide(); - $D.dialog('open'); -//These fields are used for processForm on save. - $('form',$D).first().append("<input type='hidden' name='_macrobuilder' value='admin_wholesale|WAREHOUSE-CREATE' \/><input type='hidden' name='_tag/callback' value='showMessaging' \/><input type='hidden' name='_tag/message' value='The warehouse has been successfully created.' \/><input type='hidden' name='_tag/updateDMIList' value='"+$btn.closest("[data-app-role='dualModeContainer']").attr('id')+"' /><input type='hidden' name='_tag/jqObjEmpty' value='true' \/>"); + warehouseCreateShow : function($ele,P) { + P.preventDefault(); + var $D = _app.ext.admin.i.dialogCreate({ + 'title':'Add New Warehouse', + 'templateID':'warehouseAddUpdateTemplate', + 'showLoading':false //will get passed into anycontent and disable showLoading. }); + $(".hideForCreate",$D).hide(); + _app.u.handleButtons($D); + $D.anyform().dialog('open'); +//These fields are used for processForm on save. + $('form',$D).first().append("<input type='hidden' name='_macrobuilder' value='admin_wholesale|WAREHOUSE-CREATE' \/><input type='hidden' name='_tag/callback' value='showMessaging' \/><input type='hidden' name='_tag/message' value='The warehouse has been successfully created.' \/><input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' /><input type='hidden' name='_tag/jqObjEmpty' value='true' \/>"); }, //warehouseCreateShow + warehouseDetailDMIPanel : function($ele,P) { + P.preventDefault(); + var data = $ele.closest('tr').data(); + + if(data._object == 'GEO' || (data._object == 'ZONE' && (data.zone_type == 'RECEIVING' || data.zone_type == 'UNSTRUCTURED' || data.zone_type == 'STANDARD'))) { +//these are the shared values for the DMI panel. + var panelObj = { + 'handleAppEvents' : false + } - - wholesaleZoneAddRow : function($btn) { - $btn.button({icons: {primary: "ui-icon-plus"},text: true}); - $btn.off('click.wholesaleZoneAddRow').on('click.wholesaleZoneAddRow',function(event){ - event.preventDefault(); - if($btn.data('loadstemplate')) { - var $tr = app.renderFunctions.createTemplateInstance($btn.data('loadstemplate')); - $btn.closest('table').find('tbody:first').append($tr); - app.u.handleAppEvents($tr); + if(data._object == 'ZONE') { + panelObj.templateID = 'warehouseZoneStandardTemplate'; + panelObj.panelID = 'warehouse_'+data.geo+'_'+data.id; + panelObj.header = 'Edit Zone: '+data.zone; } else { - $btn.closest('form').anymessage({"message":"In admin_wholesale.e.wholesaleZoneAddRow, no data-loadstemplate specified on trigger element.",'gMessage':true}) + panelObj.panelID = 'warehouse_'+data.geo; + panelObj.templateID = 'warehouseAddUpdateTemplate'; + panelObj.header = 'Edit Warehouse: '+data.geo; } - }); - }, //wholesaleZoneAddRow + panelObj.showLoading = false; + var $panel = _app.ext.admin.i.DMIPanelOpen($ele,panelObj); - warehouseDetailDMIPanel : function($btn) { - $btn.button({icons: {primary: "ui-icon-pencil"},text: false}); - - if($btn.closest('tr').data('zone_type') == 'RECEIVING' || $btn.closest('tr').data('zone_type') == 'UNSTRUCTURED') { - $btn.hide(); - } - else { - $btn.off('click.warehouseDetailDMIPanel').on('click.warehouseDetailDMIPanel',function(event){ - event.preventDefault(); - var data = $btn.closest('tr').data(); - - if(data._object == 'GEO' || data._object == 'ZONE') { - //these are the shared values for the DMI panel. - var panelObj = { - 'panelID' : 'warehouse_'+data.geo, - 'handleAppEvents' : true - } - - if(data._object == 'ZONE') { - panelObj.templateID = 'warehouseZoneStandardTemplate'; - panelObj.header = 'Edit Zone: '+data.zone; - } - else { - panelObj.templateID = 'warehouseAddUpdateTemplate'; - panelObj.header = 'Edit Warehouse: '+data.geo; - } - - var $panel = app.ext.admin.i.DMIPanelOpen($btn,panelObj); - - if(data._object == 'GEO') { - $("[name='GEO']",$panel).closest('label').hide().val(data.geo); //warehouse code isn't editable. hide it. setting 'disabled' will remove from serializeJSON. - $('form',$panel).append("<input type='hidden' name='_macrobuilder' value='admin_wholesale|WAREHOUSE-UPDATE' /><input type='hidden' name='_tag/callback' value='showMessaging' /><input type='hidden' name='_tag/message' value='The warehouse has been successfully updated.' /><input type='hidden' name='_tag/updateDMIList' value='"+$panel.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); - } - else { - $('form',$panel).append("<input type='hidden' name='GEO' value='"+data.geo+"' />"); - $('form',$panel).append("<input type='hidden' name='ZONE' value='"+data.zone+"' />"); - } - $panel.showLoading({'message':'Fetching warehouse details'}); - app.model.addDispatchToQ({ - '_cmd':'adminWarehouseDetail', - 'GEO' : data.geo, - '_tag': { - 'datapointer' : 'adminWarehouseDetail|'+data.geo, - 'callback':function(rd) { - if(app.model.responseHasErrors(rd)){ - $('#globalMessaging').anymessage({'message':rd}); - } - else { - //success content goes here. - if(data._object == 'GEO') { - $panel.anycontent({'translateOnly':true,'datapointer':rd.datapointer}); - } - else { - $panel.anycontent({ - 'translateOnly':true, - 'data':app.data[rd.datapointer]['%ZONES'][data.zone] - }); - app.u.handleAppEvents($panel); - } - } + if(data._object == 'GEO') { + $("[name='GEO']",$panel).closest('label').hide().val(data.geo); //warehouse code isn't editable. hide it. setting 'disabled' will remove from serializeJSON. + $('form',$panel).append("<input type='hidden' name='_macrobuilder' value='admin_wholesale|WAREHOUSE-UPDATE' /><input type='hidden' name='_tag/callback' value='showMessaging' /><input type='hidden' name='_tag/message' value='The warehouse has been successfully updated.' /><input type='hidden' name='_tag/updateDMIList' value='"+$panel.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); + } + else { + $('form',$panel).append("<input type='hidden' name='GEO' value='"+data.geo+"' />"); + $('form',$panel).append("<input type='hidden' name='ZONE' value='"+data.zone+"' />"); + } + $panel.showLoading({'message':'Fetching warehouse details'}); + _app.model.addDispatchToQ({ + '_cmd':'adminWarehouseDetail', + 'GEO' : data.geo, + '_tag': { + 'datapointer' : 'adminWarehouseDetail|'+data.geo, + 'callback':function(rd) { + if(_app.model.responseHasErrors(rd)){ + $('#globalMessaging').anymessage({'message':rd}); + } + else { + //success content goes here. + if(data._object == 'GEO') { + $panel.anycontent({'translateOnly':true,'datapointer':rd.datapointer}); } + else { + $panel.anycontent({ + 'translateOnly':true, + 'data':_app.data[rd.datapointer]['%ZONES'][data.zone] + }); + } + _app.u.handleButtons($panel); + _app.u.handleCommonPlugins($panel); } - },'mutable'); - app.model.dispatchThis('mutable'); - } - else { - $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.warehouseDetailDMIPanel, unrecognized data._object ["+data._object+"]. Must be GEO or ZONE.","gMessage":true}); + } } - - - }); + },'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.warehouseDetailDMIPanel, either unrecognized data._object ["+data._object+"] (must be GEO or ZONE) or _object is set to zone and data.zone_type is unrecognized ["+data.zone_type+"] (must be RECEIVING, STANDARD or UNSTRUCTURED).","gMessage":true}); } }, //warehouseDetailDMIPanel - warehouseRemoveConfirm : function($btn) { - $btn.button({icons: {primary: "ui-icon-trash"},text: false}); - $btn.off('click.warehouseRemoveExec').on('click.warehouseRemoveExec',function(event){ - event.preventDefault(); - - var $tr = $btn.closest('tr'); - var GEO = $tr.data('geo'); - var $D = app.ext.admin.i.dialogConfirmRemove({ - 'message':'Are you sure you want to delete '+($tr.data('_object') == 'GEO' ? (" warehouse "+GEO) : (" zone "+$tr.data('zone')))+'? There is no undo for this action.', - 'removeButtonText' : 'Delete', - 'removeFunction':function(vars,$modal){ - var $panel = $(app.u.jqSelector('#','warehouse_'+GEO)); - if($panel.length) { - $panel.anypanel('destroy'); //make sure there is no editor for this warehouse still open. - } - - if($tr.data('_object') == 'ZONE') { - app.model.addDispatchToQ({ - '_cmd':'adminWarehouseMacro', - 'GEO' : GEO, - '_tag': { - 'callback' : 'showMessaging', - 'jqObj' : $('#globalMessaging'), - 'message' : 'Zone '+$tr.data('zone')+' has been deleted.' - }, - '@updates':["ZONE-DELETE?ZONE="+$tr.data('zone')] - },'immutable'); - } - else { - app.model.addDispatchToQ({ - '_cmd':'adminWarehouseMacro', - 'GEO':GEO, - '_tag': { - 'callback' : 'showMessaging', - 'jqObj' : $('#globalMessaging'), - 'message' : 'Warehouse '+GEO+' has been deleted.' - }, - '@updates':["WAREHOUSE-DELETE"]},'immutable'); - } - - - app.model.addDispatchToQ({'_cmd':'adminWarehouseList','_tag':{'datapointer':'adminWarehouseList','callback':'DMIUpdateResults','extension':'admin','jqObj':$btn.closest("[data-app-role='dualModeContainer']")}},'immutable'); - app.model.dispatchThis('immutable'); - $modal.dialog('close'); + warehouseRemoveConfirm : function($ele,P) { + P.preventDefault(); + + var $tr = $ele.closest('tr'); + var GEO = $tr.data('geo'); + var $D = _app.ext.admin.i.dialogConfirmRemove({ + 'message':'Are you sure you want to delete '+($tr.data('_object') == 'GEO' ? (" warehouse "+GEO) : (" zone "+$tr.data('zone')))+'? There is no undo for this action.', + 'removeButtonText' : 'Delete', + 'removeFunction':function(vars,$modal){ + var $panel = $(_app.u.jqSelector('#','warehouse_'+GEO)); + if($panel.length) { + $panel.anypanel('destroy'); //make sure there is no editor for this warehouse still open. } - }); - - - }); - }, //warehouseRemoveConfirm - - warehouseZoneCreateShow : function($btn) { - $btn.button({icons: {primary: "ui-icon-plus"},text: true}); - $btn.off('click.wholesaleZoneCreateShow').on('click.wholesaleZoneCreateShow',function(event){ - event.preventDefault(); - var GEO = $btn.closest('form').find("input[name='GEO']").val(); - if(GEO) { - var $D = app.ext.admin.i.dialogCreate({ - 'title' : 'Add a New Zone', - 'templateID' : 'warehouseAddLocationTemplate', - 'data' : {'GEO':GEO}, - appendTo : $btn.closest('.ui-anypanel-content'), //This adds the dialog as a child to the anypanel content. That means the dialog can look up the DOM tree to 'find' things. - 'showLoading' : false - }); - $D.dialog('open'); - $('form',$D).append("<input type='hidden' name='_tag/updateDMIList' value='"+$btn.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); - } - else { - $btn.closest('form').anymessage({"message":"In admin_wholesale.e.wholesaleZoneCreateShow, unable to ascertain the warehouse code.",'gMessage':true}); + if($tr.data('_object') == 'ZONE') { + _app.model.addDispatchToQ({ + '_cmd':'adminWarehouseMacro', + 'GEO' : GEO, + '_tag': { + 'callback' : 'showMessaging', + 'jqObj' : $('#globalMessaging'), + 'message' : 'Zone '+$tr.data('zone')+' has been deleted.' + }, + '@updates':["ZONE-DELETE?ZONE="+$tr.data('zone')] + },'immutable'); + } + else { + _app.model.addDispatchToQ({ + '_cmd':'adminWarehouseMacro', + 'GEO':GEO, + '_tag': { + 'callback' : 'showMessaging', + 'jqObj' : $('#globalMessaging'), + 'message' : 'Warehouse '+GEO+' has been deleted.' + }, + '@updates':["WAREHOUSE-DELETE"]},'immutable'); + } + + + _app.model.addDispatchToQ({'_cmd':'adminWarehouseList','_tag':{'datapointer':'adminWarehouseList','callback':'DMIUpdateResults','extension':'admin','jqObj':$ele.closest("[data-app-role='dualModeContainer']")}},'immutable'); + _app.model.dispatchThis('immutable'); + $modal.dialog('close'); } }); + }, //warehouseRemoveConfirm + + warehouseZoneCreateShow : function($ele,P) { + P.preventDefault(); + var GEO = $ele.closest('form').find("input[name='GEO']").val(); + if(GEO) { + var $D = _app.ext.admin.i.dialogCreate({ + 'title' : 'Add a New Zone', + 'templateID' : 'warehouseAddLocationTemplate', + 'data' : {'GEO':GEO}, + appendTo : $ele.closest('.ui-anypanel-content'), //This adds the dialog as a child to the anypanel content. That means the dialog can look up the DOM tree to 'find' things. + 'showLoading' : false + }); + $D.dialog('open'); + + $('form',$D).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' />"); + } + else { + $ele.closest('form').anymessage({"message":"In admin_wholesale.e.wholesaleZoneCreateShow, unable to ascertain the warehouse code.",'gMessage':true}); + } }, //warehouseZoneCreateShow @@ -690,7 +667,7 @@ else { whimWarehouseSelect : function($ele,p) { -// app.u.dump(" -> $ele.data('geo'): "+$ele.data('geo')); +// _app.u.dump(" -> $ele.data('geo'): "+$ele.data('geo')); p = p || {}; if($ele.data('geo')) { $ele.closest("[data-app-role='slimLeftContainer']").data("geo",$ele.data('geo')).find("h1").text("Warehouse "+$ele.data('geo')); //set the geo attribute to the warehouse id. this is used for all the warehouse utilities till changed. @@ -700,9 +677,9 @@ else { // it's already set because dps is where the page load got the geo from in the firstplace if(p.skipDPSUpdate) {} else { - var whim = app.model.dpsGet('admin_wholesale',"whim") || {}; + var whim = _app.model.dpsGet('admin_wholesale',"whim") || {}; whim.geo = $ele.data('geo'); - app.model.dpsSet('admin_wholesale',"whim",whim); + _app.model.dpsSet('admin_wholesale',"whim",whim); } } else { @@ -716,8 +693,8 @@ else { $tbody.empty(); //the results should stack w/ each search. clear them. $tbody.closest('table').show(); //table is hidden by default so the thead doesn't show up when unnecessary. - if(app.u.validateForm($form)) { - app.model.addDispatchToQ({ + if(_app.u.validateForm($form)) { + _app.model.addDispatchToQ({ '_cmd':'adminWarehouseInventoryQuery', 'GEO' : $ele.closest("[data-app-role='slimLeftContainer']").data("geo"), 'SKUS' : $("textarea[name='skus']",$form).val(), @@ -728,7 +705,7 @@ else { jqObj : $tbody } },'mutable'); - app.model.dispatchThis('mutable'); + _app.model.dispatchThis('mutable'); } else {} //form validation handles error display. }, //whimSearchMacroExec @@ -750,8 +727,8 @@ else { 'showLoading' : false }).slideDown('fast'); $('form',$target).append("<input type='hidden' name='GEO' value='"+$ele.closest("[data-app-role='slimLeftContainer']").data("geo")+"' />"); - app.u.handleCommonPlugins($target); - app.u.handleButtons($target); + _app.u.handleCommonPlugins($target); + _app.u.handleButtons($target); }); } else { @@ -765,9 +742,9 @@ else { whimSetSKULocation : function($ele,p) { var $form = $ele.closest('form'); - if(app.u.validateForm($form)) { + if(_app.u.validateForm($form)) { var sfo = $form.serializeJSON(); - sfo.UUID = app.u.guidGenerator(); + sfo.UUID = _app.u.guidGenerator(); var $li = $("<li \/>"); var $ul = $ele.closest("[data-app-role='whimContainer']").find("[data-app-role='whimLocationUpdateLog']"); $li.html("<span class='wait floatLeft marginRight'></span> "+ sfo.SKU + " + "+sfo.QTY+" " + sfo.LOC).prependTo($ul); @@ -775,14 +752,14 @@ else { var updates = new Array(); updates.push("SKU-LOCATION-ADD?"+$.param(sfo)); - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ '_cmd':'adminWarehouseMacro', 'GEO' : $ele.closest("[data-app-role='slimLeftContainer']").data("geo"), '@updates' : updates, '_tag': { 'callback':function(rd) { $('.wait',$li).addClass('ui-icon').removeClass('wait') - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $('.ui-icon',$li).addClass('ui-state-error ui-icon-alert'); $li.anymessage({'message':rd,'persistant':true}); } @@ -794,7 +771,7 @@ else { } } },'immutable'); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); } else { @@ -805,170 +782,141 @@ else { //////////////////// SUPPLIERS - adminSupplierInventoryAddShow : function($btn) { - $btn.button({icons: {primary: "ui-icon-plus"},text: true}); - $btn.off('click.adminSupplierInventoryAddShow').on('click.adminSupplierInventoryAddShow',function(event){ - event.preventDefault(); - var vendor = $btn.closest('tr').data('code'); - if(vendor) { - var $D = app.ext.admin.i.dialogCreate({ - 'title':'Add Inventory for supplier '+vendor, - 'templateID':'supplierInventoryAddTemplate', - 'showLoading':false //will get passed into anycontent and disable showLoading. - }); - $D.find('form').append("<input type='hidden' name='vendor' value='"+vendor+"' />") - $D.dialog('open'); - $D.anydelegate(); - } - else { - $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.adminSupplierInventoryAddShow, unable to ascertain vendor id.","gMessage":true}); - } - - }); + adminSupplierInventoryAddShow : function($ele,P) { + P.preventDefault(); + var vendor = $ele.closest("[data-code]").data('code'); + if(vendor) { + var $D = _app.ext.admin.i.dialogCreate({ + 'title':'Add Inventory for supplier '+vendor, + 'templateID':'supplierInventoryAddTemplate', + 'showLoading':false //will get passed into anycontent and disable showLoading. + }); + $D.find('form').append("<input type='hidden' name='vendor' value='"+vendor+"' />") + $D.dialog('open'); + $D.anyform(); + } + else { + $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.adminSupplierInventoryAddShow, unable to ascertain vendor id.","gMessage":true}); + } + return false; }, - // There is a function in WHIM that is VERY similar to this. Once supplier is using delegated events instead of appevents, combine the two ### - adminSupplierInventoryAddExec : function($btn) { - - $btn.button({icons: {primary: "ui-icon-plus"},text: true}); - $btn.off('click.adminSupplierInventoryAddShow').on('click.adminSupplierInventoryAddShow',function(event){ - event.preventDefault(); + adminSupplierInventoryAddExec : function($ele,P) { + P.preventDefault(); + var $form = $ele.closest('form'); + if(_app.u.validateForm($form)) { + var + sfo = $form.serializeJSON(), + $li = $("<li \/>"); - var $form = $btn.closest('form'); - if(app.u.validateForm($form)) { + if(sfo.vendor) { + sfo.UUID = _app.u.guidGenerator(); + $li.html("<span class='wait floatLeft marginRight'></span> "+ sfo.SKU + " + "+sfo.QTY).prependTo($ele.closest("[data-app-role='supplierInventoryUpdateContainer']").find("[data-app-role='supplierInventoryUpdateLog']")); - var - sfo = $form.serializeJSON(), - $li = $("<li \/>"); - - if(sfo.vendor) { - sfo.UUID = app.u.guidGenerator(); - $li.html("<span class='wait floatLeft marginRight'></span> "+ sfo.SKU + " + "+sfo.QTY).prependTo($btn.closest("[data-app-role='supplierInventoryUpdateContainer']").find("[data-app-role='supplierInventoryUpdateLog']")); - - app.model.addDispatchToQ({ - '_cmd':'adminSupplierAction', - 'VENDORID' : sfo.vendor, - '@updates' : ["SKU:LINK?"+$.param(sfo)], - '_tag': { - 'callback':function(rd) { - $('.wait',$li).addClass('ui-icon').removeClass('wait') - if(app.model.responseHasErrors(rd)){ - $('.ui-icon',$li).addClass('ui-state-error ui-icon-alert'); - $li.anymessage({'message':rd,'persistant':true}); - } - else { - $(".resetMeOnComplete",$form).each(function(){$(this).val("")}); //clear inputs for next sku. only target class so hiddens et all don't get nuked. - $('.ui-icon',$li).addClass('ui-icon-check'); - //success content goes here. - } + _app.model.addDispatchToQ({ + '_cmd':'adminSupplierAction', + 'VENDORID' : sfo.vendor, + '@updates' : ["SKU:LINK?"+$.param(sfo)], + '_tag': { + 'callback':function(rd) { + $('.wait',$li).addClass('ui-icon').removeClass('wait') + if(_app.model.responseHasErrors(rd)){ + $('.ui-icon',$li).addClass('ui-state-error ui-icon-alert'); + $li.anymessage({'message':rd,'persistant':true}); + } + else { + $(".resetMeOnComplete",$form).each(function(){$(this).val("")}); //clear inputs for next sku. only target class so hiddens et all don't get nuked. + $('.ui-icon',$li).addClass('ui-icon-check'); + //success content goes here. } } - },'immutable'); - app.model.dispatchThis('immutable'); - } - else { - $form.anymessage({"message":"In admin_wholesale.e.adminSupplierInventoryAddExec, unable to ascertain vendor (should be a hidden input in form)","gMessage":"true"}) - } - + } + },'immutable'); + _app.model.dispatchThis('immutable'); } else { - //form validation - } - - }); - - }, + $form.anymessage({"message":"In admin_wholesale.e.adminSupplierInventoryAddExec, unable to ascertain vendor (should be a hidden input in form)","gMessage":"true"}) + } + } + else { + //form validation + } + return false; + }, //executed from within the 'list' mode (most likely) and will prompt the user in a modal to confirm, then will delete the user */ - adminSupplierRemoveExec : function($btn) { - $btn.button({icons: {primary: "ui-icon-trash"},text: false}); - $btn.off('click.adminSupplierRemoveExec').on('click.adminSupplierRemoveExec',function(event){ - - event.preventDefault(); - - var VENDORID = $btn.closest('tr').data('code'); - var $DMI = $btn.closest("[data-app-role='dualModeContainer']"); - - var $D = app.ext.admin.i.dialogConfirmRemove({ - 'message':'Are you sure you want to delete vendor '+VENDORID+'? There is no undo for this action.', - 'removeButtonText' : 'Delete Vendor', - 'removeFunction':function(vars,$modal){ - $DMI.showLoading({"message":"removing vendor "+VENDORID}); - app.model.addDispatchToQ({'_cmd':'adminSupplierRemove','VENDORID':VENDORID,'_tag':{'callback':'showMessaging','message':'The vendor '+VENDORID+' has been deleted','jqObj':$DMI}},'immutable'); - app.model.addDispatchToQ({'_cmd':'adminSupplierList','_tag':{'datapointer':'adminSupplierList','callback':'DMIUpdateResults','extension':'admin','jqObj':$DMI}},'immutable'); - app.model.dispatchThis('immutable'); - $modal.dialog('close'); - } - }); - - }); //$btn.on + adminSupplierRemoveExec : function($ele,P) { + P.preventDefault(); + + var VENDORID = $ele.closest("[data-code]").data('code'); + var $DMI = $ele.closest("[data-app-role='dualModeContainer']"); + + var $D = _app.ext.admin.i.dialogConfirmRemove({ + 'message':'Are you sure you want to delete vendor '+VENDORID+'? There is no undo for this action.', + 'removeButtonText' : 'Delete Vendor', + 'removeFunction':function(vars,$modal){ + $DMI.showLoading({"message":"removing vendor "+VENDORID}); + _app.model.addDispatchToQ({'_cmd':'adminSupplierRemove','VENDORID':VENDORID,'_tag':{'callback':'showMessaging','message':'The vendor '+VENDORID+' has been deleted','jqObj':$DMI}},'immutable'); + _app.model.addDispatchToQ({'_cmd':'adminSupplierList','_tag':{'datapointer':'adminSupplierList','callback':'DMIUpdateResults','extension':'admin','jqObj':$DMI}},'immutable'); + _app.model.dispatchThis('immutable'); + $modal.dialog('close'); + } + }); + return false; }, //adminSupplierRemoveExec - - - - - //applied to 'create user' button. just opens the modal. - adminSupplierCreateShow : function($btn) { - $btn.button(); - $btn.off('click.showSupplierCreate').on('click.showSupplierCreate',function(event){ - event.preventDefault(); - var $D = app.ext.admin.i.dialogCreate({ - 'title':'Add New Supplier', - 'templateID':'supplierAddTemplate', - 'showLoading':false //will get passed into anycontent and disable showLoading. - }); - $D.dialog('open'); + adminSupplierCreateShow : function($ele,P) { + P.preventDefault(); + var $D = _app.ext.admin.i.dialogCreate({ + 'title':'Add New Supplier', + 'templateID':'supplierAddTemplate', + 'showLoading':false //will get passed into anycontent and disable showLoading. + }); + $D.dialog('open'); //These fields are used for processForm on save. //They're here instead of in the form directly so that the form/template can be recycled for edit. - $('form',$D).first().append("<input type='hidden' name='DMIID' value='"+$btn.closest("[data-app-role='dualModeContainer']").attr('id')+"' \/>"); - app.ext.admin.u.handleFormConditionalDelegation($('form',$D)); - app.u.handleAppEvents($D,{"$context":$btn.closest("[data-app-role='supplierManager']").parent()}) - }) + $('form:first',$D).anyform({'trackEdits':true}).append("<input type='hidden' name='DMIID' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' \/>"); + _app.u.handleButtons($D); + _app.u.handleCommonPlugins($D); + return false; }, //showSupplierCreate - //applied to 'create user' button. just opens the modal. - adminSupplierCreateExec : function($btn) { - $btn.button(); - $btn.off('click.showSupplierCreate').on('click.showSupplierCreate',function(event){ - event.preventDefault(); - var $form = $btn.closest('form'); - if(app.u.validateForm($form)) { - -var sfo = $form.serializeJSON(); -sfo._cmd = 'adminSupplierCreate' -sfo._tag = { - 'callback':'showMessaging', - 'jqObj' : $form, - 'jqObjEmpty' : true, - 'updateDMIList' : sfo.DMIID, - 'message' : 'Thank you, the supplier has been added.' - } -delete sfo.DMIID; //is no longer necessary. -if(sfo.FORMAT == 'FBA') { - sfo.NAME = "Fulfillment by Amazon" - } -app.model.addDispatchToQ(sfo,'immutable'); - -//after the initial dispatch so that the VENDOR is created by the time the macro is run. -/* -if(sfo.FORMAT == 'FBA') { - app.model.addDispatchToQ({ - '_cmd' : 'adminSupplierMacro', - 'VENDOR' : 'FBA', - '@updates' : [] - },'immutable'); - } -*/ -app.model.dispatchThis('immutable'); + adminSupplierCreateExec : function($ele,P) { + P.preventDefault(); + var $form = $ele.closest('form'); + if(_app.u.validateForm($form)) { + var sfo = $form.serializeJSON(); + sfo._cmd = 'adminSupplierCreate' + + if(sfo['INIT-DEFAULTS']) { + sfo['@updates'] = ["INIT-DEFAULTS"]; + delete sfo['INIT-DEFAULTS'] } - else {}//validation handles display logic too - }); + + if(sfo.FORMAT == 'FBA') {sfo.VENDORID = 'FBA'} + + sfo._tag = { + 'callback':'showMessaging', + 'jqObj' : $form, + 'jqObjEmpty' : true, + 'updateDMIList' : sfo.DMIID, + 'message' : 'Thank you, the supplier has been added.' + } + delete sfo.DMIID; //is no longer necessary. + if(sfo.FORMAT == 'FBA') { + sfo.NAME = "Fulfillment by Amazon" + } + _app.model.addDispatchToQ(sfo,'immutable'); + _app.model.dispatchThis('immutable'); + + } + else {}//validation handles display logic too + return false; }, //showSupplierCreate @@ -978,12 +926,12 @@ app.model.dispatchThis('immutable'); //All things being equal, it'll then refresh the list of orders. adminSupplierActionOrder : function($ele,P) { - app.u.dump("BEGIN admin_wholesale.e.adminSupplierActionOrder click event"); + _app.u.dump("BEGIN admin_wholesale.e.adminSupplierActionOrder click event"); var $D = $ele.closest('.ui-dialog-content'), $form = $ele.closest('form'); - if(app.u.validateForm($form)) { + if(_app.u.validateForm($form)) { var sfo = $form.serializeJSON(), @@ -1008,12 +956,12 @@ app.model.dispatchThis('immutable'); if(sfo['@updates'].length) { - app.model.addDispatchToQ(sfo,'immutable'); + _app.model.addDispatchToQ(sfo,'immutable'); if($D.data('mode')) { if($D.data('mode') == 'adminSupplierUnorderedItemList') { $('tbody',$form).empty().showLoading({"message":"Performing action and fetching updated list of orders"}) - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ _cmd : 'adminSupplierUnorderedItemList', FILTER : 'OPEN', VENDORID : VENDORID, @@ -1026,7 +974,7 @@ app.model.dispatchThis('immutable'); } else if($D.data('mode') == 'adminSupplierOrderList') { $('tbody',$form).empty().showLoading({"message":"Performing action and fetching updated list of orders"}) - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ _cmd : 'adminSupplierOrderList', FILTER : 'RECENT', VENDORID : VENDORID, @@ -1048,7 +996,7 @@ app.model.dispatchThis('immutable'); $D.anymessage({'message':'Unable to ascertain a mode for this viewer. The request to change order status is still being attempted, but this list will not auto-refresh after that request finishes.'}); } - app.model.dispatchThis('immutable'); //dispatch for update runs whether 'list' updated or not. + _app.model.dispatchThis('immutable'); //dispatch for update runs whether 'list' updated or not. } else { $form.anymessage({"message":"Please select at least one order to perform this action on."}) @@ -1061,10 +1009,10 @@ app.model.dispatchThis('immutable'); }, - adminSupplierActionDeAssociate : function($btn) { + adminSupplierActionDeAssociate : function($ele,P) { var - $form = $btn.closest('form'), - VENDORID = $btn.closest('.ui-dialog-content').data('vendorid'), + $form = $ele.closest('form'), + VENDORID = $ele.closest('.ui-dialog-content').data('vendorid'), cmdObj = { _cmd : 'adminSupplierAction', '@updates' : new Array(), @@ -1082,8 +1030,8 @@ app.model.dispatchThis('immutable'); if(cmdObj['@updates'].length) { $form.showLoading({"message":"De-associating product and fetching updated list"}); ('tbody',$form).empty(); - app.model.addDispatchToQ(cmdObj,'immutable'); - app.model.addDispatchToQ({ + _app.model.addDispatchToQ(cmdObj,'immutable'); + _app.model.addDispatchToQ({ _cmd : 'adminSupplierInventoryList', FILTER : 'OPEN', VENDORID : VENDORID, @@ -1093,7 +1041,7 @@ app.model.dispatchThis('immutable'); jqObj : $('tbody',$form) } },'immutable'); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); } else { $D.anymessage({'message':'Please select at least one product from the list below.'}); @@ -1101,130 +1049,128 @@ app.model.dispatchThis('immutable'); }, - adminSupplierAction : function($btn) { - $btn.button(); - if($btn.data('action')) { - - if($btn.data('action') == 'INVENTORY:UPDATE') {} - else { - $btn.button('disable').attr('title','Invalid action specified on button.'); - } - - $btn.off('click.adminSupplierAction').on('click.adminSupplierAction',function(event){ - event.preventDefault(); - if($btn.data('action') == 'INVENTORY:UPDATE') { - var $fieldset = $btn.closest('fieldset'); - - if(app.u.validateForm($fieldset)) { - $fieldset.showLoading({"message":"Fetching inventory from supplier"}); - app.model.addDispatchToQ({'_cmd':'adminSupplierAction','@updates':["INVENTORY:UPDATE"],'VENDORID':$btn.closest("[data-code]").data('code'),'_tag':{'callback':function(rd){ - $fieldset.hideLoading(); - if(app.model.responseHasErrors(rd)){ - $fieldset.anymessage({'message':rd}); - } - else { - $fieldset.anymessage(app.u.successMsgObject('File imported')); - } - }}},'mutable'); - app.model.dispatchThis('mutable'); + adminSupplierAction : function($ele,P) { + //the thought here is that someday more actions will be present. + if($ele.data('action') == 'INVENTORY:UPDATE') { + var $fieldset = $ele.closest('fieldset'); + if(_app.u.validateForm($fieldset)) { + $fieldset.showLoading({"message":"Fetching inventory from supplier"}); + _app.model.addDispatchToQ({'_cmd':'adminSupplierAction','@updates':["INVENTORY:UPDATE"],'VENDORID':$ele.closest("[data-code]").data('code'),'_tag':{'callback':function(rd){ + $fieldset.hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $fieldset.anymessage({'message':rd}); } - else {} - } - else {} //shouldn't get here. actions have already been validated. - }); - - + else { + $fieldset.anymessage(_app.u.successMsgObject('File imported')); + } + }}},'mutable'); + _app.model.dispatchThis('mutable'); + } + else {} } else { - $btn.button('disable').attr('title','No action specified on button.'); + $("#globalMessaging").anymessage({"message":"In admin_wholesale.e.adminSupplierAction, invalid data-action ["+$ele.data('action')+"] set on trigger element.","gMessage":true}); } }, //applied to 'edit user' button and the link in the list (name). opens the editor. - showSupplierEditor : function($ele) { -//event used both on the supplier 'name' and the edit button. - if($ele.is('button')) { - $ele.button({icons: {primary: "ui-icon-pencil"},text: false}); - } - $ele.off('click.showSupplierEditor').on('click.showSupplierEditor',function(){ - var $row = $ele.closest('tr'); - if($row.data('code')) { + showSupplierEditor : function($ele,P) { + P.preventDefault() + var $row = $ele.closest('tr'); + if($row.data('code')) { - var $table = $ele.closest('table'); - - $table.stickytab({'tabtext':'vendors','tabID':'batchJobsStickyTab'}).addClass('small'); - $('button',$table).removeClass('ui-state-focus'); //removes class added by jqueryui onclick. - $('button',$table).removeClass('ui-state-highlight'); - $ele.addClass('ui-state-highlight'); + var $table = $ele.closest('table'); + + $table.stickytab({'tabtext':'vendors','tabID':'batchJobsStickyTab'}).addClass('small'); + $('button',$table).removeClass('ui-state-focus'); //removes class added by jqueryui onclick. + $('button',$table).removeClass('ui-state-highlight'); + $ele.addClass('ui-state-highlight'); //make sure buttons and links in the stickytab content area close the sticktab on click. good usability. - $('button, a',$table).each(function(){ - $(this).off('close.stickytab').on('click.closeStickytab',function(){ - $table.stickytab('close'); - }) + $('button, a',$table).each(function(){ + $(this).off('close.stickytab').on('click.closeStickytab',function(){ + $table.stickytab('close'); }) + }) + _app.u.addEventDelegation($table); - var $editorContainer = $(app.u.jqSelector('#',app.ext.admin.vars.tab+'Content')) - $editorContainer.empty(); - app.ext.admin_wholesale.a.showSupplierEditor($editorContainer,$row.data('code')); - } - else { - $("#globalMessaging").anymessage({'message':'In admin_wholesale.e.showSupplierEditor, unable to ascertain VENDORID','gMessage':true}); - } - }); + var $editorContainer = $(_app.u.jqSelector('#',_app.ext.admin.vars.tab+'Content')) + $editorContainer.empty(); + _app.ext.admin_wholesale.a.showSupplierEditor($editorContainer,$row.data('code')); + } + else { + $("#globalMessaging").anymessage({'message':'In admin_wholesale.e.showSupplierEditor, unable to ascertain VENDORID','gMessage':true}); + } + return false; }, //showSupplierEditor - - adminSupplierUnorderedItemListShow : function($btn) { - $btn.button(); - - $btn.off('click.adminSupplierUnorderedItemListShow').on('click.adminSupplierUnorderedItemListShow',function(){ - - var VENDORID = $btn.closest("[data-code]").data('CODE'); - var $D = app.ext.admin.i.dialogCreate({ - 'templateID': "supplierUnorderedItemsTemplate", - 'title': $btn.data('mode') == 'vendor' ? "Unordered Items for "+VENDORID : "Unordered Items", - "showLoading" : false + supplierBatchExec : function($ele,p) { +// _app.u.dump(" -> BEGIN admin_wholesale.e.supplierBatchExec"); + if($ele.data('verb')) { + _app.u.dump(" -> verb: "+$ele.data('verb')); + $ele.closest('.dualModeContainer').find(":checked").each(function(){ + var $row = $(this).closest('tr'); + _app.u.dump(" -> $row.data('code'): "+$row.data('code')); + if($row.data('code')) { + _app.ext.admin_batchjob.a.adminBatchJobCreate({'type':'SUPPLIER/'+$row.data('code')+'/'+$ele.data('verb')}); + } + else { + $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.supplierBatchExec, unable to ascertain vendor code.","gMessage":true}); + } }); - - $D.dialog('option','width','70%'); - $D.dialog('option','modal',false); + } + else { + //no data-verb + $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.supplierBatchExec, no data-verb set on trigger element.","gMessage":true}); + } + }, + + adminSupplierUnorderedItemListShow : function($ele,P) { + P.preventDefault(); + var VENDORID = $ele.closest("[data-code]").data('code'); + var $D = _app.ext.admin.i.dialogCreate({ + 'templateID': "supplierUnorderedItemsTemplate", + 'title': $ele.data('mode') == 'vendor' ? "Unordered Items for "+VENDORID : "Unordered Items", + "showLoading" : false + }); + + $D.dialog('option','width','70%'); + $D.dialog('option','modal',false); - $D.dialog( "option", "appendTo", $btn.closest("[data-app-role='dualModeContainer']")); //jq v 1.10. must be before open + $D.dialog( "option", "appendTo", $ele.closest("[data-app-role='dualModeContainer']")); //jq v 1.10. must be before open //d.data is used by button on form submit. form template also used by order list - - $D.dialog('open'); - - $('tbody',$D).showLoading({'message':'Fetching unordered item list...'}); + + $D.dialog('open'); + + $('tbody',$D).showLoading({'message':'Fetching unordered item list...'}); - var cmdObj = { - _cmd : 'adminSupplierUnorderedItemList', - FILTER : 'OPEN', - _tag : { - callback : 'anycontent', - jqObj : $('tbody',$D) - } + var cmdObj = { + _cmd : 'adminSupplierUnorderedItemList', + FILTER : 'OPEN', + _tag : { + callback : 'anycontent', + jqObj : $('tbody',$D) } + } - if($btn.data('mode') == 'vendor') { - $D.data({'vendorid':VENDORID,'mode':'adminSupplierUnorderedItemList'}); - cmdObj.VENDORID = VENDORID - cmdObj._tag.datapointer = "adminSupplierUnorderedItemList|"+cmdObj.VENDORID; - } - else if ($btn.data('mode') == 'all'){ - $D.data({'vendorid':VENDORID,'mode':'adminSupplierUnorderedItemList','vendorid':''}); - cmdObj._tag.datapointer = "adminSupplierUnorderedItemList"; - } - else {} //unrecognized mode. - //no datapointer will be set if invalid mode set. + if($ele.data('mode') == 'vendor') { + $D.data({'vendorid':VENDORID,'mode':'adminSupplierUnorderedItemList'}); + cmdObj.VENDORID = VENDORID + cmdObj._tag.datapointer = "adminSupplierUnorderedItemList|"+cmdObj.VENDORID; + } + else if ($ele.data('mode') == 'all'){ + $D.data({'vendorid':VENDORID,'mode':'adminSupplierUnorderedItemList','vendorid':''}); + cmdObj._tag.datapointer = "adminSupplierUnorderedItemList"; + } + else {} //unrecognized mode. + //no datapointer will be set if invalid mode set. - if(cmdObj._tag.datapointer) { - app.model.addDispatchToQ(cmdObj,'mutable'); - app.model.dispatchThis('mutable'); - } - - }); + if(cmdObj._tag.datapointer) { + _app.model.addDispatchToQ(cmdObj,'mutable'); + _app.model.dispatchThis('mutable'); + } + return false; }, //This code opens either the supplier specific inventory or order list. @@ -1233,384 +1179,341 @@ app.model.dispatchThis('immutable'); // and it uses closest data- instead of closest tr because in detail mode, the buttons aren't in a tr. //the code that uses this still uses app events. The dialog this opens uses delegated events. adminSupplierProdOrderListShow : function($ele,P) { - $ele.button(); - + P.preventDefault(); if($ele.data('mode') == 'product' || $ele.data('mode') == 'order') { - -$ele.off('click.adminSupplierProdOrderListShow').on('click.adminSupplierProdOrderListShow',function(event){ - event.preventDefault(); - var VENDORID = $ele.closest("[data-code]").data('code'); - - if(VENDORID) { - - var $D = app.ext.admin.i.dialogCreate({ - 'templateID': ($ele.data('mode') == 'order') ? 'supplierOrderListTemplate' : 'supplierItemListTemplate', - 'title': $ele.data('mode')+" list for vendor "+VENDORID, - 'showLoading' : false - }); - $D.data('vendorid',VENDORID); - $D.dialog('option','modal',false); - $D.dialog('option','width','70%'); - $D.dialog('option','height',($(window).height() / 2)); - $D.dialog( "option", "appendTo", $ele.closest("[data-app-role='dualModeContainer']")); //jq v 1.10. must be before open - $('form',$D).showLoading({'message':'Fetching '+$ele.data('mode')+' list...'}).append("<input type='hidden' name='VENDORID' value='"+VENDORID+"' \/>"); - $D.dialog('open'); - - var cmdObj = { - 'VENDORID':VENDORID, - '_tag': { - 'callback': 'anycontent', - 'handleEventDelegation' : true, - 'jqObj' : $('form',$D) - } - } - - if($ele.data('mode') == 'order') { - $D.data('mode','adminSupplierOrderList'); //used by button on form submit. form template also used by unordereditems - cmdObj._cmd = 'adminSupplierOrderList'; - cmdObj.FILTER = 'RECENT'; - cmdObj._tag.datapointer = 'adminSupplierOrderList|'+VENDORID; - } - else if($ele.data('mode') == 'product') { - cmdObj._cmd = 'adminSupplierInventoryList'; -// cmdObj.FILTER = 'OPEN'; - cmdObj._tag.datapointer = 'adminSupplierInventoryList|'+VENDORID; - } - else {} //should never get here. unrecognized mode. - - app.model.addDispatchToQ(cmdObj,'mutable'); - app.model.dispatchThis('mutable'); - - } - else { - $('#globalMessaging').anymessage({'message':'In admin_wholesale.e.adminSupplierProdOrderListShow, unable to determine vendorID.','gMessage':true}) - } - }); - + var VENDORID = $ele.closest("[data-code]").data('code'); + + if(VENDORID) { + + var $D = _app.ext.admin.i.dialogCreate({ + 'templateID': ($ele.data('mode') == 'order') ? 'supplierOrderListTemplate' : 'supplierItemListTemplate', + 'title': $ele.data('mode')+" list for vendor "+VENDORID, + 'showLoading' : false, + 'skipDelegation' : true //the dialog is being appended to a parent element which already has delegation on it. + }); + $D.data('vendorid',VENDORID); + $D.dialog('option','modal',false); + $D.dialog('option','width','70%'); + $D.dialog('option','height',($(window).height() / 2)); + $D.dialog( "option", "appendTo", $ele.closest("[data-app-role='dualModeContainer']")); //jq v 1.10. must be before open + $('form',$D).showLoading({'message':'Fetching '+$ele.data('mode')+' list...'}).append("<input type='hidden' name='VENDORID' value='"+VENDORID+"' \/>"); + $D.dialog('open'); + + var cmdObj = { + 'VENDORID':VENDORID, + '_tag': { + 'callback': 'anycontent', + 'skipAppEvents' : true, + 'addEventDelegation' : false, //the dialog is being appended to a parent element which already has delegation on it. + 'jqObj' : $('form',$D) + } + } + + if($ele.data('mode') == 'order') { + $D.data('mode','adminSupplierOrderList'); //used by button on form submit. form template also used by unordereditems + cmdObj._cmd = 'adminSupplierOrderList'; + cmdObj.FILTER = 'RECENT'; + cmdObj._tag.datapointer = 'adminSupplierOrderList|'+VENDORID; + } + else if($ele.data('mode') == 'product') { + cmdObj._cmd = 'adminSupplierInventoryList'; + // cmdObj.FILTER = 'OPEN'; + cmdObj._tag.datapointer = 'adminSupplierInventoryList|'+VENDORID; + } + else {} //should never get here. unrecognized mode. + _app.u.addEventDelegation($D); + _app.model.addDispatchToQ(cmdObj,'mutable'); + _app.model.dispatchThis('mutable'); + + } + else { + $('#globalMessaging').anymessage({'message':'In admin_wholesale.e.adminSupplierProdOrderListShow, unable to determine vendorID.','gMessage':true}) + } } else { - $ele.button('disable'); + $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.adminSupplierProdOrderListShow, no data-mode set on trigger element.","gMessage":true}) } + return false; }, //adminSupplierOrderListShow + + + + +//////////////////// SCHEDULES + + + priceScheduleUpdateShow : function($ele,P) { + var SID = $ele.closest('tr').data('sid'); //schedule id + var $panel = _app.ext.admin.i.DMIPanelOpen($ele,{ + 'templateID' : 'priceScheduleUpdateTemplate', + 'panelID' : 'schedule_'+SID, + 'header' : 'Edit Price Schedule: '+SID, + 'data' : $ele.closest('tr').data() + }); + $('form',$panel).append("<input type='hidden' name='_tag/updateDMIList' value='"+$ele.closest("[data-app-role='dualModeContainer']").attr('id')+"' \/>"); + _app.u.handleButtons($panel); + _app.model.dispatchThis('mutable'); + }, //priceScheduleUpdateShow - showMediaLib4OrganizationLogo : function($ele) { - $ele.off('click.mediaLib').on('click.mediaLib',function(event){ + + priceScheduleCreateShow : function($ele,P) { + P.preventDefault(); + + var $D = _app.ext.admin.i.dialogCreate({ + 'title':'Add New Schedule', + 'showLoading':false //will get passed into anycontent and disable showLoading. + }); + + $D.anyform().append("<label>Schedule ID <input type='text' size='3' data-minlength='3' maxlength='3' name='SID' value='' data-input-keyup='input-format' data-input-format='alphanumeric uppercase' \/><\/label><br />"); + + $("<button>Create Schedule<\/button>").button().on('click',function(event){ event.preventDefault(); - var $context = $ele.closest('fieldset'); - mediaLibrary($("[data-app-role='organizationLogo']",$context),$("[name='LOGO']",$context),'Choose Dropship Logo'); + if(_app.u.validateForm($D)) { + _app.model.addDispatchToQ({ + '_cmd':'adminPriceScheduleCreate', + 'SID': $(this).parent().find("[name='SID']").val(), + '_tag': { + 'callback':'showMessaging', + 'jqObj' : $D, + 'jqObjEmpty' : true, + 'message' : 'Your price schedule has been created.' + } + },'immutable'); + _app.model.addDispatchToQ({'_cmd':'adminPriceScheduleList','_tag':{'datapointer':'adminPriceScheduleList','callback':'DMIUpdateResults','extension':'admin','jqObj':$ele.closest("[data-app-role='dualModeContainer']")}},'immutable'); + _app.model.dispatchThis('immutable'); + } + else { + + } + }).appendTo($D); + + $D.dialog('open'); + }, + + priceScheduleRemoveConfirm : function($ele,P) { + var SID = $ele.closest('tr').data('sid'); + var $D = _app.ext.admin.i.dialogConfirmRemove({ + 'message':'Are you sure you want to delete schedule '+SID+'? There is no undo for this action.', + 'removeButtonText' : 'Delete Price Schedule', + 'removeFunction':function(vars,$modal){ + var $panel = $(_app.u.jqSelector('#','schedule_'+SID)); + if($panel.length) { + $panel.anypanel('destroy'); //make sure there is no editor for this schedule still open. + } + $ele.closest("[data-app-role='dualModeContainer']").showLoading({"message":"Removing price schedule "+SID}); + _app.model.addDispatchToQ({'_cmd':'adminPriceScheduleRemove','SID':SID},'immutable'); + _app.model.addDispatchToQ({'_cmd':'adminPriceScheduleList','_tag':{'datapointer':'adminPriceScheduleList','callback':'DMIUpdateResults','extension':'admin','jqObj':$ele.closest("[data-app-role='dualModeContainer']")}},'immutable'); + _app.model.dispatchThis('immutable'); + $modal.dialog('close'); + } }); - }, //showMediaLib4OrganizationLogo + }, //execTicketClose + + + +//////////////////// ORGANIZATIONS - execOrganizationSearch : function($btn){ + + showMediaLib4OrganizationLogo : function($ele) { + var $context = $ele.closest('fieldset'); + mediaLibrary($("[data-app-role='organizationLogo']",$context),$("[name='LOGO']",$context),'Choose Dropship Logo'); + }, //showMediaLib4OrganizationLogo + + execOrganizationSearch : function($ele,P){ + P.preventDefault(); + $('.dualModeListMessaging').empty(); //clear existing messaging. + var + $form = $ele.closest('form'), + sfo = $form.serializeJSON(), + $dualModeContainer = $form.closest("[data-app-role='dualModeContainer']"), + $table = $("[data-app-role='dualModeListTable']",$dualModeContainer); - $btn.button({icons: {primary: "ui-icon-search"},text: true}); - $btn.off('click.execOrganizationCreate').on('click.execOrganizationCreate',function(event) { - event.preventDefault(); - $('.dualModeListMessaging').empty(); //clear existing messaging. - var - $form = $btn.closest('form'), - sfo = $form.serializeJSON(), - $dualModeContainer = $form.closest("[data-app-role='dualModeContainer']"), - $table = $("[data-app-role='dualModeListContents']",$dualModeContainer).closest('table'); - - $("[data-app-role='dualModeResultsTable']",$dualModeContainer).show(); - $("[data-app-role='dualModeDetailContainer']",$dualModeContainer).hide(); + _app.u.dump(" -> $dualModeContainer.length: "+$dualModeContainer.length); + _app.u.dump(" -> $table.length: "+$table.length); + + $("[data-app-role='dualModeResultsTable']",$dualModeContainer).show(); + $("[data-app-role='dualModeDetailContainer']",$dualModeContainer).hide(); /* keywords and searchby are NOT required. if empty, a list of recent orgs will be returned */ - if(sfo) { -// app.u.dump(" -> sfo: "); app.u.dump(sfo); - $('tbody',$table).empty(); //clear previous search results. - $dualModeContainer.showLoading("Searching organizations by "+sfo.searchby+" for "+sfo.keywords); - - sfo[sfo.searchby] = sfo.keywords; - delete sfo.keywords; delete sfo.searchby; //sanitize before sending to API. - - app.ext.admin.calls.adminCustomerOrganizationSearch.init(sfo,{'callback':function(rd){ + if(sfo) { +// _app.u.dump(" -> sfo: "); _app.u.dump(sfo); + $('tbody',$table).empty(); //clear previous search results. + $dualModeContainer.showLoading("Searching organizations by "+sfo.searchby+" for "+sfo.keywords); + + sfo[sfo.searchby] = sfo.keywords; + delete sfo.keywords; delete sfo.searchby; //sanitize before sending to API. + + sfo._cmd = 'adminCustomerOrganizationSearch'; + sfo._tag = { + 'datapointer' : 'adminCustomerOrganizationSearch', + 'callback' : function(rd){ $dualModeContainer.hideLoading(); - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $form.anymessage({'message':rd}) } - else if(app.data[rd.datapointer] && app.data[rd.datapointer]['@ORGANIZATIONS'].length === 0){ + else if(_app.data[rd.datapointer] && _app.data[rd.datapointer]['@ORGANIZATIONS'].length === 0){ $('.dualModeListMessaging').anymessage({'message':'There were no results for your search.'}); //clear existing messaging. } else { $table.show(); $table.anycontent({'datapointer':rd.datapointer}); - $table.anytable(); - app.u.handleAppEvents($table,{'$context':$dualModeContainer}); + _app.u.handleCommonPlugins($form); + _app.u.handleButtons($form); } - - }},'mutable'); - app.model.dispatchThis(); - } - else if (!sfo) { - $('#globalMessaging').anymessage({'message':'In admin_wholesale.e.execOrganizationSearch, unable to find form OR to serialize as JSON.','gMessage':true}); - } - else { + } + }; + _app.model.addDispatchToQ(sfo,'mutable'); + _app.model.dispatchThis('mutable'); + } + else if (!sfo) { + $('#globalMessaging').anymessage({'message':'In admin_wholesale.e.execOrganizationSearch, unable to find form OR to serialize as JSON.','gMessage':true}); + } + else { // never reached, blank search shows last 50 results - $('#globalMessaging').anymessage({'message':'Either keywords ['+sfo.keywords+'] or searchby ['+sfo.searchby+'] left blank.'}); - } - - - }); + $('#globalMessaging').anymessage({'message':'Either keywords ['+sfo.keywords+'] or searchby ['+sfo.searchby+'] left blank.'}); + } }, //execOrganizationSearch - execOrganizationRemove : function($btn) { - - $btn.button({icons: {primary: "ui-icon-trash"},text: false}); - $btn.off('click.execOrganizationRemove').on('click.execOrganizationRemove',function(event){ - event.preventDefault(); - var - $D = $("<div \/>").attr('title',"Permanently Remove Organization"), - orgID = $btn.closest('tr').data('orgid'); - - $D.append("<P>Are you sure you want to delete this organization? There is no undo for this action.<\/P>"); - $D.addClass('displayNone').appendTo('body'); - $D.dialog({ - modal: true, - autoOpen: false, - close: function(event, ui) { - $(this).dialog('destroy').remove(); - }, - buttons: [ - {text: 'Cancel', click: function(){$D.dialog('close')}}, - {text: 'Delete Organization', click: function(){ - $D.parent().showLoading({"message":"Deleting Organization..."}); - app.model.destroy('adminCustomerOrganizationDetail|'+orgID); //nuke this so the org editor can't be opened for a nonexistant org. - app.ext.admin.calls.adminCustomerOrganizationRemove.init(orgID,{'callback':function(rd){ - $D.parent().hideLoading(); - if(app.model.responseHasErrors(rd)){$D.anymessage({'message':rd})} - else { - $D.anymessage(app.u.successMsgObject('The organization has been removed.')); - $btn.closest('tr').empty().remove(); //remove row in results list. - $D.dialog( "option", "buttons", [ {text: 'Close', click: function(){$D.dialog('close')}} ] ); + execOrganizationRemove : function($ele,P) { + + P.preventDefault(); + var + orgID = $ele.closest('tr').data('orgid'); + $D = _app.ext.admin.i.dialogConfirmRemove({ + message : "Are you sure you want to delete this organization? There is no undo for this action.", + title : "Permanently Remove Organization", + removeButtonText : "Remove", + removeFunction : function() { + $D.parent().showLoading({"message":"Deleting Organization..."}); + _app.model.destroy('adminCustomerOrganizationDetail|'+orgID); //nuke this so the org editor can't be opened for a nonexistant org. + _app.model.addDispatchToQ({ + '_cmd':'adminCustomerOrganizationRemove', + 'ORGID' : orgID, + '_tag': { + 'datapointer' : 'adminCustomerOrganizationRemove', + 'callback':function(rd){ + $D.parent().hideLoading(); + if(_app.model.responseHasErrors(rd)){$D.anymessage({'message':rd})} + else { + $D.empty(); + $D.anymessage(_app.u.successMsgObject('The organization has been removed.')); + $ele.closest('tr').empty().remove(); //remove row in results list. + $D.dialog( "option", "buttons", [ {text: 'Close', click: function(){$D.dialog('close')}} ] ); + } } - }},'immutable'); - app.model.dispatchThis('immutable'); - }} - ] + } + },'immutable'); + _app.model.dispatchThis('immutable'); + + } }); - $D.dialog('open'); - }) + $D.dialog('open'); + }, //execOrganizationRemove - execOrganizationUpdate : function($btn) { - $btn.button(); - $btn.off('click.execOrganizationUpdate').on('click.execOrganizationUpdate',function(event){ - event.preventDefault(); - var - $form = $btn.closest('form'), - sfo = $form.serializeJSON(); - + adminCustomerOrganizationUpdateExec : function($ele,P) { + P.preventDefault(); + var $form = $ele.closest('form'); + if(_app.u.validateForm($form)) { + var sfo = $form.serializeJSON({cb:true}) $form.showLoading({'message':'Saving Changes'}); - sfo.ORGID = $form.data('orgid'); if(sfo.DOMAIN) { - sfo.DOMAIN = app.u.getDomainFromURL(sfo.DOMAIN); //cleans off protocol and www. + sfo.DOMAIN = _app.u.getDomainFromURL(sfo.DOMAIN); //cleans off protocol and www. } -//checkbox values need to be set as 1/0, not ON/OFF - $(':checkbox',$form).each(function(){ - var $CB = $(this); - sfo[$CB.attr('name')] = ($CB.is(':checked')) ? 1 : 0; - }); - - - app.model.destroy('adminCustomerOrganizationDetail|'+sfo.ORGID) - app.ext.admin.calls.adminCustomerOrganizationUpdate.init(sfo,{'callback':function(rd){ - $form.hideLoading(); - if(app.model.responseHasErrors(rd)){$form.anymessage({'message':rd})} - else { - $form.anymessage(app.u.successMsgObject('Your changes have been saved.')); - } - }},'immutable'); - app.model.dispatchThis('immutable'); - }); - }, //execOrganizationUpdate - - - adminOrganizationSearchShowUI : function($btn) { - $btn.button({icons: {primary: "ui-icon-contact"},text: false}); - if($btn.data('searchby') && $btn.data('keywords')) { - $btn.attr('title','Search organizations by '+$btn.data('searchby').toLowerCase()+" for '"+$btn.data('keywords').toLowerCase()+"'"); - $btn.off('click.adminOrganizationSearchShowUI').on('click.adminOrganizationSearchShowUI',function(event){ - //later, maybe we add a data-stickytab to the button and, if true, closest table gets sticky. - app.ext.admin_wholesale.a.showOrganizationManager($(app.u.jqSelector('#',app.ext.admin.vars.tab+"Content")),{'searchby':$btn.data('searchby'),'keywords':$btn.data('keywords')}); - }); + _app.model.destroy('adminCustomerOrganizationDetail|'+sfo.ORGID); + sfo._cmd = 'adminCustomerOrganizationUpdate'; + sfo._tag = { + 'callback' : 'showMessaging', + 'jqObj' : $form, + 'message' : 'Your changes have been saved.' + }; + _app.model.addDispatchToQ(sfo,'immutable'); + _app.model.dispatchThis('immutable'); } else { - $btn.button('disable'); + //validateForm handles error display } - }, - + }, //adminCustomerOrganizationUpdateExec - - priceScheduleUpdateShow : function($btn) { - $btn.button({icons: {primary: "ui-icon-pencil"},text: false}); - $btn.off('click.priceScheduleUpdateShow').on('click.priceScheduleUpdateShow',function(event){ - event.preventDefault(); - var SID = $btn.closest('tr').data('sid'); //schedule id - - var $panel = app.ext.admin.i.DMIPanelOpen($btn,{ - 'templateID' : 'priceScheduleUpdateTemplate', - 'panelID' : 'schedule_'+SID, - 'header' : 'Edit Price Schedule: '+SID, - 'data' : $btn.closest('tr').data() - }); - app.u.handleAppEvents($panel); - $(":checkbox",$panel).anycb(); - app.model.dispatchThis('mutable'); - }); - }, //priceScheduleUpdateShow - - - priceScheduleCreateShow : function($btn) { - $btn.button(); - $btn.off('click.priceScheduleUpdateShow').on('click.priceScheduleUpdateShow',function(event){ - event.preventDefault(); - - var $D = app.ext.admin.i.dialogCreate({ - 'title':'Add New Schedule', - 'showLoading':false //will get passed into anycontent and disable showLoading. - }); - - $D.append("<label>Schedule ID <input type='text' name='SID' value='' \/><\/label><br />"); - - $("<button>Create Schedule<\/button>").button().on('click',function(){ - app.model.addDispatchToQ({ - '_cmd':'adminPriceScheduleCreate', - 'SID': $(this).parent().find("[name='SID']").val(), - '_tag': { - 'callback':'showMessaging', - 'jqObj' : $D, - 'jqObjEmpty' : true, - 'message' : 'Your price schedule has been created.' - } - },'immutable'); - app.model.addDispatchToQ({'_cmd':'adminPriceScheduleList','_tag':{'datapointer':'adminPriceScheduleList','callback':'DMIUpdateResults','extension':'admin','jqObj':$btn.closest("[data-app-role='dualModeContainer']")}},'immutable'); - app.model.dispatchThis('immutable'); - }).appendTo($D); - - $D.dialog('open'); - }); + adminOrganizationSearchShowUI : function($ele,P) { + if($ele.data('searchby') && $ele.data('keywords')) { + navigateTo("#!ext/admin_wholesale/showOrganizationManager",{'searchby':$ele.data('searchby'),'keywords':$ele.data('keywords')}); + } + else { + $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.adminOrganizationSearchShowUI, either searchby ["+$ele.data('searchby')+"] or keywords ["+$ele.data('keywords')+"] not set on trigger element.","gMessage":true}); + } }, - priceScheduleRemoveConfirm : function($btn) { - $btn.button({icons: {primary: "ui-icon-trash"},text: false}); - $btn.off('click.priceScheduleRemoveConfirm').on('click.priceScheduleRemoveConfirm',function(event){ - event.preventDefault(); - - var SID = $btn.closest('tr').data('sid'); - var $D = app.ext.admin.i.dialogConfirmRemove({ - 'message':'Are you sure you want to delete schedule '+SID+'? There is no undo for this action.', - 'removeButtonText' : 'Delete Price Schedule', - 'removeFunction':function(vars,$modal){ - var $panel = $(app.u.jqSelector('#','schedule_'+SID)); - if($panel.length) { - $panel.anypanel('destroy'); //make sure there is no editor for this schedule still open. - } - $btn.closest("[data-app-role='dualModeContainer']").showLoading({"message":"Removing price schedule "+SID}); - app.model.addDispatchToQ({'_cmd':'adminPriceScheduleRemove','SID':SID},'immutable'); - app.model.addDispatchToQ({'_cmd':'adminPriceScheduleList','_tag':{'datapointer':'adminPriceScheduleList','callback':'DMIUpdateResults','extension':'admin','jqObj':$btn.closest("[data-app-role='dualModeContainer']")}},'immutable'); - app.model.dispatchThis('immutable'); - $modal.dialog('close'); - } - }); - }); - }, //execTicketClose - - showOrganizationUpdate : function($btn) { - $btn.button({icons: {primary: "ui-icon-pencil"},text: false}); - $btn.off('click.showOrganizationUpdate').on('click.showOrganizationUpdate',function(event){ - event.preventDefault(); - app.u.dump('showOrganizationUpdate has been triggered.'); - var - $dualModeContainer = $btn.closest("[data-app-role='dualModeContainer']"), - orgID = $btn.closest('tr').data('orgid'); - - app.u.dump('vars have been defined'); - $("[data-app-role='dualModeResultsTable']",$dualModeContainer).hide(); - $("[data-app-role='dualModeDetailContainer']",$dualModeContainer).show(); - app.u.dump('results/content area display changes have occured.'); - app.ext.admin_wholesale.a.showOrganizationEditor($("[data-app-role='dualModeDetailContainer']",$dualModeContainer),{'orgID':orgID}); - app.u.dump('showOrganizationEditor has executed.'); - }); + showOrganizationUpdate : function($ele,P) { + P.preventDefault(); + var orgID = $ele.closest('tr').data('orgid'); + if(orgID) { + navigateTo("#!ext/admin_wholesale/showOrganizationEditor",{'orgID':orgID}); + } + else { + $('#globalMessaging').anymessage({"message":"In admin_wholesale.e.showOrganizationUpdate, unable to ascertain orgID.","gMessage":true}); + } }, //showOrganizationUpdate //triggered within the organization create modal when save is pushed. - execOrganizationCreate : function($btn){ - $btn.button(); - $btn.off('click.execOrganizationCreate').on('click.execOrganizationCreate',function(event) { - event.preventDefault(); - var - $form = $btn.closest('form'), - sfo = $form.serializeJSON(); - - if(app.u.validateForm($form)) { - - $form.showLoading({'message':'Creating New Organization'}); - - if(sfo.DOMAIN) { - sfo.DOMAIN = app.u.getDomainFromURL(sfo.DOMAIN); //cleans off protocol and www. - } - -//checkbox values need to be set as 1/0, not ON/OFF - $(':checkbox',$form).each(function(){ - var $CB = $(this); - sfo[$CB.attr('name')] = ($CB.is(':checked')) ? 1 : 0; - }); - - app.ext.admin.calls.adminCustomerOrganizationCreate.init(sfo,{callback : function(rd){ - $form.hideLoading(); - if(app.model.responseHasErrors(rd)){$form.anymessage({'message':rd})} + execOrganizationCreate : function($ele,P){ + P.preventDefault(); + var + $form = $ele.closest('form'), + sfo = $form.serializeJSON({'cb':true}); + + if(_app.u.validateForm($form)) { + $form.showLoading({'message':'Creating New Organization'}); + if(sfo.DOMAIN) { + sfo.DOMAIN = _app.u.getDomainFromURL(sfo.DOMAIN); //cleans off protocol and www. + } + sfo._cmd = 'adminCustomerOrganizationCreate'; + sfo._tag = { + 'datapointer' : 'adminCustomerOrganizationCreate', + 'callback' : function(rd) { + if(_app.model.responseHasErrors(rd)){ + $form.anymessage({'message':rd}); + } else { - $form.empty().anymessage(app.u.successMsgObject('The organization has been created.')); -// $form.append("<button>Close Window<\/button><button>Edit Organization<\/button><button>Add New Organization<\/button>"); + $form.empty().anymessage(_app.u.successMsgObject('The organization has been saved.')); + $form.append("<h2>What would you like to do next?<\/h2>"); + //sample action. success would go here. + $form.append($("<button>").text('Edit Org').button().on('click',function(){ + $(this).closest('.ui-dialog-content').dialog('close'); + navigateTo("#!ext/admin_wholesale/showOrganizationEditor",{'orgID':_app.data[rd.datapointer].ORGID}); + })); + $form.append($("<button>").text('Back to Org Manager').button().on('click',function(){ + $(this).closest('.ui-dialog-content').dialog('close'); + })); } - }},'immutable'); - app.model.dispatchThis('immutable'); - } - else {} //form validation handles error display. - }); + } + }; + _app.model.addDispatchToQ(sfo,'immutable'); + _app.model.dispatchThis('immutable'); + } + else {} //form validation handles error display. }, //execOrganizationCreate //triggered in the editor to show the organiation create form/modal. - showOrganizationCreate : function($btn) { - $btn.button({icons: {primary: "ui-icon-circle-plus"},text: true}); - $btn.off('click.showOrganizationCreate').on('click.showOrganizationCreate',function(event){ - event.preventDefault(); - -//by now, we know we have a valid mode and if that mode is edit, uuid is set. - var $D = $("<div \/>").attr('title',"Add a New Organization"); -//guid created at time modal is open. that way the guid of an edit can be added in same way and save button won't care if it's an edit or add. - $D.addClass('displayNone').appendTo('body'); -//add the content prior to turning it into a dialog so that width is properly calculated - $D.anycontent({'templateID':'organizationManagerOrgCreateUpdateTemplate','data':{}}); - $D.dialog({ - modal: true, - width: '90%', - autoOpen: false, - close: function(event, ui) { - $(this).dialog('destroy').remove(); - } - }); - $D.dialog('open'); - - $("input",$D).each(function(){ - var $input = $(this); - $input.attr('title',$input.attr('placeholder')); //add the placeholder of the input as the title so mouseover is indicative of what the field wants. - if($input.is(':checkbox')) { - $input.parent().anycb({text : {'on':'yes','off':'no'}}); - } - }); - $('.buttonset',$D).append("<button data-app-event='admin_wholesale|execOrganizationCreate'>Create Organization</button>"); - app.u.handleAppEvents($D); - + showOrganizationCreate : function($ele,P) { + P.preventDefault(); + var $D = _app.ext.admin.i.dialogCreate({ + title : "Add a New Organization", + anycontent : true, //the dialogCreate params are passed into anycontent + handleAppEvents : false //defaults to true }); + $D.anycontent({'templateID':'organizationManagerOrgCreateUpdateTemplate','data':{}}).anyform(); + $('.buttonset',$D).append("<button data-app-click='admin_wholesale|execOrganizationCreate' class='applyButton'>Create Organization</button>"); + $D.dialog('open'); + _app.u.handleCommonPlugins($D); + _app.u.handleButtons($D); } //showOrganizationCreate + }, //e [app Events] diff --git a/extensions/cart_checkout_order.js b/extensions/cart_checkout_order.js index f51644ea2..ed8e960be 100644 --- a/extensions/cart_checkout_order.js +++ b/extensions/cart_checkout_order.js @@ -16,12 +16,11 @@ -The intention of this extension is to replace store_checkout and store_cart, since there's a lot of redundant code between them. - ************************************************************** */ -//SCO = Shared Checkout Object -var cco = function() { +//CCO = Cart, Checkout and Orders. Lots of shared code across these three areas. +var cco = function(_app) { var r = { + vars : {}, //////////////////////////////////// CALLS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ /* @@ -29,87 +28,125 @@ unlike other extensions, checkout calls rarely do a 'fetchData'. The thought her calls should always return the number of dispatches needed. allows for cancelling a dispatchThis if not needed. so in most of these, a hard return of 1 is set. -initially, this extension auto-executed. Later, after callbacks were added to the extension object -the startCheckout call was added, which contains the code that was auto-executed as part of the INIT callback. -a callback was also added which just executes this call, so that checkout COULD be auto-started onload. */ calls : { //formerly getCheckoutDestinations appCheckoutDestinations : { - init : function(_tag,Q) { - this.dispatch(_tag,Q); - return 1; + init : function(cartID,_tag,Q) { + var r = 0; + if(cartID) { + this.dispatch(cartID,_tag,Q); + r = 1; + } + else { + $('#globalMessaging').anymessage({"message":"In cco.calls.appCheckoutDestinations, cartID not passed and is required.","gMessage":true}); + } + return r; }, - dispatch : function(_tag,Q) { + dispatch : function(cartID,_tag,Q) { _tag = _tag || {}; - _tag.datapointer = 'appCheckoutDestinations'; - app.model.addDispatchToQ({"_cmd":"appCheckoutDestinations","_tag": _tag},Q || 'immutable'); + _tag.datapointer = 'appCheckoutDestinations|'+cartID; + _app.model.addDispatchToQ({"_cmd":"appCheckoutDestinations","_tag": _tag,"_cartid":cartID},Q || 'immutable'); } }, //appCheckoutDestinations appPaymentMethods : { init : function(obj,_tag,Q) { - this.dispatch(obj,_tag,Q); //obj could contain country (as countrycode) and order total. - return 1; + var r = 0; + if(obj._cartid) { +// _app.u.dump(" -> appPaymentMethods cartID: "+obj._cartid); + this.dispatch(obj,_tag,Q); //obj could contain country (as countrycode) and order total. + r = 1; + } + else { + $('#globalMessaging').anymessage({"message":"In cco.calls.appPaymentMethods, obj._cartid was not passed and is required.","gMessage":true}); + } + + return r; }, dispatch : function(obj,_tag,Q) { obj._cmd = "appPaymentMethods"; obj._tag = _tag || {}; - obj._tag.datapointer = 'appPaymentMethods'; - app.model.addDispatchToQ(obj,Q || 'immutable'); + obj._tag.datapointer = 'appPaymentMethods|'+obj._cartid; + _app.model.addDispatchToQ(obj,Q || 'immutable'); } }, //appPaymentMethods cartCouponAdd : { - init : function(coupon,_tag,Q) { - this.dispatch(coupon,_tag,Q); - }, - dispatch : function(coupon,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"cartCouponAdd","coupon":coupon,"_tag" : _tag},Q || 'immutable'); + init : function(coupon,cartid,_tag,Q) { + _app.model.addDispatchToQ({"_cmd":"cartCouponAdd","_cartid":cartid,"coupon":coupon,"_tag" : _tag},Q || 'immutable'); } }, //cartCouponAdd cartGiftcardAdd : { - init : function(giftcard,_tag,Q) { - this.dispatch(giftcard,_tag,Q); - }, - dispatch : function(giftcard,_tag,Q) { - app.model.addDispatchToQ({"_cmd":"cartGiftcardAdd","giftcard":giftcard,"_tag" : _tag},Q || 'immutable'); + init : function(giftcard,cartid,_tag,Q) { + _app.model.addDispatchToQ({"_cmd":"cartGiftcardAdd","_cartid":cartid,"giftcard":giftcard,"_tag" : _tag},Q || 'immutable'); } }, //cartGiftcardAdd //can be used to verify the items in the cart have inventory available. cartItemsInventoryVerify : { - init : function(_tag,Q) { - this.dispatch(_tag,Q); - return 1; + init : function(cartid,_tag,Q) { + var r = 0; + if(cartid) { + this.dispatch(cartid,_tag,Q); + r = 1; + } + else { + $('#globalMessaging').anymessage({'message':'In calls.cartItemsInventoryVerify, no cartid passed.','gMessage':true}); + } + return r; }, - dispatch : function(_tag,Q) { + dispatch : function(cartid,_tag,Q) { _tag = _tag || {}; - _tag.datapointer = "cartItemsInventoryVerify"; - app.model.addDispatchToQ({"_cmd":"cartItemsInventoryVerify","_tag": _tag},Q || 'immutable'); + _tag.datapointer = "cartItemsInventoryVerify|"+cartid; + _app.model.addDispatchToQ({"_cmd":"cartItemsInventoryVerify","_cartid":cartid,"_tag": _tag},Q || 'immutable'); } }, //cartItemsInventoryVerify -// REMOVE from controller when this extension deploys !!! + cartItemAppend : { + init : function(obj,_tag) { + var r = 0; + if(obj && obj.sku && obj.qty && obj._cartid) { + obj.uuid = _app.u.guidGenerator(); + this.dispatch(obj,_tag); + r = 1; + } + else { + $('#globalMessaging').anymessage({'message':'Qty ['+obj.qty+'] or SKU ['+obj.sku+'] or _cartid ['+obj._cartid+'] left blank in cartItemAppend.'}); + _app.u.dump(" -> cartItemAppend obj param follows:"); _app.u.dump(obj); + } + + return r; + }, + dispatch : function(obj,_tag){ + obj._tag = _tag; + obj._cmd = "cartItemAppend"; + _app.model.addDispatchToQ(obj,'immutable'); + } + }, //cartItemAppend + cartItemUpdate : { - init : function(stid,qty,_tag) { -// app.u.dump('BEGIN app.calls.cartItemUpdate.'); + init : function(vars,_tag) { +// _app.u.dump('BEGIN _app.calls.cartItemUpdate.'); var r = 0; - if(stid && Number(qty) >= 0) { + vars = vars || {}; + if(vars.stid && Number(vars.quantity) >= 0) { r = 1; - this.dispatch(stid,qty,_tag); + this.dispatch(vars,_tag); } else { - app.u.throwGMessage("In calls.cartItemUpdate, either stid ["+stid+"] or qty ["+qty+"] not passed."); + _app.u.throwGMessage("In cco.calls.cartItemUpdate, either stid ["+vars.stid+"] or qty ["+vars.quantity+"] not passed."); } return r; }, - dispatch : function(stid,qty,_tag) { -// app.u.dump(' -> adding to PDQ. callback = '+callback) - app.model.addDispatchToQ({"_cmd":"cartItemUpdate","stid":stid,"quantity":qty,"_tag": _tag},'immutable'); - app.ext.cco.u.nukePayPalEC(); //nuke paypal token anytime the cart is updated. + dispatch : function(vars,_tag) { +// _app.u.dump(' -> adding to PDQ. callback = '+callback) + vars._cmd = "cartItemUpdate"; + vars._tag = _tag; + _app.model.addDispatchToQ(vars,'immutable'); + _app.ext.cco.u.nukePayPalEC(); //nuke paypal token anytime the cart is updated. } }, //cartItemUpdate @@ -118,45 +155,54 @@ a callback was also added which just executes this call, so that checkout COULD cartPaymentQ : { init : function(cmdObj,_tag) { //make sure id is set for inserts. - if(cmdObj.cmd == 'insert' && !cmdObj.ID) {cmdObj.ID = app.model.version+app.u.guidGenerator().substring(0,8)} + if(cmdObj.cmd == 'insert' && !cmdObj.ID) {cmdObj.ID = _app.model.version+_app.u.guidGenerator().substring(0,8)} cmdObj['_cmd'] = "cartPaymentQ"; cmdObj['_tag'] = _tag; this.dispatch(cmdObj); return 1; }, dispatch : function(cmdObj) { - app.model.addDispatchToQ(cmdObj,'immutable'); + _app.model.addDispatchToQ(cmdObj,'immutable'); } }, //cartPaymentQ -// REMOVE from controller when this extension deploys !!! + cartSet : { init : function(obj,_tag,Q) { - this.dispatch(obj,_tag,Q); - return 1; - }, - dispatch : function(obj,_tag,Q) { +// if(obj._cartid && _app.u.thisNestedExists('ext.cart_message.vars.carts.'+obj._cartid,_app)) { +// _app.model.addDispatchToQ({'_cmd':'cartMessagePush','what':'cart.update','_cartid':obj._cartid},'immutable'); +// } obj["_cmd"] = "cartSet"; obj._tag = _tag || {}; - app.model.addDispatchToQ(obj,Q || 'immutable'); + _app.model.addDispatchToQ(obj,Q || 'immutable'); + return 1; } }, //cartSet - +/* +201403 -> this is no longer necessary. this call is inline. //uses the cart ID, which is passed on the parent/headers. //always immutable. cartOrderCreate : { - init : function(_tag) { - this.dispatch(_tag); - return 1; + init : function(cartID,_tag) { + var r = 0; + if(cartID) { + r = 1; + this.dispatch(cartID,_tag); + } + else { + $('#globalMessaging').anymessage({"message":"In cco.calls.cartOrderCreate, no cart ID passed.","gMessage":true}); + } + return r; }, - dispatch : function(_tag) { + dispatch : function(cartID,_tag) { _tag = _tag || {}; _tag.datapointer = "cartOrderCreate"; - app.model.addDispatchToQ({'_cmd':'cartOrderCreate','_tag':_tag,'iama':app.vars.passInDispatchV},'immutable'); + // ### FUTURE -> domain being passed here is a temporary fix until email update occurs. only gets passed on admin. + _app.model.addDispatchToQ({'_cartid':cartID,'_cmd':'cartOrderCreate','_tag':_tag,'iama':_app.vars.passInDispatchV, 'domain' : (_app.vars.thisSessionIsAdmin ? 'www.'+_app.vars.domain : '')},'immutable'); } },//cartOrderCreate - +*/ cartPaypalSetExpressCheckout : { init : function(obj,_tag,Q) { @@ -168,14 +214,14 @@ a callback was also added which just executes this call, so that checkout COULD obj._tag = _tag || {}; var parentID = obj._tag.parentID || ''; var extras = ""; - if(window.debug1pc) {extras = "&sender=jcheckout&fl=checkout-"+app.model.version+debug1pc} //set debug1pc to a,p or r in console to force this versions 1pc layout on return from paypal + if(window.debug1pc) {extras = "&sender=jcheckout&fl=checkout-"+_app.model.version+debug1pc} //set debug1pc to a,p or r in console to force this versions 1pc layout on return from paypal obj._cmd = "cartPaypalSetExpressCheckout"; - obj.cancelURL = (app.vars._clientid == '1pc') ? zGlobals.appSettings.https_app_url+"c="+app.vars.cartID+"/cart.cgis?parentID="+parentID+extras : zGlobals.appSettings.https_app_url+"?_session="+app.vars._session+"parentID="+parentID+"&cartID="+app.vars.cartID+"#cart?show=inline"; - obj.returnURL = (app.vars._clientid == '1pc') ? zGlobals.appSettings.https_app_url+"c="+app.vars.cartID+"/checkout.cgis?parentID="+parentID+extras : zGlobals.appSettings.https_app_url+"?_session="+app.vars._session+"parentID="+parentID+"&cartID="+app.vars.cartID+"#checkout?show=checkout"; + obj.cancelURL = (_app.vars._clientid == '1pc') ? zGlobals.appSettings.https_app_url+"c="+_app.model.fetchCartID()+"/cart.cgis?parentID="+parentID+extras : zGlobals.appSettings.https_app_url+"?_session="+_app.vars._session+"&parentID="+parentID+"&cartID="+_app.model.fetchCartID()+"#!cart"; + obj.returnURL = (_app.vars._clientid == '1pc') ? zGlobals.appSettings.https_app_url+"c="+_app.model.fetchCartID()+"/checkout.cgis?parentID="+parentID+extras : zGlobals.appSettings.https_app_url+"?_session="+_app.vars._session+"&parentID="+parentID+"&cartID="+_app.model.fetchCartID()+"#!checkout?"; //? at end because paypal is going to add key value pairs to this url. obj._tag.datapointer = "cartPaypalSetExpressCheckout"; - - app.model.addDispatchToQ(obj,Q || 'immutable'); +// dump(" -> cartPaypalSetExpressCheckout obj: "); dump(obj); + _app.model.addDispatchToQ(obj,Q || 'immutable'); } }, //cartPaypalSetExpressCheckout @@ -198,11 +244,11 @@ left them be to provide guidance later. return 1; }, dispatch : function() { - app.model.addDispatchToQ({ + _app.model.addDispatchToQ({ "_cmd":"cartGoogleCheckoutURL", "analyticsdata":"", //must be set, even if blank. - "edit_cart_url" : (app.vars._clientid == '1pc') ? zGlobals.appSettings.https_app_url+"c="+app.vars.cartID+"/cart.cgis" : zGlobals.appSettings.https_app_url+"?cartID="+app.vars.cartID+"#cart?show=cart", - "continue_shopping_url" : (app.vars._clientid == '1pc') ? zGlobals.appSettings.https_app_url+"c="+app.vars.cartID+"/" : zGlobals.appSettings.https_app_url+"?cartID="+app.vars.cartID, + "edit_cart_url" : (_app.vars._clientid == '1pc') ? zGlobals.appSettings.https_app_url+"c="+_app.model.fetchCartID()+"/cart.cgis" : zGlobals.appSettings.https_app_url+"?cartID="+_app.model.fetchCartID()+"#cart?show=cart", + "continue_shopping_url" : (_app.vars._clientid == '1pc') ? zGlobals.appSettings.https_app_url+"c="+_app.model.fetchCartID()+"/" : zGlobals.appSettings.https_app_url+"?cartID="+_app.model.fetchCartID(), '_tag':{'callback':'proceedToGoogleCheckout','extension':'cco','datapointer':'cartGoogleCheckoutURL'} },'immutable'); } @@ -215,11 +261,11 @@ left them be to provide guidance later. return 1; }, dispatch : function() { - var tagObj = {'callback':'',"datapointer":"cartAmazonPaymentURL","extension":"store_cart"} - app.model.addDispatchToQ({ + var tagObj = {'callback':'',"datapointer":"cartAmazonPaymentURL","extension":"cco"} + _app.model.addDispatchToQ({ "_cmd":"cartAmazonPaymentURL", "shipping":1, -"CancelUrl":zGlobals.appSettings.https_app_url+"cart.cgis?cartID="+app.vars.cartID, +"CancelUrl":zGlobals.appSettings.https_app_url+"cart.cgis?cartID="+_app.model.fetchCartID(), "ReturnUrl":zGlobals.appSettings.https_app_url, "YourAccountUrl": zGlobals.appSettings.https_app_url+"customer/orders/", '_tag':tagObj},'immutable'); @@ -245,25 +291,48 @@ left them be to provide guidance later. return true; //returns false if checkout can't load due to account config conflict. }, onError : function() { - app.u.dump('BEGIN app.ext.orderCreate.callbacks.init.error'); + _app.u.dump('BEGIN _app.ext.order_create.callbacks.init.error'); //This would be reached if a templates was not defined in the view. } }, //init +//display the '%changes', but make no adjustments to the cart. +//can be used in store, but was built for admin UI where a merchant may want to oversell. +//the checkout extension has a callback for adjusting the inventory based on availability. + adminInventoryDiscrepencyDisplay : { + onSuccess : function(_rtag) { + _rtag.jqObj = _rtag.jqObj || $('#globalMessaging'); + if(!$.isEmptyObject(_app.data[_rtag.datapointer]['%changes'])) { + var msgObj = {} + msgObj.message = "Inventory not available (manual corrections may be needed):<ul>"; + for(var key in _app.data[_rtag.datapointer]['%changes']) { + msgObj.message += "<li>sku: "+key+" shows only "+_app.data[rd.datapointer]['%changes'][key]+" available<\/li>"; + } + msgObj.message += "<\/ul>"; + msgObj.persistent = true; + msgObj.errtype = 'halt'; + _rtag.jqObj.anymessage(msgObj); + } + else { + //there were no 'changes'. + } + } + }, +// TODO - deprecate google checkout proceedToGoogleCheckout : { onSuccess : function(tagObj) { - app.u.dump('BEGIN cco.callbacks.proceedToGoogleCheckout.onSuccess'); + _app.u.dump('BEGIN cco.callbacks.proceedToGoogleCheckout.onSuccess'); //code for tracking the google wallet payment in GA as a conversion. - _gaq.push(function() { - var pageTracker = _gaq._getAsyncTracker(); - setUrchinInputCode(pageTracker); - }); + //_gaq.push(function() { + // var pageTracker = _gaq._getAsyncTracker(); + // setUrchinInputCode(pageTracker); + // }); //getUrchinFieldValue is defined in the ga_post.js file. It's included as part of the google analytics plugin. - document.location= app.data[tagObj.datapointer].URL +"&analyticsdata="+getUrchinFieldValue(); + document.location= _app.data[tagObj.datapointer].URL +"&analyticsdata="+getUrchinFieldValue(); }, onError : function(responseData,uuid) { $('#chkoutPlaceOrderBtn').removeAttr('disabled').removeClass('ui-state-disabled'); // re-enable checkout button on checkout page. - app.u.throwMessage(responseData,uuid); + _app.u.throwMessage(responseData,uuid); } } }, //callbacks @@ -274,20 +343,24 @@ left them be to provide guidance later. //this will make sure that specific fields are populated based on tender type. //rather than returning specific error messages (which may need to change based on where this is used, an array of which fields are missing is returned //plus, this allows for the attribute/fields to be modified w/ css, whereas returning messages wouldn't allow for that. +//a 'false' returned means everything passed. +// ## FUTURE -> get these migrated into validateForm. validate : { CREDIT : function(vars) { if(vars && typeof vars == 'object') { var errors = new Array(); // what is returned. an array of the payment fields that are not correct. - if(vars['payment/CC'] && app.u.isValidCC(vars['payment/CC'])) {} else {errors.push("payment/CC");} - if(vars['payment/MM'] && app.u.isValidMonth(vars['payment/MM'])) {} else {errors.push("payment/MM");} - if(vars['payment/YY'] && app.u.isValidCCYear(vars['payment/YY'])) {} else {errors.push("payment/YY");} - if(vars['payment/CV'] && vars['payment/CV'].length > 2){} else {errors.push("payment/CV")} + if(vars['payment/CC'] && _app.u.isValidCC(vars['payment/CC'])) {} else {errors.push("payment/CC");} + if(vars['payment/MM'] && _app.u.isValidMonth(vars['payment/MM'])) {} else {errors.push("payment/MM");} + if(vars['payment/YY'] && _app.u.isValidCCYear(vars['payment/YY'])) {} else {errors.push("payment/YY");} + if(!_app.vars.thisSessionIsAdmin) { + if(vars['payment/CV'] && vars['payment/CV'].length > 2){} else {errors.push("payment/CV")} + } return (errors.length) ? errors : false; } else { - app.u.throwGMessage("in cco.u.validate.CREDIT, vars is empty or not an object."); - return false; + $('#globalMessaging').anymessage({"message":"in cco.u.validate.CREDIT, vars is empty or not an object.","gMessage":true}); + return true; } }, @@ -311,56 +384,116 @@ left them be to provide guidance later. }, //validate + a : { + //for a 'complete' event, add it to the $cart object returned by this function. It'll be executed after a fetch or a refresh. + getCartAsJqObj : function(vars) { + vars = vars || {}; + var r; //what is returned. + if(vars.templateID && vars.cartid) { + var $cart = $(_app.renderFunctions.createTemplateInstance(vars.templateID,vars)); + $cart.attr('data-template-role','cart'); + +//will fetch an entirely new copy of the cart from the server. +//still requires a dispatch be sent OUTSIDE this + $cart.on('fetch.cart',function(event,P){ + var $c = $(this); P = P || {}; + $c.showLoading({'message':'Updating cart contents'}); + _app.model.destroy('cartDetail|'+$c.data('cartid')); + _app.calls.cartDetail.init($c.data('cartid'),{ + 'callback':'tlc', + 'before' : function(r) { + r.jqObj.empty(); + }, + 'onComplete' : function(r){ + P.state = 'complete'; + _app.renderFunctions.handleTemplateEvents(r.jqObj,$.extend(true,{},P,event)); + }, + 'templateID' : $c.data('templateid'), + 'jqObj' : $c + },P.Q); + }); +//will update the cart based on what's in memory. + $cart.on('refresh.cart',function(event,P){ + var $c = $(this); P = P || {}; + $c.intervaledEmpty(); + if($c.data('tlc')) {$c.tlc('destroy')} + //w/ no destroy here, refresh will use what's in memory IF it's available. If not, it will fetch the cart. + _app.calls.cartDetail.init($c.data('cartid'),{ + 'callback':'tlc', + 'onComplete' : function(){ + P.state = 'complete'; + _app.renderFunctions.handleTemplateEvents($c,$.extend(true,{},P,event)); + }, + 'templateID' : $c.data('templateid'), + 'jqObj' : $c + },'mutable'); + _app.model.dispatchThis('mutable'); + }); + r = $cart; + } + else { + r = $("<div>").anymessage({'message':'In cco.a.getCartAsJqObj, vars.templateID ['+vars.templateID+'] and/or vars.cartid ['+vars.cartid+'] not specified. Both are required.','gMessage':true}); + } + + return r; + } + + }, + //////////////////////////////////// util [u] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ u : { -//NOTE TO SELF: -//use if/elseif for payments with special handling (cc, po, etc) and then the else should handle all the other payment types. -//that way if a new payment type is added, it's handled (as long as there's no extra inputs). - buildPaymentQ : function($form) { - app.u.dump("BEGIN cco.u.buildPaymentQ"); - var sfo = $form.serializeJSON() || {}, - payby = sfo["want/payby"]; - app.u.dump(" -> payby: "+payby); - if(payby) { - if(payby.indexOf('WALLET') == 0) { - app.ext.cco.calls.cartPaymentQ.init($.extend({'cmd':'insert'},app.ext.cco.u.getWalletByID(payby))); - } - else if(payby == 'CREDIT') { - app.ext.cco.calls.cartPaymentQ.init({"cmd":"insert","TN":"CREDIT","CC":sfo['payment/CC'],"CV":sfo['payment/CV'],"YY":sfo['payment/YY'],"MM":sfo['payment/MM']}); - } - else if(payby == 'PO') { - app.ext.cco.calls.cartPaymentQ.init({"cmd":"insert","TN":"PO","PO":sfo['payment/PO']}); - } - else if(payby == 'ECHECK') { - app.ext.cco.calls.cartPaymentQ.init({ - "cmd":"insert", - "TN":"ECHECK", - "EA":sfo['payment/EA'], - "ER":sfo['payment/ER'], - "EN":sfo['payment/EN'], - "EB":sfo['payment/EB'], - "ES":sfo['payment/ES'], - "EI":sfo['payment/EI'] - }); + getPaymentQArray : function($form,cartid){ + var payments = new Array(); +// _app.u.dump(" -> payby: "+payby); + if($form instanceof jQuery && cartid) { + var sfo = $form.serializeJSON() || {}, payby = sfo["want/payby"]; + if(payby) { + if(payby.indexOf('WALLET') == 0) { + payments.push("insert?TN=WALLET&"+_app.u.hash2kvp(_app.ext.cco.u.getWalletByID(payby,cartid))); + } + else if(payby == 'CREDIT') { + payments.push("insert?TN=CREDIT&CC="+encodeURIComponent(sfo['payment/CC'])+"&CV="+encodeURIComponent(sfo['payment/CV'])+"&YY="+encodeURIComponent(sfo['payment/YY'])+"&MM="+encodeURIComponent(sfo['payment/MM'])); + } + else if(payby == 'PO') { + payments.push("insert?TN=PO&PO="+encodeURIComponent(sfo['payment/PO'])); + } + else if(payby == 'ECHECK') { + payments.push("insert?TN=ECHECK" + +"&EA"+encodeURIComponent(sfo['payment/EA']) + +"&ER"+encodeURIComponent(sfo['payment/ER']) + +"&EN"+encodeURIComponent(sfo['payment/EN']) + +"&EB"+encodeURIComponent(sfo['payment/EB']) + +"&ES"+encodeURIComponent(sfo['payment/ES']) + +"&EI"+encodeURIComponent(sfo['payment/Ei']) + ); + } + else { + payments.push("insert?TN="+encodeURIComponent(payby)); + } + r = true; } else { - app.ext.cco.calls.cartPaymentQ.init({"cmd":"insert","TN":payby }); + //it is valid for no payby to be set. This could happen for a zero balance order. +// $form.anymessage({'message':'In cco.u.buildPaymentQ, unable to determine payby value','gMessage':true}); } } - else { - $('#globalMessaging').anymessage({'message':'In cco.u.buildPaymentQ, unable to determine payby value','gMessage':true}); - } + else { + payments = false; + $("#globalMessaging").anymessage({'message':'In cco.u.getPaymentQArray, either form was not a valid jquery instance ['+($form instanceof jQuery)+'] or no cart id ['+cartid+'] was passed.','gMessage':true}); + } + return payments; }, + paymentMethodsIncludesGiftcard : function(datapointer) { var r = false; - if(app.data[datapointer] && app.data[datapointer]['@methods'] && app.data[datapointer]['@methods'].length) { - var payMethods = app.data[datapointer]['@methods'], - L = app.data[datapointer]['@methods'].length; + if(_app.data[datapointer] && _app.data[datapointer]['@methods'] && _app.data[datapointer]['@methods'].length) { + var payMethods = _app.data[datapointer]['@methods'], + L = _app.data[datapointer]['@methods'].length; for(var i = 0; i < L; i += 1) { if(payMethods[i].id.indexOf('GIFTCARD:') === 0) { @@ -370,7 +503,7 @@ left them be to provide guidance later. } } else { - //app.data.datapointer is empty + //_app.data.datapointer is empty } return r; }, @@ -379,10 +512,9 @@ left them be to provide guidance later. //A simple check to make sure that all the required inputs are populated for a given address. //returns boolean //this is used in checkout for pre-existing addresses, to make sure they're complete. - verifyAddressIsComplete : function(addressType,addressID) { + verifyAddressIsComplete : function(addrObj,addressType) { var r = true; - if(addressType && addressID) { - var addrObj = app.ext.cco.u.getAddrObjByID(addressType,addressID); + if(typeof addrObj === 'object') { if(!addrObj[addressType+'/address1']) {r = false} else if(!addrObj[addressType+'/city']) {r = false} else if(!addrObj[addressType+'/countrycode']) {r = false} @@ -396,7 +528,7 @@ left them be to provide guidance later. } else { r = false; - $('#globalMessaging').anymessage({'message':'In cco.u.verifyAddressIsComplete, either addressType ['+addressType+'] or addressID ['+addressID+'] not set','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In cco.u.verifyAddressIsComplete, addrObj is not an object [typeof: '+(typeof addrObj)+']','gMessage':true}); } return r; }, @@ -406,41 +538,47 @@ left them be to provide guidance later. buyerHasPredefinedAddresses : function(TYPE) { var r; //What is returned. TFU. U = unknown (no TYPE) if(TYPE) { - if(app.data.buyerAddressList && !$.isEmptyObject(app.data.buyerAddressList['@'+TYPE])) {r = true} + if(_app.data.buyerAddressList && !$.isEmptyObject(_app.data.buyerAddressList['@'+TYPE])) {r = true} else {r = false} } return r; }, //will get the items from a cart and return them as links. used for social marketing. - cartContentsAsLinks : function(datapointer) { -// app.u.dump('BEGIN cco.u.cartContentsAsLinks.'); -// app.u.dump(' -> datapointer = '+datapointer); - var r = ""; - var L = app.model.countProperties(app.data.cartDetail['@ITEMS']); -// app.u.dump(' -> # items in cart: '+L); - for(var i = 0; i < L; i += 1) { -//skip coupons. - if(app.data[datapointer]['@ITEMS'][i].sku[0] != '%') { - r += "http://"+app.vars.sdomain+"/product/"+app.data[datapointer]['@ITEMS'][i].sku+"/\n"; + cartContentsAsLinks : function(cartObj) { +// _app.u.dump('BEGIN cco.u.cartContentsAsLinks.'); +// _app.u.dump(' -> datapointer = '+datapointer); + var r = false; + if(!$.isEmptyObject(cartObj)) { + var items = cartObj['@ITEMS'] || [], L = items.length; + //generally, we want to direct traffic to the non-secure domain first. That option will also be better for a native app which has no document.domain + var domain = (_app.vars.domain) ? 'http://'+_app.vars.domain : document.location.protocol+'//'+document.domain + if(L) {r = ''}; //set to blank so += doesn't start with undefined. + for(var i = 0; i < L; i += 1) { + //if the first character of a sku is a %, then it's a coupon, not a product. + if(items[i].sku.charAt(0) != '%') { + r += (_app.vars._clientid == '1pc') ? domain+"/product/"+items[i].sku+"/\n" : domain+"#!product/"+items[i].sku+"/\n"; + } } } -// app.u.dump('links = '+r); + else { + $('#globalMessaging').anymessage({'message':'In cco.u.cartContentsAsLinks, either cartid ['+cartid+'] not passed or the cart detail is not in memory.','gMessage':true}); + } return r; }, //cartContentsAsLinks //This will tell if there's a paypal tender in the paymentQ. doesn't check validity or anything like that. a quick function to be used when re-rendering panels. thisSessionIsPayPal : function() { - return (this.modifyPaymentQbyTender('PAYPALEC',null)) ? true : false; + return (this.modifyPaymentQbyTender('PAYPALEC',null,_app.model.fetchCartID())) ? true : false; }, //Will check the payment q for a valid paypal transaction. Used when a buyer leaves checkout and returns during the checkout init process. //according to B, there will be only 1 paypal tender in the paymentQ. aValidPaypalTenderIsPresent : function() { -// app.u.dump("BEGIN cco.aValidPaypalTenderIsPresent"); +// _app.u.dump("BEGIN cco.aValidPaypalTenderIsPresent"); return this.modifyPaymentQbyTender('PAYPALEC',function(PQI){ return (Math.round(+new Date(PQI.TIMESTAMP)) > +new Date()) ? true : false; - }); + },_app.model.fetchCartID()); }, /* once paypalEC has been approved by paypal, a lot of form fields lock down, but the user may decide to change @@ -448,13 +586,13 @@ payment methods or they may add something new to the cart. If they do, execute t note - dispatch isn't IN the function to give more control to developer. (you may want to execute w/ a group of updates) */ nukePayPalEC : function(_tag) { -// app.u.dump("BEGIN cco.u.nukePayPalEC"); - app.ext.orderCreate.vars['payment-pt'] = null; - app.ext.orderCreate.vars['payment-pi'] = null; +// _app.u.dump("BEGIN cco.u.nukePayPalEC"); + _app.ext.order_create.vars['payment-pt'] = null; + _app.ext.order_create.vars['payment-pi'] = null; return this.modifyPaymentQbyTender('PAYPALEC',function(PQI){ //the delete cmd will reset want/payby to blank. - app.ext.cco.calls.cartPaymentQ.init({'cmd':'delete','ID':PQI.ID},_tag || {'callback':'suppressErrors'}); //This kill process should be silent. - }); + _app.ext.cco.calls.cartPaymentQ.init({'cmd':'delete','ID':PQI.ID},_tag || {'callback':'suppressErrors'}); //This kill process should be silent. + },_app.model.fetchCartID()); }, //pass in a tender/TN [CASH, PAYPALEC, CREDIT] and an array of matching id's is returned. @@ -462,23 +600,22 @@ note - dispatch isn't IN the function to give more control to developer. (you ma //if someFunction is set then that function will get executed over each match. //the value returned gets added to an array, which is returned by this function. //the entire lineitem in the paymentQ is passed in to someFunction. - modifyPaymentQbyTender : function(tender,someFunction){ -// app.u.dump("BEGIN cco.u.modifyPaymentQbyTender"); + modifyPaymentQbyTender : function(tender,someFunction,cartID){ +// _app.u.dump("BEGIN cco.u.modifyPaymentQbyTender"); var inc = 0, //what is returned if someFunction not present. # of items in paymentQ affected. r = new Array(), //what is returned if someFunction returns anything. returned; //what is returned by this function. - - if(tender && app.data.cartDetail && app.data.cartDetail['@PAYMENTQ']) { - if(app.data.cartDetail['@PAYMENTQ'].length) { - // app.u.dump(" -> all vars present. tender: "+tender+" and typeof someFunction: "+typeof someFunction); - var L = app.data.cartDetail['@PAYMENTQ'].length; - // app.u.dump(" -> paymentQ.length: "+L); + if(tender && cartID && _app.u.thisNestedExists("data.cartDetail|"+cartID+".@PAYMENTQ",_app)) { + if(_app.data['cartDetail|'+cartID]['@PAYMENTQ'].length) { + // _app.u.dump(" -> all vars present. tender: "+tender+" and typeof someFunction: "+typeof someFunction); + var L = _app.data['cartDetail|'+cartID]['@PAYMENTQ'].length; + // _app.u.dump(" -> paymentQ.length: "+L); for(var i = 0; i < L; i += 1) { - // app.u.dump(" -> "+i+" TN: "+app.data.cartDetail['@PAYMENTQ'][i].TN); - if(app.data.cartDetail['@PAYMENTQ'][i].TN == tender) { + // _app.u.dump(" -> "+i+" TN: "+_app.data.cartDetail['@PAYMENTQ'][i].TN); + if(_app.data['cartDetail|'+cartID]['@PAYMENTQ'][i].TN == tender) { inc += 1; if(typeof someFunction == 'function') { - r.push(someFunction(app.data.cartDetail['@PAYMENTQ'][i])) + r.push(someFunction(_app.data['cartDetail|'+cartID]['@PAYMENTQ'][i])) } } } @@ -489,20 +626,46 @@ note - dispatch isn't IN the function to give more control to developer. (you ma } //paymentQ is empty. no error or warning. } else { - app.u.dump("WARNING! getPaymentQidByTender failed because tender ["+tender+"] not set or @PAYMENTQ does not exist."); + _app.u.dump("WARNING! modifyPaymentQbyTender failed because tender ["+tender+"] or cartID ["+cartID+"] not set or @PAYMENTQ does not exist."); } -// app.u.dump(" -> num tender matches: "+r); +// _app.u.dump(" -> num tender matches: "+r); return returned; }, +//used in admin. adminBuyerGet formats address w/ ship_ or bill_ instead of ship/ or bill/ +// addrArr is is the customerGet (for either @ship or @bill). ID is the ID/Shortcut of the method selected/desired. + getAndRegularizeAddrObjByID : function(addrArr,ID,type,regularize) { +// dump("BEGIN cco.u.getAndRegularizeAddrObjByID. regularize: "+regularize); + var r = false; //what is returned. + if(typeof addrArr == 'object' && ID && type) { + var address = $.extend({},addrArr[_app.ext.admin.u.getIndexInArrayByObjValue(addrArr,'_id',ID)]); //COPY array so original in memory is unaffected. + if(regularize) { +// dump(" -> got into the regularize code. if any conversions occur, they'll be listed below: "); + for(var index in address) { + if(index.indexOf(type+'_') >= 0) { +// dump(" ----> converting "+index+" to "+index.replace(type+'_',type+'/')); + address[index.replace(type+'_',type+'/')] = address[index]; + delete address[index]; + } + } + } + r = address; + } + else { + $('#globalMessaging').anymessage({'message':"In cco.u.getAndRegularizeAddrObjByID, id ["+ID+"] and/or type ["+type+"] not passed or addrArr not an object ["+(typeof addrArr)+"].",'gMessage':true}); + } + return r; + + }, + getAddrObjByID : function(type,id) { var r = false; //what is returned. if(type && id) { - if(app.data.buyerAddressList && app.data.buyerAddressList['@'+type] && app.data.buyerAddressList['@'+type].length) { - var L = app.data.buyerAddressList['@'+type].length; + if(_app.data.buyerAddressList && _app.data.buyerAddressList['@'+type] && _app.data.buyerAddressList['@'+type].length) { + var L = _app.data.buyerAddressList['@'+type].length; for(var i = 0; i < L; i += 1) { - if(app.data.buyerAddressList['@'+type][i]._id == id) { - r = app.data.buyerAddressList['@'+type][i]; + if(_app.data.buyerAddressList['@'+type][i]._id == id) { + r = _app.data.buyerAddressList['@'+type][i]; break; } else {}//not a match. continue loop. @@ -518,13 +681,22 @@ note - dispatch isn't IN the function to give more control to developer. (you ma return r; }, - getWalletByID : function(ID) { + getWalletByID : function(ID,cartid) { var r = false; - if(app.data.buyerWalletList && app.data.buyerWalletList['@wallets'].length) { - var L = app.data.buyerWalletList['@wallets'].length; + var wallets; + if(_app.u.thisIsAnAdminSession()) { + wallets = _app.data['adminCustomerDetail|'+_app.data['cartDetail|'+cartid].customer.cid]['@WALLETS']; + } + else if(_app.data.buyerWalletList && _app.data.buyerWalletList['@wallets'].length) { + wallets = _app.data.buyerWalletList['@wallets'] + } + else {} + + if(wallets) { + var L = wallets.length; for(var i = 0; i < L; i += 1) { - if(ID == app.data.buyerWalletList['@wallets'][i].ID) { - r = app.data.buyerWalletList['@wallets'][i]; + if(ID == wallets[i].ID) { + r = wallets[i]; break; } } @@ -538,8 +710,9 @@ note - dispatch isn't IN the function to give more control to developer. (you ma // SANITY -> checkout uses the required attribute for validation. do not remove! // when switching between payment types and supplemental inputs, always REMOVE the old supplemental inputs. keeps it clean & checkout doesn't like extra vars. getSupplementalPaymentInputs : function(paymentID,data,isAdmin) { -// app.u.dump("BEGIN control.u.getSupplementalPaymentInputs ["+paymentID+"]"); -// app.u.dump(" -> data:"); app.u.dump(data); +// _app.u.dump("BEGIN control.u.getSupplementalPaymentInputs ["+paymentID+"]"); +// _app.u.dump(" -> data:"); _app.u.dump(data); + data = data || {} if(paymentID) { var $o = $("<div />").addClass("paybySupplemental").attr('data-app-role','supplementalPaymentInputsContainer'), //what is returned. a jquery object (ul) w/ list item for each input of any supplemental data. tmp = '', //tmp var used to put together string of html to append to $o @@ -554,18 +727,23 @@ note - dispatch isn't IN the function to give more control to developer. (you ma //expiration is less of a concern case 'CREDIT': - tmp += "<div><label>Credit Card #<input type='text' size='30' name='payment/CC' data-input-keyup='input-format' data-input-format='numeric' class=' creditCard' value='"; + tmp += "<div><label>Credit Card # <input type='text' data-format-rules='CC' size='30' name='payment/CC' data-input-keyup='input-format' data-input-format='numeric' class='creditCard' value='"; if(data['payment/CC']){tmp += data['payment/CC']} - tmp += "' onKeyPress='' required='required' /><\/label><\/div>"; + tmp += "' required='required' /><\/label><\/div>"; - tmp += "<div><label>Expiration<\/label><select name='payment/MM' class='creditCardMonthExp' required='required'><option><\/option>"; - tmp += app.u.getCCExpMonths(data['payment/MM']); + tmp += "<div><label>Expiration<\/label><select name='payment/MM' class='creditCardMonthExp' required='required'><option value=''>month<\/option>"; + tmp += _app.u.getCCExpMonths(data['payment/MM']); tmp += "<\/select>"; - tmp += "<select name='payment/YY' class='creditCardYearExp' required='required'><option value=''><\/option>"+app.u.getCCExpYears(data['payment/YY'])+"<\/select><\/div>"; + tmp += "<select name='payment/YY' class='creditCardYearExp' required='required'><option value=''>year<\/option>"+_app.u.getCCExpYears(data['payment/YY'])+"<\/select><\/div>"; - tmp += "<div><label for='payment/CV'>CVV/CID<input type='text' size='4' name='payment/CV' class=' creditCardCVV' onKeyPress='return app.u.numbersOnly(event);' value='"; + tmp += "<div><label for='payment/CV'>CVV/CID <input data-format-rules='CV' type='text' size='4' name='payment/CV' class=' creditCardCVV' data-input-format='numeric' data-input-keyup='input-format' value='"; if(data['payment/CV']){tmp += data['payment/CV']} - tmp += "' required='required' /><\/label> <span class='ui-icon ui-icon-help creditCardCVVIcon' onClick=\"$('#cvvcidHelp').dialog({'modal':true,height:400,width:550});\"></span><\/div>"; + tmp += "' "; + if(!_app.u.thisIsAnAdminSession()) { + tmp += " required='required' " //merchant has option of acquiring cvv/cid. + } + + tmp += " /><\/label> <span class='ui-icon ui-icon-help creditCardCVVIcon' onClick=\"$('#cvvcidHelp').dialog({'modal':true,width:"+($(window).width < 400 ? '90%' : 400)+"});\"></span><\/div>"; if(isAdmin === true) { tmp += "<div><label><input type='radio' name='VERB' value='AUTHORIZE'>Authorize<\/label><\/div>" @@ -630,7 +808,7 @@ note - dispatch isn't IN the function to give more control to developer. (you ma if($o) { $o.append(tmp); //set events to save values to memory. this will ensure data repopulates as panels get reloaded in 1PC. - $('input, select',$o).each(function(){ + $(':input',$o).each(function(){ $(this).off('change.save').on('change.save',function(){ data[$(this).attr('name')] = $(this).val(); }); @@ -641,67 +819,35 @@ note - dispatch isn't IN the function to give more control to developer. (you ma $o = false; //no paymentID specified. intentionally doens't display an error. } return $o; -// app.u.dump(" -> $o:"); -// app.u.dump($o); +// _app.u.dump(" -> $o:"); +// _app.u.dump($o); }, - - -/* -executing when quantities are adjusted for a given cart item. -call is made to update quantities. -When a cart item is updated, it'll end up getting re-rendered, so data-request-state doesn't need to be updated after the request. -Since theres no 'submit' or 'go' button on the form, there was an issue where the 'enter' keypress would double-execute the onChange event. -so now, the input is disabled the first time this function is executed and a disabled class is added to the element. The presence of this class -allows us to check and make sure no request is currently in progress. -*/ - updateCartQty : function($input,_tag) { - - var stid = $input.attr('data-stid'); - var qty = $input.val(); - - if(stid && qty && !$input.hasClass('disabled')) { - $input.attr('disabled','disabled').addClass('disabled').addClass('loadingBG'); - app.u.dump('got stid: '+stid); -//some defaulting. a bare minimum callback needs to occur. if there's a business case for doing absolutely nothing -//then create a callback that does nothing. IMHO, you should always let the user know the item was modified. -//you can do something more elaborate as well, just by passing a different callback. - _tag = _tag || {}; - _tag.callback = _tag.callback ? _tag.callback : 'updateCartLineItem'; - _tag.extension = _tag.extension ? _tag.extension : 'store_cart'; - _tag.parentID = 'cartViewer_'+app.u.makeSafeHTMLId(stid); -/* -the request for quantity change needs to go first so that the request for the cart reflects the changes. -the dom update for the lineitem needs to happen last so that the cart changes are reflected, so a ping is used. -*/ - app.ext.store_cart.calls.cartItemUpdate.init(stid,qty); - this.updateCartSummary(); -//lineitem template only gets updated if qty > 1 (less than 1 would be a 'remove'). - if(qty >= 1) { - app.calls.ping.init(_tag,'immutable'); - } - else { - $('#cartViewer_'+app.u.makeSafeHTMLId(stid)).empty().remove(); - } - app.model.dispatchThis('immutable'); - } - else { - app.u.dump(" -> a stid ["+stid+"] and a quantity ["+qty+"] are required to do an update cart."); - } - }, //run this just prior to creating an order. //will clean up cart object. sanitizeAndUpdateCart : function($form,_tag) { - if($form) { +// dump("BEGIN cco.u.sanitizeAndUpdateCart"); + if($form instanceof jQuery) { _tag = _tag || {}; - var formObj = $form.serializeJSON(); + var formObj = $form.serializeJSON({cb:true}); +// dump(" -> formObj: "); dump(formObj); //po number is used for purchase order payment method, but also allowed for a reference number (if company set and po not payment method). - if(app.ext.orderCreate.vars['want/payby'] != "PO" && formObj['want/reference_number']) { + if(_app.ext.order_create.vars['want/payby'] != "PO" && formObj['want/reference_number']) { formObj['want/po_number'] = formObj['want/reference_number']; } // to save from bill to bill, pass bill,bill. to save from bill to ship, pass bill,ship var populateAddressFromShortcut = function(fromAddr,toAddr) { - var addr = app.ext.cco.u.getAddrObjByID(fromAddr,formObj[fromAddr+'/shortcut']); + dump(" -> populateAddressFromShortcut. from: "+fromAddr+" toAddr: "+toAddr); + + var addr; + if(_app.vars.thisSessionIsAdmin) { + var cartID = $form.closest("[data-app-role='checkout']").data('cartid'); + addr = _app.ext.cco.u.getAndRegularizeAddrObjByID(_app.data['adminCustomerDetail|'+_app.data['cartDetail|'+cartID].customer.cid]['@'+fromAddr.toUpperCase()],formObj[fromAddr+'/shortcut'],fromAddr,true) + } + else { + addr = _app.ext.cco.u.getAddrObjByID(fromAddr,formObj[fromAddr+'/shortcut']); + } + for(var index in addr) { if(index.indexOf(fromAddr+'/') == 0) { //looking for bill/ means fields like id and shortcut won't come over, which is desired behavior. if(fromAddr == toAddr) { @@ -727,8 +873,10 @@ the dom update for the lineitem needs to happen last so that the cart changes ar else if(formObj['want/bill_to_ship'] && formObj['bill/shortcut']) { populateAddressFromShortcut('bill','ship'); } -//bill to ship, but no short cut (not logged in) - else if(formObj['want/bill_to_ship']) { +//bill to ship, but no short cut (not logged in). +// ** 201402 -> was hitting on else if((formObj['want/bill_to_ship']) so > 0 added. + else if(formObj['want/bill_to_ship'] > 0) { + dump(" -> want/bill_to_ship = "+formObj['want/bill_to_ship']); for(var index in formObj) { //copy billing fields into shipping. not email tho. if(index.indexOf('bill/') == 0 && index != 'bill/email') { @@ -736,27 +884,262 @@ the dom update for the lineitem needs to happen last so that the cart changes ar } } } -//regularize checkbox data. - if(formObj['want/bill_to_ship'] == 'ON') {formObj['want/bill_to_ship'] = 1} - if(formObj['want/create_customer'] == 'ON') {formObj['want/create_customer'] = 1} + //these aren't valid checkout field. used only for some logic processing. delete formObj['want/reference_number']; delete formObj['want/bill_to_ship_cb']; -//cc and cv should never go. They're added as part of cartPaymentQ - delete formObj['payment/cc']; - delete formObj['payment/cv']; +//CC and CV should never go. They're saved in memory and added as part of cartPaymentQ + delete formObj['payment/CC']; + delete formObj['payment/CV']; /* these fields are in checkout/order create but not 'supported' fields. don't send them */ delete formObj['giftcard']; delete formObj['want/bill_to_ship_cb']; - delete formObj['coupon']; + delete formObj['want/new_password2']; + delete formObj['coupon']; + //the following get added to the checkout form in the admin UI + delete formObj['sku']; + delete formObj['override']; + delete formObj['add']; + delete formObj['qty']; //admin UI for line item editing. + delete formObj['price']; //admin UI for line item editing. + + delete formObj['sum/shp_carrier']; //admin UI custom ship cost. + delete formObj['sum/shp_method']; + delete formObj['sum/shp_total']; + + _app.ext.cco.calls.cartSet.init(formObj,_tag); //adds dispatches. + } + else { + $("#globalMessaging").anymessage({"message":"In cco.u.sanitizeAndUpdateCart, $form was not a valid instance of jQuery.","gMessage":true}); + } + }, //sanitizeAndUpdateCart + - app.calls.cartSet.init(formObj,_tag); //adds dispatches. +//run when a payment method is selected. updates memory and adds a class to the radio/label. +//will also display additional information based on the payment type (ex: purchase order will display PO# prompt and input) + updatePayDetails : function($container) { +// _app.u.dump("BEGIN order_create.u.updatePayDetails."); + var paymentID = $("[name='want/payby']:checked",$container).val(); + + var o = ''; + $('.ui-state-active',$container).removeClass('ui-state-active ui-corner-top ui-corner-all ui-corner-bottom'); +//in Admin, some of the supplemental inputs are shared between payment types (flag as paid) +//so to ensure the checkbox isn't on by accident, remove all supplemental material when switching between. + $('.paybySupplemental', $container).empty().remove(); + var $radio = $("[name='want/payby']:checked",$container); + + +// _app.u.dump(" -> $radio.length: "+$radio.length); + var $supplementalContainer = $("[data-ui-supplemental='"+paymentID+"']",$container); +//only add the 'subcontents' once. if it has already been added, just display it (otherwise, toggling between payments will duplicate all the contents) + if($supplementalContainer.length == 0) { + _app.u.dump(" -> supplemental is empty. add if needed."); + var supplementalOutput = _app.ext.cco.u.getSupplementalPaymentInputs(paymentID,{},true); //this will either return false if no supplemental fields are required, or a jquery UL of the fields. +// _app.u.dump("typeof supplementalOutput: "+typeof supplementalOutput); + if(typeof supplementalOutput == 'object') { + $radio.parent().addClass('ui-state-active ui-corner-top'); //supplemental content will have bottom corners +// _app.u.dump(" -> getSupplementalPaymentInputs returned an object"); + supplementalOutput.addClass('ui-widget-content ui-corner-bottom'); +//save values of inputs into memory so that when panel is reloaded, values can be populated. + $('input[type=text], select',supplementalOutput).change(function(){ + _app.ext.cco.vars[$(this).attr('name')] = $(this).val(); //use name (which coforms to cart var, not id, which is websafe and slightly different + }) + + $radio.parent().after(supplementalOutput); + } + else { + //no supplemental material. + $radio.parent().addClass('ui-state-active ui-corner-all'); + } } - } //sanitizeAndUpdateCart + else { +//supplemental material present and already generated once (switched back to it from another method) + $radio.parent().addClass('ui-state-active ui-corner-top'); //supplemental content will have bottom corners + $supplementalContainer.show(); + } //supllemental content has already been added. + }, //updatePayDetails +/* +in an order detail, the item variations are stored as %options +in a reorder, that data needs to be converted to the variations format required by cartItemAppend. +*/ + + options2Variations : function(opts) { + var variations = false; //what is returned. either false or an object. + if(!$.isEmptyObject(opts)) { + variations = {}; + for(var index in opts) { + variations[opts[index].id] = opts[index].v + } + } + return variations; + }, + +//vars.orderID is the orderID we are ordering from. - required. +//vars.cartid is the cart that the item(s) will be added to. - required. +//callback is executed as part of the cartDetail call, which is piggy backed w/ the append calls. +//skuArr is an optional param. if set, only the items in skuArr will be appended to the cart. + appendOrderItems2Cart : function(vars,callback,skuArr) { +// dump("BEGIN cco.u.appendOrderItems2Cart. skuArr: "); dump(skuArr); + vars = vars || {}; + if(vars.orderid && vars.cartid) { + var cmd; //the command used for the dispatch. varies based on whether this is admin or buyer. + skuArr = skuArr || []; + if(_app.u.thisIsAnAdminSession()) { + cmd = 'adminOrderDetail'; + } + else { + cmd = 'buyerOrderGet'; + } + + _app.model.addDispatchToQ({ + '_cmd':cmd, + 'orderid':vars.orderid, + '_tag': { + 'datapointer' : cmd+"|"+vars.orderid, + 'callback':function(rd) { + if(_app.model.responseHasErrors(rd)){ + $('#globalMessaging').anymessage({'message':rd}); + } + else { + var items = (cmd == 'adminOrderDetail') ? _app.data[rd.datapointer]['@ITEMS'] : _app.data[rd.datapointer].order['@ITEMS'], L = items.length; + for(var i = 0; i < L; i += 1) { + dump(i+") items[i].sku: "+items[i].sku+" and inArray: "+$.inArray(items[i].sku,skuArr)); + if(skuArr.length && $.inArray(items[i].sku,skuArr) < 0) { + //skuArr is defined and this item is NOT in the array. do nothing. + } + else { + //skuArr is either not defined (append all sku's from order) OR skuArr is defined and this item is in that array. Either way, proceed w/ append. + var appendObj = _app.ext.cco.u.buildCartItemAppendObj(items[i],vars.cartid); //will generate a new uuid. + _app.u.dump(" -> appendObj"); _app.u.dump(appendObj); + if(appendObj) { + _app.ext.cco.calls.cartItemAppend.init(appendObj,{},'immutable'); + } + else { + $('#globalMessaging').anymessage({'message':'In cco.u.appendOrderItems2Cart, cco.u.buildCartItemAppendObj failed. See console for details.','gMessage':true}); + } + } + } + if(L) { + _app.calls.cartDetail.init(vars.cartid,{'callback': (typeof callback == 'function') ? callback : ''},'immutable'); + _app.model.dispatchThis('immutable'); + } + } + } + } + },'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $('#globalMessaging').anymessage({'message':'In cco.u.reorder, orderid ['+vars.orderid+'] and/or cartid ['+vars.cartid+'] left blank and both are required.','gMessage':true}); + } + + }, + +//accepts an object (probable a serialized form object) which needs sku and qty. In an admin session, also accepts price. +//Will validate required fields and provide any necessary formatting. +//used in order_create in the admin UI for adding a line item and a re-order for previous orders. + buildCartItemAppendObj : function(sfo,_cartid) { + var r = false; //what is returned. either an object or false + if(sfo.sku && sfo.qty) { + if(sfo.price) {} + else {delete sfo.price} //don't pass an empty price, will set price to zero. if a price is passed when not in an admin session, it'll be ignored. + sfo.uuid = _app.u.guidGenerator(); + if(sfo['%options']) { + sfo['%variations'] = this.options2Variations(sfo['%options']) + } + if(_cartid) {sfo._cartid = _cartid;} + else {sfo._cartid = _app.model.fetchCartID();} + r = _app.u.getWhitelistedObject(sfo,['qty','%variations','price','sku','uuid','_cartid']); //whitelisted so all extra crap is dropped. ex: when %options is passed in from an existing order. + } + else { + _app.u.dump("In cco.u.buildCartItemAppendObj, both a sku ["+sfo.sku+"] and a qty ["+sfo.qty+"] are required and one was not set.",'warn'); //parent function will handle error display so that it can be case specific. + r = false; //sku and qty are required. + } + return r; + }, + +//cartid is required. +// vars must have qty and stid (store) or uuid (admin). in admin, vars.price is optional + cartItemUpdate : function(cartid,vars,_tag){ + vars = vars || {}; + var r = false; //what is returned. will be true if a dispatch is added. + if(cartid) { +//this object that is going to be added to the dispact Q. + var cmdObj = { + '_cartid' : cartid, + '_tag' : _tag || {} + } + + if(_app.u.thisIsAnAdminSession()) { + if(vars.qty && vars.uuid) { + r = true; + cmdObj._cmd = 'adminCartMacro'; + cmdObj['@updates'] = ["ITEMUPDATE?"+$.param(vars)]; + } + else { + $('#globalMessaging').anymessage({'message':'In cco.u.cartItemUpdate, vars.qty ['+vars.qty+'] and/or vars.uuid ['+vars.uuid+'] are blank, both of which are required in an admin session.','gMessage':true}); + } + } + else { + if(vars.quantity && vars.stid) { + r = true; + cmdObj.stid = vars.stid; + cmdObj.quantity = vars.quantity; + cmdObj.uuid = vars.uuid; + cmdObj._cmd = 'cartItemUpdate'; + } + else { + $('#globalMessaging').anymessage({'message':'In cco.u.cartItemUpdate, vars.quantity ['+vars.quantity+'] and/or vars.stid ['+vars.stid+'] are blank, both of which are required in an admin session.','gMessage':true}); + } + } + + if(r) { + _app.model.addDispatchToQ(cmdObj,'immutable'); + } + + } + else { + $('#globalMessaging').anymessage({'message':'In cco.u.cartItemUpdate, cartid is required and was left blank.','gMessage':true}); + } + return r; + }, //cartItemUpdateExec + + + + +//cart must already be in memory when this is run. +//will tell you which third party checkouts are available. does NOT look to see if merchant has them enabled, +// just checks to see if the cart contents would even allow it. +//currently, there is only a google field for disabling their checkout, but this is likely to change. + which3PCAreAvailable : function(cartID){ + // _app.u.dump("BEGIN control.u.which3PCAreAvailable"); + var obj = {}; + if(_app.data['cartDetail|'+cartID]) { + //by default, everything is available + obj = { + paypalec : true, + amazonpayment : true, + googlecheckout : true + } + var items = _app.data['cartDetail|'+cartID]['@ITEMS'], L = items.length; + for(var i = 0; i < L; i += 1) { + if(items[i]['%attribs'] && items[i]['%attribs']['gc:blocked']) {obj.googlecheckout = false} + if(items[i]['%attribs'] && items[i]['%attribs']['paypalec:blocked']) {obj.paypalec = false} + } + } + // cart not in memory. turn off third party checkout. + else { + obj.paypalec = false; + obj.amazonpayment = false; + obj.googlecheckout = false; + } + return obj; + } //which3PCAreAvailable + }, //util @@ -773,135 +1156,269 @@ the dom update for the lineitem needs to happen last so that the cart changes ar renderFormats : { -//value is set to ISO and sent to API that way. however, cart object returned is in 'pretty'. -//so a check occurs to set selectedCountry to the selected ISO value so it can be 'selected' - countriesAsOptions : function($tag,data) { -// app.u.dump("BEGIN app.ext.cco.renderFormats.countriesAsOptions"); -// app.u.dump(" -> Country: "+data.value); - var r = ''; - var L = app.data.appCheckoutDestinations['@destinations'].length; -// app.u.dump(" -> number of countries = "+L); - for(var i = 0; i < L; i += 1) { - r += "<option value='"+app.data.appCheckoutDestinations['@destinations'][i].ISO+"' "; - if(data.value == app.data.appCheckoutDestinations['@destinations'][i].ISO) { - r += " selected='selected' "; +// pass in parent data object (entire cart). need to get both the cart ID and the country that has already been selected. + countriesasoptions : function($tag,data) { + var r = '', cartid; + + if(data.value.cart && data.value.cart.cartid){ + cartid = data.value.cart.cartid; + } + else { + cartid = _app.model.fetchCartID(); //in some cases, such as an address editor, the cartid may not be in the data. + } + if(cartid) { + if(_app.data['appCheckoutDestinations|'+cartid] && _app.data['cartDetail|'+cartid] && data.bindData.shiptype) { + var destinations = _app.data['appCheckoutDestinations|'+cartid]['@destinations'], L = destinations.length, cartData = _app.data['cartDetail|'+cartid]; + for(var i = 0; i < L; i += 1) { + r += "<option value='"+destinations[i].ISO+"'>"+destinations[i].Z+"</option>"; + } + $tag.append(r); + $tag.val(_app.u.thisNestedExists("data.cartDetail|"+cartid+"."+data.bindData.shiptype+".countrycode",_app) ? cartData[data.bindData.shiptype].countrycode : 'US'); + } + else if(!data.bindData.shiptype) { + $tag.parent().append($("<div \/>").anymessage({'persistent':true,'message':'In cco.renderFormats.countriesasoptions, data-bind rules must have a shiptype set.','gMessage':true})); + } + else { + $tag.parent().append($("<div \/>").anymessage({'persistent':true,'message':'in cco.renderFormats.countriesasoptions, _app.data[appCheckoutDestinations|'+cartid+'] or _app.data.cartDetail|'+cartid+' and both are required. is not available in memory.','gMessage':true})); } - r += ">"+app.data.appCheckoutDestinations['@destinations'][i].Z+"</option>"; + + } + else { + dump("For countriesasoptions renderFormat in CCO, cartID could not be obtained.",'warn'); } - - $tag.html(r); }, - - //data.value should be the item object from the cart. - cartItemRemoveButton : function($tag,data) { - + cartitemremovebutton : function($tag,data) { if(data.value.stid[0] == '%') {$tag.remove()} //no remove button for coupons. else if(data.value.asm_master) {$tag.remove()} //no remove button for assembly 'children' else { -if($tag.is('button')){$tag.button({icons: {primary: "ui-icon-closethick"},text: false})} -$tag.attr({'data-stid':data.value.stid}).val(0); //val is used for the updateCartQty + if($tag.is('button')){$tag.button({icons: {primary: "ui-icon-closethick"},text: false})} +// $tag.attr({'data-stid':data.value.stid}).val(0); //val is used for the updateCartQty + } + }, -//the click event handles all the requests needed, including updating the totals panel and removing the stid from the dom. -$tag.one('click',function(event){ - event.preventDefault(); - app.ext.store_cart.u.updateCartQty($tag); - app.model.dispatchThis('immutable'); - }); + cartitemqty : function($tag,data) { + $tag.val(data.value.qty); +//for coupons and assemblies, no input desired, but qty display is needed. so the qty is inserted where the input was. + if((data.value.stid && data.value.stid[0] == '%') || data.value.asm_master) { + $tag.prop('disabled',true).css('border-width','0') + } + else { + $tag.attr('data-stid',data.value.stid); } }, - + + paypalecbutton : function($tag,data) { + if(zGlobals.checkoutSettings.paypalCheckoutApiUser) { + var payObj = _app.ext.cco.u.which3PCAreAvailable(data.value); + if(payObj.paypalec) { + $tag.empty().append("<img width='145' id='paypalECButton' height='42' border='0' src='"+(document.location.protocol === 'https:' ? 'https:' : 'http:')+"//www.paypal.com/en_US/i/btn/btn_xpressCheckoutsm.gif' alt='' />").addClass('pointer').off('click.paypal').on('click.paypal',function(){ + $(document.body).showLoading({'message':'Obtaining secure PayPal URL for transfer...'}); + _app.ext.cco.calls.cartPaypalSetExpressCheckout.init({'getBuyerAddress':1, '_cartid':_app.model.fetchCartID(),'useMobile':($(document.body).width() < 500 ? 1 : 0)},{'callback':function(rd){ + $(document.body).hideLoading(); + if(_app.model.responseHasErrors(rd)){ + $('#globalMessaging').anymessage({'message':rd}); + } + else { + if(_app.data[rd.datapointer] && _app.data[rd.datapointer].URL) { + document.location = _app.data[rd.datapointer].URL+'&useraction=commit'; //commit returns user to website for order confirmation. otherwise they stay on paypal. + } + else { + $('#globalMessaging').anymessage({"message":"In paypalecbutton render format, dispatch to obtain paypal URL was successful, but no URL in the response.","gMessage":true}); + } + } + }}); + $(this).addClass('disabled').attr('disabled','disabled'); + _app.model.dispatchThis('immutable'); + }); + } + else { + $tag.empty().append("<img width='145' id='paypalECButton' height='42' border='0' src='"+(document.location.protocol === 'https:' ? 'https:' : 'http:')+"//www.paypal.com/en_US/i/btn/btn_xpressCheckoutsm.gif' alt='' />").addClass('disabled').attr('disabled','disabled'); + } + } + else { + $tag.addClass('displayNone'); + } + }, //paypalecbutton + + googlecheckoutbutton : function($tag,data) { + + if(zGlobals.checkoutSettings.googleCheckoutMerchantId && (window._gat && window._gat._getTracker)) { + var payObj = _app.ext.cco.u.which3PCAreAvailable(); //certain product can be flagged to disable googlecheckout as a payment option. + if(payObj.googlecheckout) { + $tag.append("<img height=43 width=160 id='googleCheckoutButton' border=0 src='"+(document.location.protocol === 'https:' ? 'https:' : 'http:')+"//checkout.google.com/buttons/checkout.gif?merchant_id="+zGlobals.checkoutSettings.googleCheckoutMerchantId+"&w=160&h=43&style=trans&variant=text&loc=en_US' \/>").one('click',function(){ + _app.ext.cco.calls.cartGoogleCheckoutURL.init(); + $(this).addClass('disabled').attr('disabled','disabled'); + _app.model.dispatchThis('immutable'); + }); + } + else { + $tag.append("<img height=43 width=160 id='googleCheckoutButton' border=0 src='"+(document.location.protocol === 'https:' ? 'https:' : 'http:')+"://checkout.google.com/buttons/checkout.gif?merchant_id="+zGlobals.checkoutSettings.googleCheckoutMerchantId+"&w=160&h=43&style=trans&variant=disable&loc=en_US' \/>") + } + } + else if(zGlobals.checkoutSettings.googleCheckoutMerchantId) { + _app.u.dump("zGlobals.checkoutSettings.googleCheckoutMerchantId is set, but _gaq is not defined (google analytics not loaded but required)",'warn'); + } + else { + $tag.addClass('displayNone'); + } + + }, //googlecheckoutbutton + + + //for displaying order balance in checkout order totals. //changes value to 0 for negative amounts. Yes, this can happen. - orderBalance : function($tag,data) { - var o = ''; - var amount = data.value; -// app.u.dump('BEGIN app.renderFunctions.format.orderBalance()'); -// app.u.dump('amount * 1 ='+amount * 1 ); + orderbalance : function($tag,data) { + if(data.value) { + var o = ''; + var amount = data.value; //if the total is less than 0, just show 0 instead of a negative amount. zero is handled here too, just to avoid a formatMoney call. //if the first character is a dash, it's a negative amount. JS didn't like amount *1 (returned NAN) - - if(amount * 1 <= 0){ -// app.u.dump(' -> '+amount+' <= zero '); - o += data.bindData.currencySign ? data.bindData.currencySign : '$'; - o += '0.00'; - } - else { -// app.u.dump(' -> '+amount+' > zero '); - o += app.u.formatMoney(amount,data.bindData.currencySign,'',data.bindData.hideZero); + if(amount * 1 <= 0){ + o += data.bindData.currencySign ? data.bindData.currencySign : '$'; + o += '0.00'; + } + else { + o += _app.u.formatMoney(amount,data.bindData.currencySign,'',data.bindData.hideZero); + } + $tag.text("Balance due: "+o); //update DOM. } - - $tag.text(o); //update DOM. -// app.u.dump('END app.renderFunctions.format.orderBalance()'); }, //orderBalance - secureLink : function($tag,data) { -// app.u.dump('BEGIN app.ext.cco.renderFormats.secureLink'); -// app.u.dump(" -> data.windowName = '"+data.windowName+"'"); -//if data.windowName is set, the link will open a new tab/window. otherwise, it just changes the page/tab in focus. - if(app.u.isSet(data.windowName)) - $tag.click(function(){window.open(zGlobals.appSettings.https_app_url+$.trim(data.value)),data.windowName}); - else - $tag.click(function(){window.location = zGlobals.appSettings.https_app_url+$.trim(data.value)}); - }, //secureLink - //displays the shipping method followed by the cost. //is used in cart summary total during checkout. - shipInfoById : function($tag,data) { + shipinfobyid : function($tag,data) { var o = ''; -// app.u.dump('BEGIN app.renderFormats.shipInfo. (formats shipping for minicart)'); -// app.u.dump(data); - var shipMethods = app.data.cartDetail['@SHIPMETHODS'], - L = shipMethods.length; - for(var i = 0; i < L; i += 1) { -// app.u.dump(' -> method '+i+' = '+app.data.cartShippingMethods['@methods'][i].id); - if(shipMethods[i].id == data.value) { - var pretty = app.u.isSet(shipMethods[i]['pretty']) ? shipMethods[i]['pretty'] : shipMethods[i]['name']; //sometimes pretty isn't set. also, ie didn't like .pretty, but worked fine once ['pretty'] was used. - o = "<span class='orderShipMethod'>"+pretty+": <\/span>"; -//only show amount if not blank. - if(shipMethods[i].amount) { - o += "<span class='orderShipAmount'>"+app.u.formatMoney(shipMethods[i].amount,' $',2,false)+"<\/span>"; + var shipMethods = data.value['@SHIPMETHODS']; + if(shipMethods) { + var L = shipMethods.length; + for(var i = 0; i < L; i += 1) { + // _app.u.dump(' -> method '+i+' = '+_app.data.cartShippingMethods['@methods'][i].id); + if(shipMethods[i].id == data.value.want.shipping_id) { + //sometimes pretty isn't set. also, ie didn't like .pretty, but worked fine once ['pretty'] was used. + o = "<span class='orderShipMethod'>"+(shipMethods[i]['pretty'] ? shipMethods[i]['pretty'] : shipMethods[i]['name'])+": <\/span>"; + //only show amount if not blank. + if(shipMethods[i].amount) { + o += "<span class='orderShipAmount'>"+_app.u.formatMoney(shipMethods[i].amount,' $',2,false)+"<\/span>"; + } + break; //once we hit a match, no need to continue. at this time, only one ship method/price is available. } - break; //once we hit a match, no need to continue. at this time, only one ship method/price is available. } } + else { + //shipMethods is empty. this may be perfectly normal (admin UI -> new order -> no product in cart yet. store -> no zip or state.) + } $tag.html(o); - }, //shipInfoById - - shipMethodsAsOptions : function($tag,data) { -// app.u.dump('BEGIN app.ext.cco.formats.shipMethodsAsOptions'); - var o = ''; - var L = data.value.length; + }, //shipinfobyid - var id,isSelectedMethod,safeid,shipName; // id is actual ship id. safeid is id without any special characters or spaces. isSelectedMethod is set to true if id matches cart shipping id selected. - for(var i = 0; i < L; i += 1) { - isSelectedMethod = false; - safeid = app.u.makeSafeHTMLId(data.value[i].id); - id = data.value[i].id; - -//whether or not this iteration is for the selected method should only be determined once, but is used on a couple occasions, so save to a var. - if(id == app.data.cartDetail['want/shipping_id']) { - isSelectedMethod = true; + walletnameintoicon : function($tag,data) { + $tag.addClass('paycon_'+data.value.substring(0,4).toLowerCase()); + }, + paymentstatus : function($tag,data) { + if(Number(data.value[0]) === 0) {$tag.append("Paid");} + else{$tag.append("Unpaid")} + }, + marketplaceorderid : function($tag,data) { + var order = _app.data['adminOrderDetail|'+data.value]; + var output = ""; + if(order.flow.payment_method == 'AMAZON') {output = order.mkt.amazon_orderid} + else if(order.flow.payment_method == 'EBAY') {output = order.mkt.erefid.split('-')[0]}//splitting at dash shows just the ebay item # + else if(order.flow.payment_method == 'NEWEGG') {output = order.mkt.erefid} + else if(order.flow.payment_method == 'BUY') {output = order.mkt.erefid} + else if(order.flow.payment_method == 'SEARS') {output = order.mkt.sears_orderid} + else{} + $tag.append(output); + } + }, //renderFormats + + e : { + + cartFetchExec : function($ele,p) { + p.preventDefault(); + $ele.closest("[data-template-role='cart']").trigger('fetch',{'Q':'immutable'}); //will work if getCartAsJqObj was used to create the cart. + _app.model.dispatchThis('immutable'); + return false; + }, + + cartItemRemove : function($ele,p) { + p.preventDefault(); + var stid = $ele.closest('[data-stid]').data('stid'), cartid = $ele.closest("[data-template-role='cart']").data('cartid'); + if(stid && cartid) { + _app.ext.cco.calls.cartItemUpdate.init({'stid':stid,'quantity':0,'_cartid':cartid},{ + 'callback' : 'showMessaging', + 'message' : 'Item '+stid+' removed from your cart', + 'jqObj' : $ele.closest('form') + },'immutable'); + + // these needs to be before the empty below OR the button can't look up the foodchain for the cart container. + $ele.closest("[data-template-role='cart']").trigger('fetch',{'Q':'immutable'}); //will work if getCartAsJqObj was used to create the cart. + + $ele.closest('[data-stid]').intervaledEmpty(); + _app.model.dispatchThis('immutable'); + } + else { + $ele.closest('form').anymessage({'message':'In cco.e.cartItemRemove, unable to ascertain item STID ['+stid+'] and/or the cart id ['+cartid+'].','gMessage':true}) + } + return false; + }, //cartItemRemove + + //this update could get triggered by a quantity update, a button or a price change (admin). + //$container will contain the qty and, if present, the price. + //this can be used to update a store or admin session. the callback here is fixed and will update the cart IF the cart was generated using getCartAsJqObj + cartItemUpdateExec : function($ele,p){ + p.preventDefault(); + var + $container = $ele.closest('[data-stid]'), + $cart = $ele.closest("[data-template-role='cart']"), + cartid = $cart.data('cartid'), + vars = { + stid : $container.data('stid'), + uuid : $container.data('uuid'), + qty : $ele.val(), //admin wants qty. + quantity : $ele.val() //cartItemUpdate wants quantity } + if($("input[name='price']",$container).val() && _app.u.thisIsAnAdminSession()) { + vars.price = $("input[name='price']",$container).val(); + } -//app.u.dump(' -> id = '+id+' and want/shipping_id = '+app.data.cartDetail['want/shipping_id']); - - shipName = app.u.isSet(data.value[i].pretty) ? data.value[i].pretty : data.value[i].name - - o += "<option " - if(isSelectedMethod) - o+= " selected='selected' "; - o += " value = '"+id+"' >"+shipName+" - "+app.u.formatMoney(data.value[i].amount,'$','',false)+"<\/option>"; + //globalMessaging is used for message display so the 'fetch' for the cart doesn't nuke the messaging. + if(_app.ext.cco.u.cartItemUpdate(cartid,vars,{'callback' : 'showMessaging','message' : 'Item '+$container.data('stid')+ ' updated.','jqObj' : $cart})) { + $cart.trigger('fetch',{'Q':'immutable'}); //will work if getCartAsJqObj was used to create the cart. + _app.model.dispatchThis('immutable'); } - $tag.html(o); + else { + //cartItemUpdate will handle error display. + } + return false; + }, //cartItemUpdateExec + //will post the input to the cart, passively. + cartSetAttrib : function($ele,p) { + p.preventDefault(); + var cartid = $ele.data('cartid') || $ele.closest("[data-cartid]").data('cartid'); + if(cartid) { + var cmdObj = { + _cartid : cartid + }; + cmdObj[$ele.attr('name')] = $ele.val(); + _app.ext.cco.calls.cartSet.init(cmdObj,{},'passive'); _app.model.dispatchThis('passive'); + } + else { + $("#globalMessaging").anymessage({"message":"In cco.e.cartSetAttib, unable to ascertain cart id. Be sure data-cartid is set on/above trigger element.","gMessage":true}); + } + return false; }, - walletName2Icon : function($tag,data) { - $tag.addClass('paycon_'+data.value.substring(0,4).toLowerCase()); - } + cartZipUpdateExec : function($ele,p) { + p.preventDefault(); + _app.ext.cco.calls.cartSet.init({'ship/postal':$ele.val(), 'ship/region':'','_cartid': $ele.closest("[data-template-role='cart']").data('cartid')},{},'immutable'); + $ele.closest("[data-template-role='cart']").trigger('fetch',{'Q':'immutable'}); + _app.model.dispatchThis('immutable'); + return false; + } //cartZipUpdateExec - } //renderFormats + } } // r return r; diff --git a/extensions/cart_message/extension.js b/extensions/cart_message/extension.js new file mode 100644 index 000000000..9669d31e3 --- /dev/null +++ b/extensions/cart_message/extension.js @@ -0,0 +1,551 @@ +/* ************************************************************** + + Copyright 2013 Zoovy, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +************************************************************** */ + + + +var cart_message = function(_app) { + var theseTemplates = new Array('adminCartMessageTemplate'); + var r = { + + vars : { + "carts" : {} //a hash where key is cartID and value is hash of 'polling' and 'timeout'. polling is how long between each request and timeout is the setTimeout (so it can be cancelled). + }, +//////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + + + callbacks : { + //executed when extension is loaded. should include any validation that needs to occur. + init : { + onSuccess : function() { + var r = false; //return false if extension won't load for some reason (account config, dependencies, etc). + window.cartMessagePush = _app.ext.cart_message.u.cartMessagePush; //global shortcut. + _app.cmr = _app.cmr || []; +// _app.u.dump(" -> _app.cmr: "); _app.u.dump(_app.cmr); + var L = _app.cmr.length; + + var addCMResponse = function(id,func){ + //allow but notify if an existing response is overwritten. + if(_app.cmr[i] && _app.cmr[i][0]){ + _app.u.dump("Cart Messaging Response "+_app.cmr[i][0]+" is being overwritten","warn"); + } + _app.ext.cart_message.cmResponse[id] = func; + } + + for(var i = (L-1); i >= 0; i -= 1) { + addCMResponse(_app.cmr[i][0],_app.cmr[i][1]); + delete _app.cmr[i]; + } + _app.cmr.push = addCMResponse; // all future pushes will get added immediately to the response list. + _app.u.loadCSSFile(_app.vars.baseURL+"extensions/cart_message/styles.css","cart_messageCSS"); + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/cart_message/templates.html',theseTemplates); + //if there is any functionality required for this extension to load, put it here. such as a check for async google, the FB object, etc. return false if dependencies are not present. don't check for other extensions. + r = true; + + return r; + }, + onError : function() { + //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. + //you may or may not need it. + _app.u.dump('BEGIN cart_message.callbacks.init.onError'); + } + }, //init + + + + handleCartMessageListPolling : { + onSuccess : function(_rtag) { +/* +if no message, increment frequency by 3 seconds and trigger timeout but never greater than 1 minute. +if messages + -> update localStorage copy of messageList. store as array. push new messages onto the end of that array. + -> update DOM. + -> trigger another timout at frequency - 2 seconds BUT frequency never less than 3 seconds. + +jqObj -> this is the chat dialog/context, not the message history pane, because not all messages will be 'chat'. + +*/ + if(_rtag && _rtag.jqObj && _rtag.jqObj.data('cartid')) { + var + messages = _app.data[_rtag.datapointer]['@MSGS'], + cartID = _rtag.jqObj.data('cartid'), //shortcut. + L = messages.length + + if(L > 0) { + var messagesDPS = _app.model.dpsGet('cartMessages',cartID) || []; +// ((_app.ext.cart_message.vars.carts[cartID].frequency - 6000) < 3000) ? _app.ext.cart_message.vars.carts[cartID].frequency=3000 : _app.ext.cart_message.vars.carts[cartID].frequency-=6000; //frequency is never less than 3000; + _app.ext.cart_message.vars.carts[cartID].frequency = 3000; //if a message is present, increase frequency because chat is 'active'. + + for(var i = 0; i < L; i += 1) { + messages[i].init = _rtag.init || false; // will be set to true if this is executed as part of the init. + messagesDPS.push(messages[i]); + if(typeof _app.ext.cart_message.cmResponse[messages[i].what] == 'function') { + _app.ext.cart_message.cmResponse[messages[i].what](messages[i],_rtag.jqObj) + } + else if(typeof _app.ext.cart_message.cmResponse[messages[i].what.split('.')[0]] == 'function') { //what.split will check for 'view' instead of view.product. allows for a default. + _app.ext.cart_message.cmResponse[messages[i].what.split('.')[0]](messages[i],_rtag.jqObj) + } + else { + // ### TODO -> what to do if the message type is not defined/unrecognized? + } + } + _app.model.dpsSet('cartMessages',_rtag.jqObj.data('cartid'),messagesDPS); + _app.model.dpsSet('cartMessages','lastMessageTS',_app.u.epochNow()); //record when the last message came in. used at init. + } + else { + if(_app.ext.cart_message.vars.carts[cartID]) { + (_app.ext.cart_message.vars.carts[cartID].frequency >= 60000) ? 60000 : _app.ext.cart_message.vars.carts[cartID].frequency += 3000; //frequency is never much more than a minute. + } + } +//now queue up the next request. + if(_app.ext.cart_message.vars.carts[cartID]) { + _app.ext.cart_message.u.fetchCartMessages(_app.ext.cart_message.vars.carts[cartID].frequency,_rtag.jqObj); + } + + } + else { + $('#globalMessaging').anymessage({"message":"In cart_message.callbacks.handleCartMessageListPolling, unable to ascertain cartid.","gMessage":true}); + } + }, + onError : function(rd) { + if(rd.errid == 4) { + //this means the _cmd is not supported. not sense retrying every few seconds. + } + else if(rd && rd._rtag && rd._rtag.jqObj && rd._rtag.jqObj.data('cartid')) { + var cartID = rd._rtag.jqObj.data('cartid'); + _app.ext.cart_message.vars.carts[cartID].frequency = 10000; + _app.ext.cart_message.u.fetchCartMessages(_app.ext.cart_message.vars.carts[cartID].frequency,rd._rtag.jqObj); + } + else { + $('#globalMessaging').anymessage({"message":"In cart_message.callbacks.handleCartMessageListPolling, unable to ascertain cartid.","gMessage":true}); + } + } + } //handleCartMessageListPolling + + }, //callbacks + +/* +the responses here are executed from handleCartMessageListPolling +The responses themselves are added by the app that loads the extension. That way, the responses are app-specific (admin responses are likely different from buyer responses). +The response ID should match the 'what' that is passed. + +some defaults are present, but they can be overwritten by the app easily enough. +*/ + cmResponse : { + 'cart.change' : function(message,$context) { + $("[data-app-role='messageHistory']",$context).append("<p class='cart_update'><span class='from'>"+message.FROM+"<\/span> has updated the <span class='ui-icon ui-icon-cart'><\/span>.<\/p>"); + }, + 'chat.exit' : function(message,$context) { + $("[data-app-role='messageHistory']",$context).append("<p class='chat_exit'>"+message.FROM+" has left the chat.<\/p>"); + }, +//in a storefront, chat.join will likely be overwritten. Most likely, you'll open a dialog w/ the cart messaging UI (or something like that). + 'chat.join' : function(message,$context) { + $("[data-app-role='messageInput']",$context).show(); + $("[data-app-role='messageHistory']",$context).append("<p class='chat_join'>"+message.FROM+" has joined the chat.<\/p>"); + }, + 'cart.itemAppend' : function(opts,$context) { +//** 201405 -> the correct behavior would be to override this default if you want a 'show' executed, not the opposite. +// $("[data-app-role='messageInput']",$context).show(); + $("[data-app-role='messageHistory']",$context).append("<p class='cart_item_append'>"+opts.FROM+" has added item "+opts.sku+" to the cart.<\/p>"); + }, + 'chat.post' : function(message,$context) { + dump(message); + //do not clear textarea for message input here. this gets run on the receiving side too and could clear something that was being written by the recipient of the chat.post. + var $history = $("[data-app-role='messageHistory']",$context); + $history.append("<p class='chat_post'><span class='from'>"+message.FROM+"<\/span> "+message.message+"<\/p>"); + $history.parent().scrollTop($history.height()); + } + }, + + +//////////////////////////////////// ACTION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +//actions are functions triggered by a user interaction, such as a click/tap. +//these are going the way of the do do, in favor of app events. new extensions should have few (if any) actions. + a : { + + showCartManager : function($target) { + dump("BEGIN showCartManager"); + $target.anycontent({'templateID':'adminCartManagementTemplate','data':{'carts':_app.vars.carts}}); + _app.u.addEventDelegation($target); + $target.anyform(); + _app.u.handleButtons($target); + _app.u.handleCommonPlugins($target); + + var $tbody = $("[data-app-role='cartManagementCartsTbody']",$target); //used for context below. + + for(var i = 0, L = _app.vars.carts.length; i < L; i += 1) { + var cartID = _app.vars.carts[i]; +// _app.u.dump("tr length: "+$("tr[data-value='"+_app.vars.carts[i]+"']",$tbody).length); + _app.calls.cartDetail.init(cartID,{ + 'callback':function(rd) { + $('.wait',rd.jqObj).removeClass('wait'); + if(_app.model.responseIsMissing(rd)) { + $('#globalMessaging').anymessage({'message':rd}); //use global, not jqobj, which is a tr. + rd._rtag.jqObj.hide(); + _app.model.removeCartFromSession(cartID); + } + else if(_app.model.responseHasErrors(rd)) { + $('#globalMessaging').anymessage({'message':rd}); //use global, not jqobj, which is a tr. + } + else { + console.log(" -> thisNestedExists: "+_app.u.thisNestedExists("data."+rd.datapointer+".our.domain",_app)); + _app.callbacks.anycontent.onSuccess(rd); + if(_app.u.thisNestedExists("data."+rd.datapointer+".our.domain",_app)) { + var dmObj = _app.ext.admin.u.domainMatchesPartitionInFocus(_app.data[rd.datapointer].our.domain); + if(dmObj.prt >= 0) { + rd.jqObj.find('td:first').append(dmObj.prt); + if(dmObj.isMatch) { + $('button',rd.jqObj).button('enable'); + } + else { + //wrong partition. can't edit. Carts are very partition specific. + } + } + } + else { + //no domain set on cart. hhhmmm... + rd.jqObj.find('td:first').append("<span class='toolTip' title='Unable to ascertain partition. Most likely, there is no domain for the cart. Editing the cart on a partition that it was not created on may result in unexpected behaviors.'>?</span>"); + $('button',rd.jqObj).button('enable'); + } + } + }, + 'jqObj':$("tr[data-value='"+cartID+"']",$tbody) + },'mutable'); + } + _app.model.dispatchThis('mutable'); + }, + +//used for admin. Presents user w/ a text input for adding a CSR code. Will return the cart id. + showCart2SessionDialog : function(onComplete) { + var $D = _app.ext.admin.i.dialogCreate({ + 'title' : 'Add a cart to the session', + 'showLoading' : false + }); + $D.addClass('smallButton').dialog('option','width',320); + $D.append("<p class='hint'>Use either a full cart ID or a CSR code.<\/p>"); + $D.append("<input type='text' name='csr' value='' required='required' class='fullWidth marginBottom' />"); + $("<button \/>").text('Add').button().on('click',function(event){ + event.preventDefault(); + var cartCSR = $("[name='csr']",$D).val(); //can either be a cartID or a CSR code. + if(cartCSR && cartCSR.length > 0) { + +//one of two cmds could get executed here. Regardless of which is executed, the same callback is triggered, which executed the oncomplete passed in and passes in the cart id. + var callback = function(rd) { + var thisCartid = false; + if(_app.model.responseHasErrors(rd)){ + $D.anymessage({'message':rd}); + } + else if(_app.model.responseIsMissing(rd)) { + $D.anymessage({'message':rd}); + } + else { + thisCartid = (rd.datapointer == 'adminCSRLookup') ? _app.data[rd.datapointer].cartid : _app.data[rd.datapointer].cart.cartid + $D.dialog('close'); + } + if(typeof onComplete == 'function') { + onComplete(thisCartid); + } + } + + if(cartCSR.length == 4) { + //at four characters, this is most likely a CSR code. + _app.model.addDispatchToQ({'_cmd':'adminCSRLookup','csr':$("[name='csr']",$D).val(),'_tag': {'datapointer':'adminCSRLookup','callback':callback}},'mutable'); + } + else if(cartCSR.length < 4) { + $D.anymessage({'message':"A CSR code must be four characters.","errtype":"youerr"}); + } + else { + _app.calls.cartDetail.init(cartCSR,{'callback' : callback},'mutable'); + } + } + else { + $D.anymessage({'message':"Please add a cart or csv code","errtype":"youerr"}); + } + + _app.model.dispatchThis('mutable'); + }).appendTo($D); + $D.dialog('open'); + }, + +//this is the full blown interface, for once a cart ID is obtained. + showAdminCMUI : function(cartID) { + if(cartID) { + var $UI = $("<div \/>"); + $UI.attr({'title':'CM: '+cartID,'id':'CM_'+cartID,'data-cartid':cartID}); + $UI.addClass('isCartMessengerDialog'); + $UI.anycontent({'templateID':'adminCartMessageTemplate'}).showLoading({'message':'Fetching cart detail'}); + _app.ext.cart_message.u.initCartMessenger(cartID,$("[data-app-role='cartMessenger']",$UI)); //starts the cart message polling. needs to be after the anycontent. + $UI.dialog({ + 'width' : '30%', + 'close' : function(event,ui) { + //log that the admin is leaving. + _app.ext.cart_message.cmResponse['chat.exit']("The admin has left the chat.",$UI); + _app.ext.cart_message.u.destroyCartMessenger($("[data-app-role='cartMessenger']",$(this)).data('cartid')); //kills the cart message polling + } + }); + + $("textarea[name='message']",$UI).on('keypress',function(event){ + if (event.keyCode == 13) { + $("[data-app-role='messageSubmitButton']",$(this).closest('form')).trigger('click'); + return false; + } + return true; + }); + + _app.model.addCart2Session(cartID); //update _app.vars.carts + _app.u.handleButtons($UI); + _app.u.addEventDelegation($UI); + $UI.anyform(); + _app.model.destroy('cartDetail|'+cartID); + _app.calls.cartDetail.init(cartID,{'callback':'anycontent','translateOnly':true,'jqObj':$UI,'onComplete':function(rd){ + //if no CID is set, lock the edit buyer button. + if(_app.data[rd.datapointer].customer.cid) { + $("[data-app-role='cartMessengerBuyerEditButton']",$UI).button('enable').attr('title','Edit customer record'); + } + }},'mutable'); + _app.model.dispatchThis('mutable'); + + + } + else { + $('#globalMessaging').anymessage({"message":"In cart_message.a.showAdminCMUI, no cart id was passed.","gMessage":true}); + } + } + }, //Actions + +//////////////////////////////////// RENDERFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +//renderFormats are what is used to actually output data. +//on a data-bind, format: is equal to a renderformat. extension: tells the rendering engine where to look for the renderFormat. +//that way, two render formats named the same (but in different extensions) don't overwrite each other. + renderFormats : { + pollDetect : function($tag,data) { + if(_app.u.thisNestedExists("ext.cart_message.vars.carts."+data.value+".timeout",_app)) { + $tag.append("<span class='ui-icon ui-icon-check'></span>") + } + else { + $tag.append('disabled'); //here for testing. ### TODO -> remove this output. + } + } + }, //renderFormats +//////////////////////////////////// UTIL [u] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +//utilities are typically functions that are exected by an event or action. +//any functions that are recycled should be here. + u : { + //cartMessagePush is here for doing quick, no nonsense updates to the cart message Q. no callbacks. + //a global alias is created for this: cartMessagePush + //cartid and what are required. ex: cartMessagePush(cartid,'cart.orderCreated'); + //P is optional and can support 'message' or 'vars'. + cartMessagePush : function(cartid,what,P) { + P = P || {}; + if(cartid && what) { + P._cmd = 'cartMessagePush'; + P.what = what; + P._cartid = cartid; + _app.model.addDispatchToQ(P,'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $("#globalMessaging").anymessage({"message":"In cartMessagePush, either cartid ["+cartid+"] or what ["+what+"] were left blank. both are required.","gMessage":true}); + dump("In cartMessagePush, either cartid ["+cartid+"] or what ["+what+"] were left blank.",'debug'); + } + }, + +/* +to immediately fetch the messages, pass in zero as 'when'. +This intentionally does NOT reset the polling var. If that needs to be reset, set it when this function is called. +That way cartmessages can be fetched without impacting the polling time, if desired. +*/ + fetchCartMessages : function(when,$context) { +// _app.u.dump(" -> queued up the next cartMessages cmd"); + var cartID = $context.data('cartid'); + if(cartID) { + _app.ext.cart_message.vars.carts[cartID].timeout = setTimeout(function(){ + + _app.model.addDispatchToQ({'_cmd':'cartMessageList','since':((_app.u.thisNestedExists("data.cartMessageList.SEQ",_app)) ? (_app.data.cartMessageList.SEQ) : 0),'_cartid':cartID,'_tag': {'datapointer' : 'cartMessageList','callback':'handleCartMessageListPolling','extension' : 'cart_message','jqObj':$context}},'passive'); + _app.model.dispatchThis('passive'); + },when); + } + else { + $context.anymessage({"message":"In cart_message.u.fetchCartMessages, $context did not have data('cartid') set. It is required.","gMessage":true}); + } + }, + +//a generic init for use on both sides of the force (buyer and admin). Any 'special' handling that is app specific should be added outside this function. + initCartMessenger : function(cartID,$context){ + if(cartID && $context instanceof jQuery) { + $context.data('cartid',cartID); + var messagesDPS = _app.model.dpsGet('cartMessages',cartID) || []; //, TS = _app.model.dpsGet('cartMessages','lastMessageTS') || 0, since = 0; + _app.ext.cart_message.vars.carts[cartID] = { + frequency : 7000, + timeout : null + } + + _app.model.addDispatchToQ({'_cmd':'cartMessageList','since':0,'_cartid':cartID,'_tag': { + 'datapointer' : 'cartMessageList', + 'callback':'handleCartMessageListPolling', + 'extension' : 'cart_message', + 'init':true, //pass along that this was requested as part of init. That way, if a large history is imported, event types can be skipped if necessary. + 'jqObj' : $context + }},'mutable'); //polling takes place on passive after initial call. starts on mutable just to piggy-back w/ rest of init calls. + } + else { + $('#globalMessaging').anymessage({"message":"In cart_message.u.initCartMessenger, either cartid ["+cartID+"] not set or $context ["+($context instanceof jQuery)+"] is not a valid jquery instance","gMessage":true}); + } + }, + +//use this in an ADMIN session when a cart message session has ended. +//if used on a storefront, the cart message polling will end. + destroyCartMessenger : function(cartID){ + if(cartID) { + window.clearTimeout(_app.ext.cart_message.vars.carts[cartID].timeout); + delete _app.ext.cart_message.vars.carts[cartID]; + } + else { + $('#globalMessaging').anymessage({"message":"In cart_message.u.destroyCartMessenger, cartid ["+cartID+"] not set and is required.","gMessage":true}); + } + } + }, //u [utilities] + +//app-events are added to an element through data-app-event="extensionName|functionName" +//right now, these are not fully supported, but they will be going forward. +//they're used heavily in the admin.html file. +//while no naming convention is stricly forced, +//when adding an event, be sure to do off('click.appEventName') and then on('click.appEventName') to ensure the same event is not double-added if app events were to get run again over the same template. + e : { + adminCartInteract : function($ele,p) { + //only 1 cart messenger instance can be open at a time. + $('.isCartMessengerDialog').each(function(){ + $(this).dialog('close').dialog('destroy').intervaledEmpty(); + cartMessagePush($(this).data('cartid'),'chat.exit'); + }); + + var cartid = $ele.closest("[data-cartid]").data('cartid'); + cartMessagePush(cartid,'chat.join'); + _app.ext.cart_message.a.showAdminCMUI(cartid); + }, + + adminCartRemoveFromSession : function($ele,p) { + _app.model.removeCartFromSession($ele.closest("[data-cartid]").data('cartid')); + $ele.closest('tr').empty().remove(); + }, + + adminCartAddToSession : function($ele,p) { + //_app.ext.cart_message.a.showAdminCMUI(_app.data[rd.datapointer].cartid); + _app.ext.cart_message.a.showCart2SessionDialog(function(cartid){ + if(cartid) { + _app.model.addCart2Session(cartid); + navigateTo('#!ext/cart_message/showCartManager'); + } + else { +//Error display is handled in the cart2session dialog. false WILL be returned into this function so that additional error handling can be added. + } + }); + }, + + cartEditExec : function($ele,p) { + p.preventDefault(); + var cartID = $ele.closest("[data-app-role='cartMessenger']").data('cartid') || $ele.closest("[data-cartid]").data('cartid'); + if(cartID) { + navigateTo('#!ext/order_create/editCart',{'cartid':cartID}); + } + else { + $('#globalMessaging').anymessage({'message':'In cart_message.e.chatPostExec, unable to ascertain cartID.','gMessage':true}); + } + }, + + gotoProductShowChooser : function($ele,p) { + p.preventDefault(); + var $buttons = $("<div \/>").data('cartid',$ele.closest("[data-app-role='cartMessenger']").data('cartid')); //the data(cartid) here is used on the events for the buttons appended to this element + $("<button \/>").text('Send to Buyer').attr('data-app-click','cart_message|gotoProductExec').button().appendTo($buttons); +// $("<button \/>").text('Add to Cart').attr('data-app-click','order_create|cartItemAddWithChooser').button().appendTo($buttons); + + _app.ext.admin.a.showFinderInModal('CHOOSER','','',{'$buttons' : $buttons,'classname':'cartMessageChooser'}); + _app.u.addEventDelegation($buttons); + }, + + gotoProductExec : function($ele,p) { + p.preventDefault(); + var sku = $("input[name='sku']",'#chooserResultContainer').val(); + //cart id on parent set by gotoProductShowChooser + cartMessagePush(cartid,'goto.product',{'vars':{'pid':sku},'_cartid':$ele.parent().data('cartid')}); + $('#prodFinder').anymessage({'message':'Product '+sku+' sent to buyer.','errtype':'done'}); + }, + + buyerEditExec : function($ele,p) { + p.preventDefault(); + var cartID = $ele.closest("[data-app-role='cartMessenger']").data('cartid'); + alert('not done yet'); + // ### TODO -> finish this. + }, + //will add a chat post to the log. Could be executed by either an admin or buyer. + chatPostExec : function($ele,p) { + p.preventDefault(); + var $fieldset = $ele.closest('fieldset'), cartID = $ele.closest("[data-app-role='cartMessenger']").data('cartid'); + if(_app.u.validateForm($fieldset) && cartID) { + var $message = $ele.closest('fieldset').find("[name='message']"); + cartMessagePush(cartID,'chat.post',{'message':$message.val()}); + _app.ext.cart_message.u.fetchCartMessages(0,$ele.closest("[data-app-role='cartMessenger']")); + $message.val(""); //reset textarea. + } + else { + //validateForm handles error display if form contents not populated. + if(!cartID) { + $fieldset.anymessage({'message':'In cart_message.e.chatPostExec, unable to ascertain cartID.','gMessage':true}); + } + } + }, //chatPostExec + + cartCSRShortcutExec : function($ele,p) { + var cartID = $ele.closest("[data-app-role='cartMessenger']").data('cartid'); + if(cartID) { + _app.model.addDispatchToQ({'_cmd':'cartCSRShortcut','_cartid':cartID,'_tag': {'datapointer' : 'cartCSRShortcut','callback':function(rd){ + if(_app.model.responseHasErrors(rd)){ + $('#globalMessaging').anymessage({'message':rd}); + } + else { + //success content goes here. + $("<div \/>").append("Cart Shortcut: "+_app.data[rd.datapointer].csr).dialog({'modal':true}); + } + }}},'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $('#globalMessaging').anymessage({"message":"In cart_message.e.cartCSRShortcutExec, unable to ascertain cartid.","gMessage":true}); + } + }, //cartCSRLShortcutExec + + chatInitExec : function($ele,p) { + p.preventDefault(); + var cartID = $ele.closest("[data-app-role='cartMessenger']").data('cartid'); + if(cartID) { + cartMessagePush(cartID,'chat.join'); + _app.ext.cart_message.u.fetchCartMessages(0,$ele.closest("[data-app-role='cartMessenger']")); + $ele.hide(); + } + else { + $('#globalMessaging').anymessage({"message":"In cart_message.e.chatInitExec, unable to ascertain cartid.","gMessage":true}); + } + } //chatInitExec + + } //e [app Events] + } //r object. + return r; + } \ No newline at end of file diff --git a/extensions/cart_message/styles.css b/extensions/cart_message/styles.css new file mode 100644 index 000000000..f06c81fad --- /dev/null +++ b/extensions/cart_message/styles.css @@ -0,0 +1,21 @@ +/* +For the buyer side... +*/ + +#cartMessenger {font-weight:normal;} +.messageHistoryContainer {max-height:120px; overflow:auto; font-size:.8em; margin-bottom: .8em;} +.messageInputContainer {padding:0; margin:0; margin-bottom:.8em; border:0;} +.messageInputContainer textarea { + height:60px; + font-weight:normal; + display:block; + width:100%; + box-sizing:border-box; + -moz-box-sizing:border-box; + webkit-box-sizing:border-box; + } +.selfMessage {color:#366;} +.otherMessage {color:#639;} + + +.cartMessageChooser .chooserAddToCartForm {display:none;} diff --git a/extensions/cart_message/templates.html b/extensions/cart_message/templates.html new file mode 100644 index 000000000..a1fd5625a --- /dev/null +++ b/extensions/cart_message/templates.html @@ -0,0 +1,69 @@ + +<div id='adminCartManagementTemplate' class='ui-widget' data-tablefilter-role='container'> + <div class="ui-widget-header ui-widget-header-padding ui-corner-top"> + <span class='floatRight smallPadding'> + <input name='tableSearchQuery' type='search' placeholder='filter value' x-webkit-speech="x-webkit-speech" data-app-keyup="admin|tableFilter" /> + <button data-app-click="cart_message|adminCartAddToSession" class='applyButton marginLeft' data-text='true' data-icon-primary='ui-icon-plus'>Add Cart</button> + </span> + <h2>Cart Management</h2> + </div> + <div class='ui-widget-content ui-corner-bottom stdPadding'> + <table class='fullWidth gridTable applyAnytable' data-tablefilter-role='table'> + <thead> + <tr> + <th data-anytable-nosort='true'></th> + <th>Cart ID</th> + <th>First Name</th> + <th>Last Name</th> + <th># Items</th> + <th>Domain</th> + <th>Active Polling <span class='toolTip' title="If this is on, the admin app is actively checking for updates on this cart. If you are not interacting with the cart, you should disable this to improve performance.">?</span></th> + <th data-anytable-nosort='true'></th> + </tr> + </thead> + <tbody data-bind='var:carts(carts); format:processList; loadsTemplate:adminCartManagementRowTemplate;' data-app-role='cartManagementCartsTbody'></tbody> + </table> + </div> +</div> + + + +<table> +<tr id='adminCartManagementRowTemplate'> + <td><span class='wait'></span></td> + <td class='isSearchable' data-bind="var: cart(value); format:text;"></td><!-- the carts array passed in has the cartID as the value, which process list sets as value --> + <td class='isSearchable' data-bind="var: cart(bill/firstname); format:text;"></td> + <td class='isSearchable' data-bind="var: cart(bill/lastname); format:text;"></td> + <td data-bind="var: cart(sum/items_count); format:text;"></td> + <td data-bind="var: cart(our/domain); format:text;"></td> + <td data-bind="var: cart(value); format:pollDetect; extension:cart_message;"></td> + <td data-bind='var:cart(value);format:assignAttribute; attribute:data-cartid;' class='alignRight'> + + <button data-text='false' data-icon-primary='ui-icon-close' class='applyButton' data-app-click='cart_message|adminCartRemoveFromSession'>Remove from Session</button> + <button data-text='false' data-icon-primary='ui-icon-cart' disabled='disabled' class='applyButton' data-app-click='cart_message|cartEditExec' data-app-role='cartEditButton'>Edit Cart</button> + <button data-text='false' data-icon-primary='ui-icon-comment' disabled='disabled' class='applyButton' data-app-click='cart_message|adminCartInteract'>Interact</button> + </td> +</tr> +</table> + + + +<div id='adminCartMessageTemplate' data-app-role='cartMessenger'> + <form action='#' onsubmit="return false;" novalidate='novalidate'> + <!-- size is set on this element, but messages are appended to the child. allows messageHIstory height to be computed for scolltop --> + <div class='messageHistoryContainer' data-app-role='messageHistoryContainer'> + <section data-app-role='messageHistory'></section> + </div> + <fieldset data-app-role='messageInput' class='smallButton messageInputContainer'> + <textarea name='message' required='required' placeholder='send a message'></textarea> + <button class='applyButton' data-app-click='cart_message|chatPostExec' data-app-role='messageSubmitButton'>Send</button> + </fieldset> + <section data-app-role='messageCommands' class='messageCommandsContainer'> +<!-- <button class='applyButton' data-app-click="cart_message|chatInitExec" title="">Initiate Chat</button>opens a chat dialog if an buyer is on an app 201401+ --> + <button class='applyButton' data-app-click='cart_message|cartEditExec'>Edit Cart</button><!-- opens cart in order create/edit interface --> + <button class='applyButton' data-app-click='cart_message|gotoProductShowChooser'>Send Product</button><!-- opens product chooser and allows admin to send a given product to the buyer --> + <button class='applyButton' data-app-role='cartMessengerBuyerEditButton' data-app-click='cart_message|customerEditExec' disabled="disabled" title='There is no customer record associated with this cart.'>Edit Customer</button><!-- opens customer in customer editor interface --> +<!-- <button>Show Page</button>allows admin to send a product/category/results to buyer --> + </section> + </form> +</div> diff --git a/extensions/cart_quickadd/extension.js b/extensions/cart_quickadd/extension.js index 896f8b9ea..de4ddf82d 100644 --- a/extensions/cart_quickadd/extension.js +++ b/extensions/cart_quickadd/extension.js @@ -28,7 +28,7 @@ Dependencies: store_product (for add to cart validation). To implement, change the action on the productTemplate Add to cart to this: -onSubmit="app.ext.cart_quickadd.a.addItemToCart($(this)); return false;" +onSubmit="_app.ext.cart_quickadd.a.addItemToCart($(this)); return false;" OR, if app events are supported in the product layout (they are not at this time, but it's anticipated): <form data-app-event="cart_quickadd|execQuickaddCartAppend"... @@ -36,7 +36,7 @@ OR, if app events are supported in the product layout (they are not at this time */ -var cart_quickadd = function() { +var cart_quickadd = function(_app) { var theseTemplates = new Array('cartQuickaddTemplate'); var r = { @@ -55,8 +55,8 @@ var cart_quickadd = function() { init : { onSuccess : function() { var r = false; //return false if extension won't load for some reason (account config, dependencies, etc). - if(app.ext.cart_quickadd.vars.willFetchMyOwnTemplates) { - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/cart_quickadd/templates.html',theseTemplates); + if(_app.ext.cart_quickadd.vars.willFetchMyOwnTemplates) { + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/cart_quickadd/templates.html',theseTemplates); } //if there is any functionality required for this extension to load, put it here. such as a check for async google, the FB object, etc. return false if dependencies are not present. don't check for other extensions. r = true; @@ -66,7 +66,7 @@ var cart_quickadd = function() { onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } }, //callbacks @@ -84,24 +84,24 @@ var cart_quickadd = function() { var quickAddCallback = function(rd){ var $QC = $("#quickaddCart") $QC.hideLoading(); //only close on error. otherwise leave for removal in subsequent call. - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $QC.anymessage({'message':rd}); } else { - $QC.anycontent({'templateID':'cartQuickaddTemplate',data:app.data['appProductGet|'+$("input[name='sku']",$form).val()]}); - app.u.handleAppEvents($QC); + $QC.anycontent({'templateID':'cartQuickaddTemplate',data:_app.data['appProductGet|'+$("input[name='sku']",$form).val()]}); + _app.u.handleAppEvents($QC); } //close panel whether a success or error is shown. setTimeout(function(){ if($QC.is(':visible')) { - app.ext.cart_quickadd.u.cartHide(); + _app.ext.cart_quickadd.u.cartHide(); } else {} //already minimized, do nothing. },5000); } //the handle add to cart will take care of variations validation and error display. - if(app.ext.store_product.u.handleAddToCart($form,{'callback':quickAddCallback})) { - app.ext.cart_quickadd.u.cartShow(); //opens the cart and goes into a 'loading' state. + if(_app.ext.store_product.u.handleAddToCart($form,{'callback':quickAddCallback})) { + _app.ext.cart_quickadd.u.cartShow(); //opens the cart and goes into a 'loading' state. } else {} //no default 'fail' action. the function above handles it. } //addItemToCart @@ -111,7 +111,7 @@ var cart_quickadd = function() { u : { cartShow : function() { - app.u.dump("BEGIN cart_quickadd.u.cartShow"); + _app.u.dump("BEGIN cart_quickadd.u.cartShow"); var $QC = $("#quickaddCart"); if($QC.length) {$QC.empty()} else { @@ -148,14 +148,14 @@ var cart_quickadd = function() { $btn.button(); $btn.off('click.execQuickaddCartHide').on('click.execQuickaddCartHide',function(event){ event.preventDefault(); - app.ext.cart_quickadd.u.cartHide(); + _app.ext.cart_quickadd.u.cartHide(); }); }, //execQuickaddCartHide execQuickaddCartAppend : function($form) { $form.off('submit.execQuickaddCartAppend').on('submit.execQuickaddCartAppend',function(event){ event.preventDefault(); - app.ext.cart_quickadd.a.addItemToCart($form); + _app.ext.cart_quickadd.a.addItemToCart($form); }); }, //execQuickaddCartAppend @@ -163,7 +163,7 @@ var cart_quickadd = function() { $btn.button(); $btn.off('click.execCheckout').on('click.execCheckout',function(event){ event.preventDefault(); - app.ext.cart_quickadd.u.cartHide(); + _app.ext.cart_quickadd.u.cartHide(); showContent('checkout',{'show':'checkout'}); }); } //execCheckoutShow diff --git a/extensions/checkout/active.html b/extensions/checkout/active.html index 3f770cec9..d817023d1 100644 --- a/extensions/checkout/active.html +++ b/extensions/checkout/active.html @@ -7,43 +7,44 @@ item list and summary are separate just to give more control over location. --> -<div id='checkoutTemplate' class='checkoutFormContainer' data-app-role='checkout'> +<div id="checkoutTemplate" class="checkoutFormContainer" data-app-role="checkout"> - <form action='#'> - <input type='hidden' name='bill/shortcut' data-bind="var: cart(bill/shortcut); format:popVal;" /> - <input type='hidden' name='ship/shortcut' data-bind="var: cart(ship/shortcut); format:popVal;" /> + <form action="#"> + <input data-tlc="bind $var '.bill.shortcut'; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/shortcut" type="hidden"> + <input data-tlc="bind $var '.ship.shortcut'; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/shortcut" type="hidden"> + <input data-tlc="bind $var '.cart.cartid'; if(is $var --notblank;) {{apply --select=$var;}}; " name="_cartid" type="hidden"> <!-- define panel order --> - <fieldset data-app-role='chkoutPreflight' class='marginBottom'> - <legend class='headerPadding' >Email / Account Login</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutPreflightTemplate; useParentData:true;'></div> - <div data-app-role='buyerLogout' class='displayNone pointer' data-app-event='orderCreate|buyerLogout'> - Not you? <span class='lookLikeLink zlink'>click here</span>. + <fieldset data-app-role="chkoutPreflight" class="marginBottom"> + <legend class="headerPadding">Email / Account Login</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutPreflightTemplate'; apply --append;" data-legacy-useparentdata="true" class="panelContent"></div> + <div data-app-role="buyerLogout" class="displayNone pointer" data-app-click="order_create|buyerLogout"> + Not you? <span class="lookLikeLink zlink">click here</span>. </div> </fieldset> - <fieldset data-app-role='chkoutAccountCreate' class='displayNone marginBottom'> - <legend class='headerPadding' >Account Creation</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutAccountCreateTemplate; '></div> + <fieldset data-app-role="chkoutAccountCreate" class="displayNone marginBottom"> + <legend class="headerPadding">Account Creation</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAccountCreateTemplate'; apply --append;" class="panelContent"></div> </fieldset> - <fieldset data-app-role='chkoutAddressBill' data-app-addresstype='bill' class='marginBottom'> - <legend class='headerPadding' >Billing Address</legend> - <p data-app-role='addressExists' class='displayNone clearfix'>Click the checkmark of the address you would like to use</p> + <fieldset data-app-role="chkoutAddressBill" data-app-addresstype="bill" class="marginBottom"> + <legend class="headerPadding">Billing Address</legend> + <p data-app-role="addressExists" class="displayNone clearfix">Click the checkmark of the address you would like to use</p> - <div class='panelContent displayNone addressList' data-app-role='addressExists' data-bind='var: buyer(@bill); format:processList; loadsTemplate: chkoutBuyerAddressTemplate;'></div><!-- for return customers --> + <div data-tlc="bind $var '.@bill'; controller#loop --templateid='chkoutBuyerAddressTemplate'; if (is $var --notblank;) {{apply --append;}};" class="panelContent displayNone addressList" data-app-role="addressExists"></div><!-- for return customers --> - <div class='clearfix marginBottom' data-app-role='addressExists'><button data-app-event='orderCreate|showBuyerAddressAdd' data-app-addresstype='bill'>Add New Address</button></div> + <div class="clearfix marginBottom" data-app-role="addressExists"><button class="applyButton" data-app-click="order_create|showBuyerAddressAdd" data-app-addresstype="bill">Add New Address</button></div> - <div class='panelContent' data-app-role='addressNew' data-bind='format:loadsTemplate; loadsTemplate: chkoutAddressBillTemplate;'></div><!-- for new customers --> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAddressBillTemplate'; apply --append;" class="panelContent" data-app-role="addressNew"></div><!-- for new customers --> - <div data-app-role='billToShipContainer' > + <div data-app-role="billToShipContainer"> <label> - <input type='checkbox' name='want/bill_to_ship' data-bind="var: cart(want/bill_to_ship); format:popVal; hideZero:false;" checked='checked' data-app-event='orderCreate|tagAsBillToShip' /> + <input data-tlc="bind $var '.want.bill_to_ship'; if(is $var --notblank;) {{apply --select=$var;}}; " name="want/bill_to_ship" checked="checked" class="applyAnycb" data-app-change="order_create|tagAsBillToShip" type="checkbox"> ship to billing address </label> </div> @@ -51,49 +52,49 @@ - <fieldset data-app-role='chkoutAddressShip' data-app-addresstype='ship' class='displayNone marginBottom'> - <legend class='headerPadding' >Shipping Address</legend> - <div class='panelContent displayNone addressList' data-app-role='addressExists' data-bind='var: buyer(@ship); format:processList; loadsTemplate: chkoutBuyerAddressTemplate;'></div><!-- for return customers --> - <div class='panelContent' data-app-role='addressNew' data-bind='format:loadsTemplate; loadsTemplate: chkoutAddressShipTemplate;'></div><!-- for new customers --> - <div class='clearfix' data-app-role='addressExists'><button data-app-event='orderCreate|showBuyerAddressAdd' data-app-addresstype='ship'>Add New Shipping Address</button></div> + <fieldset data-app-role="chkoutAddressShip" data-app-addresstype="ship" class="displayNone marginBottom"> + <legend class="headerPadding">Shipping Address</legend> + <div data-tlc="bind $var '.@ship'; controller#loop --templateid='chkoutBuyerAddressTemplate'; if (is $var --notblank;) {{apply --append;}};" class="panelContent displayNone addressList" data-app-role="addressExists"></div><!-- for return customers --> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAddressShipTemplate'; apply --append;" class="panelContent" data-app-role="addressNew"></div><!-- for new customers --> + <div class="clearfix" data-app-role="addressExists"><button class="applyButton" data-app-click="order_create|showBuyerAddressAdd" data-app-addresstype="ship">Add New Shipping Address</button></div> </fieldset> - <fieldset data-app-role='chkoutMethodsShip' class='marginBottom'> - <legend class='headerPadding' >Shipping Methods</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutMethodsShipTemplate;'></div> + <fieldset data-app-role="chkoutMethodsShip" class="marginBottom"> + <legend class="headerPadding">Shipping Methods</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutMethodsShipTemplate'; apply --append;" class="panelContent"></div> </fieldset> - <fieldset data-app-role='chkoutMethodsPay' class='marginBottom'> - <legend class='headerPadding' >Payment Choices</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutMethodsPayTemplate;'></div> + <fieldset data-app-role="chkoutMethodsPay" class="marginBottom"> + <legend class="headerPadding">Payment Choices</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutMethodsPayTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- totals et all --> - <fieldset data-app-role='chkoutNotes' class='marginBottom'> - <legend class='headerPadding' >Order Notes/Special Instructions</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutNotesTemplate;'></div> + <fieldset data-app-role="chkoutNotes" class="marginBottom"> + <legend class="headerPadding">Order Notes/Special Instructions</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutNotesTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- line items --> - <fieldset data-app-role='chkoutCartItemsList' class='marginBottom'> - <legend class='headerPadding' >Contents</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutCartContentsTemplate;'></div> + <fieldset data-app-role="chkoutCartItemsList" class="marginBottom"> + <legend class="headerPadding">Contents</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutCartContentsTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- totals et all --> - <fieldset data-app-role='chkoutCartSummary' class='marginBottom'> - <legend class='headerPadding' >Summary</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutCartSummaryTemplate;'></div> + <fieldset data-app-role="chkoutCartSummary" class="marginBottom"> + <legend class="headerPadding">Summary</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutCartSummaryTemplate'; apply --append;" class="panelContent"></div> </fieldset> </form> @@ -103,21 +104,22 @@ -<section id='chkoutPreflightTemplate'> +<section id="chkoutPreflightTemplate"> -<h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email); defaultVar: cart(customer/login); format:text;"></h4> - -<div data-app-role='login'> - - <div data-app-role='loginPasswordContainer' class='displayNone floatRight passwordContainer'> - <div>If you have an account with us, please enter your password below to login</div> - <input type='password' placeholder='password' size='30' name='password' /><button data-app-event='orderCreate|execBuyerLogin'>login</button> + <h4 data-tlc="bind $var '.bill.email'; if(is $var --blank;) {{bind $var '.customer.login'; }}; if (is $var --notblank;) {{apply --append;}};" class="displayNone" data-app-role="username"></h4> + + <div data-app-role="login"> + <div class='floatLeft marginBottom'> + <input data-tlc="bind $var '.bill.email'; if(is $var --blank;) {{bind $var '.customer.login'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " required name="bill/email" size="30" placeholder="email address" data-app-blur="order_create|execBuyerEmailUpdate" type="email"><br> + <label class="accountCreateContainer"><input name="want/create_customer" class="applyAnycb" data-app-change="order_create|tagAsAccountCreate" type="checkbox" >Create account</label> + </div> + + <div data-app-role="loginPasswordContainer" class="displayNone floatRight passwordContainer"> + <div>If you have an account with us, please enter your password below to login</div> + <input placeholder="password" size="30" name="password" type="password"><button class="applyButton" data-app-click="order_create|execBuyerLogin">login</button> + </div> </div> - <input type='email' required='required' name='bill/email' size='30' placeholder="email address" data-bind="var:cart(bill/email); defaultVar:cart(customer/login); format:popVal;" data-app-event='orderCreate|execBuyerEmailUpdate' /><br /> - <label class='accountCreateContainer'><input type='checkbox' name='want/create_customer' data-app-event='orderCreate|tagAsAccountCreate' />Create customer account</label> -</div> - </section> @@ -131,29 +133,31 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) <!-- billing address panel spec This template is also used in the myAccount page, which is why a default using _ is present. +This template is used both in the billing address panel AND in the address editor (if logged in). in the address editor, the data is formatted as bill/address1 +because the panel is shared, the events (which aren't desired in the editor) are added by the checkout extension. --> -<section id='chkoutAddressBillTemplate'> +<section id="chkoutAddressBillTemplate"> - <div><input type='text' placeholder='first name' name='bill/firstname' required='required' value='' data-bind='var: cart(bill/firstname); defaultVar: cart(bill/firstname); format:popVal;' /></div> - <div><input type='text' placeholder='last name' name='bill/lastname' required='required' value='' data-bind='var: cart(bill/lastname); defaultVar: cart(bill/lastname); format:popVal;' /></div> + <div><input data-tlc="bind $var '.bill.firstname'; if(is $var --blank;){{bind $var '.bill/firstname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="bill/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.bill.lastname'; if(is $var --blank;){{bind $var '.bill/lastname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="bill/lastname" required value="" type="text"></div> - <div class='bill_company'><input type='text' name='bill/company' placeholder='company' value='' data-bind='var: cart(bill/company); defaultVar: cart(bill/company); format:popVal;' /></div><!-- class is added so it can be easily disabled w/ css --> + <div class="bill_company"><input data-tlc="bind $var '.bill.company'; if(is $var --blank;){{bind $var '.bill/company';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> - <div><input type='text' name='bill/address1' placeholder='address' required='required' value='' data-bind='var: cart(bill/address1); defaultVar: cart(bill/address1); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.address1'; if(is $var --blank;){{bind $var '.bill/address1';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/address1" placeholder="address" required value="" type="text"></div> - <div><input type='text' name='bill/address2' placeholder='address 2' value='' data-bind='var: cart(bill/address2); defaultVar: cart(bill/address2); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.address2'; if(is $var --blank;){{bind $var '.bill/address2';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/address2" placeholder="address 2" value="" type="text"></div> - <div><input type='text' name='bill/city' placeholder='city' required='required' value='' data-bind='var: cart(bill/city); defaultVar: cart(bill/city); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.city'; if(is $var --blank;){{bind $var '.bill/city';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/city" placeholder="city" required value="" type="text"></div> - <div><input type='text' name='bill/region' placeholder='state/region' required='required' size='5' value='' data-bind='var: cart(bill/region); defaultVar: cart(bill/region); format:popVal;' maxlength='20' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.region'; if(is $var --blank;){{bind $var '.bill/region';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/region" placeholder="state/region" required size="5" value="" maxlength="20" type="text"></div> <!-- postal not required for international. don't add it. --> - <div><input type='text' name='bill/postal' placeholder='zip/postal code' required='required' size='14' value='' data-bind='var: cart(bill/postal); defaultVar: cart(bill/postal); format:popVal;' maxlength='10' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.postal'; if(is $var --blank;){{bind $var '.bill/postal';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" type="text"></div> - <div class='billCountry' data-app-role='billCountry'><select name='bill/countrycode' placeholder='country' data-bind='var: cart(bill/countrycode); defaultVar: cart(bill/countrycode); defaultValue:US; format:countriesAsOptions; extension: cco;forceRender:1;' required='required' data-app-event="orderCreate|execCountryUpdate" ></select></div> + <div class="billCountry" data-app-role="billCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='bill' --legacy;" data-legacy-useparentdata="true" name="bill/countrycode" placeholder="country" required="required"><option value=''>Please choose</option></select></div> - <div><input type='tel' name='bill/phone' placeholder='phone number' required='required' value='' data-bind='var: cart(bill/phone); defaultVar: cart(bill/phone); format:popVal;' /> <span class='hint zhint'>in case of billing/delivery problems</span></div> + <div><input data-tlc="bind $var '.bill.phone'; if(is $var --blank;){{bind $var '.bill/phone';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/phone" placeholder="phone number" required value="" type="tel"> <span class="hint zhint">in case of billing/delivery problems</span></div> </section> @@ -164,46 +168,48 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) <!-- shipping address panel. don't add required to any inputs because if bill to ship is checked, NONE of these fields are required/populated. +This template is used both in the shipping panel AND in the address editor (if logged in). in the address editor, the data is formatted as ship/address1 +because the panel is shared, the events (which aren't desired in the editor) are added by the checkout extension. --> -<section id='chkoutAddressShipTemplate'> +<section id="chkoutAddressShipTemplate"> - <div><input type='text' placeholder='first name' name='ship/firstname' required='required' value='' data-bind='var: cart(ship/firstname); defaultVar: cart(ship/firstname); format:popVal;' /></div> - <div><input type='text' placeholder='last name' name='ship/lastname' required='required' value='' data-bind='var: cart(ship/lastname); defaultVar: cart(ship/lastname); format:popVal;' /></div> + <div><input data-tlc="bind $var '.ship.firstname'; if(is $var --blank;){{bind $var '.ship/firstname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="ship/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.ship.lastname'; if(is $var --blank;){{bind $var '.ship/lastname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="ship/lastname" required value="" type="text"></div> - <div class='bill_company'><input type='text' name='ship/company' placeholder='company' value='' data-bind='var: cart(ship/company); defaultVar: cart(ship/company); format:popVal;' /></div><!-- class is added so it can be easily disabled w/ css --> + <div class="bill_company"><input data-tlc="bind $var '.ship.company'; if(is $var --blank;){{bind $var '.ship/company';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> - <div><input type='text' name='ship/address1' placeholder='address' required='required' value='' data-bind='var: cart(ship/address1); defaultVar: cart(ship/address1); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.address1'; if(is $var --blank;){{bind $var '.ship/address1';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address1" placeholder="address" required value="" type="text"></div> - <div><input type='text' name='ship/address2' placeholder='address 2' value='' data-bind='var: cart(ship/address2); defaultVar: cart(ship/address2); format:popVal;' /></div> + <div><input data-tlc="bind $var '.ship.address2'; if(is $var --blank;){{bind $var '.ship/address2';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address2" placeholder="address 2" value="" type="text"></div> - <div><input type='text' name='ship/city' placeholder='city' required='required' value='' data-bind='var: cart(ship/city); defaultVar: cart(ship/city); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.city'; if(is $var --blank;){{bind $var '.ship/city';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/city" placeholder="city" required value="" type="text"></div> - <div><input type='text' name='ship/region' placeholder='state/region' required='required' size='5' value='' data-bind='var: cart(ship/region); defaultVar: cart(ship/region); format:popVal;' maxlength='20' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.region'; if(is $var --blank;){{bind $var '.ship/region';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/region" placeholder="state/region" required size="5" value="" maxlength="20" type="text"></div> - <div><input type='text' name='ship/postal' placeholder='zip/postal code' required='required' size='14' value='' data-bind='var: cart(ship/postal); defaultVar: cart(ship/postal); format:popVal;' maxlength='10' data-app-event='orderCreate|execAddressUpdate'/></div> + <div><input data-tlc="bind $var '.ship.postal'; if(is $var --blank;){{bind $var '.ship/postal';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" type="text"></div> - <div class='shipCountry' data-app-role='shipCountry'><select name='ship/countrycode' placeholder='country' data-bind='var: cart(ship/countrycode); defaultVar: cart(ship/countrycode); defaultValue:US; format:countriesAsOptions; extension: cco;forceRender:1;' data-app-event="orderCreate|execCountryUpdate" ></select></div> + <div class="shipCountry" data-app-role="shipCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='ship' --legacy;" data-legacy-useparentdata="true" name="ship/countrycode" placeholder="country"><option value=''>Please choose</option></select></div> </section> <!-- a panel that only appears in 'nice' --> -<section id='chkoutAccountCreateTemplate'> +<section id="chkoutAccountCreateTemplate"> -<div><input type='password' data-minlength='8' placeholder='password' required='required' name='want/new_password' size='12' data-bind='var: cart(want/new_password); format:popVal;' /> <span class='hint'>must be at least 8 characters</span></div> -<div><input type='password' data-minlength='8' placeholder='verify password' required='required' name='want/new_password2' size='12' data-bind='var: cart(want/new_password2); format:popVal;' /></div> +<div><input data-tlc="bind $var '.want.new_password'; if(is $var --notblank;) {{apply --select=$var;}}; " data-minlength="8" placeholder="password" required name="want/new_password" size="12" type="password"> <span class="hint">must be at least 8 characters</span></div> +<div><input data-tlc="bind $var '.want.new_password2'; if(is $var --notblank;) {{apply --select=$var;}}; " data-minlength="8" placeholder="verify password" required name="want/new_password2" size="12" type="password"></div> <label>Recovery Question -<select name='want/recovery_hint' data-bind='var: cart(want/recovery_hint); format:popVal;'> - <option value='2'>Name of your favorite childhood pet?</option> - <option value='3'>City you were born in?</option> - <option value='4'>Last name of your best friend growing up?</option> - <option value='5'>Last city you lived in?</option> +<select data-tlc="bind $var '.want.recovery_hint'; if(is $var --notblank;) {{apply --select=$var;}}; " name="want/recovery_hint"> + <option value="2">Name of your favorite childhood pet?</option> + <option value="3">City you were born in?</option> + <option value="4">Last name of your best friend growing up?</option> + <option value="5">Last city you lived in?</option> </select> </label> -<input type='text' placeholder='recovery answer' required='required' value='' name='want/recovery_answer' maxlength='20' size='20' data-bind='var: cart(want/recovery_answer); format:popVal;' /></label> +<input data-tlc="bind $var '.want.recovery_answer'; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="recovery answer" required value="" name="want/recovery_answer" maxlength="20" size="20" type="text"> </section> @@ -215,8 +221,9 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) messaging are hidden by default, then displayed if needed. keeps panel from being jittery. --> -<div id='chkoutMethodsShipTemplate'> - <ul class='noPadOrMargin listStyleNone' data-bind='var: cart(@SHIPMETHODS); format:shipMethodsAsRadioButtons; extension: orderCreate;' data-app-event='orderCreate|addTriggerShipMethodUpdate'></ul> +<div id="chkoutMethodsShipTemplate"> + <ul data-tlc="bind $var '.'; order_create#shipmethodsasradiobuttons --legacy;" data-legacy-useparentdata="true" class="noPadOrMargin listStyleNone"></ul> + <div data-app-role="upsShipRulesDisclaimer" class="upsShipRulesDisclaimer displayNone">These fees do not necessarily represent UPS published rates and may include handling charges by our company.</div> </div> @@ -232,35 +239,35 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) --> -<div id='chkoutMethodsPayTemplate'> +<div id="chkoutMethodsPayTemplate"> - <div class='giftCardContainer' data-app-role="giftcardContainer"> - <label for='giftcardCode'>Gift Certificate Code:</label> - <input type='text' name='giftcard' size='16' data-app-event='orderCreate|addTriggerButtonClick' /> - <button data-app-event='orderCreate|execGiftcardAdd'>add</button> - <small data-app-role='giftcardHint' class='zhint hint displayNone'>if you wish to combine gift cards with another payment method, enter them here</small> + <div class="giftCardContainer" data-app-role="giftcardContainer"> + <label for="giftcardCode">Gift Certificate Code:</label> + <input name="giftcard" size="16" data-input-keyup="trigger-button-id" data-input-format="alphanumeric" data-trigger-button-id="execGiftcardAdd" type="text"> + <button class="applyButton" data-app-click="order_create|execGiftcardAdd" data-button-id="execGiftcardAdd">add</button> + <p data-app-role="giftcardHint" class="zhint hint displayNone">if you wish to combine gift cards with another payment method, enter them here</p> </div> - <div data-app-role='paymentQContainer' class='marginBottom'> - <ul class='noPadOrMargin listStyleNone' data-bind='var: cart(@PAYMENTQ); format:processList; loadsTemplate:cartPaymentQTemplate;'></ul> + <div data-app-role="paymentQContainer" class="marginBottom"> + <ul data-tlc="bind $var '.@PAYMENTQ'; controller#loop --templateid='cartPaymentQTemplate'; if (is $var --notblank;) {{apply --append;}};" class="noPadOrMargin listStyleNone"></ul> </div> <!-- used in paypal transactions to cancel as paypal --> - <div data-app-event='orderCreate|execChangeFromPayPal' class='displayNone pointer zlink'> + <div data-app-click="order_create|execChangeFromPayPal" class="displayNone pointer zlink"> Choose Alternate Payment Method </div> <!-- more payment types is first but, when applicable, stored payments is shown. That way stored payments are easily selected but it's hard to miss that other payment choices are available. --> - <div data-app-role='paymentOptionsContainer' data-app-event="orderCreate|addTriggerPayMethodUpdate"> + <div data-app-role="paymentOptionsContainer" data-app-event="order_create|addTriggerPayMethodUpdate"> - <h2 data-app-role='nonStoredPaymentsHeader' class='displayNone'>More Payment Choices</h2> - <div data-app-role='nonStoredPaymentsContent'> - <div data-bind='var: getPaymentMethods(@methods); format:payMethodsAsRadioButtons; extension: orderCreate;'></div> + <h2 data-app-role="nonStoredPaymentsHeader" class="displayNone">More Payment Choices</h2> + <div data-app-role="nonStoredPaymentsContent"> + <div data-tlc="bind $var '.cart.cartid'; order_create#paymethodsasradiobuttons --legacy;"></div> </div> - <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payments</h2> - <div data-app-role='storedPaymentsContent' class='displayNone' data-bind="var: buyerWalletList(@wallets); format:processList; loadsTemplate: chkoutBuyerWalletListItem;"></div> - + <h2 data-app-role="storedPaymentsHeader" class="displayNone">Your Stored Payments</h2> + <!-- The # of children in the storedPaymentContents triggers wallet display. Do not add any children to this div. --> + <div data-tlc="bind $var '.@wallets'; controller#loop --templateid='chkoutBuyerWalletListItem'; if (is $var --notblank;) {{apply --append;}};" data-app-role="storedPaymentsContent" class="displayNone"></div> </div> @@ -276,32 +283,32 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment the defaultVar on prodName & image is for promotions, which have a 'description' attribute --> <table> -<tr id='chkoutCartItemTemplate'> - <td><img class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL; defaultVar: product(%attribs.zoovy:prod_image1);' width='50' height='50' /></td> +<tbody><tr id="chkoutCartItemTemplate"> + <td><img data-tlc="bind $var '.%attribs.zoovy:prod_thumb'; if(is $var --blank;) {{bind $var '.%attribs.zoovy:prod_image1'; }}; if (is $var --notblank;) {{ apply --img --media=$var --width=50 --height=50 --bgcolor='#ffffff' --replace;}};" class="prodThumb" height="50" width="50"></td> <td> - <div class='prodName' data-bind='var: product(prod_name); format:text; defaultVar: description;'></div> - <div class='stid' data-bind='var: product(sku); format:text; className: stid; pretext: Sku: ;'></div> - <div class='prodLatency' data-bind='var:product(%attribs.zoovy:ship_latency); format:text; pretext:Normally ships in ; posttext: day(s);'></div> - <div class='prodOptions' data-bind='var: variations(%options); format:selectedOptionsDisplay;'></div> + <div data-tlc="bind $var '.prod_name'; if(is $var --blank;) {{bind $var '.description'; }}; if (is $var --notblank;) {{apply --append;}};" class="prodName"></div> + <div data-tlc="bind $var '.sku'; if (is $var --notblank;) {{format --prepend='Sku: '; apply --add --class='stid'; apply --append;}};" class="stid"></div> + <div data-tlc="bind $var '.%attribs.zoovy:ship_latency'; if (is $var --notblank;) {{format --prepend='Normally ships in '; format --append=' day(s)'; apply --append;}};" class="prodLatency"></div> + <div data-tlc="bind $var '.%options'; controller#selectedoptionsdisplay --legacy; " class="prodOptions"></div> </td> - <td class='alignRight'><span data-bind='var: product(qty); format:text;'></span></td> - <td class='alignRight'><span data-bind='var: product(price); format:money; currencySign: $; hideZero:false; pretext: x ;'></span></td> - <td class='alignRight'><span data-bind='var: product(extended); format:money; currencySign: $; hideZero:false; pretext: = ;'></span></td> + <td class="alignRight"><span data-tlc="bind $var '.qty'; if (is $var --notblank;) {{apply --append;}};"></span></td> + <td class="alignRight"><span data-tlc="bind $var '.price'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='x '; apply --append;}};"></span></td> + <td class="alignRight"><span data-tlc="bind $var '.extended'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='= '; apply --append;}};"></span></td> </tr> -</table> +</tbody></table> -<section id='chkoutCartContentsTemplate'> -<table class='fullWidth gridTable'> +<section id="chkoutCartContentsTemplate"> +<table class="fullWidth gridTable"> <thead> <tr> - <th colspan='2' class='alignLeft'>product information</th> - <th class='alignRight'>qty</th> - <th class='alignRight'>price</th> - <th class='alignRight'>item total</th> + <th colspan="2" class="alignLeft">product information</th> + <th class="alignRight">qty</th> + <th class="alignRight">price</th> + <th class="alignRight">item total</th> </tr> </thead> -<tbody data-bind='var: cart(@ITEMS); format:processList; loadsTemplate:chkoutCartItemTemplate;'></tbody> +<tbody data-tlc="bind $var '.@ITEMS'; controller#loop --templateid='chkoutCartItemTemplate'; if (is $var --notblank;) {{apply --append;}};" data-app-role="cartItemsTbody"></tbody> </table> </section> @@ -312,35 +319,35 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment -<section id='chkoutCartSummaryTemplate'> +<section id="chkoutCartSummaryTemplate"> - <div data-bind="var: cart(sum/items_total); format:money; className:orderSubtotal; hideZero:false; currencySign: $; pretext:Subtotal: ; "></div> - <div data-bind='var: cart(sum/tax_total); format:money; className:orderTax; hideZero:true;currencySign: $; pretext:Tax: ; '></div> - <div data-bind='var: cart(want/shipping_id); format:shipInfoById; className:orderShipping; hideZero:false; extension:cco;'></div> - <div data-bind='var: cart(sum/hnd_total); format:money; className:hndTotal; currencySign: $; pretext:Handling: ; '></div> - <div data-bind='var: cart(sum/order_total); format:money; className:orderTotal; hideZero:false; currencySign: $; pretext:Order Total: ; '></div> - <div data-bind='var: cart(sum/gfc_total); format:money; className:orderGiftcardTotal; currencySign: $; pretext:Giftcard(s): ; '></div> - <div data-bind='var: cart(sum/pnt_total); format:money; className:rewardPointsTotal; currencySign: $; pretext:Reward Points: ; '></div> - <div data-bind='var: cart(sum/rmc_total); format:money; className:returnsCreditTotal; currencySign: $; pretext:Returns Credit: ; '></div> - <div data-bind='var: cart(sum/spc_total); format:money; className:spcTotal; currencySign: $; pretext:Specialty: ; '></div> - - <div data-bind='var: cart(sum/balance_due_total); format:orderBalance; className:orderBalanceDue; hideZero:false; currencySign: $; pretext:Balance Due: ; extension:cco;'></div> - - <div class='couponEntryContainer clearfix marginBottom' data-app-role='couponContainer'> - <label for='coupon'>Coupon/Promo Code:</label> - <input type='text' name='coupon' size='8' data-app-event='orderCreate|addTriggerButtonClick' /> - <button data-app-event="orderCreate|execCouponAdd" >add</button> + <div data-tlc="bind $var '.sum.items_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Subtotal: '; apply --add --class='orderSubtotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.tax_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Tax: '; apply --add --class='orderTax'; apply --append;}};"></div> + <div data-tlc="bind $var '.'; cco#shipinfobyid --legacy;" data-legacy-useparentdata="true" class="orderShipping"></div> + <div data-tlc="bind $var '.sum.hnd_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Handling: '; apply --add --class='hndTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.order_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Order Total: '; apply --add --class='orderTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.gfc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Giftcard(s): '; apply --add --class='orderGiftcardTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.pnt_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Reward Points: '; apply --add --class='rewardPointsTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.rmc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Returns Credit: '; apply --add --class='returnsCreditTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.spc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Specialty: '; apply --add --class='spcTotal'; apply --append;}};"></div> + + <div data-tlc="bind $var '.sum.balance_due_total'; cco#orderbalance --classname='orderBalanceDue' --hidezero='false' --currencysign='$' --legacy;"></div> + + <div class="couponEntryContainer clearfix marginBottom" data-app-role="couponContainer"> + <label for="coupon">Coupon/Promo Code:</label> + <input name="coupon" size="8" data-input-keyup="trigger-button-id" data-trigger-button-id="execCouponAdd" data-input-format="alphanumeric" type="text"> + <button class="applyButton" data-app-click="order_create|execCouponAdd" data-button-id="execCouponAdd">add</button> + </div> + <!-- will appear if company field is populated AND payment method is NOT PO --> + <div data-app-role="referenceNumber" class="displayNone"> + <label>Purchase Order/Reference #: </label> + <input type'text'="" name="want/reference_number" size="12"> </div> - - <button data-app-event="orderCreate|execCartOrderCreate"> + <button class="applyButton ui-state-highlight" data-app-click="order_create|execCartOrderCreate"> Place Order </button> -<div data-app-role='referenceNumber' class='displayNone'> - <label>Purchase Order/Reference #: </label> - <input type'text' name='want/reference_number' size='12' /> -</div> </section> @@ -352,13 +359,13 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment - -<address id='chkoutBuyerAddressTemplate' class='ui-widget ui-widget-content ui-corner-all stdPadding'> - <div data-bind="var:address(bill/address1); defaultVar: address(ship/address1); format:text;"></div> - <div data-bind="var:address(bill/postal); defaultVar: address(ship/postal); format:text;"></div> - <div class='clearfix'> - <button class='floatRight' data-app-event='orderCreate|execBuyerAddressSelect'>Use This Address</button> - <button class='floatRight marginRight' data-app-event="orderCreate|showBuyerAddressUpdate">Edit This Address</button> +<!-- there is display logic looking for the number of address elements in addressExists. do not change element try w/out updating display logic. --> +<address id="chkoutBuyerAddressTemplate" class="ui-widget ui-widget-content ui-corner-all stdPadding"> + <div data-tlc="bind $var '.bill/address1'; if(is $var --blank;) {{bind $var '.ship/address1'; }}; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.bill/postal'; if(is $var --blank;) {{bind $var '.ship/postal'; }}; if (is $var --notblank;) {{apply --append;}};"></div> + <div class="clearfix"> + <button class="floatRight applyButton" data-app-click="order_create|execBuyerAddressSelect" data-icon="false" data-icon-primary="ui-icon-check">Use This Address</button> + <button class="floatRight marginRight applyButton" data-app-role="addressEditButton" data-app-click="order_create|showBuyerAddressUpdate" data-icon="false" data-icon-primary="ui-icon-pencil">Edit</button> </div> </address> @@ -368,20 +375,20 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment <ul> - <li id='cartPaymentQTemplate'> - <span data-bind="var:payment(TN); format:text;"></span> - <span class='marginLeft' data-bind="var:payment($$); format:money; currencySign: $; hideZero:false;"></span><span data-bind="var:payment($#); format:money; currencySign: $; pretext:/;"></span> + <li id="cartPaymentQTemplate"> + <span data-tlc="bind $var '.TN'; if (is $var --notblank;) {{apply --append;}};"></span> + <span data-tlc="bind $var '.$$'; if (is $var --notblank;) {{format --currency='USD'; apply --append;}};" class="marginLeft"></span><span data-tlc="bind $var '.$#'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='/'; apply --append;}};"></span> <!-- <button class='marginLeft' title='Remove this payment method'>X</button> --> </li> </ul> <!-- radio name is same as rest of payments so that only 1 can be selected and form still easily passes validation --> -<div id='chkoutBuyerWalletListItem'> +<div id="chkoutBuyerWalletListItem"> <label> - <input type='radio' name='want/payby' value='' data-bind="var: wallet(ID); format:setVal;" /> - <span data-bind="var: wallet(TD); format:text;"></span> - <span data-bind="var: wallet(TD); format: walletName2Icon; extension:cco;"></span> + <input data-tlc="bind $var '.ID'; apply --inputvalue; " name="want/payby" value="" type="radio" data-app-change='order_create|shipOrPayMethodSelectExec'> + <span data-tlc="bind $var '.TD'; if (is $var --notblank;) {{apply --append;}};"></span> + <span data-tlc="bind $var '.TD'; cco#walletnameintoicon --legacy;"></span> </label> </div> @@ -391,9 +398,9 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment do NOT change the input name or id or checkout will likely break. --> -<div id='chkoutNotesTemplate'> +<div id="chkoutNotesTemplate"> <p>Please include any special instructions or comments here:</p> -<textarea class='chkoutOrderNotes fullWidth' name='want/order_notes' data-app-event='orderCreate|execCartSet' data-bind='var: cart(want/order_notes); format:popVal;'></textarea> +<textarea data-tlc="bind $var '.want.order_notes'; if(is $var --notblank;) {{apply --select=$var;}}; " class="chkoutOrderNotes fullWidth" name="want/order_notes" data-app-blur="order_create|execCartSet"></textarea> </div> @@ -407,98 +414,92 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment <!-- used after a successful checkout. --> -<div id='chkoutCompletedTemplate' class='checkoutSuccess'> +<div id="chkoutCompletedTemplate" class="checkoutSuccess"> - <div class='floatRight ocmThirdParty'> - <h2>What next?</h2> -<!-- the twitter and facebook actions are added post checkout. The order contents are included as part of the message --> - <div class='ocm ocmFacebookComment pointer zlink marginBottom checkoutSprite '></div> - <div class='ocm ocmTwitterComment pointer zlink marginBottom checkoutSprit ' ></div> - <div class='ocm ocmContinue pointer zlink marginBottom checkoutSprite'></div> - - </div> + <div class="floatRight ocmThirdParty" data-app-role="thirdPartyContainer"></div> - <div class='orderSummaryDetails'> + <div class="orderSummaryDetails"> <h2>Thank you! Your order has been placed.</h2> - <h3 data-bind='var: order(orderid); format:text; pretext:Your order id is ;'></h3> - <div class='pointer marginBottom' data-app-role='paymentMessaging'> + <h3 data-tlc="bind $var '.orderid'; if (is $var --notblank;) {{format --prepend='Your order id is '; apply --append;}};"></h3> + <div class="pointer marginBottom" data-app-role="paymentMessaging"> Click here to view/print your invoice. - <div class='zwarn' data-bind="var: order(payment_status_msg); format:text;"></div><!-- displays payment issues/errors --> + <div data-tlc="bind $var '.payment_status_msg'; if (is $var --notblank;) {{apply --append;}};" class="zwarn"></div><!-- displays payment issues/errors --> </div> - <div data-bind="var:order(payment_status_detail); format:text;" class='marginBottom'></div> - <div>You will receive an order confirmation email with details of your order</div> + <div data-tlc="bind $var '.payment_status_detail'; if (is $var --notblank;) {{apply --append;}};" class="marginBottom"></div> + <div>You will receive an order confirmation email with details of your order.</div> </div> - <div class='clearAll'></div> - <span id='BuySafeGuaranteeSpan'></span> - <div class='clearAll'></div> + <div class="clearAll"></div> + <span id="BuySafeGuaranteeSpan"></span> + <div class="clearAll"></div> -<div data-app-role='invoiceContainer'> - <table class='orderContentsTable fullWidth'> - <tr> - <td colspan='2'> - <div class='floatRight hide4Print'> - <button data-app-event="orderCreate|execInvoicePrint">Print Invoice</button> +<div data-app-role="invoiceContainer"> + <table class="orderContentsTable fullWidth"> + <tbody><tr> + <td colspan="2"> + <div class="floatRight hide4Print"> + <button class="applyButton" data-text="false" data-icon-primary="ui-icon-print" data-app-click="order_create|execInvoicePrint">Print Invoice</button> </div> - <h3 data-bind='var:order(order/data/pool);format:text; pretext:Order Status: ;'></h3> + <h2 data-tlc="bind $var '.order.our.orderid'; if (is $var --notblank;) {{apply --append;}};"></h2> + <h3 data-tlc="bind $var '.order.data.pool'; if (is $var --notblank;) {{format --prepend='Order Status: '; apply --append;}};"></h3> </td> </tr> <tr> <td> - <hgroup class='marginBottom'> + <hgroup class="marginBottom"> <!-- print icon --> <!-- <h2 data-bind='var:order(bill/firstname);format:text; pretext:Shipping Status: ;'></h2> --> - <h5 class='orderTotal' data-bind='var:order(order/sum/order_total);format:money; currencySign: $; hideZero:false; pretext:Order Total: ;'></h5> - <h5 class='balanceDue' data-bind='var:order(order/sum/balance_due_total);format:money; currencySign: $; hideZero:false; pretext:Balance Due: ;'></h5> + <h5 data-tlc="bind $var '.order.sum.order_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Order Total: '; apply --append;}};" class="orderTotal"></h5> + <h5 data-tlc="bind $var '.order.sum.balance_due_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Balance Due: '; apply --append;}};" class="balanceDue"></h5> </hgroup> - <address class='marginBottom'> + <address class="marginBottom"> <h4> - <span data-bind='var:order(order/bill/firstname);format:text; pretext:Bill To: ;'></span> - <span data-bind='var:order(order/bill/lastname);format:text;'></span> + <span data-tlc="bind $var '.order.bill.firstname'; if (is $var --notblank;) {{format --prepend='Bill To: '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.lastname'; if (is $var --notblank;) {{apply --append;}};"></span> </h4> - <div data-bind='var:order(order/bill/address1);format:text;'></div> - <div data-bind='var:order(order/bill/address2);format:text;'></div> + <div data-tlc="bind $var '.order.bill.address1'; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.order.bill.address2'; if (is $var --notblank;) {{apply --append;}};"></div> <div> - <span data-bind='var:order(order/bill/city);format:text;posttext:, ;'></span> - <span data-bind='var:order(order/bill/region);format:text;posttext:. ;'></span> - <span data-bind='var:order(order/bill/postal);format:text; defaultVar:order(data.bill_int_zip);'></span> + <span data-tlc="bind $var '.order.bill.city'; if (is $var --notblank;) {{format --append=', '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.region'; if (is $var --notblank;) {{format --append='. '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.postal'; if(is $var --blank;) {{bind $var '.data.bill_int_zip'; }}; if (is $var --notblank;) {{apply --append;}};"></span> </div> - <div data-bind='var:order(order/bill/countrycode);format:text;'></div> + <div data-tlc="bind $var '.order.bill.countrycode'; if (is $var --notblank;) {{apply --append;}};"></div> </address> <address> <h4> - <span data-bind='var:order(order/ship/firstname);format:text; pretext:Ship To: ;'></span> - <span data-bind='var:order(order/ship/lastname);format:text;'></span> + <span data-tlc="bind $var '.order.ship.firstname'; if (is $var --notblank;) {{format --prepend='Ship To: '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.lastname'; if (is $var --notblank;) {{apply --append;}};"></span> </h4> - <div data-bind='var:order(order/ship/address1);format:text;'></div> - <div data-bind='var:order(order/ship/address2);format:text;'></div> + <div data-tlc="bind $var '.order.ship.address1'; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.order.ship.address2'; if (is $var --notblank;) {{apply --append;}};"></div> <div> - <span data-bind='var:order(order/ship/city);format:text;posttext:, ;'></span> - <span data-bind='var:order(order/ship/region);format:text;posttext:. ;'></span> - <span data-bind='var:order(order/ship/postal);format:text; defaultVar:order(data.ship_int_zip);'></span> + <span data-tlc="bind $var '.order.ship.city'; if (is $var --notblank;) {{format --append=', '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.region'; if (is $var --notblank;) {{format --append='. '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.postal'; if(is $var --blank;) {{bind $var '.data.ship_int_zip'; }}; if (is $var --notblank;) {{apply --append;}};"></span> </div> - <div data-bind='var:order(order/ship/countrycode);format:text;'></div> + <div data-tlc="bind $var '.order.ship.countrycode'; if (is $var --notblank;) {{apply --append;}};"></div> </address> </td> - <td class='orderContentsProdlistContainer'> - <ul data-bind='var:order(order/tracking); format:orderTrackingLinks; extension:store_crm;before:<h4>Shipping:</h4>;' class='displayNone noListStyle marginBottom'></ul> - <table class='listStyleNone lineItemProdlist'> - <tbody data-bind="var: order(order/@ITEMS); format:stuffList; loadsTemplate:chkoutInvoiceItemTemplate;"></tbody> + <td class="orderContentsProdlistContainer"> + <ul data-tlc="bind $var '.order.tracking'; store_crm#ordertrackinglinks --legacy;" class="displayNone noListStyle marginBottom"></ul> + <table class="listStyleNone lineItemProdlist"> + <tbody data-tlc="bind $var '.order.@ITEMS'; controller#loop --templateid='chkoutInvoiceItemTemplate'; if (is $var --notblank;) {{apply --append;}};"></tbody> </table> </td> </tr> - </table> + </tbody></table> </div> </div> @@ -509,10 +510,10 @@ <h4> -<div id='cvvcidHelp' class='displayNone' title='Where to find your CVV/CID and why we ask for it'> +<div id="cvvcidHelp" class="displayNone" title="Where to find your CVV/CID and why we ask for it"> <p>For higher security and more efficient processing of your payment, you must provide a card security code to make this purchase. For Visa, MasterCard and Discover the security code is the last section of numbers in the signature area on the back of the card. For American Express the security code is the 4-digit number found in small print next to your account number on the front, usually above it on the right.</p> - <div class='checkoutSprite secCode_vmd' title='Visa/MC/Discover card security code'></div> - <div class='checkoutSprite secCode_amex' title='AMEX card security code'></div> + <div class="checkoutSprite secCode_vmd" title="Visa/MC/Discover card security code"></div> + <div class="checkoutSprite secCode_amex" title="AMEX card security code"></div> </div> @@ -532,6 +533,7 @@ <h4> + <!-- order line-item template used in order history. note - on the write review button, var:product(product) will use the pid, not the stid (which includes options). @@ -539,45 +541,35 @@ <h4> If this gets recycled, test in order history after making changes. --> <table> - <tr id='chkoutInvoiceItemTemplate' class='padMargBorderBottom'> + <tbody><tr id="chkoutInvoiceItemTemplate" class="padMargBorderBottom"> <td> - <div class='prodThumbContainer marginRight'> - <img src='/media/graphics/blank.gif' class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL;' width='55' height='55' /> + <div class="prodThumbContainer marginRight"> + <img data-tlc="bind $var '.%attribs.zoovy:prod_image1'; if (is $var --notblank;) {{ apply --img --media=$var --width=55 --height=55 --bgcolor='#ffffff' --replace;}};" src="/media/graphics/blank.gif" class="prodThumb" height="55" width="55"> </div> </td> - <td class='valignTop ztable_row'> + <td class="valignTop ztable_row"> -<div class='infoContainer'> - - <h3 data-bind='var: product(prod_name); format:text; '></h3> - <div class='ztable_row_small stid' data-bind='var: product(sku); format:text; className: stid; pretext: Sku: ;'></div> +<div class="infoContainer"> + <b data-tlc="bind $var '.prod_name'; if (is $var --notblank;) {{apply --append;}};"></b> + <div data-tlc="bind $var '.sku'; if (is $var --notblank;) {{format --prepend='Sku: '; apply --add --class='stid'; apply --append;}};" class="ztable_row_small stid"></div> + <div> - <span data-bind='var: product(qty); format:text; pretext:qty: ;'></span> - <span data-bind='var: product(price); format:money; currencySign: $; hideZero:false; pretext: x ;' ></span> - <span data-bind='var: product(extended); format:money; currencySign: $; hideZero:false; pretext: = ;'></span> + <span data-tlc="bind $var '.qty'; if (is $var --notblank;) {{format --prepend='qty: '; apply --append;}};"></span> + <span data-tlc="bind $var '.price'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='x '; apply --append;}};"></span> + <span data-tlc="bind $var '.extended'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='= '; apply --append;}};"></span> </div> - - <div class='ztable_row_small prodOptions' data-bind='var: product(%options); format:selectedOptionsDisplay;'></div> - - - + <div data-tlc="bind $var '.%options'; controller#selectedoptionsdisplay --legacy; " class="ztable_row_small prodOptions"></div> </div> </td> - <td class='alignRight hide4Print'> - <button class='writeReview' data-app-event="store_crm|showWriteReview" data-bind='var:product(product);format:assignAttribute; attribute:data-pid;'>Write Review</button> + <td class="alignRight hide4Print"> + <button data-tlc="bind $var '.product'; apply --attrib='data-pid'; " class="writeReview applyButton" data-app-click="store_crm|productReviewShow">Write Review</button> </td> </tr> -</table> - - - - - - +</tbody></table> \ No newline at end of file diff --git a/extensions/checkout/extension.js b/extensions/checkout/extension.js index 695cae3ea..98a0d3c96 100644 --- a/extensions/checkout/extension.js +++ b/extensions/checkout/extension.js @@ -17,7 +17,7 @@ ************************************************************** */ -var orderCreate = function() { +var order_create = function(_app) { var theseTemplates = new Array( 'checkoutTemplate', //container for whole checkout page. 'chkoutPreflightTemplate', @@ -37,7 +37,6 @@ var orderCreate = function() { var r = { vars : { willFetchMyOwnTemplates : true, //1pc loads it's templates locally to avoid XSS issue. - payment : {}, //used in checkout to store payment info that doesn't get added to cart till orderCreate (paymentQ) //though most extensions don't have the templates specified, checkout does because so much of the code is specific to these templates. templates : theseTemplates }, @@ -55,44 +54,37 @@ var orderCreate = function() { //callbacks.init need to return either a true or a false, depending on whether or not the file will execute properly based on store account configuration. init : { onSuccess : function() { -// app.u.dump('BEGIN app.ext.orderCreate.init.onSuccess'); -//1PC can't load the templates remotely. causes XSS issue. -// if(app.vars._clientid == '1pc') { -// app.u.dump(" -> _cliendID = 1pc. load templates from TOXML file"); -// app.model.loadTemplates(theseTemplates); //loaded from local file (main.xml) -// } -// else { - app.u.loadCSSFile(app.vars.baseURL+"extensions/checkout/styles.css","checkoutCSS"); - app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/checkout/'+app.vars.checkoutAuthMode+'.html',theseTemplates); -// } - var r = true; //returns false if checkout can't load due to account config conflict. - -//update jQuery.support with whether or not placeholder is supported. - $.support.placeholder = false; - var test = document.createElement('input') - - if('placeholder' in test) {$.support.placeholder = true}; - app.u.dump(" -> document.compatMode: "+document.compatMode); - app.u.dump(" -> document.documentMode: "+document.documentMode); +// _app.u.dump('BEGIN _app.ext.order_create.init.onSuccess'); - if(typeof _gaq === 'undefined' && !app.vars.thisSessionIsAdmin) { -// app.u.dump(" -> _gaq is undefined"); - $('#globalMessaging').anymessage({'message':'It appears you are not using the Asynchronous version of Google Analytics. It is required to use this checkout.','uiClass':'error','uiIcon':'alert'}); - r = false; + _app.u.loadCSSFile(_app.vars.baseURL+"extensions/checkout/styles.css","checkoutCSS"); + if(_app.vars._clientid == '1pc') { + _app.u.loadCSSFile(_app.vars.baseURL+"extensions/checkout/opc_styles.css","opcCheckoutCSS"); //loaded after checkoutCSS so that overrides can be set, if need be. } + _app.model.fetchNLoadTemplates(_app.vars.baseURL+'extensions/checkout/'+_app.vars.checkoutAuthMode+'.html',theseTemplates); + + var r = true; //returns false if checkout can't load due to account config conflict. + //messaging for the test harness 'success'. - else if(app.u.getParameterByName('_testharness')) { + if(_app.u.getParameterByName('_testharness')) { $('#globalMessaging').anymessage({'message':'<strong>Excellent!<\/strong> Your store meets the requirements to use this one page checkout extension.','uiIcon':'circle-check','uiClass':'success'}); - $('#'+app.ext.orderCreate.vars.containerID).append(""); + $('#'+_app.ext.order_create.vars.containerID).append(""); r = true; } - else if(!app.vars.checkoutAuthMode) { + else if(!_app.vars.checkoutAuthMode) { r = false; - $('#globalMessaging').anymessage({'message':'<strong>Uh Oh!<\/strong> app.vars.checkoutAuthMode is not set. should be set to passive, required or active (depending on the checkout behavior desired).'}); + $('#globalMessaging').anymessage({'message':'<strong>Uh Oh!<\/strong> _app.vars.checkoutAuthMode is not set. should be set to passive, required or active (depending on the checkout behavior desired).'}); + } + else if(_app.vars.thisSessionIsAdmin) { + r = true; + //don't execute a localStorage.clear() on an admin session cuz it'll nuke the session ID and the carts. } else { r = true; - if(document.domain.indexOf('app-hosted.com') >= 0) {window.localStorage.clear()} //clear localStorage for shared domain to avoid cross-store contamination. + if(document.domain.indexOf('app-hosted.com') >= 0) { + if(jQuery.support.localStorage) { + window.localStorage.clear(); + } + } //clear localStorage for shared domain to avoid cross-store contamination. } if(r == false) { @@ -101,30 +93,31 @@ var orderCreate = function() { this.onError(); } return r; -// app.u.dump('END app.ext.orderCreate.init.onSuccess'); +// _app.u.dump('END _app.ext.order_create.init.onSuccess'); }, onError : function() { - app.u.dump('BEGIN app.ext.orderCreate.callbacks.init.error'); + _app.u.dump('BEGIN _app.ext.order_create.callbacks.init.error'); } }, //init - startCheckout : { - onSuccess : function(tagObj) { - //used for one page checkout only. - app.u.dump("BEGIN startcheckout callback for legacy 1PC"); - app.model.destroy('buyerAddressList'); //list 'may' have been updated in vstore UI. - app.ext.orderCreate.a.startCheckout($('#zContent')); - } - }, - - - adminCustomerDetail : { + updateAllPanels : { onSuccess : function(tagObj) { //used for one page checkout only. - app.u.dump("BEGIN adminCustomerDetail callback for 1PC"); - app.ext.orderCreate.u.handlePanel(tagObj.jqObj,'chkoutPreflight',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel(tagObj.jqObj,'chkoutAddressBill',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel(tagObj.jqObj,'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents']); +// _app.u.dump("BEGIN adminCustomerDetail callback for 1PC"); + if(tagObj.jqObj instanceof jQuery) { + tagObj.jqObj.hideLoading(); + _app.ext.order_create.u.handlePanel(tagObj.jqObj,'chkoutPreflight',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel(tagObj.jqObj,'chkoutAddressBill',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel(tagObj.jqObj,'chkoutAddressShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel(tagObj.jqObj,'chkoutMethodsShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel(tagObj.jqObj,'chkoutMethodsPay',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel(tagObj.jqObj,'chkoutCartItemsList',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel(tagObj.jqObj,'chkoutCartSummary',['empty','translate','handleDisplayLogic']); + } + else { + $("#globalMessaging").anymessage({"message":"In order_create.callbacks.updateAllPanels.onSuccess, tagObj.jqObj was NOT an instanceof jQuery. See Console for some details.","gMessage":true}); + dump(" -> tagObj.jqObj (which SHOULD be a jquery instance but isn't"); dump(tagObj.jqObj); + } } }, @@ -135,7 +128,7 @@ var orderCreate = function() { //this gives us a 1 call model for success and 2 calls for failure (instead of 2 and 2). handlePayPalIntoPaymentQ : { onSuccess : function(tagObj) { - app.u.dump('BEGIN orderCreate[nice].callbacks.handlePayPalIntoPaymentQ.onSuccess'); + _app.u.dump('BEGIN order_create[nice].callbacks.handlePayPalIntoPaymentQ.onSuccess'); //this is the callback AFTER the payment is added to the Q, so no success is needed, only specific error handling. }, onError : function(responseData,uuid) { @@ -144,24 +137,25 @@ var orderCreate = function() { $('#globalMessaging').anymessage({'message':responseData,'persistent':true}); //nuke vars so user MUST go thru paypal again or choose another method. //nuke local copy right away too so that any cart logic executed prior to dispatch completing is up to date. - app.ext.cco.u.nukePayPalEC({'callback':function(rd){ + _app.ext.cco.u.nukePayPalEC({'callback':function(rd){ //suppress errors but unlock all the panels. $('body').hideLoading(); var $context = responseData._rtag.jqObj; -app.u.dump(" -> $context.length: "+$context.length); -app.ext.orderCreate.u.handlePanel($context,'chkoutMethodsShip',['empty','translate','handleDisplayLogic','handleAppEvents']); -app.ext.orderCreate.u.handlePanel($context,'chkoutMethodsPay',['empty','translate','handleDisplayLogic','handleAppEvents']); -app.ext.orderCreate.u.handlePanel($context,'chkoutAddressBill',['empty','translate','handleDisplayLogic','handleAppEvents']); -app.ext.orderCreate.u.handlePanel($context,'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents']); +_app.ext.order_create.u.handlePanel($context,'chkoutAddressBill',['empty','translate','handleDisplayLogic']); +_app.ext.order_create.u.handlePanel($context,'chkoutAddressShip',['empty','translate','handleDisplayLogic']); +_app.ext.order_create.u.handlePanel($context,'chkoutMethodsShip',['empty','translate','handleDisplayLogic']); +_app.ext.order_create.u.handlePanel($context,'chkoutMethodsPay',['empty','translate','handleDisplayLogic']); }}); - app.model.destroy('cartDetail'); - app.calls.cartDetail.init({},'immutable'); - app.ext.cco.calls.appPaymentMethods.init({_cartid:app.vars.cartID},{},'immutable'); - app.model.dispatchThis('immutable'); + var cartid = $context.closest("[data-app-role='checkout']").data('cartid'); + _app.model.destroy('cartDetail|'+cartid); + _app.calls.cartDetail.init(cartid,{},'immutable'); + _app.ext.cco.calls.appPaymentMethods.init({_cartid:cartid},{},'immutable'); + _app.model.dispatchThis('immutable'); } }, //handlePayPalIntoPaymentQ + //executing this will not only return which items have had an inventory update (in a pretty format) but also create the dispatches // to update the cart and then to actually update it as well. // the individual cart update posts (there may be multiple) go without the callback. If callback is added, a ping to execute it is run. @@ -169,164 +163,110 @@ app.ext.orderCreate.u.handlePanel($context,'chkoutAddressShip',['empty','transla onSuccess : function(_rtag) { var r = false; //if false is returned, then no inventory update occured. - if(app.data[_rtag.datapointer] && !$.isEmptyObject(app.data[_rtag.datapointer]['%changes'])) { - var $form = _rtag.jqObj; + if(_app.data[_rtag.datapointer] && !$.isEmptyObject(_app.data[_rtag.datapointer]['%changes'])) { + var $form = _rtag.jqObj.find('form:first'), cartid = $form.closest("[data-app-role='checkout']").data('cartid'); r = "<p>It appears that some inventory adjustments needed to be made:<ul>"; - for(var key in app.data[_rtag.datapointer]['%changes']) { - r += "<li>sku: "+key+" was set to "+app.data[_rtag.datapointer]['%changes'][key]+" due to availability<\/li>"; - app.calls.cartItemUpdate.init(key,app.data[_rtag.datapointer]['%changes'][key]); - } - app.u.dump(" -> SANITY: an extra cartDetail call is occuring because inventory availability required some cartUpdates to occur."); - app.model.destroy('cartDetail'); - app.calls.cartDetail.init({'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ + for(var key in _app.data[_rtag.datapointer]['%changes']) { + r += "<li>sku: "+key+" was set to "+_app.data[_rtag.datapointer]['%changes'][key]+" due to availability<\/li>"; + _app.ext.cco.calls.cartItemUpdate.init({'_cartid':cartid,'stid':key,'quantity':_app.data[_rtag.datapointer]['%changes'][key]}); //## TODO -> this probably needs a cartid. + } + _app.u.dump(" -> SANITY: an extra cartDetail call is occuring because inventory availability required some cartUpdates to occur."); + _app.model.destroy('cartDetail|'+cartid); + _app.calls.cartDetail.init(cartid,{'callback':function(rd){ + if(_app.model.responseHasErrors(rd)){ $('#globalMessaging').anymessage({'message':rd}); } else { - app.u.dump(" -> inventory adjustment has occurred. update panels to reflect change."); - app.ext.orderCreate.u.handlePanel($form,'chkoutCartItemsList',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($form,'chkoutCartSummary',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($form,'chkoutMethodsPay',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($form,'chkoutMethodsShip',['empty','translate','handleDisplayLogic','handleAppEvents']); + _app.u.dump(" -> inventory adjustment has occurred. update panels to reflect change."); + _app.ext.order_create.u.handlePanel($form,'chkoutCartItemsList',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($form,'chkoutCartSummary',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($form,'chkoutMethodsPay',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($form,'chkoutMethodsShip',['empty','translate','handleDisplayLogic']); } }},'immutable'); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); r += "<\/ul><\/p>"; $('#globalMessaging').anymessage({'message':r,'persistent':true}); } - return r; - } }, //handleInventoryUpdate +//callback executed on the cartOrderCreate AND subsequent cartOrderStatus calls. - -/* -this callback is executed after a successful checkout. 'success' is defined as an order created, the order may contain 'payment required' warnings. -this is what would traditionally be called an 'invoice' page, but certainly not limited to just showing the invoice. -*/ - cart2OrderIsComplete : { + cartOrderStatus : { onSuccess : function(_rtag) { -// app.u.dump('BEGIN app.ext.orderCreate.callbacks.checkoutSuccess.onSuccess datapointer = '+_rtag.datapointer); - $('body').hideLoading(); -//nuke old form content. not needed anymore. gets replaced with invoice-ish content. - var $checkout = _rtag.jqObj, - checkoutData = app.data[_rtag.datapointer], - oldCartID = app.vars.cartID, - orderID = app.data[_rtag.datapointer].orderid; - -// SLIDE UP to top of checkout here. - -//show post-checkout invoice and success messaging. - $checkout.empty(); - $checkout.anycontent({'templateID':'chkoutCompletedTemplate',data: checkoutData}); // $.extend(true,checkoutData,{'invoice':app.data.cartDetail}) - app.u.handleAppEvents($checkout); - - var cartContentsAsLinks = encodeURI(app.ext.cco.u.cartContentsAsLinks('order|'+orderID)) + dump("BEGIN order_create.callbacks.cartOrderStatus.onSuccess"); + if(_app.data[_rtag.datapointer].finished) { + _app.ext.order_create.a.checkoutComplete(_rtag); + } + else { + _rtag.attempt = _rtag.attempt || 1; + + //when the cartOrderCreate response comes back, update the loading text to show the order id. + if(_rtag.datapointer.indexOf('cartOrderCreate') >= 0) { + $(document.body).showLoading({'message':'Order '+_app.data[_rtag.datapointer].orderid+' Created. Verifying payment...'}); + } + + if(_rtag.attempt === 1) { + if(_app.data[_rtag.datapointer]['previous-cartid']) { + dump(" -> removing the cartID from the session."); + //first attempt. To get here, the 'cart' has been received by the API and is in memory and being processed. Pull the cart out of memory. + _app.model.removeCartFromSession(_app.data[_rtag.datapointer]['previous-cartid']); + } + } +//Continue polling till order is finished. + setTimeout(function(){ + _app.model.addDispatchToQ({"_cmd":"cartOrderStatus","_cartid":_app.data[_rtag.datapointer]['status-cartid'],"_tag":{"datapointer":"cartOrderStatus","parentID":_rtag.parentID,"attempt" :(_rtag.attempt+1), "callback":"cartOrderStatus","extension":"order_create"}},"mutable"); + dump(" -------------> timeout triggered. dispatch cartOrderStatus. attempt: "+_rtag.attempt); + _app.model.dispatchThis("mutable"); + },2000); + } + }, + onError : function(rd) { + dump("BEGIN order_create.callbacks.cartOrderStatus.onError"); + //could get here from cartOrderStatus inquiry OR cartOrderCreate response. + //if a cart id is set, keep polling. could mean that one orderStatus call failed for some reason. + //but no order id likely means the cartOrderCreate call failed. show the errors. +// dump(" -> rd: "); dump(rd); - $('.ocmTwitterComment').click(function(){ - window.open('http://twitter.com/home?status='+cartContentsAsLinks,'twitter'); - _gaq.push(['_trackEvent','Checkout','User Event','Tweeted about order']); - }); - -//the fb code only works if an appID is set, so don't show banner if not present. - if(zGlobals.thirdParty.facebook.appId && typeof FB == 'object') { - $('.ocmFacebookComment').click(function(){ - app.thirdParty.fb.postToWall(cartContentsAsLinks); - _gaq.push(['_trackEvent','Checkout','User Event','FB message about order']); - }); + function handleError() { + $(document.body).hideLoading(); + $("#globalMessaging").anymessage({"message":rd,"gMessage":true,"persistent":true}); //error messaging is persistent so that buyer has adequate time to read/copy it. } - else {$('.ocmFacebookComment').hide()} - - -//time for some cleanup. Nuke the old cart from memory and local storage, then obtain a new cart. - app.model.destroy('cartDetail'); -//***201342 cartDetail call moved into a callback to the appCartCreate call. This is due to the fact that cartDetail call needs a cartID -// passed to it in order to know which cart to fetch (no longer connected to the session!). This resulted in a bug that multiple -// orders placed from the same computer in multiple sessions could have the same cartID attached. Very bad. - app.calls.appCartCreate.init({ - "callback" : function(rd){ - if(!app.model.responseHasErrors(rd)){ - app.calls.cartDetail.init({"_cartid" : rd._cartid},'immutable'); - app.model.dispatchThis('immutable'); + + if(rd._rtag && rd._rtag.datapointer) { + if(_app.data[rd._rtag.datapointer] && _app.data[rd._rtag.datapointer].finished) { + _app.ext.order_create.a.checkoutComplete(_rtag); + } + else if(_app.data[rd._rtag.datapointer] && _app.data[rd._rtag.datapointer]['status-cartid']) { + rd._rtag.attempt = rd._rtag.attempt || 0; //start at zero for an error. so '1' is hit next time. + setTimeout(function(){ + _app.model.addDispatchToQ({"_cmd":"cartOrderStatus","_cartid":_app.data[rd._rtag.datapointer]['status-cartid'],"_tag":{"datapointer":"cartOrderStatus","parentID":rd._rtag.parentID,"attempt" : rd._rtag.attempt++, "callback":"cartOrderStatus","extension":"order_create"}},"mutable"); + _app.model.dispatchThis("mutable"); + },2000); + } + else if(rd._rtag.datapointer.indexOf('cartOrderCreate') >= 0) { + //if the error came back as part of cartOrderCreate, then we should show checkout again so the user has the chance to resubmit. + if(rd._rtag.parentID) { + handleError(); + $(_app.u.jqSelector('#',rd._rtag.parentID)).show(); } - else { - app.u.throwMessage(rd); + else { + handleError(); } } - }); //!IMPORTANT! after the order is created, a new cart needs to be created and used. the old cart id is no longer valid. - //app.calls.cartDetail.init({},'immutable'); - app.model.dispatchThis('immutable'); //these are auto-dispatched because they're essential. - -_gaq.push(['_trackEvent','Checkout','App Event','Order created']); -_gaq.push(['_trackEvent','Checkout','User Event','Order created ('+orderID+')']); - - if(app.ext.orderCreate.checkoutCompletes) { - var L = app.ext.orderCreate.checkoutCompletes.length; - for(var i = 0; i < L; i += 1) { - app.ext.orderCreate.checkoutCompletes[i]({'cartID':oldCartID,'orderID':orderID,'datapointer':_rtag.datapointer}); + else { + handleError() } } - - app.ext.orderCreate.u.scripts2iframe(checkoutData['@TRACKERS']) - -if(app.vars._clientid == '1pc') { -//add the html roi to the dom. this likely includes tracking scripts. LAST in case script breaks something. -//this html roi is only generated if clientid = 1PC OR model version is pre 2013. for apps, add code using checkoutCompletes. - - - -// *** -> new method for handling third party checkout scripts. -/* setTimeout(function(){ - $checkout.append(checkoutData['html:roi']); - app.u.dump('wrote html:roi to DOM.'); - },1000); -*/ - -//GTS for apps is handled in google extension - if(typeof window.GoogleTrustedStore) { - delete window.GoogleTrustedStore; //delete existing object or gts conversion won't load right. -//running this will reload the script. the 'span' will be added as part of html:roi -//if this isn't run in the time-out, the 'span' w/ order totals won't be added to DOM and this won't track as a conversion. - (function() { - var scheme = (("https:" == document.location.protocol) ? "https://" : "http://"); - var gts = document.createElement("script"); - gts.type = "text/javascript"; - gts.async = true; - gts.src = scheme + "www.googlecommerce.com/trustedstores/gtmp_compiled.js"; - var s = document.getElementsByTagName("script")[0]; - s.parentNode.insertBefore(gts, s); - })(); - } - - - - } -else { - app.u.dump("Not 1PC."); - app.u.dump(" -> [data-app-role='paymentMessaging'],$checkout).length: "+("[data-app-role='paymentMessaging']",$checkout).length); - //the code below is to disable any links in the payment messaging for apps. there may be some legacy links depending on the message. - $("[data-app-role='paymentMessaging'] a",$checkout).on('click',function(event){ - event.preventDefault(); - }); - $("[data-app-role='paymentMessaging']",$checkout).on('click',function(event){ - event.preventDefault(); - //cart and order id are in uriParams to keep data locations in sync in showCustomer. uriParams is where they are when landing on this page directly. - showContent('customer',{'show':'invoice','uriParams':{'cartid':oldCartID,'orderid':orderID}}); - }); - } - - }, - onError : function(rd) { - $('body').hideLoading(); - $('#globalMessaging').anymessage({'message':rd}); - -_gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occured. ('+d['_msg_1_id']+')']); - + else { + //if rd._rtag is not set, the error is pretty big, probably an ISE or ISEERR + handleError() + } } - } //cart2OrderIsComplete + } }, //callbacks @@ -340,8 +280,6 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure validate : { - - //runs individual panel/fieldset validation and returns whether or not all checkout fields are populated/valid. //the individual fieldset validator returns a 1/0 depending on whether it passes/fails the validation. @@ -350,7 +288,7 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure checkout : function($form) { var r = false; //what is returned. Either true or false. if($form) { - + var formObj = $form.serializeJSON(), //done here and passed into validation funcitons so serialization only occurs once. (more efficient) $fieldsets = $('fieldset[data-app-role]',$form), //The number of fieldsets. must match value of sum to be valid. @@ -367,8 +305,8 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure var $fieldset = $(this), role = $(this).data('app-role'); - if(role && typeof app.ext.orderCreate.validate[role] === 'function') { - sum += app.ext.orderCreate.validate[role]($fieldset,formObj); + if(role && typeof _app.ext.order_create.validate[role] === 'function') { + sum += _app.ext.order_create.validate[role]($fieldset,formObj); } else { errors += "<div>validate role ["+role+"] is not a function<\/div>"; @@ -378,7 +316,7 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure //errors would only be set if something went wrong in validation, not for missing fields which are handled within the individual panel validation. if(errors != '') { r = false; - $('#globalMessaging').anymessage({'message':'In orderCreate.validate.checkout, the following errors occured:<br>'+errors,'gMessage':true}); + $('#globalMessaging').anymessage({'message':'In order_create.validate.checkout, the following errors occured:<br>'+errors,'gMessage':true}); } else if(sum == $fieldsets.length) { r = true; @@ -390,9 +328,9 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure } else { r = false; - $('#globalMessaging').anymessage({'message':'In orderCreate.validate.checkout, $form was not passed.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In order_create.validate.checkout, $form was not passed.','gMessage':true}); } - app.u.dump("validate.checkout: "+r); + _app.u.dump("validate.checkout: "+r); return r; }, //isValid //validation function should be named the same as the data-app-role of the fieldset. @@ -401,13 +339,15 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure var valid = 0; //used to return validation state. 0 = false, 1 = true. integers used to sum up panel validation. if($fieldset && formObj) { - if(app.u.validateForm($fieldset)) {valid = 1;} //the validateForm field takes care of highlighting necessary fields and hints. + if(_app.u.validateForm($fieldset)) {valid = 1;} //the validateForm field takes care of highlighting necessary fields and hints. else {valid = 0} } else { - $('#globalMessaging').anymessage({'message':'In orderCreate.validate.chkoutPreflight, $form or formObj not passed.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In order_create.validate.chkoutPreflight, $form or formObj not passed.','gMessage':true}); + } + if(!valid) { + _app.u.dump(" -> order_create.validate.chkoutPreflight: "+valid); } -// app.u.dump(" -> orderCreate.validate.chkoutPreflight: "+valid); return valid; }, //chkoutPreflightFieldset @@ -416,7 +356,7 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure if($fieldset && formObj) { if(!formObj['want/create_customer']) {valid = 1} - else if(app.u.validateForm($fieldset)) { + else if(_app.u.validateForm($fieldset)) { if(formObj['want/new_password'] == formObj['want/new_password2']) {valid = 1;} else { valid = 0; @@ -426,9 +366,11 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure else {valid = 0;} //didn't pass the basic validation. } else { - $('#globalMessaging').anymessage({'message':'In orderCreate.validate.chkoutAccountCreate, $form or formObj not passed.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In order_create.validate.chkoutAccountCreate, $form or formObj not passed.','gMessage':true}); + } + if(!valid) { + _app.u.dump(" -> order_create.validate.chkoutAccountCreate: "+valid); } -// app.u.dump(" -> orderCreate.validate.chkoutAccountCreate: "+valid); return valid; }, //validate.chkoutAccountInfoFieldset @@ -436,9 +378,9 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure chkoutMethodsShip : function($fieldset,formObj) { var valid = 0; if($fieldset && formObj) { - if(app.ext.cco.u.thisSessionIsPayPal()) {valid = 1} //ship address comes back from paypal. panel is hidden. auto-approve. + if(_app.ext.cco.u.thisSessionIsPayPal()) {valid = 1} //ship address comes back from paypal. panel is hidden. auto-approve. else if($("[name='want/shipping_id']:checked").length) { - if(app.u.validateForm($fieldset)){valid = 1;} + if(_app.u.validateForm($fieldset)){valid = 1;} else {valid = 0;} } else { @@ -447,24 +389,30 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure } } else { - $('#globalMessaging').anymessage({'message':'In orderCreate.validate.chkoutMethodsShip, $form or formObj not passed.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In order_create.validate.chkoutMethodsShip, $form or formObj not passed.','gMessage':true}); + } + if(!valid) { + _app.u.dump(" -> order_create.validate.chkoutMethodsShip: "+valid); } - -// app.u.dump(" -> orderCreate.validate.chkoutMethodsShip: "+valid); return valid; }, //validate.chkoutShipMethodsFieldset - + //in addition to selecting a pay option, certain extra fields may be present and must be checked for. chkoutMethodsPay : function($fieldset,formObj) { var valid = 0; + var cartID = $fieldset.closest("[data-app-role='checkout']").data('cartid'); if($fieldset && formObj) { - if(app.ext.cco.u.thisSessionIsPayPal() && app.ext.cco.u.aValidPaypalTenderIsPresent()) {valid = 1;} //if paypal + if(_app.ext.cco.u.thisSessionIsPayPal() && _app.ext.cco.u.aValidPaypalTenderIsPresent()) {valid = 1;} //if paypal //should only get match here for expired paypal payments or some unexpected paypal related issue. - else if(app.ext.cco.u.thisSessionIsPayPal()){ + else if(_app.ext.cco.u.thisSessionIsPayPal()){ $fieldset.anymessage({'message':"It appears something has gone wrong with your paypal authorization. Perhaps it expired. Please click the 'choose alternate payment method' link and either re-authorize through paypal or choose an alternate payment method. We apologize for the inconvenience. "}) } + //if the balance is zero, no payment method is necessary. + else if(_app.u.thisNestedExists("data.cartDetail|"+cartID+".sum.balance_due_total",_app) && Number(_app.data["cartDetail|"+cartID].sum.balance_due_total) <= 0) { + valid = 1; + } else if($('[name="want/payby"]:checked',$fieldset).length) { - if(app.u.validateForm($fieldset)) {valid = 1;} + if(_app.u.validateForm($fieldset)) {valid = 1;} else {valid = 0} } else { @@ -474,23 +422,35 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure } else { valid = 0; - $('#globalMessaging').anymessage({'message':'In orderCreate.validate.chkoutMethodsPay, $form or formObj not passed.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In order_create.validate.chkoutMethodsPay, $form or formObj not passed.','gMessage':true}); + } + if(!valid) { + _app.u.dump(" -> order_create.validate.chkoutMethodsPay: "+valid); } -// app.u.dump(" -> orderCreate.validate.chkoutMethodsPay: "+valid); return valid; }, //chkoutPayOptionsFieldset - - chkoutAddressBill: function($fieldset,formObj) { - var valid = 0; + chkoutAddressBill: function($fieldset,formObj) { + var valid = 0, cartID = $fieldset.closest("[data-app-role='checkout']").data('cartid'), CID; + + if(_app.u.thisNestedExists("data.cartDetail|"+cartID+".customer.cid",_app) && _app.data['cartDetail|'+cartID].customer.cid > 0) { + CID = _app.data['cartDetail|'+cartID].customer.cid; + } if($fieldset && formObj) { // *** 201338 -> some paypal orders not passing validation due to address wonkyness returned from paypal. //paypal address gets returned with as much as paypal needs/wants. trust what we already have (which may not be enough for OUR validation) - if(app.ext.cco.u.thisSessionIsPayPal()) { + if(_app.ext.cco.u.thisSessionIsPayPal()) { valid = 1; } //if the buyer is logged in AND has pre-existing billing addresses, make sure one is selected. - else if(app.u.buyerIsAuthenticated() && app.data.buyerAddressList && app.data.buyerAddressList['@bill'] && app.data.buyerAddressList['@bill'].length) { + else if(_app.u.buyerIsAuthenticated() && _app.data.buyerAddressList && _app.data.buyerAddressList['@bill'] && _app.data.buyerAddressList['@bill'].length) { + if(formObj['bill/shortcut']) {valid = 1} + else { + $fieldset.anymessage({'message':'Please select the address you would like to use (push the checkmark button)'}); + } + } +//in an admin session w/ an existing user, make sure the address has been selected IF the buyer has pre-defined addresses. + else if(_app.u.thisIsAnAdminSession() && CID && _app.u.thisNestedExists("data.adminCustomerDetail|"+CID+".@BILL",_app) && _app.data['adminCustomerDetail|'+CID]['@BILL'].length ) { if(formObj['bill/shortcut']) {valid = 1} else { $fieldset.anymessage({'message':'Please select the address you would like to use (push the checkmark button)'}); @@ -499,7 +459,8 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure else { //handle phone number input based on zGlobals setting. - if(zGlobals && zGlobals.checkoutSettings && zGlobals.checkoutSettings.chkout_phone == 'REQUIRED') { + + if(!_app.u.thisIsAnAdminSession() && zGlobals && zGlobals.checkoutSettings && zGlobals.checkoutSettings.chkout_phone == 'REQUIRED') { $("input[name='bill/phone']",$fieldset).attr('required','required'); } else { @@ -520,32 +481,42 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure $("input[name='bill/region']",$fieldset).attr('required','').removeAttr('required'); } - if(app.u.validateForm($fieldset)) {valid = 1;} //the validateForm field takes care of highlighting necessary fields and hints. + if(_app.u.validateForm($fieldset)) {valid = 1;} //the validateForm field takes care of highlighting necessary fields and hints. else {valid = 0} } } else { valid = 0; - $('#globalMessaging').anymessage({'message':'In orderCreate.validate.chkoutAddressBill, $form or formObj not passed.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In order_create.validate.chkoutAddressBill, $form or formObj not passed.','gMessage':true}); + } + if(!valid) { + _app.u.dump(" -> order_create.validate.chkoutAddressBill: "+valid); } - -// app.u.dump(" -> orderCreate.validate.chkoutAddressBill: "+valid); return valid; }, //chkoutBillAddressFieldset - + chkoutAddressShip: function($fieldset,formObj) { - var valid = 0; + dump("BEGIN ship address validation"); + var valid = 0, cartID = $fieldset.closest("[data-app-role='checkout']").data('cartid'); if($fieldset && formObj) { - if(formObj['want/bill_to_ship']) {valid = 1} + if(formObj['want/bill_to_ship']) {dump(" -> Bill to ship is enabled."); valid = 1;} // *** 201338 -> some paypal orders not passing validation due to address wonkyness returned from paypal. //paypal address gets returned with as much as they need/want. trust what we already have (which may not be enough for OUR validation) - else if(app.ext.cco.u.thisSessionIsPayPal()) { + else if(_app.ext.cco.u.thisSessionIsPayPal()) { valid = 1; } //if the buyer is logged in AND has pre-existing billing addresses, make sure one is selected. - else if(app.u.buyerIsAuthenticated() && app.data.buyerAddressList && app.data.buyerAddressList['@ship'] && app.data.buyerAddressList['@ship'].length) { + else if(_app.u.buyerIsAuthenticated() && _app.data.buyerAddressList && _app.data.buyerAddressList['@ship'] && _app.data.buyerAddressList['@ship'].length) { + dump(" -> user is authenticated and has ship address(es) defined"); + if(formObj['ship/shortcut']) {valid = 1} + else { + $fieldset.anymessage({'message':'Please select the address you would like to use (push the checkmark button)'}); + } + } +//in an admin session w/ an existing user, make sure the address has been selected. + else if(_app.u.thisIsAnAdminSession() && _app.u.thisNestedExists("data.cartDetail|"+cartID+".customer.cid",_app) && _app.data['cartDetail|'+cartID].customer.cid > 0) { if(formObj['ship/shortcut']) {valid = 1} else { $fieldset.anymessage({'message':'Please select the address you would like to use (push the checkmark button)'}); @@ -567,16 +538,17 @@ _gaq.push(['_trackEvent','Checkout','App Event','Order NOT created. error occure $("input[name='bill/region']",$fieldset).attr('required','').removeAttr('required'); } - if(app.u.validateForm($fieldset)) {valid = 1;} //the validateForm field takes care of highlighting necessary fields and hints. + if(_app.u.validateForm($fieldset)) {valid = 1;} //the validateForm field takes care of highlighting necessary fields and hints. else {valid = 0} } } else { valid = 0; - $('#globalMessaging').anymessage({'message':'In orderCreate.validate.chkoutAddressShip, $form or formObj not passed.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In order_create.validate.chkoutAddressShip, $form or formObj not passed.','gMessage':true}); + } + if(!valid) { + _app.u.dump(" -> cs2o.validate.chkoutAddressShip: "+valid); } - - app.u.dump(" -> cs2o.validate.chkoutAddressShip: "+valid); return valid; }, //chkoutBillAddressFieldset @@ -616,15 +588,15 @@ after a login occurs, all the panels are updated because the users account could payment options, pricing, etc */ chkoutPreflight : function(formObj,$fieldset) { -// app.u.dump("BEGIN orderCreate.panelDisplayLogic.chkoutPreflight"); +// _app.u.dump("BEGIN order_create.panelDisplayLogic.chkoutPreflight"); //If the user is logged in, no sense showing password or create account prompts. $("[data-app-role='buyerLogout']").hide(); //make sure this is hidden. Will be shown when necessary. - if(app.u.buyerIsAuthenticated() || app.ext.cco.u.thisSessionIsPayPal()) { - app.u.dump(" -> session is authenticated OR this is an authorized paypal transaction."); + if(_app.u.buyerIsAuthenticated() || _app.ext.cco.u.thisSessionIsPayPal()) { + _app.u.dump(" -> session is authenticated OR this is an authorized paypal transaction."); $("[data-app-role='login']",$fieldset).hide(); $("[data-app-role='username']",$fieldset).show(); //if the user is logged in, show the 'not you?' feature. However, don't show it if this is already paypal (at that point, they are who they say they are) - if(!app.ext.cco.u.thisSessionIsPayPal()) { + if(!_app.ext.cco.u.thisSessionIsPayPal()) { $("[data-app-role='buyerLogout']").show(); } } @@ -639,16 +611,26 @@ payment options, pricing, etc $("[data-app-role='username']",$fieldset).hide(); $("[data-app-role='loginPasswordContainer']",$fieldset).show(); } - app.ext.orderCreate.u.handlePlaceholder($fieldset); + // ** 201402 + //if the user is logged in, make sure the 'create account' checkbox is NOT checked. + //otherwise, if checked=checked is set to enable account create by default and a user logs in, the checked box will cause validation error on a hidden panel. + if(_app.u.buyerIsAuthenticated()) { + $("input[name='want/create_customer']",$fieldset).prop('checked',false); + } + + _app.ext.order_create.u.handlePlaceholder($fieldset); }, //preflight chkoutAccountCreate : function(formObj,$fieldset) { -// app.u.dump('BEGIN orderCreate.panelDisplayLogic.chkoutAccountCreate'); +// _app.u.dump('BEGIN order_create.panelDisplayLogic.chkoutAccountCreate'); - var authState = app.u.determineAuthentication(), + var authState = _app.u.determineAuthentication(), createCustomer = formObj['want/create_customer']; - - if(authState == 'authenticated' || authState == 'thirdPartyGuest' || app.ext.cco.u.thisSessionIsPayPal()) { + + if(_app.u.buyerIsAuthenticated()) { + $fieldset.hide(); + } + else if(authState == 'thirdPartyGuest' || _app.ext.cco.u.thisSessionIsPayPal()) { $fieldset.hide(); } else { @@ -660,7 +642,7 @@ payment options, pricing, etc $fieldset.hide(); } } - app.ext.orderCreate.u.handlePlaceholder($fieldset); + _app.ext.order_create.u.handlePlaceholder($fieldset); }, //chkoutAccountCreate /* @@ -668,15 +650,16 @@ a guest checkout gets just a standard address entry. an existing user gets a list of previous addresses they've used and an option to enter a new address. */ chkoutAddressBill : function(formObj,$fieldset) { -// app.u.dump("BEGIN displayLogic.chkoutAddressBill"); +// _app.u.dump("BEGIN displayLogic.chkoutAddressBill"); var checkoutMode = $fieldset.closest('form').data('app-checkoutmode'), //='required' - isAuthenticated = app.u.buyerIsAuthenticated(); + isAuthenticated = _app.u.buyerIsAuthenticated(), + cartID = $fieldset.closest("[data-app-role='checkout']").data('cartid'); if(!isAuthenticated && checkoutMode == 'required') { //do nothing. panel is hidden by default, so no need to 'show' it. } - else if(app.ext.cco.u.thisSessionIsPayPal()){ - app.u.dump("This is a paypal session"); + else if(_app.ext.cco.u.thisSessionIsPayPal()){ + _app.u.dump("This is a paypal session"); $fieldset.show(); //make sure panel is visible. $("[data-app-role='addressExists']",$fieldset).hide(); $("[data-app-role='addressNew']",$fieldset).show(); @@ -684,17 +667,17 @@ an existing user gets a list of previous addresses they've used and an option to $("[name='want/bill_to_ship']",$fieldset).attr({'disabled':'disabled'}).removeAttr('checked'); //set val //name is provided by paypal and can't be changed. $("[name='bill/firstname'], [name='bill/lastname']",$fieldset).attr('disabled','disabled'); - } - else if(isAuthenticated && app.ext.cco.u.buyerHasPredefinedAddresses('bill') == true) { +//displayLogic is executed AFTER the translation has occured, so use the # of <address> tags to determine if any addresses are present. + else if($("address",$fieldset).length >= 1) { $fieldset.show(); //make sure panel is visible. $("[data-app-role='addressExists']",$fieldset).show(); $("[data-app-role='addressNew']",$fieldset).hide(); - $("address button[data-app-event='orderCreate|execBuyerAddressSelect']",$fieldset).removeClass('ui-state-highlight').button({icons: {primary: "ui-icon-check"},text:false}); //content was likely cleared, so button() these again. + $("address button[data-app-click='order_create|execBuyerAddressSelect']",$fieldset).removeClass('ui-state-highlight').button({icons: {primary: "ui-icon-check"},text:false}); //content was likely cleared, so button() these again. if(formObj['bill/shortcut']) { - app.u.dump("Bill shortcut is set: "+formObj['bill/shortcut']); + _app.u.dump("Bill shortcut is set: "+formObj['bill/shortcut']); //highlight the checked button of the address selected.<< - var $button = $("[data-_id='"+formObj['bill/shortcut']+"'] button[data-app-event='orderCreate|execBuyerAddressSelect']",$fieldset).addClass('ui-state-highlight').button( "option", "icons", { primary: "ui-icon-check"} ); + var $button = $("[data-_id='"+formObj['bill/shortcut']+"'] button[data-app-click='order_create|execBuyerAddressSelect']",$fieldset).addClass('ui-state-highlight').button( "option", "icons", { primary: "ui-icon-check"} ); } } else { @@ -702,24 +685,28 @@ an existing user gets a list of previous addresses they've used and an option to $("[data-app-role='addressExists']",$fieldset).hide(); $("[data-app-role='addressNew']",$fieldset).show(); //from a usability perspective, we don't want a single item select list to show up. so hide if only 1 or 0 options are available. - if(app.data.appCheckoutDestinations['@destinations'].length < 2) { + if(_app.data['appCheckoutDestinations|'+cartID] && _app.data['appCheckoutDestinations|'+cartID]['@destinations'] && _app.data['appCheckoutDestinations|'+cartID]['@destinations'].length < 2) { $("[data-app-role='billCountry']",$fieldset).hide(); } +//The template used for address input is shared w/ address edit for authenticated users. In edit, certain events are not desired. So the events are added here. + $("input[name='bill/address1'], input[name='bill/address2'], input[name='bill/city'], input[name='bill/region'], input[name='bill/postal']",$fieldset).attr('data-app-blur','order_create|execAddressUpdate'); + $("select[name='bill/countrycode']",$fieldset).attr('data-app-change','order_create|execCountryUpdate'); } - app.ext.orderCreate.u.handlePlaceholder($fieldset); + _app.ext.order_create.u.handlePlaceholder($fieldset); }, //chkoutAddressBill chkoutAddressShip : function(formObj,$fieldset) { var checkoutMode = $fieldset.closest('form').data('app-checkoutmode'), //='required' - isAuthenticated = app.u.buyerIsAuthenticated(); + isAuthenticated = _app.u.buyerIsAuthenticated(), + cartID = $fieldset.closest("[data-app-role='checkout']").data('cartid'); //determine if panel should be visible or not. - if(formObj['want/bill_to_ship'] == 'on' && !app.ext.cco.u.thisSessionIsPayPal()) {$fieldset.hide()} + if(formObj['want/bill_to_ship'] == 'on' && !_app.ext.cco.u.thisSessionIsPayPal()) {$fieldset.hide()} else if(!isAuthenticated && checkoutMode == 'required') {} //do nothing. panel is hidden by default in required mode. else {$fieldset.show()} //update display of panel contents. - if(app.ext.cco.u.thisSessionIsPayPal()){ + if(_app.ext.cco.u.thisSessionIsPayPal()){ $("[data-app-role='addressExists']",$fieldset).hide(); $("[data-app-role='addressNew']",$fieldset).show(); //disable all shipping address inputs that are populated (by paypal) and select lists @@ -729,70 +716,90 @@ an existing user gets a list of previous addresses they've used and an option to } }); } - else if(app.u.buyerIsAuthenticated() && app.ext.cco.u.buyerHasPredefinedAddresses('ship') == true) { +//displayLogic is executed AFTER the translation has occured, so use the # of <address> tags to determine if any addresses are present. + else if($("address",$fieldset).length >= 1) { $("[data-app-role='addressExists']",$fieldset).show(); $("[data-app-role='addressNew']",$fieldset).hide(); - $("address button[data-app-event='orderCreate|execBuyerAddressSelect']",$fieldset).removeClass('ui-state-highlight').button({icons: {primary: "ui-icon-check"},text:false}); //content was likely cleared, so button() these again. + $("address button[data-app-click='order_create|execBuyerAddressSelect']",$fieldset).removeClass('ui-state-highlight').button({icons: {primary: "ui-icon-check"},text:false}); //content was likely cleared, so button() these again. if(formObj['ship/shortcut']) { - app.u.dump("Ship shortcut is set: "+formObj['ship/shortcut']); + _app.u.dump("Ship shortcut is set: "+formObj['ship/shortcut']); //highlight the checked button of the address selected.<< - var $button = $("[data-_id='"+formObj['ship/shortcut']+"'] button[data-app-event='orderCreate|execBuyerAddressSelect']",$fieldset).addClass('ui-state-highlight').button( "option", "icons", { primary: "ui-icon-check"} ); + var $button = $("[data-_id='"+formObj['ship/shortcut']+"'] button[data-app-click='order_create|execBuyerAddressSelect']",$fieldset).addClass('ui-state-highlight').button( "option", "icons", { primary: "ui-icon-check"} ); } } else { $("[data-app-role='addressExists']",$fieldset).hide(); $("[data-app-role='addressNew']",$fieldset).show(); //from a usability perspective, we don't want a single item select list to show up. so hide if only 1 or 0 options are available. - if(app.data.appCheckoutDestinations['@destinations'].length < 2) { + if(_app.data['appCheckoutDestinations|'+cartID] && _app.data['appCheckoutDestinations|'+cartID]['@destinations'] && _app.data['appCheckoutDestinations|'+cartID]['@destinations'].length < 2) { $("[data-app-role='shipCountry']",$fieldset).hide(); } +//The template used for address input is shared w/ address edit for authenticated users. In edit, certain events are not desired. So the events are added here. + $("input[name='ship/address1'], input[name='ship/address2'], input[name='ship/city'], input[name='ship/region'], input[name='ship/postal']",$fieldset).attr('data-app-blur','order_create|execAddressUpdate'); + $("select[name='ship/countrycode']",$fieldset).attr('data-app-change','order_create|execCountryUpdate'); } - app.ext.orderCreate.u.handlePlaceholder($fieldset); + _app.ext.order_create.u.handlePlaceholder($fieldset); }, //chkoutAddressShip chkoutMethodsShip : function(formObj,$fieldset) { -// app.u.dump('BEGIN app.ext.orderCreate.panelContent.shipMethods'); +// _app.u.dump('BEGIN _app.ext.order_create.panelContent.shipMethods'); //close any existing error messages if($('.ui-widget-anymessage',$fieldset).length) { $fieldset.anymessage('close'); } var checkoutMode = $fieldset.closest('form').data('app-checkoutmode'), //='required' - isAuthenticated = app.u.buyerIsAuthenticated(), - shipMethods = app.data.cartDetail['@SHIPMETHODS'], + isAuthenticated = _app.u.buyerIsAuthenticated(), + cartID = $fieldset.closest("[data-app-role='checkout']").data('cartid'), + shipMethods = (_app.data['cartDetail|'+cartID]) ? _app.data['cartDetail|'+cartID]['@SHIPMETHODS'] : [], L = (shipMethods) ? shipMethods.length : 0; -// app.u.dump(' -> shipMethods.length: '+L); // app.u.dump(shipMethods); +// _app.u.dump(' -> shipMethods.length: '+L); // _app.u.dump(shipMethods); -//if it is decided not to hide the panel, the radio buttons must be locked/disabled. +//WARNING -> if you decide not to hide the panel, the radio buttons must be locked/disabled instead. if(!isAuthenticated && checkoutMode == 'required') { //do nothing. panel is hidden by default, so no need to 'show' it. } - else if(app.ext.cco.u.thisSessionIsPayPal()) { + else if(_app.ext.cco.u.thisSessionIsPayPal()) { $fieldset.hide(); } else { $fieldset.show(); } - - +//add the click event so that a change updates the cart/panels as needed. +//not in the render format itself so that it can be recycled. + $(":radio",$fieldset).each(function(){ + $(this).attr('data-app-change','order_create|shipOrPayMethodSelectExec'); + }) //must appear after panel is loaded because otherwise the divs don't exist. //per brian, use shipping methods in cart, not in shipping call. // the panel content IS rendered even if not shown. ship method needs to be set for paypal if(L >= 1) { -// app.u.dump(" -> Shipping methods are present."); +// _app.u.dump(" -> Shipping methods are present."); +//if the method selected is UPS AND the merchant has rules enabled for that method, UPS requires the disclaimer to be shown. + for(var i = 0; i < L; i += 1) { + if(shipMethods[i].id == formObj['want/shipping_id']) { + if(shipMethods[i]._carrier == 'UPS' && shipMethods[i].rules) { + $("[data-app-role='upsShipRulesDisclaimer']",$fieldset).show(); + } + break; //exit early once a match is found. + } + } + } + else if(_app.vars.thisSessionIsAdmin && !_app.data['cartDetail|'+cartID]['@ITEMS'].length) { + $fieldset.anymessage({"message":"<p>An item must be added to the cart before shipping can be displayed.</p>","persistent":true}); } //no shipping methods and buyer is logged in. - else if(app.u.buyerIsAuthenticated()) { - var hasPredefBillAddr = app.ext.cco.u.buyerHasPredefinedAddresses('bill'), - hasPredefShipAddr = app.ext.cco.u.buyerHasPredefinedAddresses('ship'); + else if(_app.u.buyerIsAuthenticated()) { + var hasPredefBillAddr = _app.ext.cco.u.buyerHasPredefinedAddresses('bill'), + hasPredefShipAddr = _app.ext.cco.u.buyerHasPredefinedAddresses('ship'); if(formObj['want/bill_to_ship'] && hasPredefBillAddr && formObj['bill/shortcut']){ $fieldset.anymessage({"message":"<p>No shipping methods are available.</p>","persistent":true}); } - else if(!formObj['want/bill_to_ship'] && app.ext.cco.u.buyerHasPredefinedAddresses('ship') == true && formObj['ship/shortcut']){ + else if(!formObj['want/bill_to_ship'] && _app.ext.cco.u.buyerHasPredefinedAddresses('ship') == true && formObj['ship/shortcut']){ $fieldset.anymessage({"message":"<p>No shipping methods are available.</p>","persistent":true}); } else { @@ -801,13 +808,9 @@ an existing user gets a list of previous addresses they've used and an option to } //no shipping methods present and buyer is logged out. else { -// *** 201324 -> correct typos. nice catch MikeC. The absence of a 'not' was causing messaging to appear at the wrong time. -// only impacted merchants who had 'require zip to quote shipping' enabled. -// if(formObj['want/bill_to_ship'] && formObj['bill/postal']) { if(formObj['want/bill_to_ship'] && !formObj['bill/postal']) { $fieldset.anymessage({"message":"<p>Please enter a billing/shipping zip code for a list of shipping options.</p>","persistent":true}); } -// else if(!formObj['want/bill_to_ship'] && formObj['ship/postal']) { else if(!formObj['want/bill_to_ship'] && !formObj['ship/postal']) { $fieldset.anymessage({"message":"<p>Please enter a shipping zip code for a list of shipping options.</p>","persistent":true}); } @@ -819,7 +822,7 @@ an existing user gets a list of previous addresses they've used and an option to chkoutCartItemsList : function(formObj,$fieldset){ var checkoutMode = $fieldset.closest('form').data('app-checkoutmode'), //='required' - isAuthenticated = app.u.buyerIsAuthenticated(); + isAuthenticated = _app.u.buyerIsAuthenticated(); if(!isAuthenticated && checkoutMode == 'required') { //do nothing. panel is hidden by default, so no need to 'show' it. } @@ -830,8 +833,7 @@ an existing user gets a list of previous addresses they've used and an option to chkoutCartSummary : function(formObj,$fieldset) { var checkoutMode = $fieldset.closest('form').data('app-checkoutmode'), //='required' - isAuthenticated = app.u.buyerIsAuthenticated(); - + isAuthenticated = _app.u.buyerIsAuthenticated(); if(!isAuthenticated && checkoutMode == 'required') { //do nothing. panel is hidden by default, so no need to 'show' it. } @@ -849,68 +851,82 @@ an existing user gets a list of previous addresses they've used and an option to } }, //chkoutCartSummary - chkoutMethodsPay : function(formObj,$fieldset) { + chkoutMethodsPay : function(formObj,$fieldset,cartData) { //the renderformat will handle the checked=checked. however some additional payment inputs may need to be added. that happens here. - var checkoutMode = $fieldset.closest('form').data('app-checkoutmode'), //='required' - isAuthenticated = app.u.buyerIsAuthenticated(); + var + checkoutMode = $fieldset.closest('form').data('app-checkoutmode'), //='required' + isAuthenticated = _app.u.buyerIsAuthenticated(), + cartID = $fieldset.closest("[data-app-role='checkout']").data('cartid'); if(!isAuthenticated && checkoutMode == 'required') { //do nothing. panel is hidden by default, so no need to 'show' it. } - else if(app.ext.cco.u.thisSessionIsPayPal()) { + else if(_app.ext.cco.u.thisSessionIsPayPal()) { $fieldset.show(); //this is a paypal session. payment methods are not available any longer. stored payments are irrelevant. show paymentQ //also show a message to allow the merchant to remove the paypal payment option and use a different method? $("[data-app-role='giftcardContainer']",$fieldset).hide(); $("[data-app-role='paymentOptionsContainer']",$fieldset).hide(); - $("[data-app-event='orderCreate|execChangeFromPayPal']",$fieldset).show(); + $("[data-app-click='order_create|execChangeFromPayPal']",$fieldset).show(); } else { $fieldset.show(); //if the user is logged in and has giftcards, show a message about partial GC payments. - if(app.u.buyerIsAuthenticated() && app.ext.cco.u.paymentMethodsIncludesGiftcard('appPaymentMethods')){ + if(_app.u.buyerIsAuthenticated() && _app.ext.cco.u.paymentMethodsIncludesGiftcard('appPaymentMethods|'+$fieldset.closest("[data-app-role='checkout']").data('cartid'))){ $("[data-app-role='giftcardHint']",$fieldset).show(); } else {} //user is not logged in. - -//if the user is logged in and has wallets, they are displayed in a tabbed format. - if(app.u.buyerIsAuthenticated() && app.data.buyerWalletList && app.data.buyerWalletList['@wallets'].length) { - - $("[data-app-role='storedPaymentsHeader']",$fieldset).show(); - $("[data-app-role='storedPaymentsContent']",$fieldset).show(); - $("[data-app-role='nonStoredPaymentsHeader']",$fieldset).show(); - $("[data-app-role='nonStoredPaymentsContent']",$fieldset).show(); - - $("[data-app-role='paymentOptionsContainer']",$fieldset).accordion({ - heightStyle: "content", - active: (app.data.cartDetail && app.data.cartDetail.want && app.data.cartDetail.want.payby && app.data.cartDetail.want.payby.indexOf('WALLET') == -1) ? 0 : 1 //unless a buyer has already selected a non-wallet payment method, show stores payments as open. - }); + //if the balance is zero, hide the payment inputs to avoid confusion. + if(_app.u.thisNestedExists("data.cartDetail|"+cartID+".sum.balance_due_total",_app) && Number(_app.data["cartDetail|"+cartID].sum.balance_due_total) <= 0) { + $("[data-app-role='paymentOptionsContainer']",$fieldset).hide(); } else { - $("[data-app-role='storedPaymentsHeader']",$fieldset).hide(); - $("[data-app-role='storedPaymentsContent']",$fieldset).hide(); - $("[data-app-role='nonStoredPaymentsHeader']",$fieldset).hide(); //header only needed if stored payments are present. - $("[data-app-role='nonStoredPaymentsContent']",$fieldset).show(); +//detect # of wallets and behave accordingly. + if($("[data-app-role='storedPaymentsContent']",$fieldset).children().length >= 1) { + var cartID = $fieldset.closest("[data-app-role='checkout']").data('cartid'); + $("[data-app-role='storedPaymentsHeader']",$fieldset).show(); + $("[data-app-role='storedPaymentsContent']",$fieldset).show(); + $("[data-app-role='nonStoredPaymentsHeader']",$fieldset).show(); + $("[data-app-role='nonStoredPaymentsContent']",$fieldset).show(); + + $("[data-app-role='paymentOptionsContainer']",$fieldset).accordion({ + heightStyle: "content", + active: (_app.data['cartDetail|'+cartID] && _app.data['cartDetail|'+cartID].want && _app.data['cartDetail|'+cartID].want.payby && _app.data['cartDetail|'+cartID].want.payby.indexOf('WALLET') == -1) ? 0 : 1 //unless a buyer has already selected a non-wallet payment method, show stores payments as open. + }); + } + else { + $("[data-app-role='storedPaymentsHeader']",$fieldset).hide(); + $("[data-app-role='storedPaymentsContent']",$fieldset).hide(); + $("[data-app-role='nonStoredPaymentsHeader']",$fieldset).hide(); //header only needed if stored payments are present. + $("[data-app-role='nonStoredPaymentsContent']",$fieldset).show(); + } } - -//data-app-role='giftcardHint' - //if a payment method has been selected, show the supplemental inputs and check the selected payment. //additionally, if the payment is NOT Purchase Order AND the company field is populated, show the reference # input. -// !!! this doesn't work because want/payby is no longer a valid field. Either need a field to temporarily store this in OR need to start using localStorage for this. - if(formObj['want/payby']) { +//* 201405 -> issue w/ IE8 not recognizing want/payby being set after selecting/changing payment methods. + var payby = formObj['want/payby']; + if(!payby && _app.u.thisNestedExists("want.payby",cartData)) { + payby = cartData.want.payby; + } + if(payby) { var - $radio = $("input[value='"+formObj['want/payby']+"']",$fieldset), - $supplemental = app.ext.orderCreate.u.showSupplementalInputs($radio,app.ext.orderCreate.vars); - - $radio.attr('checked','checked'); + $radio = $("input[value='"+payby+"']",$fieldset), + $supplemental = _app.ext.order_create.u.showSupplementalInputs($radio,_app.ext.order_create.vars); if($supplemental) { - app.u.dump(" -> payment method ["+formObj['want/payby']+"] HAS supplemental inputs"); + _app.u.dump(" -> payment method ["+payby+"] HAS supplemental inputs"); $radio.closest("[data-app-role='paymentMethodContainer']").append($supplemental); } + //the 'loop' renderformat for wallet display only accepts one piece of data. in this case, the walley payment method. + //so the 'cart' isn't available to load payby. crappy. a better long term solution would be a tlcFormat + if(payby.indexOf('WALLET') >= 0) { + $radio.prop('checked','checked') + } + } + else { +//no payment method selected yet. } } @@ -919,17 +935,17 @@ an existing user gets a list of previous addresses they've used and an option to chkoutNotes : function(formObj,$fieldset) { var checkoutMode = $fieldset.closest('form').data('app-checkoutmode'), //='required' - isAuthenticated = app.u.buyerIsAuthenticated(); + isAuthenticated = _app.u.buyerIsAuthenticated(); if(!isAuthenticated && checkoutMode == 'required') { //do nothing. panel is hidden by default, so no need to 'show' it. } - else if(app.vars.thisSessionIsAdmin || zGlobals.checkoutSettings.chkout_order_notes) {$fieldset.show()} + else if(_app.u.thisIsAnAdminSession() || zGlobals.checkoutSettings.chkout_order_notes) {$fieldset.show()} else {$fieldset.hide()} } //chkoutNotes - }, //panelContent + }, //panelDisplayLogic -//push onto this (orderCreate.checkoutCompletes.push(function(P){}); +//push onto this (order_create.checkoutCompletes.push(function(P){}); //after checkout, these will be iterated thru and executed. /* Parameters included are as follows: @@ -937,668 +953,1035 @@ P.orderID P.cartID (this would be the cartID associated w/ the order. immediately after checkout, this is dumped by the mvc and a new cart id is generated/used) P.datapointer - pointer to cartOrderCreate -note - the order object is available at app.data['order|'+P.orderID] +note - the order object is available at _app.data['order|'+P.orderID] */ checkoutCompletes : [], a : { - - startCheckout : function($chkContainer) { -// app.u.dump("BEGIN orderCreate.a.startCheckout"); -// app.u.dump(" -> app.u.buyerIsAuthenticated(): "+app.u.buyerIsAuthenticated()); + //used in the admin UI for creating a new cart. + appCartCreate : function($target) { + _app.calls.appCartCreate.init({'datapointer':'appCartCreate','callback':function(rd){ + if(_app.model.responseHasErrors(rd)){ + $target.anymessage({'message':rd}); + } + else { +//appCartCreate will automatically update the carts object in localstorage + _app.ext.order_create.a.startCheckout($target,_app.data[rd.datapointer]._cartid); + _app.ext.cco.calls.cartSet.init({'_cartid':_app.data[rd.datapointer]._cartid,'our/domain':_app.vars.domain}); //do NOT set a host here. + _app.model.dispatchThis('immutable'); + } + }},'immutable'); + _app.model.dispatchThis('immutable'); + }, +// ### FUTURE -> get rid of this. startCheckout should support an object instead of a single param. + editCart : function($target,P) { + this.startCheckout($target,P.cartid); + }, - if($chkContainer && $chkContainer.length) { +//don't execute this UNTIL you have a valid cart id. + startCheckout : function($chkContainer,cartID) { + _app.u.dump("BEGIN order_create.a.startCheckout. cartID: "+cartID); +// _app.u.dump(" -> _app.u.buyerIsAuthenticated(): "+_app.u.buyerIsAuthenticated()); + + if($chkContainer && $chkContainer.length && cartID) { + _app.u.dump(" -> startCheckout cartid: "+cartID); $chkContainer.empty(); + + _app.u.addEventDelegation($chkContainer); + $chkContainer.anyform({ + trackEdits : _app.u.thisIsAnAdminSession() //edits are only tracked in the admin interface + }); $chkContainer.css('min-height','300'); //set min height so loading shows up. + $chkContainer.showLoading({'message':'Fetching cart contents and payment options'}); - if(app.vars.thisSessionIsAdmin) { - } - else if(Number(zGlobals.globalSettings.inv_mode) > 1) { - app.u.dump(" -> inventory mode set in such a way that an inventory check will occur."); - app.ext.cco.calls.cartItemsInventoryVerify.init({'callback':'handleInventoryUpdate','extension':'orderCreate','jqObj':$chkContainer}); + if(_app.u.buyerIsAuthenticated()) { + _app.calls.buyerAddressList.init({'callback':'suppressErrors'},'immutable'); //will check localStorage. + _app.model.addDispatchToQ({'_cmd':'buyerWalletList','_tag': {'datapointer' : 'buyerWalletList','callback':'suppressErrors'}},'immutable'); //always obtain clean copy of wallets. } - if(app.u.buyerIsAuthenticated()) { - app.calls.buyerAddressList.init({'callback':'suppressErrors'},'immutable'); - app.calls.buyerWalletList.init({'callback':'suppressErrors'},'immutable'); - } + _app.ext.order_create.vars[cartID] = _app.ext.order_create.vars[cartID] || {'payment':{}}; - app.ext.orderCreate.u.handlePaypalInit($chkContainer); //handles paypal code, including paymentQ update. should be before any callbacks. - app.ext.cco.calls.appPaymentMethods.init({_cartid:app.vars.cartID},{},'immutable'); - app.ext.cco.calls.appCheckoutDestinations.init({},'immutable'); - - app.model.destroy('cartDetail'); + _app.ext.order_create.u.handlePaypalInit($chkContainer, cartID); //handles paypal code, including paymentQ update. should be before any callbacks. + _app.ext.cco.calls.appPaymentMethods.init({_cartid:cartID},{},'immutable'); + _app.ext.cco.calls.appCheckoutDestinations.init(cartID,{},'immutable'); + _app.model.destroy('cartDetail|'+cartID); - app.calls.cartDetail.init({'callback':function(rd){ + _app.calls.cartDetail.init(cartID,{'callback':function(rd){ $chkContainer.hideLoading(); //always hideloading, errors or no, so interface is still usable. - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $('#globalMessaging').anymessage({'message':rd}); } else { -// app.u.dump(" -> cartDetail callback for startCheckout reached."); - if(app.data.cartDetail['@ITEMS'].length || app.vars.thisSessionIsAdmin) { - app.u.dump(" -> cart has items or this is an admin session."); -//NOTE - this should only be done once. panels should be updated individually from there forward. -// $chkContainer.anycontent({'templateID':'checkoutTemplate',data: app.ext.orderCreate.u.extendedDataForCheckout()}); -// app.u.dump("NOT using anycontent plugin."); - var $checkoutContents = app.renderFunctions.transmogrify({},'checkoutTemplate',app.ext.orderCreate.u.extendedDataForCheckout()); -// app.u.dump("transmogrify saved to var"); +// _app.u.dump(" -> cartDetail callback for startCheckout reached."); + if(_app.data[rd.datapointer]['@ITEMS'].length || _app.u.thisIsAnAdminSession()) { + _app.u.dump(" -> cart has items or this is an admin session. cartID: "+cartID); +// var $checkoutContents = _app.renderFunctions.transmogrify({},'checkoutTemplate',_app.ext.order_create.u.extendedDataForCheckout(cartID)); + var $checkoutContents = new tlc().runTLC({'templateid':'checkoutTemplate','dataset':_app.ext.order_create.u.extendedDataForCheckout(cartID)}) + + $checkoutContents.data('cartid',cartID); + + if($checkoutContents.attr('id')) {} + else { + $checkoutContents.attr('id','ordercreate_'+_app.u.guidGenerator()); //add a random/unique id for use w/ dialogs and callbacks. + } + $chkContainer.append($checkoutContents); - app.u.dump(" -> checkout appended to container."); +_app.u.handleButtons($chkContainer); //will handle buttons outside any of the fieldsets. $("fieldset[data-app-role]",$chkContainer).each(function(index, element) { var $fieldset = $(element), role = $fieldset.data('app-role'); $fieldset.addClass('ui-corner-all'); $("legend",$fieldset).addClass('ui-widget-header ui-corner-all'); - app.ext.orderCreate.u.handlePanel($chkContainer,role,['handleDisplayLogic','handleAppEvents']); + _app.ext.order_create.u.handlePanel($chkContainer,role,['handleDisplayLogic']); }); -// app.u.dump(" -> handlePanel has been run over all fieldsets."); - -if(document.compatMode == 'CSS1Compat') {} -else { - app.u.dump(" -> we are in quirks mode. rerender the panels after a short delay. this is to correct an issue w/ quirks and jquery ui button()",'warn'); - setTimeout(function(){ - app.ext.orderCreate.u.handlePanel($chkContainer,'chkoutCartSummary',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($chkContainer,'chkoutMethodsPay',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($chkContainer,'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($chkContainer,'chkoutAddressBill',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($chkContainer,'chkoutAccountCreate',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($chkContainer,'chkoutPreflight',['empty','translate','handleDisplayLogic','handleAppEvents']); - },1000); - } +// _app.u.dump(" -> handlePanel has been run over all fieldsets."); + if(_app.u.thisNestedExists("zGlobals.globalSettings.inv_mode") && Number(zGlobals.globalSettings.inv_mode) > 1 && !_app.u.thisIsAnAdminSession()) { + _app.u.dump(" -> inventory mode set in such a way that an inventory check will occur."); + _app.ext.cco.calls.cartItemsInventoryVerify.init(cartID,{'callback':'handleInventoryUpdate','extension':'order_create','jqObj':$checkoutContents}); + _app.model.dispatchThis('immutable'); + } + else if(_app.u.thisIsAnAdminSession() && _app.data[rd.datapointer].customer.cid) { + //in the admin interface, the quirksmode bug won't be an issue because it only happens at app init and we're well past that by now. + // context must NOT be $checkoutContainer because that is 'higher' than the data-app-role='checkout' that is used by the panels to ascertain the cart id. + $checkoutContents.showLoading({'message':'Fetching customer record'}); + _app.ext.admin.calls.adminCustomerDetail.init({'CID':_app.data[rd.datapointer].customer.cid,'rewards':1,'notes':1,'orders':1,'organization':1,'wallets':1},{'callback' : 'updateAllPanels','extension':'order_create','jqObj':$checkoutContents},'mutable'); + _app.model.dispatchThis('mutable'); + } + else if(document.compatMode == 'CSS1Compat') {} + else { + _app.u.dump(" -> Quirks mode detected. Re-render the panels after a short delay. this is to correct an issue w/ quirks and jquery ui button()",'warn'); + setTimeout(function(){ + _app.ext.order_create.u.handlePanel($checkoutContents,'chkoutCartSummary',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkoutContents,'chkoutMethodsPay',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkoutContents,'chkoutAddressShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkoutContents,'chkoutAddressBill',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkoutContents,'chkoutAccountCreate',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkoutContents,'chkoutPreflight',['empty','translate','handleDisplayLogic']); + },1000); + } } else { $chkContainer.anymessage({'message':'It appears your cart is empty. If you think you are receiving this message in error, please refresh the page or contact us.'}); } } }},'immutable'); -// app.u.dump(" -> made it past adding calls to Q for startCheckout. now dispatch."); - app.model.dispatchThis('immutable'); +// _app.u.dump(" -> made it past adding calls to Q for startCheckout. now dispatch."); + _app.model.dispatchThis('immutable'); + } + else { + $('#globalMessaging').anymessage({'message':'in order_create.a.startCheckout, no $chkContainer [jQuery instance: '+($chkContainer instanceof jQuery)+'] not passed or does not exist or cartid ['+cartID+'] not passed.','gMessage':true}); + } + }, //startCheckout + + //When this gets run, the datapointer in _rtag will be cartOrderStatus. + checkoutComplete : function(_rtag) { + _app.u.dump('BEGIN order_create.a.checkoutComplete. _rtag: '); dump(_rtag); + $(document.body).hideLoading(); + + //getting here is not a guarantee checkout was successful. Check _rtag for errors. + //could be that a max. # of polls was reached or some other error occured. + if(_app.model.responseHasErrors(_rtag)){ + $('#globalMessaging').anymessage({'message':_rtag}); + } + else { + var $checkout = $(_app.u.jqSelector('#',_rtag.parentID)), + checkoutData = _app.data[_rtag.datapointer] || {}; + + if($checkout instanceof jQuery && $checkout.length) { + var orderID = checkoutData.orderid, + previousCartid = checkoutData.order.cart.cartid; +//show post-checkout invoice and success messaging. + $checkout.empty().show(); + $checkout.tlc({'templateid':'chkoutCompletedTemplate',dataset: checkoutData}); //show invoice + + +//This will add a cart message. handy if the buyer and merchant are dialoging. + if(typeof cartMessagePush === 'function') { + cartMessagePush(previousCartid,'cart.orderCreate',{'vars':{'orderid':orderID,'description':'Order created.'}}); + } +// * 201403 -> duplicate of cartMessagePush above. +//if a cart messenger is open, log the cart update. +// if(_app.u.thisNestedExists('ext.cart_message.vars.carts.'+previousCartid,_app)) { +// _app.model.addDispatchToQ({'_cmd':'cartMessagePush','what':'cart.update','orderid':orderID,'description':'Order created.','_cartid':previousCartid},'immutable'); +// } + + _app.u.handleButtons($checkout); + + if(_app.u.thisIsAnAdminSession() || _app.vars._clientid == '1pc') {} //no need to get a new cart id for an admin session or 1PC. handle any third party display code. + else { + +//cartDetail call in a callback to the appCartCreate call because that cartDetail call needs a cart id +// passed to it in order to know which cart to fetch (no longer connected to the session!). This resulted in a bug that multiple +// orders placed from the same computer in multiple sessions could have the same cart id attached. Very bad. + _app.calls.appCartCreate.init({ + "datapointer" : "appCartCreate", + "callback" : function(rd){ +// dump(" -----------> rd: "); dump(rd); + if(_app.model.responseHasErrors(rd)){ + _app.u.throwMessage(rd); + } + else if(_app.data[rd.datapointer] && _app.data[rd.datapointer]._cartid) { + _app.calls.cartDetail.init(_app.data[rd.datapointer]._cartid,{},'immutable'); + _app.model.dispatchThis('immutable'); + } + else { + //something went wrong. no cart id in the appcartcreate. + } + } + }); //!IMPORTANT! after the order is created, a new cart needs to be created and used. the old cart id is no longer valid. + + } //ends the not admin/1pc if. + + window[_app.vars.analyticsPointer]('send','event','Checkout','App Event','Order created'); + window[_app.vars.analyticsPointer]('send','event','Checkout','User Event','Order created ('+orderID+')'); + + + if(_app.ext.order_create.checkoutCompletes) { + var L = _app.ext.order_create.checkoutCompletes.length; + for(var i = 0; i < L; i += 1) { + _app.ext.order_create.checkoutCompletes[i]({'cartID':previousCartid,'orderID':orderID,'datapointer':_rtag.datapointer},$checkout); + } + } +//This will handle the @trackers code. Doesn't get run in admin. + if(!_app.u.thisIsAnAdminSession()) { + _app.ext.order_create.u.scripts2iframe(checkoutData['@TRACKERS']); + } +// ### TODO -> move this out of here. move it into the appropriate app init. + if(_app.vars._clientid == '1pc') { + //GTS for apps is handled in google extension +// * 201405 -> IE8 didn't like this delete. changed how the check occurs and the delete itself. + if('GoogleTrustedStore' in window) { + try { + delete GoogleTrustedStore; //delete existing object or gts conversion won't load right. + //running this will reload the script. the 'span' will be added as part of html:roi + //if this isn't run in the time-out, the 'span' w/ order totals won't be added to DOM and this won't track as a conversion. + (function() { + var scheme = (("https:" == document.location.protocol) ? "https://" : "http://"); + var gts = document.createElement("script"); + gts.type = "text/javascript"; + gts.async = true; + gts.src = scheme + "www.googlecommerce.com/trustedstores/gtmp_compiled.js"; + var s = document.getElementsByTagName("script")[0]; + s.parentNode.insertBefore(gts, s); + })(); + } + catch(e) { + dump("Was unable to delete GoogleTrustedStore from window. conversion may not track properly. error: ",'warn'); dump(e); + } + + } + } + else if(_app.u.thisIsAnAdminSession()) { + //no special handling here. + } + else { + //this is an 'app'. +// _app.u.dump("Not 1PC."); +// _app.u.dump(" -> [data-app-role='paymentMessaging'],$checkout).length: "+("[data-app-role='paymentMessaging']",$checkout).length); + + //MUST destroy the cart. it has data-cartid set that would point to the wrong cart. + $('#modalCart').empty().remove(); + $('#mainContentArea_cart').empty().remove(); + + //the code below is to disable any links in the payment messaging for apps. there may be some legacy links depending on the message. + $("[data-app-role='paymentMessaging'] a",$checkout).on('click',function(event){ + event.preventDefault(); + }); + $("[data-app-role='paymentMessaging']",$checkout).on('click',function(event){ + event.preventDefault(); + //cart and order id are in uriParams to keep data locations in sync in showCustomer. uriParams is where they are when landing on this page directly. + showContent('customer',{'show':'invoice','uriParams':{'cartid':previousCartid,'orderid':orderID}}); + }); + + } + //outside the if/else above so that cartMessagesPush and cartCreate can share the same pipe. + _app.model.dispatchThis('immutable'); //these are auto-dispatched because they're essential. + } + else { + //something went wrong. $checkout is not a valid jquery instance or has no length. + $('#globalMessaging').anymessage({'message':'Your order ('+checkoutData.orderid+') was created, but something went amiss along the way and the invoice can not be displayed. Please go to my account and order history to view your invoice. A copy was also mailed to you.','persistent':true}); + } + + } + } + + + }, //a +//////////////////////////////////// appEvents [e] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + e : { + adminCustomerLookup : function($ele,p) { + p.preventDefault(); + var + $context = $ele.closest("[data-app-role='checkout']"), + email = $ele.closest('fieldset').find("[name='bill/email']").val(), //save to var before handleing panel or val is gone. + cartid = $context.data('cartid'); + if(email) { + _app.ext.admin_customer.a.customerSearch({'searchfor':email,'scope':'EMAIL'},function(customer){ + _app.ext.order_create.u.handlePanel($context,'chkoutPreflight',['empty','showLoading']); + _app.ext.order_create.u.handlePanel($context,'chkoutAddressBill',['empty','showLoading']); + _app.ext.order_create.u.handlePanel($context,'chkoutAddressShip',['empty','showLoading']); + + _app.ext.cco.calls.cartSet.init({'_cartid':cartid,'bill/email':customer.EMAIL}); + _app.model.addDispatchToQ({ + '_cmd':'adminCartMacro', + '_cartid' : cartid, + '_tag' : { + 'callback' : 'showMessaging', + 'jqObj' : $('#globalMessaging'), + 'message' : 'Customer '+customer.EMAIL+' assigned to this cart' + }, + "@updates" : ["LINK-CUSTOMER-ID?CID="+customer.CID] + },'immutable'); + _app.model.destroy('cartDetail|'+cartid); + _app.model.destroy('appPaymentMethods|'+cartid); +//get a clean copy of the customer record for 2 reason. 1 to make sure it's up to date. 2 because cartDetail just got nuked from memory so callback on customerDetail would load a blank cart. + _app.model.destroy('adminCustomerDetail|'+customer.CID); + _app.calls.cartDetail.init(cartid,{},'immutable'); + _app.ext.cco.calls.appPaymentMethods.init({_cartid:cartid},{},'immutable'); //update pay and ship anytime either address changes. + _app.ext.admin.calls.adminCustomerDetail.init({'CID':customer.CID,'rewards':1,'notes':1,'orders':1,'organization':1,'wallets':1},{'callback' : 'updateAllPanels','extension':'order_create','jqObj':$context},'immutable'); + _app.model.dispatchThis('immutable'); + }); } else { - $('#globalMessaging').anymessage({'message':'in orderCreate.a.startCheckout, no $chkContainer not passed or does not exist.'}); + _app.u.validateForm($ele.closest('fieldset')); //this will handle the error display. } - } //startCheckout + return false; + }, - }, + adminAddressCreateUpdateShow : function($ele,p) { + p.preventDefault(); + var + $checkout = $ele.closest("[data-app-role='checkout']"), + addressType = $ele.closest("[data-app-addresstype]").attr('data-app-addresstype'), + CID = _app.data['cartDetail|'+$checkout.data('cartid')].customer.cid, + vars = { + 'mode' : $ele.data('mode'), //will b create or update. + 'show' : 'dialog', + 'TYPE' : addressType, + 'CID' : CID, + 'editorID' : $checkout.attr('id') + }; + + + _app.ext.admin_customer.a.addressCreateUpdateShow(vars,function(v,addrObj){ + + _app.ext.order_create.u.handlePanel($checkout,'chkoutPreflight',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkout,'chkoutAddressBill',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkout,'chkoutAddressShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkout,'chkoutMethodsShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkout,'chkoutMethodsPay',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkout,'chkoutCartItemsList',['empty','translate','handleDisplayLogic']); + if($ele.data('mode') == 'update') { + //can't use $ele to trigger the click on the address select after updating the panels, because $ele is no longer on the dom, so $checkout, which is a constant, is used to find the address/button + $("fieldset[data-app-addresstype='"+addressType+"']",$checkout).find("address[data-_id='"+addrObj.SHORTCUT+"'] button[data-app-role='addressSelectButton']").trigger('click'); + } + },_app.ext.cco.u.getAndRegularizeAddrObjByID(_app.data['adminCustomerDetail|'+CID]['@'+vars.TYPE.toUpperCase()],$ele.closest("[data-_id]").data('_id'),vars.TYPE,false)); + return false; + }, + adminCartRemoveFromSession : function($ele,p) { + p.preventDefault(); + _app.model.removeCartFromSession($ele.closest("[data-app-role='checkout']").data('cartid')); + navigateTo("#!tab/orders"); + return false; + }, + adminOrderDetailShow : function($ele,p) { + p.preventDefault(); + var orderID = $ele.closest("[data-orderid]").data('orderid'); + if(orderID) { + var $orderContent = $("[data-app-role='orderContents']:first",$ele.closest("[data-app-role='orderContainer']")).show(); + _app.ext.admin.calls.adminOrderDetail.init(orderID,{ + 'callback' : 'tlc', + 'jqObj' : $orderContent, + 'verb' : 'translate' + },'mutable'); + _app.model.dispatchThis('mutable'); + } + else { + $('#globalMessaging').anymessage({"message":"In order_create.e.adminOrderDetailShow, unable to ascertain orderid.","gMessage":true}); + } + return false; + }, -//////////////////////////////////// appEvents [e] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + buyerLogout : function($ele,p) { + p.preventDefault; +// _app.u.dump(" BEGIN order_create.e.buyerLogout"); +// _app.u.dump(" -> order_create.e.buyerLogout (Click!)"); + _app.calls.buyerLogout.init({'callback':function(rt){ + _app.ext.order_create.u.handlePanel($ele.closest('form'),'chkoutPreflight',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($ele.closest('form'),'chkoutAddressBill',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($ele.closest('form'),'chkoutAddressShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handleCommonPanels($ele.closest('form')); + _app.model.dispatchThis('immutable'); + }}); + _app.model.dispatchThis('immutable'); + $('body').removeClass('buyerLoggedIn'); //allows for css changes to occur based on authentication + return false; + }, - e : { + cartItemAppendSKU : function($ele,p) { + p.preventDefault(); + p.skuArr = [$ele.closest("[data-sku]").data('sku')]; + this.cartItemAppendAllSKUsFromOrder($ele,p); + return false; + }, - adminCustomerLookup : function($ele) { - $ele.button(); - $ele.off('click.adminCustomerLookup').on('click.adminCustomerLookup',function(){ + //SKU/STID required (fully qualified, w/ variations et all); + cartItemAppendAllSKUsFromOrder : function($ele,p) { + p.preventDefault(); + var $container = $ele.closest("[data-app-role='orderContainer']"), orderID = $container.data('orderid'); + if(orderID) { + var $checkout = $ele.closest("[data-app-role='checkout']"), cartID = $checkout.data('cartid'); + _app.ext.cco.u.appendOrderItems2Cart({'orderid':orderID,'cartid':cartID},function(rd){ +//run an inventory check. However, do NOT auto-adjust. Merchants should be allowed to over-order if desired. +//throw a fatty warning tho to make sure it isn't missed. + _app.ext.cco.calls.cartItemsInventoryVerify.init(cartID,{'callback':'adminInventoryDiscrepencyDisplay','extension':'cco','jqObj':$container}); + _app.ext.order_create.u.handleCommonPanels($checkout); + _app.model.dispatchThis('immutable'); + + },p.skuArr || []); + } + else { + + } + return false; + }, + //updates line item in cart. This event can be fired on an element (input, button, etc) within the scope of the line item template. + cartItemUpdateExec : function($ele,p){ + p.preventDefault(); var - $context = $ele.closest("[data-app-role='checkout']"), - email = $ele.closest('fieldset').find("[name='bill/email']").val(); //save to var before handleing panel or val is gone. + $container = $ele.closest('[data-stid]'), + cartid = $ele.closest(":data(cartid)").data('cartid'), + vars = { + stid : $container.data('stid'), + uuid : $container.attr('data-uuid'), + qty : $("input[name='qty']",$container).val(), //admin wants qty. + quantity : $("input[name='qty']",$container).val() //cartItemUpdate wants quantity + } - app.ext.orderCreate.u.handlePanel($context,'chkoutPreflight',['empty','showLoading']); - app.ext.orderCreate.u.handlePanel($context,'chkoutAddressBill',['empty','showLoading']); - app.ext.orderCreate.u.handlePanel($context,'chkoutAddressShip',['empty','showLoading']); + if($("input[name='price']",$container).val() && _app.u.thisIsAnAdminSession()) { + vars.price = $("input[name='price']",$container).val(); + } - app.ext.admin.calls.adminCustomerSearch.init({'scope':'EMAIL','searchfor':email},{'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ - $('#globalMessaging').anymessage({'message':rd}); - } - else { - if(app.data[rd.datapointer] && app.data[rd.datapointer].CID) { - //Match FOund. - app.calls.cartSet.init({"customer/cid":app.data[rd.datapointer].CID}); - app.data.cartDetail.customer.cid = app.data[rd.datapointer].CID; //updatate local copy of cart. - app.ext.admin.calls.adminCustomerDetail.init({'CID':app.data[rd.datapointer].CID},{'callback' : 'adminCustomerDetail','extension':'orderCreate','jqObj':$context},'immutable'); - app.model.dispatchThis('immutable'); - } - else { - $('#globalMessaging').anymessage({'message':'No matching customer record found.'}); - } - } - }},'mutable'); - app.model.dispatchThis('mutable'); - }); - }, + if(_app.ext.cco.u.cartItemUpdate(cartid,vars,{'callback' : 'updateAllPanels','extension':'order_create','jqObj':$ele.closest('form')})) { + _app.model.destroy('cartDetail|'+cartid); + _app.calls.cartDetail.init(cartid,{},'immutable'); + _app.model.dispatchThis('immutable'); + } + else { + //cartItemUpdate will handle error display. + } + return false; + }, //cartItemUpdateExec - buyerLogout : function($ele) { -// app.u.dump(" BEGIN orderCreate.e.buyerLogout"); - $ele.off('click.buyerLogout').on('click.buyerLogout',function(event){ -// app.u.dump(" -> orderCreate.e.buyerLogout (Click!)"); - app.calls.buyerLogout.init({'callback':function(rt){ - app.ext.orderCreate.u.handlePanel($ele.closest('form'),'chkoutPreflight',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($ele.closest('form'),'chkoutAddressBill',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($ele.closest('form'),'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handleCommonPanels($ele.closest('form')); - app.model.dispatchThis('immutable'); - }}); - app.model.dispatchThis('immutable'); - }); - }, + cartShippingSave : function($ele,p) { + p.preventDefault(); + var + $container = $ele.closest("[data-app-role='customShipMethodContainer']"), + cartid = $ele.closest(":data(cartid)").data('cartid'), + sfo = $container.serializeJSON(); + $('.ui-state.error',$container).removeClass('ui-state-error'); //remove any previous errors. + if(sfo['sum/shp_carrier'] && sfo['sum/shp_method'] && sfo['sum/shp_total']) { + _app.model.addDispatchToQ({ + '_cmd':'adminCartMacro', + '_cartid' : cartid, + '_tag' : {}, + "@updates" : ["SETSHIPPING?"+_app.u.hash2kvp(sfo)] + },'immutable'); + _app.ext.order_create.u.handleCommonPanels($ele.closest('form')); + _app.model.dispatchThis('immutable'); + } + else { + //handle errors. + if($("[name='sum/shp_carrier']",$container).val()) {} + else {$("[name='sum/shp_carrier']",$container).addClass('ui-state-error')} - cartItemAddFromForm : function($btn) { - $btn.button(); - $btn.off('click.cartItemAdd').on('click.cartItemAdd',function(event){ - event.preventDefault(); - app.u.dump("BEGIN orderCreate.e.cartItemAddFromForm (Click!)"); - app.ext.store_product.u.handleAddToCart($btn.closest('form')); - app.model.destroy('cartDetail'); - app.calls.cartDetail.init({ + if($("[name='sum/shp_method']",$container).val()) {} + else {$("[name='sum/shp_method']",$container).addClass('ui-state-error')} + + if($("[name='sum/shp_total']",$container).val()) {} + else {$("[name='sum/shp_total']",$container).addClass('ui-state-error')} + } + return false; + }, //orderSummarySave + + + cartItemAddFromForm : function($ele,p) { + p.preventDefault(); + var $chkoutForm = $ele.closest("[data-add2cart-role='container']"), $checkout = $ele.closest("[data-app-role='checkout']"); + _app.ext.store_product.u.handleAddToCart($chkoutForm,{'callback': function(){ + _app.model.destroy('cartDetail|'+$checkout.data('cartid')); + _app.model.destroy('appPaymentMethods|'+$checkout.data('cartid')); + _app.ext.cco.calls.appPaymentMethods.init({_cartid:$checkout.data('cartid')},{},'immutable'); + _app.calls.cartDetail.init($checkout.data('cartid'),{ 'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ - $btn.closest('fieldset').anymessage({'message':rd}); + if(_app.model.responseHasErrors(rd)){ + $ele.closest('fieldset').anymessage({'message':rd}); } else { - app.ext.orderCreate.u.handlePanel($btn.closest('form'),'chkoutCartItemsList',['empty','translate','handleDisplayLogic','handleAppEvents']); //for toggling display of ref. # field. - app.ext.orderCreate.u.handlePanel($btn.closest('form'),'chkoutCartSummary',['empty','translate','handleDisplayLogic','handleAppEvents']); //for toggling display of ref. # field. + _app.ext.order_create.u.handlePanel($checkout,'chkoutCartItemsList',['empty','translate','handleDisplayLogic']); //for toggling display of ref. # field. + _app.ext.order_create.u.handlePanel($checkout,'chkoutCartSummary',['empty','translate','handleDisplayLogic']); //for toggling display of ref. # field. + _app.ext.order_create.u.handlePanel($checkout,'chkoutMethodsShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkout,'chkoutMethodsPay',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($checkout,'chkoutCartSummary',['empty','translate','handleDisplayLogic']); } } },'immutable'); //update cart so that if successful, the refresh on preflight panel has updated info. - app.model.dispatchThis('immutable'); - }); + _app.model.dispatchThis('immutable'); + }}); + return false; }, //cartItemAddFromForm - cartItemAddWithChooser : function($btn) { - - $btn.button(); - $btn.off('click.cartItemAddWithChooser').on('click.cartItemAddWithChooser',function(event){ + cartItemAddWithChooser : function($ele,p) { + p.preventDefault(); +//$button is passed into the showFinder function. This is the button that appears IN the chooser/finder for adding to the cart/order. + var $chkoutForm = $ele.closest('form'), $checkout = $ele.closest("[data-app-role='checkout']") + var $button = $("<button>").text("Add to Cart").button().on('click',function(event){ event.preventDefault(); -app.u.dump("BEGIN orderCreate.e.cartItemAddWithChooser (Click!)"); -//$button is passed into the showFinder function. This is the button that appears IN the chooser/finder for adding to the cart/order. - var $button = $("<button>").text("Add to Order").button().on('click',function(event){ - event.preventDefault(); - $(this).button('disable'); //prevent doubleclick. - $form = $('form','#chooserResultContainer'); - if($form && $form.length) { - var sfo = $form.serializeJSON(); //Serialized Form Object. - var pid = sfo.sku; //shortcut - sfo.product_id = pid; // - if(app.ext.store_product.validate.addToCart(pid,$form)) { - app.ext.store_product.u.handleAddToCart($form); - app.model.destroy('cartDetail'); - app.calls.cartDetail.init({ + $(this).button('disable'); //prevent doubleclick. + var $form = $('form','#chooserResultContainer'); + if($form && $form.length) { +// _app.u.dump(" -> found form"); + $form.append("<input type='hidden' name='_cartid' value='"+$checkout.data('cartid')+"' \/>"); + var sfo = $form.serializeJSON(); //Serialized Form Object. + var pid = sfo.sku; //shortcut + sfo.product_id = pid; // +// _app.u.dump(" -> sfo: "); _app.u.dump(sfo); + if(_app.ext.store_product.validate.addToCart(pid,$form)) { + _app.u.dump(" -> passed validation"); + _app.ext.store_product.u.handleAddToCart($form,{'callback' : function(){ + + _app.model.destroy('cartDetail|'+$checkout.data('cartid')); + _app.model.destroy('appPaymentMethods|'+$checkout.data('cartid')); + _app.ext.cco.calls.appPaymentMethods.init({_cartid:$checkout.data('cartid')},{},'immutable'); + _app.calls.cartDetail.init($checkout.data('cartid'),{ 'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $('#prodFinder').anymessage({'message':rd}); } else { $('#prodFinder').dialog('close'); - app.ext.orderCreate.u.handlePanel($btn.closest('form'),'chkoutCartItemsList',['empty','translate','handleDisplayLogic','handleAppEvents']); //for toggling display of ref. # field. - app.ext.orderCreate.u.handlePanel($btn.closest('form'),'chkoutCartSummary',['empty','translate','handleDisplayLogic','handleAppEvents']); //for toggling display of ref. # field. + // dump(" ----> $chkoutForm.length: "+$chkoutForm.length); + _app.ext.order_create.u.handlePanel($chkoutForm,'chkoutCartItemsList',['empty','translate','handleDisplayLogic']); //for toggling display of ref. # field. + _app.ext.order_create.u.handlePanel($chkoutForm,'chkoutCartSummary',['empty','translate','handleDisplayLogic']); //for toggling display of ref. # field. + _app.ext.order_create.u.handlePanel($chkoutForm,'chkoutMethodsShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($chkoutForm,'chkoutMethodsPay',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($chkoutForm,'chkoutCartSummary',['empty','translate','handleDisplayLogic']); } } },'immutable'); //update cart so that if successful, the refresh on preflight panel has updated info. - app.model.dispatchThis('immutable'); - } - else { - $(this).button('enable'); //prevent doubleclick. - } + //an issue w/ the API maybe? the cartDetail is coming back w/out the updated items list. ### FUTURE -> address this. + setTimeout(function(){ + _app.model.dispatchThis('immutable'); + },500); + }}); + } else { - app.u.throwGMessage("WARNING! add to cart $form has no length. can not add to cart."); - $(this).button('enable'); + _app.u.dump("Chooser add to cart did not pass validation",'warn'); + $(this).button('enable'); //prevent doubleclick. } - }); - app.ext.admin.a.showFinderInModal('CHOOSER','','',{'$buttons' : $button}) + } + else { + $('#productFinderContents').anymessage({"message":"In order_create.e.cartItemAddWithChooser, #chooserResultContainer had no length.","gMessage":true}); + $(this).button('enable'); + } }); + _app.ext.admin.a.showFinderInModal('CHOOSER','','',{'$buttons' : $button}); + return false; }, -//applied to inputs like coupon and giftcard so that when 'enter' is pushed, it triggers a click on the corresponding button. - addTriggerButtonClick : function($input) { - $input.off('keypress.addTriggerButtonClick').on('keypress.addTriggerButtonClick',function(event){ - if(event.keyCode==13){$input.parent().find('button').first().trigger('click')} - }) - }, //addTriggerButtonClick - //ele is likely a div or section. the element around all the inputs. - addTriggerPayMethodUpdate : function($ele) { + addTriggerPayMethodUpdate : function($ele,p) { + p.preventDefault(); var $fieldset = $ele.closest('fieldset'); $("input[type='radio']",$ele).each(function(){ var $input = $(this); - $input.off("change.addTriggerPayMethodUpdate").on("change.addTriggerPayMethodUpdate", function(){ - app.ext.cco.calls.cartSet.init({'want/payby':$input.val()}); - app.model.dispatchThis('immutable'); //any reason to obtain a new cart object here? don't think so. - app.ext.orderCreate.u.showSupplementalInputs($input); - app.ext.orderCreate.u.handlePanel($input.closest('form'),'chkoutCartSummary',['empty','translate','handleDisplayLogic','handleAppEvents']); //for toggling display of ref. # field. + _app.ext.cco.calls.cartSet.init({'_cartid':$ele.closest("[data-app-role='checkout']").data('cartid'),'want/payby':$input.val()}); + _app.model.dispatchThis('immutable'); //any reason to obtain a new cart object here? don't think so. + _app.ext.order_create.u.showSupplementalInputs($input); + _app.ext.order_create.u.handlePanel($input.closest('form'),'chkoutCartSummary',['empty','translate','handleDisplayLogic']); //for toggling display of ref. # field. }); - }) + }); + return false; }, //addTriggerPayMethodUpdate - - addTriggerShipMethodUpdate : function($ul) { - $("input",$ul).each(function(){ - - var $rb = $(this), //Radio Button - shipID = $(this).val(); - - $rb.off("change.addTriggerShipMethodUpdate").on("change.addTriggerShipMethodUpdate", function(){ - app.calls.cartSet.init({'want/shipping_id':shipID}); - //destroys cart and updates big three panels (shipping, payment and summary) - app.ext.orderCreate.u.handleCommonPanels($ul.closest('form')); - app.model.dispatchThis("immutable"); - }); - }) - }, //addTriggerShipMethodUpdate + + shipOrPayMethodSelectExec : function($ele,p) { + p.preventDefault(); + var obj = {}; + obj[$ele.attr('name')] = $ele.val(); + if($ele.data('updatemode') == 'cart') { + obj._cartid = $ele.closest("[data-template-role='cart']").data('cartid'); + } + else {} + obj._cartid = $ele.closest("[data-app-role='checkout']").data('cartid'); + _app.ext.cco.calls.cartSet.init(obj); +//destroys cart and updates big three panels (shipping, payment and summary) + _app.ext.order_create.u.handleCommonPanels($ele.closest('form')); + _app.model.dispatchThis("immutable"); + return false; + }, + //triggered on specific address inputs. When an address is updated, several things could be impacted, including tax, shipping options and payment methods. - execAddressUpdate : function($input) { - $input.off('change.execAddressUpdate').on('change.execAddressUpdate',function(){ - var obj = {}; - obj[$input.attr('name')] = $input.val(); - //if bill/ship are the same, duplicate data in both places OR shipping methods won't update. - if($input.closest('form').find("input[name='want/bill_to_ship']").is(':checked') && $input.attr('name').indexOf('bill/') >= 0) { - obj[$input.attr('name').replace('bill/','ship/')] = $input.val(); - } - app.calls.cartSet.init(obj); //update the cart - app.ext.orderCreate.u.handleCommonPanels($input.closest('form')); - app.model.dispatchThis('immutable'); - - }) + execAddressUpdate : function($ele,p) { + p.preventDefault(); + var obj = {}; + obj[$ele.attr('name')] = $ele.val(); + //if bill/ship are the same, duplicate data in both places OR shipping methods won't update. + if($ele.closest('form').find("input[name='want/bill_to_ship']").is(':checked') && $ele.attr('name').indexOf('bill/') >= 0) { + obj[$ele.attr('name').replace('bill/','ship/')] = $ele.val(); + } + obj._cartid = $ele.closest("[data-app-role='checkout']").data('cartid'); + _app.ext.cco.calls.cartSet.init(obj); //update the cart + _app.ext.order_create.u.handleCommonPanels($ele.closest('form')); + _app.model.dispatchThis('immutable'); + return false }, //execAddressUpdate //executed when an predefined address (from a buyer who is logged in) is selected. - execBuyerAddressSelect : function($btn) { - $btn.button(); - $btn.off('click.execBuyerAddressUpdate').on('click.execBuyerAddressUpdate',function(event){ - event.preventDefault(); - var addressType = $btn.closest('fieldset').data('app-addresstype'), //will be ship or bill. - $form = $btn.closest('form'), - addressID = $btn.closest('address').data('_id'); -//** 201342 -> update to better handle an incomplete address. edit dialog will open automatically and prompt for invalid fields. The intent to select the address will also update the cart. - if(addressType && addressID) { - //even if the address doesn't pass validation, set the shortcut to this id. checkout won't let them proceed, but this way their intent is still saved. - //and after the update occurs, this address will be selected. - $("[name='"+addressType+"/shortcut']",$form).val(addressID); - var cartUpdate = {}; - cartUpdate[addressType+"/shortcut"] = addressID; - - if(app.ext.cco.u.verifyAddressIsComplete(addressType,addressID)) { - - - if(addressType == 'bill' && $btn.closest('form').find("input[name='want/bill_to_ship']").is(':checked')) { - // app.u.dump("Ship to billing address checked. set fields in billing."); + execBuyerAddressSelect : function($ele,p) { + p.preventDefault(); + var + addressType = $ele.closest('fieldset').data('app-addresstype'), //will be ship or bill. + $form = $ele.closest('form'), + addressID = $ele.closest('address').data('_id'), + $checkout = $ele.closest("[data-app-role='checkout']"); + + +// For an incomplete address, the edit dialog will open automatically and prompt for invalid fields. The intent to select the address will also update the cart. +// ### FUTURE -> this could be optimized. some vars declared at the top and lookups still occur later. + if(addressType && addressID) { + $ele.closest('fieldset').find('.ui-button.ui-state-highlight').removeClass('ui-state-highlight'); + $ele.addClass('ui-state-highlight'); + //even if the address doesn't pass validation, set the shortcut to this id. checkout won't let them proceed, but this way their intent is still saved. + //and after the update occurs, this address will be selected. + $("[name='"+addressType+"/shortcut']",$form).val(addressID); + var cartUpdate = {}; + cartUpdate[addressType+"/shortcut"] = addressID; + cartUpdate._cartid = $ele.closest("[data-app-role='checkout']").data('cartid'); + + var addrObj = _app.u.thisIsAnAdminSession() ? _app.ext.cco.u.getAndRegularizeAddrObjByID(_app.data['adminCustomerDetail|'+_app.data['cartDetail|'+$checkout.data('cartid')].customer.cid]['@'+addressType.toUpperCase()],addressID,addressType,true) : _app.ext.cco.u.getAddrObjByID(addressType,addressID); //will return address object. + + if(_app.ext.cco.u.verifyAddressIsComplete(addrObj,addressType)) { + + if(addressType == 'bill' && $ele.closest('form').find("input[name='want/bill_to_ship']").is(':checked')) { +// _app.u.dump("Ship to billing address checked. set fields in billing."); //copy the address into the shipping fields so shipping rates update. - var addrObj = app.ext.cco.u.getAddrObjByID(addressType,addressID); //will return address object. - if(!$.isEmptyObject(addrObj)) { - for(var index in addrObj) { - cartUpdate[index.replace('bill/','ship/')] = addrObj[index]; - } + if(!$.isEmptyObject(addrObj)) { + for(var index in addrObj) { +//At the time this is being written, buyer calls return the address with bill/ and admin calls return bill_. convenient. + cartUpdate[index.replace('bill/','ship/')] = addrObj[index]; } } - - - app.calls.cartSet.init(cartUpdate,{'callback':function(){ - app.ext.orderCreate.u.handlePanel($form,(addressType == 'bill') ? 'chkoutAddressBill' : 'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents']); - }}); //no need to populate address fields, shortcut handles that. - app.ext.orderCreate.u.handleCommonPanels($form); - app.model.dispatchThis('immutable'); - } - else { - app.calls.cartSet.init(cartUpdate,{},'passive'); - app.model.dispatchThis('passive'); - $btn.closest('fieldset').find("[data-app-event='orderCreate|showBuyerAddressUpdate']").data('validate-form',true).trigger('click'); } +//there was a callback on this, but no clear reason why it was necessary. removed for now (will test prior to deleting this code) +// _app.ext.cco.calls.cartSet.init(cartUpdate,{'callback':function(){ +// _app.ext.order_create.u.handlePanel($form,(addressType == 'bill') ? 'chkoutAddressBill' : 'chkoutAddressShip',['empty','translate','handleDisplayLogic']); +// }}); //no need to populate address fields, shortcut handles that. + _app.ext.cco.calls.cartSet.init(cartUpdate) + _app.ext.order_create.u.handleCommonPanels($form); + _app.model.dispatchThis('immutable'); } else { - $btn.closest('fieldset').anymessage({'message':'In orderCreate.e.execBuyerAddressSelect, either addressType ['+addressType+'] and/or addressID ['+addressID+'] not set. Both are required.','gMessage':true}); + _app.ext.cco.calls.cartSet.init(cartUpdate,{},'passive'); + _app.model.dispatchThis('passive'); + $ele.closest('address').find("[data-app-role='addressEditButton']").data('validate-form',true).trigger('click'); } - }); + } + else { + $ele.closest('fieldset').anymessage({'message':'In order_create.e.execBuyerAddressSelect, either addressType ['+addressType+'] and/or addressID ['+addressID+'] not set. Both are required.','gMessage':true}); + } + return false; }, //execBuyerAddressSelect //immediately update cart anytime the email address is added/changed. for remarketing purposes. //no need to refresh the cartDetail here. - execBuyerEmailUpdate : function($input) { - $input.off('blur.execEmailUpdate').on('blur.execEmailUpdate',function(){ - if(app.u.isValidEmail($input.val())) { - app.ext.cco.calls.cartSet.init({'bill/email':$input.val()},{},'immutable'); - app.model.dispatchThis('immutable'); - } - }); - }, //execBuyerEmailUpdate - - execBuyerLogin : function($btn) { - $btn.button(); - $btn.off('click.execBuyerLogin').on('click.execBuyerLogin',function(event){ - event.preventDefault(); - var $fieldset = $btn.closest('fieldset'), - $email = $("[name='bill/email']",$fieldset), - $password = $("[name='password']",$fieldset); - - if($email.val() && $password.val()) { - $('body').showLoading({'message':'Verifying username and password...'}); - //we have want we need. attempt login. - app.model.destroy('buyerAddressList'); - app.model.destroy('buyerWalletList'); - app.model.destroy('cartDetail'); + execBuyerEmailUpdate : function($ele,p) { + p.preventDefault(); + if(_app.u.isValidEmail($ele.val())) { + _app.ext.cco.calls.cartSet.init({'_cartid':$ele.closest("[data-app-role='checkout']").data('cartid'),'bill/email':$ele.val()},{},'immutable'); + _app.model.dispatchThis('immutable'); + } + return false; + }, //execBuyerEmailUpdate - app.calls.appBuyerLogin.init({"login":$email.val(),"password":$password.val()},{'callback':function(rd){ -// app.u.dump("BEGIN exeBuyerLogin anonymous callback"); - $('body').hideLoading(); - if(app.model.responseHasErrors(rd)){$fieldset.anymessage({'message':rd})} - else { - app.u.dump(" -> no errors. user is logged in."); - var $form = $fieldset.closest('form'), - $fieldsets = $('fieldset',$form); + execBuyerLogin : function($ele,p) { + p.preventDefault(); + var $fieldset = $ele.closest('fieldset'), + $email = $("[name='bill/email']",$fieldset), + $password = $("[name='password']",$fieldset), + $checkout = $ele.closest("[data-app-role='checkout']"); + + if($email.val() && $password.val()) { + $('body').showLoading({'message':'Verifying username and password...'}); + //we have want we need. attempt login. + + _app.model.destroy('buyerAddressList'); + _app.model.destroy('buyerWalletList'); + _app.model.destroy('cartDetail|'+$checkout.data('cartid')); + + _app.ext.cco.calls.cartSet.init({"bill/email":$email.val(),"_cartid":$checkout.data('cartid')}) //whether the login succeeds or not, set bill/email in the cart. + _app.model.addDispatchToQ({"_cmd":"appBuyerLogin","login":$email.val(),"password":$password.val(),'method':'unsecure',"_tag":{"datapointer":"appBuyerLogin","callback":function(rd){ + $('body').hideLoading(); + if(_app.model.responseHasErrors(rd)){$fieldset.anymessage({'message':rd})} + else { + _app.u.dump(" -> no errors. user is logged in."); + $('body').addClass('buyerLoggedIn'); //allows for css changes based on auth. + var $form = $fieldset.closest('form'), + $fieldsets = $('fieldset',$form); //set all panels to loading. - $fieldsets.each(function(){ - app.ext.orderCreate.u.handlePanel($form,$(this).data('app-role'),['showLoading']); - }); + $fieldsets.each(function(){ + _app.ext.order_create.u.handlePanel($form,$(this).data('app-role'),['showLoading']); + }); //can't piggyback these on login because they'll error at the API side (and will kill the login request) - app.calls.buyerAddressList.init({'callback':function(){ + _app.calls.buyerAddressList.init({'callback':function(){ //no error handling needed. if call fails or returns zero addesses, the panels still need to be rendered. //re-render all panels. each could be affected by a login (either just on the display side or new/updated info for discounts, addresses, giftcards, etc) - $fieldsets.each(function(){ - app.ext.orderCreate.u.handlePanel($form,$(this).data('app-role'),['empty','translate','handleDisplayLogic','handleAppEvents']); - }); - }},'immutable'); - - app.calls.buyerWalletList.init({},'immutable'); - app.model.dispatchThis('immutable'); - $fieldset.anymessage({'message':'Thank you, you are now logged in.','_msg_0_type':'success'}); - } - }}); - app.calls.cartDetail.init({},'immutable'); //update cart so that if successful, the refresh on preflight panel has updated info. - app.model.dispatchThis('immutable'); - } - else { - $fieldset.anymessage({'message':'Please fill out the fields indicated below:'}); - if(!app.u.isValidEmail($email.val())) { - //email is blank or invalid - $email.addClass('ui-state-error'); - } - if(!$password.val()) { - $password.addClass('ui-state-error'); - } + $fieldsets.each(function(){ + _app.ext.order_create.u.handlePanel($form,$(this).data('app-role'),['empty','translate','handleDisplayLogic']); + }); + }},'immutable'); + + _app.model.addDispatchToQ({'_cmd':'buyerWalletList','_tag': {'datapointer' : 'buyerWalletList','callback':''}},'immutable'); + _app.model.dispatchThis('immutable'); + $fieldset.anymessage({'message':'Thank you, you are now logged in.','_msg_0_type':'success'}); + } + }}},"immutable"); + _app.calls.cartDetail.init($checkout.data('cartid'),{},'immutable'); //update cart so that if successful, the refresh on preflight panel has updated info. + _app.model.dispatchThis('immutable'); + } + else { + $fieldset.anymessage({'message':'Please fill out the fields indicated below:'}); + if(!_app.u.isValidEmail($email.val())) { + //email is blank or invalid + $email.addClass('ui-state-error'); } - }) + if(!$password.val()) { + $password.addClass('ui-state-error'); + } + } + return false; }, //execBuyerLogin - execCartOrderCreate : function($btn) { - $btn.addClass('ui-state-highlight').button().css('display','block'); + cartOrderSave : function($ele,p) { + var $form = $ele.closest('form'); + _app.ext.cco.u.sanitizeAndUpdateCart($form,{ + callback : 'showMessaging', + message : 'Your changes have been saved', + jqObj : $form, + restoreInputsFromTrackingState : true + }); + _app.model.dispatchThis('immutable'); + }, - $btn.off('click.execCartOrderCreate').on('click.execCartOrderCreate',function(event){ - event.preventDefault(); - var $form = $btn.closest('form'); - + execCartOrderCreate : function($ele,p) { + p.preventDefault(); + var $form = $ele.closest('form'); + //if paypalEC is selected, skip validation and go straight to paypal. Upon return, bill and ship will get populated automatically. - if($("input[name='want/payby']:checked",$form).val() == 'PAYPALEC' && !app.ext.cco.u.thisSessionIsPayPal()) { - $('body').showLoading({'message':'Transferring you to PayPal payment authorization'}); - app.ext.cco.calls.cartPaypalSetExpressCheckout.init({'getBuyerAddress': (app.u.buyerIsAuthenticated()) ? 0 : 1},{'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ - $('body').hideLoading(); - $('html, body').animate({scrollTop : $fieldset.offset().top},1000); //scroll to first instance of error. - $fieldset.anymessage({'message':rd}); - } - else { - window.location = app.data[rd.datapointer].URL - } - },"extension":"orderCreate",'parentID': $btn.closest("[data-app-role='checkout']").parent().attr('id')},'immutable'); - app.model.dispatchThis('immutable'); - } - else { - - if(app.ext.orderCreate.validate.checkout($form)) { + if($("input[name='want/payby']:checked",$form).val() == 'PAYPALEC' && !_app.ext.cco.u.thisSessionIsPayPal()) { + $('body').showLoading({'message':'Transferring you to PayPal payment authorization'}); +//***201402 Must pass cartid parameter on the call itself -mc + var cartid = $ele.closest("[data-app-role='checkout']").data('cartid'); + _app.ext.cco.calls.cartPaypalSetExpressCheckout.init({ + 'getBuyerAddress': (_app.u.buyerIsAuthenticated()) ? 0 : 1, + '_cartid':cartid, + 'useMobile':($(document.body).width() < 500 ? 1 : 0) + },{'callback':function(rd){ + if(_app.model.responseHasErrors(rd)){ + $('body').hideLoading(); + $('html, body').animate({scrollTop : $fieldset.offset().top},1000); //scroll to first instance of error. + $fieldset.anymessage({'message':rd}); + } + else { + window.location = _app.data[rd.datapointer].URL+'&useraction=commit'; //commit returns user to website for order confirmation. otherwise they stay on paypal. + } + },"extension":"order_create",'parentID': $ele.closest("[data-app-role='checkout']").attr('id')},'immutable'); + _app.model.dispatchThis('immutable'); + } + else { + if(_app.ext.order_create.validate.checkout($form)) { + var $checkout = $form.closest("[data-app-role='checkout']"); + $checkout.slideUp('fast',function(){ $('body').showLoading({'message':'Creating order...'}); - app.ext.cco.u.sanitizeAndUpdateCart($form); + }); + _app.ext.cco.u.sanitizeAndUpdateCart($form); + var cartid = $ele.closest("[data-app-role='checkout']").data('cartid'), payments; //paypal payments are added to the q as soon as the user returns from paypal. //This will solve the double-add to the payment Q //payment method validation ensures a valid tender is present. - if(app.ext.cco.u.thisSessionIsPayPal()) {} - else { - app.ext.cco.u.buildPaymentQ($form); - } - app.ext.cco.calls.cartOrderCreate.init({'callback':'cart2OrderIsComplete','extension':'orderCreate','jqObj':$form}); - app.model.dispatchThis('immutable'); - - } + if(_app.ext.cco.u.thisSessionIsPayPal()) {} else { - //even though validation failed, take this opportunity to update the cart on the server. - app.ext.cco.u.sanitizeAndUpdateCart($form); - app.model.dispatchThis('immutable'); - //scrolls up to first instance of an error. - $('html, body').animate({scrollTop : $('.formValidationError, .ui-widget-anymessage, .ui-state-error',$form).first().offset().top},1000); //scroll to first instance of error. + payments = _app.ext.cco.u.getPaymentQArray($form,cartid); } +// _app.ext.cco.calls.cartOrderCreate.init(cartid,{'callback':'cart2OrderIsComplete','extension':'order_create','jqObj':$form}); + _app.model.addDispatchToQ({ + '_cartid':cartid, + '_cmd':'cartOrderCreate', + '@PAYMENTS' : payments, + 'async' : 1, + '_tag':{'datapointer':'cartOrderCreate|'+cartid,'callback':'cartOrderStatus','extension':'order_create','parentID':$checkout.attr('id')}, + 'iama':_app.vars.passInDispatchV, + 'domain' : (_app.vars.thisSessionIsAdmin ? 'www.'+_app.vars.domain : '') + },'immutable'); + _app.model.dispatchThis('immutable'); + } - }) + else { + //even though validation failed, take this opportunity to update the cart on the server. + _app.ext.cco.u.sanitizeAndUpdateCart($form); + _app.model.dispatchThis('immutable'); + //scrolls up to first instance of an error. + $('html, body').animate({scrollTop : $('.formValidationError, .ui-widget-anymessage, .ui-state-error',$form).first().offset().top},1000); //scroll to first instance of error. + } + } + return false; }, //execCartOrderCreate //update the cart. no callbacks or anything like that, just get the data to the api. //used on notes and could be recyled if needed. - execCartSet : function($ele) { - $ele.off('blur.execCartSet').on('blur.execCartSet',function(){ - var obj = {}; - obj[$ele.attr('name')] = $ele.val(); - app.calls.cartSet.init(obj); - app.model.dispatchThis('immutable'); - }) + execCartSet : function($ele,p) { + p.preventDefault(); + var obj = {}; + obj[$ele.attr('name')] = $ele.val(); + obj._cartid = $ele.closest("[data-app-role='checkout']").data('cartid'); + _app.ext.cco.calls.cartSet.init(obj); + _app.model.dispatchThis('immutable'); + return false; }, //execCartSet - execChangeFromPayPal : function($ele) { - $ele.off('click.execChangeFromPayPal').on('click.execChangeFromPayPal',function(){ - app.u.dump("execChangeFromPayPal has been Executed"); - app.ext.cco.u.nukePayPalEC(); - var $form = $ele.closest('form'); - app.ext.orderCreate.u.handleCommonPanels($form); - app.calls.ping.init({callback:function(){ - app.ext.orderCreate.u.handlePanel($form,'chkoutAddressBill',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($form,'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents']); - }},'immutable'); - app.model.dispatchThis('immutable'); - }); - - + execChangeFromPayPal : function($ele,p) { + p.preventDefault(); + _app.ext.cco.u.nukePayPalEC(); + var $form = $ele.closest('form'); + _app.ext.order_create.u.handleCommonPanels($form); + _app.calls.ping.init({callback:function(){ + _app.ext.order_create.u.handlePanel($form,'chkoutAddressBill',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($form,'chkoutAddressShip',['empty','translate','handleDisplayLogic']); + }},'immutable'); + _app.model.dispatchThis('immutable'); + return false; }, - execCountryUpdate : function($sel) { + execCountryUpdate : function($ele,p) { + p.preventDefault(); //recalculate the shipping methods and payment options. - $sel.off('change.execCountryUpdate').on('change.execCountryUpdate',function(){ - var obj = {}, $form = $sel.closest('form'); + var obj = {}, $form = $ele.closest('form'); //temporary workaround. setting bill country to int isn't updating ship methods correctly. -// app.u.dump(" -> $sel.attr('name'): "+$sel.attr('name')); //if bill to ship is enabled, must update ship country or shipping won't update. - if($sel.attr('name') == 'bill/countrycode' && $("[name='want/bill_to_ship']",$form).is(':checked')) { -// app.u.dump(" -> ship to bill is enabled. update ship country."); - obj['ship/countrycode'] = $sel.val(); - } - - obj[$sel.attr('name')] = $sel.val(); - app.calls.cartSet.init(obj); //update the cart w/ the country. - app.ext.orderCreate.u.handleCommonPanels($form); - app.model.dispatchThis('immutable'); - }) + if($ele.attr('name') == 'bill/countrycode' && $("[name='want/bill_to_ship']",$form).is(':checked')) { + obj['ship/countrycode'] = $ele.val(); + } + + obj[$ele.attr('name')] = $ele.val(); + obj._cartid = $ele.closest("[data-app-role='checkout']").data('cartid'); + _app.ext.cco.calls.cartSet.init(obj); //update the cart w/ the country. + _app.ext.order_create.u.handleCommonPanels($form); + _app.model.dispatchThis('immutable'); + return false; }, //execCountryUpdate - execCouponAdd : function($btn) { - $btn.button(); - $btn.off('click.execCouponAdd').on('click.execCouponAdd',function(event){ - event.preventDefault(); - - var $fieldset = $btn.closest('fieldset'), - $form = $btn.closest('form'), - $input = $("[name='coupon']",$fieldset); - - $btn.button('disable'); - - -//update the panel only on a successful add. That way, error messaging is persistent. success messaging gets nuked, but coupon will show in cart so that's okay. + execCouponAdd : function($ele,p) { + p.preventDefault(); + var $fieldset = $ele.closest('fieldset'), + $form = $ele.closest('form'), + cartid = $ele.closest("[data-app-role='checkout']").data('cartid'), + $input = $("[name='coupon']",$fieldset); - app.ext.cco.calls.cartCouponAdd.init($input.val(),{"callback":function(rd){ + if($ele.is('button')){$ele.button('disable');} - if(app.model.responseHasErrors(rd)){ - $fieldset.anymessage({'message':rd}); - } - else { - $input.val(''); //reset input only on success. allows for a typo to be corrected. - $fieldset.anymessage(app.u.successMsgObject('Your coupon has been added.')); - app.ext.orderCreate.u.handlePanel($form,'chkoutCartItemsList',['empty','translate','handleDisplayLogic','handleAppEvents']); -// _gaq.push(['_trackEvent','Checkout','User Event','Cart updated - coupon added']); +//update the panel only on a successful add. That way, error messaging is persistent. success messaging gets nuked, but coupon will show in cart so that's okay. + _app.ext.cco.calls.cartCouponAdd.init($input.val(),cartid,{"callback":function(rd){ + if(_app.model.responseHasErrors(rd)){ + $fieldset.anymessage({'message':rd}); + } + else { + $input.val(''); //reset input only on success. allows for a typo to be corrected. + $fieldset.anymessage(_app.u.successMsgObject('Your coupon has been added.')); + _app.ext.order_create.u.handlePanel($form,'chkoutCartItemsList',['empty','translate','handleDisplayLogic']); +//if a cart messenger is open, log the cart update. + if(cartid && _app.u.thisNestedExists('ext.cart_message.vars.carts.'+cartid,_app)) { + _app.model.addDispatchToQ({'_cmd':'cartMessagePush','what':'cart.update','description':'Coupon added','_cartid':cartid},'passive'); + _app.model.dispatchThis('passive'); } - - }}); - - app.ext.orderCreate.u.handleCommonPanels($form); - app.model.dispatchThis('immutable'); - }) + window[_app.vars.analyticsPointer]('send', 'event','Checkout','User Event','Cart updated - coupon added'); + } + }}); + + _app.ext.order_create.u.handleCommonPanels($form); + _app.model.dispatchThis('immutable'); + return false; }, //execCouponAdd - execGiftcardAdd : function($btn) { - $btn.button(); - $btn.off('click.execGiftcardAdd').on('click.execGiftcardAdd',function(event){ - event.preventDefault(); - - var $fieldset = $btn.closest('fieldset'), - $input = $("[name='giftcard']",$fieldset); - - $btn.button('disable'); - +//executed on a giftcard when it is in the list of payment methods. + addGiftcardPaymethodAsPayment : function($ele,p) { + p.preventDefault(); + if($ele.attr('data-giftcard-id')) { + $ele.button('disable'); + var $checkout = $ele.closest("[data-app-role='checkout']"); + _app.ext.cco.calls.cartGiftcardAdd.init($ele.attr('data-giftcard-id'),$checkout.data('cartid'),{'jqObj':$checkout},'immutable'); //jqObj passed for error handling. callback handled by cart update. + _app.model.destroy('cartDetail|'+$checkout.data('cartid')); + _app.calls.cartDetail.init($checkout.data('cartid'),{'callback':'updateAllPanels','extension':'order_create','jqObj':$checkout},'immutable'); + _app.model.dispatchThis('immutable'); + } + else { + $("#globalMessaging").anymessage({"message":"In order_create.e.addGiftcardPaymethodAsPayment, data-giftcard-id is not set on trigger element.","gMessage":true}); + } + return false; + }, -//update the panel only on a successful add. That way, error messaging is persistent. success messaging gets nuked, but coupon will show in cart so that's okay. + execGiftcardAdd : function($ele,p) { + p.preventDefault(); + var $fieldset = $ele.closest('fieldset'), + cartid = $ele.closest("[data-app-role='checkout']").data('cartid'), + $input = $("[name='giftcard']",$fieldset); - app.ext.cco.calls.cartGiftcardAdd.init($input.val(),{"callback":function(rd){ - - if(app.model.responseHasErrors(rd)){ - $fieldset.anymessage({'message':rd}); - } - else { - $input.val(''); //reset input - $fieldset.anymessage(app.u.successMsgObject('Your giftcard has been added.')); -// _gaq.push(['_trackEvent','Checkout','User Event','Cart updated - giftcard added']); + if($ele.is('button')){$ele.button('disable');} +//update the panel only on a successful add. That way, error messaging is persistent. success messaging gets nuked, but coupon will show in cart so that's okay. + _app.ext.cco.calls.cartGiftcardAdd.init($input.val(),cartid,{"callback":function(rd){ + if(_app.model.responseHasErrors(rd)){ + $fieldset.anymessage({'message':rd}); + } + else { + $input.val(''); //reset input + $fieldset.anymessage(_app.u.successMsgObject('Your giftcard has been added.')); +//if a cart messenger is open, log the cart update. + if(cartid && _app.u.thisNestedExists('ext.cart_message.vars.carts.'+cartid,_app)) { + _app.model.addDispatchToQ({'_cmd':'cartMessagePush','what':'cart.update','description':'Giftcard added','_cartid':cartid},'passive'); + _app.model.dispatchThis('passive'); } - - }}); - app.ext.orderCreate.u.handleCommonPanels($input.closest('form')); - app.model.dispatchThis('immutable'); - }) + window[_app.vars.analyticsPointer]('send','event','Checkout','User Event','Cart updated - giftcard added'); + } + }}); + _app.ext.order_create.u.handleCommonPanels($input.closest('form')); + _app.model.dispatchThis('immutable'); + return false; }, //execGiftcardAdd - execInvoicePrint : function($btn) { - $btn.button({icons: {primary: "ui-icon-print"},text: false}); - - $btn.off('click.execInvoicePrint').on('click.execInvoicePrint',function(event){ - event.preventDefault(); - app.u.printByjqObj($btn.closest("[data-app-role='invoiceContainer']")); - }); - + execInvoicePrint : function($ele,p) { + p.preventDefault(); + _app.u.printByjqObj($ele.closest("[data-app-role='invoiceContainer']")); + return false; }, //execInvoicePrint - showBuyerAddressAdd : function($btn) { - $btn.button(); - - var $checkoutForm = $btn.closest('form'), //used in some callbacks later. - $checkoutAddrFieldset = $btn.closest('fieldset'); - - $btn.off('click.showBuyerAddressAdd').on('click.showBuyerAddressAdd',function(event){ - event.preventDefault(); - var addressType = $btn.data('app-addresstype').toLowerCase(); - app.ext.store_crm.u.showAddressAddModal({'addressType':addressType},function(rd,serializedForm){ + showBuyerAddressAdd : function($ele,p) { + p.preventDefault(); + var + $checkoutForm = $ele.closest('form'), //used in some callbacks later. + $checkoutAddrFieldset = $ele.closest('fieldset'), + addressType = $ele.attr('data-app-addresstype').toLowerCase(); + if(_app.u.thisIsAnAdminSession()) { + var $D = _app.ext.admin_customer.a.createUpdateAddressShow({'mode':'create','show':'dialog','type':addressType}); + } + else { + _app.ext.store_crm.u.showAddressAddModal({'addressType':addressType},function(rd,serializedForm){ //by here, the new address has been created. //set appropriate address panel to loading. - app.ext.orderCreate.u.handlePanel($checkoutForm,$checkoutAddrFieldset.data('app-role'),['showLoading']); - //update cart and set shortcut as address. - var updateObj = {} + _app.ext.order_create.u.handlePanel($checkoutForm,$checkoutAddrFieldset.data('app-role'),['showLoading']); +//update cart and set shortcut as address. + var updateObj = {'_cartid':$ele.closest("[data-app-role='checkout']").data('cartid')} updateObj[addressType+'/shortcut'] = serializedForm.shortcut; - app.ext.cco.calls.cartSet.init(updateObj,{},'immutable'); + _app.ext.cco.calls.cartSet.init(updateObj,{},'immutable'); - //update DOM/input for shortcut w/ new shortcut value. +//update DOM/input for shortcut w/ new shortcut value. $("[name='"+addressType+"/shortcut']",$checkoutForm); - //get the updated address list and update the address panel. - app.model.destroy('buyerAddressList'); - app.calls.buyerAddressList.init({'callback':function(rd){ - app.ext.orderCreate.u.handlePanel($checkoutForm,$checkoutAddrFieldset.data('app-role'),['empty','translate','handleDisplayLogic','handleAppEvents']); +//get the updated address list and update the address panel. + _app.model.destroy('buyerAddressList'); + _app.calls.buyerAddressList.init({'callback':function(rd){ + _app.ext.order_create.u.handlePanel($checkoutForm,$checkoutAddrFieldset.data('app-role'),['empty','translate','handleDisplayLogic']); }},'immutable'); - //update appropriate address panel plus big three. - app.ext.orderCreate.u.handleCommonPanels($checkoutForm); - app.model.dispatchThis('immutable'); +//update appropriate address panel plus big three. + _app.ext.order_create.u.handleCommonPanels($checkoutForm); + _app.model.dispatchThis('immutable'); }); - }) + } + return false; }, //showBuyerAddressAdd - showBuyerAddressUpdate : function($btn,p) { - $btn.button({icons: {primary: "ui-icon-pencil"},text: false}); + showBuyerAddressUpdate : function($ele,p) { + p.preventDefault(); p = p || {}; - var $checkoutForm = $btn.closest('form'), //used in some callbacks later. - $checkoutAddrFieldset = $btn.closest('fieldset'); - - $btn.off('click.showBuyerAddressUpdate').on('click.showBuyerAddressUpdate',function(event){ - event.preventDefault(); - var addressType = $btn.closest("[data-app-addresstype]").data('app-addresstype'); - - app.ext.store_crm.u.showAddressEditModal({ - 'addressID' : $btn.closest("address").data('_id'), - 'addressType' : addressType, - 'validateForm' : $btn.data('validate-form') - },function(){ + var $checkoutForm = $ele.closest('form'), //used in some callbacks later. + $checkoutAddrFieldset = $ele.closest('fieldset'); + + var addressType = $ele.closest("[data-app-addresstype]").data('app-addresstype'); + dump(" ---------> addressType: "+addressType); + _app.ext.store_crm.u.showAddressEditModal({ + 'addressID' : $ele.closest("address").data('_id'), + 'addressType' : addressType, + 'validateForm' : $ele.data('validate-form') + },function(){ //by here, the new address has been edited. //set appropriate address panel to loading. //editing and address does NOT auto-select it. - app.ext.orderCreate.u.handlePanel($checkoutForm,$checkoutAddrFieldset.data('app-role'),['showLoading']); - - //get the updated address list and update the address panel. - app.model.destroy('buyerAddressList'); - app.calls.buyerAddressList.init({'callback':function(rd){ - app.ext.orderCreate.u.handlePanel($checkoutForm,$checkoutAddrFieldset.data('app-role'),['empty','translate','handleDisplayLogic','handleAppEvents']); - }},'immutable'); - - app.model.dispatchThis('immutable'); - }) - }); - }, //showBuyerAddressUpdate + _app.ext.order_create.u.handlePanel($checkoutForm,$checkoutAddrFieldset.data('app-role'),['showLoading']); - tagAsAccountCreate : function($cb) { - $cb.anycb({text : {on : 'yes',off : 'no'}}); - $cb.off('change.tagAsAccountCreate').on('change.tagAsAccountCreate',function() { - app.ext.cco.calls.cartSet.init({'want/create_customer': $cb.is(':checked') ? 1 : 0}); //val of a cb is on or off, but we want 1 or 0. - app.model.destroy('cartDetail'); - app.ext.orderCreate.u.handlePanel($cb.closest('form'),'chkoutPreflight',['handleDisplayLogic']); - app.calls.cartDetail.init({'callback':function(rd){ - app.ext.orderCreate.u.handlePanel($cb.closest('form'),'chkoutAccountCreate',['handleDisplayLogic']); +//get the updated address list and update the address panel. + _app.model.destroy('buyerAddressList'); + _app.calls.buyerAddressList.init({'callback':function(rd){ + _app.ext.order_create.u.handlePanel($checkoutForm,$checkoutAddrFieldset.data('app-role'),['empty','translate','handleDisplayLogic']); }},'immutable'); - app.model.dispatchThis('immutable'); + + _app.model.dispatchThis('immutable'); }); + return false; + }, //showBuyerAddressUpdate + + tagAsAccountCreate : function($ele,p) { + p.preventDefault(); + var $checkout = $ele.closest("[data-app-role='checkout']"); + _app.ext.cco.calls.cartSet.init({'_cartid':$checkout.data('cartid'),'want/create_customer': $ele.is(':checked') ? 1 : 0}); //val of a cb is on or off, but we want 1 or 0. + _app.model.destroy('cartDetail|'+$checkout.data('cartid')); + _app.ext.order_create.u.handlePanel($ele.closest('form'),'chkoutPreflight',['handleDisplayLogic']); + _app.calls.cartDetail.init($checkout.data('cartid'),{'callback':function(rd){ + _app.ext.order_create.u.handlePanel($ele.closest('form'),'chkoutAccountCreate',['handleDisplayLogic']); + }},'immutable'); + _app.model.dispatchThis('immutable'); + return false; }, //tagAsAccountCreate - - tagAsBillToShip : function($cb) { - $cb.anycb({text : {on : 'yes',off : 'no'}}); - $cb.off('change.tagAsBillToShip').on('change.tagAsBillToShip',function() { - var $form = $cb.closest('form'); - app.calls.cartSet.init({'want/bill_to_ship':($cb.is(':checked')) ? 1 : 0},{},'immutable'); //adds dispatches. + tagAsBillToShip : function($ele,p) { + p.preventDefault(); + var $form = $ele.closest('form'); + _app.ext.cco.calls.cartSet.init({'want/bill_to_ship':($ele.is(':checked')) ? 1 : 0,_cartid : $ele.closest("[data-app-role='checkout']").data('cartid')},{},'immutable'); //adds dispatches. //when toggling back to ship to bill, update shipping zip BLANK to re-compute shipping. // re-render the panel as well so that if bill to ship is unchecked, the zip has to be re-entered. makes sure ship quotes are up to date. // originally, had ship zip change to bill instead of blank, but seemed like there'd be potential for a buyer to miss that change. - if($cb.is(':checked')) { -//** Fixes bug where if ship to bill is disabled, shipping is populated, then ship to bill is re-enabled, bill address is not used for shipping quotes (entered ship address is) - app.ext.cco.u.sanitizeAndUpdateCart($form,{ - 'callback':function(rd){app.ext.orderCreate.u.handlePanel($form,'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents'])} - }); - -// app.calls.cartSet.init({'ship/postal': ""},{'callback':function(rd){ -// app.ext.orderCreate.u.handlePanel($form,'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents']); -// }},'immutable'); //update ship zip to bill zip. - } - else { - app.ext.orderCreate.u.handlePanel($form,'chkoutAddressShip',['handleDisplayLogic']); - } - app.model.destroy('cartDetail'); - app.ext.orderCreate.u.handleCommonPanels($form); - app.model.dispatchThis('immutable'); - }); + if($ele.is(':checked')) { +// -> Sanitize is here to address bug where if ship to bill is disabled, shipping is populated, then ship to bill is re-enabled, bill address is not used for shipping quotes (entered ship address is) +// all panels get updated because shipping, totals and potentially payment methods can be impacted by ship country. + _app.ext.cco.u.sanitizeAndUpdateCart($form,{ + 'callback':'updateAllPanels', + 'extension' : 'order_create', + 'jqObj' : $form + }); + } + else { + _app.ext.order_create.u.handlePanel($form,'chkoutAddressShip',['handleDisplayLogic']); + } + _app.ext.order_create.u.handleCommonPanels($form); + _app.model.dispatchThis('immutable'); + return false; } //tagAsBillToShip }, @@ -1609,48 +1992,49 @@ app.u.dump("BEGIN orderCreate.e.cartItemAddWithChooser (Click!)"); u : { //Combines the various data objects into one, so that they can be fed into the translator and rendered in one pass. - extendedDataForCheckout : function() { -// app.u.dump("BEGIN orderCreate.u.extendedDataForCheckout - 2013-04-13"); -// app.u.dump("app.data.cartDetail:"); app.u.dump(app.data.cartDetail); - var obj; - if(app.vars.thisSessionIsAdmin) { - //can skip all the paypal code in an admin session. it isn't a valid payment option. - if(app.data.cartDetail.customer.cid && app.data['adminCustomerDetail|'+app.data.cartDetail.customer.cid]) { - //change this so object stores the data how buyerAddressList and buyerWalletList would. - obj = { - '@wallets' : app.data['adminCustomerDetail|'+app.data.cartDetail.customer.cid]['@WALLETS'], - '@bill' : app.data['adminCustomerDetail|'+app.data.cartDetail.customer.cid]['@BILL'], - '@ship' : app.data['adminCustomerDetail|'+app.data.cartDetail.customer.cid]['@SHIP'] - }; - } - obj = $.extend(true,obj,app.data.appPaymentMethods,app.data.appCheckoutDestinations,app.data.cartDetail); - } - else { - if(app.u.buyerIsAuthenticated()) { - // app.u.dump(" -> buyer is authenticated"); - obj = $.extend(true,app.data.appPaymentMethods,app.data.appCheckoutDestinations,app.data.buyerAddressList,app.data.buyerWalletList,app.data.cartDetail); + extendedDataForCheckout : function(cartID) { +// _app.u.dump("BEGIN order_create.u.extendedDataForCheckout - 2013-04-13"); +// _app.u.dump("_app.data.cartDetail:"); _app.u.dump(_app.data.cartDetail); + var obj = {}; + if(cartID) { + if(_app.u.thisIsAnAdminSession()) { + //can skip all the paypal code in an admin session. it isn't a valid payment option. + if(_app.u.thisNestedExists("data.cartDetail|"+cartID+".customer.cid",_app) && _app.data['adminCustomerDetail|'+_app.data['cartDetail|'+cartID].customer.cid]) { + //change this so object stores the data how buyerAddressList and buyerWalletList would. + obj = $.extend(true,obj,_app.data['adminCustomerDetail|'+_app.data['cartDetail|'+cartID].customer.cid]); //have to copy the detail record or it gets updated in memory. + } + $.extend(obj,_app.data['appPaymentMethods|'+cartID],_app.data['appCheckoutDestinations|'+cartID],_app.data['cartDetail|'+cartID]); } else { - // app.u.dump(" -> buyer is not authenticated."); - obj = $.extend(true,app.data.appPaymentMethods,app.data.appCheckoutDestinations,app.data.cartDetail); - } + if(_app.u.buyerIsAuthenticated()) { + // _app.u.dump(" -> buyer is authenticated"); + $.extend(true,obj,_app.data['appPaymentMethods|'+cartID],_app.data['appCheckoutDestinations|'+cartID],_app.data.buyerAddressList,_app.data.buyerWalletList,_app.data['cartDetail|'+cartID]); + } + else { + // _app.u.dump(" -> buyer is not authenticated."); + $.extend(true,obj,_app.data['appPaymentMethods|'+cartID],_app.data['appCheckoutDestinations|'+cartID],_app.data['cartDetail|'+cartID]); + } //when a buyer returns from paypal, the shipping is populated, but the billing is not always. //this will put the ship info into the bill fields if they're blank. - if(app.ext.cco.u.thisSessionIsPayPal()) { - // app.u.dump(" -> session is paypal. copy some data around."); - if(obj.bill && obj.ship) { - if(!obj.bill.company) {obj.bill.company = obj.ship.company} - if(!obj.bill.address1) {obj.bill.address1 = obj.ship.address1} - if(!obj.bill.address2) {obj.bill.address2 = obj.ship.address2} - if(!obj.bill.city) {obj.bill.city = obj.ship.city} - if(!obj.bill.region) {obj.bill.region = obj.ship.region} - if(!obj.bill.postal) {obj.bill.postal = obj.ship.postal} - if(!obj.bill.countrycode) {obj.bill.countrycode = obj.ship.countrycode} + if(_app.ext.cco.u.thisSessionIsPayPal()) { + // _app.u.dump(" -> session is paypal. copy some data around."); + if(obj.bill && obj.ship) { + if(!obj.bill.company) {obj.bill.company = obj.ship.company} + if(!obj.bill.address1) {obj.bill.address1 = obj.ship.address1} + if(!obj.bill.address2) {obj.bill.address2 = obj.ship.address2} + if(!obj.bill.city) {obj.bill.city = obj.ship.city} + if(!obj.bill.region) {obj.bill.region = obj.ship.region} + if(!obj.bill.postal) {obj.bill.postal = obj.ship.postal} + if(!obj.bill.countrycode) {obj.bill.countrycode = obj.ship.countrycode} + } } } } -// app.u.dump("END orderCreate.u.extendedDataForCheckout"); + else { + $('#globalMessaging').anymessage({"message":"In order_create.u.extendedDataForCheckout, no cart id passed.","gMessage":true}); + } +// _app.u.dump("END order_create.u.extendedDataForCheckout"); return obj; }, //extendedDataForCheckout @@ -1671,35 +2055,34 @@ app.u.dump("BEGIN orderCreate.e.cartItemAddWithChooser (Click!)"); //$content could be the parent form or the forms container. just something around this checkout. (so that multiple checkout forms are possible. imp in UI //role is the value of data-app-role on the fieldset. -//actions is what needs to happen. an array. accepted values are empty, showLoading, addAppEvents, translate and handleDisplayLogic. ex: ['translate','handleDisplayLogic'] +//actions is what needs to happen. an array. accepted values are empty, showLoading, translate and handleDisplayLogic. ex: ['translate','handleDisplayLogic'] //actions are rendered in the order they're passed. handlePanel : function($context, role, actions) { -// app.u.dump("BEGIN handlePanel"); //app.u.dump(actions); +// _app.u.dump("BEGIN handlePanel ["+role+"]."); //_app.u.dump(actions); + + if($context instanceof jQuery && role && actions && typeof actions === 'object') { +// _app.u.dump(" -> role: "+role); - if($context && role && actions && typeof actions === 'object') { -// app.u.dump(" -> role: "+role); var L = actions.length, formObj = $context.is('form') ? $context.serializeJSON() : $("form",$context).serializeJSON(), - $fieldset = $("[data-app-role='"+app.u.jqSelector('',role)+"']",$context), + cartID = $context.closest("[data-app-role='checkout']").data('cartid'), + $fieldset = $("[data-app-role='"+_app.u.jqSelector('',role)+"']",$context), ao = {}; ao.showLoading = function (formObj, $fieldset){$(".panelContent",$fieldset).showLoading({'message':'Fetching updated content'})}, ao.hideLoading = function (formObj, $fieldset){$(".panelContent",$fieldset).hideLoading()}, ao.empty = function(formObj, $fieldset){$(".panelContent",$fieldset).empty()}, - ao.handleAppEvents = function(formObj, $fieldset){app.u.handleAppEvents($fieldset)}, ao.handleDisplayLogic = function(formObj, $fieldset){ - if(typeof app.ext.orderCreate.panelDisplayLogic[role] === 'function') { - app.ext.orderCreate.panelDisplayLogic[role](formObj,$fieldset); + if(typeof _app.ext.order_create.panelDisplayLogic[role] === 'function') { + _app.ext.order_create.panelDisplayLogic[role](formObj,$fieldset,_app.data['cartDetail|'+cartID]); } else { - $fieldset.anymessage({'message':'In orderCreate.u.handlePanel, panelDisplayLogic['+role+'] not a function','gMessage':true}); + $fieldset.anymessage({'message':'In order_create.u.handlePanel, panelDisplayLogic['+role+'] not a function','gMessage':true}); } }, //perform things like locking form fields, hiding/showing the panel based on some setting. never pass in the setting, have it read from the form or cart. ao.translate = function(formObj, $fieldset) { -// app.u.dump(" -> translating "+role); -// app.u.dump("app.ext.orderCreate.u.extendedDataForCheckout()"); app.u.dump(app.ext.orderCreate.u.extendedDataForCheckout()); - $fieldset.anycontent({'data' : app.ext.orderCreate.u.extendedDataForCheckout()}); + $fieldset.tlc({'verb' : 'translate','dataset' : _app.ext.order_create.u.extendedDataForCheckout(cartID)}); } //populates the template. for(var i = 0; i < L; i += 1) { @@ -1707,13 +2090,17 @@ app.u.dump("BEGIN orderCreate.e.cartItemAddWithChooser (Click!)"); ao[actions[i]](formObj, $fieldset); } else { - $('#globalMessaging').anymessage({'message':"In orderCreate.u.handlePanel, undefined action ["+actions[i]+"]",'gMessage':true}); + $('#globalMessaging').anymessage({'message':"In order_create.u.handlePanel, undefined action ["+actions[i]+"]",'gMessage':true}); } + _app.u.handleButtons($fieldset); + $('.applyAnycb',$fieldset).each(function(){ + $(this).anycb({text : {on : 'yes',off : 'no'}}); + }); } } else { - $('#globalMessaging').anymessage({'message':"In orderCreate.u.handlePanel, either $context ["+typeof $context+"], role ["+role+"] or actions ["+actions+"] not defined or not an object ["+typeof actions+"]",'gMessage':true}); + $('#globalMessaging').anymessage({'message':"In order_create.u.handlePanel, either $context ["+typeof $context+"], role ["+role+"] or actions ["+actions+"] not defined or not an object ["+typeof actions+"]",'gMessage':true}); } }, //handlePanel @@ -1721,64 +2108,80 @@ app.u.dump("BEGIN orderCreate.e.cartItemAddWithChooser (Click!)"); //sets payment options, shipping options and cart summary to loading, then adds immutable dispatches/callbacks/etc for updating. //does NOT dispatch. That way, other requests can be piggy-backed. handleCommonPanels : function($context) { - app.ext.orderCreate.u.handlePanel($context,'chkoutMethodsShip',['showLoading']); - app.ext.orderCreate.u.handlePanel($context,'chkoutMethodsPay',['showLoading']); - app.ext.orderCreate.u.handlePanel($context,'chkoutCartSummary',['showLoading']); - - app.model.destroy('cartDetail'); - app.ext.cco.calls.appPaymentMethods.init({_cartid:app.vars.cartID},{},'immutable'); //update pay and ship anytime either address changes. - app.calls.cartDetail.init({'callback':function(){ -// app.u.dump('cartDetail: '); app.u.dump(app.data.cartDetail); - app.ext.orderCreate.u.handlePanel($context,'chkoutMethodsShip',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($context,'chkoutMethodsPay',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($context,'chkoutCartSummary',['empty','translate','handleDisplayLogic','handleAppEvents']); - }},'immutable'); + var cartid = $context.closest("[data-app-role='checkout']").data('cartid'); +// _app.u.dump(" -> handleCommonPanels cartID: "+cartid); + if(cartid) { + _app.ext.order_create.u.handlePanel($context,'chkoutMethodsShip',['showLoading']); + _app.ext.order_create.u.handlePanel($context,'chkoutMethodsPay',['showLoading']); + _app.ext.order_create.u.handlePanel($context,'chkoutCartSummary',['showLoading']); + + if(_app.u.thisIsAnAdminSession()) { + _app.ext.order_create.u.handlePanel($context,'chkoutCartItemsList',['showLoading']); + } + + _app.model.destroy('cartDetail|'+cartid); + _app.ext.cco.calls.appPaymentMethods.init({_cartid:cartid},{},'immutable'); //update pay and ship anytime either address changes. + _app.calls.cartDetail.init(cartid,{'callback':function(){ + // _app.u.dump('cartDetail: '); _app.u.dump(_app.data.cartDetail); + _app.ext.order_create.u.handlePanel($context,'chkoutMethodsShip',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($context,'chkoutMethodsPay',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($context,'chkoutCartSummary',['empty','translate','handleDisplayLogic']); + //in an admin session, the cart contents are updated much more frequently because the 'cart' is editable. + //if a storefront offers an editable cart within checkout, then remove the if around the chkoutCartItemsList update. + if(_app.u.thisIsAnAdminSession()) { + _app.ext.order_create.u.handlePanel($context,'chkoutCartItemsList',['empty','translate','handleDisplayLogic']); + } + }},'immutable'); + } + else { + $context.anymessage({'message':'In order_create.u.handleCommonPanels, unable to ascertain cartid [closest(data-app-role="checkout").length: '+$context.closest("[data-app-role='checkout']").length+'] ','gMessage':true}) + } }, //handleCommonPanels - handlePaypalInit : function($context) { -// app.u.dump("BEGIN orderCreate.u.handlePaypalInit"); + handlePaypalInit : function($context, cartID) { +// _app.u.dump("BEGIN order_create.u.handlePaypalInit"); //paypal code need to be in this startCheckout and not showCheckoutForm so that showCheckoutForm can be // executed w/out triggering the paypal code (which happens when payment method switches FROM paypal to some other method) because // the paypalgetdetails cmd only needs to be executed once per session UNLESS the cart contents change. //calls are piggybacked w/ this. do not add dispatch here. - var token = app.u.getParameterByName('token'); - var payerid = app.u.getParameterByName('PayerID'); -// app.u.dump(" -> aValidPaypalTenderIsPresent(): "+app.ext.cco.u.aValidPaypalTenderIsPresent()); + var token = _app.u.getParameterByName('token'); + var payerid = _app.u.getParameterByName('PayerID'); +// _app.u.dump(" -> aValidPaypalTenderIsPresent(): "+_app.ext.cco.u.aValidPaypalTenderIsPresent()); if(token && payerid) { -// app.u.dump(" -> both token and payerid are set."); - if(app.ext.cco.u.aValidPaypalTenderIsPresent()) { - app.u.dump(" -> token and payid are set but a valid paypal tender is already present."); + _app.u.dump(" -> both token and payerid are set."); + if(_app.ext.cco.u.aValidPaypalTenderIsPresent()) { + _app.u.dump(" -> token and payid are set but a valid paypal tender is already present."); } //already have paypal in paymentQ. could be user refreshed page. don't double-add to Q. else { $context.anymessage({'message':'Welcome Back! you are almost done. Simply verify the information below and push the place order button to complete your transaction.','iconClass':'ui-icon-check','containerClass':'ui-state-highlight ui-state-success'}); - app.u.dump("It appears we've just returned from PayPal."); - app.ext.orderCreate.vars['payment-pt'] = token; - app.ext.orderCreate.vars['payment-pi'] = payerid; - app.ext.cco.calls.cartPaymentQ.init({"cmd":"insert","PT":token,"ID":token,"PI":payerid,"TN":"PAYPALEC"},{"extension":"orderCreate","callback":"handlePayPalIntoPaymentQ",'jqObj':$context}); + _app.u.dump("It appears we've just returned from PayPal."); + _app.ext.order_create.vars['payment-pt'] = token; + _app.ext.order_create.vars['payment-pi'] = payerid; + _app.ext.cco.calls.cartPaymentQ.init({"cmd":"insert","PT":token,"ID":token,"PI":payerid,"TN":"PAYPALEC",'_cartid':cartID},{"extension":"order_create","callback":"handlePayPalIntoPaymentQ",'jqObj':$context}); } } //if token and/or payerid is NOT set on URI, then this is either not yet a paypal order OR is/was paypal and user left checkout and has returned. - else if(app.ext.cco.u.thisSessionIsPayPal()) { - app.u.dump(" -> no token or payerid set. nuke all paypal if present."); - if(!app.ext.cco.u.aValidPaypalTenderIsPresent()) { - app.u.dump(" -> validPayalTender found. Nuke it."); - app.ext.cco.u.nukePayPalEC(); + else if(_app.ext.cco.u.thisSessionIsPayPal()) { + _app.u.dump(" -> no token or payerid set. nuke all paypal if present."); + if(!_app.ext.cco.u.aValidPaypalTenderIsPresent()) { + _app.u.dump(" -> validPayalTender found. Nuke it."); + _app.ext.cco.u.nukePayPalEC(); //update the panels too so that the ship/billing is 'unlocked' and payments get updated. - app.ext.orderCreate.u.handleCommonPanels($form); - app.calls.ping.init({callback:function(){ - app.ext.orderCreate.u.handlePanel($form,'chkoutAddressBill',['empty','translate','handleDisplayLogic','handleAppEvents']); - app.ext.orderCreate.u.handlePanel($form,'chkoutAddressShip',['empty','translate','handleDisplayLogic','handleAppEvents']); + _app.ext.order_create.u.handleCommonPanels($form); + _app.calls.ping.init({callback:function(){ + _app.ext.order_create.u.handlePanel($form,'chkoutAddressBill',['empty','translate','handleDisplayLogic']); + _app.ext.order_create.u.handlePanel($form,'chkoutAddressShip',['empty','translate','handleDisplayLogic']); }},'immutable'); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); } - app.u.dump(" -> paypal nuked "); + _app.u.dump(" -> paypal nuked "); } else { //do nothing. } - app.u.dump("END orderCreate.u.handlePaypalInit"); +// _app.u.dump("END order_create.u.handlePaypalInit"); }, //handlePaypalInit //run when a payment method is selected or when payment panel is re-rendered. @@ -1789,13 +2192,14 @@ app.u.dump("BEGIN orderCreate.e.cartItemAddWithChooser (Click!)"); var $label = $input.closest('label'), $fieldset = $input.closest('fieldset'), - $pmc = $input.closest("[data-app-role='paymentMethodContainer']"); //payment method container. an li or div or row. who knows. + $pmc = $input.closest("[data-app-role='paymentMethodContainer']"), //payment method container. an li or div or row. who knows. + cartID = $input.closest("[data-app-role='checkout']").data('cartid'); //handle the previously selected payment method. $('.ui-state-active',$fieldset).removeClass('ui-state-active ui-corner-top ui-corner-all'); $("[data-app-role='supplementalPaymentInputsContainer']",$fieldset).empty().remove(); //must be removed so form inputs are not present. - var $supplementalOutput = app.ext.cco.u.getSupplementalPaymentInputs($input.val(),app.ext.orderCreate.vars.payment); + var $supplementalOutput = _app.ext.cco.u.getSupplementalPaymentInputs($input.val(),_app.ext.order_create.vars[cartID].payment); if($supplementalOutput) { $label.addClass("ui-state-active ui-corner-top"); $supplementalOutput.addClass('ui-corner-bottom ui-widget ui-widget-content').appendTo($pmc); @@ -1803,7 +2207,7 @@ app.u.dump("BEGIN orderCreate.e.cartItemAddWithChooser (Click!)"); else { $label.addClass("ui-state-active ui-corner-all"); } - app.ext.orderCreate.u.handlePlaceholder($pmc); + _app.ext.order_create.u.handlePlaceholder($pmc); } else { $('#globalMessaging').anymessage({'message':'In cco.u.showSupplementalInputs, $input not defined or not a jquery object.','gMessage':true}); @@ -1815,31 +2219,49 @@ app.u.dump("BEGIN orderCreate.e.cartItemAddWithChooser (Click!)"); // *** 201338 -> new means for executing ROI tracking codes. //pass in what is returned after order create in @TRACKERS scripts2iframe : function(arr) { - app.u.dump('running scripts2iframe'); + _app.u.dump('running scripts2iframe'); if(typeof window.scriptCallback == 'function') {} else { - window.scriptCallback = app.ext.orderCreate.u.scriptCallback; //assigned global scope to reduce likely hood of any errors resulting in callback. - app.u.dump(" -> typeof window.scriptCallback: "+typeof window.scriptCallback); + window.scriptCallback = _app.ext.order_create.u.scriptCallback; //assigned global scope to reduce likely hood of any errors resulting in callback. + _app.u.dump(" -> typeof window.scriptCallback: "+typeof window.scriptCallback); } if(typeof arr == 'object' && !$.isEmptyObject(arr)) { +/* +the timeout is added for multiple reasons. +1. jquery needed a moment between adding the iframe to the DOM and accessing it's contents. +2. by adding some time between each interation (100 * 1), if there's an exception in the tracker, the next code will still run. +*/ + for(var i = 0, L = arr.length; i < L; i++) { + setTimeout(function(thisArr){ + try { + $(document.body).append(thisArr.script); + } + catch(e) { + window.scriptCallback(thisArr.owner,e); + } + },(200 * (i + 1)),arr[i]); + } + +/* +left here in case we want to come back to this. It'll work IF each tracker can run in an isolated environment. +unfortunately, too many of the tracker codes rely on scripts being loaded onLoad in the parent window and are not functioning + properly when isolated in an iframe. var L = arr.length; for(var i = 0; i < L; i++) { -//adding to iframe gives us an isolation layer -//data-script-id added so the iframe can be removed easily later. +adding to iframe gives us an isolation layer +data-script-id added so the iframe can be removed easily later. arr[i].id = 'iframe_3ps_'+i $("<iframe \/>",{'id':arr[i].id}).attr({'data-script-id':arr[i].owner,'height':1,'width':1}).css({'display':'none'}).appendTo('body'); // -> commented out for testing !!! -/* the timeout is added for multiple reasons. 1. jquery needed a moment between adding the iframe to the DOM and accessing it's contents. 2. by adding some time between each interation (100 * 1), if there's a catastrophic error, the next code will still run. -*/ - setTimeout(function(thisArr){ + setTimeout(function(thisArr){ var $iframe = $('#'+thisArr.id).contents().find("html"); $iframe.append(thisArr.script); -/// hhhmmm... some potential problems with this. non-script based output. sequence needs to be preserved for includes and inline. +// hhhmmm... some potential problems with this. non-script based output. sequence needs to be preserved for includes and inline. -/* var $div = $("<div \/>").append(thisArr.script); //may contain multiple scripts. + var $div = $("<div \/>").append(thisArr.script); //may contain multiple scripts. var scripts = ""; //all the non 'src' based script contents, in one giant lump. it's put into a 'try' to track code errors. $div.find('script').each(function(){ var $s = $(this); @@ -1852,9 +2274,9 @@ the timeout is added for multiple reasons. } }); $iframe.append("<script>try{"+scripts+"\n window.parent.scriptCallback('"+arr.owner+"','success');} catch(err){window.parent.scriptCallback('"+arr.owner+"','error: '+err);}<\/script>"); -*/ },(100 * (i + 1)),arr[i]) + },(100 * (i + 1)),arr[i]) } - } +*/ } else { //didn't get anything or what we got wasn't an array. } @@ -1862,8 +2284,8 @@ the timeout is added for multiple reasons. //is executed if one of the ROI scripts contains a javascript error (fails in the 'try'). scriptCallback : function(owner,err) { -app.u.dump("The script for "+owner+" Contained an error and most likely did not execute properly. (it failed the 'try').","warn"); -app.model.addDispatchToQ({ +_app.u.dump("The script for "+owner+" Contained an error and most likely did not execute properly. (it failed the 'try').","warn"); +_app.model.addDispatchToQ({ '_cmd':'appAccidentDataRecorder', 'owner' : owner, 'app' : '1pc', //if the API call logs the clientid, this won't be necessary. @@ -1873,7 +2295,62 @@ app.model.addDispatchToQ({ 'callback':'suppressErrors' } },'passive'); -app.model.dispatchThis('passive'); +_app.model.dispatchThis('passive'); + }, + + buildPaymentOptionsAsRadios : function(pMethods,payby) { + var + $r = $("<p>"), //the children of R are returned (the P is not). + L = pMethods.length; + +//ZERO will be in the list of payment options if customer has a zero due (giftcard or paypal) order. + if(pMethods[0].id == 'ZERO') { + $r.hide(); //hide payment options. + $r.append("<div ><input type='radio' name='want/payby' value='ZERO' checked='checked' \/>"+pMethods[0].pretty+"<\/div>"); + } + else if(L > 0) { + for(var i = 0; i < L; i += 1) { + var $div = $("<div class='headerPadding' data-app-role='paymentMethodContainer'>"); + var $label = $("<label \/>"); + if(pMethods[i].id.indexOf("GIFTCARD") === 0) { + //onClick event is added through an app-event. allows for app-specific events. + $("<button>Add</button>") + .attr({'title':'Apply this giftcard towards this purchase','data-giftcard-id':pMethods[i].id.split(':')[1]}) + .button({icons: {primary: "ui-icon-cart"},text: true}) + .addClass('isGiftcard') + .appendTo($label); + $label.append(pMethods[i].pretty).appendTo($div); + } + else if(!_app.vars.thisSessionIsAdmin && pMethods[i].id.indexOf("WALLET") === 0) { + //wallets are in the 'stored payments' section already. If they're shown here too, the input name/value will be duplicated. This duplication causes usability issues. + } + else { + //onClick event is added through an app-event. allows for app-specific events. + // ** 201405 -> the 'checked=checked' needs to occur here for IE8. + $label.append("<input type='radio' name='want/payby' value='"+pMethods[i].id+"' "+(pMethods[i].id == payby ? "checked='checked'" : "")+" />"); + $label.append((pMethods[i].id == 'CREDIT' ? 'Credit Card' : pMethods[i].pretty)); + if(pMethods[i].icons) { + $.each(pMethods[i].icons.split(' '),function(){ + $("<span \/>").addClass('paycon '+this).appendTo($label); + }); + } + $label.appendTo($div); //keep cc text short. use icons + } + $div.appendTo($r); + } + } + else { + _app.u.dump("No payment methods are available. This happens if the session is non-secure and CC is the only payment option. Other circumstances could likely cause this to happen too.",'warn'); + + $r.append("<p>It appears no payment options are currently available.<\/p>"); + if(document.location.protocol != "https:") { + $r.append("This session is <b>not secure</b>, so credit card payment is not available."); + } + } + if(payby) { + $("input[value='"+payby+"']",$r).closest('label').addClass('selected ui-state-active') + } + return $r.children(); } @@ -1887,66 +2364,44 @@ app.model.dispatchThis('passive'); renderFormats : { - - shipMethodsAsRadioButtons : function($tag,data) { -// app.u.dump('BEGIN store_cart.renderFormat.shipMethodsAsRadioButtons'); - var o = ''; - var shipName,id,isSelectedMethod,safeid; // id is actual ship id. safeid is id without any special characters or spaces. isSelectedMethod is set to true if id matches cart shipping id selected.; - var L = data.value.length; - for(var i = 0; i < L; i += 1) { - id = data.value[i].id; //shortcut of this shipping methods ID. - if(app.data.cartDetail && app.data.cartDetail.want && app.data.cartDetail.want.shipping_id == id) {isSelectedMethod = true;} - else {isSelectedMethod = false;} - - safeid = app.u.makeSafeHTMLId(data.value[i].id); - shipName = app.u.isSet(data.value[i].pretty) ? data.value[i].pretty : data.value[i].name - o += "<li class='headerPadding " - if(isSelectedMethod) - o+= ' selected '; - o += "shipcon_"+safeid; - o += "'><label><input type='radio' name='want/shipping_id' value='"+id+"' "; - if(isSelectedMethod) - o += " checked='checked' " - o += "/>"+shipName+": <span >"+app.u.formatMoney(data.value[i].amount,'$','',false)+"<\/span><\/label><\/li>"; - } - $tag.html(o); - }, //shipMethodsAsRadioButtons - - payMethodsAsRadioButtons : function($tag,data) { -// app.u.dump('BEGIN app.ext.orderCreate.renderFormats.payOptionsAsRadioButtons'); -// app.u.dump(data); - - var L = data.value.length, - o = "", //the output appended to $tag - id = ''; //recycled. - -//ZERO will be in the list of payment options if customer has a zero due (giftcard or paypal) order. - if(data.value[0].id == 'ZERO') { - $tag.hide(); //hide payment options. - $tag.append("<div ><input type='radio' name='want/payby' value='ZERO' checked='checked' \/>"+data.value[i].pretty+"<\/div>"); - } - else if(L > 0) { +//pass the cart(cart/cartid); in for the databind var. Multiple pieces of data are required for this render format (want/shipping_id and @SHIPMETHODS). + shipmethodsasradiobuttons : function($tag,data) { + var o = '',sMethods,L; + sMethods = data.value['@SHIPMETHODS']; + if(sMethods && sMethods.length) { + L = sMethods.length; for(var i = 0; i < L; i += 1) { - id = data.value[i].id; - -//onClick event is added through an app-event. allows for app-specific events. - o += "<div class='headerPadding' data-app-role='paymentMethodContainer'><label><input type='radio' name='want/payby' value='"+id+"' "; - o += " />"+data.value[i].pretty+"<\/label></div>"; - } - $tag.html(o); - if(app.data.cartDetail && app.data.cartDetail.want && app.data.cartDetail.want.payby) { - $("input[value='"+app.data.cartDetail.want.payby+"']",$tag).attr('checked','checked'); + o += "<li class='headerPadding'><label><input type='radio' name='want/shipping_id' value='"+sMethods[i].id+"' "; + o += "/>"+(sMethods[i].pretty ? sMethods[i].pretty : sMethods[i].name)+": <span >"+_app.u.formatMoney(sMethods[i].amount,'$','',false)+"<\/span><\/label><\/li>"; } } else { - app.u.dump("No payment methods are available. This happens if the session is non-secure and CC is the only payment option. Other circumstances could likely cause this to happen too.",'warn'); - - $tag.append("It appears no payment options are currently available."); - if(document.location.protocol != "https:") { - $tag.append("This is not a secure session, so credit card payment is not available."); - } + //Currently, checkout handles this on it's own. if something is added here, test checkout to make sure warnings are not appearing twice. + } + $tag.html(o); + if(data.value.want && data.value.want.shipping_id) { + $("input[value='"+data.value.want.shipping_id+"']",$tag).prop('checked','checked').closest('li').addClass('selected ui-state-active'); + } + }, //shipmethodsasradiobuttons + + paymethodsasradiobuttons : function($tag,data) { +// _app.u.dump('BEGIN _app.ext.order_create.renderFormats.payOptionsAsRadioButtons'); +// _app.u.dump(data); + var o = '', cartData,pMethods; + if(_app.data['cartDetail|'+data.value] && _app.data['appPaymentMethods|'+data.value]) { + cartData = _app.data['cartDetail|'+data.value]; + pMethods = _app.data['appPaymentMethods|'+data.value]['@methods']; + o = _app.ext.order_create.u.buildPaymentOptionsAsRadios(pMethods,cartData.want.payby); + $("button[data-giftcard-id]",o).attr('data-app-click','order_create|addGiftcardPaymethodAsPayment'); + $(":radio",o).each(function(){ + $(this).attr('data-app-change','order_create|shipOrPayMethodSelectExec'); + }); } - } //payMethodsAsRadioButtons + else { + o = $("<div \/>").anymessage({'persistent':true,'message':'In order_create.renderFormats.paymethodsasradiobuttons, cartDetail|'+data.value+' ['+( typeof _app.data['cartDetail|'+data.value] )+'] and/or appPaymentMethods|'+data.value+' ['+( typeof _app.data['appPaymentMethods|'+data.value] )+'] not found in memory. Both are required.','gMessage':true}); + } + $tag.html(o); + } //paymethodsasradiobuttons diff --git a/extensions/checkout/images/loading.gif b/extensions/checkout/images/loading.gif new file mode 100644 index 000000000..53926e058 Binary files /dev/null and b/extensions/checkout/images/loading.gif differ diff --git a/extensions/checkout/images/payment_icons_sprite.png b/extensions/checkout/images/payment_icons_sprite.png new file mode 100644 index 000000000..b7d3e38c0 Binary files /dev/null and b/extensions/checkout/images/payment_icons_sprite.png differ diff --git a/extensions/checkout/images/wait.gif b/extensions/checkout/images/wait.gif new file mode 100644 index 000000000..53926e058 Binary files /dev/null and b/extensions/checkout/images/wait.gif differ diff --git a/extensions/checkout/opc_styles.css b/extensions/checkout/opc_styles.css new file mode 100644 index 000000000..5f446a975 --- /dev/null +++ b/extensions/checkout/opc_styles.css @@ -0,0 +1,163 @@ +@charset "utf-8"; + + +/* +*** 201403 -> here to fix a bug in jqueryUI. the dialogs, when attempting to move, would jump away from the cursor in FF. This fixed it. +Put this high in the doc as a reminder to occassionally re-check if it can be removed +*/ +.ui-dialog { + position: fixed; + } + + + +/* +this file is included by the checkout extension IF _clientid = 1pc +*/ + +#appTemplates {display:none;} /* container for all templates. should be hidden */ +#appPreView {width:50%; max-width:550px; margin:0 auto;} + +/* +loading class. add class to your templates if you want a loading graphic to appear while data is requested. add only to the parent element. +loadingBG classname is removed once template is rendered. +note - wait should only be used in cases where the entire template is being reloaded. the class is NOT automatically removed ever. +note - background- are use instead of background in case element this is applied to has a bgcolor and it's !important. (like a modal parent) +*/ +.loadingBG {background-image:url(images/loading.gif) !important; background-repeat: no-repeat !important; background-position: center center; min-height:100px !important; min-width:100px;} +li.loadingBG, .wait {background:url(images/wait.gif) no-repeat top center !important; min-height:20px !important; min-width:20px;} +span.wait {display:inline-block;} + +/* global styles - added for cross-browser uniformity or usability */ + +#mainContentArea img {border:0; vertical-align: top; display:inline-block;} /* vertical-align: top; removes the whitespace sometimes added under an image. */ + +#mainContentArea button {display:inline-block; margin: 0; padding: 0; cursor:pointer;} +/* for small buttons */ +.smallButton .ui-button-text {line-height:normal; font-size:.75em;} /* don't mess with padding. will effect icon buttons */ +.smallButton .ui-button-text-icon-primary .ui-button-icon-primary {left:.25em} + +#mainContentArea p {margin-bottom:1em;} + + +#mainContentArea table { + border-collapse: collapse; + border-spacing: 0; + } +#mainContentArea td {vertical-align:top;} +#mainContentArea td.valignMiddle {vertical-align: middle;} + + + +/* feel free to delete these or override in your own .css file */ +#mainContentArea h1, #mainContentArea h2, #mainContentArea h3, #mainContentArea h4, #mainContentArea h5, #mainContentArea h6 {padding:0; margin:0;} + +/* some optional form styling +<label><span class='prompt'>prompt</span><input class='alignInput'></label> w/ alignedForm class around it on form, fieldset, whatever + */ +.alignedForm label {display:block; clear:both; margin-bottom:.2em; vertical-align:top;} +.alignedForm label:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; + } +.alignedForm .prompt {text-align:right; float:left; width:35%; display:block; margin-right:2%;} +.alignedForm .alignInput {width:60%; float:right;} /* not enforcing width is common enough that it justifies using a class to enforce it. */ + +/* chrome and safari add an outer border/glow to the input in focus. this removes it. */ +input:focus { + outline:none; + } + +input.numberInput {width:50px} +label span.prompt {display:inline-block; width:20%; margin-right:2em; vertical-align:top;} +button:focus {outline:none;} + +/* +classes used on menus that are toggled on/off. wrap offMenu around the default buttons and onMenu around buttons that get turned on. +for example, in /customer/myaccount, a 'change' button is displayed (wrapped in offMenu) for each address. onClick, 'onMenu' is toggled on, revealing save and cancel +and offMenu is toggle off, hiding the change button. +*/ +.onMenu {display:none;} +.offMenu {} + +/* some general classes used for styling templates. feel free to use these. It's not recommended you delete or rename them */ + + + +/* positioning */ + +.floatLeft {float:left;} +.floatRight {float:right;} + +.alignCenter {text-align:center;} +.alignLeft {text-align:left;} +.alignRight {text-align:right;} +.alignJustify {text-align:justify;} + +.center {margin:0 auto;} + + +/* aesthetics/usability */ + +/* added to buttons (such as place order) when they're disabled to clearly indicate they should not be clicked again. */ +.disabled { + cursor:crosshair !important; + filter: alpha(opacity=50); + opacity:0.5; + } +.formValidationError, .zwarn {color:#cc0000;} /* applied to errors displayed in form validation or generic warnings */ +.pointer {cursor:pointer;} + +/* used when an element needs to start of hidden. this is used frequently. */ +.displayNone {display:none;} + +.lineThrough {text-decoration:line-through} +.underline {text-decoration:underline; cursor:pointer} /* only use this on clickable text */ +.borderNone {border:none;} + +.clearfix {clear:both;} +.clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + +/* added to a piece of text once it becomed editable */ +.editable {} /* put this on any editable field. */ +.editEnabled {border:1px solid #ffcc00; min-width:25px; min-height:22px; width:200px; display:inline-block; padding:2px; margin-bottom:2px;} /* added to any editable field once editor is enabled. */ +.edited {border:1px solid #390;} /* added if a field is changed */ + + +.marginLeft {margin-left:1em;} +.marginRight {margin-right:1em;} +.marginTop {margin-top:1em;} +.marginBottom {margin-bottom:1em;} + +.stdMargin {margin:1em;} +.headerPadding {padding: .2em .4em;} /* for use in headings or legends that use the ui-state classes and need a little padding within. */ +.stdPadding {padding:1em;} +.smallPadding {padding:.5em;} +.fullWidth {width:100%;} + + + +.buyerLoggedIn .hideIfLoggedIn {display:none;} + +.hideIfLoggedOut {display:none;} + +.buyerLoggedIn .hideIfLoggedOut {display: block;} /* may be 'block' */ +.buyerLoggedIn span.hideIfLoggedOut, .buyerLoggedIn a.hideIfLoggedOut {display: inline;} /* ensures inline on span elements */ + +#mainContentArea .hint {font-weight:normal; font-size:.8em;} + +/* used in order history and faq (possibly other places) in a format similar to an accordian, but more than one panel can be open. */ +.appAccordianesque .ui-accordion-header {padding:.5em 2em;} + +.listStyleNone, .listStyleNone li {list-style:none;} /* apply to a ul or ol */ +.noPadOrMargin {padding:0; margin:0;} +.fluidList li {float:left; margin:1em; padding:0; display:inline-block;} \ No newline at end of file diff --git a/extensions/checkout/order_create.html b/extensions/checkout/order_create.html index 23494fcbc..0d6f4b5f6 100644 --- a/extensions/checkout/order_create.html +++ b/extensions/checkout/order_create.html @@ -1,5 +1,8 @@ <!-- +This layout is used in the ADMIN interface. It should not be selected on the storefront + + Each panel (fieldset) loads it's own template within the panelContent so that as needed, the panel can be easily updated. This also allows for messaging to be easily added to the fieldset that is NOT impacted by a template being updated. The name of the role in the fieldset matches the template (ex: chkoutPreflight = chkoutPreflightTemplate). @@ -15,43 +18,44 @@ --> -<div id='checkoutTemplate' class='checkoutFormContainer' data-app-role='checkout'> - <form action='#' data-skipvalidation='1'><!-- skipvalidation is checked for on the quick add to cart. --> - <table class='fullWidth'> - <tr> - <td class='valignTop twoColumn'> +<div id="checkoutTemplate" class="checkoutFormContainer" data-app-role="checkout"> + <form action="#" data-skipvalidation="1" novalidate onsubmit="return false;"><!-- skipvalidation is checked for on the quick add to cart. --> + <table class="fullWidth"> + <tbody><tr> + <td class="valignTop twoColumn"> - <input type='hidden' name='bill/shortcut' data-bind="var: cart(bill/shortcut); format:popVal;" /> - <input type='hidden' name='ship/shortcut' data-bind="var: cart(ship/shortcut); format:popVal;" /> + <input data-tlc="bind $var '.bill.shortcut'; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/shortcut" type="hidden"> + <input data-tlc="bind $var '.ship.shortcut'; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/shortcut" type="hidden"> + <input data-tlc="bind $var '.cart.cartid'; if(is $var --notblank;) {{apply --select=$var;}}; " name="_cartid" type="hidden"> <!-- define panel order --> - <fieldset data-app-role='chkoutPreflight' class='marginBottom ui-widget-content'> - <legend class='smallPadding' >Email / Account Login</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutPreflightTemplate; useParentData:true;'></div> + <fieldset data-app-role="chkoutPreflight" class="marginBottom ui-widget-content"> + <legend class="smallPadding">Email / Account Login</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutPreflightTemplate'; apply --append;" data-legacy-useparentdata="true" class="panelContent"></div> </fieldset> - <fieldset data-app-role='chkoutAccountCreate' class='displayNone marginBottom ui-widget-content'> - <legend class='smallPadding' >Account Creation</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutAccountCreateTemplate; '></div> + <fieldset data-app-role="chkoutAccountCreate" class="displayNone marginBottom ui-widget-content"> + <legend class="smallPadding">Account Creation</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAccountCreateTemplate'; apply --append;" class="panelContent"></div> </fieldset> - <fieldset data-app-role='chkoutAddressBill' data-app-addresstype='bill' class='marginBottom ui-widget-content'> - <legend class='smallPadding' >Billing Address</legend> - <p data-app-role='addressExists' class='displayNone clearfix'>Click the checkmark of the address you would like to use</p> + <fieldset data-app-role="chkoutAddressBill" data-app-addresstype="bill" class="marginBottom ui-widget-content"> + <legend class="smallPadding">Billing Address</legend> + <p data-app-role="addressExists" class="displayNone clearfix">Click the checkmark of the address you would like to use</p> - <div class='panelContent displayNone addressList' data-app-role='addressExists' data-bind='var: buyer(@bill); format:processList; loadsTemplate: chkoutBuyerAddressTemplate;'></div><!-- for return customers --> + <div data-tlc="bind $var '.@BILL'; controller#loop --templateid='chkoutBuyerAddressTemplate'; if (is $var --notblank;) {{apply --append;}};" class="panelContent displayNone addressList" data-app-role="addressExists"></div><!-- for return customers --> - <div class='clearfix marginBottom' data-app-role='addressExists'><button data-app-event='orderCreate|showBuyerAddressAdd' data-app-addresstype='bill'>Add New Address</button></div> + <div class="clearfix marginBottom" data-app-role="addressExists"><button class="applyButton" data-app-click="order_create|adminAddressCreateUpdateShow" data-mode="create" data-app-addresstype="bill">Add New Address</button></div> - <div class='panelContent' data-app-role='addressNew' data-bind='format:loadsTemplate; loadsTemplate: chkoutAddressBillTemplate;'></div><!-- for new customers --> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAddressBillTemplate'; apply --append;" class="panelContent" data-app-role="addressNew"></div><!-- for new customers --> - <div data-app-role='billToShipContainer' > + <div data-app-role="billToShipContainer"> <label> - <input type='checkbox' name='want/bill_to_ship' data-bind="var: cart(want/bill_to_ship); format:popVal; hideZero:false;" checked='checked' data-app-event='orderCreate|tagAsBillToShip' /> + <input data-tlc="bind $var '.want.bill_to_ship'; if(is $var --notblank;) {{apply --select=$var;}}; " name="want/bill_to_ship" checked="checked" class="applyAnycb" data-app-change="order_create|tagAsBillToShip" type="checkbox"> ship to billing address </label> </div> @@ -59,88 +63,93 @@ - <fieldset data-app-role='chkoutAddressShip' data-app-addresstype='ship' class='displayNone marginBottom ui-widget-content'> - <legend class='smallPadding' >Shipping Address</legend> - <div class='panelContent displayNone addressList' data-app-role='addressExists' data-bind='var: buyer(@ship); format:processList; loadsTemplate: chkoutBuyerAddressTemplate;'></div><!-- for return customers --> - <div class='panelContent' data-app-role='addressNew' data-bind='format:loadsTemplate; loadsTemplate: chkoutAddressShipTemplate;'></div><!-- for new customers --> - <div class='clearfix' data-app-role='addressExists'><button data-app-event='orderCreate|showBuyerAddressAdd' data-app-addresstype='ship'>Add New Shipping Address</button></div> + <fieldset data-app-role="chkoutAddressShip" data-app-addresstype="ship" class="displayNone marginBottom ui-widget-content"> + <legend class="smallPadding">Shipping Address</legend> + <div data-tlc="bind $var '.@SHIP'; controller#loop --templateid='chkoutBuyerAddressTemplate'; if (is $var --notblank;) {{apply --append;}};" class="panelContent displayNone addressList" data-app-role="addressExists"></div><!-- for return customers --> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAddressShipTemplate'; apply --append;" class="panelContent" data-app-role="addressNew"></div><!-- for new customers --> + <div class="clearfix" data-app-role="addressExists"><button class="applyButton" data-app-click="order_create|showBuyerAddressAdd" data-app-addresstype="ship">Add New Shipping Address</button></div> </fieldset> - <fieldset data-app-role='chkoutMethodsShip' class='marginBottom ui-widget-content'> - <legend class='smallPadding' >Shipping Methods</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutMethodsShipTemplate;'></div> + <fieldset data-app-role="chkoutMethodsShip" class="marginBottom ui-widget-content"> + <legend class="smallPadding">Shipping Methods</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutMethodsShipTemplate'; apply --append;" class="panelContent"></div> </fieldset> - <fieldset data-app-role='chkoutMethodsPay' class='marginBottom ui-widget-content'> - <legend class='smallPadding' >Payment Choices</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutMethodsPayTemplate;'></div> + <fieldset data-app-role="chkoutMethodsPay" class="marginBottom ui-widget-content"> + <legend class="smallPadding">Payment Choices</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutMethodsPayTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- totals et all --> - <fieldset data-app-role='chkoutNotes' class='marginBottom ui-widget-content'> - <legend class='smallPadding' >Order Notes/Special Instructions</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutNotesTemplate;'></div> + <fieldset data-app-role="chkoutNotes" class="marginBottom ui-widget-content"> + <legend class="smallPadding">Order Notes/Special Instructions</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutNotesTemplate'; apply --append;" class="panelContent"></div> </fieldset> </td> - <td class='valignTop twoColumn'> + <td class="valignTop twoColumn"> <!-- line items --> - <fieldset data-app-role='chkoutCartItemsList' class='marginBottom ui-widget-content'> - <legend class='smallPadding' >Contents</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutCartContentsTemplate;'></div> - - - <legend class='ui-widget-header ui-corner-all'>Add Item to Order</legend> - <input type="hidden" name="add" value="yes" /> - <input type="hidden" name="override" value="1" /> + <fieldset data-app-role="chkoutCartItemsList" class="marginBottom ui-widget-content"> + <legend class="smallPadding">Contents</legend> - <label><span>Qty:</span><input type="text" name="qty" size="3" value="1" /></label> - <label><span>Product id:</span><input type='text' name='sku' size='10' /></label> - <label><span>Price: </span><input type='number' class='price' size='5' name='price' step='0.01' min='0' /></label> - <button data-app-event="orderCreate|cartItemAddFromForm">Add</button> - <hr /> - <button data-app-event="orderCreate|cartItemAddWithChooser">Use Chooser</button> <span class='hint'>use this for an easier method to select items with variations</span> - <hr /> - Show previous orders for re-order: - ORDERS GO HERE. - + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutCartContentsTemplate'; apply --append;" class="panelContent marginBottom"></div> </fieldset> <!-- totals et all --> - <fieldset data-app-role='chkoutCartSummary' class='marginBottom ui-widget-content'> - <legend class='smallPadding' >Summary</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutCartSummaryTemplate;'></div> + <fieldset data-app-role="chkoutCartSummary" class="marginBottom ui-widget-content"> + <legend class="smallPadding">Summary</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutCartSummaryTemplate'; apply --append;" class="panelContent"></div> </fieldset> + + +<!-- moved these out of the fieldsets for the adminUI. noticed if you update a field w/ a blur, such as zip, then push save, the blur event triggers the panel to clear prior to the click being triggered --> +<section id="checkoutButtons"> + + <div class="buttonset alignRight"> + <button class="floatLeft applyButton" data-app-click="order_create|adminCartRemoveFromSession" title="This will remove the cart from your session. It will NOT delete the cart.">Remove Cart</button> + <button class="applyButton" data-app-role="saveButton" data-app-click="order_create|cartOrderSave" title="Save changes without creating an order. This will NOT save credit card numbers.">Save <span class="numChanges"></span> Changes</button> + <button class="applyButton ui-state-highlight" data-app-click="order_create|execCartOrderCreate">Create Order</button> + </div> +</section> + + + + </td> </tr> -</table> +</tbody></table> </form> </div> -<section id='chkoutPreflightTemplate'> - -<h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email); defaultVar: cart(customer/login); format:text;"></h4> +<section id="chkoutPreflightTemplate"> -<div data-app-role='login'> + <h4 data-tlc="bind $var '.bill.email'; if(is $var --blank;) {{bind $var '.customer.login'; }}; if (is $var --notblank;) {{apply --append;}};" class="displayNone" data-app-role="username"></h4> + + <div data-app-role="login" class="clearfix marginBottom"> + + <input data-tlc="bind $var '.bill.email'; if(is $var --blank;) {{bind $var '.customer.login'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " required name="bill/email" size="30" placeholder="email address" data-app-blur="order_create|execBuyerEmailUpdate" type="email"> <button class="applyButton" data-app-click="order_create|adminCustomerLookup">Lookup</button><br> + <label class="accountCreateContainer"><input name="want/create_customer" class="applyAnycb" data-app-change="order_create|tagAsAccountCreate" type="checkbox">Create account</label> + </div> - <input type='email' required='required' name='bill/email' size='30' placeholder="email address" data-bind="var:cart(bill/email); defaultVar:cart(customer/login); format:popVal;" data-app-event='orderCreate|execBuyerEmailUpdate' /> <button data-app-event="orderCreate|adminCustomerLookup">Lookup</button><br /> - <label class='accountCreateContainer'><input type='checkbox' name='want/create_customer' data-app-event='orderCreate|tagAsAccountCreate' />Create customer account</label> -</div> + <div data-tlc="bind $var '.@ORDERS.length'; if(is $var --notblank;) {{ apply --show; }}; " class="displayNone"> + <h2 data-input-click="show-selector" data-show-selector=".orderHistory" class="lookLikeLink">» Order history</h2> + <ol data-tlc="bind $var '.@ORDERS'; controller#loop --templateid='chkoutOrderHistoryLineItem'; if (is $var --notblank;) {{apply --append;}};" class="displayNone orderHistory"></ol> + </div> </section> @@ -157,27 +166,27 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) This template is also used in the myAccount page, which is why a default using _ is present. --> -<section id='chkoutAddressBillTemplate'> +<section id="chkoutAddressBillTemplate" class="addressForm"> - <div><input type='text' placeholder='first name' name='bill/firstname' required='required' value='' data-bind='var: cart(bill/firstname); defaultVar: cart(bill/firstname); format:popVal;' /></div> - <div><input type='text' placeholder='last name' name='bill/lastname' required='required' value='' data-bind='var: cart(bill/lastname); defaultVar: cart(bill/lastname); format:popVal;' /></div> + <div><input data-tlc="bind $var '.bill.firstname'; if(is $var --blank;) {{bind $var '.bill_firstname'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="bill/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.bill.lastname'; if(is $var --blank;) {{bind $var '.bill_lastname'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="bill/lastname" required value="" type="text"></div> - <div class='bill_company'><input type='text' name='bill/company' placeholder='company' value='' data-bind='var: cart(bill/company); defaultVar: cart(bill/company); format:popVal;' /></div><!-- class is added so it can be easily disabled w/ css --> + <div class="bill_company"><input data-tlc="bind $var '.bill.company'; if(is $var --blank;) {{bind $var '.bill_company'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> - <div><input type='text' name='bill/address1' placeholder='address' required='required' value='' data-bind='var: cart(bill/address1); defaultVar: cart(bill/address1); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.address1'; if(is $var --blank;) {{bind $var '.bill_address1'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/address1" placeholder="address" required value="" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='bill/address2' placeholder='address 2' value='' data-bind='var: cart(bill/address2); defaultVar: cart(bill/address2); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.address2'; if(is $var --blank;) {{bind $var '.bill_address2'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/address2" placeholder="address 2" value="" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='bill/city' placeholder='city' required='required' value='' data-bind='var: cart(bill/city); defaultVar: cart(bill/city); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.city'; if(is $var --blank;) {{bind $var '.bill_city'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/city" placeholder="city" required value="" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='bill/region' placeholder='state/region' required='required' size='5' value='' data-bind='var: cart(bill/region); defaultVar: cart(bill/region); format:popVal;' maxlength='20' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.region'; if(is $var --blank;) {{bind $var '.bill_region'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/region" placeholder="state/region" required size="5" value="" maxlength="20" data-app-blur="order_create|execAddressUpdate" type="text"></div> <!-- postal not required for international. don't add it. --> - <div><input type='text' name='bill/postal' placeholder='zip/postal code' required='required' size='14' value='' data-bind='var: cart(bill/postal); defaultVar: cart(bill/postal); format:popVal;' maxlength='10' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.postal'; if(is $var --blank;) {{bind $var '.bill_postal'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div class='billCountry' data-app-role='billCountry'><select name='bill/countrycode' placeholder='country' data-bind='var: cart(bill/countrycode); defaultVar: cart(bill/countrycode); defaultValue:US; format:countriesAsOptions; extension: cco;forceRender:1;' required='required' data-app-event="orderCreate|execCountryUpdate" ></select></div> + <div class="billCountry" data-app-role="billCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='bill' --legacy;" data-legacy-useparentdata="true" name="bill/countrycode" placeholder="country" required="required" data-app-change="order_create|execCountryUpdate"></select></div> - <div><input type='tel' name='bill/phone' placeholder='phone number' required='required' value='' data-bind='var: cart(bill/phone); defaultVar: cart(bill/phone); format:popVal;' /> <span class='hint zhint'>in case of billing/delivery problems</span></div> + <div><input data-tlc="bind $var '.bill.phone'; if(is $var --blank;) {{bind $var '.bill_phone'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/phone" placeholder="phone number" required value="" type="tel"> <span class="hint zhint">in case of billing/delivery problems</span></div> </section> @@ -190,44 +199,44 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) don't add required to any inputs because if bill to ship is checked, NONE of these fields are required/populated. --> -<section id='chkoutAddressShipTemplate'> +<section id="chkoutAddressShipTemplate" class="addressForm"> - <div><input type='text' placeholder='first name' name='ship/firstname' required='required' value='' data-bind='var: cart(ship/firstname); defaultVar: cart(ship/firstname); format:popVal;' /></div> - <div><input type='text' placeholder='last name' name='ship/lastname' required='required' value='' data-bind='var: cart(ship/lastname); defaultVar: cart(ship/lastname); format:popVal;' /></div> + <div><input data-tlc="bind $var '.ship.firstname'; if(is $var --blank;) {{bind $var '.ship_firstname'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="ship/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.ship.lastname'; if(is $var --blank;) {{bind $var '.ship_lastname'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="ship/lastname" required value="" type="text"></div> - <div class='bill_company'><input type='text' name='ship/company' placeholder='company' value='' data-bind='var: cart(ship/company); defaultVar: cart(ship/company); format:popVal;' /></div><!-- class is added so it can be easily disabled w/ css --> + <div class="bill_company"><input data-tlc="bind $var '.ship.company'; if(is $var --blank;) {{bind $var '.ship_company'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> - <div><input type='text' name='ship/address1' placeholder='address' required='required' value='' data-bind='var: cart(ship/address1); defaultVar: cart(ship/address1); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.address1'; if(is $var --blank;) {{bind $var '.ship_address1'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address1" placeholder="address" required value="" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='ship/address2' placeholder='address 2' value='' data-bind='var: cart(ship/address2); defaultVar: cart(ship/address2); format:popVal;' /></div> + <div><input data-tlc="bind $var '.ship.address2'; if(is $var --blank;) {{bind $var '.ship_address2'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address2" placeholder="address 2" value="" type="text"></div> - <div><input type='text' name='ship/city' placeholder='city' required='required' value='' data-bind='var: cart(ship/city); defaultVar: cart(ship/city); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.city'; if(is $var --blank;) {{bind $var '.ship_city'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/city" placeholder="city" required value="" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='ship/region' placeholder='state/region' required='required' size='5' value='' data-bind='var: cart(ship/region); defaultVar: cart(ship/region); format:popVal;' maxlength='20' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.region'; if(is $var --blank;) {{bind $var '.ship_region'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/region" placeholder="state/region" required size="5" value="" maxlength="20" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='ship/postal' placeholder='zip/postal code' required='required' size='14' value='' data-bind='var: cart(ship/postal); defaultVar: cart(ship/postal); format:popVal;' maxlength='10' data-app-event='orderCreate|execAddressUpdate'/></div> + <div><input data-tlc="bind $var '.ship.postal'; if(is $var --blank;) {{bind $var '.ship_postal'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div class='shipCountry' data-app-role='shipCountry'><select name='ship/countrycode' placeholder='country' data-bind='var: cart(ship/countrycode); defaultVar: cart(ship/countrycode); defaultValue:US; format:countriesAsOptions; extension: cco;forceRender:1;' data-app-event="orderCreate|execCountryUpdate" ></select></div> + <div class="shipCountry" data-app-role="shipCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='ship' --legacy;" data-legacy-useparentdata="true" name="ship/countrycode" placeholder="country" data-app-change="order_create|execCountryUpdate"></select></div> </section> <!-- a panel that only appears in 'nice' --> -<section id='chkoutAccountCreateTemplate'> +<section id="chkoutAccountCreateTemplate"> -<div><input type='password' data-minlength='8' placeholder='password' required='required' name='want/new_password' size='12' data-bind='var: cart(want/new_password); format:popVal;' /> <span class='hint'>must be at least 8 characters</span></div> -<div><input type='password' data-minlength='8' placeholder='verify password' required='required' name='want/new_password2' size='12' data-bind='var: cart(want/new_password2); format:popVal;' /></div> +<div><input data-tlc="bind $var '.want.new_password'; if(is $var --notblank;) {{apply --select=$var;}}; " data-minlength="8" placeholder="password" required name="want/new_password" size="12" type="password"> <span class="hint">must be at least 8 characters</span></div> +<div><input data-tlc="bind $var '.want.new_password2'; if(is $var --notblank;) {{apply --select=$var;}}; " data-minlength="8" placeholder="verify password" required name="want/new_password2" size="12" type="password"></div> <label>Recovery Question -<select name='want/recovery_hint' data-bind='var: cart(want/recovery_hint); format:popVal;'> - <option value='2'>Name of your favorite childhood pet?</option> - <option value='3'>City you were born in?</option> - <option value='4'>Last name of your best friend growing up?</option> - <option value='5'>Last city you lived in?</option> +<select data-tlc="bind $var '.want.recovery_hint'; if(is $var --notblank;) {{apply --select=$var;}}; " name="want/recovery_hint"> + <option value="2">Name of your favorite childhood pet?</option> + <option value="3">City you were born in?</option> + <option value="4">Last name of your best friend growing up?</option> + <option value="5">Last city you lived in?</option> </select> </label> -<input type='text' placeholder='recovery answer' required='required' value='' name='want/recovery_answer' maxlength='20' size='20' data-bind='var: cart(want/recovery_answer); format:popVal;' /></label> +<input data-tlc="bind $var '.want.recovery_answer'; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="recovery answer" required value="" name="want/recovery_answer" maxlength="20" size="20" type="text"> </section> @@ -239,8 +248,23 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) messaging are hidden by default, then displayed if needed. keeps panel from being jittery. --> -<div id='chkoutMethodsShipTemplate'> - <ul class='noPadOrMargin listStyleNone' data-bind='var: cart(@SHIPMETHODS); format:shipMethodsAsRadioButtons; extension: orderCreate;' data-app-event='orderCreate|addTriggerShipMethodUpdate'></ul> +<div id="chkoutMethodsShipTemplate"> + <ul data-tlc="bind $var '.'; order_create#shipmethodsasradiobuttons --legacy;" data-legacy-useparentdata="true" class="noPadOrMargin listStyleNone"></ul> + <hr /> + <p>Use the form below to set a new shipping amount. Selected method above will be ignored.</p> + <div data-app-role='customShipMethodContainer'> + <!-- ### TODO -> this needs an 'undo' feature because selecting a new method doesn't save over this --> + <select data-tlc="bind $var '.sum.shp_carrier'; if(is $var --notblank;) {{apply --select=$var;}}; " name="sum/shp_carrier" class='skipTrack'> + <option value="SLOW">slow</option> + <option value="FAST">fast</option> + <option value="CPU">customer pickup</option> + <option value="ELSE">other</option> + </select> + <input data-tlc="bind $var '.sum.shp_method'; if(is $var --notblank;) {{apply --select=$var;}}; " class='skipTrack' name="sum/shp_method" size="15" type="text"> + <input data-tlc="bind $var '.sum.shp_total'; if(is $var --notblank;) {{apply --select=$var;}}; " class="smallInput skipTrack" name="sum/shp_total" size="5" step="0.01" min="0" type="number"> + <button class='applyButton' data-app-click="order_create|cartShippingSave">Apply</button> + </div> + </div> @@ -256,34 +280,35 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) --> -<div id='chkoutMethodsPayTemplate'> +<div id="chkoutMethodsPayTemplate"> - <div class='giftCardContainer' data-app-role="giftcardContainer"> - <label for='giftcardCode'>Gift Certificate Code:</label> - <input type='text' name='giftcard' size='16' data-app-event='orderCreate|addTriggerButtonClick' /> - <button data-app-event='orderCreate|execGiftcardAdd'>add</button> - <small data-app-role='giftcardHint' class='zhint hint displayNone'>if you wish to combine gift cards with another payment method, enter them here</small> + <div class="giftCardContainer" data-app-role="giftcardContainer"> + <label for="giftcardCode">Gift Certificate Code:</label> + <input name="giftcard" size="16" class='skipTrack' data-input-keyup="trigger-button-id" data-input-format="alphanumeric" data-trigger-button-id="execGiftcardAdd" type="text"> + <button class="applyButton" data-app-click="order_create|execGiftcardAdd" data-button-id="execGiftcardAdd">add</button> + <small data-app-role="giftcardHint" class="zhint hint displayNone">if you wish to combine gift cards with another payment method, enter them here</small> </div> - <div data-app-role='paymentQContainer' class='marginBottom'> - <ul class='noPadOrMargin listStyleNone' data-bind='var: cart(@PAYMENTQ); format:processList; loadsTemplate:cartPaymentQTemplate;'></ul> + <div data-app-role="paymentQContainer" class="marginBottom"> + <ul data-tlc="bind $var '.@PAYMENTQ'; controller#loop --templateid='cartPaymentQTemplate'; if (is $var --notblank;) {{apply --append;}};" class="noPadOrMargin listStyleNone"></ul> </div> <!-- used in paypal transactions to cancel as paypal --> - <div data-app-event='orderCreate|execChangeFromPayPal' class='displayNone pointer zlink'> + <div data-app-click="order_create|execChangeFromPayPal" class="displayNone pointer zlink"> Choose Alternate Payment Method </div> <!-- more payment types is first but, when applicable, stored payments is shown. That way stored payments are easily selected but it's hard to miss that other payment choices are available. --> - <div data-app-role='paymentOptionsContainer' data-app-event="orderCreate|addTriggerPayMethodUpdate"> + <div data-app-role="paymentOptionsContainer" data-app-event="order_create|addTriggerPayMethodUpdate"> - <h2 data-app-role='nonStoredPaymentsHeader' class='displayNone'>More Payment Choices</h2> - <div data-app-role='nonStoredPaymentsContent'> - <div data-bind='var: getPaymentMethods(@methods); format:payMethodsAsRadioButtons; extension: orderCreate;'></div> + <h2 data-app-role="nonStoredPaymentsHeader" class="displayNone">More Payment Choices</h2> + <div data-app-role="nonStoredPaymentsContent"> + <div data-tlc="bind $var '.cart.cartid'; order_create#paymethodsasradiobuttons --legacy;"></div> </div> - <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payments</h2> - <div data-app-role='storedPaymentsContent' class='displayNone' data-bind="var: buyerWalletList(@wallets); format:processList; loadsTemplate: chkoutBuyerWalletListItem;"></div> + <h2 data-app-role="storedPaymentsHeader" class="displayNone">Stored Payments</h2> + <!-- The # of children in the storedPaymentContents triggers wallet display. Do not add any children to this div. --> + <div data-tlc="bind $var '.@WALLETS'; controller#loop --templateid='chkoutBuyerWalletListItem'; if (is $var --notblank;) {{apply --append;}};" data-app-role="storedPaymentsContent" class="displayNone"></div> </div> @@ -300,33 +325,59 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment the defaultVar on prodName & image is for promotions, which have a 'description' attribute --> <table> -<tr id='chkoutCartItemTemplate'> - <td><img class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL; defaultVar: product(%attribs.zoovy:prod_image1);' width='50' height='50' /></td> +<tbody><tr id="chkoutCartItemTemplate"> + <td><img data-tlc="bind $var '.%attribs.zoovy:prod_thumb'; if(is $var --blank;) {{bind $var '.%attribs.zoovy:prod_image1'; }}; if (is $var --notblank;) {{ apply --img --media=$var --width=50 --height=50 --bgcolor='#ffffff' --replace;}};" class="prodThumb" height="50" width="50"></td> <td> - <div class='prodName' data-bind='var: product(prod_name); format:text; defaultVar: description;'></div> - <div class='stid' data-bind='var: product(sku); format:text; className: stid; pretext: Sku: ;'></div> - <div class='prodLatency' data-bind='var:product(%attribs.zoovy:ship_latency); format:text; pretext:Normally ships in ; posttext: day(s);'></div> - <div class='prodOptions' data-bind='var: variations(%options); format:selectedOptionsDisplay;'></div> + <div data-tlc="bind $var '.prod_name'; if(is $var --blank;) {{bind $var '.description'; }}; if (is $var --notblank;) {{apply --append;}};" class="prodName"></div> + <div data-tlc="bind $var '.sku'; if (is $var --notblank;) {{format --prepend='Sku: '; apply --add --class='stid'; apply --append;}};" class="stid"></div> + <div data-tlc="bind $var '.%attribs.zoovy:ship_latency'; if (is $var --notblank;) {{format --prepend='Normally ships in '; format --append=' day(s)'; apply --append;}};" class="prodLatency"></div> + + <div data-tlc="bind $var '.%options'; controller#selectedoptionsdisplay --legacy;" class="prodOptions alignRight"></div></td> + <td><input data-tlc="bind $var '.qty'; apply --select=$var;" class="smallInput skipTrack" name="qty" step="1" size="3" min="0" data-app-change="order_create|cartItemUpdateExec" type="number"></td> + <td class="alignRight"> + <input data-tlc="bind $var '.price'; apply --select=$var;" class="smallInput skipTrack" name="price" step=".01" size="8" min="0" data-app-change="order_create|cartItemUpdateExec" type="number"> </td> - <td class='alignRight'><span data-bind='var: product(qty); format:text;'></span></td> - <td class='alignRight'><span data-bind='var: product(price); format:money; currencySign: $; hideZero:false; pretext: x ;'></span></td> - <td class='alignRight'><span data-bind='var: product(extended); format:money; currencySign: $; hideZero:false; pretext: = ;'></span></td> + <td class="alignRight"><span data-tlc="bind $var '.extended'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='= '; apply --append;}};"></span></td> + <td><button data-tlc="bind $var '.'; cco#cartitemremovebutton --legacy;" data-legacy-useparentdata="true" class="floatRight removeButton" data-app-click="cco|cartItemRemove">Remove Item From Cart</button></td> </tr> -</table> +</tbody></table> -<section id='chkoutCartContentsTemplate'> -<table class='fullWidth gridTable'> -<thead> -<tr> - <th colspan='2' class='alignLeft'>product information</th> - <th class='alignRight'>qty</th> - <th class='alignRight'>price</th> - <th class='alignRight'>item total</th> -</tr> -</thead> -<tbody data-bind='var: cart(@ITEMS); format:processList; loadsTemplate:chkoutCartItemTemplate;'></tbody> -</table> +<section data-tlc="bind $var '.cart.cartid'; apply --attrib='data-cartid'; " id="chkoutCartContentsTemplate" data-template-role="cart"> + <div data-tlc="bind $var '.cart.cartid'; if (is $var --notblank;) {{format --prepend='Cart ID: '; apply --append;}};" class="marginBottom smallButton"></div> + <table class="fullWidth gridTable applyAnytable marginBottom"> + <thead> + <tr> + <th colspan="2" class="alignLeft">product information</th> + <th class="alignRight">qty</th> + <th class="alignRight">price</th> + <th class="alignRight">item total</th> + <th></th> + </tr> + </thead> + <tbody data-tlc="bind $var '.@ITEMS'; controller#loop --templateid='chkoutCartItemTemplate'; if (is $var --notblank;) {{apply --append;}};" data-app-role="cartItemsTbody"></tbody> + </table> + + <div class="clearfix marginBottom"> + <h4 class="floatLeft">Add Item to Order : </h4> + <button class="applyButton floatLeft marginLeft" data-app-click="order_create|cartItemAddWithChooser">Chooser</button> + <button class="applyButton floatLeft marginLeft" data-show-selector=".cartItemAddDirectShow" data-input-click="show-selector">Direct Add</button> + </div> + + + + + <div class="displayNone cartItemAddDirectShow" data-add2cart-role="container"> + <input name="add" value="yes" type="hidden"> + <input name="override" value="1" type="hidden"> + <input data-tlc="bind $var '.cart.cartid'; if(is $var --notblank;) {{apply --select=$var;}}; " name="_cartid" value="" type="hidden"><!-- used in store_product.u.handleAddToCart --> + + <label><span>Qty:</span><input class="smallInput skipTrack" step="1" min="0" name="qty" size="3" value="1" type="number"></label> + <label><span>SKU:</span><input name="sku" class='skipTrack' size="10" type="text"></label><!-- do not force 'pid' formatting, this could be a sku --> + <label><span>Price: </span><input class="price smallInput skipTrack" size="5" name="price" step="0.01" min="0" type="number"></label> + <span class="applyButton" data-app-click="order_create|cartItemAddFromForm">Add</span> + </div> + </section> @@ -336,35 +387,36 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment -<section id='chkoutCartSummaryTemplate'> +<section id="chkoutCartSummaryTemplate"> - <div data-bind="var: cart(sum/items_total); format:money; className:orderSubtotal; hideZero:false; currencySign: $; pretext:Subtotal: ; "></div> - <div data-bind='var: cart(sum/tax_total); format:money; className:orderTax; hideZero:true;currencySign: $; pretext:Tax: ; '></div> - <div data-bind='var: cart(want/shipping_id); format:shipInfoById; className:orderShipping; hideZero:false; extension:cco;'></div> - <div data-bind='var: cart(sum/hnd_total); format:money; className:hndTotal; currencySign: $; pretext:Handling: ; '></div> - <div data-bind='var: cart(sum/order_total); format:money; className:orderTotal; hideZero:false; currencySign: $; pretext:Order Total: ; '></div> - <div data-bind='var: cart(sum/gfc_total); format:money; className:orderGiftcardTotal; currencySign: $; pretext:Giftcard(s): ; '></div> - <div data-bind='var: cart(sum/pnt_total); format:money; className:rewardPointsTotal; currencySign: $; pretext:Reward Points: ; '></div> - <div data-bind='var: cart(sum/rmc_total); format:money; className:returnsCreditTotal; currencySign: $; pretext:Returns Credit: ; '></div> - <div data-bind='var: cart(sum/spc_total); format:money; className:spcTotal; currencySign: $; pretext:Specialty: ; '></div> - - <div data-bind='var: cart(sum/balance_due_total); format:orderBalance; className:orderBalanceDue; hideZero:false; currencySign: $; pretext:Balance Due: ; extension:cco;'></div> - - <div class='couponEntryContainer clearfix marginBottom' data-app-role='couponContainer'> - <label for='coupon'>Coupon/Promo Code:</label> - <input type='text' name='coupon' size='8' data-app-event='orderCreate|addTriggerButtonClick' /> - <button data-app-event="orderCreate|execCouponAdd" >add</button> + <div data-tlc="bind $var '.sum.items_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Subtotal: '; apply --add --class='orderSubtotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.tax_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Tax: '; apply --add --class='orderTax'; apply --append;}};"></div> + + <div> + <span data-tlc="bind $method '.sum.shp_method'; apply --append;"></span> + <span data-tlc="bind $carrier '.sum.shp_carrier'; if (is $var --notblank;) {{format --prepend='(' --append='): '; apply --append;}};"></span> + <span data-tlc="bind $var '.sum.shp_total'; if (is $var --notblank;) {{format --currency='USD' --prepend=': '; apply --append;}};"></span> + </div> + + <div data-tlc="bind $var '.sum.hnd_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Handling: '; apply --add --class='hndTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.order_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Order Total: '; apply --add --class='orderTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.gfc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Giftcard(s): '; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.pnt_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Reward Points: '; apply --add --class='rewardPointsTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.rmc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Returns Credit: '; apply --add --class='returnsCreditTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.spc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Specialty: '; apply --add --class='spcTotal'; apply --append;}};"></div> + + <div class='orderBalanceDue' data-tlc="bind $var '.sum.balance_due_total'; cco#orderbalance --hidezero='false' --currencysign='$' --legacy;"></div> + + <div class="couponEntryContainer clearfix marginBottom" data-app-role="couponContainer"> + <label for="coupon">Coupon/Promo Code:</label> + <input name="coupon" size="8" data-input-keyup="trigger-button-id" data-trigger-button-id="execCouponAdd" data-input-format="alphanumeric" type="text"> + <span class="applyButton" data-app-click="order_create|execCouponAdd" data-button-id="execCouponAdd">add</span> + </div> + <!-- will appear if company field is populated AND payment method is NOT PO --> + <div data-app-role="referenceNumber" class="displayNone"> + <label>Purchase Order/Reference #: </label> + <input type'text'="" name="want/reference_number" size="12"> </div> - - - <button data-app-event="orderCreate|execCartOrderCreate"> - Place Order - </button> - -<div data-app-role='referenceNumber' class='displayNone'> - <label>Purchase Order/Reference #: </label> - <input type'text' name='want/reference_number' size='12' /> -</div> </section> @@ -376,13 +428,13 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment - -<address id='chkoutBuyerAddressTemplate' class='ui-widget ui-widget-content ui-corner-all stdPadding'> - <div data-bind="var:address(bill/address1); defaultVar: address(ship/address1); format:text;"></div> - <div data-bind="var:address(bill/postal); defaultVar: address(ship/postal); format:text;"></div> - <div class='clearfix'> - <button class='floatRight' data-app-event='orderCreate|execBuyerAddressSelect'>Use This Address</button> - <button class='floatRight marginRight' data-app-event="orderCreate|showBuyerAddressUpdate">Edit This Address</button> +<!-- there is display logic looking for the number of address elements in addressExists. do not change element try w/out updating display logic. --> +<address id="chkoutBuyerAddressTemplate" class="ui-widget ui-widget-content ui-corner-all stdPadding"> + <div data-tlc="bind $var '.bill_address1'; if(is $var --blank;) {{bind $var '.ship_address1'; }}; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.bill_postal'; if(is $var --blank;) {{bind $var '.ship_postal'; }}; if (is $var --notblank;) {{apply --append;}};"></div> + <div class="clearfix"> + <button class="floatRight applyButton" data-app-role="addressSelectButton" data-app-click="order_create|execBuyerAddressSelect" data-icon="false" data-icon-primary="ui-icon-check">Use This Address</button> + <button class="floatRight marginRight applyButton" data-app-role="addressEditButton" data-app-click="order_create|adminAddressCreateUpdateShow" data-icon="false" data-icon-primary="ui-icon-pencil" data-mode="update">Edit This Address</button> </div> </address> @@ -391,21 +443,22 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment + <ul> - <li id='cartPaymentQTemplate'> - <span data-bind="var:payment(TN); format:text;"></span> - <span class='marginLeft' data-bind="var:payment($$); format:money; currencySign: $; hideZero:false;"></span><span data-bind="var:payment($#); format:money; currencySign: $; pretext:/;"></span> -<!-- <button class='marginLeft' title='Remove this payment method'>X</button> --> + <li id="cartPaymentQTemplate"> + <span data-tlc="bind $var '.TN'; if (is $var --notblank;) {{apply --append;}};"></span> + <span data-tlc="bind $var '.$$'; if (is $var --notblank;) {{format --currency='USD'; apply --append;}};" class="marginLeft"></span><span data-tlc="bind $var '.$#'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='/'; apply --append;}};"></span> +<!-- <button class='marginLeft applyButton' title='Remove this payment method'>X</button> --> </li> </ul> <!-- radio name is same as rest of payments so that only 1 can be selected and form still easily passes validation --> -<div id='chkoutBuyerWalletListItem'> +<div id="chkoutBuyerWalletListItem"> <label> - <input type='radio' name='want/payby' value='' data-bind="var: wallet(ID); format:setVal;" /> - <span data-bind="var: wallet(TD); format:text;"></span> - <span data-bind="var: wallet(TD); format: walletName2Icon; extension:cco;"></span> + <input data-tlc="bind $var '.ID'; apply --inputvalue; " name="want/payby" value="" type="radio"> + <span data-tlc="bind $var '.TD'; if (is $var --notblank;) {{apply --append;}};"></span> + <span data-tlc="bind $var '.TD'; cco#walletnameintoicon --legacy;"></span> </label> </div> @@ -415,9 +468,9 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment do NOT change the input name or id or checkout will likely break. --> -<div id='chkoutNotesTemplate'> +<div id="chkoutNotesTemplate"> <p>Please include any special instructions or comments here:</p> -<textarea class='chkoutOrderNotes fullWidth' name='want/order_notes' data-app-event='orderCreate|execCartSet' data-bind='var: cart(want/order_notes); format:popVal;'></textarea> +<textarea data-tlc="bind $var '.want.order_notes'; if(is $var --notblank;) {{apply --select=$var;}}; " class="chkoutOrderNotes fullWidth" name="want/order_notes" data-app-blur="order_create|execCartSet"></textarea> </div> @@ -429,100 +482,87 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment -<!-- used after a successful checkout. --> +<!-- used after a successful order create. --> -<div id='chkoutCompletedTemplate' class='checkoutSuccess'> +<div id="chkoutCompletedTemplate" class="checkoutSuccess"> - <div class='floatRight ocmThirdParty'> - <h2>What next?</h2> -<!-- the twitter and facebook actions are added post checkout. The order contents are included as part of the message --> - <div class='ocm ocmFacebookComment pointer zlink marginBottom checkoutSprite '></div> - <div class='ocm ocmTwitterComment pointer zlink marginBottom checkoutSprit ' ></div> - <div class='ocm ocmContinue pointer zlink marginBottom checkoutSprite'></div> - - </div> - - - <div class='orderSummaryDetails'> - <h2>Thank you! Your order has been placed.</h2> - <h3 data-bind='var: order(orderid); format:text; pretext:Your order id is ;'></h3> - <div class='pointer marginBottom' data-app-role='paymentMessaging'> - Click here to view/print your invoice. - <div class='zwarn' data-bind="var: order(payment_status_msg); format:text;"></div><!-- displays payment issues/errors --> + <div class="floatRight ocmThirdParty" data-app-role="thirdPartyContainer"></div> + + <div class="orderSummaryDetails"> + <h2>The order has been created.</h2> + <h3 data-tlc="bind $var '.orderid'; if (is $var --notblank;) {{format --prepend='Your order id is '; apply --append;}};"></h3> + <div class="pointer marginBottom" data-app-role="paymentMessaging"> + <div data-tlc="bind $var '.payment_status_msg'; if (is $var --notblank;) {{apply --append;}};" class="zwarn"></div><!-- displays payment issues/errors --> </div> - <div data-bind="var:order(payment_status_detail); format:text;" class='marginBottom'></div> - <div>You will receive an order confirmation email with details of your order</div> + <div data-tlc="bind $var '.payment_status_detail'; if (is $var --notblank;) {{apply --append;}};" class="marginBottom"></div> + <div>You will receive an order confirmation email with details of your order.</div> </div> - <div class='clearAll'></div> - <span id='BuySafeGuaranteeSpan'></span> - <div class='clearAll'></div> + <div class="clearAll"></div> + <span id="BuySafeGuaranteeSpan"></span> + <div class="clearAll"></div> -<div data-app-role='invoiceContainer'> - <table class='orderContentsTable fullWidth'> - <tr> - <td colspan='2'> - <div class='floatRight hide4Print'> - <button data-app-event="orderCreate|execInvoicePrint">Print Invoice</button> - </div> +<div data-app-role="invoiceContainer"> + <table class="orderContentsTable fullWidth"> + <tbody><tr> + <td colspan="2"> - <h3 data-bind='var:order(order/data/pool);format:text; pretext:Order Status: ;'></h3> + <h3 data-tlc="bind $var '.order.data.pool'; if (is $var --notblank;) {{format --prepend='Order Status: '; apply --append;}};"></h3> </td> </tr> <tr> <td> - <hgroup class='marginBottom'> + <hgroup class="marginBottom"> <!-- print icon --> <!-- <h2 data-bind='var:order(bill/firstname);format:text; pretext:Shipping Status: ;'></h2> --> - <h5 class='orderTotal' data-bind='var:order(order/sum/order_total);format:money; currencySign: $; hideZero:false; pretext:Order Total: ;'></h5> - <h5 class='balanceDue' data-bind='var:order(order/sum/balance_due_total);format:money; currencySign: $; hideZero:false; pretext:Balance Due: ;'></h5> + <h5 data-tlc="bind $var '.order.sum.order_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Order Total: '; apply --append;}};" class="orderTotal"></h5> + <h5 data-tlc="bind $var '.order.sum.balance_due_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Balance Due: '; apply --append;}};" class="balanceDue"></h5> </hgroup> - <address class='marginBottom'> + <address class="marginBottom"> <h4> - <span data-bind='var:order(order/bill/firstname);format:text; pretext:Bill To: ;'></span> - <span data-bind='var:order(order/bill/lastname);format:text;'></span> + <span data-tlc="bind $var '.order.bill.firstname'; if (is $var --notblank;) {{format --prepend='Bill To: '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.lastname'; if (is $var --notblank;) {{apply --append;}};"></span> </h4> - <div data-bind='var:order(order/bill/address1);format:text;'></div> - <div data-bind='var:order(order/bill/address2);format:text;'></div> + <div data-tlc="bind $var '.order.bill.address1'; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.order.bill.address2'; if (is $var --notblank;) {{apply --append;}};"></div> <div> - <span data-bind='var:order(order/bill/city);format:text;posttext:, ;'></span> - <span data-bind='var:order(order/bill/region);format:text;posttext:. ;'></span> - <span data-bind='var:order(order/bill/postal);format:text; defaultVar:order(data.bill_int_zip);'></span> + <span data-tlc="bind $var '.order.bill.city'; if (is $var --notblank;) {{format --append=', '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.region'; if (is $var --notblank;) {{format --append='. '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.postal'; if(is $var --blank;) {{bind $var '.data.bill_int_zip'; }}; if (is $var --notblank;) {{apply --append;}};"></span> </div> - <div data-bind='var:order(order/bill/countrycode);format:text;'></div> + <div data-tlc="bind $var '.order.bill.countrycode'; if (is $var --notblank;) {{apply --append;}};"></div> </address> <address> <h4> - <span data-bind='var:order(order/ship/firstname);format:text; pretext:Ship To: ;'></span> - <span data-bind='var:order(order/ship/lastname);format:text;'></span> + <span data-tlc="bind $var '.order.ship.firstname'; if (is $var --notblank;) {{format --prepend='Ship To: '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.lastname'; if (is $var --notblank;) {{apply --append;}};"></span> </h4> - <div data-bind='var:order(order/ship/address1);format:text;'></div> - <div data-bind='var:order(order/ship/address2);format:text;'></div> + <div data-tlc="bind $var '.order.ship.address1'; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.order.ship.address2'; if (is $var --notblank;) {{apply --append;}};"></div> <div> - <span data-bind='var:order(order/ship/city);format:text;posttext:, ;'></span> - <span data-bind='var:order(order/ship/region);format:text;posttext:. ;'></span> - <span data-bind='var:order(order/ship/postal);format:text; defaultVar:order(data.ship_int_zip);'></span> + <span data-tlc="bind $var '.order.ship.city'; if (is $var --notblank;) {{format --append=', '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.region'; if (is $var --notblank;) {{format --append='. '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.postal'; if(is $var --blank;) {{bind $var '.data.ship_int_zip'; }}; if (is $var --notblank;) {{apply --append;}};"></span> </div> - <div data-bind='var:order(order/ship/countrycode);format:text;'></div> + <div data-tlc="bind $var '.order.ship.countrycode'; if (is $var --notblank;) {{apply --append;}};"></div> </address> </td> - <td class='orderContentsProdlistContainer'> - <ul data-bind='var:order(order/tracking); format:orderTrackingLinks; extension:store_crm;before:<h4>Shipping:</h4>;' class='displayNone noListStyle marginBottom'></ul> - <table class='listStyleNone lineItemProdlist'> - <tbody data-bind="var: order(order/@ITEMS); format:stuffList; loadsTemplate:chkoutInvoiceItemTemplate;"></tbody> + <td class="orderContentsProdlistContainer"> + <table class="listStyleNone lineItemProdlist"> + <tbody data-tlc="bind $var '.order.@ITEMS'; controller#loop --templateid='chkoutInvoiceItemTemplate'; if (is $var --notblank;) {{apply --append;}};"></tbody> </table> </td> </tr> - </table> + </tbody></table> </div> </div> @@ -533,10 +573,10 @@ <h4> -<div id='cvvcidHelp' class='displayNone' title='Where to find your CVV/CID and why we ask for it'> +<div id="cvvcidHelp" class="displayNone" title="Where to find your CVV/CID and why we ask for it"> <p>For higher security and more efficient processing of your payment, you must provide a card security code to make this purchase. For Visa, MasterCard and Discover the security code is the last section of numbers in the signature area on the back of the card. For American Express the security code is the 4-digit number found in small print next to your account number on the front, usually above it on the right.</p> - <div class='checkoutSprite secCode_vmd' title='Visa/MC/Discover card security code'></div> - <div class='checkoutSprite secCode_amex' title='AMEX card security code'></div> + <div class="checkoutSprite secCode_vmd" title="Visa/MC/Discover card security code"></div> + <div class="checkoutSprite secCode_amex" title="AMEX card security code"></div> </div> @@ -563,45 +603,51 @@ <h4> If this gets recycled, test in order history after making changes. --> <table> - <tr id='chkoutInvoiceItemTemplate' class='padMargBorderBottom'> + <tbody><tr id="chkoutInvoiceItemTemplate" class="padMargBorderBottom"> <td> - <div class='prodThumbContainer marginRight'> - <img src='/media/graphics/blank.gif' class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL;' width='55' height='55' /> + <div class="prodThumbContainer marginRight"> + <img data-tlc="bind $var '.%attribs.zoovy:prod_image1'; if (is $var --notblank;) {{ apply --img --media=$var --width=55 --height=55 --bgcolor='#ffffff' --replace;}};" src="/media/graphics/blank.gif" class="prodThumb" height="55" width="55"> </div> </td> - <td class='valignTop ztable_row'> + <td class="valignTop ztable_row"> -<div class='infoContainer'> - - <h3 data-bind='var: product(prod_name); format:text; '></h3> - <div class='ztable_row_small stid' data-bind='var: product(sku); format:text; className: stid; pretext: Sku: ;'></div> +<div class="infoContainer"> + <b data-tlc="bind $var '.prod_name'; if (is $var --notblank;) {{apply --append;}};"></b> + <div data-tlc="bind $var '.sku'; if (is $var --notblank;) {{format --prepend='Sku: '; apply --add --class='stid'; apply --append;}};" class="ztable_row_small stid"></div> + <div> - <span data-bind='var: product(qty); format:text; pretext:qty: ;'></span> - <span data-bind='var: product(price); format:money; currencySign: $; hideZero:false; pretext: x ;' ></span> - <span data-bind='var: product(extended); format:money; currencySign: $; hideZero:false; pretext: = ;'></span> + <span data-tlc="bind $var '.qty'; if (is $var --notblank;) {{format --prepend='qty: '; apply --append;}};"></span> + <span data-tlc="bind $var '.price'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='x '; apply --append;}};"></span> + <span data-tlc="bind $var '.extended'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='= '; apply --append;}};"></span> </div> - - <div class='ztable_row_small prodOptions' data-bind='var: product(%options); format:selectedOptionsDisplay;'></div> - - - + <div data-tlc="bind $var '.%options'; controller#selectedoptionsdisplay --legacy; " class="ztable_row_small prodOptions"></div> </div> </td> - <td class='alignRight hide4Print'> - <button class='writeReview' data-app-event="store_crm|showWriteReview" data-bind='var:product(product);format:assignAttribute; attribute:data-pid;'>Write Review</button> + <td class="alignRight hide4Print"> + <button data-tlc="bind $var '.product'; apply --attrib='data-pid'; " class="writeReview applyButton" data-app-click="store_crm|showWriteReview">Write Review</button> </td> </tr> -</table> - - +</tbody></table> +<ol> + <li id="chkoutOrderHistoryLineItem" data-app-role="orderContainer" class="marginBottom"> + <span data-tlc="bind $var '.ORDERID'; if (is $var --notblank;) {{apply --append;}};" data-app-click="order_create|adminOrderDetailShow" class="lookLikeLink"></span> on <span data-tlc="bind $var '.CREATED_GMT'; datetime --out='pretty'; if (is $var --notblank;) {{apply --append;}};"></span> + <button data-app-click="order_create|cartItemAppendAllSKUsFromOrder" class="applyButton" data-icon-primary="ui-icon-arrowrefresh-1-e">Re-order</button><!-- ### TOTO -> after an add or add all, do an inventory check --> + <div data-tlc="bind $var '.@ITEMS'; controller#loop --templateid='chkoutOrderHistoryItemLineItem'; if (is $var --notblank;) {{apply --append;}};" class="displayNone marginBottom" data-app-role="orderContents"></div> + </li> +</ol> +<div id="chkoutOrderHistoryItemLineItem" data-app-role="cartItemContainer" class="marginTop"> + <span data-tlc="bind $var '.stid'; if (is $var --notblank;) {{apply --append;}};"></span> - + <span data-tlc="bind $var '.prod_name'; if (is $var --notblank;) {{apply --append;}};"></span> + <button data-app-click="order_create|cartItemAppendSKU" class="applyButton" data-text="false" data-icon-primary="ui-icon-cart">Add</button> +</div> \ No newline at end of file diff --git a/extensions/checkout/passive.html b/extensions/checkout/passive.html index 7dcc46c5f..e5d53abcf 100644 --- a/extensions/checkout/passive.html +++ b/extensions/checkout/passive.html @@ -7,18 +7,19 @@ item list and summary are separate just to give more control over location. --> -<div id='checkoutTemplate' class='checkoutFormContainer' data-app-role='checkout'> +<div id="checkoutTemplate" class="checkoutFormContainer" data-app-role="checkout"> - <form action='#'> - <input type='hidden' name='bill/shortcut' data-bind="var: cart(bill/shortcut); format:popVal;" /> - <input type='hidden' name='ship/shortcut' data-bind="var: cart(ship/shortcut); format:popVal;" /> + <form action="#"> + <input data-tlc="bind $var '.bill.shortcut'; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/shortcut" type="hidden"> + <input data-tlc="bind $var '.ship.shortcut'; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/shortcut" type="hidden"> + <input data-tlc="bind $var '.cart.cartid'; if(is $var --notblank;) {{apply --select=$var;}}; " name="_cartid" type="hidden"> <!-- define panel order --> - <fieldset data-app-role='chkoutPreflight' class='marginBottom'> - <legend class='headerPadding' >Email / Account Login</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutPreflightTemplate; useParentData:true;'></div> - <div data-app-role='buyerLogout' class='displayNone pointer' data-app-event='orderCreate|buyerLogout'> - Not you? <span class='lookLikeLink zlink'>click here</span>. + <fieldset data-app-role="chkoutPreflight" class="marginBottom"> + <legend class="headerPadding">Email / Account Login</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutPreflightTemplate'; apply --append;" data-legacy-useparentdata="true" class="panelContent"></div> + <div data-app-role="buyerLogout" class="displayNone pointer" data-app-click="order_create|buyerLogout"> + Not you? <span class="lookLikeLink zlink">click here</span>. </div> </fieldset> @@ -32,19 +33,19 @@ --> - <fieldset data-app-role='chkoutAddressBill' data-app-addresstype='bill' class='marginBottom'> - <legend class='headerPadding' >Billing Address</legend> - <p data-app-role='addressExists' class='displayNone clearfix'>Click the checkmark of the address you would like to use</p> + <fieldset data-app-role="chkoutAddressBill" data-app-addresstype="bill" class="marginBottom"> + <legend class="headerPadding">Billing Address</legend> + <p data-app-role="addressExists" class="displayNone clearfix">Click the checkmark of the address you would like to use</p> - <div class='panelContent displayNone addressList' data-app-role='addressExists' data-bind='var: buyer(@bill); format:processList; loadsTemplate: chkoutBuyerAddressTemplate;'></div><!-- for return customers --> + <div data-tlc="bind $var '.@bill'; controller#loop --templateid='chkoutBuyerAddressTemplate'; if (is $var --notblank;) {{apply --append;}};" class="panelContent displayNone addressList" data-app-role="addressExists"></div><!-- for return customers --> - <div class='clearfix marginBottom' data-app-role='addressExists'><button data-app-event='orderCreate|showBuyerAddressAdd' data-app-addresstype='bill'>Add New Address</button></div> + <div class="clearfix marginBottom" data-app-role="addressExists"><button class=" applyButton" data-app-click="order_create|showBuyerAddressAdd" data-app-addresstype="bill">Add New Address</button></div> - <div class='panelContent' data-app-role='addressNew' data-bind='format:loadsTemplate; loadsTemplate: chkoutAddressBillTemplate;'></div><!-- for new customers --> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAddressBillTemplate'; apply --append;" class="panelContent" data-app-role="addressNew"></div><!-- for new customers --> - <div data-app-role='billToShipContainer' > + <div data-app-role="billToShipContainer"> <label> - <input type='checkbox' name='want/bill_to_ship' data-bind="var: cart(want/bill_to_ship); format:popVal; hideZero:false;" checked='checked' data-app-event='orderCreate|tagAsBillToShip' /> + <input data-tlc="bind $var '.want.bill_to_ship'; if(is $var --notblank;) {{apply --select=$var;}}; " name="want/bill_to_ship" checked="checked" class="applyAnycb" data-app-change="order_create|tagAsBillToShip" type="checkbox"> ship to billing address </label> </div> @@ -52,49 +53,49 @@ - <fieldset data-app-role='chkoutAddressShip' data-app-addresstype='ship' class='displayNone marginBottom'> - <legend class='headerPadding' >Shipping Address</legend> - <div class='panelContent displayNone addressList' data-app-role='addressExists' data-bind='var: buyer(@ship); format:processList; loadsTemplate: chkoutBuyerAddressTemplate;'></div><!-- for return customers --> - <div class='panelContent' data-app-role='addressNew' data-bind='format:loadsTemplate; loadsTemplate: chkoutAddressShipTemplate;'></div><!-- for new customers --> - <div class='clearfix' data-app-role='addressExists'><button data-app-event='orderCreate|showBuyerAddressAdd' data-app-addresstype='ship'>Add New Shipping Address</button></div> + <fieldset data-app-role="chkoutAddressShip" data-app-addresstype="ship" class="displayNone marginBottom"> + <legend class="headerPadding">Shipping Address</legend> + <div data-tlc="bind $var '.@ship'; controller#loop --templateid='chkoutBuyerAddressTemplate'; if (is $var --notblank;) {{apply --append;}};" class="panelContent displayNone addressList" data-app-role="addressExists"></div><!-- for return customers --> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAddressShipTemplate'; apply --append;" class="panelContent" data-app-role="addressNew"></div><!-- for new customers --> + <div class="clearfix" data-app-role="addressExists"><button class=" applyButton" data-app-click="order_create|showBuyerAddressAdd" data-app-addresstype="ship">Add New Shipping Address</button></div> </fieldset> - <fieldset data-app-role='chkoutMethodsShip' class='marginBottom'> - <legend class='headerPadding' >Shipping Methods</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutMethodsShipTemplate;'></div> + <fieldset data-app-role="chkoutMethodsShip" class="marginBottom"> + <legend class="headerPadding">Shipping Methods</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutMethodsShipTemplate'; apply --append;" class="panelContent"></div> </fieldset> - <fieldset data-app-role='chkoutMethodsPay' class='marginBottom'> - <legend class='headerPadding' >Payment Choices</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutMethodsPayTemplate;'></div> + <fieldset data-app-role="chkoutMethodsPay" class="marginBottom"> + <legend class="headerPadding">Payment Choices</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutMethodsPayTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- totals et all --> - <fieldset data-app-role='chkoutNotes' class='marginBottom'> - <legend class='headerPadding' >Order Notes/Special Instructions</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutNotesTemplate;'></div> + <fieldset data-app-role="chkoutNotes" class="marginBottom"> + <legend class="headerPadding">Order Notes/Special Instructions</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutNotesTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- line items --> - <fieldset data-app-role='chkoutCartItemsList' class='marginBottom'> - <legend class='headerPadding' >Contents</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutCartContentsTemplate;'></div> + <fieldset data-app-role="chkoutCartItemsList" class="marginBottom"> + <legend class="headerPadding">Contents</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutCartContentsTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- totals et all --> - <fieldset data-app-role='chkoutCartSummary' class='marginBottom'> - <legend class='headerPadding' >Summary</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutCartSummaryTemplate;'></div> + <fieldset data-app-role="chkoutCartSummary" class="marginBottom"> + <legend class="headerPadding">Summary</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutCartSummaryTemplate'; apply --append;" class="panelContent"></div> </fieldset> </form> @@ -104,23 +105,23 @@ -<section id='chkoutPreflightTemplate'> +<section id="chkoutPreflightTemplate"> -<h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email); defaultVar: cart(customer/login); format:text;"></h4> +<h4 data-tlc="bind $var '.bill.email'; if(is $var --blank;) {{bind $var '.customer.login'; }}; if (is $var --notblank;) {{apply --append;}};" class="displayNone" data-app-role="username"></h4> -<div data-app-role='login'> +<div data-app-role="login"> <!-- Not used in passive <div data-app-role='loginPasswordContainer' class='displayNone floatRight'> <div>If you have an account with us, please enter your password below to login</div> - <input type='password' placeholder='password' size='30' name='password' /><button data-app-event='orderCreate|execBuyerLogin'>login</button> + <input type='password' placeholder='password' size='30' name='password' /><button class=' applyButton' data-app-click='order_create|execBuyerLogin'>login</button> </div> --> - <input type='email' name='bill/email' required='required' size='30' placeholder="email address" data-bind="var:cart(bill/email); defaultVar:cart(customer/login); format:popVal;" data-app-event='orderCreate|execBuyerEmailUpdate' /><br /> + <input data-tlc="bind $var '.bill.email'; if(is $var --blank;) {{bind $var '.customer.login'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/email" required size="30" placeholder="email address" data-app-blur="order_create|execBuyerEmailUpdate" type="email"><br> <!-- Not used in assive - <label class='accountCreateContainer'><input type='checkbox' name='want/create_customer' data-app-event='orderCreate|tagAsAccountCreate' />Create customer account</label> + <label class='accountCreateContainer'><input type='checkbox' name='want/create_customer' class='applyAnycb' data-app-change='order_create|tagAsAccountCreate' />Create account</label> --> @@ -137,32 +138,35 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) + <!-- billing address panel spec This template is also used in the myAccount page, which is why a default using _ is present. +This template is used both in the billing address panel AND in the address editor (if logged in). in the address editor, the data is formatted as bill/address1 +because the panel is shared, the events (which aren't desired in the editor) are added by the checkout extension. --> -<section id='chkoutAddressBillTemplate'> +<section id="chkoutAddressBillTemplate"> - <div><input type='text' placeholder='first name' name='bill/firstname' required='required' value='' data-bind='var: cart(bill/firstname); defaultVar: cart(bill/firstname); format:popVal;' /></div> - <div><input type='text' placeholder='last name' name='bill/lastname' required='required' value='' data-bind='var: cart(bill/lastname); defaultVar: cart(bill/lastname); format:popVal;' /></div> + <div><input data-tlc="bind $var '.bill.firstname'; if(is $var --blank;){{bind $var '.bill/firstname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="bill/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.bill.lastname'; if(is $var --blank;){{bind $var '.bill/lastname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="bill/lastname" required value="" type="text"></div> - <div class='bill_company'><input type='text' name='bill/company' placeholder='company' value='' data-bind='var: cart(bill/company); defaultVar: cart(bill/company); format:popVal;' /></div><!-- class is added so it can be easily disabled w/ css --> + <div class="bill_company"><input data-tlc="bind $var '.bill.company'; if(is $var --blank;){{bind $var '.bill/company';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> - <div><input type='text' name='bill/address1' placeholder='address' required='required' value='' data-bind='var: cart(bill/address1); defaultVar: cart(bill/address1); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.address1'; if(is $var --blank;){{bind $var '.bill/address1';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/address1" placeholder="address" required value="" type="text"></div> - <div><input type='text' name='bill/address2' placeholder='address 2' value='' data-bind='var: cart(bill/address2); defaultVar: cart(bill/address2); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.address2'; if(is $var --blank;){{bind $var '.bill/address2';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/address2" placeholder="address 2" value="" type="text"></div> - <div><input type='text' name='bill/city' placeholder='city' required='required' value='' data-bind='var: cart(bill/city); defaultVar: cart(bill/city); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.city'; if(is $var --blank;){{bind $var '.bill/city';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/city" placeholder="city" required value="" type="text"></div> - <div><input type='text' name='bill/region' placeholder='state/region' required='required' size='5' value='' data-bind='var: cart(bill/region); defaultVar: cart(bill/region); format:popVal;' maxlength='20' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.region'; if(is $var --blank;){{bind $var '.bill/region';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/region" placeholder="state/region" required size="5" value="" maxlength="20" type="text"></div> <!-- postal not required for international. don't add it. --> - <div><input type='text' name='bill/postal' placeholder='zip/postal code' required='required' size='14' value='' data-bind='var: cart(bill/postal); defaultVar: cart(bill/postal); format:popVal;' maxlength='10' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.postal'; if(is $var --blank;){{bind $var '.bill/postal';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" type="text"></div> - <div class='billCountry' data-app-role='billCountry'><select name='bill/countrycode' placeholder='country' data-bind='var: cart(bill/countrycode); defaultVar: cart(bill/countrycode); defaultValue:US; format:countriesAsOptions; extension: cco;forceRender:1;' required='required' data-app-event="orderCreate|execCountryUpdate" ></select></div> + <div class="billCountry" data-app-role="billCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='bill' --legacy;" data-legacy-useparentdata="true" name="bill/countrycode" placeholder="country" required="required"><option value=''>Please choose</option></select></div> - <div><input type='tel' name='bill/phone' placeholder='phone number' required='required' value='' data-bind='var: cart(bill/phone); defaultVar: cart(bill/phone); format:popVal;' /> <span class='hint zhint'>in case of billing/delivery problems</span></div> + <div><input data-tlc="bind $var '.bill.phone'; if(is $var --blank;){{bind $var '.bill/phone';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/phone" placeholder="phone number" required value="" type="tel"> <span class="hint zhint">in case of billing/delivery problems</span></div> </section> @@ -173,46 +177,52 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) <!-- shipping address panel. don't add required to any inputs because if bill to ship is checked, NONE of these fields are required/populated. +This template is used both in the shipping panel AND in the address editor (if logged in). in the address editor, the data is formatted as ship/address1 +because the panel is shared, the events (which aren't desired in the editor) are added by the checkout extension. --> -<section id='chkoutAddressShipTemplate'> +<section id="chkoutAddressShipTemplate"> - <div><input type='text' placeholder='first name' name='ship/firstname' required='required' value='' data-bind='var: cart(ship/firstname); defaultVar: cart(ship/firstname); format:popVal;' /></div> - <div><input type='text' placeholder='last name' name='ship/lastname' required='required' value='' data-bind='var: cart(ship/lastname); defaultVar: cart(ship/lastname); format:popVal;' /></div> + <div><input data-tlc="bind $var '.ship.firstname'; if(is $var --blank;){{bind $var '.ship/firstname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="ship/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.ship.lastname'; if(is $var --blank;){{bind $var '.ship/lastname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="ship/lastname" required value="" type="text"></div> - <div class='bill_company'><input type='text' name='ship/company' placeholder='company' value='' data-bind='var: cart(ship/company); defaultVar: cart(ship/company); format:popVal;' /></div><!-- class is added so it can be easily disabled w/ css --> + <div class="bill_company"><input data-tlc="bind $var '.ship.company'; if(is $var --blank;){{bind $var '.ship/company';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> - <div><input type='text' name='ship/address1' placeholder='address' required='required' value='' data-bind='var: cart(ship/address1); defaultVar: cart(ship/address1); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.address1'; if(is $var --blank;){{bind $var '.ship/address1';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address1" placeholder="address" required value="" type="text"></div> - <div><input type='text' name='ship/address2' placeholder='address 2' value='' data-bind='var: cart(ship/address2); defaultVar: cart(ship/address2); format:popVal;' /></div> + <div><input data-tlc="bind $var '.ship.address2'; if(is $var --blank;){{bind $var '.ship/address2';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address2" placeholder="address 2" value="" type="text"></div> - <div><input type='text' name='ship/city' placeholder='city' required='required' value='' data-bind='var: cart(ship/city); defaultVar: cart(ship/city); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.city'; if(is $var --blank;){{bind $var '.ship/city';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/city" placeholder="city" required value="" type="text"></div> - <div><input type='text' name='ship/region' placeholder='state/region' required='required' size='5' value='' data-bind='var: cart(ship/region); defaultVar: cart(ship/region); format:popVal;' maxlength='20' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.region'; if(is $var --blank;){{bind $var '.ship/region';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/region" placeholder="state/region" required size="5" value="" maxlength="20" type="text"></div> - <div><input type='text' name='ship/postal' placeholder='zip/postal code' required='required' size='14' value='' data-bind='var: cart(ship/postal); defaultVar: cart(ship/postal); format:popVal;' maxlength='10' data-app-event='orderCreate|execAddressUpdate'/></div> + <div><input data-tlc="bind $var '.ship.postal'; if(is $var --blank;){{bind $var '.ship/postal';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" type="text"></div> - <div class='shipCountry' data-app-role='shipCountry'><select name='ship/countrycode' placeholder='country' data-bind='var: cart(ship/countrycode); defaultVar: cart(ship/countrycode); defaultValue:US; format:countriesAsOptions; extension: cco;forceRender:1;' data-app-event="orderCreate|execCountryUpdate" ></select></div> + <div class="shipCountry" data-app-role="shipCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='ship' --legacy;" data-legacy-useparentdata="true" name="ship/countrycode" placeholder="country"><option value=''>Please choose</option></select></div> </section> + + + + <!-- a panel that only appears in 'nice' --> -<section id='chkoutAccountCreateTemplate'> +<section id="chkoutAccountCreateTemplate"> -<div><input type='password' data-minlength='8' placeholder='password' required='required' name='want/new_password' size='12' data-bind='var: cart(want/new_password); format:popVal;' /> <span class='hint'>must be at least 8 characters</span></div> -<div><input type='password' data-minlength='8' placeholder='verify password' required='required' name='want/new_password2' size='12' data-bind='var: cart(want/new_password2); format:popVal;' /></div> +<div><input data-tlc="bind $var '.want.new_password'; if(is $var --notblank;) {{apply --select=$var;}}; " data-minlength="8" placeholder="password" required name="want/new_password" size="12" type="password"> <span class="hint">must be at least 8 characters</span></div> +<div><input data-tlc="bind $var '.want.new_password2'; if(is $var --notblank;) {{apply --select=$var;}}; " data-minlength="8" placeholder="verify password" required name="want/new_password2" size="12" type="password"></div> <label>Recovery Question -<select name='want/recovery_hint' data-bind='var: cart(want/recovery_hint); format:popVal;'> - <option value='2'>Name of your favorite childhood pet?</option> - <option value='3'>City you were born in?</option> - <option value='4'>Last name of your best friend growing up?</option> - <option value='5'>Last city you lived in?</option> +<select data-tlc="bind $var '.want.recovery_hint'; if(is $var --notblank;) {{apply --select=$var;}}; " name="want/recovery_hint"> + <option value="2">Name of your favorite childhood pet?</option> + <option value="3">City you were born in?</option> + <option value="4">Last name of your best friend growing up?</option> + <option value="5">Last city you lived in?</option> </select> </label> -<input type='text' placeholder='recovery answer' required='required' value='' name='want/recovery_answer' maxlength='20' size='20' data-bind='var: cart(want/recovery_answer); format:popVal;' /></label> +<input data-tlc="bind $var '.want.recovery_answer'; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="recovery answer" required value="" name="want/recovery_answer" maxlength="20" size="20" type="text"> </section> @@ -224,8 +234,9 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) messaging are hidden by default, then displayed if needed. keeps panel from being jittery. --> -<div id='chkoutMethodsShipTemplate'> - <ul class='noPadOrMargin listStyleNone' data-bind='var: cart(@SHIPMETHODS); format:shipMethodsAsRadioButtons; extension: orderCreate;' data-app-event='orderCreate|addTriggerShipMethodUpdate'></ul> +<div id="chkoutMethodsShipTemplate"> + <ul data-tlc="bind $var '.'; order_create#shipmethodsasradiobuttons --legacy;" data-legacy-useparentdata="true" class="noPadOrMargin listStyleNone"></ul> + <div data-app-role="upsShipRulesDisclaimer" class="upsShipRulesDisclaimer displayNone">These fees do not necessarily represent UPS published rates and may include handling charges by our company.</div> </div> @@ -241,34 +252,35 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) --> -<div id='chkoutMethodsPayTemplate'> +<div id="chkoutMethodsPayTemplate"> - <div class='giftCardContainer' data-app-role="giftcardContainer"> - <label for='giftcardCode'>Gift Certificate Code:</label> - <input type='text' name='giftcard' size='16' data-app-event='orderCreate|addTriggerButtonClick' /> - <button data-app-event='orderCreate|execGiftcardAdd'>add</button> - <small data-app-role='giftcardHint' class='zhint hint displayNone'>if you wish to combine gift cards with another payment method, enter them here</small> + <div class="giftCardContainer" data-app-role="giftcardContainer"> + <label for="giftcardCode">Gift Certificate Code:</label> + <input name="giftcard" size="16" data-input-keyup="trigger-button-id" data-input-format="alphanumeric" data-trigger-button-id="execGiftcardAdd" type="text"> + <button class="applyButton" data-app-click="order_create|execGiftcardAdd" data-button-id="execGiftcardAdd">add</button> + <p data-app-role="giftcardHint" class="zhint hint displayNone">if you wish to combine gift cards with another payment method, enter them here</p> </div> - <div data-app-role='paymentQContainer' class='marginBottom'> - <ul class='noPadOrMargin listStyleNone' data-bind='var: cart(@PAYMENTQ); format:processList; loadsTemplate:cartPaymentQTemplate;'></ul> + <div data-app-role="paymentQContainer" class="marginBottom"> + <ul data-tlc="bind $var '.@PAYMENTQ'; controller#loop --templateid='cartPaymentQTemplate'; if (is $var --notblank;) {{apply --append;}};" class="noPadOrMargin listStyleNone"></ul> </div> <!-- used in paypal transactions to cancel as paypal --> - <div data-app-event='orderCreate|execChangeFromPayPal' class='displayNone pointer zlink'> + <div data-app-click="order_create|execChangeFromPayPal" class="displayNone pointer zlink"> Choose Alternate Payment Method </div> <!-- more payment types is first but, when applicable, stored payments is shown. That way stored payments are easily selected but it's hard to miss that other payment choices are available. --> - <div data-app-role='paymentOptionsContainer' data-app-event="orderCreate|addTriggerPayMethodUpdate"> + <div data-app-role="paymentOptionsContainer" data-app-event="order_create|addTriggerPayMethodUpdate"> - <h2 data-app-role='nonStoredPaymentsHeader' class='displayNone'>More Payment Choices</h2> - <div data-app-role='nonStoredPaymentsContent'> - <div data-bind='var: getPaymentMethods(@methods); format:payMethodsAsRadioButtons; extension: orderCreate;'></div> + <h2 data-app-role="nonStoredPaymentsHeader" class="displayNone">More Payment Choices</h2> + <div data-app-role="nonStoredPaymentsContent"> + <div data-tlc="bind $var '.cart.cartid'; order_create#paymethodsasradiobuttons --legacy;"></div> </div> - <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payments</h2> - <div data-app-role='storedPaymentsContent' class='displayNone' data-bind="var: buyerWalletList(@wallets); format:processList; loadsTemplate: chkoutBuyerWalletListItem;"></div> + <h2 data-app-role="storedPaymentsHeader" class="displayNone">Your Stored Payments</h2> + <!-- The # of children in the storedPaymentContents triggers wallet display. Do not add any children to this div. --> + <div data-tlc="bind $var '.@wallets'; controller#loop --templateid='chkoutBuyerWalletListItem'; if (is $var --notblank;) {{apply --append;}};" data-app-role="storedPaymentsContent" class="displayNone"></div> </div> @@ -285,32 +297,32 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment the defaultVar on prodName & image is for promotions, which have a 'description' attribute --> <table> -<tr id='chkoutCartItemTemplate'> - <td><img class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL; defaultVar: product(%attribs.zoovy:prod_image1);' width='50' height='50' /></td> +<tbody><tr id="chkoutCartItemTemplate"> + <td><img data-tlc="bind $var '.%attribs.zoovy:prod_thumb'; if(is $var --blank;) {{bind $var '.%attribs.zoovy:prod_image1'; }}; if (is $var --notblank;) {{ apply --img --media=$var --width=50 --height=50 --bgcolor='#ffffff' --replace;}};" class="prodThumb" height="50" width="50"></td> <td> - <div class='prodName' data-bind='var: product(prod_name); format:text; defaultVar: description;'></div> - <div class='stid' data-bind='var: product(sku); format:text; className: stid; pretext: Sku: ;'></div> - <div class='prodLatency' data-bind='var:product(%attribs.zoovy:ship_latency); format:text; pretext:Normally ships in ; posttext: day(s);'></div> - <div class='prodOptions' data-bind='var: variations(%options); format:selectedOptionsDisplay;'></div> + <div data-tlc="bind $var '.prod_name'; if(is $var --blank;) {{bind $var '.description'; }}; if (is $var --notblank;) {{apply --append;}};" class="prodName"></div> + <div data-tlc="bind $var '.sku'; if (is $var --notblank;) {{format --prepend='Sku: '; apply --add --class='stid'; apply --append;}};" class="stid"></div> + <div data-tlc="bind $var '.%attribs.zoovy:ship_latency'; if (is $var --notblank;) {{format --prepend='Normally ships in '; format --append=' day(s)'; apply --append;}};" class="prodLatency"></div> + <div data-tlc="bind $var '.%options'; controller#selectedoptionsdisplay --legacy; " class="prodOptions"></div> </td> - <td class='alignRight'><span data-bind='var: product(qty); format:text;'></span></td> - <td class='alignRight'><span data-bind='var: product(price); format:money; currencySign: $; hideZero:false; pretext: x ;'></span></td> - <td class='alignRight'><span data-bind='var: product(extended); format:money; currencySign: $; hideZero:false; pretext: = ;'></span></td> + <td class="alignRight"><span data-tlc="bind $var '.qty'; if (is $var --notblank;) {{apply --append;}};"></span></td> + <td class="alignRight"><span data-tlc="bind $var '.price'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='x '; apply --append;}};"></span></td> + <td class="alignRight"><span data-tlc="bind $var '.extended'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='= '; apply --append;}};"></span></td> </tr> -</table> +</tbody></table> -<section id='chkoutCartContentsTemplate'> -<table class='fullWidth gridTable'> +<section id="chkoutCartContentsTemplate"> +<table class="fullWidth gridTable"> <thead> <tr> - <th colspan='2' class='alignLeft'>product information</th> - <th class='alignRight'>qty</th> - <th class='alignRight'>price</th> - <th class='alignRight'>item total</th> + <th colspan="2" class="alignLeft">product information</th> + <th class="alignRight">qty</th> + <th class="alignRight">price</th> + <th class="alignRight">item total</th> </tr> </thead> -<tbody data-bind='var: cart(@ITEMS); format:processList; loadsTemplate:chkoutCartItemTemplate;'></tbody> +<tbody data-tlc="bind $var '.@ITEMS'; controller#loop --templateid='chkoutCartItemTemplate'; if (is $var --notblank;) {{apply --append;}};" data-app-role="cartItemsTbody"></tbody> </table> </section> @@ -321,37 +333,37 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment -<section id='chkoutCartSummaryTemplate'> +<section id="chkoutCartSummaryTemplate"> + + <div data-tlc="bind $var '.sum.items_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Subtotal: '; apply --add --class='orderSubtotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.tax_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Tax: '; apply --add --class='orderTax'; apply --append;}};"></div> + <div data-tlc="bind $var '.'; cco#shipinfobyid --legacy;" data-legacy-useparentdata="true" class="orderShipping"></div> + <div data-tlc="bind $var '.sum.hnd_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Handling: '; apply --add --class='hndTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.order_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Order Total: '; apply --add --class='orderTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.gfc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Giftcard(s): '; apply --add --class='orderGiftcardTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.pnt_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Reward Points: '; apply --add --class='rewardPointsTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.rmc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Returns Credit: '; apply --add --class='returnsCreditTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.spc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Specialty: '; apply --add --class='spcTotal'; apply --append;}};"></div> + + <div data-tlc="bind $var '.sum.balance_due_total'; cco#orderbalance --classname='orderBalanceDue' --hidezero='false' --currencysign='$' --legacy;"></div> + + <div class="couponEntryContainer clearfix marginBottom" data-app-role="couponContainer"> + <label for="coupon">Coupon/Promo Code:</label> + <input name="coupon" size="8" data-input-keyup="trigger-button-id" data-trigger-button-id="execCouponAdd" data-input-format="alphanumeric" type="text"> + <button class="applyButton" data-app-click="order_create|execCouponAdd" data-button-id="execCouponAdd">add</button> + </div> - <div data-bind="var: cart(sum/items_total); format:money; className:orderSubtotal; hideZero:false; currencySign: $; pretext:Subtotal: ; "></div> - <div data-bind='var: cart(sum/tax_total); format:money; className:orderTax; hideZero:true;currencySign: $; pretext:Tax: ; '></div> - <div data-bind='var: cart(want/shipping_id); format:shipInfoById; className:orderShipping; hideZero:false; extension:cco;'></div> - <div data-bind='var: cart(sum/hnd_total); format:money; className:hndTotal; currencySign: $; pretext:Handling: ; '></div> - <div data-bind='var: cart(sum/order_total); format:money; className:orderTotal; hideZero:false; currencySign: $; pretext:Order Total: ; '></div> - <div data-bind='var: cart(sum/gfc_total); format:money; className:orderGiftcardTotal; currencySign: $; pretext:Giftcard(s): ; '></div> - <div data-bind='var: cart(sum/pnt_total); format:money; className:rewardPointsTotal; currencySign: $; pretext:Reward Points: ; '></div> - <div data-bind='var: cart(sum/rmc_total); format:money; className:returnsCreditTotal; currencySign: $; pretext:Returns Credit: ; '></div> - <div data-bind='var: cart(sum/spc_total); format:money; className:spcTotal; currencySign: $; pretext:Specialty: ; '></div> - - <div data-bind='var: cart(sum/balance_due_total); format:orderBalance; className:orderBalanceDue; hideZero:false; currencySign: $; pretext:Balance Due: ; extension:cco;'></div> - - <div class='couponEntryContainer clearfix marginBottom' data-app-role='couponContainer'> - <label for='coupon'>Coupon/Promo Code:</label> - <input type='text' name='coupon' size='8' data-app-event='orderCreate|addTriggerButtonClick' /> - <button data-app-event="orderCreate|execCouponAdd" >add</button> + <!-- will appear if company field is populated AND payment method is NOT PO --> + <div data-app-role="referenceNumber" class="displayNone"> + <label>Purchase Order/Reference #: </label> + <input type'text'="" name="want/reference_number" size="12"> </div> - <button data-app-event="orderCreate|execCartOrderCreate"> + <button class="ui-state-highlight applyButton" data-app-click="order_create|execCartOrderCreate"> Place Order </button> -<div data-app-role='referenceNumber' class='displayNone'> - <label>Purchase Order/Reference #: </label> - <input type'text' name='want/reference_number' size='12' /> -</div> - - </section> @@ -361,13 +373,13 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment - -<address id='chkoutBuyerAddressTemplate' class='ui-widget ui-widget-content ui-corner-all stdPadding'> - <div data-bind="var:address(bill/address1); defaultVar: address(ship/address1); format:text;"></div> - <div data-bind="var:address(bill/postal); defaultVar: address(ship/postal); format:text;"></div> - <div class='clearfix'> - <button class='floatRight' data-app-event='orderCreate|execBuyerAddressSelect'>Use This Address</button> - <button class='floatRight marginRight' data-app-event="orderCreate|showBuyerAddressUpdate">Edit This Address</button> +<!-- there is display logic looking for the number of address elements in addressExists. do not change element try w/out updating display logic. --> +<address id="chkoutBuyerAddressTemplate" class="ui-widget ui-widget-content ui-corner-all stdPadding"> + <div data-tlc="bind $var '.bill/address1'; if(is $var --blank;) {{bind $var '.ship/address1'; }}; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.bill/postal'; if(is $var --blank;) {{bind $var '.ship/postal'; }}; if (is $var --notblank;) {{apply --append;}};"></div> + <div class="clearfix"> + <button class="floatRight applyButton" data-app-click="order_create|execBuyerAddressSelect" data-icon="false" data-icon-primary="ui-icon-check">Use This Address</button> + <button class="floatRight marginRight applyButton" data-app-role="addressEditButton" data-app-click="order_create|showBuyerAddressUpdate" data-icon="false" data-icon-primary="ui-icon-pencil">Edit</button> </div> </address> @@ -377,20 +389,20 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment <ul> - <li id='cartPaymentQTemplate'> - <span data-bind="var:payment(TN); format:text;"></span> - <span class='marginLeft' data-bind="var:payment($$); format:money; currencySign: $; hideZero:false;"></span><span data-bind="var:payment($#); format:money; currencySign: $; pretext:/;"></span> -<!-- <button class='marginLeft' title='Remove this payment method'>X</button> --> + <li id="cartPaymentQTemplate"> + <span data-tlc="bind $var '.TN'; if (is $var --notblank;) {{apply --append;}};"></span> + <span data-tlc="bind $var '.$$'; if (is $var --notblank;) {{format --currency='USD'; apply --append;}};" class="marginLeft"></span><span data-tlc="bind $var '.$#'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='/'; apply --append;}};"></span> +<!-- <button class='marginLeft applyButton' title='Remove this payment method'>X</button> --> </li> </ul> <!-- radio name is same as rest of payments so that only 1 can be selected and form still easily passes validation --> -<div id='chkoutBuyerWalletListItem'> +<div id="chkoutBuyerWalletListItem"> <label> - <input type='radio' name='want/payby' value='' data-bind="var: wallet(ID); format:setVal;" /> - <span data-bind="var: wallet(TD); format:text;"></span> - <span data-bind="var: wallet(TD); format: walletName2Icon; extension:cco;"></span> + <input data-tlc="bind $var '.ID'; apply --inputvalue; " name="want/payby" value="" type="radio" data-app-change='order_create|shipOrPayMethodSelectExec'> + <span data-tlc="bind $var '.TD'; if (is $var --notblank;) {{apply --append;}};"></span> + <span data-tlc="bind $var '.TD'; cco#walletnameintoicon --legacy;"></span> </label> </div> @@ -400,9 +412,9 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment do NOT change the input name or id or checkout will likely break. --> -<div id='chkoutNotesTemplate'> +<div id="chkoutNotesTemplate"> <p>Please include any special instructions or comments here:</p> -<textarea class='chkoutOrderNotes fullWidth' name='want/order_notes' data-app-event='orderCreate|execCartSet' data-bind='var: cart(want/order_notes); format:popVal;' rows='5'></textarea> +<textarea data-tlc="bind $var '.want.order_notes'; if(is $var --notblank;) {{apply --select=$var;}}; " class="chkoutOrderNotes fullWidth" name="want/order_notes" data-app-blur="order_create|execCartSet" rows="5"></textarea> </div> @@ -416,98 +428,91 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment <!-- used after a successful checkout. --> -<div id='chkoutCompletedTemplate' class='checkoutSuccess'> +<div id="chkoutCompletedTemplate" class="checkoutSuccess"> - <div class='floatRight ocmThirdParty'> - <h2>What next?</h2> -<!-- the twitter and facebook actions are added post checkout. The order contents are included as part of the message --> - <div class='ocm ocmFacebookComment pointer zlink marginBottom checkoutSprite '></div> - <div class='ocm ocmTwitterComment pointer zlink marginBottom checkoutSprit ' ></div> - <div class='ocm ocmContinue pointer zlink marginBottom checkoutSprite'></div> - - </div> + <div class="floatRight ocmThirdParty" data-app-role="thirdPartyContainer"></div> - <div class='orderSummaryDetails'> + <div class="orderSummaryDetails"> <h2>Thank you! Your order has been placed.</h2> - <h3 data-bind='var: order(orderid); format:text; pretext:Your order id is ;'></h3> - <div class='pointer marginBottom' data-app-role='paymentMessaging'> + <h3 data-tlc="bind $var '.orderid'; if (is $var --notblank;) {{format --prepend='Your order id is '; apply --append;}};"></h3> + <div class="pointer marginBottom" data-app-role="paymentMessaging"> Click here to view/print your invoice. - <div class='zwarn' data-bind="var: order(payment_status_msg); format:text;"></div><!-- displays payment issues/errors --> + <div data-tlc="bind $var '.payment_status_msg'; if (is $var --notblank;) {{apply --append;}};" class="zwarn"></div><!-- displays payment issues/errors --> </div> - <div data-bind="var:order(payment_status_detail); format:text;" class='marginBottom'></div> - <div>You will receive an order confirmation email with details of your order</div> + <div data-tlc="bind $var '.payment_status_detail'; if (is $var --notblank;) {{apply --append;}};" class="marginBottom"></div> + <div>You will receive an order confirmation email with details of your order.</div> </div> - <div class='clearAll'></div> - <span id='BuySafeGuaranteeSpan'></span> - <div class='clearAll'></div> + <div class="clearAll"></div> + <span id="BuySafeGuaranteeSpan"></span> + <div class="clearAll"></div> -<div data-app-role='invoiceContainer'> - <table class='orderContentsTable fullWidth'> - <tr> - <td colspan='2'> - <div class='floatRight hide4Print'> - <button data-app-event="orderCreate|execInvoicePrint">Print Invoice</button> +<div data-app-role="invoiceContainer"> + <table class="orderContentsTable fullWidth"> + <tbody><tr> + <td colspan="2"> + <div class="floatRight hide4Print"> + <button class=" applyButton" data-app-click="order_create|execInvoicePrint">Print Invoice</button> </div> - - <h3 data-bind='var:order(order/data/pool);format:text; pretext:Order Status: ;'></h3> + <h2 data-tlc="bind $var '.order.our.orderid'; if (is $var --notblank;) {{apply --append;}};"></h2> + <h3 data-tlc="bind $var '.order.data.pool'; if (is $var --notblank;) {{format --prepend='Order Status: '; apply --append;}};"></h3> </td> </tr> <tr> <td> - <hgroup class='marginBottom'> + <hgroup class="marginBottom"> <!-- print icon --> <!-- <h2 data-bind='var:order(bill/firstname);format:text; pretext:Shipping Status: ;'></h2> --> - <h5 class='orderTotal' data-bind='var:order(order/sum/order_total);format:money; currencySign: $; hideZero:false; pretext:Order Total: ;'></h5> - <h5 class='balanceDue' data-bind='var:order(order/sum/balance_due_total);format:money; currencySign: $; hideZero:false; pretext:Balance Due: ;'></h5> + <h5 data-tlc="bind $var '.order.sum.order_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Order Total: '; apply --append;}};" class="orderTotal"></h5> + <h5 data-tlc="bind $var '.order.sum.balance_due_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Balance Due: '; apply --append;}};" class="balanceDue"></h5> </hgroup> - <address class='marginBottom'> + <address class="marginBottom"> <h4> - <span data-bind='var:order(order/bill/firstname);format:text; pretext:Bill To: ;'></span> - <span data-bind='var:order(order/bill/lastname);format:text;'></span> + <span data-tlc="bind $var '.order.bill.firstname'; if (is $var --notblank;) {{format --prepend='Bill To: '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.lastname'; if (is $var --notblank;) {{apply --append;}};"></span> </h4> - <div data-bind='var:order(order/bill/address1);format:text;'></div> - <div data-bind='var:order(order/bill/address2);format:text;'></div> + <div data-tlc="bind $var '.order.bill.address1'; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.order.bill.address2'; if (is $var --notblank;) {{apply --append;}};"></div> <div> - <span data-bind='var:order(order/bill/city);format:text;posttext:, ;'></span> - <span data-bind='var:order(order/bill/region);format:text;posttext:. ;'></span> - <span data-bind='var:order(order/bill/postal);format:text; defaultVar:order(data.bill_int_zip);'></span> + <span data-tlc="bind $var '.order.bill.city'; if (is $var --notblank;) {{format --append=', '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.region'; if (is $var --notblank;) {{format --append='. '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.postal'; if(is $var --blank;) {{bind $var '.data.bill_int_zip'; }}; if (is $var --notblank;) {{apply --append;}};"></span> </div> - <div data-bind='var:order(order/bill/countrycode);format:text;'></div> + <div data-tlc="bind $var '.order.bill.countrycode'; if (is $var --notblank;) {{apply --append;}};"></div> </address> <address> <h4> - <span data-bind='var:order(order/ship/firstname);format:text; pretext:Ship To: ;'></span> - <span data-bind='var:order(order/ship/lastname);format:text;'></span> + <span data-tlc="bind $var '.order.ship.firstname'; if (is $var --notblank;) {{format --prepend='Ship To: '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.lastname'; if (is $var --notblank;) {{apply --append;}};"></span> </h4> - <div data-bind='var:order(order/ship/address1);format:text;'></div> - <div data-bind='var:order(order/ship/address2);format:text;'></div> + <div data-tlc="bind $var '.order.ship.address1'; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.order.ship.address2'; if (is $var --notblank;) {{apply --append;}};"></div> <div> - <span data-bind='var:order(order/ship/city);format:text;posttext:, ;'></span> - <span data-bind='var:order(order/ship/region);format:text;posttext:. ;'></span> - <span data-bind='var:order(order/ship/postal);format:text; defaultVar:order(data.ship_int_zip);'></span> + <span data-tlc="bind $var '.order.ship.city'; if (is $var --notblank;) {{format --append=', '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.region'; if (is $var --notblank;) {{format --append='. '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.postal'; if(is $var --blank;) {{bind $var '.data.ship_int_zip'; }}; if (is $var --notblank;) {{apply --append;}};"></span> </div> - <div data-bind='var:order(order/ship/countrycode);format:text;'></div> + <div data-tlc="bind $var '.order.ship.countrycode'; if (is $var --notblank;) {{apply --append;}};"></div> </address> </td> - <td class='orderContentsProdlistContainer'> - <ul data-bind='var:order(order/tracking); format:orderTrackingLinks; extension:store_crm;before:<h4>Shipping:</h4>;' class='displayNone noListStyle marginBottom'></ul> - <table class='listStyleNone lineItemProdlist'> - <tbody data-bind="var: order(order/@ITEMS); format:stuffList; loadsTemplate:chkoutInvoiceItemTemplate;"></tbody> + <td class="orderContentsProdlistContainer"> + <ul data-tlc="bind $var '.order.tracking'; store_crm#ordertrackinglinks --legacy;" class="displayNone noListStyle marginBottom"></ul> + <table class="listStyleNone lineItemProdlist"> + <tbody data-tlc="bind $var '.order.@ITEMS'; controller#loop --templateid='chkoutInvoiceItemTemplate'; if (is $var --notblank;) {{apply --append;}};"></tbody> </table> </td> </tr> - </table> + </tbody></table> </div> </div> @@ -518,15 +523,15 @@ <h4> -<div id='cvvcidHelp' class='displayNone' title='Where to find your CVV/CID and why we ask for it'> +<div id="cvvcidHelp" class="displayNone" title="Where to find your CVV/CID and why we ask for it"> <p>For higher security and more efficient processing of your payment, you must provide a card security code to make this purchase.</p> - <div class='floatLeft marginRight'> - <div class='checkoutSprite secCode_vmd' title='Visa/MC/Discover card security code'></div> + <div class="floatLeft marginRight"> + <div class="checkoutSprite secCode_vmd" title="Visa/MC/Discover card security code"></div> <h6>Visa, Mastercard and Discover</h6> <p>The security code is the last section of numbers in the signature area on the back of the card.</p> </div> - <div class='floatLeft'> - <div class='checkoutSprite secCode_amex' title='AMEX card security code'></div> + <div class="floatLeft"> + <div class="checkoutSprite secCode_amex" title="AMEX card security code"></div> <h6>American Express</h6> <p>The security code is the 4-digit number found in small print next to your account number on the front, usually above it on the right.</p> </div> @@ -556,45 +561,35 @@ <h6>American Express</h6> If this gets recycled, test in order history after making changes. --> <table> - <tr id='chkoutInvoiceItemTemplate' class='padMargBorderBottom'> + <tbody><tr id="chkoutInvoiceItemTemplate" class="padMargBorderBottom"> <td> - <div class='prodThumbContainer marginRight'> - <img src='/media/graphics/blank.gif' class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL;' width='55' height='55' /> + <div class="prodThumbContainer marginRight"> + <img data-tlc="bind $var '.%attribs.zoovy:prod_image1'; if (is $var --notblank;) {{ apply --img --media=$var --width=55 --height=55 --bgcolor='#ffffff' --replace;}};" src="/media/graphics/blank.gif" class="prodThumb" height="55" width="55"> </div> </td> - <td class='valignTop ztable_row'> + <td class="valignTop ztable_row"> -<div class='infoContainer'> - - <h3 data-bind='var: product(prod_name); format:text; '></h3> - <div class='ztable_row_small stid' data-bind='var: product(sku); format:text; className: stid; pretext: Sku: ;'></div> +<div class="infoContainer"> + <b data-tlc="bind $var '.prod_name'; if (is $var --notblank;) {{apply --append;}};"></b> + <div data-tlc="bind $var '.sku'; if (is $var --notblank;) {{format --prepend='Sku: '; apply --add --class='stid'; apply --append;}};" class="ztable_row_small stid"></div> + <div> - <span data-bind='var: product(qty); format:text; pretext:qty: ;'></span> - <span data-bind='var: product(price); format:money; currencySign: $; hideZero:false; pretext: x ;' ></span> - <span data-bind='var: product(extended); format:money; currencySign: $; hideZero:false; pretext: = ;'></span> + <span data-tlc="bind $var '.qty'; if (is $var --notblank;) {{format --prepend='qty: '; apply --append;}};"></span> + <span data-tlc="bind $var '.price'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='x '; apply --append;}};"></span> + <span data-tlc="bind $var '.extended'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='= '; apply --append;}};"></span> </div> - - <div class='ztable_row_small prodOptions' data-bind='var: product(%options); format:selectedOptionsDisplay;'></div> - - - + <div data-tlc="bind $var '.%options'; controller#selectedoptionsdisplay --legacy; " class="ztable_row_small prodOptions"></div> </div> </td> - <td class='alignRight hide4Print'> - <button class='writeReview' data-app-event="store_crm|showWriteReview" data-bind='var:product(product);format:assignAttribute; attribute:data-pid;'>Write Review</button> + <td class="alignRight hide4Print"> + <button data-tlc="bind $var '.product'; apply --attrib='data-pid'; " class="writeReview applyButton" data-app-click="store_crm|productReviewShow">Write Review</button> </td> </tr> -</table> - - - - - - +</tbody></table> \ No newline at end of file diff --git a/extensions/checkout/required.html b/extensions/checkout/required.html index 09796dc9c..e2ac04bdd 100644 --- a/extensions/checkout/required.html +++ b/extensions/checkout/required.html @@ -7,43 +7,44 @@ item list and summary are separate just to give more control over location. --> -<div id='checkoutTemplate' class='checkoutFormContainer' data-app-role='checkout'> +<div id="checkoutTemplate" class="checkoutFormContainer" data-app-role="checkout"> - <form action='#' data-app-checkoutmode='required'> - <input type='hidden' name='bill/shortcut' data-bind="var: cart(bill/shortcut); format:popVal;" /> - <input type='hidden' name='ship/shortcut' data-bind="var: cart(ship/shortcut); format:popVal;" /> + <form action="#" data-app-checkoutmode="required"> + <input data-tlc="bind $var '.bill.shortcut'; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/shortcut" type="hidden"> + <input data-tlc="bind $var '.ship.shortcut'; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/shortcut" type="hidden"> + <input data-tlc="bind $var '.cart.cartid'; if(is $var --notblank;) {{apply --select=$var;}}; " name="_cartid" type="hidden"> <!-- define panel order --> - <fieldset data-app-role='chkoutPreflight' class='marginBottom'> - <legend class='headerPadding' >Email / Account Login</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutPreflightTemplate; useParentData:true;'></div> - <div data-app-role='buyerLogout' class='displayNone pointer' data-app-event='orderCreate|buyerLogout'> - Not you? <span class='lookLikeLink zlink'>click here</span>. + <fieldset data-app-role="chkoutPreflight" class="marginBottom"> + <legend class="headerPadding">Email / Account Login</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutPreflightTemplate'; apply --append;" data-legacy-useparentdata="true" class="panelContent"></div> + <div data-app-role="buyerLogout" class="displayNone pointer" data-app-click="order_create|buyerLogout"> + Not you? <span class="lookLikeLink zlink">click here</span>. </div> </fieldset> - <fieldset data-app-role='chkoutAccountCreate' class='displayNone marginBottom'> - <legend class='headerPadding' >Account Creation</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutAccountCreateTemplate; '></div> + <fieldset data-app-role="chkoutAccountCreate" class="displayNone marginBottom"> + <legend class="headerPadding">Account Creation</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAccountCreateTemplate'; apply --append;" class="panelContent"></div> </fieldset> - <fieldset data-app-role='chkoutAddressBill' data-app-addresstype='bill' class='marginBottom displayNone'> - <legend class='headerPadding' >Billing Address</legend> - <p data-app-role='addressExists' class='displayNone clearfix'>Click the checkmark of the address you would like to use</p> + <fieldset data-app-role="chkoutAddressBill" data-app-addresstype="bill" class="marginBottom displayNone"> + <legend class="headerPadding">Billing Address</legend> + <p data-app-role="addressExists" class="displayNone clearfix">Click the checkmark of the address you would like to use</p> - <div class='panelContent displayNone addressList' data-app-role='addressExists' data-bind='var: buyer(@bill); format:processList; loadsTemplate: chkoutBuyerAddressTemplate;'></div><!-- for return customers --> + <div data-tlc="bind $var '.@bill'; controller#loop --templateid='chkoutBuyerAddressTemplate'; if (is $var --notblank;) {{apply --append;}};" class="panelContent displayNone addressList" data-app-role="addressExists"></div><!-- for return customers --> - <div class='clearfix marginBottom' data-app-role='addressExists'><button data-app-event='orderCreate|showBuyerAddressAdd' data-app-addresstype='bill'>Add New Address</button></div> + <div class="clearfix marginBottom" data-app-role="addressExists"><button class="applyButton" data-app-click="order_create|showBuyerAddressAdd" data-app-addresstype="bill">Add New Address</button></div> - <div class='panelContent' data-app-role='addressNew' data-bind='format:loadsTemplate; loadsTemplate: chkoutAddressBillTemplate;'></div><!-- for new customers --> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAddressBillTemplate'; apply --append;" class="panelContent" data-app-role="addressNew"></div><!-- for new customers --> - <div data-app-role='billToShipContainer' > + <div data-app-role="billToShipContainer"> <label> - <input type='checkbox' name='want/bill_to_ship' data-bind="var: cart(want/bill_to_ship); format:popVal; hideZero:false;" checked='checked' data-app-event='orderCreate|tagAsBillToShip' /> + <input data-tlc="bind $var '.want.bill_to_ship'; if(is $var --notblank;) {{apply --select=$var;}}; " name="want/bill_to_ship" checked="checked" class="applyAnycb" data-app-change="order_create|tagAsBillToShip" type="checkbox"> ship to billing address </label> </div> @@ -51,49 +52,49 @@ - <fieldset data-app-role='chkoutAddressShip' data-app-addresstype='ship' class='displayNone marginBottom'> - <legend class='headerPadding' >Shipping Address</legend> - <div class='panelContent displayNone addressList' data-app-role='addressExists' data-bind='var: buyer(@ship); format:processList; loadsTemplate: chkoutBuyerAddressTemplate;'></div><!-- for return customers --> - <div class='panelContent' data-app-role='addressNew' data-bind='format:loadsTemplate; loadsTemplate: chkoutAddressShipTemplate;'></div><!-- for new customers --> - <div class='clearfix' data-app-role='addressExists'><button data-app-event='orderCreate|showBuyerAddressAdd' data-app-addresstype='ship'>Add New Shipping Address</button></div> + <fieldset data-app-role="chkoutAddressShip" data-app-addresstype="ship" class="displayNone marginBottom"> + <legend class="headerPadding">Shipping Address</legend> + <div data-tlc="bind $var '.@ship'; controller#loop --templateid='chkoutBuyerAddressTemplate'; if (is $var --notblank;) {{apply --append;}};" class="panelContent displayNone addressList" data-app-role="addressExists"></div><!-- for return customers --> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutAddressShipTemplate'; apply --append;" class="panelContent" data-app-role="addressNew"></div><!-- for new customers --> + <div class="clearfix" data-app-role="addressExists"><button class="applyButton" data-app-click="order_create|showBuyerAddressAdd" data-app-addresstype="ship">Add New Shipping Address</button></div> </fieldset> - <fieldset data-app-role='chkoutMethodsShip' class='marginBottom displayNone'> - <legend class='headerPadding' >Shipping Methods</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutMethodsShipTemplate;'></div> + <fieldset data-app-role="chkoutMethodsShip" class="marginBottom displayNone"> + <legend class="headerPadding">Shipping Methods</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutMethodsShipTemplate'; apply --append;" class="panelContent"></div> </fieldset> - <fieldset data-app-role='chkoutMethodsPay' class='marginBottom displayNone'> - <legend class='headerPadding' >Payment Choices</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutMethodsPayTemplate;'></div> + <fieldset data-app-role="chkoutMethodsPay" class="marginBottom displayNone"> + <legend class="headerPadding">Payment Choices</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutMethodsPayTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- totals et all --> - <fieldset data-app-role='chkoutNotes' class='marginBottom displayNone'> - <legend class='headerPadding' >Order Notes/Special Instructions</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutNotesTemplate;'></div> + <fieldset data-app-role="chkoutNotes" class="marginBottom displayNone"> + <legend class="headerPadding">Order Notes/Special Instructions</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutNotesTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- line items --> - <fieldset data-app-role='chkoutCartItemsList' class='marginBottom displayNone'> - <legend class='headerPadding' >Contents</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutCartContentsTemplate;'></div> + <fieldset data-app-role="chkoutCartItemsList" class="marginBottom displayNone"> + <legend class="headerPadding">Contents</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutCartContentsTemplate'; apply --append;" class="panelContent"></div> </fieldset> <!-- totals et all --> - <fieldset data-app-role='chkoutCartSummary' class='marginBottom displayNone'> - <legend class='headerPadding' >Summary</legend> - <div class='panelContent' data-bind='format:loadsTemplate; loadsTemplate: chkoutCartSummaryTemplate;'></div> + <fieldset data-app-role="chkoutCartSummary" class="marginBottom displayNone"> + <legend class="headerPadding">Summary</legend> + <div data-tlc="bind $var '.'; transmogrify --dataset=$var --templateid='chkoutCartSummaryTemplate'; apply --append;" class="panelContent"></div> </fieldset> </form> @@ -103,11 +104,11 @@ -<section id='chkoutPreflightTemplate'> +<section id="chkoutPreflightTemplate"> -<h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email); defaultVar: cart(customer/login); format:text;"></h4> +<h4 data-tlc="bind $var '.bill.email'; if(is $var --blank;) {{bind $var '.customer.login'; }}; if (is $var --notblank;) {{apply --append;}};" class="displayNone" data-app-role="username"></h4> -<div data-app-role='login'> +<div data-app-role="login"> <!-- not used in required <div data-app-role='loginPasswordContainer' class='displayNone floatRight'> @@ -115,10 +116,10 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) </div> --> - <input type='email' name='bill/email' required='required' size='30' placeholder="email address" data-bind="var:cart(bill/email); defaultVar:cart(customer/login); format:popVal;" data-app-event='orderCreate|execBuyerEmailUpdate' /> <input type='password' placeholder='password' size='30' name='password' /> <button data-app-event='orderCreate|execBuyerLogin'>login</button> + <input data-tlc="bind $var '.bill.email'; if(is $var --blank;) {{bind $var '.customer.login'; }}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/email" required size="30" placeholder="email address" data-app-blur="order_create|execBuyerEmailUpdate" type="email"> <input placeholder="password" size="30" name="password" type="password"> <button class="applyButton" data-app-click="order_create|execBuyerLogin">login</button> <!-- not used in required - <label class='accountCreateContainer'><input type='checkbox' name='want/create_customer' data-app-event='orderCreate|tagAsAccountCreate' />Create customer account</label> + <label class='accountCreateContainer'><input type='checkbox' name='want/create_customer' class='applyAnycb' data-app-change='order_create|tagAsAccountCreate' />Create account</label> --> @@ -129,37 +130,34 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) - - - - - <!-- billing address panel spec This template is also used in the myAccount page, which is why a default using _ is present. +This template is used both in the billing address panel AND in the address editor (if logged in). in the address editor, the data is formatted as bill/address1 +because the panel is shared, the events (which aren't desired in the editor) are added by the checkout extension. --> -<section id='chkoutAddressBillTemplate'> +<section id="chkoutAddressBillTemplate"> - <div><input type='text' placeholder='first name' name='bill/firstname' required='required' value='' data-bind='var: cart(bill/firstname); defaultVar: cart(bill/firstname); format:popVal;' /></div> - <div><input type='text' placeholder='last name' name='bill/lastname' required='required' value='' data-bind='var: cart(bill/lastname); defaultVar: cart(bill/lastname); format:popVal;' /></div> + <div><input data-tlc="bind $var '.bill.firstname'; if(is $var --blank;){{bind $var '.bill/firstname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="bill/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.bill.lastname'; if(is $var --blank;){{bind $var '.bill/lastname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="bill/lastname" required value="" type="text"></div> - <div class='bill_company'><input type='text' name='bill/company' placeholder='company' value='' data-bind='var: cart(bill/company); defaultVar: cart(bill/company); format:popVal;' /></div><!-- class is added so it can be easily disabled w/ css --> + <div class="bill_company"><input data-tlc="bind $var '.bill.company'; if(is $var --blank;){{bind $var '.bill/company';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> - <div><input type='text' name='bill/address1' placeholder='address' required='required' value='' data-bind='var: cart(bill/address1); defaultVar: cart(bill/address1); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.address1'; if(is $var --blank;){{bind $var '.bill/address1';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/address1" placeholder="address" required value="" type="text"></div> - <div><input type='text' name='bill/address2' placeholder='address 2' value='' data-bind='var: cart(bill/address2); defaultVar: cart(bill/address2); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.address2'; if(is $var --blank;){{bind $var '.bill/address2';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/address2" placeholder="address 2" value="" type="text"></div> - <div><input type='text' name='bill/city' placeholder='city' required='required' value='' data-bind='var: cart(bill/city); defaultVar: cart(bill/city); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.city'; if(is $var --blank;){{bind $var '.bill/city';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/city" placeholder="city" required value="" type="text"></div> - <div><input type='text' name='bill/region' placeholder='state/region' required='required' size='5' value='' data-bind='var: cart(bill/region); defaultVar: cart(bill/region); format:popVal;' maxlength='20' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.region'; if(is $var --blank;){{bind $var '.bill/region';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/region" placeholder="state/region" required size="5" value="" maxlength="20" type="text"></div> <!-- postal not required for international. don't add it. --> - <div><input type='text' name='bill/postal' placeholder='zip/postal code' required='required' size='14' value='' data-bind='var: cart(bill/postal); defaultVar: cart(bill/postal); format:popVal;' maxlength='10' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.bill.postal'; if(is $var --blank;){{bind $var '.bill/postal';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" type="text"></div> - <div class='billCountry' data-app-role='billCountry'><select name='bill/countrycode' placeholder='country' data-bind='var: cart(bill/countrycode); defaultVar: cart(bill/countrycode); defaultValue:US; format:countriesAsOptions; extension: cco;forceRender:1;' required='required' data-app-event="orderCreate|execCountryUpdate" ></select></div> + <div class="billCountry" data-app-role="billCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='bill' --legacy;" data-legacy-useparentdata="true" name="bill/countrycode" placeholder="country" required="required"><option value=''>Please choose</option></select></div> - <div><input type='tel' name='bill/phone' placeholder='phone number' required='required' value='' data-bind='var: cart(bill/phone); defaultVar: cart(bill/phone); format:popVal;' /> <span class='hint zhint'>in case of billing/delivery problems</span></div> + <div><input data-tlc="bind $var '.bill.phone'; if(is $var --blank;){{bind $var '.bill/phone';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="bill/phone" placeholder="phone number" required value="" type="tel"> <span class="hint zhint">in case of billing/delivery problems</span></div> </section> @@ -167,49 +165,86 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) + +<!-- +shipping address panel. +don't add required to any inputs because if bill to ship is checked, NONE of these fields are required/populated. +This template is used both in the shipping panel AND in the address editor (if logged in). in the address editor, the data is formatted as ship/address1 +because the panel is shared, the events (which aren't desired in the editor) are added by the checkout extension. +--> + +<section id="chkoutAddressShipTemplate"> + + <div><input data-tlc="bind $var '.ship.firstname'; if(is $var --blank;){{bind $var '.ship/firstname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="ship/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.ship.lastname'; if(is $var --blank;){{bind $var '.ship/lastname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="ship/lastname" required value="" type="text"></div> + + <div class="bill_company"><input data-tlc="bind $var '.ship.company'; if(is $var --blank;){{bind $var '.ship/company';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> + + <div><input data-tlc="bind $var '.ship.address1'; if(is $var --blank;){{bind $var '.ship/address1';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address1" placeholder="address" required value="" type="text"></div> + + <div><input data-tlc="bind $var '.ship.address2'; if(is $var --blank;){{bind $var '.ship/address2';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address2" placeholder="address 2" value="" type="text"></div> + + <div><input data-tlc="bind $var '.ship.city'; if(is $var --blank;){{bind $var '.ship/city';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/city" placeholder="city" required value="" type="text"></div> + + <div><input data-tlc="bind $var '.ship.region'; if(is $var --blank;){{bind $var '.ship/region';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/region" placeholder="state/region" required size="5" value="" maxlength="20" type="text"></div> + + <div><input data-tlc="bind $var '.ship.postal'; if(is $var --blank;){{bind $var '.ship/postal';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" type="text"></div> + + <div class="shipCountry" data-app-role="shipCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='ship' --legacy;" data-legacy-useparentdata="true" name="ship/countrycode" placeholder="country"></select></div> + +</section> + + + + <!-- shipping address panel. don't add required to any inputs because if bill to ship is checked, NONE of these fields are required/populated. +This template is used both in the shipping panel AND in the address editor (if logged in). in the address editor, the data is formatted as ship/address1 --> -<section id='chkoutAddressShipTemplate'> +<section id="chkoutAddressShipTemplate"> - <div><input type='text' placeholder='first name' name='ship/firstname' required='required' value='' data-bind='var: cart(ship/firstname); defaultVar: cart(ship/firstname); format:popVal;' /></div> - <div><input type='text' placeholder='last name' name='ship/lastname' required='required' value='' data-bind='var: cart(ship/lastname); defaultVar: cart(ship/lastname); format:popVal;' /></div> + <div><input data-tlc="bind $var '.ship.firstname'; if(is $var --blank;){{bind $var '.ship/firstname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="first name" name="ship/firstname" required value="" type="text"></div> + <div><input data-tlc="bind $var '.ship.lastname'; if(is $var --blank;){{bind $var '.ship/lastname';}}; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="last name" name="ship/lastname" required value="" type="text"></div> - <div class='bill_company'><input type='text' name='ship/company' placeholder='company' value='' data-bind='var: cart(ship/company); defaultVar: cart(ship/company); format:popVal;' /></div><!-- class is added so it can be easily disabled w/ css --> + <div class="bill_company"><input data-tlc="bind $var '.ship.company'; if(is $var --blank;){{bind $var '.ship/company';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/company" placeholder="company" value="" type="text"></div><!-- class is added so it can be easily disabled w/ css --> - <div><input type='text' name='ship/address1' placeholder='address' required='required' value='' data-bind='var: cart(ship/address1); defaultVar: cart(ship/address1); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.address1'; if(is $var --blank;){{bind $var '.ship/address1';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address1" placeholder="address" required value="" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='ship/address2' placeholder='address 2' value='' data-bind='var: cart(ship/address2); defaultVar: cart(ship/address2); format:popVal;' /></div> + <div><input data-tlc="bind $var '.ship.address2'; if(is $var --blank;){{bind $var '.ship/address2';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/address2" placeholder="address 2" value="" type="text"></div> - <div><input type='text' name='ship/city' placeholder='city' required='required' value='' data-bind='var: cart(ship/city); defaultVar: cart(ship/city); format:popVal;' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.city'; if(is $var --blank;){{bind $var '.ship/city';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/city" placeholder="city" required value="" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='ship/region' placeholder='state/region' required='required' size='5' value='' data-bind='var: cart(ship/region); defaultVar: cart(ship/region); format:popVal;' maxlength='20' data-app-event='orderCreate|execAddressUpdate' /></div> + <div><input data-tlc="bind $var '.ship.region'; if(is $var --blank;){{bind $var '.ship/region';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/region" placeholder="state/region" required size="5" value="" maxlength="20" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div><input type='text' name='ship/postal' placeholder='zip/postal code' required='required' size='14' value='' data-bind='var: cart(ship/postal); defaultVar: cart(ship/postal); format:popVal;' maxlength='10' data-app-event='orderCreate|execAddressUpdate'/></div> + <div><input data-tlc="bind $var '.ship.postal'; if(is $var --blank;){{bind $var '.ship/postal';}}; if(is $var --notblank;) {{apply --select=$var;}}; " name="ship/postal" placeholder="zip/postal code" required size="14" value="" maxlength="10" data-app-blur="order_create|execAddressUpdate" type="text"></div> - <div class='shipCountry' data-app-role='shipCountry'><select name='ship/countrycode' placeholder='country' data-bind='var: cart(ship/countrycode); defaultVar: cart(ship/countrycode); defaultValue:US; format:countriesAsOptions; extension: cco;forceRender:1;' data-app-event="orderCreate|execCountryUpdate" ></select></div> + <div class="shipCountry" data-app-role="shipCountry"><select data-tlc="bind $var '.'; cco#countriesasoptions --shiptype='ship' --legacy;" data-legacy-useparentdata="true" name="ship/countrycode" placeholder="country" data-app-change="order_create|execCountryUpdate"></select></div> </section> + + + + <!-- a panel that only appears in 'nice' --> -<section id='chkoutAccountCreateTemplate'> +<section id="chkoutAccountCreateTemplate"> -<div><input type='password' data-minlength='8' placeholder='password' required='required' name='want/new_password' size='12' data-bind='var: cart(want/new_password); format:popVal;' /> <span class='hint'>must be at least 8 characters</span></div> -<div><input type='password' data-minlength='8' placeholder='verify password' required='required' name='want/new_password2' size='12' data-bind='var: cart(want/new_password2); format:popVal;' /></div> +<div><input data-tlc="bind $var '.want.new_password'; if(is $var --notblank;) {{apply --select=$var;}}; " data-minlength="8" placeholder="password" required name="want/new_password" size="12" type="password"> <span class="hint">must be at least 8 characters</span></div> +<div><input data-tlc="bind $var '.want.new_password2'; if(is $var --notblank;) {{apply --select=$var;}}; " data-minlength="8" placeholder="verify password" required name="want/new_password2" size="12" type="password"></div> <label>Recovery Question -<select name='want/recovery_hint' data-bind='var: cart(want/recovery_hint); format:popVal;'> - <option value='2'>Name of your favorite childhood pet?</option> - <option value='3'>City you were born in?</option> - <option value='4'>Last name of your best friend growing up?</option> - <option value='5'>Last city you lived in?</option> +<select data-tlc="bind $var '.want.recovery_hint'; if(is $var --notblank;) {{apply --select=$var;}}; " name="want/recovery_hint"> + <option value="2">Name of your favorite childhood pet?</option> + <option value="3">City you were born in?</option> + <option value="4">Last name of your best friend growing up?</option> + <option value="5">Last city you lived in?</option> </select> </label> -<input type='text' placeholder='recovery answer' required='required' value='' name='want/recovery_answer' maxlength='20' size='20' data-bind='var: cart(want/recovery_answer); format:popVal;' /></label> +<input data-tlc="bind $var '.want.recovery_answer'; if(is $var --notblank;) {{apply --select=$var;}}; " placeholder="recovery answer" required value="" name="want/recovery_answer" maxlength="20" size="20" type="text"> </section> @@ -221,8 +256,9 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) messaging are hidden by default, then displayed if needed. keeps panel from being jittery. --> -<div id='chkoutMethodsShipTemplate'> - <ul class='noPadOrMargin listStyleNone' data-bind='var: cart(@SHIPMETHODS); format:shipMethodsAsRadioButtons; extension: orderCreate;' data-app-event='orderCreate|addTriggerShipMethodUpdate'></ul> +<div id="chkoutMethodsShipTemplate"> + <ul data-tlc="bind $var '.'; order_create#shipmethodsasradiobuttons --legacy;" data-legacy-useparentdata="true" class="noPadOrMargin listStyleNone"></ul> + <div data-app-role="upsShipRulesDisclaimer" class="upsShipRulesDisclaimer displayNone">These fees do not necessarily represent UPS published rates and may include handling charges by our company.</div> </div> @@ -238,34 +274,35 @@ <h4 class='displayNone' data-app-role='username' data-bind="var:cart(bill/email) --> -<div id='chkoutMethodsPayTemplate'> +<div id="chkoutMethodsPayTemplate"> - <div class='giftCardContainer' data-app-role="giftcardContainer"> - <label for='giftcardCode'>Gift Certificate Code:</label> - <input type='text' name='giftcard' size='16' data-app-event='orderCreate|addTriggerButtonClick' /> - <button data-app-event='orderCreate|execGiftcardAdd'>add</button> - <small data-app-role='giftcardHint' class='zhint hint displayNone'>if you wish to combine gift cards with another payment method, enter them here</small> + <div class="giftCardContainer" data-app-role="giftcardContainer"> + <label for="giftcardCode">Gift Certificate Code:</label> + <input name="giftcard" size="16" data-input-keyup="trigger-button-id" data-input-format="alphanumeric" data-trigger-button-id="execGiftcardAdd" type="text"> + <button class="applyButton" data-app-click="order_create|execGiftcardAdd" data-button-id="execGiftcardAdd">add</button> + <p data-app-role="giftcardHint" class="zhint hint displayNone">if you wish to combine gift cards with another payment method, enter them here</p> </div> - <div data-app-role='paymentQContainer' class='marginBottom'> - <ul class='noPadOrMargin listStyleNone' data-bind='var: cart(@PAYMENTQ); format:processList; loadsTemplate:cartPaymentQTemplate;'></ul> + <div data-app-role="paymentQContainer" class="marginBottom"> + <ul data-tlc="bind $var '.@PAYMENTQ'; controller#loop --templateid='cartPaymentQTemplate'; if (is $var --notblank;) {{apply --append;}};" class="noPadOrMargin listStyleNone"></ul> </div> <!-- used in paypal transactions to cancel as paypal --> - <div data-app-event='orderCreate|execChangeFromPayPal' class='displayNone pointer zlink'> + <div data-app-click="order_create|execChangeFromPayPal" class="displayNone pointer zlink"> Choose Alternate Payment Method </div> <!-- more payment types is first but, when applicable, stored payments is shown. That way stored payments are easily selected but it's hard to miss that other payment choices are available. --> - <div data-app-role='paymentOptionsContainer' data-app-event="orderCreate|addTriggerPayMethodUpdate"> + <div data-app-role="paymentOptionsContainer" data-app-event="order_create|addTriggerPayMethodUpdate"> - <h2 data-app-role='nonStoredPaymentsHeader' class='displayNone'>More Payment Choices</h2> - <div data-app-role='nonStoredPaymentsContent'> - <div data-bind='var: getPaymentMethods(@methods); format:payMethodsAsRadioButtons; extension: orderCreate;'></div> + <h2 data-app-role="nonStoredPaymentsHeader" class="displayNone">More Payment Choices</h2> + <div data-app-role="nonStoredPaymentsContent"> + <div data-tlc="bind $var '.cart.cartid'; order_create#paymethodsasradiobuttons --legacy;"></div> </div> - <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payments</h2> - <div data-app-role='storedPaymentsContent' class='displayNone' data-bind="var: buyerWalletList(@wallets); format:processList; loadsTemplate: chkoutBuyerWalletListItem;"></div> + <h2 data-app-role="storedPaymentsHeader" class="displayNone">Your Stored Payments</h2> + <!-- The # of children in the storedPaymentContents triggers wallet display. Do not add any children to this div. --> + <div data-tlc="bind $var '.@wallets'; controller#loop --templateid='chkoutBuyerWalletListItem'; if (is $var --notblank;) {{apply --append;}};" data-app-role="storedPaymentsContent" class="displayNone"></div> </div> @@ -282,32 +319,31 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment the defaultVar on prodName & image is for promotions, which have a 'description' attribute --> <table> -<tr id='chkoutCartItemTemplate'> - <td><img class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL; defaultVar: product(%attribs.zoovy:prod_image1);' width='50' height='50' /></td> +<tbody><tr id="chkoutCartItemTemplate"> + <td><img data-tlc="bind $var '.%attribs.zoovy:prod_thumb'; if(is $var --blank;) {{bind $var '.%attribs.zoovy:prod_image1'; }}; if (is $var --notblank;) {{ apply --img --media=$var --width=50 --height=50 --bgcolor='#ffffff' --replace;}};" class="prodThumb" height="50" width="50"></td> <td> - <div class='prodName' data-bind='var: product(prod_name); format:text; defaultVar: description;'></div> - <div class='stid' data-bind='var: product(sku); format:text; className: stid; pretext: Sku: ;'></div> - <div class='prodLatency' data-bind='var:product(%attribs.zoovy:ship_latency); format:text; pretext:Normally ships in ; posttext: day(s);'></div> - <div class='prodOptions' data-bind='var: variations(%options); format:selectedOptionsDisplay;'></div> + <div data-tlc="bind $var '.prod_name'; if(is $var --blank;) {{bind $var '.description'; }}; if (is $var --notblank;) {{apply --append;}};" class="prodName"></div> + <div data-tlc="bind $var '.sku'; if (is $var --notblank;) {{format --prepend='Sku: '; apply --add --class='stid'; apply --append;}};" class="stid"></div> + <div data-tlc="bind $var '.%attribs.zoovy:ship_latency'; if (is $var --notblank;) {{format --prepend='Normally ships in '; format --append=' day(s)'; apply --append;}};" class="prodLatency"></div> + <div data-tlc="bind $var '.%options'; controller#selectedoptionsdisplay --legacy; " class="prodOptions"></div> </td> - <td class='alignRight'><span data-bind='var: product(qty); format:text;'></span></td> - <td class='alignRight'><span data-bind='var: product(price); format:money; currencySign: $; hideZero:false; pretext: x ;'></span></td> - <td class='alignRight'><span data-bind='var: product(extended); format:money; currencySign: $; hideZero:false; pretext: = ;'></span></td> + <td class="alignRight"><span data-tlc="bind $var '.qty'; if (is $var --notblank;) {{apply --append;}};"></span></td> + <td class="alignRight"><span data-tlc="bind $var '.price'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='x '; apply --append;}};"></span></td> + <td class="alignRight"><span data-tlc="bind $var '.extended'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='= '; apply --append;}};"></span></td> </tr> -</table> +</tbody></table> - -<section id='chkoutCartContentsTemplate'> -<table class='fullWidth gridTable'> +<section id="chkoutCartContentsTemplate"> +<table class="fullWidth gridTable"> <thead> <tr> - <th colspan='2' class='alignLeft'>product information</th> - <th class='alignRight'>qty</th> - <th class='alignRight'>price</th> - <th class='alignRight'>item total</th> + <th colspan="2" class="alignLeft">product information</th> + <th class="alignRight">qty</th> + <th class="alignRight">price</th> + <th class="alignRight">item total</th> </tr> </thead> -<tbody data-bind='var: cart(@ITEMS); format:processList; loadsTemplate:chkoutCartItemTemplate;'></tbody> +<tbody data-tlc="bind $var '.@ITEMS'; controller#loop --templateid='chkoutCartItemTemplate'; if (is $var --notblank;) {{apply --append;}};" data-app-role="cartItemsTbody"></tbody> </table> </section> @@ -318,38 +354,39 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment -<section id='chkoutCartSummaryTemplate'> +<section id="chkoutCartSummaryTemplate"> - <div data-bind="var: cart(sum/items_total); format:money; className:orderSubtotal; hideZero:false; currencySign: $; pretext:Subtotal: ; "></div> - <div data-bind='var: cart(sum/tax_total); format:money; className:orderTax; hideZero:true;currencySign: $; pretext:Tax: ; '></div> - <div data-bind='var: cart(want/shipping_id); format:shipInfoById; className:orderShipping; hideZero:false; extension:cco;'></div> - <div data-bind='var: cart(sum/hnd_total); format:money; className:hndTotal; currencySign: $; pretext:Handling: ; '></div> - <div data-bind='var: cart(sum/order_total); format:money; className:orderTotal; hideZero:false; currencySign: $; pretext:Order Total: ; '></div> - <div data-bind='var: cart(sum/gfc_total); format:money; className:orderGiftcardTotal; currencySign: $; pretext:Giftcard(s): ; '></div> - <div data-bind='var: cart(sum/pnt_total); format:money; className:rewardPointsTotal; currencySign: $; pretext:Reward Points: ; '></div> - <div data-bind='var: cart(sum/rmc_total); format:money; className:returnsCreditTotal; currencySign: $; pretext:Returns Credit: ; '></div> - <div data-bind='var: cart(sum/spc_total); format:money; className:spcTotal; currencySign: $; pretext:Specialty: ; '></div> - - <div data-bind='var: cart(sum/balance_due_total); format:orderBalance; className:orderBalanceDue; hideZero:false; currencySign: $; pretext:Balance Due: ; extension:cco;'></div> - - <div class='couponEntryContainer clearfix marginBottom' data-app-role='couponContainer'> - <label for='coupon'>Coupon/Promo Code:</label> - <input type='text' name='coupon' size='8' data-app-event='orderCreate|addTriggerButtonClick' /> - <button data-app-event="orderCreate|execCouponAdd" >add</button> + <div data-tlc="bind $var '.sum.items_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Subtotal: '; apply --add --class='orderSubtotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.tax_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Tax: '; apply --add --class='orderTax'; apply --append;}};"></div> + <div data-tlc="bind $var '.'; cco#shipinfobyid --legacy;" data-legacy-useparentdata="true" class="orderShipping"></div> + <div data-tlc="bind $var '.sum.hnd_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Handling: '; apply --add --class='hndTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.order_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Order Total: '; apply --add --class='orderTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.gfc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Giftcard(s): '; apply --add --class='orderGiftcardTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.pnt_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Reward Points: '; apply --add --class='rewardPointsTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.rmc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Returns Credit: '; apply --add --class='returnsCreditTotal'; apply --append;}};"></div> + <div data-tlc="bind $var '.sum.spc_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Specialty: '; apply --add --class='spcTotal'; apply --append;}};"></div> + + <div data-tlc="bind $var '.sum.balance_due_total'; cco#orderbalance --classname='orderBalanceDue' --hidezero='false' --currencysign='$' --legacy;"></div> + + <div class="couponEntryContainer clearfix marginBottom" data-app-role="couponContainer"> + <label for="coupon">Coupon/Promo Code:</label> + <input name="coupon" size="8" data-input-keyup="trigger-button-id" data-trigger-button-id="execCouponAdd" data-input-format="alphanumeric" type="text"> + <button class="applyButton" data-app-click="order_create|execCouponAdd" data-button-id="execCouponAdd">add</button> + </div> + <!-- will appear if company field is populated AND payment method is NOT PO --> + <div data-app-role="referenceNumber" class="displayNone"> + <label>Purchase Order/Reference #: </label> + <input type'text'="" name="want/reference_number" size="12"> </div> - <button data-app-event="orderCreate|execCartOrderCreate"> + <button class="ui-state-highlight applyButton" data-app-click="order_create|execCartOrderCreate"> Place Order </button> -<div data-app-role='referenceNumber' class='displayNone'> - <label>Purchase Order/Reference #: </label> - <input type'text' name='want/reference_number' size='12' /> -</div> -</section> +</section> @@ -358,12 +395,13 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment -<address id='chkoutBuyerAddressTemplate' class='ui-widget ui-widget-content ui-corner-all stdPadding'> - <div data-bind="var:address(bill/address1); defaultVar: address(ship/address1); format:text;"></div> - <div data-bind="var:address(bill/postal); defaultVar: address(ship/postal); format:text;"></div> - <div class='clearfix'> - <button class='floatRight' data-app-event='orderCreate|execBuyerAddressSelect'>Use This Address</button> - <button class='floatRight marginRight' data-app-event="orderCreate|showBuyerAddressUpdate">Edit This Address</button> +<!-- there is display logic looking for the number of address elements in addressExists. do not change element try w/out updating display logic. --> +<address id="chkoutBuyerAddressTemplate" class="ui-widget ui-widget-content ui-corner-all stdPadding"> + <div data-tlc="bind $var '.bill/address1'; if(is $var --blank;) {{bind $var '.ship/address1'; }}; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.bill/postal'; if(is $var --blank;) {{bind $var '.ship/postal'; }}; if (is $var --notblank;) {{apply --append;}};"></div> + <div class="clearfix"> + <button class="floatRight applyButton" data-app-click="order_create|execBuyerAddressSelect" data-icon="false" data-icon-primary="ui-icon-check">Use This Address</button> + <button class="floatRight marginRight applyButton" data-app-role="addressEditButton" data-app-click="order_create|showBuyerAddressUpdate" data-icon="false" data-icon-primary="ui-icon-pencil">Edit</button> </div> </address> @@ -373,20 +411,20 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment <ul> - <li id='cartPaymentQTemplate'> - <span data-bind="var:payment(TN); format:text;"></span> - <span class='marginLeft' data-bind="var:payment($$); format:money; currencySign: $; hideZero:false;"></span><span data-bind="var:payment($#); format:money; currencySign: $; pretext:/;"></span> -<!-- <button class='marginLeft' title='Remove this payment method'>X</button> --> + <li id="cartPaymentQTemplate"> + <span data-tlc="bind $var '.TN'; if (is $var --notblank;) {{apply --append;}};"></span> + <span data-tlc="bind $var '.$$'; if (is $var --notblank;) {{format --currency='USD'; apply --append;}};" class="marginLeft"></span><span data-tlc="bind $var '.$#'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='/'; apply --append;}};"></span> +<!-- <button class='marginLeft applyButton' title='Remove this payment method'>X</button> --> </li> </ul> <!-- radio name is same as rest of payments so that only 1 can be selected and form still easily passes validation --> -<div id='chkoutBuyerWalletListItem'> +<div id="chkoutBuyerWalletListItem"> <label> - <input type='radio' name='want/payby' value='' data-bind="var: wallet(ID); format:setVal;" /> - <span data-bind="var: wallet(TD); format:text;"></span> - <span data-bind="var: wallet(TD); format: walletName2Icon; extension:cco;"></span> + <input data-tlc="bind $var '.ID'; apply --inputvalue; " name="want/payby" value="" type="radio" data-app-change='order_create|shipOrPayMethodSelectExec'> + <span data-tlc="bind $var '.TD'; if (is $var --notblank;) {{apply --append;}};"></span> + <span data-tlc="bind $var '.TD'; cco#walletnameintoicon --legacy;"></span> </label> </div> @@ -396,9 +434,9 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment do NOT change the input name or id or checkout will likely break. --> -<div id='chkoutNotesTemplate'> +<div id="chkoutNotesTemplate"> <p>Please include any special instructions or comments here:</p> -<textarea class='chkoutOrderNotes fullWidth' name='want/order_notes' data-app-event='orderCreate|execCartSet' data-bind='var: cart(want/order_notes); format:popVal;' rows='5'></textarea> +<textarea data-tlc="bind $var '.want.order_notes'; if(is $var --notblank;) {{apply --select=$var;}}; " class="chkoutOrderNotes fullWidth" name="want/order_notes" data-app-blur="order_create|execCartSet" rows="5"></textarea> </div> @@ -412,98 +450,91 @@ <h2 data-app-role='storedPaymentsHeader' class='displayNone'>Your Stored Payment <!-- used after a successful checkout. --> -<div id='chkoutCompletedTemplate' class='checkoutSuccess'> - - <div class='floatRight ocmThirdParty'> - <h2>What next?</h2> -<!-- the twitter and facebook actions are added post checkout. The order contents are included as part of the message --> - <div class='ocm ocmFacebookComment pointer zlink marginBottom checkoutSprite '></div> - <div class='ocm ocmTwitterComment pointer zlink marginBottom checkoutSprit ' ></div> - <div class='ocm ocmContinue pointer zlink marginBottom checkoutSprite'></div> +<div id="chkoutCompletedTemplate" class="checkoutSuccess"> - </div> + <div class="floatRight ocmThirdParty" data-app-role="thirdPartyContainer"></div> - <div class='orderSummaryDetails'> + <div class="orderSummaryDetails"> <h2>Thank you! Your order has been placed.</h2> - <h3 data-bind='var: order(orderid); format:text; pretext:Your order id is ;'></h3> - <div class='pointer marginBottom' data-app-role='paymentMessaging'> + <h3 data-tlc="bind $var '.orderid'; if (is $var --notblank;) {{format --prepend='Your order id is '; apply --append;}};"></h3> + <div class="pointer marginBottom" data-app-role="paymentMessaging"> Click here to view/print your invoice. - <div class='zwarn' data-bind="var: order(payment_status_msg); format:text;"></div><!-- displays payment issues/errors --> + <div data-tlc="bind $var '.payment_status_msg'; if (is $var --notblank;) {{apply --append;}};" class="zwarn"></div><!-- displays payment issues/errors --> </div> - <div data-bind="var:order(payment_status_detail); format:text;" class='marginBottom'></div> - <div>You will receive an order confirmation email with details of your order</div> + <div data-tlc="bind $var '.payment_status_detail'; if (is $var --notblank;) {{apply --append;}};" class="marginBottom"></div> + <div>You will receive an order confirmation email with details of your order.</div> </div> - <div class='clearAll'></div> - <span id='BuySafeGuaranteeSpan'></span> - <div class='clearAll'></div> + <div class="clearAll"></div> + <span id="BuySafeGuaranteeSpan"></span> + <div class="clearAll"></div> -<div data-app-role='invoiceContainer'> - <table class='orderContentsTable fullWidth'> - <tr> - <td colspan='2'> - <div class='floatRight hide4Print'> - <button data-app-event="orderCreate|execInvoicePrint">Print Invoice</button> +<div data-app-role="invoiceContainer"> + <table class="orderContentsTable fullWidth"> + <tbody><tr> + <td colspan="2"> + <div class="floatRight hide4Print"> + <button class="applyButton" data-app-click="order_create|execInvoicePrint">Print Invoice</button> </div> - - <h3 data-bind='var:order(order/data/pool);format:text; pretext:Order Status: ;'></h3> + <h2 data-tlc="bind $var '.order.our.orderid'; if (is $var --notblank;) {{apply --append;}};"></h2> + <h3 data-tlc="bind $var '.order.data.pool'; if (is $var --notblank;) {{format --prepend='Order Status: '; apply --append;}};"></h3> </td> </tr> <tr> <td> - <hgroup class='marginBottom'> + <hgroup class="marginBottom"> <!-- print icon --> <!-- <h2 data-bind='var:order(bill/firstname);format:text; pretext:Shipping Status: ;'></h2> --> - <h5 class='orderTotal' data-bind='var:order(order/sum/order_total);format:money; currencySign: $; hideZero:false; pretext:Order Total: ;'></h5> - <h5 class='balanceDue' data-bind='var:order(order/sum/balance_due_total);format:money; currencySign: $; hideZero:false; pretext:Balance Due: ;'></h5> + <h5 data-tlc="bind $var '.order.sum.order_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Order Total: '; apply --append;}};" class="orderTotal"></h5> + <h5 data-tlc="bind $var '.order.sum.balance_due_total'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='Balance Due: '; apply --append;}};" class="balanceDue"></h5> </hgroup> - <address class='marginBottom'> + <address class="marginBottom"> <h4> - <span data-bind='var:order(order/bill/firstname);format:text; pretext:Bill To: ;'></span> - <span data-bind='var:order(order/bill/lastname);format:text;'></span> + <span data-tlc="bind $var '.order.bill.firstname'; if (is $var --notblank;) {{format --prepend='Bill To: '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.lastname'; if (is $var --notblank;) {{apply --append;}};"></span> </h4> - <div data-bind='var:order(order/bill/address1);format:text;'></div> - <div data-bind='var:order(order/bill/address2);format:text;'></div> + <div data-tlc="bind $var '.order.bill.address1'; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.order.bill.address2'; if (is $var --notblank;) {{apply --append;}};"></div> <div> - <span data-bind='var:order(order/bill/city);format:text;posttext:, ;'></span> - <span data-bind='var:order(order/bill/region);format:text;posttext:. ;'></span> - <span data-bind='var:order(order/bill/postal);format:text; defaultVar:order(data.bill_int_zip);'></span> + <span data-tlc="bind $var '.order.bill.city'; if (is $var --notblank;) {{format --append=', '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.region'; if (is $var --notblank;) {{format --append='. '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.bill.postal'; if(is $var --blank;) {{bind $var '.data.bill_int_zip'; }}; if (is $var --notblank;) {{apply --append;}};"></span> </div> - <div data-bind='var:order(order/bill/countrycode);format:text;'></div> + <div data-tlc="bind $var '.order.bill.countrycode'; if (is $var --notblank;) {{apply --append;}};"></div> </address> <address> <h4> - <span data-bind='var:order(order/ship/firstname);format:text; pretext:Ship To: ;'></span> - <span data-bind='var:order(order/ship/lastname);format:text;'></span> + <span data-tlc="bind $var '.order.ship.firstname'; if (is $var --notblank;) {{format --prepend='Ship To: '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.lastname'; if (is $var --notblank;) {{apply --append;}};"></span> </h4> - <div data-bind='var:order(order/ship/address1);format:text;'></div> - <div data-bind='var:order(order/ship/address2);format:text;'></div> + <div data-tlc="bind $var '.order.ship.address1'; if (is $var --notblank;) {{apply --append;}};"></div> + <div data-tlc="bind $var '.order.ship.address2'; if (is $var --notblank;) {{apply --append;}};"></div> <div> - <span data-bind='var:order(order/ship/city);format:text;posttext:, ;'></span> - <span data-bind='var:order(order/ship/region);format:text;posttext:. ;'></span> - <span data-bind='var:order(order/ship/postal);format:text; defaultVar:order(data.ship_int_zip);'></span> + <span data-tlc="bind $var '.order.ship.city'; if (is $var --notblank;) {{format --append=', '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.region'; if (is $var --notblank;) {{format --append='. '; apply --append;}};"></span> + <span data-tlc="bind $var '.order.ship.postal'; if(is $var --blank;) {{bind $var '.data.ship_int_zip'; }}; if (is $var --notblank;) {{apply --append;}};"></span> </div> - <div data-bind='var:order(order/ship/countrycode);format:text;'></div> + <div data-tlc="bind $var '.order.ship.countrycode'; if (is $var --notblank;) {{apply --append;}};"></div> </address> </td> - <td class='orderContentsProdlistContainer'> - <ul data-bind='var:order(order/tracking); format:orderTrackingLinks; extension:store_crm;before:<h4>Shipping:</h4>;' class='displayNone noListStyle marginBottom'></ul> - <table class='listStyleNone lineItemProdlist'> - <tbody data-bind="var: order(order/@ITEMS); format:stuffList; loadsTemplate:chkoutInvoiceItemTemplate;"></tbody> + <td class="orderContentsProdlistContainer"> + <ul data-tlc="bind $var '.order.tracking'; store_crm#ordertrackinglinks --legacy;" class="displayNone noListStyle marginBottom"></ul> + <table class="listStyleNone lineItemProdlist"> + <tbody data-tlc="bind $var '.order.@ITEMS'; controller#loop --templateid='chkoutInvoiceItemTemplate'; if (is $var --notblank;) {{apply --append;}};"></tbody> </table> </td> </tr> - </table> + </tbody></table> </div> </div> @@ -514,10 +545,10 @@ <h4> -<div id='cvvcidHelp' class='displayNone' title='Where to find your CVV/CID and why we ask for it'> +<div id="cvvcidHelp" class="displayNone" title="Where to find your CVV/CID and why we ask for it"> <p>For higher security and more efficient processing of your payment, you must provide a card security code to make this purchase. For Visa, MasterCard and Discover the security code is the last section of numbers in the signature area on the back of the card. For American Express the security code is the 4-digit number found in small print next to your account number on the front, usually above it on the right.</p> - <div class='checkoutSprite secCode_vmd' title='Visa/MC/Discover card security code'></div> - <div class='checkoutSprite secCode_amex' title='AMEX card security code'></div> + <div class="checkoutSprite secCode_vmd" title="Visa/MC/Discover card security code"></div> + <div class="checkoutSprite secCode_amex" title="AMEX card security code"></div> </div> @@ -544,45 +575,35 @@ <h4> If this gets recycled, test in order history after making changes. --> <table> - <tr id='chkoutInvoiceItemTemplate' class='padMargBorderBottom'> + <tbody><tr id="chkoutInvoiceItemTemplate" class="padMargBorderBottom"> <td> - <div class='prodThumbContainer marginRight'> - <img src='/media/graphics/blank.gif' class='prodThumb' data-bind='var: product(zoovy:prod_image1); format:imageURL;' width='55' height='55' /> + <div class="prodThumbContainer marginRight"> + <img data-tlc="bind $var '.%attribs.zoovy:prod_image1'; if (is $var --notblank;) {{ apply --img --media=$var --width=55 --height=55 --bgcolor='#ffffff' --replace;}};" src="/media/graphics/blank.gif" class="prodThumb" height="55" width="55"> </div> </td> - <td class='valignTop ztable_row'> + <td class="valignTop ztable_row"> -<div class='infoContainer'> - - <h3 data-bind='var: product(prod_name); format:text; '></h3> - <div class='ztable_row_small stid' data-bind='var: product(sku); format:text; className: stid; pretext: Sku: ;'></div> +<div class="infoContainer"> + <b data-tlc="bind $var '.prod_name'; if (is $var --notblank;) {{apply --append;}};"></b> + <div data-tlc="bind $var '.sku'; if (is $var --notblank;) {{format --prepend='Sku: '; apply --add --class='stid'; apply --append;}};" class="ztable_row_small stid"></div> + <div> - <span data-bind='var: product(qty); format:text; pretext:qty: ;'></span> - <span data-bind='var: product(price); format:money; currencySign: $; hideZero:false; pretext: x ;' ></span> - <span data-bind='var: product(extended); format:money; currencySign: $; hideZero:false; pretext: = ;'></span> + <span data-tlc="bind $var '.qty'; if (is $var --notblank;) {{format --prepend='qty: '; apply --append;}};"></span> + <span data-tlc="bind $var '.price'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='x '; apply --append;}};"></span> + <span data-tlc="bind $var '.extended'; if (is $var --notblank;) {{format --currency='USD'; format --prepend='= '; apply --append;}};"></span> </div> - - <div class='ztable_row_small prodOptions' data-bind='var: product(%options); format:selectedOptionsDisplay;'></div> - - - + <div data-tlc="bind $var '.%options'; controller#selectedoptionsdisplay --legacy; " class="ztable_row_small prodOptions"></div> </div> </td> - <td class='alignRight hide4Print'> - <button class='writeReview' data-app-event="store_crm|showWriteReview" data-bind='var:product(product);format:assignAttribute; attribute:data-pid;'>Write Review</button> + <td class="alignRight hide4Print"> + <button data-tlc="bind $var '.product'; apply --attrib='data-pid'; " class="writeReview applyButton" data-app-click="store_crm|productReviewShow">Write Review</button> </td> </tr> -</table> - - - - - - +</tbody></table> \ No newline at end of file diff --git a/extensions/checkout/styles.css b/extensions/checkout/styles.css index 40257a666..dca8fb5df 100644 --- a/extensions/checkout/styles.css +++ b/extensions/checkout/styles.css @@ -1,8 +1,8 @@ - +/* 1PC uses this file in addition to quickstart, admin and any other app referencing checkout */ .checkoutSprite {background-color:#660000;} /* add this to any element that uses one of the following classes (preparation for sprite) */ .ocmFacebookComment {background:url(images/fb_comment-133x32.png) no-repeat; width:133px; height:32px;} -.ocmTwitterComment {background:url(images/tweet_comment-133x32.png) no-repeat; width:133px; height:32px;} +.ocmTwitterComment {background:url(images/tweet-133x32.png) no-repeat; width:133px; height:32px;} .ocmContinue {background:url(images/continue_shopping-133x32.png) no-repeat; width:133px; height:32px;} .secCode_vmd {background:url(images/sec_code-159x100.gif) no-repeat; width:159px; height:100px;} /* Visa/Mastercard/Discover */ @@ -10,4 +10,25 @@ /* a fix for IE < 10 that will impact 1PC only. */ -#zContent .ui-button {position:relative; } /* the inline-block is causing the buttons to not appear correctly in IE */ \ No newline at end of file +#zContent .ui-button {position:relative; } /* the inline-block is causing the buttons to not appear correctly in IE */ + +.checkoutFormContainer fieldset {padding:1em;} +.checkoutFormContainer legend.smallPadding {margin:0; padding:.2em .6em} /* the fieldset padding sets the left margin on the legend */ + + + + +#paybySupplemental_CREDIT .ui-icon-help {display:inline-block; margin-left:.5em;} + + +.paybySupplemental {padding:1em; font-weight:normal; border-top-width:0;} +.paybySupplemental select {margin-right:1em;} + +.addressList address {float:left; margin:0 1em 1em 0;} + +.creditCardCVVIcon {display:inline-block !important;} + +.checkoutFormContainer input, checkoutFormContainer select {margin:.3em .5em .3em 0;} +.checkoutFormContainer input[type='password'] {width:200px;} /* class affects both login password and create account passwords */ + +.headerPadding label {padding:.3em .5em;} \ No newline at end of file diff --git a/extensions/entomologist/extension.js b/extensions/entomologist/extension.js index 36cea86c3..ffd866473 100644 --- a/extensions/entomologist/extension.js +++ b/extensions/entomologist/extension.js @@ -25,7 +25,7 @@ to debug issues in a shopping application. */ -var entomologist = function() { +var entomologist = function(_app) { var theseTemplates = new Array(''); var r = { @@ -39,16 +39,16 @@ var entomologist = function() { init : { onSuccess : function() { var r = false; - window.showDebugger = app.ext.entomologist.a.showDebugger + window.showDebugger = _app.ext.entomologist.a.showDebugger - app.model.fetchNLoadTemplates(app.vars.baseURL + "extensions/entomologist/templates.html", []); - app.u.loadCSSFile("extensions/entomologist/styles.css","entomologistCSS"); + _app.model.fetchNLoadTemplates(_app.vars.baseURL + "extensions/entomologist/templates.html", []); + _app.u.loadCSSFile("extensions/entomologist/styles.css","entomologistCSS"); r = true; return r; }, onError : function() { - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } }, //callbacks @@ -61,27 +61,27 @@ var entomologist = function() { showDebugger : function(width, height){ width = width || 800; height = height || 500; - if(app.ext.entomologist.vars.$debugger){ - app.ext.entomologist.vars.$debugger.dialog('open'); + if(_app.ext.entomologist.vars.$debugger){ + _app.ext.entomologist.vars.$debugger.dialog('open'); } else { var $debugger = $('<div></div>'); $debugger.anycontent({'data':{}, 'templateID':'debuggerTemplate'}); - app.ext.entomologist.vars.$debugger = $debugger; + _app.ext.entomologist.vars.$debugger = $debugger; $debugger.on('click.refreshDebug', '[data-debug="refresh"]', function(){ if($(this).attr('data-debug-target')){ - //app.u.dump($('[data-debug="'+$(this).attr('data-debug-target')+'"]', $debugger)); - app.ext.entomologist.u.update($('[data-debug="'+$(this).attr('data-debug-target')+'"]', $debugger)); + //_app.u.dump($('[data-debug="'+$(this).attr('data-debug-target')+'"]', $debugger)); + _app.ext.entomologist.u.update($('[data-debug="'+$(this).attr('data-debug-target')+'"]', $debugger)); } }); - $('.tabificateMe', $debugger).anytabs(); + $('.tabificateMe', $debugger).anytabs(); //consider adding an 'applyAnytabs' to this element and running _app.u.handleCommonPlugins($debugger); $debugger.dialog({'title':'Entomology Lab', 'height':height, 'width':width}); } - //app.ext.entomologist.u.update( $('[data-debug="prodDumperList"]', $debugger)); - //app.ext.entomologist.u.update( $('[data-debug="catDumperList"]', $debugger)); - app.ext.entomologist.u.update( $('[data-debug="localStorageDumperList"]', $debugger)); + //_app.ext.entomologist.u.update( $('[data-debug="prodDumperList"]', $debugger)); + //_app.ext.entomologist.u.update( $('[data-debug="catDumperList"]', $debugger)); + _app.ext.entomologist.u.update( $('[data-debug="localStorageDumperList"]', $debugger)); return "Opening Entomology Lab..."; @@ -92,7 +92,7 @@ var entomologist = function() { renderFormats : { dumpData : function($tag, data){ - app.u.dump(data.value); + _app.u.dump(data.value); } }, //renderFormats @@ -100,12 +100,12 @@ var entomologist = function() { u : { updateList : function($target, datapointerPrefix, templateID, useLocalStorage){ - app.u.dump('BEGIN app.ext.entomologist.u.updateList'); + _app.u.dump('BEGIN _app.ext.entomologist.u.updateList'); $target.intervaledEmpty(); - app.u.dump(datapointerPrefix); - app.u.dump(templateID); - app.u.dump(useLocalStorage); + _app.u.dump(datapointerPrefix); + _app.u.dump(templateID); + _app.u.dump(useLocalStorage); if(useLocalStorage){ for(var i = 0; i < localStorage.length; i++){ if(localStorage.key(i).indexOf(datapointerPrefix >= 0)){ @@ -123,17 +123,17 @@ var entomologist = function() { } } else { - for(var index in app.data){ + for(var index in _app.data){ if(index.indexOf(datapointerPrefix) >= 0){ - //app.u.dump(index); - var $listing = $('<div />').anycontent({'data':app.data[index], 'templateID':templateID}); + //_app.u.dump(index); + var $listing = $('<div />').anycontent({'data':_app.data[index], 'templateID':templateID}); $target.append($listing.children()); } } } }, updateTag : function($target, datapointer, templateID, useLocalStorage){ - app.u.dump('BEGIN app.ext.entomologist.u.updateTag'); + _app.u.dump('BEGIN _app.ext.entomologist.u.updateTag'); if(useLocalStorage){ if(localStorage.getItem(datapointer)){ var obj = {}; @@ -148,50 +148,50 @@ var entomologist = function() { } } else { - if(app.data[datapointer]){ - $target.intervaledEmpty().anycontent({'data':app.data[datapointer], 'templateID':templateID}); + if(_app.data[datapointer]){ + $target.intervaledEmpty().anycontent({'data':_app.data[datapointer], 'templateID':templateID}); } } }, update : function($target){ - app.u.dump('BEGIN app.ext.entomologist.u.update'); + _app.u.dump('BEGIN _app.ext.entomologist.u.update'); if($target.attr('data-debug-loadsTemplate') && ($target.attr('data-debug-datapointerPrefix') || $target.attr('data-debug-datapointerPrefix') === "")){ - app.u.dump('Looks like a list!'); + _app.u.dump('Looks like a list!'); this.updateList($target, $target.attr('data-debug-datapointerPrefix'), $target.attr('data-debug-loadsTemplate'), $target.attr('data-debug-localStorage')); } else if($target.attr('data-debug-templateID') && $target.attr('data-debug-datapointer')) { - app.u.dump('Looks like a tag!'); + _app.u.dump('Looks like a tag!'); this.updateTag($target, $target.attr('data-debug-datapointer'), $target.attr('data-debug-templateID'), $target.attr('data-debug-localStorage')); } }, dumpData : function(datapointer, json, useLocalStorage){ if(useLocalStorage){ if(localStorage.getItem(datapointer)){ - app.u.dump("Data for "+datapointer+" in localStorage:"); + _app.u.dump("Data for "+datapointer+" in localStorage:"); if(json || localStorage.getItem(datapointer).charAt(0) != "{" || localStorage.getItem(datapointer).charAt(0) != "["){ - app.u.dump(localStorage.getItem(datapointer)); + _app.u.dump(localStorage.getItem(datapointer)); } else{ - app.u.dump(JSON.parse(localStorage.getItem(datapointer))); + _app.u.dump(JSON.parse(localStorage.getItem(datapointer))); } } else { - app.u.dump("-> Error: app.ext.entomologist.u.dumpData could not find data in localStorage for "+datapointer); + _app.u.dump("-> Error: _app.ext.entomologist.u.dumpData could not find data in localStorage for "+datapointer); } } else { - if(app.data[datapointer]){ - app.u.dump("Data for "+datapointer+" in app.data:"); + if(_app.data[datapointer]){ + _app.u.dump("Data for "+datapointer+" in _app.data:"); if(json){ - app.u.dump(JSON.stringify(app.data[datapointer])); + _app.u.dump(JSON.stringify(_app.data[datapointer])); } else{ - app.u.dump(app.data[datapointer]); + _app.u.dump(_app.data[datapointer]); } } else { - app.u.dump("-> Error: app.ext.entomologist.u.dumpData could not find data in app.data for "+datapointer); + _app.u.dump("-> Error: _app.ext.entomologist.u.dumpData could not find data in _app.data for "+datapointer); } } } diff --git a/extensions/jquery-cycle.js b/extensions/jquery-cycle.js new file mode 100644 index 000000000..398c1fd65 --- /dev/null +++ b/extensions/jquery-cycle.js @@ -0,0 +1,1540 @@ +/*! + * jQuery Cycle Plugin (with Transition Definitions) + * Examples and documentation at: http://jquery.malsup.com/cycle/ + * Copyright (c) 2007-2013 M. Alsup + * Version: 3.0.2 (19-APR-2013) + * Dual licensed under the MIT and GPL licenses. + * http://jquery.malsup.com/license.html + * Requires: jQuery v1.7.1 or later + */ +;(function($, undefined) { +"use strict"; + +var ver = '3.0.2'; + +function debug(s) { + if ($.fn.cycle.debug) + log(s); +} +function log() { + if (window.console && console.log) + console.log('[cycle] ' + Array.prototype.join.call(arguments,' ')); +} +$.expr[':'].paused = function(el) { + return el.cyclePause; +}; + + +// the options arg can be... +// a number - indicates an immediate transition should occur to the given slide index +// a string - 'pause', 'resume', 'toggle', 'next', 'prev', 'stop', 'destroy' or the name of a transition effect (ie, 'fade', 'zoom', etc) +// an object - properties to control the slideshow +// +// the arg2 arg can be... +// the name of an fx (only used in conjunction with a numeric value for 'options') +// the value true (only used in first arg == 'resume') and indicates +// that the resume should occur immediately (not wait for next timeout) + +$.fn.cycle = function(options, arg2) { + var o = { s: this.selector, c: this.context }; + + // in 1.3+ we can fix mistakes with the ready state + if (this.length === 0 && options != 'stop') { + if (!$.isReady && o.s) { + log('DOM not ready, queuing slideshow'); + $(function() { + $(o.s,o.c).cycle(options,arg2); + }); + return this; + } + // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready() + log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)')); + return this; + } + + // iterate the matched nodeset + return this.each(function() { + var opts = handleArguments(this, options, arg2); + if (opts === false) + return; + + opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink; + + // stop existing slideshow for this container (if there is one) + if (this.cycleTimeout) + clearTimeout(this.cycleTimeout); + this.cycleTimeout = this.cyclePause = 0; + this.cycleStop = 0; // issue #108 + + var $cont = $(this); + var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children(); + var els = $slides.get(); + + if (els.length < 2) { + log('terminating; too few slides: ' + els.length); + return; + } + + var opts2 = buildOptions($cont, $slides, els, opts, o); + if (opts2 === false) + return; + + var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.backwards); + + // if it's an auto slideshow, kick it off + if (startTime) { + startTime += (opts2.delay || 0); + if (startTime < 10) + startTime = 10; + debug('first timeout: ' + startTime); + this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts.backwards);}, startTime); + } + }); +}; + +function triggerPause(cont, byHover, onPager) { + var opts = $(cont).data('cycle.opts'); + if (!opts) + return; + var paused = !!cont.cyclePause; + if (paused && opts.paused) + opts.paused(cont, opts, byHover, onPager); + else if (!paused && opts.resumed) + opts.resumed(cont, opts, byHover, onPager); +} + +// process the args that were passed to the plugin fn +function handleArguments(cont, options, arg2) { + if (cont.cycleStop === undefined) + cont.cycleStop = 0; + if (options === undefined || options === null) + options = {}; + if (options.constructor == String) { + switch(options) { + case 'destroy': + case 'stop': + var opts = $(cont).data('cycle.opts'); + if (!opts) + return false; + cont.cycleStop++; // callbacks look for change + if (cont.cycleTimeout) + clearTimeout(cont.cycleTimeout); + cont.cycleTimeout = 0; + if (opts.elements) + $(opts.elements).stop(); + $(cont).removeData('cycle.opts'); + if (options == 'destroy') + destroy(cont, opts); + return false; + case 'toggle': + cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1; + checkInstantResume(cont.cyclePause, arg2, cont); + triggerPause(cont); + return false; + case 'pause': + cont.cyclePause = 1; + triggerPause(cont); + return false; + case 'resume': + cont.cyclePause = 0; + checkInstantResume(false, arg2, cont); + triggerPause(cont); + return false; + case 'prev': + case 'next': + opts = $(cont).data('cycle.opts'); + if (!opts) { + log('options not found, "prev/next" ignored'); + return false; + } + if (typeof arg2 == 'string') + opts.oneTimeFx = arg2; + $.fn.cycle[options](opts); + return false; + default: + options = { fx: options }; + } + return options; + } + else if (options.constructor == Number) { + // go to the requested slide + var num = options; + options = $(cont).data('cycle.opts'); + if (!options) { + log('options not found, can not advance slide'); + return false; + } + if (num < 0 || num >= options.elements.length) { + log('invalid slide index: ' + num); + return false; + } + options.nextSlide = num; + if (cont.cycleTimeout) { + clearTimeout(cont.cycleTimeout); + cont.cycleTimeout = 0; + } + if (typeof arg2 == 'string') + options.oneTimeFx = arg2; + go(options.elements, options, 1, num >= options.currSlide); + return false; + } + return options; + + function checkInstantResume(isPaused, arg2, cont) { + if (!isPaused && arg2 === true) { // resume now! + var options = $(cont).data('cycle.opts'); + if (!options) { + log('options not found, can not resume'); + return false; + } + if (cont.cycleTimeout) { + clearTimeout(cont.cycleTimeout); + cont.cycleTimeout = 0; + } + go(options.elements, options, 1, !options.backwards); + } + } +} + +function removeFilter(el, opts) { + if (!$.support.opacity && opts.cleartype && el.style.filter) { + try { el.style.removeAttribute('filter'); } + catch(smother) {} // handle old opera versions + } +} + +// unbind event handlers +function destroy(cont, opts) { + if (opts.next) + $(opts.next).unbind(opts.prevNextEvent); + if (opts.prev) + $(opts.prev).unbind(opts.prevNextEvent); + + if (opts.pager || opts.pagerAnchorBuilder) + $.each(opts.pagerAnchors || [], function() { + this.unbind().remove(); + }); + opts.pagerAnchors = null; + $(cont).unbind('mouseenter.cycle mouseleave.cycle'); + if (opts.destroy) // callback + opts.destroy(opts); +} + +// one-time initialization +function buildOptions($cont, $slides, els, options, o) { + var startingSlideSpecified; + // support metadata plugin (v1.0 and v2.0) + var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {}); + var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null; + if (meta) + opts = $.extend(opts, meta); + if (opts.autostop) + opts.countdown = opts.autostopCount || els.length; + + var cont = $cont[0]; + $cont.data('cycle.opts', opts); + opts.$cont = $cont; + opts.stopCount = cont.cycleStop; + opts.elements = els; + opts.before = opts.before ? [opts.before] : []; + opts.after = opts.after ? [opts.after] : []; + + // push some after callbacks + if (!$.support.opacity && opts.cleartype) + opts.after.push(function() { removeFilter(this, opts); }); + if (opts.continuous) + opts.after.push(function() { go(els,opts,0,!opts.backwards); }); + + saveOriginalOpts(opts); + + // clearType corrections + if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg) + clearTypeFix($slides); + + // container requires non-static position so that slides can be position within + if ($cont.css('position') == 'static') + $cont.css('position', 'relative'); + if (opts.width) + $cont.width(opts.width); + if (opts.height && opts.height != 'auto') + $cont.height(opts.height); + + if (opts.startingSlide !== undefined) { + opts.startingSlide = parseInt(opts.startingSlide,10); + if (opts.startingSlide >= els.length || opts.startSlide < 0) + opts.startingSlide = 0; // catch bogus input + else + startingSlideSpecified = true; + } + else if (opts.backwards) + opts.startingSlide = els.length - 1; + else + opts.startingSlide = 0; + + // if random, mix up the slide array + if (opts.random) { + opts.randomMap = []; + for (var i = 0; i < els.length; i++) + opts.randomMap.push(i); + opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;}); + if (startingSlideSpecified) { + // try to find the specified starting slide and if found set start slide index in the map accordingly + for ( var cnt = 0; cnt < els.length; cnt++ ) { + if ( opts.startingSlide == opts.randomMap[cnt] ) { + opts.randomIndex = cnt; + } + } + } + else { + opts.randomIndex = 1; + opts.startingSlide = opts.randomMap[1]; + } + } + else if (opts.startingSlide >= els.length) + opts.startingSlide = 0; // catch bogus input + opts.currSlide = opts.startingSlide || 0; + var first = opts.startingSlide; + + // set position and zIndex on all the slides + $slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) { + var z; + if (opts.backwards) + z = first ? i <= first ? els.length + (i-first) : first-i : els.length-i; + else + z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i; + $(this).css('z-index', z); + }); + + // make sure first slide is visible + $(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case + removeFilter(els[first], opts); + + // stretch slides + if (opts.fit) { + if (!opts.aspect) { + if (opts.width) + $slides.width(opts.width); + if (opts.height && opts.height != 'auto') + $slides.height(opts.height); + } else { + $slides.each(function(){ + var $slide = $(this); + var ratio = (opts.aspect === true) ? $slide.width()/$slide.height() : opts.aspect; + if( opts.width && $slide.width() != opts.width ) { + $slide.width( opts.width ); + $slide.height( opts.width / ratio ); + } + + if( opts.height && $slide.height() < opts.height ) { + $slide.height( opts.height ); + $slide.width( opts.height * ratio ); + } + }); + } + } + + if (opts.center && ((!opts.fit) || opts.aspect)) { + $slides.each(function(){ + var $slide = $(this); + $slide.css({ + "margin-left": opts.width ? + ((opts.width - $slide.width()) / 2) + "px" : + 0, + "margin-top": opts.height ? + ((opts.height - $slide.height()) / 2) + "px" : + 0 + }); + }); + } + + if (opts.center && !opts.fit && !opts.slideResize) { + $slides.each(function(){ + var $slide = $(this); + $slide.css({ + "margin-left": opts.width ? ((opts.width - $slide.width()) / 2) + "px" : 0, + "margin-top": opts.height ? ((opts.height - $slide.height()) / 2) + "px" : 0 + }); + }); + } + + // stretch container + var reshape = (opts.containerResize || opts.containerResizeHeight) && $cont.innerHeight() < 1; + if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9 + var maxw = 0, maxh = 0; + for(var j=0; j < els.length; j++) { + var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight(); + if (!w) w = e.offsetWidth || e.width || $e.attr('width'); + if (!h) h = e.offsetHeight || e.height || $e.attr('height'); + maxw = w > maxw ? w : maxw; + maxh = h > maxh ? h : maxh; + } + if (opts.containerResize && maxw > 0 && maxh > 0) + $cont.css({width:maxw+'px',height:maxh+'px'}); + if (opts.containerResizeHeight && maxh > 0) + $cont.css({height:maxh+'px'}); + } + + var pauseFlag = false; // https://github.com/malsup/cycle/issues/44 + if (opts.pause) + $cont.bind('mouseenter.cycle', function(){ + pauseFlag = true; + this.cyclePause++; + triggerPause(cont, true); + }).bind('mouseleave.cycle', function(){ + if (pauseFlag) + this.cyclePause--; + triggerPause(cont, true); + }); + + if (supportMultiTransitions(opts) === false) + return false; + + // apparently a lot of people use image slideshows without height/width attributes on the images. + // Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that. + var requeue = false; + options.requeueAttempts = options.requeueAttempts || 0; + $slides.each(function() { + // try to get height/width of each slide + var $el = $(this); + this.cycleH = (opts.fit && opts.height) ? opts.height : ($el.height() || this.offsetHeight || this.height || $el.attr('height') || 0); + this.cycleW = (opts.fit && opts.width) ? opts.width : ($el.width() || this.offsetWidth || this.width || $el.attr('width') || 0); + + if ( $el.is('img') ) { + var loading = (this.cycleH === 0 && this.cycleW === 0 && !this.complete); + // don't requeue for images that are still loading but have a valid size + if (loading) { + if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever + log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH); + setTimeout(function() {$(o.s,o.c).cycle(options);}, opts.requeueTimeout); + requeue = true; + return false; // break each loop + } + else { + log('could not determine size of image: '+this.src, this.cycleW, this.cycleH); + } + } + } + return true; + }); + + if (requeue) + return false; + + opts.cssBefore = opts.cssBefore || {}; + opts.cssAfter = opts.cssAfter || {}; + opts.cssFirst = opts.cssFirst || {}; + opts.animIn = opts.animIn || {}; + opts.animOut = opts.animOut || {}; + + $slides.not(':eq('+first+')').css(opts.cssBefore); + $($slides[first]).css(opts.cssFirst); + + if (opts.timeout) { + opts.timeout = parseInt(opts.timeout,10); + // ensure that timeout and speed settings are sane + if (opts.speed.constructor == String) + opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed,10); + if (!opts.sync) + opts.speed = opts.speed / 2; + + var buffer = opts.fx == 'none' ? 0 : opts.fx == 'shuffle' ? 500 : 250; + while((opts.timeout - opts.speed) < buffer) // sanitize timeout + opts.timeout += opts.speed; + } + if (opts.easing) + opts.easeIn = opts.easeOut = opts.easing; + if (!opts.speedIn) + opts.speedIn = opts.speed; + if (!opts.speedOut) + opts.speedOut = opts.speed; + + opts.slideCount = els.length; + opts.currSlide = opts.lastSlide = first; + if (opts.random) { + if (++opts.randomIndex == els.length) + opts.randomIndex = 0; + opts.nextSlide = opts.randomMap[opts.randomIndex]; + } + else if (opts.backwards) + opts.nextSlide = opts.startingSlide === 0 ? (els.length-1) : opts.startingSlide-1; + else + opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1; + + // run transition init fn + if (!opts.multiFx) { + var init = $.fn.cycle.transitions[opts.fx]; + if ($.isFunction(init)) + init($cont, $slides, opts); + else if (opts.fx != 'custom' && !opts.multiFx) { + log('unknown transition: ' + opts.fx,'; slideshow terminating'); + return false; + } + } + + // fire artificial events + var e0 = $slides[first]; + if (!opts.skipInitializationCallbacks) { + if (opts.before.length) + opts.before[0].apply(e0, [e0, e0, opts, true]); + if (opts.after.length) + opts.after[0].apply(e0, [e0, e0, opts, true]); + } + if (opts.next) + $(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,1);}); + if (opts.prev) + $(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,0);}); + if (opts.pager || opts.pagerAnchorBuilder) + buildPager(els,opts); + + exposeAddSlide(opts, els); + + return opts; +} + +// save off original opts so we can restore after clearing state +function saveOriginalOpts(opts) { + opts.original = { before: [], after: [] }; + opts.original.cssBefore = $.extend({}, opts.cssBefore); + opts.original.cssAfter = $.extend({}, opts.cssAfter); + opts.original.animIn = $.extend({}, opts.animIn); + opts.original.animOut = $.extend({}, opts.animOut); + $.each(opts.before, function() { opts.original.before.push(this); }); + $.each(opts.after, function() { opts.original.after.push(this); }); +} + +function supportMultiTransitions(opts) { + var i, tx, txs = $.fn.cycle.transitions; + // look for multiple effects + if (opts.fx.indexOf(',') > 0) { + opts.multiFx = true; + opts.fxs = opts.fx.replace(/\s*/g,'').split(','); + // discard any bogus effect names + for (i=0; i < opts.fxs.length; i++) { + var fx = opts.fxs[i]; + tx = txs[fx]; + if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) { + log('discarding unknown transition: ',fx); + opts.fxs.splice(i,1); + i--; + } + } + // if we have an empty list then we threw everything away! + if (!opts.fxs.length) { + log('No valid transitions named; slideshow terminating.'); + return false; + } + } + else if (opts.fx == 'all') { // auto-gen the list of transitions + opts.multiFx = true; + opts.fxs = []; + for (var p in txs) { + if (txs.hasOwnProperty(p)) { + tx = txs[p]; + if (txs.hasOwnProperty(p) && $.isFunction(tx)) + opts.fxs.push(p); + } + } + } + if (opts.multiFx && opts.randomizeEffects) { + // munge the fxs array to make effect selection random + var r1 = Math.floor(Math.random() * 20) + 30; + for (i = 0; i < r1; i++) { + var r2 = Math.floor(Math.random() * opts.fxs.length); + opts.fxs.push(opts.fxs.splice(r2,1)[0]); + } + debug('randomized fx sequence: ',opts.fxs); + } + return true; +} + +// provide a mechanism for adding slides after the slideshow has started +function exposeAddSlide(opts, els) { + opts.addSlide = function(newSlide, prepend) { + var $s = $(newSlide), s = $s[0]; + if (!opts.autostopCount) + opts.countdown++; + els[prepend?'unshift':'push'](s); + if (opts.els) + opts.els[prepend?'unshift':'push'](s); // shuffle needs this + opts.slideCount = els.length; + + // add the slide to the random map and resort + if (opts.random) { + opts.randomMap.push(opts.slideCount-1); + opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;}); + } + + $s.css('position','absolute'); + $s[prepend?'prependTo':'appendTo'](opts.$cont); + + if (prepend) { + opts.currSlide++; + opts.nextSlide++; + } + + if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg) + clearTypeFix($s); + + if (opts.fit && opts.width) + $s.width(opts.width); + if (opts.fit && opts.height && opts.height != 'auto') + $s.height(opts.height); + s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height(); + s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width(); + + $s.css(opts.cssBefore); + + if (opts.pager || opts.pagerAnchorBuilder) + $.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts); + + if ($.isFunction(opts.onAddSlide)) + opts.onAddSlide($s); + else + $s.hide(); // default behavior + }; +} + +// reset internal state; we do this on every pass in order to support multiple effects +$.fn.cycle.resetState = function(opts, fx) { + fx = fx || opts.fx; + opts.before = []; opts.after = []; + opts.cssBefore = $.extend({}, opts.original.cssBefore); + opts.cssAfter = $.extend({}, opts.original.cssAfter); + opts.animIn = $.extend({}, opts.original.animIn); + opts.animOut = $.extend({}, opts.original.animOut); + opts.fxFn = null; + $.each(opts.original.before, function() { opts.before.push(this); }); + $.each(opts.original.after, function() { opts.after.push(this); }); + + // re-init + var init = $.fn.cycle.transitions[fx]; + if ($.isFunction(init)) + init(opts.$cont, $(opts.elements), opts); +}; + +// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt +function go(els, opts, manual, fwd) { + var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide]; + + // opts.busy is true if we're in the middle of an animation + if (manual && opts.busy && opts.manualTrump) { + // let manual transitions requests trump active ones + debug('manualTrump in go(), stopping active transition'); + $(els).stop(true,true); + opts.busy = 0; + clearTimeout(p.cycleTimeout); + } + + // don't begin another timeout-based transition if there is one active + if (opts.busy) { + debug('transition active, ignoring new tx request'); + return; + } + + + // stop cycling if we have an outstanding stop request + if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual) + return; + + // check to see if we should stop cycling based on autostop options + if (!manual && !p.cyclePause && !opts.bounce && + ((opts.autostop && (--opts.countdown <= 0)) || + (opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) { + if (opts.end) + opts.end(opts); + return; + } + + // if slideshow is paused, only transition on a manual trigger + var changed = false; + if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) { + changed = true; + var fx = opts.fx; + // keep trying to get the slide size if we don't have it yet + curr.cycleH = curr.cycleH || $(curr).height(); + curr.cycleW = curr.cycleW || $(curr).width(); + next.cycleH = next.cycleH || $(next).height(); + next.cycleW = next.cycleW || $(next).width(); + + // support multiple transition types + if (opts.multiFx) { + if (fwd && (opts.lastFx === undefined || ++opts.lastFx >= opts.fxs.length)) + opts.lastFx = 0; + else if (!fwd && (opts.lastFx === undefined || --opts.lastFx < 0)) + opts.lastFx = opts.fxs.length - 1; + fx = opts.fxs[opts.lastFx]; + } + + // one-time fx overrides apply to: $('div').cycle(3,'zoom'); + if (opts.oneTimeFx) { + fx = opts.oneTimeFx; + opts.oneTimeFx = null; + } + + $.fn.cycle.resetState(opts, fx); + + // run the before callbacks + if (opts.before.length) + $.each(opts.before, function(i,o) { + if (p.cycleStop != opts.stopCount) return; + o.apply(next, [curr, next, opts, fwd]); + }); + + // stage the after callacks + var after = function() { + opts.busy = 0; + $.each(opts.after, function(i,o) { + if (p.cycleStop != opts.stopCount) return; + o.apply(next, [curr, next, opts, fwd]); + }); + if (!p.cycleStop) { + // queue next transition + queueNext(); + } + }; + + debug('tx firing('+fx+'); currSlide: ' + opts.currSlide + '; nextSlide: ' + opts.nextSlide); + + // get ready to perform the transition + opts.busy = 1; + if (opts.fxFn) // fx function provided? + opts.fxFn(curr, next, opts, after, fwd, manual && opts.fastOnEvent); + else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ? + $.fn.cycle[opts.fx](curr, next, opts, after, fwd, manual && opts.fastOnEvent); + else + $.fn.cycle.custom(curr, next, opts, after, fwd, manual && opts.fastOnEvent); + } + else { + queueNext(); + } + + if (changed || opts.nextSlide == opts.currSlide) { + // calculate the next slide + var roll; + opts.lastSlide = opts.currSlide; + if (opts.random) { + opts.currSlide = opts.nextSlide; + if (++opts.randomIndex == els.length) { + opts.randomIndex = 0; + opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;}); + } + opts.nextSlide = opts.randomMap[opts.randomIndex]; + if (opts.nextSlide == opts.currSlide) + opts.nextSlide = (opts.currSlide == opts.slideCount - 1) ? 0 : opts.currSlide + 1; + } + else if (opts.backwards) { + roll = (opts.nextSlide - 1) < 0; + if (roll && opts.bounce) { + opts.backwards = !opts.backwards; + opts.nextSlide = 1; + opts.currSlide = 0; + } + else { + opts.nextSlide = roll ? (els.length-1) : opts.nextSlide-1; + opts.currSlide = roll ? 0 : opts.nextSlide+1; + } + } + else { // sequence + roll = (opts.nextSlide + 1) == els.length; + if (roll && opts.bounce) { + opts.backwards = !opts.backwards; + opts.nextSlide = els.length-2; + opts.currSlide = els.length-1; + } + else { + opts.nextSlide = roll ? 0 : opts.nextSlide+1; + opts.currSlide = roll ? els.length-1 : opts.nextSlide-1; + } + } + } + if (changed && opts.pager) + opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass); + + function queueNext() { + // stage the next transition + var ms = 0, timeout = opts.timeout; + if (opts.timeout && !opts.continuous) { + ms = getTimeout(els[opts.currSlide], els[opts.nextSlide], opts, fwd); + if (opts.fx == 'shuffle') + ms -= opts.speedOut; + } + else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic + ms = 10; + if (ms > 0) + p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.backwards); }, ms); + } +} + +// invoked after transition +$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) { + $(pager).each(function() { + $(this).children().removeClass(clsName).eq(currSlide).addClass(clsName); + }); +}; + +// calculate timeout value for current transition +function getTimeout(curr, next, opts, fwd) { + if (opts.timeoutFn) { + // call user provided calc fn + var t = opts.timeoutFn.call(curr,curr,next,opts,fwd); + while (opts.fx != 'none' && (t - opts.speed) < 250) // sanitize timeout + t += opts.speed; + debug('calculated timeout: ' + t + '; speed: ' + opts.speed); + if (t !== false) + return t; + } + return opts.timeout; +} + +// expose next/prev function, caller must pass in state +$.fn.cycle.next = function(opts) { advance(opts,1); }; +$.fn.cycle.prev = function(opts) { advance(opts,0);}; + +// advance slide forward or back +function advance(opts, moveForward) { + var val = moveForward ? 1 : -1; + var els = opts.elements; + var p = opts.$cont[0], timeout = p.cycleTimeout; + if (timeout) { + clearTimeout(timeout); + p.cycleTimeout = 0; + } + if (opts.random && val < 0) { + // move back to the previously display slide + opts.randomIndex--; + if (--opts.randomIndex == -2) + opts.randomIndex = els.length-2; + else if (opts.randomIndex == -1) + opts.randomIndex = els.length-1; + opts.nextSlide = opts.randomMap[opts.randomIndex]; + } + else if (opts.random) { + opts.nextSlide = opts.randomMap[opts.randomIndex]; + } + else { + opts.nextSlide = opts.currSlide + val; + if (opts.nextSlide < 0) { + if (opts.nowrap) return false; + opts.nextSlide = els.length - 1; + } + else if (opts.nextSlide >= els.length) { + if (opts.nowrap) return false; + opts.nextSlide = 0; + } + } + + var cb = opts.onPrevNextEvent || opts.prevNextClick; // prevNextClick is deprecated + if ($.isFunction(cb)) + cb(val > 0, opts.nextSlide, els[opts.nextSlide]); + go(els, opts, 1, moveForward); + return false; +} + +function buildPager(els, opts) { + var $p = $(opts.pager); + $.each(els, function(i,o) { + $.fn.cycle.createPagerAnchor(i,o,$p,els,opts); + }); + opts.updateActivePagerLink(opts.pager, opts.startingSlide, opts.activePagerClass); +} + +$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) { + var a; + if ($.isFunction(opts.pagerAnchorBuilder)) { + a = opts.pagerAnchorBuilder(i,el); + debug('pagerAnchorBuilder('+i+', el) returned: ' + a); + } + else + a = '<a href="#">'+(i+1)+'</a>'; + + if (!a) + return; + var $a = $(a); + // don't reparent if anchor is in the dom + if ($a.parents('body').length === 0) { + var arr = []; + if ($p.length > 1) { + $p.each(function() { + var $clone = $a.clone(true); + $(this).append($clone); + arr.push($clone[0]); + }); + $a = $(arr); + } + else { + $a.appendTo($p); + } + } + + opts.pagerAnchors = opts.pagerAnchors || []; + opts.pagerAnchors.push($a); + + var pagerFn = function(e) { + e.preventDefault(); + opts.nextSlide = i; + var p = opts.$cont[0], timeout = p.cycleTimeout; + if (timeout) { + clearTimeout(timeout); + p.cycleTimeout = 0; + } + var cb = opts.onPagerEvent || opts.pagerClick; // pagerClick is deprecated + if ($.isFunction(cb)) + cb(opts.nextSlide, els[opts.nextSlide]); + go(els,opts,1,opts.currSlide < i); // trigger the trans +// return false; // <== allow bubble + }; + + if ( /mouseenter|mouseover/i.test(opts.pagerEvent) ) { + $a.hover(pagerFn, function(){/* no-op */} ); + } + else { + $a.bind(opts.pagerEvent, pagerFn); + } + + if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble) + $a.bind('click.cycle', function(){return false;}); // suppress click + + var cont = opts.$cont[0]; + var pauseFlag = false; // https://github.com/malsup/cycle/issues/44 + if (opts.pauseOnPagerHover) { + $a.hover( + function() { + pauseFlag = true; + cont.cyclePause++; + triggerPause(cont,true,true); + }, function() { + if (pauseFlag) + cont.cyclePause--; + triggerPause(cont,true,true); + } + ); + } +}; + +// helper fn to calculate the number of slides between the current and the next +$.fn.cycle.hopsFromLast = function(opts, fwd) { + var hops, l = opts.lastSlide, c = opts.currSlide; + if (fwd) + hops = c > l ? c - l : opts.slideCount - l; + else + hops = c < l ? l - c : l + opts.slideCount - c; + return hops; +}; + +// fix clearType problems in ie6 by setting an explicit bg color +// (otherwise text slides look horrible during a fade transition) +function clearTypeFix($slides) { + debug('applying clearType background-color hack'); + function hex(s) { + s = parseInt(s,10).toString(16); + return s.length < 2 ? '0'+s : s; + } + function getBg(e) { + for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) { + var v = $.css(e,'background-color'); + if (v && v.indexOf('rgb') >= 0 ) { + var rgb = v.match(/\d+/g); + return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]); + } + if (v && v != 'transparent') + return v; + } + return '#ffffff'; + } + $slides.each(function() { $(this).css('background-color', getBg(this)); }); +} + +// reset common props before the next transition +$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) { + $(opts.elements).not(curr).hide(); + if (typeof opts.cssBefore.opacity == 'undefined') + opts.cssBefore.opacity = 1; + opts.cssBefore.display = 'block'; + if (opts.slideResize && w !== false && next.cycleW > 0) + opts.cssBefore.width = next.cycleW; + if (opts.slideResize && h !== false && next.cycleH > 0) + opts.cssBefore.height = next.cycleH; + opts.cssAfter = opts.cssAfter || {}; + opts.cssAfter.display = 'none'; + $(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0)); + $(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1)); +}; + +// the actual fn for effecting a transition +$.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) { + var $l = $(curr), $n = $(next); + var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut; + $n.css(opts.cssBefore); + if (speedOverride) { + if (typeof speedOverride == 'number') + speedIn = speedOut = speedOverride; + else + speedIn = speedOut = 1; + easeIn = easeOut = null; + } + var fn = function() { + $n.animate(opts.animIn, speedIn, easeIn, function() { + cb(); + }); + }; + $l.animate(opts.animOut, speedOut, easeOut, function() { + $l.css(opts.cssAfter); + if (!opts.sync) + fn(); + }); + if (opts.sync) fn(); +}; + +// transition definitions - only fade is defined here, transition pack defines the rest +$.fn.cycle.transitions = { + fade: function($cont, $slides, opts) { + $slides.not(':eq('+opts.currSlide+')').css('opacity',0); + opts.before.push(function(curr,next,opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.cssBefore.opacity = 0; + }); + opts.animIn = { opacity: 1 }; + opts.animOut = { opacity: 0 }; + opts.cssBefore = { top: 0, left: 0 }; + } +}; + +$.fn.cycle.ver = function() { return ver; }; + +// override these globally if you like (they are all optional) +$.fn.cycle.defaults = { + activePagerClass: 'activeSlide', // class name used for the active pager link + after: null, // transition callback (scope set to element that was shown): function(currSlideElement, nextSlideElement, options, forwardFlag) + allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling + animIn: null, // properties that define how the slide animates in + animOut: null, // properties that define how the slide animates out + aspect: false, // preserve aspect ratio during fit resizing, cropping if necessary (must be used with fit option) + autostop: 0, // true to end slideshow after X transitions (where X == slide count) + autostopCount: 0, // number of transitions (optionally used with autostop to define X) + backwards: false, // true to start slideshow at last slide and move backwards through the stack + before: null, // transition callback (scope set to element to be shown): function(currSlideElement, nextSlideElement, options, forwardFlag) + center: null, // set to true to have cycle add top/left margin to each slide (use with width and height options) + cleartype: !$.support.opacity, // true if clearType corrections should be applied (for IE) + cleartypeNoBg: false, // set to true to disable extra cleartype fixing (leave false to force background color setting on slides) + containerResize: 1, // resize container to fit largest slide + containerResizeHeight: 0, // resize containers height to fit the largest slide but leave the width dynamic + continuous: 0, // true to start next transition immediately after current one completes + cssAfter: null, // properties that defined the state of the slide after transitioning out + cssBefore: null, // properties that define the initial state of the slide before transitioning in + delay: 0, // additional delay (in ms) for first transition (hint: can be negative) + easeIn: null, // easing for "in" transition + easeOut: null, // easing for "out" transition + easing: null, // easing method for both in and out transitions + end: null, // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options) + fastOnEvent: 0, // force fast transitions when triggered manually (via pager or prev/next); value == time in ms + fit: 0, // force slides to fit container + fx: 'fade', // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle') + fxFn: null, // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag) + height: 'auto', // container height (if the 'fit' option is true, the slides will be set to this height as well) + manualTrump: true, // causes manual transition to stop an active transition instead of being ignored + metaAttr: 'cycle', // data- attribute that holds the option data for the slideshow + next: null, // element, jQuery object, or jQuery selector string for the element to use as event trigger for next slide + nowrap: 0, // true to prevent slideshow from wrapping + onPagerEvent: null, // callback fn for pager events: function(zeroBasedSlideIndex, slideElement) + onPrevNextEvent: null, // callback fn for prev/next events: function(isNext, zeroBasedSlideIndex, slideElement) + pager: null, // element, jQuery object, or jQuery selector string for the element to use as pager container + pagerAnchorBuilder: null, // callback fn for building anchor links: function(index, DOMelement) + pagerEvent: 'click.cycle', // name of event which drives the pager navigation + pause: 0, // true to enable "pause on hover" + pauseOnPagerHover: 0, // true to pause when hovering over pager link + prev: null, // element, jQuery object, or jQuery selector string for the element to use as event trigger for previous slide + prevNextEvent: 'click.cycle',// event which drives the manual transition to the previous or next slide + random: 0, // true for random, false for sequence (not applicable to shuffle fx) + randomizeEffects: 1, // valid when multiple effects are used; true to make the effect sequence random + requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded + requeueTimeout: 250, // ms delay for requeue + rev: 0, // causes animations to transition in reverse (for effects that support it such as scrollHorz/scrollVert/shuffle) + shuffle: null, // coords for shuffle animation, ex: { top:15, left: 200 } + skipInitializationCallbacks: false, // set to true to disable the first before/after callback that occurs prior to any transition + slideExpr: null, // expression for selecting slides (if something other than all children is required) + slideResize: 1, // force slide width/height to fixed size before every transition + speed: 1000, // speed of the transition (any valid fx speed value) + speedIn: null, // speed of the 'in' transition + speedOut: null, // speed of the 'out' transition + startingSlide: undefined,// zero-based index of the first slide to be displayed + sync: 1, // true if in/out transitions should occur simultaneously + timeout: 4000, // milliseconds between slide transitions (0 to disable auto advance) + timeoutFn: null, // callback for determining per-slide timeout value: function(currSlideElement, nextSlideElement, options, forwardFlag) + updateActivePagerLink: null,// callback fn invoked to update the active pager link (adds/removes activePagerClass style) + width: null // container width (if the 'fit' option is true, the slides will be set to this width as well) +}; + +})(jQuery); + + +/*! + * jQuery Cycle Plugin Transition Definitions + * This script is a plugin for the jQuery Cycle Plugin + * Examples and documentation at: http://malsup.com/jquery/cycle/ + * Copyright (c) 2007-2010 M. Alsup + * Version: 2.73 + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +(function($) { +"use strict"; + +// +// These functions define slide initialization and properties for the named +// transitions. To save file size feel free to remove any of these that you +// don't need. +// +$.fn.cycle.transitions.none = function($cont, $slides, opts) { + opts.fxFn = function(curr,next,opts,after){ + $(next).show(); + $(curr).hide(); + after(); + }; +}; + +// not a cross-fade, fadeout only fades out the top slide +$.fn.cycle.transitions.fadeout = function($cont, $slides, opts) { + $slides.not(':eq('+opts.currSlide+')').css({ display: 'block', 'opacity': 1 }); + opts.before.push(function(curr,next,opts,w,h,rev) { + $(curr).css('zIndex',opts.slideCount + (rev !== true ? 1 : 0)); + $(next).css('zIndex',opts.slideCount + (rev !== true ? 0 : 1)); + }); + opts.animIn.opacity = 1; + opts.animOut.opacity = 0; + opts.cssBefore.opacity = 1; + opts.cssBefore.display = 'block'; + opts.cssAfter.zIndex = 0; +}; + +// scrollUp/Down/Left/Right +$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push($.fn.cycle.commonReset); + var h = $cont.height(); + opts.cssBefore.top = h; + opts.cssBefore.left = 0; + opts.cssFirst.top = 0; + opts.animIn.top = 0; + opts.animOut.top = -h; +}; +$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push($.fn.cycle.commonReset); + var h = $cont.height(); + opts.cssFirst.top = 0; + opts.cssBefore.top = -h; + opts.cssBefore.left = 0; + opts.animIn.top = 0; + opts.animOut.top = h; +}; +$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push($.fn.cycle.commonReset); + var w = $cont.width(); + opts.cssFirst.left = 0; + opts.cssBefore.left = w; + opts.cssBefore.top = 0; + opts.animIn.left = 0; + opts.animOut.left = 0-w; +}; +$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push($.fn.cycle.commonReset); + var w = $cont.width(); + opts.cssFirst.left = 0; + opts.cssBefore.left = -w; + opts.cssBefore.top = 0; + opts.animIn.left = 0; + opts.animOut.left = w; +}; +$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) { + $cont.css('overflow','hidden').width(); + opts.before.push(function(curr, next, opts, fwd) { + if (opts.rev) + fwd = !fwd; + $.fn.cycle.commonReset(curr,next,opts); + opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW); + opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW; + }); + opts.cssFirst.left = 0; + opts.cssBefore.top = 0; + opts.animIn.left = 0; + opts.animOut.top = 0; +}; +$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push(function(curr, next, opts, fwd) { + if (opts.rev) + fwd = !fwd; + $.fn.cycle.commonReset(curr,next,opts); + opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1); + opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH; + }); + opts.cssFirst.top = 0; + opts.cssBefore.left = 0; + opts.animIn.top = 0; + opts.animOut.left = 0; +}; + +// slideX/slideY +$.fn.cycle.transitions.slideX = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $(opts.elements).not(curr).hide(); + $.fn.cycle.commonReset(curr,next,opts,false,true); + opts.animIn.width = next.cycleW; + }); + opts.cssBefore.left = 0; + opts.cssBefore.top = 0; + opts.cssBefore.width = 0; + opts.animIn.width = 'show'; + opts.animOut.width = 0; +}; +$.fn.cycle.transitions.slideY = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $(opts.elements).not(curr).hide(); + $.fn.cycle.commonReset(curr,next,opts,true,false); + opts.animIn.height = next.cycleH; + }); + opts.cssBefore.left = 0; + opts.cssBefore.top = 0; + opts.cssBefore.height = 0; + opts.animIn.height = 'show'; + opts.animOut.height = 0; +}; + +// shuffle +$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) { + var i, w = $cont.css('overflow', 'visible').width(); + $slides.css({left: 0, top: 0}); + opts.before.push(function(curr,next,opts) { + $.fn.cycle.commonReset(curr,next,opts,true,true,true); + }); + // only adjust speed once! + if (!opts.speedAdjusted) { + opts.speed = opts.speed / 2; // shuffle has 2 transitions + opts.speedAdjusted = true; + } + opts.random = 0; + opts.shuffle = opts.shuffle || {left:-w, top:15}; + opts.els = []; + for (i=0; i < $slides.length; i++) + opts.els.push($slides[i]); + + for (i=0; i < opts.currSlide; i++) + opts.els.push(opts.els.shift()); + + // custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!) + opts.fxFn = function(curr, next, opts, cb, fwd) { + if (opts.rev) + fwd = !fwd; + var $el = fwd ? $(curr) : $(next); + $(next).css(opts.cssBefore); + var count = opts.slideCount; + $el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() { + var hops = $.fn.cycle.hopsFromLast(opts, fwd); + for (var k=0; k < hops; k++) { + if (fwd) + opts.els.push(opts.els.shift()); + else + opts.els.unshift(opts.els.pop()); + } + if (fwd) { + for (var i=0, len=opts.els.length; i < len; i++) + $(opts.els[i]).css('z-index', len-i+count); + } + else { + var z = $(curr).css('z-index'); + $el.css('z-index', parseInt(z,10)+1+count); + } + $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() { + $(fwd ? this : curr).hide(); + if (cb) cb(); + }); + }); + }; + $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 }); +}; + +// turnUp/Down/Left/Right +$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,false); + opts.cssBefore.top = next.cycleH; + opts.animIn.height = next.cycleH; + opts.animOut.width = next.cycleW; + }); + opts.cssFirst.top = 0; + opts.cssBefore.left = 0; + opts.cssBefore.height = 0; + opts.animIn.top = 0; + opts.animOut.height = 0; +}; +$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,false); + opts.animIn.height = next.cycleH; + opts.animOut.top = curr.cycleH; + }); + opts.cssFirst.top = 0; + opts.cssBefore.left = 0; + opts.cssBefore.top = 0; + opts.cssBefore.height = 0; + opts.animOut.height = 0; +}; +$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,true); + opts.cssBefore.left = next.cycleW; + opts.animIn.width = next.cycleW; + }); + opts.cssBefore.top = 0; + opts.cssBefore.width = 0; + opts.animIn.left = 0; + opts.animOut.width = 0; +}; +$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,true); + opts.animIn.width = next.cycleW; + opts.animOut.left = curr.cycleW; + }); + $.extend(opts.cssBefore, { top: 0, left: 0, width: 0 }); + opts.animIn.left = 0; + opts.animOut.width = 0; +}; + +// zoom +$.fn.cycle.transitions.zoom = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,false,true); + opts.cssBefore.top = next.cycleH/2; + opts.cssBefore.left = next.cycleW/2; + $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH }); + $.extend(opts.animOut, { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 }); + }); + opts.cssFirst.top = 0; + opts.cssFirst.left = 0; + opts.cssBefore.width = 0; + opts.cssBefore.height = 0; +}; + +// fadeZoom +$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,false); + opts.cssBefore.left = next.cycleW/2; + opts.cssBefore.top = next.cycleH/2; + $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH }); + }); + opts.cssBefore.width = 0; + opts.cssBefore.height = 0; + opts.animOut.opacity = 0; +}; + +// blindX +$.fn.cycle.transitions.blindX = function($cont, $slides, opts) { + var w = $cont.css('overflow','hidden').width(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.animIn.width = next.cycleW; + opts.animOut.left = curr.cycleW; + }); + opts.cssBefore.left = w; + opts.cssBefore.top = 0; + opts.animIn.left = 0; + opts.animOut.left = w; +}; +// blindY +$.fn.cycle.transitions.blindY = function($cont, $slides, opts) { + var h = $cont.css('overflow','hidden').height(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.animIn.height = next.cycleH; + opts.animOut.top = curr.cycleH; + }); + opts.cssBefore.top = h; + opts.cssBefore.left = 0; + opts.animIn.top = 0; + opts.animOut.top = h; +}; +// blindZ +$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) { + var h = $cont.css('overflow','hidden').height(); + var w = $cont.width(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.animIn.height = next.cycleH; + opts.animOut.top = curr.cycleH; + }); + opts.cssBefore.top = h; + opts.cssBefore.left = w; + opts.animIn.top = 0; + opts.animIn.left = 0; + opts.animOut.top = h; + opts.animOut.left = w; +}; + +// growX - grow horizontally from centered 0 width +$.fn.cycle.transitions.growX = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,true); + opts.cssBefore.left = this.cycleW/2; + opts.animIn.left = 0; + opts.animIn.width = this.cycleW; + opts.animOut.left = 0; + }); + opts.cssBefore.top = 0; + opts.cssBefore.width = 0; +}; +// growY - grow vertically from centered 0 height +$.fn.cycle.transitions.growY = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,false); + opts.cssBefore.top = this.cycleH/2; + opts.animIn.top = 0; + opts.animIn.height = this.cycleH; + opts.animOut.top = 0; + }); + opts.cssBefore.height = 0; + opts.cssBefore.left = 0; +}; + +// curtainX - squeeze in both edges horizontally +$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,true,true); + opts.cssBefore.left = next.cycleW/2; + opts.animIn.left = 0; + opts.animIn.width = this.cycleW; + opts.animOut.left = curr.cycleW/2; + opts.animOut.width = 0; + }); + opts.cssBefore.top = 0; + opts.cssBefore.width = 0; +}; +// curtainY - squeeze in both edges vertically +$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,false,true); + opts.cssBefore.top = next.cycleH/2; + opts.animIn.top = 0; + opts.animIn.height = next.cycleH; + opts.animOut.top = curr.cycleH/2; + opts.animOut.height = 0; + }); + opts.cssBefore.height = 0; + opts.cssBefore.left = 0; +}; + +// cover - curr slide covered by next slide +$.fn.cycle.transitions.cover = function($cont, $slides, opts) { + var d = opts.direction || 'left'; + var w = $cont.css('overflow','hidden').width(); + var h = $cont.height(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.cssAfter.display = ''; + if (d == 'right') + opts.cssBefore.left = -w; + else if (d == 'up') + opts.cssBefore.top = h; + else if (d == 'down') + opts.cssBefore.top = -h; + else + opts.cssBefore.left = w; + }); + opts.animIn.left = 0; + opts.animIn.top = 0; + opts.cssBefore.top = 0; + opts.cssBefore.left = 0; +}; + +// uncover - curr slide moves off next slide +$.fn.cycle.transitions.uncover = function($cont, $slides, opts) { + var d = opts.direction || 'left'; + var w = $cont.css('overflow','hidden').width(); + var h = $cont.height(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,true,true); + if (d == 'right') + opts.animOut.left = w; + else if (d == 'up') + opts.animOut.top = -h; + else if (d == 'down') + opts.animOut.top = h; + else + opts.animOut.left = -w; + }); + opts.animIn.left = 0; + opts.animIn.top = 0; + opts.cssBefore.top = 0; + opts.cssBefore.left = 0; +}; + +// toss - move top slide and fade away +$.fn.cycle.transitions.toss = function($cont, $slides, opts) { + var w = $cont.css('overflow','visible').width(); + var h = $cont.height(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,true,true); + // provide default toss settings if animOut not provided + if (!opts.animOut.left && !opts.animOut.top) + $.extend(opts.animOut, { left: w*2, top: -h/2, opacity: 0 }); + else + opts.animOut.opacity = 0; + }); + opts.cssBefore.left = 0; + opts.cssBefore.top = 0; + opts.animIn.left = 0; +}; + +// wipe - clip animation +$.fn.cycle.transitions.wipe = function($cont, $slides, opts) { + var w = $cont.css('overflow','hidden').width(); + var h = $cont.height(); + opts.cssBefore = opts.cssBefore || {}; + var clip; + if (opts.clip) { + if (/l2r/.test(opts.clip)) + clip = 'rect(0px 0px '+h+'px 0px)'; + else if (/r2l/.test(opts.clip)) + clip = 'rect(0px '+w+'px '+h+'px '+w+'px)'; + else if (/t2b/.test(opts.clip)) + clip = 'rect(0px '+w+'px 0px 0px)'; + else if (/b2t/.test(opts.clip)) + clip = 'rect('+h+'px '+w+'px '+h+'px 0px)'; + else if (/zoom/.test(opts.clip)) { + var top = parseInt(h/2,10); + var left = parseInt(w/2,10); + clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)'; + } + } + + opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)'; + + var d = opts.cssBefore.clip.match(/(\d+)/g); + var t = parseInt(d[0],10), r = parseInt(d[1],10), b = parseInt(d[2],10), l = parseInt(d[3],10); + + opts.before.push(function(curr, next, opts) { + if (curr == next) return; + var $curr = $(curr), $next = $(next); + $.fn.cycle.commonReset(curr,next,opts,true,true,false); + opts.cssAfter.display = 'block'; + + var step = 1, count = parseInt((opts.speedIn / 13),10) - 1; + (function f() { + var tt = t ? t - parseInt(step * (t/count),10) : 0; + var ll = l ? l - parseInt(step * (l/count),10) : 0; + var bb = b < h ? b + parseInt(step * ((h-b)/count || 1),10) : h; + var rr = r < w ? r + parseInt(step * ((w-r)/count || 1),10) : w; + $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' }); + (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none'); + })(); + }); + $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 }); + opts.animIn = { left: 0 }; + opts.animOut = { left: 0 }; +}; + +})(jQuery); \ No newline at end of file diff --git a/extensions/partner_addthis.js b/extensions/partner_addthis.js index d627afb9b..6801e8e4c 100644 --- a/extensions/partner_addthis.js +++ b/extensions/partner_addthis.js @@ -26,7 +26,7 @@ For AddThis API docs, go here: http://support.addthis.com/customer/portal/articl */ -var partner_addthis = function() { +var partner_addthis = function(_app) { var r= { vars : { @@ -45,17 +45,17 @@ var partner_addthis = function() { init : { onSuccess : function(){ var scriptPath = (document.location.protocol == 'https:' ? 'https:' : 'http:')+'//s7.addthis.com/js/250/addthis_widget.js'; - if(app.ext.partner_addthis.vars.addthis_config.username && app.ext.partner_addthis.vars.addthis_config.username !== ""){ - scriptPath+= '#username='+app.ext.partner_addthis.vars.addthis_config.username+'&domready'; + if(_app.ext.partner_addthis.vars.addthis_config.username && _app.ext.partner_addthis.vars.addthis_config.username !== ""){ + scriptPath+= '#username='+_app.ext.partner_addthis.vars.addthis_config.username+'&domready'; } else { scriptPath += '#domready'; } - app.u.loadScript(scriptPath); + _app.u.loadScript(scriptPath); //This is an example of how to add an addthis toolbox to a product page - app.rq.push(['templateFunction','productTemplate','onCompletes',function(infoObj){ - var $context = $(app.u.jqSelector('#',infoObj.parentID)); + _app.rq.push(['templateFunction','productTemplate','onCompletes',function(infoObj){ + var $context = $(_app.u.jqSelector('#',infoObj.parentID)); var $toolbox = $('.socialLinks', $context); if($toolbox.hasClass('addThisRendered')){ //Already rendered, don't do it again. @@ -70,13 +70,13 @@ var partner_addthis = function() { + '<a class="addthis_button_compact"></a>' + '</div>'); - app.ext.partner_addthis.u.toolbox($toolbox, infoObj); + _app.ext.partner_addthis.u.toolbox($toolbox, infoObj); } }]); return true; }, onError : function() { - app.u.dump('BEGIN app.ext.partner_addthis.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.partner_addthis.callbacks.init.onError'); } } }, @@ -87,8 +87,8 @@ var partner_addthis = function() { var call = 'toolbox'; var target = $tags.get(); - var configObj = app.ext.partner_addthis.vars.addthis_config; - var sharingObj = app.ext.partner_addthis.u.buildSharingObj(infoObj); + var configObj = _app.ext.partner_addthis.vars.addthis_config; + var sharingObj = _app.ext.partner_addthis.u.buildSharingObj(infoObj); this.callAddThis(call, target, configObj, sharingObj); }, @@ -96,8 +96,8 @@ var partner_addthis = function() { var call = 'button'; var target = $tags.get(); - var configObj = app.ext.partner_addthis.vars.addthis_config; - var sharingObj = app.ext.partner_addthis.u.buildSharingObj(infoObj); + var configObj = _app.ext.partner_addthis.vars.addthis_config; + var sharingObj = _app.ext.partner_addthis.u.buildSharingObj(infoObj); this.callAddThis(call, target, configObj, sharingObj); }, @@ -105,8 +105,8 @@ var partner_addthis = function() { var call = 'counter'; var target = $tags.get(); - var configObj = app.ext.partner_addthis.vars.addthis_config; - var sharingObj = app.ext.partner_addthis.u.buildSharingObj(infoObj); + var configObj = _app.ext.partner_addthis.vars.addthis_config; + var sharingObj = _app.ext.partner_addthis.u.buildSharingObj(infoObj); this.callAddThis(call, target, configObj, sharingObj); }, @@ -118,10 +118,10 @@ var partner_addthis = function() { } else { if(attempts > 40){ - app.u.dump("ADDTHIS FAILED "+call); + _app.u.dump("ADDTHIS FAILED "+call); } else { - setTimeout(function(){app.ext.partner_addthis.u.callAddThis(call, target,configObj, sharingObj, attempts+1);}, 250); + setTimeout(function(){_app.ext.partner_addthis.u.callAddThis(call, target,configObj, sharingObj, attempts+1);}, 250); } } }, @@ -131,23 +131,23 @@ var partner_addthis = function() { // http://support.addthis.com/customer/portal/articles/381263-addthis-client-api#configuration-sharing // By default only url, title, and description are supported. sharingObj = { - url : (document.location.protocol === "https:" ? zGlobals.appSettings.https_app_url : zGlobals.appSettings.http_app_url)+ app.ext.myRIA.u.buildRelativePath(infoObj), - title : app.ext.partner_addthis.vars.titlePrefix || "", - description : app.ext.partner_addthis.vars.defaultDesc || "" + url : (document.location.protocol === "https:" ? zGlobals.appSettings.https_app_url : zGlobals.appSettings.http_app_url)+ _app.ext.quickstart.u.buildRelativePath(infoObj), + title : _app.ext.partner_addthis.vars.titlePrefix || "", + description : _app.ext.partner_addthis.vars.defaultDesc || "" }; - var data = app.ext.myRIA.u.getDataFromInfoObj(infoObj); + var data = _app.ext.quickstart.u.getDataFromInfoObj(infoObj); switch(infoObj.pageType){ case "product" : - if(app.ext.partner_addthis.vars.setTitle){ + if(_app.ext.partner_addthis.vars.setTitle){ sharingObj.title += data['%attribs']['zoovy:prod_name']; } - if(app.ext.partner_addthis.vars.setDesc){ + if(_app.ext.partner_addthis.vars.setDesc){ sharingObj.description = data['%attribs']['zoovy:prod_desc']; } break; case "category" : - if(app.ext.partner_addthis.vars.setTitle){ + if(_app.ext.partner_addthis.vars.setTitle){ sharingObj.title += data.pretty; } break; diff --git a/extensions/partner_buysafe_guarantee.js b/extensions/partner_buysafe_guarantee.js index b14c7df0b..38c5f9b7c 100644 --- a/extensions/partner_buysafe_guarantee.js +++ b/extensions/partner_buysafe_guarantee.js @@ -22,12 +22,12 @@ The functions here are designed to work with 'reasonable' size lists of categori */ -var buysafe_guarantee = function() { +var buysafe_guarantee = function(_app) { var r = { vars : { "dependAttempts" : 0, //used to count how many times loading the dependencies has been attempted. - "dependencies" : ['myRIA'] //a list of other extensions (just the namespace) that are required for this one to load + "dependencies" : ['quickstart'] //a list of other extensions (just the namespace) that are required for this one to load }, //////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ @@ -36,29 +36,29 @@ var buysafe_guarantee = function() { callbacks : { init : { onSuccess : function() { - app.u.dump('BEGIN app.ext.buysafe_guarantee.onSuccess'); + _app.u.dump('BEGIN _app.ext.buysafe_guarantee.onSuccess'); /* To keep this extension as self-contained as possible, it loads it's own script. the callback is handled in the extension loader. It will handle sequencing for the most part. The startExtension will re-execute if this script isn't loaded until it has finished loading. */ - app.u.loadScript('https://seal.buysafe.com/private/rollover/rollover.js'); + _app.u.loadScript('https://seal.buysafe.com/private/rollover/rollover.js'); return true; //return false if extension won't load for some reason (account config, dependencies, etc). }, onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN app.ext.store_navcats.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_navcats.callbacks.init.onError'); } }, startExtension : { onSuccess : function(){ -app.u.dump("BEGIN buysafe_guarantee.startExtension.onSuccess."); +_app.u.dump("BEGIN buysafe_guarantee.startExtension.onSuccess."); -//make sure that not only has myRIA been loaded, but that the createTemplateFunctions has executed - if(app.ext.myRIA && app.ext.myRIA.template && app.ext.myRIA.template.productTemplate && typeof WriteBuySafeKickers == 'function' && typeof buySAFE == 'object') { +//make sure the templates have been loaded. all the quickstart templates are loaded at the same time. + if(_app.templates && _app.templates.productTemplate && typeof WriteBuySafeKickers == 'function' && typeof buySAFE == 'object') { //http://developer.buysafe.com/bsg_overview.php //http://www.buysafe.com/web/general/kickerpreview.aspx @@ -68,21 +68,21 @@ if(buySAFE.Hash.length > 0) { //the showContent function may have already executed prior to startExtension getting executed. WriteBuySafeKickers(); - app.ext.myRIA.template.productTemplate.onCompletes.push(function(P) { -// app.u.dump("Execute WriteBuySafeKicker"); + _app.templates.productTemplate.on('complete.buysafe',function(event,$ele,P) { +// _app.u.dump("Execute WriteBuySafeKicker"); //buysafe trigger goes here. WriteBuySafeKickers(); }) - app.ext.myRIA.template.cartTemplate.onCompletes.push(function(P) { + _app.templates.cartTemplate.on('complete.buysafe',function(event,$ele,P) { //buysafe trigger goes here. WriteBuySafeKickers(); }) - app.ext.orderCreate.checkoutCompletes.push(function(P){ + _app.templates.checkoutTemplate.on('complete.buysafe',function(event,$ele,P){ - app.u.dump("BEGIN buysafe_guarantee code pushed on orderCreate.checkoutCompletes"); - var order = app.data['order|'+P.orderID].cart; + _app.u.dump("BEGIN buysafe_guarantee code pushed on order_create.checkoutCompletes"); + var order = _app.data['order|'+P.orderID].cart; buySAFE.Guarantee.order = P.orderID; buySAFE.Guarantee.subtotal = order['sum/items_total']; @@ -92,11 +92,11 @@ if(buySAFE.Hash.length > 0) { }); // end .push } else { - app.u.dump("WARNING! buySAFE.Hash not set/valid ["+buySAFE.Hash+"]"); + _app.u.dump("WARNING! buySAFE.Hash not set/valid ["+buySAFE.Hash+"]"); } } else { - setTimeout(function(){app.ext.buysafe_guarantee.callbacks.startExtension.onSuccess()},250); + setTimeout(function(){_app.ext.buysafe_guarantee.callbacks.startExtension.onSuccess()},250); } }, diff --git a/extensions/partner_google_adwords.js b/extensions/partner_google_adwords.js index 361930649..9233fd57c 100644 --- a/extensions/partner_google_adwords.js +++ b/extensions/partner_google_adwords.js @@ -17,47 +17,184 @@ ************************************************************** */ /* -An extension for Google Adwords conversion tracking. - -This extension is untested. - +An extension for acquiring and displaying 'lists' of categories. +The functions here are designed to work with 'reasonable' size lists of categories. */ -var google_adwords = function() { - var r= { - vars : { - }, +var google_analytics = function(_app) { + var r = { + vars : { +//GA records an app visit/departure as a bounce unless an event is fired triggering the opt_noninteraction option. +//so we fire one off after the page changes once. This var is used to track it so that we don't fire it off multiple times. + triggeredBounceCode : false //Need to fire some event after app inits and after page change to get google to track bounces correc + }, + +//////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + callbacks : { init : { - onSuccess : function(){ - //nothing needs to be loaded except on conversion. + onSuccess : function() { + +/* +To keep this extension as self-contained as possible, it loads it's own script. +the callback is handled in the extension loader. It will handle sequencing for the most part. +The startExtension will re-execute if this script isn't loaded until it has finished loading. +*/ + _app.u.loadScript(('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'); + if(zGlobals.checkoutSettings.googleCheckoutMerchantId) { + _app.u.loadScript(('https:' == document.location.protocol ? 'https://' : 'http://') + 'checkout.google.com/files/digital/ga_post.js'); //needed 4 tracking google wallet orders in GA. + } + return true; + }, + onError : function() { + //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. + //you may or may not need it. + _app.u.dump('BEGIN _app.ext.google_analytics.callbacks.init.onError'); + } }, - onError : function() { - app.u.dump('BEGIN app.ext.google_adwords.callbacks.init.onError'); + + startExtension : { + onSuccess : function(){ +// _app.u.dump("BEGIN google_analytics.callbacks.startExtension.onSuccess"); + +//make sure that not only has quickstart been loaded, but that the createTemplateFunctions has executed + if(_app.templates && _app.templates.productTemplate && typeof _gaq == 'object') { + +//_app.u.dump(" -> adding triggers"); +_app.templates.homepageTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/index.html']); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.categoryTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/category/'+P.navcat]); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.productTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/product/'+P.pid]); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.companyTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/company/'+P.show]); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.customerTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/customer/'+P.show]); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.checkoutTemplate.on('init.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/checkout']); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) + +_app.templates.searchTemplate.on('init.googleanalytics',function(event,$ele,P) { + _gaq.push('_trackPageview','/search?KEYWORDS='+P.KEYWORDS); + _app.ext.google_analytics.u.handleAntiBounceEvent(P); + }) +//404's don't execute the anti-bounce event because if you go homepage then 404 and leave, it should register as a bounce. +_app.templates.pageNotFoundTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer]);}) + + +//for GoogleTrustedStores. +_app.ext.order_create.checkoutCompletes.push(function(P){ + if(typeof window.GoogleTrustedStore) { + if(P && P.datapointer && _app.data[P.datapointer] && _app.data[P.datapointer].order) { + var order = _app.data[P.datapointer].order, + $div = $("<div \/>",{'id':'gts-order'}), + L = order['@ITEMS'].length, hasPreBack = 'N', discounts = 0; + + for(var i = 0; i < L; i += 1) { + if(order['@ITEMS'][i].sku.charAt(0) == '%') {discounts += Number(order['@ITEMS'][i].extended)} } - }, - startExtension : { - onSuccess : function (){ - if(app.ext.myRIA && app.ext.myRIA.template){ - app.ext.orderCreate.checkoutCompletes.push(function(P){ - app.u.dump("BEGIN google_adwords code pushed on orderCreate.checkoutCompletes"); - var order = app.data['order|'+P.orderID]; - google_conversion_value = order.sum.items_total; - app.u.loadScript(('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.googleadservices.com/pagead/conversion.js'); - }); - } else { - setTimeout(function(){app.ext.google_adwords.callbacks.startExtension.onSuccess()},250); - } - }, - onError : function (){ - app.u.dump('BEGIN app.ext.google_adwords.callbacks.startExtension.onError'); + $("<span \/>",{'id':'gts-o-id'}).text(P.orderID).appendTo($div); + $("<span \/>",{'id':'gts-o-domain'}).text(document.domain).appendTo($div); //sdomain + $("<span \/>",{'id':'gts-o-email'}).text(order.customer.login || order.bill.email).appendTo($div); + $("<span \/>",{'id':'gts-o-country'}).text(order.bill.countrycode).appendTo($div); + $("<span \/>",{'id':'gts-o-total'}).text(order.sum.order_total).appendTo($div); + $("<span \/>",{'id':'gts-o-currency'}).text('USD').appendTo($div); + $("<span \/>",{'id':'gts-o-discounts'}).text(discounts).appendTo($div); + $("<span \/>",{'id':'gts-o-shipping-total'}).text(order.sum.ship_total).appendTo($div); + $("<span \/>",{'id':'gts-o-tax-total'}).text(order.sum.tax_total).appendTo($div); + //$("<span \/>",{'id':'gts-o-est-ship-date'}).text("").appendTo($div); //!!! needs to be set. + $("<span \/>",{'id':'gts-o-has-preorder'}).text(hasPreBack).appendTo($div); //set in loop above. + $("<span \/>",{'id':'gts-o-has-digital'}).text('N').appendTo($div); + + $div.appendTo('body'); + +//delete existing object or gts conversion won't load right. + delete window.GoogleTrustedStore; +//this function will re-load the gts code. The spans above tell the GTS store to treat this as a conversion. +//so it's important those spans are added to the DOM prior to this code being run. + (function() { + var scheme = (("https:" == document.location.protocol) ? "https://" : "http://"); + var gts = document.createElement("script"); + gts.type = "text/javascript"; + gts.async = true; + gts.src = scheme + "www.googlecommerce.com/trustedstores/gtmp_compiled.js"; + var s = document.getElementsByTagName("script")[0]; + s.parentNode.insertBefore(gts, s); + })(); + + + } + else { + //unable to determine order contents. + } + } + }); + + +_app.ext.order_create.checkoutCompletes.push(function(P){ + _app.u.dump("BEGIN google_analytics code pushed on order_create.checkoutCompletes"); + if(P && P.datapointer && _app.data[P.datapointer] && _app.data[P.datapointer].order) { + var order = _app.data[P.datapointer].order; + if(_app.data[P.datapointer].payment_status && _app.data[P.datapointer].payment_status.charAt(0) == 0) { + + _gaq.push(['_addTrans', + P.orderID, // order ID - required + '', // affiliation or store name + order.sum.order_total, // total - required + order.sum.tax_total, // tax + order.sum.ship_total, // shipping + order.sum.city, // city + order.sum.region, // state or province + order.sum.countrycode // country + ]); + + var L = order['@ITEMS'].length; + _app.u.dump(" -> "+L+" items in @ITEMS"); + + for(var i = 0; i < L; i += 1) { + _gaq.push(['_addItem', + P.orderID, // order ID - necessary to associate item with transaction + order['@ITEMS'][i].product, // SKU/code - required + order['@ITEMS'][i].prod_name, // product name - necessary to associate revenue with product + order['@ITEMS'][i].stid, // category or variation + order['@ITEMS'][i].base_price, // unit price - required + order['@ITEMS'][i].qty // quantity - required + ]); } + _gaq.push(['_trackTrans']); + + + } + else { + //payment was declined or some kind of error occured. Do not track as conversion. + } } - } + else { + //unable to determine order contents. + } + }); // end .push + + } + else { + setTimeout(function(){_app.ext.google_analytics.callbacks.startExtension.onSuccess()},250); + } + + }, + onError : function(){} + } + }, //callbacks + u : { + handleAntiBounceEvent : function(P) { +//see comment up by var triggerBounceCode for what this is for. + if(!_app.ext.google_analytics.vars.triggeredBounceCode) { + _gaq.push(['_trackEvent','pageView','navigate','','',false]); + _app.ext.google_analytics.vars.triggeredBounceCode = true; + } + else { + //catch. + } + } + } //util + } //r object. return r; -} \ No newline at end of file + } \ No newline at end of file diff --git a/extensions/partner_google_analytics.js b/extensions/partner_google_analytics.js index c2efbd73d..9233fd57c 100644 --- a/extensions/partner_google_analytics.js +++ b/extensions/partner_google_analytics.js @@ -22,7 +22,7 @@ The functions here are designed to work with 'reasonable' size lists of categori */ -var google_analytics = function() { +var google_analytics = function(_app) { var r = { vars : { @@ -43,9 +43,9 @@ To keep this extension as self-contained as possible, it loads it's own script. the callback is handled in the extension loader. It will handle sequencing for the most part. The startExtension will re-execute if this script isn't loaded until it has finished loading. */ - app.u.loadScript(('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'); + _app.u.loadScript(('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'); if(zGlobals.checkoutSettings.googleCheckoutMerchantId) { - app.u.loadScript(('https:' == document.location.protocol ? 'https://' : 'http://') + 'checkout.google.com/files/digital/ga_post.js'); //needed 4 tracking google wallet orders in GA. + _app.u.loadScript(('https:' == document.location.protocol ? 'https://' : 'http://') + 'checkout.google.com/files/digital/ga_post.js'); //needed 4 tracking google wallet orders in GA. } return true; @@ -53,38 +53,38 @@ The startExtension will re-execute if this script isn't loaded until it has fini onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN app.ext.google_analytics.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.google_analytics.callbacks.init.onError'); } }, startExtension : { onSuccess : function(){ -// app.u.dump("BEGIN google_analytics.callbacks.startExtension.onSuccess"); +// _app.u.dump("BEGIN google_analytics.callbacks.startExtension.onSuccess"); -//make sure that not only has myRIA been loaded, but that the createTemplateFunctions has executed - if(app.ext.myRIA && app.ext.myRIA.template && typeof _gaq == 'object') { +//make sure that not only has quickstart been loaded, but that the createTemplateFunctions has executed + if(_app.templates && _app.templates.productTemplate && typeof _gaq == 'object') { -//app.u.dump(" -> adding triggers"); -app.ext.myRIA.template.homepageTemplate.onCompletes.push(function(P) {_gaq.push(['_trackPageview', '/index.html']); app.ext.google_analytics.u.handleAntiBounceEvent(P);}) -app.ext.myRIA.template.categoryTemplate.onCompletes.push(function(P) {_gaq.push(['_trackPageview', '/category/'+P.navcat]); app.ext.google_analytics.u.handleAntiBounceEvent(P);}) -app.ext.myRIA.template.productTemplate.onCompletes.push(function(P) {_gaq.push(['_trackPageview', '/product/'+P.pid]); app.ext.google_analytics.u.handleAntiBounceEvent(P);}) -app.ext.myRIA.template.companyTemplate.onCompletes.push(function(P) {_gaq.push(['_trackPageview', '/company/'+P.show]); app.ext.google_analytics.u.handleAntiBounceEvent(P);}) -app.ext.myRIA.template.customerTemplate.onCompletes.push(function(P) {_gaq.push(['_trackPageview', '/customer/'+P.show]); app.ext.google_analytics.u.handleAntiBounceEvent(P);}) -app.ext.myRIA.template.checkoutTemplate.onInits.push(function(P) {_gaq.push(['_trackPageview', '/checkout']); app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +//_app.u.dump(" -> adding triggers"); +_app.templates.homepageTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/index.html']); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.categoryTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/category/'+P.navcat]); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.productTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/product/'+P.pid]); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.companyTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/company/'+P.show]); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.customerTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/customer/'+P.show]); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) +_app.templates.checkoutTemplate.on('init.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/checkout']); _app.ext.google_analytics.u.handleAntiBounceEvent(P);}) -app.ext.myRIA.template.searchTemplate.onInits.push(function(P) { +_app.templates.searchTemplate.on('init.googleanalytics',function(event,$ele,P) { _gaq.push('_trackPageview','/search?KEYWORDS='+P.KEYWORDS); - app.ext.google_analytics.u.handleAntiBounceEvent(P); + _app.ext.google_analytics.u.handleAntiBounceEvent(P); }) //404's don't execute the anti-bounce event because if you go homepage then 404 and leave, it should register as a bounce. -app.ext.myRIA.template.pageNotFoundTemplate.onCompletes.push(function(P) {_gaq.push(['_trackPageview', '/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer]);}) +_app.templates.pageNotFoundTemplate.on('complete.googleanalytics',function(event,$ele,P) {_gaq.push(['_trackPageview', '/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer]);}) //for GoogleTrustedStores. -app.ext.orderCreate.checkoutCompletes.push(function(P){ +_app.ext.order_create.checkoutCompletes.push(function(P){ if(typeof window.GoogleTrustedStore) { - if(P && P.datapointer && app.data[P.datapointer] && app.data[P.datapointer].order) { - var order = app.data[P.datapointer].order, + if(P && P.datapointer && _app.data[P.datapointer] && _app.data[P.datapointer].order) { + var order = _app.data[P.datapointer].order, $div = $("<div \/>",{'id':'gts-order'}), L = order['@ITEMS'].length, hasPreBack = 'N', discounts = 0; @@ -130,35 +130,44 @@ app.ext.orderCreate.checkoutCompletes.push(function(P){ }); -app.ext.orderCreate.checkoutCompletes.push(function(P){ - app.u.dump("BEGIN google_analytics code pushed on orderCreate.checkoutCompletes"); - if(P && P.datapointer && app.data[P.datapointer] && app.data[P.datapointer].order) { - var order = app.data[P.datapointer].order; - _gaq.push(['_addTrans', - P.orderID, // order ID - required - '', // affiliation or store name - order.sum.order_total, // total - required - order.sum.tax_total, // tax - order.sum.ship_total, // shipping - order.sum.city, // city - order.sum.region, // state or province - order.sum.countrycode // country - ]); - - var L = order['@ITEMS'].length; - app.u.dump(" -> "+L+" items in @ITEMS"); - - for(var i = 0; i < L; i += 1) { - _gaq.push(['_addItem', - P.orderID, // order ID - necessary to associate item with transaction - order['@ITEMS'][i].product, // SKU/code - required - order['@ITEMS'][i].prod_name, // product name - necessary to associate revenue with product - order['@ITEMS'][i].stid, // category or variation - order['@ITEMS'][i].base_price, // unit price - required - order['@ITEMS'][i].qty // quantity - required - ]); +_app.ext.order_create.checkoutCompletes.push(function(P){ + _app.u.dump("BEGIN google_analytics code pushed on order_create.checkoutCompletes"); + if(P && P.datapointer && _app.data[P.datapointer] && _app.data[P.datapointer].order) { + var order = _app.data[P.datapointer].order; + if(_app.data[P.datapointer].payment_status && _app.data[P.datapointer].payment_status.charAt(0) == 0) { + + _gaq.push(['_addTrans', + P.orderID, // order ID - required + '', // affiliation or store name + order.sum.order_total, // total - required + order.sum.tax_total, // tax + order.sum.ship_total, // shipping + order.sum.city, // city + order.sum.region, // state or province + order.sum.countrycode // country + ]); + + var L = order['@ITEMS'].length; + _app.u.dump(" -> "+L+" items in @ITEMS"); + + for(var i = 0; i < L; i += 1) { + _gaq.push(['_addItem', + P.orderID, // order ID - necessary to associate item with transaction + order['@ITEMS'][i].product, // SKU/code - required + order['@ITEMS'][i].prod_name, // product name - necessary to associate revenue with product + order['@ITEMS'][i].stid, // category or variation + order['@ITEMS'][i].base_price, // unit price - required + order['@ITEMS'][i].qty // quantity - required + ]); + } + _gaq.push(['_trackTrans']); + + + } + else { + //payment was declined or some kind of error occured. Do not track as conversion. + } - _gaq.push(['_trackTrans']); } else { //unable to determine order contents. @@ -167,7 +176,7 @@ app.ext.orderCreate.checkoutCompletes.push(function(P){ } else { - setTimeout(function(){app.ext.google_analytics.callbacks.startExtension.onSuccess()},250); + setTimeout(function(){_app.ext.google_analytics.callbacks.startExtension.onSuccess()},250); } }, @@ -177,9 +186,9 @@ app.ext.orderCreate.checkoutCompletes.push(function(P){ u : { handleAntiBounceEvent : function(P) { //see comment up by var triggerBounceCode for what this is for. - if(!app.ext.google_analytics.vars.triggeredBounceCode) { + if(!_app.ext.google_analytics.vars.triggeredBounceCode) { _gaq.push(['_trackEvent','pageView','navigate','','',false]); - app.ext.google_analytics.vars.triggeredBounceCode = true; + _app.ext.google_analytics.vars.triggeredBounceCode = true; } else { //catch. diff --git a/extensions/partner_magictoolbox_mzp.js b/extensions/partner_magictoolbox_mzp.js index a9067f5dc..4991004ea 100644 --- a/extensions/partner_magictoolbox_mzp.js +++ b/extensions/partner_magictoolbox_mzp.js @@ -32,7 +32,7 @@ EX: <img src='images/blank.gif' data-bind='var: product(zoovy:prod_image1); form */ -var magicToolBox_mzp = function() { +var magicToolBox_mzp = function(_app) { return { @@ -52,23 +52,23 @@ var magicToolBox_mzp = function() { init : { onSuccess : function() { - // app.u.dump('BEGIN app.ext.store_crm.init.onSuccess '); + // _app.u.dump('BEGIN _app.ext.store_crm.init.onSuccess '); return true; //currently, no system or config requirements to use this extension - // app.u.dump('END app.ext.store_crm.init.onSuccess'); + // _app.u.dump('END _app.ext.store_crm.init.onSuccess'); }, onError : function(d) { - app.u.dump('BEGIN magicToolBox_mzp.callbacks.init.onError'); + _app.u.dump('BEGIN magicToolBox_mzp.callbacks.init.onError'); } }, startExtension : { onSuccess : function(){ - app.u.dump("BEGIN magictoolbox.callbacks.startExtension"); - app.rq.push(['css',0,'examples/magictoolbox/magiczoomplus.css','mzpStylesheet']); - app.rq.push(['script',0,'examples/magictoolbox/magiczoomplus.js',function(){ + _app.u.dump("BEGIN magictoolbox.callbacks.startExtension"); + _app.rq.push(['css',0,'examples/magictoolbox/magiczoomplus.css','mzpStylesheet']); + _app.rq.push(['script',0,'examples/magictoolbox/magiczoomplus.js',function(){ MagicZoomPlus.start(); - app.rq.push(['templateFunction','productTemplate','onCompletes',function(P) {app.u.dump("Refreshing MZP."); setTimeout(function(){MagicZoomPlus.refresh();},2000)}]); + _app.rq.push(['templateFunction','productTemplate','onCompletes',function(P) {_app.u.dump("Refreshing MZP."); setTimeout(function(){MagicZoomPlus.refresh();},2000)}]); }]); -// app.rq.push(['templateFunction','productTemplate','onCompletes',function(P) {app.u.dump("Refreshing MZP."); MagicZoomPlus.refresh();}]); +// _app.rq.push(['templateFunction','productTemplate','onCompletes',function(P) {_app.u.dump("Refreshing MZP."); MagicZoomPlus.refresh();}]); }, onError : function(d){} @@ -84,13 +84,13 @@ var magicToolBox_mzp = function() { renderFormats : { magicZoomPlus : function($tag,data) { - app.u.dump('BEGIN myRIA.renderFormats.magicZoomPlus'); + _app.u.dump('BEGIN quickstart.renderFormats.magicZoomPlus'); var bgcolor = data.bindData.bgcolor ? data.bindData.bgcolor : 'ffffff' if(data.value) { - var imgSrc = app.u.makeImage({'tag':0,'w':$tag.attr('width'),'h':$tag.attr('height'),'name':data.value,'b':bgcolor}); - app.u.dump('ID => '+$tag.attr('id')); + var imgSrc = _app.u.makeImage({'tag':0,'w':$tag.attr('width'),'h':$tag.attr('height'),'name':data.value,'b':bgcolor}); + _app.u.dump('ID => '+$tag.attr('id')); $tag.attr('src',imgSrc); - $tag.wrap("<a href='"+app.u.makeImage({'tag':0,'name':data.value,'b':bgcolor})+"' class='MagicZoomPlus' id='"+$tag.attr('id')+"_href' />") + $tag.wrap("<a href='"+_app.u.makeImage({'tag':0,'name':data.value,'b':bgcolor})+"' class='MagicZoomPlus' id='"+$tag.attr('id')+"_href' />") } else { $tag.style('display','none'); //if there is no image, hide the src. !!! added 1/26/2012. this a good idea? @@ -98,13 +98,13 @@ var magicToolBox_mzp = function() { }, magicThumb : function($tag,data) { - app.u.dump('BEGIN myRIA.renderFormats.magicThumb'); + _app.u.dump('BEGIN quickstart.renderFormats.magicThumb'); var bgcolor = data.bindData.bgcolor ? data.bindData.bgcolor : 'ffffff' if(data.value) { - var imgSrc = app.u.makeImage({'tag':0,'w':$tag.attr('width'),'h':$tag.attr('height'),'name':data.value,'b':bgcolor}); -// app.u.dump('IMGSRC => '+imgSrc); + var imgSrc = _app.u.makeImage({'tag':0,'w':$tag.attr('width'),'h':$tag.attr('height'),'name':data.value,'b':bgcolor}); +// _app.u.dump('IMGSRC => '+imgSrc); $tag.attr('src',imgSrc); - $tag.wrap("<a href='"+app.u.makeImage({'tag':0,'name':data.value,'b':bgcolor})+"' rev='"+app.u.makeImage({'tag':0,'w':350,'h':350,'name':data.value,'b':bgcolor})+"' class='MagicThumb Selector MagicThumb-swap' />") + $tag.wrap("<a href='"+_app.u.makeImage({'tag':0,'name':data.value,'b':bgcolor})+"' rev='"+_app.u.makeImage({'tag':0,'w':350,'h':350,'name':data.value,'b':bgcolor})+"' class='MagicThumb Selector MagicThumb-swap' />") // makes shit blow up: rel='zoom-id:bigAssImage_href; selectors-change:mouseover;' } else { @@ -116,15 +116,15 @@ var magicToolBox_mzp = function() { // used to display product image 1 thru X where X is the last image. checks spot 1 - 50 // product id should be used as var productImages : function($tag,data) { -// app.u.dump("BEGIN myRIA.renderFormats.productImages ["+data.value+"]"); - var pdata = app.data['appProductGet|'+data.value]['%attribs']; //short cut to product object in memory. +// _app.u.dump("BEGIN quickstart.renderFormats.productImages ["+data.value+"]"); + var pdata = _app.data['appProductGet|'+data.value]['%attribs']; //short cut to product object in memory. var imgs = ''; //all the html for all the images. appended to $tag after loop. var imgName; //recycled in loop. for(i = 1; i < 30; i += 1) { imgName = pdata['zoovy:prod_image'+i]; -// app.u.dump(" -> "+i+": "+imgName); - if(app.u.isSet(imgName)) { - imgs += "<li><a class='MagicThumb' rel='zoom-id: prodBigImage_href;' rev='"+app.u.makeImage({'tag':0,'w':380,'h':380,'name':imgName,'b':'ffffff'})+"' href='"+app.u.makeImage({'tag':0,'w':'','h':'','name':imgName,'b':'ffffff'})+"'><img src='"+app.u.makeImage({'tag':0,'w':50,'h':50,'name':imgName,'b':'ffffff'})+"' \/><\/a><\/li>"; +// _app.u.dump(" -> "+i+": "+imgName); + if(_app.u.isSet(imgName)) { + imgs += "<li><a class='MagicThumb' rel='zoom-id: prodBigImage_href;' rev='"+_app.u.makeImage({'tag':0,'w':380,'h':380,'name':imgName,'b':'ffffff'})+"' href='"+_app.u.makeImage({'tag':0,'w':'','h':'','name':imgName,'b':'ffffff'})+"'><img src='"+_app.u.makeImage({'tag':0,'w':50,'h':50,'name':imgName,'b':'ffffff'})+"' \/><\/a><\/li>"; } } $tag.append(imgs); diff --git a/extensions/partner_powerreviews_reviews.js b/extensions/partner_powerreviews_reviews.js index aed6f617e..d9b20d2ed 100644 --- a/extensions/partner_powerreviews_reviews.js +++ b/extensions/partner_powerreviews_reviews.js @@ -23,7 +23,7 @@ NOTE - requires powerReviews service. To add powerReviews, do the following: #1) add extension to extensions object. -ex: app.rq.push(['extension',1,'powerReviews','extensions/reviews_powerreviews.js','startExtension']); +ex: _app.rq.push(['extension',1,'powerReviews','extensions/reviews_powerreviews.js','startExtension']); #2) update the vars object with merchant and group id. all are required and will be provided by the merchant or project manager. #3) update templates to use the following databind databind: @@ -56,7 +56,7 @@ This file is included in an iFrame for 'write review' */ -var powerReviews_reviews = function() { +var powerReviews_reviews = function(_app) { return { @@ -79,35 +79,35 @@ var powerReviews_reviews = function() { init : { onSuccess : function() { -// app.u.dump('BEGIN app.ext.store_crm.init.onSuccess '); +// _app.u.dump('BEGIN _app.ext.store_crm.init.onSuccess '); var r; - if(app.ext.powerReviews_reviews.vars.merchantID && app.ext.powerReviews_reviews.vars.groupID) { + if(_app.ext.powerReviews_reviews.vars.merchantID && _app.ext.powerReviews_reviews.vars.groupID) { r = true; } else { - var msg = app.u.errMsgObject("Uh Oh! It seems an error occured on our app. PowerReviews may not load properly. We apologize for the inconvenience."); + var msg = _app.u.errMsgObject("Uh Oh! It seems an error occured on our _app. PowerReviews may not load properly. We apologize for the inconvenience."); msg.persistent = true; - app.u.throwMessage(msg); - app.u.dump("ERROR! powerReviews_reviews did not pass init. The following variables are all required:"); - app.u.dump(" -> app.ext.powerReviews_reviews.vars.merchantID: "+app.ext.powerReviews_reviews.vars.merchantID); - app.u.dump(" -> app.ext.powerReviews_reviews.vars.groupID: "+app.ext.powerReviews_reviews.vars.groupID); - app.u.dump(" -> app.ext.powerReviews_reviews.vars.hash: "+app.ext.powerReviews_reviews.vars.hash); + _app.u.throwMessage(msg); + _app.u.dump("ERROR! powerReviews_reviews did not pass init. The following variables are all required:"); + _app.u.dump(" -> _app.ext.powerReviews_reviews.vars.merchantID: "+_app.ext.powerReviews_reviews.vars.merchantID); + _app.u.dump(" -> _app.ext.powerReviews_reviews.vars.groupID: "+_app.ext.powerReviews_reviews.vars.groupID); + _app.u.dump(" -> _app.ext.powerReviews_reviews.vars.hash: "+_app.ext.powerReviews_reviews.vars.hash); r = false; } return r; - // app.u.dump('END app.ext.store_crm.init.onSuccess'); + // _app.u.dump('END _app.ext.store_crm.init.onSuccess'); }, onError : function(d) { - app.u.dump('BEGIN app.ext.store_crm.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_crm.callbacks.init.onError'); } }, startExtension : { onSuccess : function(){ - app.u.dump("BEGIN powerReviews_reviews.callbacks.startExtension"); - app.rq.push(['script',0,'http://cdn.powerreviews.com/repos/'+app.ext.powerReviews_reviews.vars.merchantID+'/pr/pwr/engine/js/full.js']); - app.rq.push(['css',0,'http://cdn.powerreviews.com/repos/'+app.ext.powerReviews_reviews.vars.merchantID+'/pr/pwr/engine/pr_styles_review.css','prBaseStylesheet']); - app.rq.push(['css',0,'http://cdn.powerreviews.com/aux/'+app.ext.powerReviews_reviews.vars.merchantID+'/'+app.ext.powerReviews_reviews.vars.groupID+'/css/powerreviews_express.css','prMerchantOverrideStylesheet']); + _app.u.dump("BEGIN powerReviews_reviews.callbacks.startExtension"); + _app.rq.push(['script',0,'http://cdn.powerreviews.com/repos/'+_app.ext.powerReviews_reviews.vars.merchantID+'/pr/pwr/engine/js/full.js']); + _app.rq.push(['css',0,'http://cdn.powerreviews.com/repos/'+_app.ext.powerReviews_reviews.vars.merchantID+'/pr/pwr/engine/pr_styles_review.css','prBaseStylesheet']); + _app.rq.push(['css',0,'http://cdn.powerreviews.com/aux/'+_app.ext.powerReviews_reviews.vars.merchantID+'/'+_app.ext.powerReviews_reviews.vars.groupID+'/css/powerreviews_express.css','prMerchantOverrideStylesheet']); }, onError : function(d){} } @@ -125,21 +125,21 @@ var powerReviews_reviews = function() { if(document.location.protocol != 'https:') { POWERREVIEWS.display.snippet({ write : function(content) { $tag.append(content); } }, { pr_page_id : data.value, - pr_write_review : "javascript:app.ext.powerReviews_reviews.a.writeReview('"+data.value+"');" + pr_write_review : "javascript:_app.ext.powerReviews_reviews.a.writeReview('"+data.value+"');" }) } }, //reviewSnippet reviewEngine : function ($tag,data) { -// app.u.dump("BEGIN powerreviews.renderFormats.reviewEngine ["+data.value+"]"); +// _app.u.dump("BEGIN powerreviews.renderFormats.reviewEngine ["+data.value+"]"); if(document.location.protocol != 'https:') { POWERREVIEWS.display.engine({ write : function(content) { $tag.append(content); - // app.u.dump(content); + // _app.u.dump(content); }},{ pr_page_id : data.value, - pr_write_review : "javascript:app.ext.powerReviews_reviews.a.writeReview('"+data.value+"');" + pr_write_review : "javascript:_app.ext.powerReviews_reviews.a.writeReview('"+data.value+"');" }); } } @@ -166,7 +166,7 @@ var powerReviews_reviews = function() { $div.dialog('open'); */ } else { - app.u.dump("WARNING! - no pid was specified for powerReviews_reviews.a.writeReview"); + _app.u.dump("WARNING! - no pid was specified for powerReviews_reviews.a.writeReview"); } } //writeReview }, //action diff --git a/extensions/partner_resellerratings_survey.js b/extensions/partner_resellerratings_survey.js index a66f2cef7..102e2dd12 100644 --- a/extensions/partner_resellerratings_survey.js +++ b/extensions/partner_resellerratings_survey.js @@ -25,7 +25,7 @@ seller_id = #####; */ -var resellerratings_survey = function() { +var resellerratings_survey = function(_app) { var r = { vars : { @@ -37,24 +37,24 @@ var resellerratings_survey = function() { callbacks : { init : { onSuccess : function() { - app.rq.push(['css',0,'https://www.resellerratings.com/images/js/dhtml_survey.css','resellerratings_styles']); + _app.rq.push(['css',0,'https://www.resellerratings.com/images/js/dhtml_survey.css','resellerratings_styles']); return true; }, onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN app.ext.store_navcats.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_navcats.callbacks.init.onError'); } }, startExtension : { onSuccess : function(){ -app.ext.orderCreate.checkoutCompletes.push(function(P){ +_app.ext.order_create.checkoutCompletes.push(function(P){ //declared as window. to indicate they should be global. window.__rr_inv = P.orderID; window.__rr_email_pass = P.bill.email; - app.u.loadScript('https://www.resellerratings.com/images/js/popup_include.js'); + _app.u.loadScript('https://www.resellerratings.com/images/js/popup_include.js'); }); // end .push }, diff --git a/extensions/prodlist_infinite.js b/extensions/prodlist_infinite.js index b5a0a9101..cb2847bc9 100644 --- a/extensions/prodlist_infinite.js +++ b/extensions/prodlist_infinite.js @@ -35,7 +35,7 @@ Currently, this is specific to product Lists and will not work on a prodsearch a */ -var prodlist_infinite = function() { +var prodlist_infinite = function(_app) { var r = { vars : { forgetmeContainer : {} //used to store an object of pids (key) for items that don't show in the prodlist. value can be app specific. TS makes sense. @@ -56,18 +56,13 @@ var prodlist_infinite = function() { //callbacks.init need to return either a true or a false, depending on whether or not the file will execute properly based on store account configuration. init : { onSuccess : function() { -// app.u.dump('BEGIN app.ext.prodlist_infinite.init.onSuccess '); +// _app.u.dump('BEGIN _app.ext.prodlist_infinite.init.onSuccess '); return true; //currently, there are no config or extension dependencies, so just return true. may change later. -//unbind this from window anytime a category page is left. -//NOTE! if infinite prodlist is used on other pages, remove run this on that template as well. - app.rq.push(['templateFunction','categoryTemplate','onCompletes',function(P) { - $(window).off('scroll.infiniteScroll'); - }]); - -// app.u.dump('END app.ext.store_prodlist.init.onSuccess'); + +// _app.u.dump('END _app.ext.store_prodlist.init.onSuccess'); }, onError : function() { - app.u.dump('BEGIN app.ext.store_prodlist.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_prodlist.callbacks.init.onError'); } } @@ -91,13 +86,14 @@ var prodlist_infinite = function() { //that parent ID is prepended to the sku and used in the list item id to decrease likelyhood of duplicate id's //data.bindData will get passed into getProdlistVar and used for defaults on the list itself. That means any var supported in prodlistVars can be set in bindData. - infiniteProductList : function($tag,data) { -// app.u.dump("BEGIN prodlist_infinite.renderFormats.infiniteProductList"); -// app.u.dump(" -> data.bindData: "); app.u.dump(data.bindData); - if(app.u.isSet(data.value)) { + infiniteproductlist : function($tag,data) { +// _app.u.dump("BEGIN prodlist_infinite.renderFormats.infiniteProductList"); dump(data); +// _app.u.dump(" -> data.bindData: "); _app.u.dump(data.bindData); + data.bindData.loadsTemplate = data.bindData.templateid; + if(_app.u.isSet(data.value)) { data.bindData.csv = data.value; $tag.data('bindData',data.bindData); - app.ext.prodlist_infinite.u.buildInfiniteProductList($tag); + _app.ext.prodlist_infinite.u.buildInfiniteProductList($tag); } }//prodlist @@ -123,8 +119,8 @@ This is the function that gets executed to build a product list. It is run once, executed by the renderFormat. */ buildInfiniteProductList : function($tag) { -// app.u.dump("BEGIN store_prodlist.u.buildInfiniteProductList()"); -// app.u.dump(" -> obj: "); app.u.dump(obj); +// _app.u.dump("BEGIN store_prodlist.u.buildInfiniteProductList()"); +// _app.u.dump(" -> obj: "); _app.u.dump(obj); var bindData = $tag.data('bindData'); //tag is likely an li or a table. add a loading graphic after it. @@ -134,57 +130,50 @@ It is run once, executed by the renderFormat. //Need either the tag itself ($tag) or the parent id to build a list. recommend $tag to ensure unique parent id is created //also need a list of product (csv) if($tag && bindData.csv) { -// app.u.dump(" -> required parameters exist. Proceed..."); +// _app.u.dump(" -> required parameters exist. Proceed..."); - bindData.csv = app.ext.store_prodlist.u.cleanUpProductList(bindData.csv); //strip blanks and make sure this is an array. prod attributes are not, by default. - app.u.dump(" -> bindData.csv after cleanup: "); app.u.dump(bindData.csv); + bindData.csv = _app.ext.store_prodlist.u.cleanUpProductList(bindData.csv); //strip blanks and make sure this is an array. prod attributes are not, by default. +// _app.u.dump(" -> bindData.csv after cleanup: "); _app.u.dump(bindData.csv); this.addProductToPage($tag); } else { - app.u.throwGMessage("WARNING: store_prodlist.u.buildInfiniteProductList is missing some required fields. bindData follows: "); - app.u.dump(bindData); + _app.u.throwGMessage("WARNING: store_prodlist.u.buildInfiniteProductList is missing some required fields. bindData follows: "); + _app.u.dump(bindData); } -// app.u.dump(" -> r = "+r); +// _app.u.dump(" -> r = "+r); }, //buildInfiniteProductList addProductToPage : function($tag) { - app.u.dump("BEGIN prodlist_infinite.u.addProductToPage"); + _app.u.dump("BEGIN prodlist_infinite.u.addProductToPage"); $tag.data('isDispatching',true); - var plObj = app.ext.store_prodlist.u.setProdlistVars($tag.data('bindData')), + var plObj = _app.ext.store_prodlist.u.setProdlistVars($tag.data('bindData')), numRequests = 0, - pageCSV = app.ext.store_prodlist.u.getSkusForThisPage(plObj), //gets a truncated list based on items per page. + pageCSV = _app.ext.store_prodlist.u.getSkusForThisPage(plObj), //gets a truncated list based on items per page. L = pageCSV.length; $tag.data('prodlist',plObj); //sets data object on parent + var $template = new tlc().getTemplateInstance(plObj.loadsTemplate); + function handleProd(pid,$templateCopy) { + $templateCopy.attr('data-pid',pid); + return _app.calls.appProductGet.init({"pid":pid,"withVariations":plObj.withVariations,"withInventory":plObj.withInventory},{'callback':'translateTemplate','extension':'store_prodlist',jqObj:$templateCopy,'verb':'translate'},'mutable'); + } //Go get ALL the data and render it at the end. Less optimal from a 'we have it in memory already' point of view, but solves a plethora of other problems. for(var i = 0; i < L; i += 1) { - numRequests += app.calls.appProductGet.init({ - "pid":pageCSV[i], - "withVariations":plObj.withVariations, - "withInventory":plObj.withInventory - },{},'mutable'); + numRequests += handleProd(pageCSV[i],$template.clone(true).appendTo($tag)) if(plObj.withReviews) { - numRequests += app.ext.store_prodlist.calls.appReviewsList.init(pageCSV[i],{},'mutable'); + numRequests += _app.ext.store_prodlist.calls.appReviewsList.init(pageCSV[i],{},'mutable'); } } - + var infiniteCallback = function(rd) { + $('.loadingBG',$tag).removeClass('loadingBG'); $tag.data('isDispatching',false); //toggle T/F as a dispatch occurs so that only 1 infinite scroll dispatch occurs at a time. - if(app.model.responseHasErrors(rd)){ + if(_app.model.responseHasErrors(rd)){ $tag.parent().anymessage({'message':rd}); } else { - for(var i = 0; i < L; i += 1) { -// *** 201330 Uses $placeholders and the new insertProduct function to simulate aynchronous callback and preserve product order -// while inserting products. Before, if more appProductGet's were sent than could fit into a single pipeline, if the pipelined -// request that held the "ping" with the infiniteCallback returned before another, the app.data["appProductGet|"...] would return -// undefined and the callback would fail mid-append. - var $placeholder = $('<span />'); - $tag.append($placeholder); - app.ext.prodlist_infinite.u.insertProduct(pageCSV[i], plObj, $placeholder); - } - app.ext.prodlist_infinite.u.handleScroll($tag); + _app.ext.prodlist_infinite.u.handleScroll($tag); } } @@ -192,32 +181,33 @@ It is run once, executed by the renderFormat. infiniteCallback({}) } else { - app.calls.ping.init({'callback':infiniteCallback},'mutable'); - app.model.dispatchThis(); + _app.calls.ping.init({'callback':infiniteCallback},'mutable'); + _app.model.dispatchThis(); } }, // *** 201330 The new insertProduct function re-attempts the append a reasonable number of times // before failing with a warning to the console. insertProduct : function(pid, plObj, $placeholder, attempts){ - var data = app.data['appProductGet|'+pid]; + var data = _app.data['appProductGet|'+pid]; attempts = attempts || 0; if(data){ - if(typeof app.data['appReviewsList|'+pid] == 'object' && app.data['appReviewsList|'+pid]['@reviews'].length) { - data['reviews'] = app.ext.store_prodlist.u.summarizeReviews(pid); //generates a summary object (total, average) - data['reviews']['@reviews'] = app.data['appReviewsList|'+pid]['@reviews'] + if(typeof _app.data['appReviewsList|'+pid] == 'object' && _app.data['appReviewsList|'+pid]['@reviews'].length) { + data['reviews'] = _app.ext.store_prodlist.u.summarizeReviews(pid); //generates a summary object (total, average) + data['reviews']['@reviews'] = _app.data['appReviewsList|'+pid]['@reviews'] } - //if you want this list inventory aware, do you check here and skip the append below. - $placeholder.before(app.renderFunctions.transmogrify({'pid':pid},plObj.loadsTemplate,data)); +//if you want this list inventory aware, do you check here and skip the append below. +// $placeholder.before(_app.renderFunctions.transmogrify({'pid':pid},plObj.loadsTemplate,data)); + $placeholder.before(new tlc().getTemplateInstance(plObj.loadsTemplate).attr('data-pid',pid)) $placeholder.remove(); } else if(attempts < 50){ setTimeout(function(){ - app.ext.prodlist_infinite.u.insertProduct(pid, plObj, $placeholder, attempts+1); + _app.ext.prodlist_infinite.u.insertProduct(pid, plObj, $placeholder, attempts+1); }, 250); } else { - app.u.dump("-> prodlist_infinite FAILED TO INSERT PRODUCT: "+pid) + _app.u.dump("-> prodlist_infinite FAILED TO INSERT PRODUCT: "+pid) $placeholder.remove(); } }, @@ -237,7 +227,7 @@ else { else { plObj.prodlist.page_in_focus += 1; $tag.data('prodlist',plObj.prodlist); - app.ext.prodlist_infinite.u.addProductToPage($tag); + _app.ext.prodlist_infinite.u.addProductToPage($tag); } } }); diff --git a/extensions/sample.js b/extensions/sample.js index 6cfd09f68..c0f761779 100644 --- a/extensions/sample.js +++ b/extensions/sample.js @@ -20,7 +20,7 @@ // !!! -> TODO: replace 'username' in the line below with the merchants username. <- !!! -var store_username = function() { +var store_username = function(_app) { var theseTemplates = new Array(''); var r = { @@ -43,7 +43,7 @@ var store_username = function() { onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); } } }, //callbacks diff --git a/extensions/store_cart.js b/extensions/store_cart.js index fdc59a218..2b00e3b25 100755 --- a/extensions/store_cart.js +++ b/extensions/store_cart.js @@ -266,7 +266,6 @@ formerly showCart else if(data.value.asm_master) {$tag.remove()} else { $tag.attr({'data-stid':data.value.stid}).val(0); //val is used for the updateCartQty -$tag.button({icons: {primary: "ui-icon-closethick"},text: false}); //the click event handles all the requests needed, including updating the totals panel and removing the stid from the dom. $tag.one('click',function(event){ event.preventDefault(); @@ -390,7 +389,7 @@ either templateID needs to be set OR showloading must be true. TemplateID will t else { $modal = $("<div \/>").attr({"id":"modalCart","title":"Your Shopping Cart"}).appendTo('body'); $modal.append("<div id='cartMessaging' class='appMessaging'><\/div><div id='modalCartContents'><\/div>"); - $modal.dialog({modal: true,width:'80%',height:$(window).height() - 200}); //browser doesn't like percentage for height + $modal.dialog({modal: true,width:'80%',height:$(window).height() - 75}); //browser doesn't like percentage for height } if(P.showLoading === true) { diff --git a/extensions/store_crm.js b/extensions/store_crm.js index 0698526fa..1633487cb 100755 --- a/extensions/store_crm.js +++ b/extensions/store_crm.js @@ -23,11 +23,11 @@ well as info about the shopper (who they're logged in as, where they are [based for the 'lists' calls, no default callbacks are present. If something generic enough to be useful comes to mind later, I'll add them. In the meantime, define the callback in your extension, -tailored to your app. +tailored to your _app. */ -var store_crm = function() { +var store_crm = function(_app) { var r = { vars : {}, @@ -44,17 +44,17 @@ var store_crm = function() { var r = 0; tagObj = $.isEmptyObject(tagObj) ? {} : tagObj; tagObj.datapointer = "appFAQs" - if(app.model.fetchData('appFAQs') == false) { + if(_app.model.fetchData('appFAQs') == false) { r = 1; this.dispatch(tagObj); } else { - app.u.handleCallback(tagObj); + _app.u.handleCallback(tagObj); } return r; }, dispatch : function(tagObj) { - app.model.addDispatchToQ({"_cmd":"appFAQs","method":"all","_tag" : tagObj}); + _app.model.addDispatchToQ({"_cmd":"appFAQs","method":"all","_tag" : tagObj}); } },//appFAQsTopics @@ -82,7 +82,7 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore return 1; }, dispatch : function(cmdObj) { - app.model.addDispatchToQ(cmdObj,'immutable'); + _app.model.addDispatchToQ(cmdObj,'immutable'); } },//buyerOrderMacro @@ -99,24 +99,10 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore obj['softauth'] = "order"; obj["_tag"] = tagObj; obj["_tag"]["datapointer"] = "buyerOrderGet|"+obj.orderid; - app.model.addDispatchToQ(obj,Q); + _app.model.addDispatchToQ(obj,Q); } }, //buyerOrderGet - setNewsletters : { - init : function(obj,tagObj) { - app.u.dump("BEGIN store_crm.calls.setNewsletters.init"); - var r = 1; - this.dispatch(obj,tagObj); - return r; - }, - dispatch : function(obj,tagObj) { - obj['_tag'] = tagObj; - obj['_cmd'] = "setNewsletters"; - app.model.addDispatchToQ(obj); - } - }, //setNewsletters - buyerAddressList : { init : function(tagObj,Q) { tagObj = $.isEmptyObject(tagObj) ? {} : tagObj; @@ -125,7 +111,7 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore return 1; }, dispatch : function(tagObj,Q) { - app.model.addDispatchToQ({"_cmd":"buyerAddressList","_tag": tagObj},Q); + _app.model.addDispatchToQ({"_cmd":"buyerAddressList","_tag": tagObj},Q); } } //buyerAddressList }, //calls @@ -152,12 +138,12 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore //callbacks.init need to return either a true or a false, depending on whether or not the file will execute properly based on store account configuration. init : { onSuccess : function() { -// app.u.dump('BEGIN app.ext.store_crm.init.onSuccess '); +// _app.u.dump('BEGIN _app.ext.store_crm.init.onSuccess '); return true; //currently, no system or config requirements to use this extension -// app.u.dump('END app.ext.store_crm.init.onSuccess'); +// _app.u.dump('END _app.ext.store_crm.init.onSuccess'); }, onError : function(d) { - app.u.dump('BEGIN app.ext.store_crm.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_crm.callbacks.init.onError'); } }, @@ -168,14 +154,16 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore // ** 201336 This prevents FAQ's from being re-appended in the event the user revisits the FAQ page if(!$parent.data('faqs-rendered')){ $parent.removeClass('loadingBG'); - var L = app.data[tagObj.datapointer]['@topics'].length; - app.u.dump(" -> L = "+L); + var L = _app.data[tagObj.datapointer]['@topics'].length; + _app.u.dump(" -> L = "+L); var topicID; if(L > 0) { for(var i = 0; i < L; i += 1) { - topicID = app.data[tagObj.datapointer]['@topics'][i]['TOPIC_ID'] - app.u.dump(" -> TOPIC ID = "+topicID); - $parent.append(app.renderFunctions.transmogrify({'id':topicID,'data-topicid':topicID},tagObj.templateID,app.data[tagObj.datapointer]['@topics'][i])) + topicID = _app.data[tagObj.datapointer]['@topics'][i]['TOPIC_ID'] +// _app.u.dump(" -> TOPIC ID = "+topicID); +// ** 201403 -> transmogrify is data-bind, so this didn't work. +// $parent.append(_app.renderFunctions.transmogrify({'id':topicID,'topicid':topicID},tagObj.templateID,_app.data[tagObj.datapointer]['@topics'][i])) + $parent.tlc({'templateid':tagObj.templateID,'dataset':_app.data[tagObj.datapointer]['@topics'][i],'dataAttribs':{'topicid':topicID}}); } } else { @@ -191,13 +179,13 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore onSuccess : function(tagObj) { var $parent = $('#'+tagObj.parentID); var orderid; - var L = app.data[tagObj.datapointer]['@orders'].length; + var L = _app.data[tagObj.datapointer]['@orders'].length; if(L > 0) { $parent.empty(); for(var i = 0; i < L; i += 1) { - orderid = app.data[tagObj.datapointer]['@orders'][i].ORDERID; - $parent.append(app.renderFunctions.createTemplateInstance(tagObj.templateID,"order_"+orderid)); - app.renderFunctions.translateTemplate(app.data[tagObj.datapointer]['@orders'][i],"order_"+orderid); + orderid = _app.data[tagObj.datapointer]['@orders'][i].ORDERID; + $parent.append(_app.renderFunctions.createTemplateInstance(tagObj.templateID,"order_"+orderid)); + _app.renderFunctions.translateTemplate(_app.data[tagObj.datapointer]['@orders'][i],"order_"+orderid); } } else { @@ -209,10 +197,10 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore showSubscribeForm : { onSuccess : function(tagObj) { -// app.u.dump('BEGIN app.ext.store_crm.showSubscribeForm.onSuccess '); +// _app.u.dump('BEGIN _app.ext.store_crm.showSubscribeForm.onSuccess '); var $parent = $('#'+tagObj.parentID); - $parent.append(app.renderFunctions.createTemplateInstance(tagObj.templateID,"subscribeFormContainer")); - app.renderFunctions.translateTemplate(app.data[tagObj.datapointer],"subscribeFormContainer"); + $parent.append(_app.renderFunctions.createTemplateInstance(tagObj.templateID,"subscribeFormContainer")); + _app.renderFunctions.translateTemplate(_app.data[tagObj.datapointer],"subscribeFormContainer"); } }, //showSubscribeForm @@ -235,7 +223,7 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore validate : { addReview : function(obj) { -// app.u.dump(obj); +// _app.u.dump(obj); var errors = ''; if(!obj.SUBJECT) errors += 'please enter a subject.<br \/>'; @@ -248,48 +236,42 @@ obj['softauth'] = "order"; // [OPTIONAL]. if user is logged in, this gets ignore return true; else return errors; - }, - - changePassword : function(obj) { -// app.u.dump(obj); - var valid = true; - if(obj.password == ''){valid = false} - if(obj.password != obj.password2) {valid = false} - return valid; } }, //validate + tlcFormats : { + + buyersubscribe : function(data,thisTLC) { + dump(" -> data.globals.id: "+data.globals.binds.id); + if(_app.u.thisNestedExists("data.buyerDetail.%info.@TAGS",_app)) { + if($.inArray(data.globals.binds.id,_app.data.buyerDetail['%info']['@TAGS']) >= 0) { + dump(" -> MATCH!"); + data.globals.binds[data.globals.focusBind] = 'checked'; + } + } + return true; + } + }, - renderFormats : { -//Displays a list of the merchants newsletters. - subscribeCheckboxes : function($tag,data) { -// app.u.dump('BEGIN app.ext.store_prodlist.renderFormats.mpPagesAsListItems'); -// app.u.dump(data); - var o = ""; - for(var index in data.value) { - o += "<div class='subscribeListItem'><label title='"+data.value[index].EXEC_SUMMARY+"'>"; - o += "<input type='checkbox' checked='checked' name='newsletter-"+data.value[index].ID+"' \/>"; - o += data.value[index].NAME+"<\/label><\/div>"; - } - $tag.append(o); - - }, + renderFormats : { - orderTrackingLinks : function($tag,data) { - app.u.dump("BEGIN myRIA.renderFormats.orderTrackingLinks"); - app.u.dump(data.value); - - var L = data.value.length; - var o = ''; //what is appended to tag. a compiled list of shipping lineitems. - for(var i = 0; i < L; i += 1) { - o += "<li><a href='"+app.ext.myRIA.u.getTrackingURL(data.value[i].carrier,data.value[i].track)+"' target='"+data.value[i].carrier+"'>"+data.value[i].track+"</a>"; - if(app.u.isSet(data.value[i].cost)) - o += " ("+app.u.formatMoney(data.value[i].cost,'$',2,true)+")"; - o += "<\/li>"; + ordertrackinglinks : function($tag,data) { +// _app.u.dump("BEGIN quickstart.renderFormats.ordertrackinglinks"); +// _app.u.dump(data.value); + if(data.value) { + var L = data.value.length; + var o = ''; //what is appended to tag. a compiled list of shipping lineitems. + for(var i = 0; i < L; i += 1) { + // ### TODO -> need to get the link to quickstart out of here. + o += "<li><a href='"+_app.ext.quickstart.u.getTrackingURL(data.value[i].carrier,data.value[i].track)+"' target='"+data.value[i].carrier+"'>"+data.value[i].track+"</a>"; + if(_app.u.isSet(data.value[i].cost)) + o += " ("+_app.u.formatMoney(data.value[i].cost,'$',2,true)+")"; + o += "<\/li>"; + } + $tag.show().append("<h4>Tracking Number(s):</h4>").append(o); } - $tag.show().append("<h4>Tracking Number(s):</h4>").append(o); } }, @@ -308,63 +290,47 @@ if the P.pid and data-pid do not match, empty the modal before openeing/populati */ showReviewFrmInModal : function(P) { if(!P.pid || !P.templateID) { - app.u.dump(" -> pid or template id left blank"); + _app.u.dump(" -> pid or template id left blank"); } else { var $parent = $('#review-modal'); //if no review modal has been created before, create one. if($parent.length == 0) { - app.u.dump(" -> modal window doesn't exist. create it."); $parent = $("<div \/>").attr({"id":"review-modal",'data-pid':P.pid}).appendTo(document.body); } else { - app.u.dump(" -> use existing modal. empty it."); //this is a new product being displayed in the viewer. $parent.empty(); } $parent.dialog({modal: true,width: ($(window).width() > 500) ? 500 : '90%',height:500,autoOpen:false,"title":"Write a review for "+P.pid}); //the only data needed in the reviews form is the pid. //the entire product record isn't passed in because it may not be available (such as in invoice or order history, or a third party site). - $parent.dialog('open').append(app.renderFunctions.transmogrify({id:'review-modal_'+P.pid},P.templateID,{'pid':P.pid})); +// $parent.dialog('open').append(_app.renderFunctions.transmogrify({id:'review-modal_'+P.pid},P.templateID,{'pid':P.pid})); + $parent.tlc({'templateid' : P.templateID,'dataset' : {'pid':P.pid}}); + $parent.dialog('open'); + _app.u.handleButtons($parent); + _app.u.addEventDelegation($parent); //1PC doesn't have delegation on the body. } }, - handleReviews : function(formID) { - var - $form = $('#'+formID), - frmObj = $form.serializeJSON(); - - $('.zMessage',$form).empty().remove(); //clear any existing error messages. - var isValid = app.ext.store_crm.validate.addReview(frmObj); //returns true or some errors. - if(isValid === true) { - app.calls.appReviewAdd.init(frmObj,{ - "callback":"showMessaging", - "jqObj":$form, - "jqObjEmpty" : true, - "message":"Thank you for your review. Pending approval, it will be added to the store."},'immutable'); - app.model.dispatchThis('immutable'); - } - else { - //report errors. - var errObj = app.u.youErrObject(isValid,'42'); - errObj.parentID = formID - app.u.throwMessage(errObj); - } - }, /* will output a newsletter form into 'parentid' using 'templateid'. */ showSubscribe : function(P) { if(!P.targetID && !P.templateID) { - app.u.dump("for crm_store.u.showSubscribe, both targetID and templateID are required"); + _app.u.dump("for crm_store.u.showSubscribe, both targetID and templateID are required"); } else { -// $('#'+P.parentID); //if a loadingBG class is needed, add it outside this function. -// ### modify this so callback and extension can be passed in, but are defaulted if none. -//in this case, the template is not populated until the call comes back. otherwise, the form would show up but no subscribe list. - if(app.calls.appNewsletterList.init({"parentID":P.parentID,"templateID":P.templateID,"callback":"showSubscribeForm","extension":"store_crm"})) {app.model.dispatchThis()} + var _tag = {"parentID":P.parentID,"templateID":P.templateID,"callback":"showSubscribeForm","extension":"store_crm","datapointer":"appNewsletterList"} + if(app.data.appNewsletterList) { + _app.u.handleCallback(_tag); + } + else { + _app.model.addDispatchToQ({"_cmd":"appNewsletterList","_tag" : _tag},'mutable'); + _app.model.dispatchThis('mutable') + } } }, @@ -382,33 +348,22 @@ will output a newsletter form into 'parentid' using 'templateid'. } else { url = false; //unrecognized ship carrier. - app.u.dump("WARNING: unrecognized ship carrier ["+carrier+"] for parcel: "+tracknum); + _app.u.dump("WARNING: unrecognized ship carrier ["+carrier+"] for parcel: "+tracknum); } return url; }, getAllBuyerListsDetails : function(datapointer,tagObj) { -var data = app.data[datapointer]['@lists']; //shortcut -var L = data.length; -var numRequests = 0; -for(var i = 0; i < L; i += 1) { - numRequests += app.calls.buyerProductListDetail.init(data[i].id,tagObj) - } -return numRequests; + var data = _app.data[datapointer]['@lists']; //shortcut + var L = data.length; + var numRequests = 0; + for(var i = 0; i < L; i += 1) { + numRequests += _app.calls.buyerProductListDetail.init(data[i].id,tagObj) + } + return numRequests; }, - getBuyerListsAsUL : function(datapointer) { - -var data = app.data[datapointer]['@lists']; //shortcut -var L = data.length; -var $r = $("<ul>"); -var $li; //recycled -for(var i = 0; i < L; i += 1) { - $li = $("<li\/>").data("buyerlistid",data[i].id).text(data[i].id+" ("+data[i].items+" items)"); - $li.appendTo($r); - } -return $r; - }, + /* The list object returned on a buyerProductListDetail is not a csv or even a string of skus, it's an array of objects, each object containing information @@ -417,48 +372,51 @@ This is used to get add an array of skus, most likely for a product list. */ getSkusFromBuyerList : function(listID) { - app.u.dump("BEGIN store_crm.u.getSkusFromList ("+listID+")"); - var L = app.data['buyerProductListDetail|'+listID]['@'+listID].length; + _app.u.dump("BEGIN store_crm.u.getSkusFromList ("+listID+")"); + var L = _app.data['buyerProductListDetail|'+listID]['@'+listID].length; var csvArray = new Array(); //array of skus. What is returned. for(var i = 0; i < L; i+=1) { - csvArray.push(app.data['buyerProductListDetail|'+listID]['@'+listID][i].SKU); + csvArray.push(_app.data['buyerProductListDetail|'+listID]['@'+listID][i].SKU); } csvArray = $.grep(csvArray,function(n){return(n);}); //remove blanks return csvArray; }, //getSkusFromList handleChangePassword : function($form,tagObj) { - -$('.messaging', $form).empty(); //clear any existing messaging -var formObj = $form.serializeJSON(); -if(app.ext.store_crm.validate.changePassword(formObj)){ - app.calls.buyerPasswordUpdate.init(formObj.password,tagObj); - app.model.dispatchThis('immutable'); - } -else{ - var errObj = app.u.youErrObject("The two passwords do not match.",'42'); - $(".messaging",$form).anymessage(errObj); - } + var formObj = $form.serializeJSON(); + if(formObj.password && formObj.password == formObj.password2) { + _app.model.addDispatchToQ({"_cmd":"buyerPasswordUpdate","password":formObj.password,"_tag":tagObj},"immutable"); + _app.model.dispatchThis('immutable'); + } + else{ + $form.anymessage({"message":"The two passwords do not match.","errtype":"youerr"}); + } }, //handleChangePassword handleSubscribe : function($form) { -// app.u.dump("BEGIN store_crm.u.handleSubscribe"); +// _app.u.dump("BEGIN store_crm.u.handleSubscribe"); if($form) { -// app.u.dump(" -> $form is set."); - frmObj = $form.serializeJSON(); - if(app.u.validateForm($form)) { -// app.u.dump(" -> $form validated."); - app.ext.store_crm.calls.setNewsletters.init(frmObj,{'callback':function(rd){ - if(app.model.responseHasErrors(rd)){ - $form.anymessage({'message':rd}); - } - else { - $form.anymessage(app.u.successMsgObject("Thank you, you are now subscribed.")); +// _app.u.dump(" -> $form is set."); + var sfo = $form.serializeJSON(); + if(_app.u.validateForm($form)) { +// _app.u.dump(" -> $form validated."); + sfo._cmd = 'appBuyerCreate'; + sfo._tag = { + "datapointer":"appBuyerCreate", + "callback":function(rd){ + if(_app.model.responseHasErrors(rd)){ + $form.anymessage({'message':rd}); + } + else { +//* 201404 -> to customize the 'success' message, add a hidden input w/ name of 'message' and set the value to what you want displayed. + $form.anymessage(_app.u.successMsgObject(sfo.message || "Thank you, you are now subscribed.")); + } } - }}); - app.model.dispatchThis(); + }; + _app.model.addDispatchToQ(sfo,"immutable"); + _app.model.dispatchThis('immutable'); } else {} } @@ -472,12 +430,12 @@ else{ var r = false; //what is returned. true if editor is displayed, false if an error occured. if(typeof vars === 'object' && vars.addressID && vars.addressType) { - var addressData = app.ext.cco.u.getAddrObjByID(vars.addressType,vars.addressID); - app.u.dump(addressData); + var addressData = _app.ext.cco.u.getAddrObjByID(vars.addressType,vars.addressID); + if(addressData) { r = true; var $editor = $("<div \/>"); - $editor.anycontent({'templateID':(vars.addressType == 'ship') ? 'chkoutAddressShipTemplate' : 'chkoutAddressBillTemplate','data':addressData}); + $editor.tlc({'templateid':(vars.addressType == 'ship') ? 'chkoutAddressShipTemplate' : 'chkoutAddressBillTemplate','dataset':addressData}); $editor.append("<input type='hidden' name='shortcut' value='"+vars.addressID+"' \/>"); $editor.append("<input type='hidden' name='type' value='"+vars.addressType+"' \/>"); if(vars.addressType == 'bill') { @@ -498,29 +456,34 @@ else{ 'save' : function(event,ui) { event.preventDefault(); var $form = $('form',$(this)).first(); - - if(app.u.validateForm($form)) { - $('body').showLoading('Updating Address'); - var serializedForm = $form.serializeJSON(); -//save and then refresh the page to show updated info. - app.calls.buyerAddressAddUpdate.init(serializedForm,{'callback':function(rd){ - $('body').hideLoading(); //always hide loading, regardless of errors. - if(app.model.responseHasErrors(rd)){ - $form.anymessage({'message':rd}); - } - else if(typeof onSuccessCallback === 'function') { - onSuccessCallback(rd,serializedForm); - $editor.dialog('close'); + var $editor = $(this); + if(_app.u.validateForm($form)) { + $form.showLoading('Updating Address'); + var sfo = $form.serializeJSON(); + sfo._cmd = 'buyerAddressAddUpdate', + sfo._tag = { + 'callback':function(rd){ + $form.hideLoading(); //always hide loading, regardless of errors. + if(_app.model.responseHasErrors(rd)){ + $form.anymessage({'message':rd}); + } + else if(typeof onSuccessCallback === 'function') { + $editor.dialog('close'); + onSuccessCallback(rd,sfo); + } + else { + //no callback defined + $editor.dialog('close'); + } + } } - else { - //no callback defined - $editor.dialog('close'); - } - }},'immutable'); + +//save and then refresh the page to show updated info. + _app.model.addDispatchToQ(sfo,'immutable'); //dump data in memory and local storage. get new copy up updated address list for display. - app.model.destroy('buyerAddressList'); - app.calls.buyerAddressList.init({},'immutable'); - app.model.dispatchThis('immutable'); + _app.model.destroy('buyerAddressList'); + _app.calls.buyerAddressList.init({},'immutable'); + _app.model.dispatchThis('immutable'); } else {} //errors handled in validateForm @@ -530,7 +493,7 @@ else{ }); //* 201342 -> used in checkout (or potentailly any editor) to immediately highlight any invalid fields (useful in 'edit' as opposed to 'create' address) if(vars.validateForm) { - app.u.validateForm($editor); + _app.u.validateForm($editor); } @@ -555,15 +518,17 @@ else{ var $editor = $("<div \/>"); $editor.append("<input type='hidden' name='type' value='"+vars.addressType.toUpperCase()+"' \/>"); - $editor.anycontent({'templateID':(vars.addressType == 'ship') ? 'chkoutAddressShipTemplate' : 'chkoutAddressBillTemplate','data':{},'showLoading':false}); -//* 201338 -> the address id should be at the bottom of the form, not the top. isn't that important or required. - $editor.append("<input type='text' maxlength='6' data-minlength='6' name='shortcut' placeholder='address id (6 characters)' \/>"); +// ** 201403 -> need to pass in a blank dataset so translation occurs. required for country dropdown. + $editor.tlc({'templateid':(vars.addressType == 'ship') ? 'chkoutAddressShipTemplate' : 'chkoutAddressBillTemplate','dataset':{}}); +//the address id should be at the bottom of the form, not the top. isn't that important or required. + $editor.append("<input type='text' maxlength='6' data-minlength='6' name='shortcut' placeholder='address id (6 characters)' \/> <span class='hint'>A shortcut to identify this address (ex: office, myhome, etc)"); $editor.wrapInner('<form \/>'); //needs this for serializeJSON later. -//** 201338 -> if the placeholder attribute on an input is not supported (thx IE8), then add labels. - if(app.ext.orderCreate) { - app.ext.orderCreate.u.handlePlaceholder($editor); +//if the placeholder attribute on an input is not supported (thx IE8), then add labels. + if(_app.ext.order_create) { + _app.ext.order_create.u.handlePlaceholder($editor); } +//adds a tooltip which is displayed on focus. lets the user know what field they're working on once they start typing and placeholder goes away. $(":input",$editor).each(function(index){ var $input = $(this); if($input.attr('placeholder') && !$input.attr('title')) { @@ -595,28 +560,34 @@ else{ event.preventDefault(); var $form = $('form',$(this)).first(); - if(app.u.validateForm($form)) { - $('body').showLoading('Adding Address'); - var serializedForm = $form.serializeJSON(); + if(_app.u.validateForm($form)) { + $form.showLoading('Adding Address'); + var sfo = $form.serializeJSON(); //save and then refresh the page to show updated info. - app.calls.buyerAddressAddUpdate.init(serializedForm,{'callback':function(rd){ - $('body').hideLoading(); //always hide loading, regardless of errors. - if(app.model.responseHasErrors(rd)){ - $form.anymessage({'message':rd}); - } - else if(typeof onSuccessCallback === 'function') { - onSuccessCallback(rd,serializedForm); - $editor.dialog('close'); - } - else { - //no callback defined or an error occured and has been reported. - $editor.dialog('close'); + _app.model.addDispatchToQ($.extend({},sfo,{ + '_cmd':'buyerAddressAddUpdate', + '_tag': { + 'callback':function(rd){ + $form.hideLoading(); //always hide loading, regardless of errors. + if(_app.model.responseHasErrors(rd)){ + $form.anymessage({'message':rd}); + } + else if(typeof onSuccessCallback === 'function') { + onSuccessCallback(rd,sfo); + $editor.dialog('close'); + } + else { + //no callback defined or an error occured and has been reported. + $editor.dialog('close'); + } + } } - }},'immutable'); + }),'mutable'); + _app.model.dispatchThis('mutable'); //dump data in memory and local storage. get new copy up updated address list for display. - app.model.destroy('buyerAddressList'); - app.calls.buyerAddressList.init({},'immutable'); - app.model.dispatchThis('immutable'); + _app.model.destroy('buyerAddressList'); + _app.calls.buyerAddressList.init({},'immutable'); + _app.model.dispatchThis('immutable'); } else {} //errors handled in validateForm @@ -636,19 +607,116 @@ else{ e : { + //generic event, inteded to support more than tags through the use of the data-update-verb= + buyerUpdate : function($ele,p) { + p.preventDefault(); + if(_app.u.validateForm($ele)) { + var cmdObj = { + "_cmd":"buyerUpdate", + "@updates" : [], + "cartid" : _app.model.fetchCartID(), + "_tag":{ + "datapointer":"", + "callback":function(rd){} + } + } + + $("[data-update-verb='tags']",$ele).find(":checkbox").each(function(){ + var $cb = $(this); + cmdObj['@updates'].push(($cb.is(':checked') ? 'TAG-ADD' : 'TAG-CLEAR')+"?TAG="+$cb.attr('name')); + }); + + + _app.model.addDispatchToQ(cmdObj,"mutable"); + _app.model.dispatchThis("mutable"); + } + else {} //validateForm handles error display. + return false; + }, - showWriteReview : function($btn) { - $btn.button(); - $btn.off('click.showWriteReview').on('click.showWriteReview',function(event){ - event.preventDefault(); - var pid = $btn.attr("data-pid") || $btn.closest("[data-stid]").data('stid'); - if(pid) { - app.ext.store_crm.u.showReviewFrmInModal({"pid":pid,"templateID":"reviewFrmTemplate"}); + contactFormSubmit : function($ele,p) { + p.preventDefault(); + dump(" -> BEGIN store_crm.e.contactFormSubmit"); + if(_app.u.validateForm($ele)) { + var sfo = $ele.serializeJSON(); + sfo._cmd = "appSendMessage"; + sfo._tag = { + 'callback':'showMessaging', + 'jqObj':$ele, + 'message':'Thank you, your message has been sent' + }; + _app.model.addDispatchToQ(sfo,"immutable"); + _app.model.dispatchThis('immutable'); + } + else { + dump(" -> did not pass validation."); + } //validateForm handles error display. + return false; + }, + + productBuyerListRemoveExec : function($ele,p) { + p.preventDefault(); + var pid = $ele.closest("[data-stid]").data('stid') || $ele.closest("[data-pid]").data('pid'); + var listid = $ele.closest("[data-buyerlistid]").data('buyerlistid'); + if(pid && listid) { + _app.u.dump(" -> templateRole.length: "+$ele.closest("[data-template-role='listitem']").length); + _app.model.addDispatchToQ({ + '_cmd':'buyerProductListRemoveFrom', + 'listid' : listid, + 'sku' : pid, + '_tag': { + 'callback':'showMessaging', + 'message' : 'Item '+pid+' has been removed from list: '+listid, + 'jqObjEmpty' : true, + 'jqObj' : $ele.closest("[data-template-role='listitem']") + } + },'immutable'); + _app.model.destroy("buyerProductListDetail|"+listid); //destroy the list in memory so the next time we visit the list page, a new copy is fetched. + _app.model.dispatchThis('immutable'); + window[_app.vars.analyticsPointer]('send','event','Manage buyer list','User Event','item removed'); + } + else { + $('#globalMessaging').anymessage({"message":"In store_crm.e.productByerListRemoveExec, either unable to ascertain pid ["+pid+"] and/or buyerlistid ["+listid+"].","gMessage":true}); + } + return false; + }, + + //add this as submit action on the form. + productReviewSubmit : function($ele,p) { + p.preventDefault(); + var $form = $ele.closest('form'); //this way, $ele can be a button within the form or an onSubmit action on the form itself. + if(_app.u.validateForm($form)) { + var sfo = $form.serializeJSON(); + if(sfo.pid) { + sfo._cmd = "appReviewAdd"; + sfo._tag = { + "callback":"showMessaging", + "jqObj":$form, + "jqObjEmpty" : true, + "message":"Thank you for your review. Pending approval, it will be added to the store." + } + _app.model.addDispatchToQ(sfo,"immutable"); + _app.model.dispatchThis('immutable'); } else { - $('#globalMessaging').anymessage({'message':'In store_crm.e.showWriteReview, unable to determine pid/stid','gMessage':true}); + $ele.anymessage({"message":"In productReviewSubmit, validation not passed because no pid was found in the form.","gMessage":true}); } - }) + } + else {} //validateForm will handle error display. + return false; + }, + + productReviewShow : function($ele,p) { + p.preventDefault(); + + var pid = $ele.data('pid') || $ele.closest("[data-pid]").data('pid'); //used on product page + if(pid) { + _app.ext.store_crm.u.showReviewFrmInModal({"pid":pid,"templateID":"reviewFrmTemplate"}); + } + else { + $('#globalMessaging').anymessage({'message':'In store_crm.e.productReviewShow, unable to determine pid/stid','gMessage':true}); + } + return false; } } //e/events diff --git a/extensions/store_navcats.js b/extensions/store_navcats.js index 489efa38c..b11ad7486 100755 --- a/extensions/store_navcats.js +++ b/extensions/store_navcats.js @@ -22,7 +22,7 @@ The functions here are designed to work with 'reasonable' size lists of categori */ -var store_navcats = function() { +var store_navcats = function(_app) { var r = { vars : {}, @@ -33,27 +33,31 @@ var store_navcats = function() { calls : { //formerly categoryTree appCategoryList : { - init : function(root,tagObj,Q) { -// app.u.dump("BEGIN store_navcats.calls.appCategoryList.init"); + init : function(root,_tag,Q) { +// _app.u.dump("BEGIN store_navcats.calls.appCategoryList.init w/ root: "+root); var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. - if(app.model.fetchData('appCategoryList') == false) { - r = 1; - this.dispatch(root,tagObj,Q); + if(root) { + _tag = _tag || {}; + _tag.datapointer = _tag.datapointer || 'appCategoryList|'+root; + if(_app.model.fetchData(_tag.datapointer)) { + _app.u.handleCallback(_tag) + } + else { + r = 1; + this.dispatch(root,_tag,Q); + } } - else { - app.u.handleCallback(tagObj) + else { + $('#globalMessaging').anymessage({"message":"In store_navcats.calls.appCategoryList, root was not passed and is required.","gMessage":true}); } return r; }, - dispatch : function(root,tagObj,Q) { + dispatch : function(root,_tag,Q) { var obj = {}; obj['_cmd'] = "appCategoryList"; obj.root = root; - obj['_tag'] = typeof tagObj == 'object' ? tagObj : {}; - obj['_tag'].datapointer = 'appCategoryList'; //for now, override datapointer for consistency's sake. -//if no extension is set, use this one. need to b able to override so that a callback from outside the extension can be added. - obj['_tag'].extension = obj['_tag'].extension ? obj['_tag'].extension : 'store_navcats'; - app.model.addDispatchToQ(obj,Q); + obj._tag = _tag; + _app.model.addDispatchToQ(obj,Q); } }, //appCategoryList @@ -66,19 +70,19 @@ obj.PATH = .cat.safe.id */ appPageGet : { init : function(obj,tagObj,Q) { -// app.u.dump("BEGIN store_navcats.calls.appPageGet.init"); -// app.u.dump(" -> @get: "); app.u.dump(obj['@get']); +// _app.u.dump("BEGIN store_navcats.calls.appPageGet.init"); +// _app.u.dump(" -> @get: "); _app.u.dump(obj['@get']); obj['_tag'] = typeof tagObj == 'object' ? tagObj : {}; obj['_tag'].datapointer = 'appPageGet|'+obj.PATH; //no local storage of this. ### need to explore solutions. var r = 0; var hasAllLocal = true; - if(app.model.fetchData('appPageGet|'+obj.PATH) == false) { + if(_app.model.fetchData('appPageGet|'+obj.PATH) == false) { hasAllLocal = false; } - else if(app.data['appPageGet|'+obj.PATH] && app.data['appPageGet|'+obj.PATH]['%page']) { + else if(_app.data['appPageGet|'+obj.PATH] && _app.data['appPageGet|'+obj.PATH]['%page']) { var L = obj['@get'].length; for(var i = 0; i < L; i += 1) { - if(!app.data['appPageGet|'+obj.PATH]['%page'][obj['@get'][i]]) { + if(!_app.data['appPageGet|'+obj.PATH]['%page'][obj['@get'][i]]) { hasAllLocal = false; break; //once we know 1 piece of data is missing, just get all of it. } @@ -88,7 +92,7 @@ obj.PATH = .cat.safe.id hasAllLocal = false; } if(hasAllLocal) { - app.u.handleCallback(tagObj); + _app.u.handleCallback(tagObj); } else { this.dispatch(obj,tagObj,Q); @@ -98,237 +102,37 @@ obj.PATH = .cat.safe.id }, dispatch : function(obj,tagObj,Q) { obj['_cmd'] = "appPageGet"; - app.model.addDispatchToQ(obj,Q); - } - }, //appPageGet -//formerly categoryDetail - appNavcatDetail : { - init : function(catSafeID,tagObj,Q) { - Q = Q || 'mutable'; -// app.u.dump('BEGIN app.ext.store_navcats.calls.appNavcatDetail.init ('+catSafeID+')'); - var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. - tagObj = typeof tagObj !== 'object' ? {} : tagObj; -//whether max, more or just detail, always save to same loc. -//add here so if tagObj is passed directly into callback because data is in localStorage, the datapointer is set. - tagObj.datapointer = 'appNavcatDetail|'+catSafeID; - if(app.model.fetchData(tagObj.datapointer) == false) { - r += 1; - this.dispatch(catSafeID,tagObj,Q); - } - else { -// app.u.dump(' -> using local'); - app.u.handleCallback(tagObj) - } - return r; - }, - dispatch : function(catSafeID,tagObj,Q) { -// app.u.dump('BEGIN app.ext.store_navcats.calls.appNavcatDetail.dispatch'); - var catSafeID; - app.model.addDispatchToQ({"_cmd":"appNavcatDetail","safe":catSafeID,"detail":"fast","_tag" : tagObj},Q); - } - },//appNavcatDetail - - appNavcatDetail : { - init : function(path,tagObj,Q) { - app.u.dump('BEGIN app.ext.store_navcats.calls.appNavcatDetail.init ('+path+')'); - Q = Q || 'mutable'; - var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. - tagObj = typeof tagObj !== 'object' ? {} : tagObj; -//whether max, more or just detail, always save to same loc. -//add here so if tagObj is passed directly into callback because data is in localStorage, the datapointer is set. - tagObj.datapointer = 'appNavcatDetail|'+path; - if(app.model.fetchData(tagObj.datapointer) == false) { - r += 1; - this.dispatch(path,tagObj,Q); - } - else { - // app.u.dump(' -> using local'); - app.u.handleCallback(tagObj) - } - return r; - }, - dispatch : function(path,tagObj,Q) { - // app.u.dump('BEGIN app.ext.store_navcats.calls.appNavcatDetail.dispatch'); - var path; - app.model.addDispatchToQ({"_cmd":"appNavcatDetail","path":path, "detail":"fast","_tag" : tagObj},Q); - } - },//appNavcatDetail - - appNavcatDetailMore : { - init : function(catSafeID,tagObj,Q) { - Q = Q || 'mutable'; -// app.u.dump('BEGIN app.ext.store_navcats.calls.appNavcatDetailMore.init'); - var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. - tagObj = typeof tagObj !== 'object' ? {} : tagObj; - tagObj.datapointer = 'appNavcatDetail|'+catSafeID; - if(app.model.fetchData(tagObj.datapointer) == false) { -//nothing is local. go get it. - this.dispatch(catSafeID,tagObj,Q); - r += 1; - } - else { -//something is in local. if max or more, use it. - if(app.data[tagObj.datapointer].detail == 'max' || app.data[tagObj.datapointer].detail == 'more') { - app.u.handleCallback(tagObj) - } - else { -//local is probably from a 'fast' request. go get more. - this.dispatch(catSafeID,tagObj,Q); - r += 1; - } - } - return r; - }, - dispatch : function(catSafeID,tagObj,Q) { - var catSafeID; - tagObj.datapointer = 'appNavcatDetail|'+catSafeID; //whether max, more or just detail, always save to same loc. - tagObj.detail = 'more'; //if detail is in tabObj, model will add it to data object. - app.model.addDispatchToQ({"_cmd":"appNavcatDetail","safe":catSafeID,"detail":"more","_tag" : tagObj},Q); - } - },//appNavcatDetailMore - - appNavcatDetailMore : { - init : function(catSafeID,tagObj,Q) { - Q = Q || 'mutable'; -// app.u.dump('BEGIN app.ext.store_navcats.calls.appNavcatDetailMore.init'); - var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. - tagObj = typeof tagObj !== 'object' ? {} : tagObj; - tagObj.datapointer = 'appNavcatDetail|'+catSafeID; - if(app.model.fetchData(tagObj.datapointer) == false) { -//nothing is local. go get it. - this.dispatch(catSafeID,tagObj,Q); - r += 1; - } - else { -//something is in local. if max or more, use it. - if(app.data[tagObj.datapointer].detail == 'max' || app.data[tagObj.datapointer].detail == 'more') { - app.u.handleCallback(tagObj) - } - else { -//local is probably from a 'fast' request. go get more. - this.dispatch(catSafeID,tagObj,Q); - r += 1; - } - } - return r; - }, - dispatch : function(catSafeID,tagObj,Q) { - var catSafeID; - tagObj.datapointer = 'appNavcatDetail|'+catSafeID; //whether max, more or just detail, always save to same loc. - tagObj.detail = 'more'; //if detail is in tabObj, model will add it to data object. - app.model.addDispatchToQ({"_cmd":"appNavcatDetail","path":catSafeID,"detail":"more","_tag" : tagObj},Q); - } - },//appNavcatDetailMore - - appNavcatDetailMax : { - init : function(catSafeID,tagObj,Q) { - Q = Q || 'mutable'; -// app.u.dump('BEGIN app.ext.store_navcats.calls.appNavcatDetailMax.init'); - var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. - tagObj = typeof tagObj !== 'object' ? {} : tagObj; -//whether max, more or just detail, always save to same loc. -//add here so if tagObj is passed directly into callback because data is in localStorage, the datapointer is set. - tagObj.datapointer = 'appNavcatDetail|'+catSafeID; -// app.u.dump(' -> datapointer = '+tagObj.datapointer); - - if(app.model.fetchData(tagObj.datapointer) == false) { -// app.u.dump(' -> data is not local. go get it.'); - r += 1; - this.dispatch(catSafeID,tagObj,Q); - } - else { - if(app.data[tagObj.datapointer].detail == 'max') { - app.u.handleCallback(tagObj); - } - else { - r += 1; - this.dispatch(catSafeID,tagObj,Q); - } - } - return r; - }, - dispatch : function(catSafeID,tagObj,Q) { -// app.u.dump(' -> safeid = '+catSafeID); -// app.u.dump(' -> executing dispatch.'); - tagObj.detail = 'max'; - app.model.addDispatchToQ({"_cmd":"appNavcatDetail","safe":catSafeID,"detail":"max","_tag" : tagObj},Q); + _app.model.addDispatchToQ(obj,Q); } - },//appNavcatDetailMax - - appNavcatDetailMax : { - init : function(catSafeID,tagObj,Q) { - Q = Q || 'mutable'; -// app.u.dump('BEGIN app.ext.store_navcats.calls.appNavcatDetailMax.init'); - var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. - tagObj = typeof tagObj !== 'object' ? {} : tagObj; -//whether max, more or just detail, always save to same loc. -//add here so if tagObj is passed directly into callback because data is in localStorage, the datapointer is set. - tagObj.datapointer = 'appNavcatDetail|'+catSafeID; -// app.u.dump(' -> datapointer = '+tagObj.datapointer); - - if(app.model.fetchData(tagObj.datapointer) == false) { -// app.u.dump(' -> data is not local. go get it.'); - r += 1; - this.dispatch(catSafeID,tagObj,Q); - } - else { - if(app.data[tagObj.datapointer].detail == 'max') { - app.u.handleCallback(tagObj); - } - else { - r += 1; - this.dispatch(catSafeID,tagObj,Q); - } - } - return r; - }, - dispatch : function(catSafeID,tagObj,Q) { -// app.u.dump(' -> safeid = '+catSafeID); -// app.u.dump(' -> executing dispatch.'); - tagObj.detail = 'max'; - app.model.addDispatchToQ({"_cmd":"appNavcatDetail","path":catSafeID,"detail":"max","_tag" : tagObj},Q); - } - }//appNavcatDetailMax - - - + } //appPageGet }, //calls - - - - - //////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ - - - - callbacks : { //callbacks.init need to return either a true or a false, depending on whether or not the file will execute properly based on store account configuration. init : { onSuccess : function() { -// app.u.dump('BEGIN app.ext.store_navcats.init.onSuccess '); +// _app.u.dump('BEGIN _app.ext.store_navcats.init.onSuccess '); return true; //currently, no system or config requirements to use this extension -// app.u.dump('END app.ext.store_navcats.init.onSuccess'); +// _app.u.dump('END _app.ext.store_navcats.init.onSuccess'); }, onError : function() { - app.u.dump('BEGIN app.ext.store_navcats.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_navcats.callbacks.init.onError'); } }, getRootCatsData : { onSuccess : function(tagObj) { -// app.u.dump("BEGIN app.ext.store_navcats.callbacks.handleProduct.onSuccess"); - app.ext.store_navcats.u.getRootCatsData(tagObj); +// _app.u.dump("BEGIN _app.ext.store_navcats.callbacks.handleProduct.onSuccess"); + _app.ext.store_navcats.u.getRootCatsData(tagObj); } }, /* @@ -339,21 +143,22 @@ in this case, the DOM element may not be necessary, and in those cases (hidden c params in addition to standard tagObj (datapointer, callback, etc). -templateID - the template id used (from app.templates) +templateID - the template id used (from _app.templates) */ addCatToDom : { onSuccess : function(tagObj) { -// app.u.dump("BEGIN app.ext.store_navcats.callbacks.addCatToDom.onSuccess"); -// app.u.dump(" -> datapointer = "+tagObj.datapointer); -// app.u.dump(" -> add data to template: "+tagObj.parentID+"_"+tagObj.datapointer.split('|')[1]); +// _app.u.dump("BEGIN _app.ext.store_navcats.callbacks.addCatToDom.onSuccess"); +// _app.u.dump(" -> datapointer = "+tagObj.datapointer); +// _app.u.dump(" -> add data to template: "+tagObj.parentID+"_"+tagObj.datapointer.split('|')[1]); //yes, actually have to make sure .pretty exists. no shit. this happeneed. errored cuz pretty wasn't set. - if(app.data[tagObj.datapointer].pretty && app.data[tagObj.datapointer].pretty.charAt(0) !== '!') { -// app.u.dump("store_navcats.callback.addCatToDom.onsuccess - Category ("+tagObj.datapointer+") is hidden."); - app.renderFunctions.translateTemplate(app.data[tagObj.datapointer],tagObj.parentID+"_"+tagObj.datapointer.split('|')[1]); + if(_app.data[tagObj.datapointer].pretty && _app.data[tagObj.datapointer].pretty.charAt(0) !== '!') { +// _app.u.dump("store_navcats.callback.addCatToDom.onsuccess - Category ("+tagObj.datapointer+") is hidden."); +// _app.renderFunctions.translateTemplate(_app.data[tagObj.datapointer],tagObj.parentID+"_"+tagObj.datapointer.split('|')[1]); + $(_app.u.jqSelector('#',tagObj.parentID+"_"+tagObj.datapointer.split('|')[1])).tlc({'verb':'translate','datapointer':tagObj.datapointer}); } else { -// app.u.dump(" -> cat '"+app.data[tagObj.datapointer].pretty+"' is hidden. nuke it!"); - $('#'+app.u.makeSafeHTMLId(tagObj.parentID+"_"+tagObj.datapointer.split('|')[1])).empty().remove(); +// _app.u.dump(" -> cat '"+_app.data[tagObj.datapointer].pretty+"' is hidden. nuke it!"); + $(_app.u.jqSelector('#',tagObj.parentID+"_"+tagObj.datapointer.split('|')[1])).empty().remove(); } } }, @@ -364,12 +169,12 @@ templateID - the template id used (from app.templates) // override the callback, which will be set to simply display the category in the DOM. getChildDataOf handles creating the template instance as long as parentID and templateID are set. getChildData : { onSuccess : function(tagObj) { -// app.u.dump('BEGIN app.ext.myRIA.callbacks.getChildData.onSuccess'); - var catSafeID = tagObj.datapointer.split('|')[1]; -// app.u.dump(" -> catsafeid: "+catSafeID); +// _app.u.dump('BEGIN _app.ext.quickstart.callbacks.getChildData.onSuccess'); + var path = tagObj.datapointer.split('|')[1]; +// _app.u.dump(" -> path: "+path); tagObj.callback = 'addCatToDom'; //the tagObj will have - app.ext.store_navcats.u.getChildDataOf(catSafeID,tagObj,'appNavcatDetail'); //generate nav for 'browse'. doing a 'max' because the page will use that anway. - app.model.dispatchThis(); + _app.ext.store_navcats.u.getChildDataOf(path,tagObj,'fast'); //generate nav for 'browse'. doing a 'max' because the page will use that anway. + _app.model.dispatchThis(); } } //getChildData @@ -390,129 +195,73 @@ templateID - the template id used (from app.templates) renderFormats : { + numsubcats : function($tag,data){ + $tag.append(data.value.length); + }, //numsubcats - numSubcats : function($tag,data){ -// app.u.dump('BEGIN store_navcats.renderFormats.numSubcats'); - $tag.append(data.value.length); - }, //numSubcats - - numProduct : function($tag,data){ -// app.u.dump('BEGIN store_navcats.renderFormats.numProduct'); - $tag.append(data.value.length); - }, //numSubcats - + numproduct : function($tag,data){ + $tag.append(data.value.length); + }, //numproduct - categoryList : function($tag,data) { -// app.u.dump("BEGIN store_navcats.renderFormats.categoryList"); + categorylist : function($tag,data) { +// dump(" BEGIN store_navcats.renderFormats.categorylist"); + data.value = data.value; +// dump(" -> data.value"); dump(data.value); if(typeof data.value == 'object' && data.value.length > 0) { var L = data.value.length; var call = 'appNavcatDetail'; var numRequests = 0; + data.bindData.detail = data.bindData.detail || 'fast'; //The process is different depending on whether or not 'detail' is set. detail requires a call for additional data. //detail will be set when more than the very basic information about the category is displayed (thumb, subcats, etc) - if(data.bindData.detail) { - if(data.bindData.detail == 'min') {} //uses default call - else if(data.bindData.detail == 'more' || data.bindData.detail == 'max') { - call = call+(data.bindData.detail.charAt(0).toUpperCase() + data.bindData.detail.slice(1)); //first letter of detail needs to be uppercase - } - else { - app.u.dump("WARNING! invalid value for 'detail' in categoryList renderFunction"); - } - for(var i = 0; i < L; i += 1) { -// *** 201344 null pretty name is NOT a hidden category. But we have to check to avoid a null ptr error. -mc - if(!data.value[i].pretty || data.value[i].pretty[0] != '!') { -// ** 201336+ appNavcatDetail id param changed to path -mc -// *** 201338 Missed a few references to id here -mc - var parentID = data.value[i].path+"_catgid+"+(app.u.guidGenerator().substring(10)); - $tag.append(app.renderFunctions.createTemplateInstance(data.bindData.loadsTemplate,{'id':parentID,'catsafeid':data.value[i].path})); - numRequests += app.ext.store_navcats.calls[call].init(data.value[i].path,{'parentID':parentID,'callback':'translateTemplate'}); - } - } - if(numRequests) {app.model.dispatchThis()} - } -//if no detail level is specified, only what is in the actual value (typically, id, pretty and @products) will be available. Considerably less data, but no request per category. - else { - for(var i = 0; i < L; i += 1) { -// ** 201336+ appNavcatDetail id param changed to path -mc - var parentID = data.value[i].path+"_catgid+"+(app.u.guidGenerator().substring(10)); - if(data.value[i].pretty[0] != '!') { - $tag.append(app.renderFunctions.transmogrify({'id':parentID,'catsafeid':data.value[i].path},data.bindData.loadsTemplate,data.value[i])); - } + for(var i = 0; i < L; i += 1) { +//a null pretty name is NOT a hidden category. But we have to check to avoid a null ptr error. - mc + if(!data.value[i].pretty || data.value[i].pretty[0] != '!') { +// var parentID = data.value[i].path+"_catgid+"+(_app.u.guidGenerator().substring(10)); +// var $ele = _app.renderFunctions.createTemplateInstance(data.bindData.loadsTemplate,{'catsafeid':data.value[i].path}); + var $tmp = $("<ul \/>").tlc({'templateid':data.bindData.templateid,'verb':'template','dataAttribs':{'catsafeid':data.value[i].path}}); + var $ele = $tmp.children().first(); + $tag.append($ele); + numRequests += _app.calls.appNavcatDetail.init({'path':data.value[i].path,'detail':data.bindData.detail},{'callback':'tlc','jqObj':$ele,'verb':'translate'},'mutable'); } } + if(numRequests) {_app.model.dispatchThis('mutable')} } else { //value isn't an object or is empty. perfectly normal to get here if a page has no subs. } }, -//assumes that you have already gotten a 'max' detail for the safecat specified data.value. -//shows the category, plus the first three subcategories. - subcategory2LevelList : function($tag,data) { - app.u.dump("BEGIN store_navcats.renderFormats.subcategory2LevelList"); - var catSafeID; //used in the loop for a short reference. - var subcatDetail = data.value; - var o = ''; - if(!$.isEmptyObject(subcatDetail)) { - var L = subcatDetail.length; - if(data.bindData.size == 'false') {size = L} - else if(Number(data.bindData.size)) {size = Number(data.bindData.size)} //if size is valid, use it. - else {size = L > 15 ? 15 : L; } //don't show more than 15 unless specified -//!!! hhhmm.. needs fixin. need to compensate 'i' for hidden categories. - for(var i = 0; i < size; i +=1) { - if(subcatDetail[i].pretty[0] != '!') { -// *** 201338 appNavcatDetail response format changed from id to path -mc - catSafeID = subcatDetail[i].path; - o += "<li><a href='#' onClick=\"showContent('category',{'navcat':'"+catSafeID+"'}); return false;\">"+subcatDetail[i].pretty+ "<\/a><\/li>"; - } - } - if(L > size) { - o += "<li class='viewAllSubcategories' onClick=\"showContent('category',{'navcat':'"+data.value+"'});\">View all "+L+" Categories<\/li>"; - } - $tag.append(o); - } - }, //subcategory2LevelList - //pass in category safe id as value breadcrumb : function($tag,data) { -app.u.dump("BEGIN store_navcats.renderFunctions.breadcrumb"); -var numRequests = 0; //number of requests (this format may require a dispatch to retrieve parent category info - when entry is a page 3 levels deep) - -if(app.u.isSet(data.value)) { - var pathArray = data.value.split('.'); - var L = pathArray.length; - var s = '.' - var catSafeID; //recycled in loop for path of category in focus during iteration. - //make sure homepage has a pretty. yes, it sometimes happens that it doesn't. -// if(!app.data['appNavcatDetail|.'] || !app.data['appNavcatDetail|.'].pretty) { -// app.data['appNavcatDetail|.'].pretty = 'Home'; -// } - +//_app.u.dump("BEGIN store_navcats.renderFunctions.breadcrumb"); +// in some cases, the breadcrumb may be outside the page content (in the master header, for example), so empty it first. +// if/when data-binds get more command-centric, get rid of this. + $tag.empty(); //reset each time + if(_app.u.isSet(data.value)) { + var pathArray = data.value.split('.'); + var L = pathArray.length; + var s = '.' //Creates var for tracking whether root has been met. - var reachedRoot = false; + var reachedRoot = false; // homepage has already been rendered. if path == ., likely we r on a product page, arriving from homepage. don't show bc. - if(data.value == '.'){} - else { - for(var i = 0; i < L; i += 1) { - s += pathArray[i]; - + if(data.value == '.'){} + else { + for(var i = 0; i < L; i += 1) { + s += pathArray[i]; //Checks the rootcat to ensure we don't add extra categories above our root to the breadcrumb. Once reachedRoot is triggered, add all categories below the root. - if(!reachedRoot) { - reachedRoot = (zGlobals.appSettings.rootcat === s); - } - if(reachedRoot) { - //app.u.dump(" -> "+i+" s(path): "+s); - //app.u.dump(app.data['appNavcatDetail|'+s]); - $tag.append(app.renderFunctions.transmogrify({'id':'.','catsafeid':s},data.bindData.loadsTemplate,app.data['appNavcatDetail|'+s])); - } - if(i!=0) - s += '.'; - } - } - - - -} + if(!reachedRoot) { + reachedRoot = (zGlobals.appSettings.rootcat === s); + } + if(reachedRoot) { +// $tag.append(_app.renderFunctions.transmogrify({'id':'.','catsafeid':s},data.bindData.loadsTemplate,_app.data['appNavcatDetail|'+s])); + $tag.append(new tlc().runTLC({templateid : data.bindData.templateid, dataset : _app.data['appNavcatDetail|'+s]}).attr({'data-catsafeid':s})); + } + if(i!=0) + s += '.'; + } + } + } } //breadcrumb }, //renderFormats @@ -529,68 +278,72 @@ will return an object of id:safeid, which is how the categories are stored in a the formatted is specific so that getChildDataOf can be used for a specific id or '.' so don't change the output without testing it in that function. */ getRootCats : function() { -// app.u.dump('BEGIN app.ext.store_navcats.u.getRootCats'); +// _app.u.dump('BEGIN _app.ext.store_navcats.u.getRootCats'); var r = false; - if(app.data.appCategoryList) { - var L = app.data.appCategoryList['@paths'].length; +// *** 201401 path appended to appCategoryList datapointer in 201352 -mc + if(_app.data["appCategoryList|"+zGlobals.appSettings.rootcat]) { + var L = _app.data["appCategoryList|"+zGlobals.appSettings.rootcat]['@paths'].length; r = new Array(); - // app.u.dump(' -> num cats = '+L); + // _app.u.dump(' -> num cats = '+L); for(var i = 0; i < L; i += 1) { - if(app.data.appCategoryList['@paths'][i].split('.').length == 2) { - r.push(app.data.appCategoryList['@paths'][i]); + if(_app.data["appCategoryList|"+zGlobals.appSettings.rootcat]['@paths'][i].split('.').length == 2) { + r.push(_app.data["appCategoryList|"+zGlobals.appSettings.rootcat]['@paths'][i]); } } } else { - app.u.dump("WARNING! Attempted to run store_navcats.u.getRootCats before appCategoryList is in data/memory."); + _app.u.dump("WARNING! Attempted to run store_navcats.u.getRootCats before appCategoryList is in data/memory."); } return r; }, //getRootCatsData - getCatsFromCategoryList : function(catSafeID) { - app.u.dump('BEGIN app.ext.store_navcats.u.getCatsFromCategoryList'); + getCatsFromCategoryList : function(path) { +// _app.u.dump('BEGIN _app.ext.store_navcats.u.getCatsFromCategoryList'); var r = false; //what is returned. false if appCategoryList is not defined. otherwise an array of category id's. empty array if no subcats defined. - if(!catSafeID) { - app.u.throwGMessage("catSafeID not specified in store_navcats.u.getCatsFromCategoryList"); + if(!path) { + _app.u.throwGMessage("path not specified in store_navcats.u.getCatsFromCategoryList"); } - else if(!app.data.appCategoryList) { - app.u.throwGMessage("Attempted to run store_navcats.u.getCatsFromCategoryList before appCategoryList is in data/memory."); +// *** 201401 path appended to appCategoryList datapointer in 201352 -mc + else if(!_app.data["appCategoryList|"+path]) { + _app.u.throwGMessage("Attempted to run store_navcats.u.getCatsFromCategoryList before appCategoryList is in data/memory."); } - else if(catSafeID == '.') { - r = app.ext.store_navcats.u.getRootCats(); + else if(path == zGlobals.appSettings.rootcat) { + r = _app.ext.store_navcats.u.getRootCats(); } - else if(app.data.appCategoryList && catSafeID) { - var L = app.data.appCategoryList['@paths'].length; + else if(_app.data["appCategoryList|"+path] && path) { + var L = _app.data["appCategoryList|"+path]['@paths'].length; r = new Array(); - for(var i = 0; i < L; i += 1) { - if(app.data.appCategoryList['@paths'][i].indexOf(catSafeID) == 0) { - r.push(app.data.appCategoryList['@paths'][i]); +// *** 201352 now returns only direct subcats, instead of including nested also. -mc + for(var i = 0; i < L; i += 1) { + var path = _app.data["appCategoryList|"+path]['@paths'][i]; + if(path != path && path.indexOf(path) == 0 && path.replace(path+'.', "").indexOf('.') < 0) { + r.push(path); } } } else { - app.u.throwGMessage("An unknown error occured in store_navcats.u.getCatsFromCategoryList"); + _app.u.throwGMessage("An unknown error occured in store_navcats.u.getCatsFromCategoryList"); } return r; }, //getRootCatsData - getListOfSubcats : function(catSafeID){ -// app.u.dump("BEGIN store_navcats.u.getListOfSubcats ["+catSafeID+"]"); + getListOfSubcats : function(path){ +// _app.u.dump("BEGIN store_navcats.u.getListOfSubcats ["+path+"]"); var catsArray = new Array(); - if(catSafeID == '.') { + if(path == zGlobals.appSettings.rootcat) { catsArray = this.getRootCats(); } - else if(app.data['appNavcatDetail|'+catSafeID]) { - if(typeof app.data['appNavcatDetail|'+catSafeID]['@subcategories'] == 'object') { - catsArray = app.data['appNavcatDetail|'+catSafeID]['@subcategories']; + else if(_app.model.fetchData('appNavcatDetail|'+path)) { + if(typeof _app.data['appNavcatDetail|'+path]['@subcategories'] == 'object') { + catsArray = _app.data['appNavcatDetail|'+path]['@subcategories']; } //when a max detail is done for appNavcatDetail, subcategories[] is replaced with subcategoryDetail[] in which each subcat is an object. - else if(typeof app.data['appNavcatDetail|'+catSafeID]['@subcategoryDetail'] == 'object') { - catsArray = this.getSubsFromDetail(catSafeID); + else if(typeof _app.data['appNavcatDetail|'+path]['@subcategoryDetail'] == 'object') { + catsArray = this.getSubsFromDetail(path); } -// app.u.dump(" -> catsArray: "); app.u.dump(catsArray); +// _app.u.dump(" -> catsArray: "); _app.u.dump(catsArray); } - else if(catsArray = this.getCatsFromCategoryList(catSafeID)){} // = instead of == cuz we're setting the value of catsArray in the IF + else if(catsArray = this.getCatsFromCategoryList(path)){} // = instead of == cuz we're setting the value of catsArray in the IF else {} //catch return catsArray; }, @@ -598,7 +351,7 @@ the formatted is specific so that getChildDataOf can be used for a specific id o /* a function for obtaining information about a categories children. assumes you have already retrieved data on parent so that @subcategories or @subcategoryDetail is present. - -> catSafeID should be the category safe id that you want to obtain information for. + -> path should be the category safe id that you want to obtain information for. -> call, in all likelyhood, will be set to one of the following: appNavcatDetailMax, appNavcatDetailMore, appNavcatDetail. It'll default to Fast (no suffix). tagObj is optional and would contain an object to be passed as _tag in the request (callback, templateID, etc). if the parentID and templateID are passed as part of tagObj, a template instance is created within parentID. @@ -608,20 +361,20 @@ note - there is NO error checking in here to make sure the subcats aren't alread (see examples/site-analyzer/ actions.showSubcats */ - getChildDataOf : function(catSafeID,tagObj,call){ + getChildDataOf : function(path,tagObj,detail){ var numRequests = 0; //will get incremented once for each request that needs dispatching. -// app.u.dump("BEGIN app.ext.store_navcats.u.getChildDataOf ("+catSafeID+")"); -// app.u.dump(app.data['appNavcatDetail|'+catSafeID]) -//if . is passed as catSafeID, then tier1 cats are desired. The list needs to be generated. - var catsArray = this.getListOfSubcats(catSafeID) +// _app.u.dump("BEGIN _app.ext.store_navcats.u.getChildDataOf ("+path+")"); +// _app.u.dump(_app.data['appNavcatDetail|'+path]) +//if . is passed as path, then tier1 cats are desired. The list needs to be generated. + var catsArray = this.getListOfSubcats(path) var newParentID; - var tier = (catSafeID.split('.').length) - 1; //root cat split to 2, so subtract 1. + var tier = (path.split('.').length) - 1; //root cat split to 2, so subtract 1. if(catsArray.length > 0) { catsArray.sort(); //sort by safe id. var L = catsArray.length; - var call = call ? call : "appNavcatDetail" + detail = detail || "fast" //used in the for loop below to determine whether or not to render a template. use this instead of checking the two vars (templateID and parentID) renderTemplate = false; if(tagObj.templateID && tagObj.parentID) { @@ -633,12 +386,13 @@ note - there is NO error checking in here to make sure the subcats aren't alread //homepage is skipped. at this point we're dealing with subcat data and don't want 'homepage' to display among them if(catsArray[i] != '.') { newParentID = tagObj.parentID+"_"+catsArray[i] - $parent.append(app.renderFunctions.createTemplateInstance(tagObj.templateID,{"id":newParentID,"catsafeid":catsArray[i]})); +// $parent.append(_app.renderFunctions.createTemplateInstance(tagObj.templateID,{"id":newParentID,"catsafeid":catsArray[i]})); + $parent.append(new tlc().getTemplateInstance(tagObj.templateID).attr({"id":newParentID,"catsafeid":catsArray[i]})); } } //if tagObj was passed in without .extend, the datapointer would end up being shared across all calls. //I would have though that manipulating tagObj within another function would be local to that function. apparently not. - numRequests += app.ext.store_navcats.calls[call].init(catsArray[i],$.extend({'parentID':newParentID},tagObj)); + numRequests += _app.calls.appNavcatDetail.init({'path':catsArray[i],'detail':detail},$.extend({'parentID':newParentID},tagObj)); } } return numRequests; @@ -646,34 +400,34 @@ note - there is NO error checking in here to make sure the subcats aren't alread //on a appNavcatDetail, the @subcategoryDetail contains an object. The data is structured differently than @subcategories. //this function will return an array of subcat id's, formatted like the value of @subcategories. - getSubsFromDetail : function(catSafeID) { + getSubsFromDetail : function(path) { var catsArray = new Array(); //what is returned. incremented with each dispatch created. - var L = app.data['appNavcatDetail|'+catSafeID]['@subcategoryDetail'].length + var L = _app.data['appNavcatDetail|'+path]['@subcategoryDetail'].length for(var i = 0; i < L; i += 1) { // *** 201338 appNavcatDetail id changed to path - catsArray.push(app.data['appNavcatDetail|'+catSafeID]['@subcategoryDetail'][i].path); + catsArray.push(_app.data['appNavcatDetail|'+path]['@subcategoryDetail'][i].path); } - //app.u.dump(catsArray); + //_app.u.dump(catsArray); return catsArray; }, //getSubsFromDetail addQueries4BreadcrumbToQ : function(path) { -// app.u.dump("BEGIN myRIA.u.getBreadcrumbData"); - var numRequests = 0; +// _app.u.dump("BEGIN quickstart.u.getBreadcrumbData"); + var datapointers = new Array(); //what's returned. the length can be used to update numRequests (if necessary). the array itself can be used for extending by datapointers, if necessary. var pathArray = path.split('.'); var len = pathArray.length var s= '.'; //used to contatonate safe id. - numRequests += app.ext.store_navcats.calls.appNavcatDetail.init('.'); //homepage data. outside of loop so I can keep loop more efficient + _app.calls.appNavcatDetail.init({'path':'.','detail':'fast'}); //homepage data. outside of loop so I can keep loop more efficient for (var i=1; i < len; i += 1) { s += pathArray[i]; //pathArray[0] will be blank, so s (.) plus nothing is just . -// app.u.dump(" -> path for breadcrumb: "+s); - numRequests += app.ext.store_navcats.calls.appNavcatDetail.init(s); +// _app.u.dump(" -> path for breadcrumb: "+s); + datapointers.push("appNavcatDetail|"+s); + _app.calls.appNavcatDetail.init({'path':s,'detail':'fast'}); //after each loop, the . is added so when the next cat id is appended, they're concatonated with a . between. won't matter on the last loop cuz we're done. s += "."; //put a period between each id. do this first so homepage data gets retrieved. - } - return numRequests; + return datapointers; } diff --git a/extensions/store_prodlist.js b/extensions/store_prodlist.js index 67edce6b2..3fae6ea24 100755 --- a/extensions/store_prodlist.js +++ b/extensions/store_prodlist.js @@ -25,7 +25,7 @@ currently, sorting is not available as part of the multipage header. ### */ -var store_prodlist = function() { +var store_prodlist = function(_app) { var r = { vars : { forgetmeContainer : {} //used to store an object of pids (key) for items that don't show in the prodlist. value can be app specific. TS makes sense. @@ -57,12 +57,12 @@ The advantage of saving the data in memory and local storage is lost if the data tagObj = $.isEmptyObject(tagObj) ? {} : tagObj; tagObj["datapointer"] = "appProductGet|"+pid; //fetchData checks the timestamp, so no need to doublecheck it here unless there's a need to make sure it is newer than what is specified (1 day) in the fetchData function - if(app.model.fetchData('appProductGet|'+pid) == false) { + if(_app.model.fetchData('appProductGet|'+pid) == false) { r = 2; this.dispatch(pid,tagObj,Q); } else { - app.u.handleCallback(tagObj) + _app.u.handleCallback(tagObj) } return r; }, @@ -71,7 +71,7 @@ The advantage of saving the data in memory and local storage is lost if the data obj["_cmd"] = "appProductGet"; obj["pid"] = pid; obj["_tag"] = tagObj; - app.model.addDispatchToQ(obj,Q); + _app.model.addDispatchToQ(obj,Q); } }, //appProductGet @@ -80,34 +80,34 @@ The advantage of saving the data in memory and local storage is lost if the data getDetailedProduct : { init : function(obj,tagObj,Q) { var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. -// app.u.dump("BEGIN app.ext.store_product.calls.appProductGet"); -// app.u.dump(" -> PID: "+obj.pid); -// app.u.dump(" -> obj['withReviews']: "+obj['withReviews']); +// _app.u.dump("BEGIN _app.ext.store_product.calls.appProductGet"); +// _app.u.dump(" -> PID: "+obj.pid); +// _app.u.dump(" -> obj['withReviews']: "+obj['withReviews']); tagObj = $.isEmptyObject(tagObj) ? {} : tagObj; tagObj["datapointer"] = "appProductGet|"+obj.pid; //fetchData checks the timestamp, so no need to doublecheck it here unless there's a need to make sure it is newer than what is specified (1 day) in the fetchData function - if(app.model.fetchData(tagObj.datapointer) == false) { -// app.u.dump(" -> appProductGet not in memory or local. refresh both."); + if(_app.model.fetchData(tagObj.datapointer) == false) { +// _app.u.dump(" -> appProductGet not in memory or local. refresh both."); r += 1; } - else if(obj['withInventory'] && typeof app.data[tagObj.datapointer]['@inventory'] == 'undefined') { + else if(obj['withInventory'] && typeof _app.data[tagObj.datapointer]['@inventory'] == 'undefined') { r += 1; } - else if(obj['withVariations'] && typeof app.data[tagObj.datapointer]['@variations'] == 'undefined') { + else if(obj['withVariations'] && typeof _app.data[tagObj.datapointer]['@variations'] == 'undefined') { r += 1; } -// && app.model.addDispatchToQ(obj,Q) -> not sure why this was here. +// && _app.model.addDispatchToQ(obj,Q) -> not sure why this was here. if(obj['withReviews']) { //callback will b on appProductGet, but make sure this request is first so that when callback is executed, this is already in memory. - r += app.ext.store_prodlist.calls.appReviewsList.init(obj.pid,{},Q); + r += _app.ext.store_prodlist.calls.appReviewsList.init(obj.pid,{},Q); } //To ensure accurate data, if inventory or variations are desired, data is requested. //r will be greater than zero if product record not already in local or memory if(r == 0) { - app.u.handleCallback(tagObj) + _app.u.handleCallback(tagObj) } else { this.dispatch(obj,tagObj,Q) @@ -118,7 +118,7 @@ The advantage of saving the data in memory and local storage is lost if the data dispatch : function(obj,tagObj,Q) { obj["_cmd"] = "appProductGet"; obj["_tag"] = tagObj; - app.model.addDispatchToQ(obj,Q); + _app.model.addDispatchToQ(obj,Q); } }, //appProductGet @@ -132,17 +132,17 @@ The advantage of saving the data in memory and local storage is lost if the data tagObj = $.isEmptyObject(tagObj) ? {} : tagObj; tagObj["datapointer"] = "appReviewsList|"+pid; - if(app.model.fetchData('appReviewsList|'+pid) == false) { + if(_app.model.fetchData('appReviewsList|'+pid) == false) { r = 1; this.dispatch(pid,tagObj,Q) } else { - app.u.handleCallback(tagObj) + _app.u.handleCallback(tagObj) } return r; }, dispatch : function(pid,tagObj,Q) { - app.model.addDispatchToQ({"_cmd":"appReviewsList","pid":pid,"_tag" : tagObj},Q); + _app.model.addDispatchToQ({"_cmd":"appReviewsList","pid":pid,"_tag" : tagObj},Q); } }//appReviewsList @@ -170,12 +170,12 @@ The advantage of saving the data in memory and local storage is lost if the data //callbacks.init need to return either a true or a false, depending on whether or not the file will execute properly based on store account configuration. init : { onSuccess : function() { -// app.u.dump('BEGIN app.ext.store_prodlist.init.onSuccess '); +// _app.u.dump('BEGIN _app.ext.store_prodlist.init.onSuccess '); return true; //currently, there are no config or extension dependencies, so just return true. may change later. -// app.u.dump('END app.ext.store_prodlist.init.onSuccess'); +// _app.u.dump('END _app.ext.store_prodlist.init.onSuccess'); }, onError : function() { - app.u.dump('BEGIN app.ext.store_prodlist.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_prodlist.callbacks.init.onError'); } }, /* @@ -183,33 +183,54 @@ A special translate template for product so that reviews can be merged into the */ translateTemplate : { onSuccess : function(tagObj) { -// app.u.dump("BEGIN app.ext.store_prodlist.callbacks.translateTemplate.onSuccess"); -// app.u.dump(tagObj); -// app.u.dump(" -> tagObj.datapointer = "+tagObj.datapointer); -// app.u.dump(" -> tagObj.parentID = "+tagObj.parentID+" and $(#"+tagObj.parentID+").length: "+$('#'+tagObj.parentID).length); - var tmp = app.data[tagObj.datapointer]; - var pid = app.data[tagObj.datapointer].pid; -// app.u.dump(" -> typeof app.data['appReviewsList|'+pid]:"+ typeof app.data['appReviewsList|'+pid]); - if(typeof app.data['appReviewsList|'+pid] == 'object' && app.data['appReviewsList|'+pid]['@reviews'].length) { -// app.u.dump(" -> Item ["+pid+"] has "+app.data['appReviewsList|'+pid]['@reviews'].length+" review(s)"); - tmp['reviews'] = app.ext.store_prodlist.u.summarizeReviews(pid); //generates a summary object (total, average) - tmp['reviews']['@reviews'] = app.data['appReviewsList|'+pid]['@reviews'] - } - (tagObj.jqObj instanceof jQuery) ? tagObj.jqObj.anycontent({'datapointer':tagObj.datapointer}) : $(app.u.jqSelector('#',tagObj.parentID)).anycontent({'datapointer':tagObj.datapointer}) -// app.renderFunctions.translateTemplate(app.data[tagObj.datapointer],tagObj.parentID); +// _app.u.dump("BEGIN _app.ext.store_prodlist.callbacks.translateTemplate.onSuccess "); +// _app.u.dump(tagObj); +// _app.u.dump(" -> tagObj.datapointer = "+tagObj.datapointer); +// _app.u.dump(" -> tagObj.parentID = "+tagObj.parentID+" and $(#"+tagObj.parentID+").length: "+$('#'+tagObj.parentID).length); + var tmp = _app.data[tagObj.datapointer]; + var pid = _app.data[tagObj.datapointer].pid; +// _app.u.dump(" -> typeof _app.data['appReviewsList|'+pid]:"+ typeof _app.data['appReviewsList|'+pid]); + if(typeof _app.data['appReviewsList|'+pid] == 'object' && _app.data['appReviewsList|'+pid]['@reviews'].length) { +// _app.u.dump(" -> Item ["+pid+"] has "+_app.data['appReviewsList|'+pid]['@reviews'].length+" review(s)"); + tmp['reviews'] = _app.ext.store_prodlist.u.summarizeReviews(pid); //generates a summary object (total, average) + tmp['reviews']['@reviews'] = _app.data['appReviewsList|'+pid]['@reviews'] + } + + var $product = tagObj.jqObj.removeClass('loadingBG').attr('data-pid',pid); + var $prodlist = $product.parent(); + + $product.tlc({'dataset':tmp,'verb':'translate'}).attr('data-template-role','listitem'); + _app.u.handleButtons($product); + + + $prodlist.data('pageProductLoaded',($prodlist.data('pageProductLoaded') + 1)); //tracks if page is done. + $prodlist.data('totalProductLoaded',($prodlist.data('totalProductLoaded') + 1)); //tracks if entire list is done. handy for last page which may have fewer than an entire pages worth of data. + if(($prodlist instanceof jQuery && $prodlist.data('pageProductLoaded')) && (($prodlist.data('pageProductLoaded') == $prodlist.data('prodlist').items_per_page) || ($prodlist.data('totalProductLoaded') == $prodlist.data('prodlist').total_product_count))) { +// _app.u.dump($._data($prodlist[0],'events')); //how to see what events are tied to an element. not a supported method. + $prodlist.trigger('listcomplete'); + } + + +// _app.renderFunctions.translateTemplate(_app.data[tagObj.datapointer],tagObj.parentID); }, //error needs to clear parent or we end up with orphans (especially in UI finder). onError : function(responseData,uuid) { responseData.persistent = true; //throwMessage will NOT hide error. better for these to be pervasive to keep merchant fixing broken things. var pid = responseData.pid; - var $parent = $('#'+responseData['_rtag'].parentID) - $parent.empty().removeClass('loadingBG'); - $parent.anymessage(responseData,uuid); + + var $product =(responseData.jqObj instanceof jQuery) ? responseData.jqObj : $(_app.u.jqSelector('#',responseData.parentID)); + $product.empty().removeClass('loadingBG'); + $product.anymessage(responseData,uuid); +//even if the product errors out, productLoaded gets incremented so the oncomplete runs. + var $prodlist = $product.parent(); + $prodlist.data('pageProductLoaded',($prodlist.data('pageProductLoaded') + 1)); + $prodlist.data('totalProductLoaded',($prodlist.data('totalProductLoaded') + 1)); + //for UI prod finder. if admin session, adds a 'remove' button so merchant can easily take missing items from list. - if(app.vars.thisSessionIsAdmin) { + if(_app.u.thisIsAnAdminSession()) { $("<button \/>").text("Remove "+pid).button().on('click',function(){ - app.ext.admin.u.removePidFromFinder($(this).closest("[data-pid]")); //function accepts a jquery object. - }).appendTo($('.ui-widget-anymessage',$parent)); + _app.ext.admin.u.removePidFromFinder($(this).closest("[data-pid]")); //function accepts a jquery object. + }).appendTo($('.ui-widget-anymessage',$product)); } } }, @@ -217,10 +238,10 @@ A special translate template for product so that reviews can be merged into the //put an array of sku's into memory for quick access. This array is what is used in filterProdlist to remove items from the forgetme list. handleForgetmeList : { onSuccess : function(tagObj) { - var L = app.data['getCustomerList|forgetme']['@forgetme'].length - app.ext.store_prodlist.vars.forgetmeContainer.csv = []; //reset list. + var L = _app.data['getCustomerList|forgetme']['@forgetme'].length + _app.ext.store_prodlist.vars.forgetmeContainer.csv = []; //reset list. for(var i = 0; i < L; i += 1) { - app.ext.store_prodlist.vars.forgetmeContainer.csv.push(app.data['getCustomerList|forgetme']['@forgetme'][i].SKU) + _app.ext.store_prodlist.vars.forgetmeContainer.csv.push(_app.data['getCustomerList|forgetme']['@forgetme'][i].SKU) } } } @@ -244,18 +265,24 @@ A special translate template for product so that reviews can be merged into the //a product list needs an ID for multipage to work right. will assign a random one if none is set. //that parent ID is prepended to the sku and used in the list item id to decrease likelyhood of duplicate id's //data.bindData will get passed into getProdlistVar and used for defaults on the list itself. That means any var supported in prodlistVars can be set in bindData. - + productlist : function($tag,data) { + //need to keep admin and quickstart both running. +// dump(" data.value: "); dump(data.value); + data.bindData.loadsTemplate = data.bindData.templateid; // ### TODO -> once the prodlist code is updated, this can be ditched. + data.value = data.value; + this.productList($tag,data); + }, productList : function($tag,data) { -// app.u.dump("BEGIN store_prodlist.renderFormats.productList"); -// app.u.dump(" -> data.bindData: "); app.u.dump(data.bindData); - if(app.u.isSet(data.value)) { +// _app.u.dump("BEGIN store_prodlist.renderFormats.productList"); +// _app.u.dump(" -> data.bindData: "); _app.u.dump(data.bindData); + if(_app.u.isSet(data.value)) { data.bindData.csv = data.value; - app.ext.store_prodlist.u.buildProductList(data.bindData,$tag); + _app.ext.store_prodlist.u.buildProductList(data.bindData,$tag); } },//prodlist mpPagesAsListItems : function($tag,data) { -// app.u.dump('BEGIN app.ext.store_prodlist.renderFormats.mpPagesAsListItems'); +// _app.u.dump('BEGIN _app.ext.store_prodlist.renderFormats.mpPagesAsListItems'); var o = ''; for(var i = 1; i <= data.value; i += 1) { o += "<li class='mpControlJumpToPage' data-page='"+i+"'><span>page: "+i+"<\/span><\/li>"; //data-page is used for MP 'jumping'. don't use index or .text because order and text could get changed. @@ -272,9 +299,9 @@ will remove the add to cart button if the item is not purchaseable. */ - addToCartButton : function($tag,data) { -// app.u.dump("BEGIN store_product.renderFunctions.addToCartButton"); -// app.u.dump(" -> ID before any manipulation: "+$tag.attr('id')); + addtocartbutton : function($tag,data) { +// _app.u.dump("BEGIN store_product.renderFunctions.addtocartbutton"); +// _app.u.dump(" -> ID before any manipulation: "+$tag.attr('id')); var pid = data.value; var showATC = true; @@ -282,11 +309,11 @@ will remove the add to cart button if the item is not purchaseable. // add a success message div to be output before the button so that messaging can be added to it. // atcButton class is added as well, so that the addToCart call can disable and re-enable the buttons. $tag.attr('id',$tag.attr('id')+'_'+pid).addClass('atcButton').before("<div class='atcSuccessMessage' id='atcMessaging_"+pid+"'><\/div>"); - if(app.ext.store_product.u.productIsPurchaseable(pid)) { + if(_app.ext.store_product.u.productIsPurchaseable(pid)) { //product is purchaseable. make sure button is visible and enabled. $tag.show().removeClass('displayNone').removeAttr('disabled'); - if(typeof app.data['appProductGet|'+pid]['@variations'] == 'undefined') {showATC = false} - else if(!$.isEmptyObject(app.data['appProductGet|'+pid]['@variations'])){showATC = false} + if(typeof _app.data['appProductGet|'+pid]['@variations'] == 'undefined') {showATC = false} + else if(!$.isEmptyObject(_app.data['appProductGet|'+pid]['@variations'])){showATC = false} /* when the template is initially created (using createInstance and then translate template @@ -295,28 +322,28 @@ so the atc events are unbinded, then binded. */ if(showATC) { -// app.u.dump(" -> is add to cart."); +// _app.u.dump(" -> is add to cart."); $tag.addClass('addToCartButton').unbind('.myATCEvent').bind('click.myATCEvent',function(event){ -// app.u.dump("BUTTON pushed. $(this).parent().attr('id') = "+$(this).parent().attr('id')); +// _app.u.dump("BUTTON pushed. $(this).parent().attr('id') = "+$(this).parent().attr('id')); $(this).parent().submit(); event.preventDefault(); }).text('Add To Cart') } else { -// app.u.dump(" -> is choose options."); +// _app.u.dump(" -> is choose options."); $tag.addClass('chooseOptionsButton').unbind('.myATCEvent').bind('click.myATCEvent',function(event){ event.preventDefault(); -// !!! TEMPORARY!!! this needs to be handled better. a function needs to be passed in or something. -//move into the custom app. -app.ext.myRIA.u.handlePageContent('product',pid) +// ### TODO -> this needs to be handled better. a function needs to be passed in or something. +//move into the custom _app. +_app.ext.quickstart.u.handlePageContent('product',pid) }).text('Choose Options')} } else { $tag.replaceWith("<span class='notAvailable'>not available</span>"); } -// app.u.dump(" -> ID at end: "+$tag.attr('id')); - } //addToCartButton +// _app.u.dump(" -> ID at end: "+$tag.attr('id')); + } //addtocartbutton }, @@ -354,8 +381,7 @@ the object created here is passed as 'data' into the mulitpage template. that's */ setProdlistVars : function(obj) { -// app.u.dump("BEGIN store_prodlist.u.setProdlistVars"); -// app.u.dump(obj); +// _app.u.dump("BEGIN store_prodlist.u.setProdlistVars"); _app.u.dump(obj); var r = false; var hideMultipageControls = false; //if set to true, will hide just the dropdown/page controls. @@ -372,7 +398,7 @@ the object created here is passed as 'data' into the mulitpage template. that's obj.withInventory = (obj.withInventory) ? 1 : 0; obj.withVariations = (obj.withVariations) ? 1 : 0; obj.withReviews = (obj.withReviews) ? 1 : 0; - obj.parentID = obj.parentID || 'pl_'+app.u.guidGenerator().substring(0,12); //gotta have an ID. really really wants a unique id. + obj.parentID = obj.parentID || 'pl_'+_app.u.guidGenerator().substring(0,12); //gotta have an ID. really really wants a unique id. var firstProductOnPage = (obj.page_in_focus-1)*obj.items_per_page; //subtract 1 from page so that we start at the zero point in the array. var lastProductOnPage = firstProductOnPage + obj.items_per_page; //last spot in csv for this page. @@ -393,7 +419,7 @@ the object created here is passed as 'data' into the mulitpage template. that's } else{ - app.u.dump(" -> Missing some required fields for setProdlistVars. requires csv and loadstemplate."); app.u.dump(obj); + _app.u.dump(" -> Missing some required fields for setProdlistVars. requires csv and loadstemplate."); _app.u.dump(obj); r = false; } return r; @@ -419,8 +445,11 @@ the object created here is passed as 'data' into the mulitpage template. that's if(typeof csv == 'string') { csv = csv.split(','); } -// app.u.dump(" -> typeof csv: "+typeof csv); +// _app.u.dump(" -> typeof csv: "+typeof csv); csv = $.grep(csv,function(n){return(n);}); //remove blanks. commonly occurs in product attributes cuz of extra comma +// *** 201404 -> IE8 does NOT support trim(). + csv = $.map(csv,function(n){return(n.replace(/^\s+|\s+$/g, ''));}); //remove blanks. commonly occurs in product attributes cuz of extra comma. +// csv = $.map(csv,function(n){return(n.trim());}); //remove blanks. commonly occurs in product attributes cuz of extra comma return csv; }, @@ -431,7 +460,7 @@ the object created here is passed as 'data' into the mulitpage template. that's var pageCSV = this.getSkusForThisPage(plObj); var L = pageCSV.length; for(var i = 0; i < L; i += 1) { - $r.append(app.renderFunctions.createTemplateInstance(plObj.loadsTemplate,{"id":this.getSkuSafeIdForList(plObj.parentID,pageCSV[i]),"pid":pageCSV[i]})); //create a 'place' for this product in the list. + $r.append(_app.renderFunctions.createTemplateInstance(plObj.loadsTemplate,{"id":this.getSkuSafeIdForList(plObj.parentID,pageCSV[i]),"pid":pageCSV[i]})); //create a 'place' for this product in the list. } } return $r.children(); @@ -439,7 +468,7 @@ the object created here is passed as 'data' into the mulitpage template. that's //builds the safeID for the container of a product. unique per list/sku getSkuSafeIdForList : function(parentID,sku) { - return parentID+"_"+app.u.makeSafeHTMLId(sku); + return parentID+"_"+_app.u.makeSafeHTMLId(sku); }, /* @@ -456,13 +485,12 @@ if no parentID is set, then this function gets the data into memory for later us */ getProductDataForList : function(plObj,$tag,Q) { - app.u.dump("BEGIN store_prodlist.u.getProductDataForList ["+plObj.parentID+"]"); - +// _app.u.dump("BEGIN store_prodlist.u.getProductDataForList ["+plObj.parentID+"]"); _app.u.dump(plObj); Q = Q || 'mutable'; var numRequests = 0; //# of requests that will b made. what is returned. if(plObj && plObj.csv) { - app.u.dump(" -> csv defined. length: "+plObj.csv.length); - var pageCSV = this.getSkusForThisPage(plObj); +// _app.u.dump(" -> csv defined. length: "+plObj.csv.length); _app.u.dump(plObj.csv); + var pageCSV = this.getSkusForThisPage(plObj); var L = pageCSV.length; var call = 'appProductGet'; //this call is used unless variations or inventory are needed. this call is 'light' and just gets basic info. if(Number(plObj.withVariations) + Number(plObj.withInventory) + Number(plObj.withReviews) > 0) { @@ -470,24 +498,28 @@ if no parentID is set, then this function gets the data into memory for later us } for(var i = 0; i < L; i += 1) { - app.u.dump("Queueing data fetch for "+pageCSV[i]); +// _app.u.dump("Queueing data fetch for "+pageCSV[i]); var _tag = {}; if(plObj.isWizard) { _tag = {'callback':'translateTemplate','extension':'store_prodlist','jqObj':magic.inspect('#'+this.getSkuSafeIdForList(plObj.parentID,pageCSV[i]))} } else if(plObj.parentID) { - _tag = {'callback':'translateTemplate','extension':'store_prodlist','parentID':this.getSkuSafeIdForList(plObj.parentID,pageCSV[i])} +// _app.u.dump(" -> parentID is set."); + _tag = {'callback':'translateTemplate','extension':'store_prodlist','jqObj':$(plObj.placeholders[i])} + } + else { + _app.u.dump(" -> no parentID set. item not queued."); } - else {} - numRequests += app.ext.store_prodlist.calls[call].init({ + numRequests += _app.ext.store_prodlist.calls[call].init({ "pid":pageCSV[i], + "withReviews":plObj.withReviews, "withVariations":plObj.withVariations, - "withReviews":plObj.withReviews, "withInventory":plObj.withInventory },_tag, Q); //tagObj not passed if parentID not set. } } - if(numRequests > 0) {app.model.dispatchThis(Q)} + + if(numRequests > 0) {_app.model.dispatchThis(Q)} return numRequests; }, //getProductDataForList @@ -509,30 +541,28 @@ obj is most likely the databind object. It can be any params set in setProdlistV params that are missing will be auto-generated. */ buildProductList : function(obj,$tag) { -// app.u.dump("BEGIN store_prodlist.u.buildProductList()"); -// app.u.dump(" -> obj: "); app.u.dump(obj); +// _app.u.dump("BEGIN store_prodlist.u.buildProductList()"); _app.u.dump(" -> obj: "); _app.u.dump(obj); //Need either the tag itself ($tag) or the parent id to build a list. recommend $tag to ensure unique parent id is created //also need a list of product (csv) if(($tag || (obj && obj.parentID)) && obj.csv) { -// app.u.dump(" -> required parameters exist. Proceed..."); - obj.csv = app.ext.store_prodlist.u.cleanUpProductList(obj.csv); //strip blanks and make sure this is an array. prod attributes are not, by default. +// _app.u.dump(" -> required parameters exist. Proceed..."); + obj.csv = _app.ext.store_prodlist.u.cleanUpProductList(obj.csv); //strip blanks and make sure this is an array. prod attributes are not, by default. -// app.u.dump(" -> plObj: "); app.u.dump(plObj); -// app.u.dump(" -> obj: "); app.u.dump(obj); +// use child as template is used within KISS. if(obj.useChildAsTemplate) { - app.u.dump(" -> obj.useChildAsTemplate is true."); +// _app.u.dump(" -> obj.useChildAsTemplate is true."); obj.loadsTemplate = "_"+$tag.attr('id')+"ListItemTemplate"; - if(app.templates[obj.loadsTemplate]) { - app.u.dump(" -> template already exists"); + if(_app.templates[obj.loadsTemplate]) { + _app.u.dump(" -> template already exists"); //child has already been made into a template. } else { - app.u.dump(" -> template does not exist. create it"); +// _app.u.dump(" -> template does not exist. create it"); if($tag.children().length) { - app.u.dump(" -> tag has a child. create template: "+obj.loadsTemplate); - app.model.makeTemplate($("li:first",$tag),obj.loadsTemplate); + _app.u.dump(" -> tag has a child. create template: "+obj.loadsTemplate); + _app.model.makeTemplate($("li:first",$tag),obj.loadsTemplate); $('li:first',$tag).empty().remove(); //removes the product list 'template' which is part of the UL. } else { @@ -540,7 +570,6 @@ params that are missing will be auto-generated. $('#globalMessaging').anymessage({"message":"In store_prodlist.u.buildProductList, the parent declared 'useChildAsTemplate', but has no children. No template could be created. The product list will not render.","gMessage":true}); } } - } var plObj = this.setProdlistVars(obj); //full prodlist object now. @@ -548,7 +577,12 @@ params that are missing will be auto-generated. //need a jquery obj. to work with. if($tag) {$tag.attr('id',plObj.parentID);} else {$tag = $('#'+plObj.parentID);} -//a wrapper around all the prodlist content is created just one. Used in multipage to clear old multipage content. This allows for multiple multi-page prodlists on one page. Hey. it could happen. + + + $tag.data('pageProductLoaded',0); //used to count how many product have been loaded on this page (for prodlistComplete) + $tag.data('totalProductLoaded',0); //used to count how many product have been loaded for total count (for prodlistComplete) + +//a wrapper around all the prodlist content is created just once. Used in multipage to clear old multipage content. This allows for multiple multi-page prodlists on one page. Hey. it could happen. if($('#'+plObj.parentID+'_container').length == 0) { if($tag.is('tbody')) { $tag.closest('table').wrap("<div id='"+plObj.parentID+"_container' />"); @@ -559,7 +593,12 @@ params that are missing will be auto-generated. } //adds all the placeholders. must happen before getProductDataForList so individual product translation can occur. //can't just transmogrify beccause sequence is important and if some data is local and some isn't, order will get messed up. - $tag.append(this.getProdlistPlaceholders(plObj)).removeClass('loadingBG'); + +//***201352 Separating out the placeholders so that they can be used in getProductDataForList individually for the jqObj. +// Otherwise the callback tries to reference the placeholder by using the parentID, but in the case of anycontent +// when we already have the data, the placeholder is not yet on the DOM and then data is never rendered. -mc + plObj.placeholders = this.getProdlistPlaceholders(plObj); + $tag.append(plObj.placeholders).removeClass('loadingBG'); $tag.data('prodlist',plObj); //sets data object on parent if(!obj.hide_summary) { @@ -572,52 +611,17 @@ params that are missing will be auto-generated. $tag.after(this.showProdlistSummary(plObj,'footer')); //multipage Footer } } -//The timeout was here because of an issue where the placeholders were getting nuked. That issue was caused by translateTemplate doing a replace. -//that code was changed in 201239 (as was this function) so the timeout was commented out. This comment is here in case the change to translateFunction is changed back. -// setTimeout(function(){ - app.ext.store_prodlist.u.getProductDataForList(plObj,$tag,'mutable'); -// },1000); //will render individual product, if data already present or fetch data and render as part of response. - + _app.ext.store_prodlist.u.getProductDataForList(plObj,$tag,'mutable'); } else { - app.u.throwGMessage("WARNING: store_prodlist.u.buildProductList is missing some required fields. Obj follows: "); - app.u.dump(obj); + _app.u.throwGMessage("WARNING: store_prodlist.u.buildProductList is missing some required fields. Obj follows: "); + _app.u.dump(obj); } -// app.u.dump(" -> r = "+r); +// _app.u.dump(" -> r = "+r); }, //buildProductList -/* -This is executed when the page is changed in a prodlist. -initially, this was how product lists were handled, the the productList renderFormat was introduced. -need to remove duplicate code from this and the renderFormat. ### -*/ -/* - handleProductList : function(parentID) { - var r = 0; //returns the number of requests. -// app.u.dump("BEGIN app.ext.store_prodlist.u.handleProductList"); -// app.u.dump(" -> parent = "+parentID); - var $parent = $('#'+parentID).empty(); - var csvArray = new Array(); - if(app.ext.store_prodlist.vars[parentID].items_per_page >= app.ext.store_prodlist.vars[parentID].csv.length) { -// app.u.dump(' -> single page product list'); - csvArray = app.ext.store_prodlist.vars[parentID].csv - } - else { -//in a multipage format, just request the pids of the page in focus. -// app.u.dump(' -> multi page product list.'); - csvArray = app.ext.store_prodlist.vars[parentID].csv.slice(app.ext.store_prodlist.vars[parentID].page_start_point - 1,app.ext.store_prodlist.vars[parentID].page_end_point); - if(!app.ext.store_prodlist.vars[parentID].hide_summary) { - $('.mpControlContainer').empty().remove(); - $parent.before(app.ext.store_prodlist.u.showMPControls(parentID,'header')); - $parent.after(app.ext.store_prodlist.u.showMPControls(parentID,'footer')); - } - } -//now that we have our prodlist, get the product data and add it to the DOM. - r = app.ext.store_prodlist.u.getProductDataForList(csvArray,parentID); - return r; - }, -*/ + /* function is executed both from the next/previous buttons and list of page links. @@ -626,20 +630,21 @@ $pageTag is the jquery object of whatever was clicked. the data to be used is st */ mpJumpToPage : function($pageTag) { - -// app.u.dump("BEGIN app.ext.store_prodlist.u.mpJumpToPage"); - var targetList = $pageTag.closest('[data-targetlist]').attr('data-targetlist'); - var plObj = $('#'+targetList).data('prodlist'); + if($pageTag.attr('disabled') != 'disabled'){ +// _app.u.dump("BEGIN _app.ext.store_prodlist.u.mpJumpToPage"); + var targetList = $pageTag.closest('[data-targetlist]').attr('data-targetlist'); + var plObj = $('#'+targetList).data('prodlist'); //figure out what page to show next. //the multipage controls take care of enabling/disabling next/back buttons to ensure no 'next' appears/is clickable on last page. - if($pageTag.attr('data-role') == 'next') {plObj.page_in_focus += 1} - else if($pageTag.attr('data-role') == 'previous') {plObj.page_in_focus -= 1} - else {plObj.page_in_focus = $pageTag.attr('data-page')} + if($pageTag.attr('data-role') == 'next') {plObj.page_in_focus += 1} + else if($pageTag.attr('data-role') == 'previous') {plObj.page_in_focus -= 1} + else {plObj.page_in_focus = $pageTag.attr('data-page')} - $('.mpControlContainer','#'+plObj.parentID+'_container').empty().remove(); //clear all summary/multipage for this prodlist. - $('#'+plObj.parentID).empty(); //empty prodlist so new page gets clean data. - this.buildProductList(plObj); + $('.mpControlContainer','#'+plObj.parentID+'_container').empty().remove(); //clear all summary/multipage for this prodlist. + $('#'+plObj.parentID).empty(); //empty prodlist so new page gets clean data. + this.buildProductList(plObj); + } }, showProdlistSummary : function(plObj,location){ @@ -650,10 +655,16 @@ $pageTag is the jquery object of whatever was clicked. the data to be used is st if(plObj.hide_pagination === true) { } else { - $output = app.renderFunctions.transmogrify({'id':'mpControl_'+plObj.parentID+'_'+location,'targetList':plObj.parentID},'mpControlSpec',plObj); +// $output = _app.renderFunctions.transmogrify({'id':'mpControl_'+plObj.parentID+'_'+location,'targetList':plObj.parentID},'mpControlSpec',plObj); + $output = $("<div \/>"); + $output.tlc({ + 'templateid' : 'mpControlSpec', + 'dataset' : plObj, + 'dataAttribs' : {'id':'mpControl_'+plObj.parentID+'_'+location} + }) $output.find('.mpControlJumpToPage, .paging').click(function(){ - app.ext.store_prodlist.u.mpJumpToPage($(this)) - app.u.jumpToAnchor('mpControl_'+plObj.parentID+'_header'); + _app.ext.store_prodlist.u.mpJumpToPage($(this)) + _app.u.jumpToAnchor('mpControl_'+plObj.parentID+'_header'); }) $output.find('.paging').each(function(){ var $this = $(this) @@ -673,17 +684,17 @@ $pageTag is the jquery object of whatever was clicked. the data to be used is st //data saved into appProductGet so that it can be accessed from a product databind. helpful in prodlists where only summaries are needed. //NOTE - this function is also in store_product. probably ought to merge prodlist and product, as they're sharing more and more. summarizeReviews : function(pid) { -// app.u.dump("BEGIN store_product.u.summarizeReviews"); +// _app.u.dump("BEGIN store_product.u.summarizeReviews"); var L = 0; var sum = 0; var avg = 0; - if(typeof app.data['appReviewsList|'+pid] == 'undefined' || $.isEmptyObject(app.data['appReviewsList|'+pid]['@reviews'])) { + if(typeof _app.data['appReviewsList|'+pid] == 'undefined' || $.isEmptyObject(_app.data['appReviewsList|'+pid]['@reviews'])) { //item has no reviews or for whatver reason, data isn't available. } else { - L = app.data['appReviewsList|'+pid]['@reviews'].length; + L = _app.data['appReviewsList|'+pid]['@reviews'].length; for(var i = 0; i < L; i += 1) { - sum += Number(app.data['appReviewsList|'+pid]['@reviews'][i].RATING); + sum += Number(_app.data['appReviewsList|'+pid]['@reviews'][i].RATING); } avg = Math.round(sum/L); } diff --git a/extensions/store_product.js b/extensions/store_product.js index 7945ec10b..d63442d18 100755 --- a/extensions/store_product.js +++ b/extensions/store_product.js @@ -22,7 +22,7 @@ The functions here are designed to work with 'reasonable' size lists of categori */ -var store_product = function() { +var store_product = function(_app) { var r = { vars : {}, @@ -38,8 +38,8 @@ var store_product = function() { appProductGet : { init : function(pid,tagObj,Q) { var r = 0; //will return 1 if a request is needed. if zero is returned, all data needed was in local. -// app.u.dump("BEGIN app.ext.store_product.calls.appProductGet"); -// app.u.dump(" -> PID: "+pid); +// _app.u.dump("BEGIN _app.ext.store_product.calls.appProductGet"); +// _app.u.dump(" -> PID: "+pid); //datapointer must be added here because it needs to be passed into the callback. The callback could get executed before the ajax call (if in local). //if no object is passed in, one must be created so that adding datapointer to a non existent object doesn't cause a js error @@ -50,24 +50,24 @@ var store_product = function() { tagObj["datapointer"] = "appProductGet|"+pid; //fetchData checks the timestamp, so no need to doublecheck it here unless there's a need to make sure it is newer than what is specified (1 day) in the fetchData function - if(app.model.fetchData(tagObj.datapointer) == false) { -// app.u.dump(" -> appProductGet not in memory or local. refresh both."); + if(_app.model.fetchData(tagObj.datapointer) == false) { +// _app.u.dump(" -> appProductGet not in memory or local. refresh both."); r += 1; this.dispatch(pid,tagObj,Q) } - else if(typeof app.data[tagObj.datapointer]['@inventory'] == 'undefined' || typeof app.data[tagObj.datapointer]['@variations'] == 'undefined') { - app.u.dump(" -> either inventory or variations not in memory or local. get everything."); + else if(typeof _app.data[tagObj.datapointer]['@inventory'] == 'undefined' || typeof _app.data[tagObj.datapointer]['@variations'] == 'undefined') { + _app.u.dump(" -> either inventory or variations not in memory or local. get everything."); //check to make sure inventory and pog info is available. r += 1; this.dispatch(pid,tagObj,Q) } //if the product record is in memory BUT the inventory is zero, go get updated record in case it's back in stock. - else if(app.ext.store_product.u.getProductInventory(pid) === 0) { + else if(_app.ext.store_product.u.getProductInventory(_app.data[tagObj.datapointer]) === 0) { r += 1; this.dispatch(pid,tagObj,Q); } else { - app.u.handleCallback(tagObj) + _app.u.handleCallback(tagObj) } return r; }, @@ -77,11 +77,11 @@ var store_product = function() { obj["_cmd"] = "appProductGet"; obj["withVariations"] = 1; //only get inventory if it matters. inv_mode of 1 means inventory is not important. - if(app.vars.thisSessionIsAdmin || (typeof zGlobals == 'object' && zGlobals.globalSettings.inv_mode != 1)) + if(_app.u.thisIsAnAdminSession() || (typeof zGlobals == 'object' && zGlobals.globalSettings.inv_mode != 1)) obj["withInventory"] = 1; obj["pid"] = pid; obj["_tag"] = tagObj; - app.model.addDispatchToQ(obj,Q); + _app.model.addDispatchToQ(obj,Q); } }, //appProductGet @@ -92,23 +92,23 @@ var store_product = function() { appReviewsList : { init : function(pid,tagObj,Q) { var r = 0; //will return a 1 or a 0 based on whether the item is in local storage or not, respectively. -//app.u.dump("appReviewsList tagObj:"); -//app.u.dump(tagObj); +//_app.u.dump("appReviewsList tagObj:"); +//_app.u.dump(tagObj); pid = pid.toString().toUpperCase(); tagObj = $.isEmptyObject(tagObj) ? {} : tagObj; tagObj["datapointer"] = "appReviewsList|"+pid; - if(app.model.fetchData('appReviewsList|'+pid) == false) { + if(_app.model.fetchData('appReviewsList|'+pid) == false) { r = 1; this.dispatch(pid,tagObj,Q) } else { - app.u.handleCallback(tagObj) + _app.u.handleCallback(tagObj) } return r; }, dispatch : function(pid,tagObj,Q) { - app.model.addDispatchToQ({"_cmd":"appReviewsList","pid":pid,"_tag" : tagObj},Q); + _app.model.addDispatchToQ({"_cmd":"appReviewsList","pid":pid,"_tag" : tagObj},Q); } }//appReviewsList }, //calls @@ -127,14 +127,14 @@ var store_product = function() { //the callback is auto-executed as part of the extensions loading process. init : { onSuccess : function() { -// app.u.dump('BEGIN app.ext.store_product.init.onSuccess '); +// _app.u.dump('BEGIN _app.ext.store_product.init.onSuccess '); var r = true; //return false if extension won't load for some reason (account config, dependencies, etc). return r; }, onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN app.ext.store_product.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_product.callbacks.init.onError'); } } //init @@ -154,35 +154,36 @@ var store_product = function() { //this'll change going forward. addToCart : function (pid,$form){ -// app.u.dump("BEGIN store_product.validate.addToCart"); -// app.u.dump(" -> pid: "+pid); + _app.u.dump("BEGIN store_product.validate.addToCart. pid: "+pid); var valid = true; //what is returned. - if(pid && $form) { + if(pid && $form instanceof jQuery) { +// _app.u.dump(" -> have a pid and a valid $form."); //copied locally for quick reference. - var sogJSON = app.data['appProductGet|'+pid]['@variations'], - formJSON = $form.serializeJSON(); - - // app.u.dump('BEGIN validate_pogs. Formid ='+formId); + var + sogJSON = _app.u.thisNestedExists("data.appProductGet|"+pid+".@variations",_app) ? _app.data['appProductGet|'+pid]['@variations'] : {}, + formJSON = $form.serializeJSON(); + + // _app.u.dump('BEGIN validate_pogs. Formid ='+formId); if($.isEmptyObject(sogJSON)) { -// app.u.dump('no sogs present (or empty object)'); //valid. product may not have sogs. +// _app.u.dump('no sogs present (or empty object). this is valid, product may not have variations.'); } else if($.isEmptyObject(formJSON)) { -// app.u.throwGMessage("In store_product.validate.addToCart, formJSON is empty."); + _app.u.throwGMessage("In store_product.validate.addToCart, formJSON is empty."); } //this shouldn't be empty. if it is, likely $form not valid or on DOM. else { -// app.u.dump(" -> everything is accounted for. Start validating."); +// _app.u.dump(" -> everything is accounted for. Start validating."); $('.appMessage',$form).empty().remove(); //clear all existing errors/messages. var thisSTID = pid, //used to compose the STID for inventory lookup. inventorySogPrompts = '',//the prompts for sogs with inventory. used to report inventory messaging if inventory checks are performed errors = '', pogid, pogType; -// app.u.dump(" -> formJSON: "); app.u.dump(formJSON); +// _app.u.dump(" -> formJSON: "); _app.u.dump(formJSON); //No work to do if there are no sogs. if(sogJSON) { - // app.u.dump('got into the pogs-are-present validation'); + // _app.u.dump('got into the pogs-are-present validation'); for(var i = 0; i < sogJSON.length; i++) { pogid = sogJSON[i]['id']; //the id is used multiple times so a var is created to reduce number of lookups needed. pogType = sogJSON[i]['type']; //the type is used multiple times so a var is created to reduce number of lookups needed. @@ -214,33 +215,37 @@ addToCart : function (pid,$form){ } - // app.u.dump('past validation, before inventory validation. valid = '+valid); + _app.u.dump('past validation, before inventory validation. valid = '+valid); //if errors occured, report them. if(valid == false) { - // app.u.dump(errors); - var errObj = app.u.youErrObject("Uh oh! Looks like you left something out. Please make the following selection(s):<ul>"+errors+"<\/ul>",'42'); - errObj.parentID = 'JSONpogErrors_'+pid - app.u.throwMessage(errObj); + $form.anymessage({ + 'message' : 'It appears you left some required selections blank. Please make the following selection(s): <ul>'+errors+'<\/ul>', + 'errtype' : 'youerr' + }) } //if all options are selected AND checkinventory is on, do inventory check. - else if(valid == true && typeof zGlobals == 'object' && zGlobals.globalSettings.inv_mode > 1) { + else if(typeof zGlobals == 'object' && zGlobals.globalSettings.inv_mode > 1) { // alert(thisSTID); - if(!$.isEmptyObject(app.data['appProductGet|'+pid]['@inventory']) && !$.isEmptyObject(app.data['appProductGet|'+pid]['@inventory'][thisSTID]) && app.data['appProductGet|'+pid]['@inventory'][thisSTID]['inv'] < 1) { - var errObj = app.u.youErrObject("We're sorry, but the combination of selections you've made is not available. Try changing one of the following:<ul>"+inventorySogPrompts+"<\/ul>",'42'); + if(!$.isEmptyObject(_app.data['appProductGet|'+pid]['@inventory']) && !$.isEmptyObject(_app.data['appProductGet|'+pid]['@inventory'][thisSTID]) && _app.data['appProductGet|'+pid]['@inventory'][thisSTID]['inv'] < 1) { + var errObj = _app.u.youErrObject("We're sorry, but the combination of selections you've made is not available. Try changing one of the following:<ul>"+inventorySogPrompts+"<\/ul>",'42'); errObj.parentID = 'JSONpogErrors_'+pid - app.u.throwMessage(errObj); + _app.u.throwMessage(errObj); valid = false; } } + else {} } } + else if($form instanceof jQuery) { + $form.anymessage({'message':'In store_product.validate.addToCart, pid was not passed','gMessage':true}); + } else { - app.u.throwGMessage("in store_product.validate.addToCart, either pid ("+pid+") not set or $form was not passed."); + _app.u.throwGMessage("in store_product.validate.addToCart, either pid ("+pid+") not set or $form was not passed."); valid = false; } -// app.u.dump('STID = '+thisSTID); +// _app.u.dump('STID = '+thisSTID); return valid; } //validate.addToCart @@ -266,60 +271,62 @@ addToCart : function (pid,$form){ //creates some required form inputs. //the ID on the product_id input should NOT be changed without updating the addToCart call (which uses this id to obtain the pid). - atcForm : function($tag,data) { + atcform : function($tag,data) { $tag.append("<input type='hidden' name='sku' value='"+data.value+"' />"); }, - reviewList : function($tag,data) { -// app.u.dump("BEGIN store_product.renderFormats.reviewList"); + reviewlist : function($tag,data) { +// _app.u.dump("BEGIN store_product.renderFormats.reviewList"); var templateID = data.bindData.loadsTemplate; -// app.u.dump(data.value) +// _app.u.dump(data.value) var L = data.value.length; for(var i = 0; i < L; i += 1) { - $tag.append(app.renderFunctions.transmogrify({'id':'review_'+i},templateID,data.value[i])); + $tag.append(_app.renderFunctions.transmogrify({'id':'review_'+i},templateID,data.value[i])); } return L; }, - quantityDiscounts : function($tag,data) { -// app.u.dump("BEGIN store_product.renderFormats.quantityDiscounts"); -// app.u.dump("value: "+data.value); + quantitydiscounts : function($tag,data) { +// _app.u.dump("BEGIN store_product.renderFormats.quantityDiscounts"); +// _app.u.dump("value: "+data.value); var o = ''; //what is output; - - var dArr = data.value.split(','); - var tmp,num; - var L = dArr.length; -//## operator can be either / or = (5=125 means buy 5 @ $125ea., 5/125 means buy 5 @ $25ea.) - for(var i = 0; i < L; i += 1) { - if(dArr[i].indexOf('=') > -1) { -// app.u.dump(' -> treat as ='); - tmp = dArr[i].split('='); - if(tmp[1].indexOf('$') >= 0){tmp[1] = tmp[1].substring(1)} //strip $, if present -// app.u.dump(" -> tmp[1] = "+tmp[1]); - o += "<div>buy "+tmp[0]+"+ for "+app.u.formatMoney(Number(tmp[1]),'$','')+" each<\/div>"; //test gss COR6872 - } - else if(dArr[i].indexOf('/') > -1) { -// app.u.dump(' -> treat as /'); - tmp = dArr[i].split('/'); - o += "<div>buy "+tmp[0]+"+ for "; - if(tmp[1].indexOf('$') >= 0){tmp[1] = tmp[1].substring(1)} //strip $, if present -// app.u.dump(" -> tmp[1] = "+tmp[1]); - num = Number(tmp[1]) / Number(tmp[0]) -// app.u.dump(" -> number = "+num); - o += app.u.formatMoney(num,'$','') //test spork 1000 - o += " each<\/div>"; - } - else { - app.u.dump("WARNING! invalid value for qty discount. Contained neither a '/' or an '='."); + if(data.value) { + var dArr = data.value.split(','); + var tmp,num; + var L = dArr.length; + //## operator can be either / or = (5=125 means buy 5 @ $125ea., 5/125 means buy 5 @ $25ea.) + // sample data: 2/$30,4/$20,10=$3.50 + for(var i = 0; i < L; i += 1) { + if(dArr[i].indexOf('=') > -1) { + // _app.u.dump(' -> treat as ='); + tmp = dArr[i].split('='); + if(tmp[1].indexOf('$') >= 0){tmp[1] = tmp[1].substring(1)} //strip $, if present + // _app.u.dump(" -> tmp[1] = "+tmp[1]); + o += "<div>buy "+tmp[0]+"+ for "+_app.u.formatMoney(Number(tmp[1]),'$','')+" each<\/div>"; //test gss COR6872 + } + else if(dArr[i].indexOf('/') > -1) { + // _app.u.dump(' -> treat as /'); + tmp = dArr[i].split('/'); + o += "<div>buy "+tmp[0]+"+ for "; + if(tmp[1].indexOf('$') == 0){tmp[1] = tmp[1].substring(1)} //strip $, if present +// _app.u.dump(" -> tmp[1] = "+tmp[1]); + num = Number(tmp[1]) / Number(tmp[0]) + // _app.u.dump(" -> number = "+num); + o += _app.u.formatMoney(num,'$','') //test spork 1000 + o += " each<\/div>"; + } + else { + _app.u.dump("WARNING! invalid value for qty discount. Contained neither a '/' or an '='."); + } + tmp = ''; //reset after each loop. } - tmp = ''; //reset after each loop. + $tag.append("<div class='marginBottom'>"+o+"<\/div>").prepend("<h3>Quantity Discounts: <\/h3>"); } - $tag.append(o); }, - simpleInvDisplay : function($tag,data) { + simpleinvdisplay : function($tag,data) { //data.value = available inventory -// app.u.dump("BEGIN store_product.renderFunctions.invAvail."); +// _app.u.dump("BEGIN store_product.renderFunctions.invAvail."); if(data.value > 0) $tag.addClass('instock').append("In Stock"); else @@ -327,20 +334,20 @@ addToCart : function (pid,$form){ }, //data.value should be entire product object. - detailedInvDisplay : function($tag,data) { + detailedinvdisplay : function($tag,data) { var pid = data.value.pid; if(pid && data.value['@inventory'] && data.value['@inventory'][pid]) { $tag.append("<div>Available Inventory: "+data.value['@inventory'][pid].inv+"<\/div>"); } else if(pid && data.value['@inventory']) { var inventory = data.value['@inventory'], - vlt = app.ext.store_product.u.buildVariationLookup(data.value['@variations']), //variation lookup table. + vlt = _app.ext.store_product.u.buildVariationLookup(data.value['@variations']), //variation lookup table. $table = $("<table class='gridTable fullWidth marginBottom' \/>"); $table.append("<thead><tr><th class='alignLeft'>Variation<\/th><th class='alignRight'>Inv. Available<\/th><\/tr>"); for(var index in inventory) { // var pretty = vlt[index.split(':')[1].substr[0,2]]; // pretty += - $table.append("<tr><td>"+app.ext.store_product.u.inventoryID2Pretty(index,vlt)+"<\/td><\/tr>"); + $table.append("<tr><td>"+_app.ext.store_product.u.inventoryID2Pretty(index,vlt)+"<\/td><\/tr>"); } $table.appendTo($tag); $table.anytable(); @@ -348,13 +355,13 @@ addToCart : function (pid,$form){ else { $tag.append("Unable to determine inventory count"); } - }, //detailedInvDisplay + }, //detailedinvdisplay //add all the necessary fields for quantity inputs. - atcQuantityInput : function($tag,data) { + atcquantityinput : function($tag,data) { var $input = $("<input \/>",{'name':'qty'}); - if(app.ext.store_product.u.productIsPurchaseable(data.value.pid)) { - $input.attr({'size':3,'min':0,'step':1,'type':'number'}).appendTo($tag); + if(_app.ext.store_product.u.productIsPurchaseable(data.value.pid)) { + $input.attr({'size':3,'min':0,'step':1,'type':'number'}).addClass('numberInput').appendTo($tag); $input.on('keyup.classChange',function(){ if(Number($(this).val()) > 0){$(this).addClass('qtyChanged ui-state-highlight');} }); @@ -364,7 +371,7 @@ addToCart : function (pid,$form){ $input.attr({'type':'hidden'}).appendTo($tag); //add so that handleaddtocart doesn't throw error that no qty input is present } //set this. because the name is shared by (potentially) a lot of inputs, the browser 'may' use the previously set value (like if you add 1 then go to another page, all the inputs will be set to 1. bad in a prodlist format) - $input.val(data.bindData.defaultValue || 0); + $input.val(data.bindData.defaultvalue || 0); }, @@ -372,22 +379,22 @@ addToCart : function (pid,$form){ // in this case, we aren't modifying an attribute of $tag, we're appending to it. a lot. //this code requires the includes.js file. //it loops through the products options and adds them to the fieldset (or whatever $tag is, but a fieldset is a good idea). - atcVariations : function($tag,data) { -// app.u.dump("BEGIN store_product.renderFormats.atcVariations"); + atcvariations : function($tag,data) { +// _app.u.dump("BEGIN store_product.renderFormats.atcvariations"); var pid = data.value; var formID = $tag.closest('form').attr('id'); //move up the dom tree till the parent form is found $tag.empty(); /* prodlist fix */ -// app.u.dump(" -> pid: "+pid); -// app.u.dump(" -> formID: "+formID); +// _app.u.dump(" -> pid: "+pid); +// _app.u.dump(" -> formID: "+formID); - if(app.ext.store_product.u.productIsPurchaseable(pid)) { -// app.u.dump(" -> item is purchaseable."); - if(!$.isEmptyObject(app.data['appProductGet|'+pid]['@variations']) && app.model.countProperties(app.data['appProductGet|'+pid]['@variations']) > 0) { + if(_app.ext.store_product.u.productIsPurchaseable(pid)) { +// _app.u.dump(" -> item is purchaseable."); + if(!$.isEmptyObject(_app.data['appProductGet|'+pid]['@variations']) && _app.model.countProperties(_app.data['appProductGet|'+pid]['@variations']) > 0) { $("<div \/>").attr('id','JSONpogErrors_'+pid).addClass('zwarn').appendTo($tag); var $display = $("<div \/>"); //holds all the pogs and is appended to at the end. -pogs = new handlePogs(app.data['appProductGet|'+pid]['@variations'],{"formId":formID,"sku":pid}); +pogs = new handlePogs(_app.data['appProductGet|'+pid]['@variations'],{"formId":formID,"sku":pid}); var pog; if(typeof pogs.xinit === 'function') {pogs.xinit()} //this only is needed if the class is being extended (custom sog style). var ids = pogs.listOptionIDs(); @@ -398,7 +405,7 @@ for ( var i=0, len=ids.length; i<len; ++i) { $display.appendTo($tag); } else { -// app.u.dump(" -> @variations is empty."); +// _app.u.dump(" -> @variations is empty."); } } @@ -407,12 +414,11 @@ $display.appendTo($tag); //will remove the add to cart button if the item is not purchaseable. - addToCartButton : function($tag,data) { -// app.u.dump("BEGIN store_product.renderFunctions.addToCartButton"); -// app.u.dump(" -> ID before any manipulation: "+$tag.attr('id')); + addtocartbutton : function($tag,data) { +// _app.u.dump("BEGIN store_product.renderFunctions.addtocartbutton"); dump(data.value); var pid = data.value; - var pData = app.data['appProductGet|'+pid]; - if(app.ext.store_product.u.productIsPurchaseable(pid)) { + var pData = _app.data['appProductGet|'+pid]; + if(_app.ext.store_product.u.productIsPurchaseable(pid)) { if(pData && pData['%attribs'] && pData['%attribs']['is:preorder']) { $tag.addClass('preorderButton').text('value', 'Preorder'); } @@ -425,8 +431,8 @@ $display.appendTo($tag); $tag.hide().addClass('displayNone').before("<span class='notAvailableForPurchase'>This item is not available for purchase<\/span>"); //hide button, item is not purchaseable. } -// app.u.dump(" -> ID at end: "+$tag.attr('id')); - } //addToCartButton +// _app.u.dump(" -> ID at end: "+$tag.attr('id')); + } //addtocartbutton }, @@ -442,36 +448,55 @@ it is a parent it has no inventory AND inventory matters to merchant */ productIsPurchaseable : function(pid) { -// app.u.dump("BEGIN store_product.u.productIsPurchaseable"); - var r = true; //returns true if purchaseable, false if not or error. - if(!pid) { - app.u.dump("ERROR! pid not passed into store_product.u.productIsPurchaseable"); - r = false; - } - else if(app.data['appProductGet|'+pid]['%attribs']['zoovy:base_price'] == '') { -// app.u.dump(" -> base price not set: "+pid); - r = false; - } - else if(app.data['appProductGet|'+pid]['%attribs']['zoovy:grp_type'] == 'PARENT') { -// app.u.dump(" -> product is a parent: "+pid); - r = false; - } -//inventory mode of 1 will allow selling more than what's in stock, so skip any inv validating if == 1. - else if(typeof zGlobals == 'object' && zGlobals.globalSettings.inv_mode != 1) { -//if a product has no options, the inventory record looks like this: -//["appProductGet|PID"]["@inventory"].PID.inv where both instances of PID are subbed with the product id -// ex: app.data["appProductGet|"+PID]["@inventory"][PID].inv -// also avail is ...[PID].res (reserved) - if(typeof app.data['appProductGet|'+pid]['@inventory'] === 'undefined' || typeof app.data['appProductGet|'+pid]['@variations'] === 'undefined') { - app.u.dump(" -> inventory ("+typeof app.data['appProductGet|'+pid]['@inventory']+") and/or variations ("+typeof app.data['appProductGet|'+pid]['@variations']+") object(s) not defined."); - r = false; +// _app.u.dump("BEGIN store_product.u.productIsPurchaseable"); + var + r = true, //returns true if purchaseable, false if not or error. + prodData; + + + if(pid) { + if(_app.u.thisNestedExists("data.adminProductGet|"+pid,_app)) { + prodData = _app.data['adminProductGet|'+pid]; } else { - if(app.ext.store_product.u.getProductInventory(pid) <= 0) { - app.u.dump(" -> inventory not available: "+pid); - r = false + prodData = _app.data['appProductGet|'+pid]; + } + + if(prodData) { + if(prodData['%attribs']['zoovy:base_price'] == '') { + _app.u.dump(" -> not purchaseable because base price not set: "+pid); + r = false; + } + else if(prodData['%attribs']['zoovy:grp_type'] == 'PARENT') { + _app.u.dump(" -> not purchaseable because product is a parent: "+pid); + r = false; + } + //inventory mode of 1 will allow selling more than what's in stock, so skip any inv validating if == 1. + else if(typeof zGlobals == 'object' && zGlobals.globalSettings.inv_mode != 1) { + //if a product has no options, the inventory record looks like this: + //["appProductGet|PID"]["@inventory"].PID.inv where both instances of PID are subbed with the product id + // ex: _app.data["appProductGet|"+PID]["@inventory"][PID].inv + // also avail is ...[PID].res (reserved) + if(typeof prodData['@inventory'] === 'undefined' || typeof prodData['@variations'] === 'undefined') { + _app.u.dump(" -> not purchaseable because inventory ("+typeof prodData['@inventory']+") and/or variations ("+typeof prodData['@variations']+") object(s) not defined."); + r = false; + } + else { + if(_app.ext.store_product.u.getProductInventory(prodData) <= 0) { + _app.u.dump(" -> not purchaseable because inventory not available: "+pid); + r = false + } + } } } + else { + _app.u.dump("ERROR! could not find product data in memory for store_product.u.productIsPurchaseable"); + r = false; + } + } + else { + _app.u.dump("ERROR! pid not passed into store_product.u.productIsPurchaseable"); + r = false; } return r; }, //productIsPurchaseable @@ -493,7 +518,7 @@ it has no inventory AND inventory matters to merchant } } else { - app.u.dump("WARNING! in store_product.u.buildVariationLookup, variations was empty."); + _app.u.dump("WARNING! in store_product.u.buildVariationLookup, variations was empty."); } return r; }, @@ -506,12 +531,12 @@ it has no inventory AND inventory matters to merchant var splitID = ID.split(':'), L = splitID.length; for(var i = 1; i < L; i += 1) { -// app.u.dump(" -> splitID[i].substr(0,2): "+splitID[i].substr(0,2)); +// _app.u.dump(" -> splitID[i].substr(0,2): "+splitID[i].substr(0,2)); r += VLT[splitID[i].substr(0,2)][splitID[i].substr(2,2)]+" "; } } else { - app.u.dump("In store_product.u.inventoryID2Pretty, ID or VLT not defined"); + _app.u.dump("In store_product.u.inventoryID2Pretty, ID or VLT not defined"); r = false; } return r; @@ -522,34 +547,34 @@ it has no inventory AND inventory matters to merchant //checks to make sure no blanks, undefined or null pids go through getProductDataForLaterUse : function(csv,Q) { var r = 0; //what's returned. # of requests -// app.u.dump("BEGIN store_product.u.getProductDataForLaterUse"); -// app.u.dump(csv); +// _app.u.dump("BEGIN store_product.u.getProductDataForLaterUse"); +// _app.u.dump(csv); var L = csv.length; for(var i = 0; i < L; i += 1) { - if(app.u.isSet(csv[i])) {r += app.ext.store_product.calls.appProductGet.init(csv[i],{},Q)} + if(_app.u.isSet(csv[i])) {r += _app.ext.store_product.calls.appProductGet.init(csv[i],{},Q)} } -// app.u.dump(" -> getProdDataForLaterUser numRequests: "+r); +// _app.u.dump(" -> getProdDataForLaterUser numRequests: "+r); return r; }, //getProductDataForList //will return 0 if no inventory is available. //otherwise, will return the items inventory or, if variations are present, the sum of all inventoryable variations. //basically, a simple check to see if the item has purchaseable inventory. - getProductInventory : function(pid) { -// app.u.dump("BEGIN store_product.u.getProductInventory ["+pid+"]"); + getProductInventory : function(prodData) { +// _app.u.dump("BEGIN store_product.u.getProductInventory ["+pid+"]"); var inv = false; //if variations are NOT present, inventory count is readily available. - if(app.data['appProductGet|'+pid]) { - if((app.data['appProductGet|'+pid]['@variations'] && $.isEmptyObject(app.data['appProductGet|'+pid]['@variations'])) && !$.isEmptyObject(app.data['appProductGet|'+pid]['@inventory'])) { - inv = Number(app.data['appProductGet|'+pid]['@inventory'][pid].inv); - // app.u.dump(" -> item has no variations. inv = "+inv); + if(!$.isEmptyObject(prodData)) { + if((prodData['@variations'] && $.isEmptyObject(prodData['@variations'])) && !$.isEmptyObject(prodData['@inventory'])) { + inv = Number(prodData['@inventory'][prodData.pid].AVAILABLE); + // _app.u.dump(" -> item has no variations. inv = "+inv); } //if variations ARE present, inventory must be summed from each inventory-able variation. else { - for(var index in app.data['appProductGet|'+pid]['@inventory']) { - inv += Number(app.data['appProductGet|'+pid]['@inventory'][index].inv) + for(var index in prodData['@inventory']) { + inv += Number(prodData['@inventory'][index].AVAILABLE) } - // app.u.dump(" -> item HAS variations. inv = "+inv); + // _app.u.dump(" -> item HAS variations. inv = "+inv); } } else {} //cant get inventory without a product record. @@ -577,24 +602,24 @@ NOTES P.width = P.width ? P.width : 600; P.height = P.height ? P.height : 660; - var $parent = $(app.u.jqSelector('#',parentID)); + var $parent = $(_app.u.jqSelector('#',parentID)); //parent may not exist. empty if it does, otherwise create it. if($parent.length) {$parent.empty()} else {$parent = $("<div \/>").attr({"id":parentID,"title":"Product Images"}).appendTo('body');} if(P.templateID) { - $parent.append(app.renderFunctions.createTemplateInstance(P.templateID,"imageViewer_"+parentID)); - app.renderFunctions.translateTemplate(app.data["appProductGet|"+P.pid],"imageViewer_"+parentID); + $parent.append(_app.renderFunctions.createTemplateInstance(P.templateID,"imageViewer_"+parentID)); + _app.renderFunctions.translateTemplate(_app.data["appProductGet|"+P.pid],"imageViewer_"+parentID); } else { - $parent.append(app.u.makeImage({"class":"imageViewerSoloImage","h":"550","w":"550","bg":"ffffff","name":app.data['appProductGet|'+P.pid]['%attribs'][imageAttr],"tag":1})); + $parent.append(_app.u.makeImage({"class":"imageViewerSoloImage","h":"550","w":"550","bg":"ffffff","name":_app.data['appProductGet|'+P.pid]['%attribs'][imageAttr],"tag":1})); } $parent.dialog({modal: true,width:P.width ,height:P.height}); - $parent.dialog('option', 'title', app.data["appProductGet|"+P.pid]['%attribs']['zoovy:prod_name']); //proper way to set title. otherwise doesn't update after first dialog is opened. + $parent.dialog('option', 'title', _app.data["appProductGet|"+P.pid]['%attribs']['zoovy:prod_name']); //proper way to set title. otherwise doesn't update after first dialog is opened. $parent.dialog('open'); //here to solve an issue where the modal would only open once. } else { - app.u.dump(" -> no pid specified for image viewer. That little tidbit is required."); + _app.u.dump(" -> no pid specified for image viewer. That little tidbit is required."); } }, //showPicsInModal @@ -611,6 +636,7 @@ NOTES - if you pass a parentID, it is your responsibility to empty that parent, if needed. */ prodDataInModal : function(P) { +// dump("BEGIN prodDataInModal"); if(P.pid && P.templateID) { var $parent = $("#product-modal"); @@ -620,102 +646,117 @@ NOTES $parent = $("<div \/>").attr({"id":'product-modal',"title":""}).appendTo('body'); $parent.dialog({modal: true,width:'86%',height:$(window).height() - 100,autoOpen:false}); } +//In the handleTemplateEvents execution, the template instance is 'found'. The init, complete and depart events are NOT on $parent, they're on the template instance. + $parent.dialog('option','close',function(){ +// dump(" -> GOT into the option close callback."); dump(P); + P.state = 'depart'; + _app.renderFunctions.handleTemplateEvents($parent.find("[data-templateid='"+P.templateID+"']:first"),P); + }); - - $parent.dialog('open'); - - app.ext.store_product.calls.appProductGet.init(P.pid,{'callback': function(rd){ - if(app.model.responseHasErrors(rd)){ +// $parent.dialog('open').append(_app.renderFunctions.createTemplateInstance(P.templateID,P)); + $parent.dialog('open').append(new tlc().getTemplateInstance(P.templateID).attr('data-pid',P.pid)); + P.state = 'init'; + _app.renderFunctions.handleTemplateEvents($parent.find("[data-templateid='"+P.templateID+"']:first"),P); + _app.ext.store_product.calls.appProductGet.init(P.pid,{'callback': function(rd){ + if(_app.model.responseHasErrors(rd)){ $parent.anymessage({'message':rd}); } else { - $parent.dialog( "option", "title", app.data["appProductGet|"+P.pid]['%attribs']['zoovy:prod_name'] ); - $parent.anycontent({'templateID':P.templateID,'datapointer':"appProductGet|"+P.pid}); + $parent.dialog( "option", "title", _app.data["appProductGet|"+P.pid]['%attribs']['zoovy:prod_name'] ); + $parent.tlc({'templateid':P.templateID,'verb':'translate','datapointer':"appProductGet|"+P.pid}); + _app.u.handleCommonPlugins($parent); + P.state = 'complete'; + _app.renderFunctions.handleTemplateEvents($parent.find("[data-templateid='"+P.templateID+"']:first"),P); } }}); - app.ext.store_product.calls.appReviewsList.init(P.pid); // - app.model.dispatchThis(); - + _app.ext.store_product.calls.appReviewsList.init(P.pid); // + _app.model.dispatchThis(); + _app.u.handleCommonPlugins($parent); } else { - app.u.dump(" -> pid ("+P.pid+") or templateID ("+P.templateID+") not set for viewer. both are required."); + _app.u.dump(" -> pid ("+P.pid+") or templateID ("+P.templateID+") not set for viewer. both are required."); } return P; }, //prodDataInModal - showProductDataIn : function(targetID,P) { if(targetID && P && P.pid && P.templateID) { - var $target = $(app.u.jqSelector('#',targetID)); + var $target = $(_app.u.jqSelector('#',targetID)); if($target.length) { - app.u.dump(""); + _app.u.dump(""); //make sure the ID is unique in case this function is used to add product to dom twice (in different locations) - P.id = 'prodView_'+P.pid+'_'+app.u.guidGenerator().substring(0,10); - $target.append(app.renderFunctions.createTemplateInstance(P.templateID,P)); + P.id = 'prodView_'+P.pid+'_'+_app.u.guidGenerator().substring(0,10); + $target.append(_app.renderFunctions.createTemplateInstance(P.templateID,P)); P.callback = P.callback || 'translateTemplate'; //translateTemplate is part of controller, not an extension P.extension = P.extension || ''; //translateTemplate is part of controller, not an extension P.parentID = targetID; - app.ext.store_product.calls.appProductGet.init(P.pid,P); - app.ext.store_product.calls.appReviewsList.init(P.pid); - app.model.dispatchThis(); + _app.ext.store_product.calls.appProductGet.init(P.pid,P); + _app.ext.store_product.calls.appReviewsList.init(P.pid); + _app.model.dispatchThis(); } else { - app.u.throwGMessage("In store_product.u.showProductDataIn, $('#"+targetID+"') does not exist on the DOM"); + _app.u.throwGMessage("In store_product.u.showProductDataIn, $('#"+targetID+"') does not exist on the DOM"); } } else { - app.u.throwGMessage("In store_product.u.showProductDatIn, targetID ["+targetID+"] not set or required params (pid,templateID) not set. see console for params obj."); - app.u.dump(P); + _app.u.throwGMessage("In store_product.u.showProductDatIn, targetID ["+targetID+"] not set or required params (pid,templateID) not set. see console for params obj."); + _app.u.dump(P); } }, //showProductDataIn +//SANITY -> if multiple carts are in use, make sure that _cartid is part of $form as a hidden input. buildCartItemAppendObj : function($form) { - var obj = false; //what is returned. either the obj or false. - if($form && $form.is('form')) { + var obj = false; //what is returned. either the obj or false. returning false will prevent the addItemToCart from dispatching calls + if($form instanceof jQuery && $form.length) { var $qtyInput = $("input[name='qty']",$form), sku = $("input[name='sku']",$form).val(); - if(sku && $qtyInput.val() >= 1) { - obj = $form.serializeJSON(); - app.u.dump(" -> buildCartItemAppendObj into sku/qtyInput section"); -//here for the admin side of things. Will have no impact on retail as price can't be set. -//should always occur, validating or not. - if(obj.price == "") {delete obj.price; app.u.dump("Deleting price");} - else{} - -//There are use cases for skipping validation, such as admin, quick order, etc. - if($form.data('skipvalidation') || app.ext.store_product.validate.addToCart(sku,$form)) { - - obj['%variations'] = {}; - - for(var index in obj) { - // app.u.dump(" -> index: "+index); - //move variations into the %variaitons object. this isn't 100% reliable, but there isn't much likelyhood of non-variations 2 character inputs that are all uppercase. - //pids must be longer and qty (the other supported input) won't conflict. - if(index.length == 2 && index.toUpperCase() == index) { - obj['%variations'][index] = obj[index]; - delete obj[index]; + if(sku && $qtyInput.length) { + if($qtyInput.val() >= 1) { + obj = $form.serializeJSON(); + _app.u.dump(" -> buildCartItemAppendObj into sku/qtyInput section"); + //here for the admin side of things. Will have no impact on retail as price can't be set. + //should always occur, validating or not. + if(obj.price == "") {delete obj.price; _app.u.dump("Deleting price");} + else{} + //The sku could be a fully qualified sku (ex: PRODUCTID:AOOO:A112:ABThis is the value). + //just add these to the obj and the loop a little further down will format them properly into the %variations object. + if(sku.indexOf(':') >= -1) { + var skuArr = sku.split(':'); + obj.sku = skuArr[0]; + for(var i = 1; i < skuArr.length; i += 1) { + obj[skuArr[i].substring(0,2)] = skuArr[i].substr(2); } } - + //There are use cases for skipping validation, such as admin, quick order, etc. + if($form.data('skipvalidation') || _app.ext.store_product.validate.addToCart(sku,$form)) { + obj['%variations'] = {}; + for(var index in obj) { +//move variations into the %variaitons object. this isn't 100% reliable, but there isn't much likelyhood of non-variations 2 character inputs that are all uppercase. +//pids must be longer and qty (the other supported input) won't conflict. + if(index.length == 2 && index.toUpperCase() == index) { + obj['%variations'][index] = obj[index]; + delete obj[index]; + } + } + } + else { + obj = false; + //the validation itself will display the errors. + } } else { -// ** 201318 returning false will prevent the addItemToCart from dispatching calls - obj = false; - //the validation itself will display the errors. + $form.anymessage({'message':'Please select a quantity of at least 1'}) } } else { -// ** 201318 returning false will prevent the addItemToCart from dispatching calls obj = false; $form.anymessage({'message':'The form for store_product.u.handleAddToCart was either missing a sku ['+sku+'] or qty input ['+$qtyInput.length+'].','gMessage':true}); } - } else { -// ** 201318 returning false will prevent the addItemToCart from dispatching calls obj = false; - $('#globalMessaging').anymessage({'message':'In store_product.u.buildCartItemAppendObj, $form not passed.','gMessage':true}); + $('#globalMessaging').anymessage({'message':'In store_product.u.buildCartItemAppendObj, $form was not a valid jquery instance ['+($form instanceof jQuery)+'] or had no length ['+$form.length+'].','gMessage':true}); } return obj; }, //buildCartItemAppendObj @@ -723,23 +764,25 @@ NOTES //a no frills add to cart. returns false unless a dispatch occurs, then true. handleAddToCart : function($form,_tag) { var r = false; //what is returned. True if a dispatch occurs. - app.u.dump("BEGIN store_product.u.handleAddToCart"); - if($form && $form.length && $form.is('form')) { - var cartObj = app.ext.store_product.u.buildCartItemAppendObj($form); +// _app.u.dump("BEGIN store_product.u.handleAddToCart"); +// SANITY -> don't 'require' $form to be a form. It could be a fieldset or some other container as part of a bigger form (such as order create). + if($form instanceof jQuery) { + var cartObj = _app.ext.store_product.u.buildCartItemAppendObj($form); if(cartObj) { -// app.u.dump(" -> have a valid cart object"); app.u.dump(cartObj); +// _app.u.dump(" -> have a valid cart object"); _app.u.dump(cartObj); if(cartObj) { r = true; - app.calls.cartItemAppend.init(cartObj,_tag || {},'immutable'); - app.model.dispatchThis('immutable'); + _app.ext.cco.calls.cartItemAppend.init(cartObj,_tag || {},'immutable'); + _app.model.dispatchThis('immutable'); + cartMessagePush(cartObj._cartid,'cart.itemAppend',_app.u.getWhitelistedObject(cartObj,['sku','pid','qty','quantity','%variations'])); } } else { - app.u.dump(" -> cart object is not valid"); + _app.u.dump(" -> cart object is not valid"); } //do nothing, the validation handles displaying the errors. } else { - $('#globalMessaging').anymessage({'message':"In store_product.u.handleAddToCart, $form ["+typeof $form+"] not set, has no length ["+$form.length+"] or is not a form ["+$form.is('form')+"].",'gMessage':true}); + $('#globalMessaging').anymessage({'message':"In store_product.u.handleAddToCart, $form is not an instanceof jQuery.",'gMessage':true}); } return r; }, //handleAddToCart @@ -747,20 +790,20 @@ NOTES //$FP should be a form's parent element. Can contain 1 or several forms. handleBulkAddToCart : function($FP,_tag) { - app.u.dump("BEGIN store_product.u.handleBulkAddToCart"); + _app.u.dump("BEGIN store_product.u.handleBulkAddToCart"); if(typeof $FP == 'object') { var $forms = $('form',$FP); - app.u.dump(" -> $forms.length: "+$forms.length); +// _app.u.dump(" -> $forms.length: "+$forms.length); _tag = _tag || {}; if($forms.length) { $forms.each(function(){ - var cartObj = app.ext.store_product.u.buildCartItemAppendObj($(this)); //handles error display. + var cartObj = _app.ext.store_product.u.buildCartItemAppendObj($(this)); //handles error display. if(cartObj) { - app.calls.cartItemAppend.init(cartObj,_tag,'immutable'); + _app.ext.cco.calls.cartItemAppend.init(cartObj,_tag,'immutable'); } }); - app.model.dispatchThis('immutable'); + _app.model.dispatchThis('immutable'); } else { $('#globalMessaging').anymessage({'message':'handleAddToCart requires $FP to contain at least 1 form.','gMessage':true}); @@ -775,17 +818,17 @@ NOTES //data saved into appProductGet so that it can be accessed from a product databind. helpful in prodlists where only summaries are needed. //NOTE - this function is also in store_prodlist. probably ought to merge prodlist and product, as they're sharing more and more. summarizeReviews : function(pid) { -// app.u.dump("BEGIN store_product.u.summarizeReviews"); +// _app.u.dump("BEGIN store_product.u.summarizeReviews"); var L = 0; var sum = 0; var avg = 0; - if(typeof app.data['appReviewsList|'+pid] == 'undefined' || $.isEmptyObject(app.data['appReviewsList|'+pid]['@reviews'])) { + if(typeof _app.data['appReviewsList|'+pid] == 'undefined' || $.isEmptyObject(_app.data['appReviewsList|'+pid]['@reviews'])) { //item has no reviews or for whatver reason, data isn't available. } else { - L = app.data['appReviewsList|'+pid]['@reviews'].length; + L = _app.data['appReviewsList|'+pid]['@reviews'].length; for(var i = 0; i < L; i += 1) { - sum += Number(app.data['appReviewsList|'+pid]['@reviews'][i].RATING); + sum += Number(_app.data['appReviewsList|'+pid]['@reviews'][i].RATING); } avg = Math.round(sum/L); } diff --git a/extensions/store_routing.js b/extensions/store_routing.js new file mode 100644 index 000000000..3fe084134 --- /dev/null +++ b/extensions/store_routing.js @@ -0,0 +1,286 @@ +/* ************************************************************** + + Copyright 2013 Zoovy, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +************************************************************** */ + + + + +var store_routing = function(_app) { + var theseTemplates = new Array(''); + var r = { + + +//////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + + + callbacks : { + init : { + onSuccess : function() { + var r = false; + + if(_app.u.getParameterByName('seoRequest')){ + _app.vars.showContentHashChange = true; + _app.vars.ignoreHashChange = true; + } + + + _app.router.addAlias('homepage', function(routeObj){showContent('homepage', routeObj.params);}); + _app.router.addAlias('category', function(routeObj){ + //* 201403 -> chrome on iOS doesn't like /. in hashbang. + if(routeObj.params && routeObj.params.navcat && routeObj.params.navcat.charAt(0) != '.') { + routeObj.params.navcat = '.'+routeObj.params.navcat; + } + showContent('category', routeObj.params); + }); + + _app.router.addAlias('product', function(routeObj){showContent('product', routeObj.params);}); + _app.router.addAlias('company', function(routeObj){showContent('company', routeObj.params);}); + _app.router.addAlias('customer', function(routeObj){showContent('customer', routeObj.params);}); + _app.router.addAlias('checkout', function(routeObj){showContent('checkout', routeObj.params);}); + + _app.router.addAlias('search', function(routeObj){showContent('search', routeObj.params);}); + + + _app.router.appendHash({'type':'exact','route':'cart','callback':function(routeObj){showContent('cart',routeObj.params);}}); + _app.router.appendHash({'type':'exact','route':'home','callback':'homepage'}); + _app.router.appendHash({'type':'exact','route':'','callback':'homepage'}); + _app.router.appendHash({'type':'match','route':'category/{{navcat}}*','callback':'category'}); + _app.router.appendHash({'type':'match','route':'product/{{pid}}/{{name}}*','callback':'product'}); + _app.router.appendHash({'type':'match','route':'product/{{pid}}*','callback':'product'}); + _app.router.appendHash({'type':'match','route':'company/{{show}}*','callback':'company'}); + _app.router.appendHash({'type':'exact','route':'company','callback':'company'}); + _app.router.appendHash({'type':'match','route':'customer/{{show}}*','callback':'customer'}); + _app.router.appendHash({'type':'exact','route':'customer','callback':'company'}); + _app.router.appendHash({'type':'match','route':'checkout*','callback':'checkout'}); + _app.router.appendHash({'type':'match','route':'search/tag/{{tag}}*','callback':'search'}); + _app.router.appendHash({'type':'match','route':'search/keywords/{{KEYWORDS}}*','callback':'search'}); + + +/* +some other things we could do +_app.router.appendHash({'type':'match','route':'quickview/product/{{pid}}*','callback':function(routeObj){ + quickview('product',routeObj.params); + }}); + +or a more generic one, like so: +_app.router.appendHash({'type':'match','route':'modal/product/{{pid}}*','callback':function(routeObj){ + quickview('product',routeObj.params); + }}); +*/ + r = true; + + return r; + }, + onError : function() { + _app.u.dump('BEGIN store_routing.callbacks.init.onError'); + } + }, + attachEventHandlers : { + onSuccess : function(){ + _app.templates.homepageTemplate.on('complete.routing', function(event, $context, infoObj){_app.ext.store_routing.u.setHash("#!/");}); + + _app.templates.categoryTemplate.on('complete.routing', function(event, $context, infoObj){ + var hash = ""; + var $routeEle = $('[data-routing-hash]',$context) + if($routeEle.length){ + hash = $routeEle.attr('data-routing-hash'); + } + else { + hash = "#!/category/"+infoObj.navcat+"/"; + } + _app.ext.store_routing.u.setHash(hash); + }); + + _app.templates.categoryTemplateFilteredSearch.on('complete.routing', function(event, $context, infoObj){ + var hash = ""; + var $routeEle = $('[data-routing-hash]',$context) + if($routeEle.length){ + hash = $routeEle.attr('data-routing-hash'); + } + else { + hash = "#!/category/"+infoObj.navcat+"/"; + } + _app.ext.store_routing.u.setHash(hash); + }); + + _app.templates.productTemplate.on('complete.routing', function(event, $context, infoObj){ + var hash = ""; + var $routeEle = $('[data-routing-hash]',$context) + if($routeEle.length){ + hash = $routeEle.attr('data-routing-hash'); + } + else { + hash = "#!/product/"+infoObj.pid+"/"; + } + dump(hash); + _app.ext.store_routing.u.setHash(hash); + }); + + _app.templates.companyTemplate.on('complete.routing', function(event, $context, infoObj){_app.ext.store_routing.u.setHash("#!/company/"+infoObj.show+"/");}); + _app.templates.customerTemplate.on('complete.routing', function(event, $context, infoObj){_app.ext.store_routing.u.setHash("#!/customer/"+infoObj.show+"/");}); + _app.templates.searchTemplate.on('complete.routing', function(event, $context, infoObj){_app.ext.store_routing.u.setHash("#!/search/"+encodeURIComponent(infoObj.KEYWORDS)+"/");}); + _app.templates.cartTemplate.on('complete.routing', function(event, $context, infoObj){if(infoObj.show == "inline"){_app.ext.store_routing.u.setHash("#!/cart/");}}); + //_app.templates.checkoutTemplate.on('complete.routing', function(event, $context, infoObj){_app.ext.store_routing.u.setHash("#!/checkout/");}); + }, + onError : function(){} + } + }, //callbacks + + + +//////////////////////////////////// ACTION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + a : { + + }, //Actions + +//////////////////////////////////// RENDERFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + tlcFormats : { + productlink : function(data, thisTLC){ + var args = thisTLC.args2obj(data.command.args, data.globals); + if(args.pid && args.seo){ + data.globals.binds[data.globals.focusBind] = _app.ext.store_routing.u.productAnchor(args.pid, args.seo); + return true; + } + else { + dump('-> store_routing productlink tlcformat: The PID or SEO content was not provided in the tlc.'); + //stop execution of the commands. throw a tantrum. + return false; + } + }, + +/* +optional params: + type -> acceptable values are product, category, dwiw or blank (blank = dwiw). set implicitly for best results. + -> if blank/dwiw, type is guessed. + seo -> supported for both category and product, will append /product pretty name or /category pretty name (uri encoded) to the end of the href. +*/ + seoanchor : function(data, thisTLC){ + var args = thisTLC.args2obj(data.command.args, data.globals), r; + if(!args.type || args.type == 'dwiw') { + if(data.value.pid) {args.type = 'product'} + else if(data.value.path) {args.type = 'category'} + else {} + } + + switch(args.type) { + case 'product': + r = true; + var seoname = ''; + if(args.seoname) { + seoname = args.seoname; + } + //seoname isn't clearly defined, so we go into some dwiw guesswork. + else if(args.seo && data.value['%attribs']) { + seoname = data.value['%attribs']['zoovy:prod_seo_title'] || data.value['%attribs']['zoovy:prod_name'] || ''; //this would be a product list. + } + else if(args.seo && data.value.prod_name) { + seoname = data.value.prod_name; //this would be an elastic search results. + } + else {} //not defined. guesswork came back negative. + data.globals.binds[data.globals.focusBind] = _app.ext.store_routing.u.productAnchor(data.value.pid, seoname); + break; + + case 'category': + r = true; + data.globals.binds[data.globals.focusBind] = _app.ext.store_routing.u.categoryAnchor(data.value.path, (args.seo ? data.value.pretty : '')); + break; + + default: + dump("in tlcFormat.seolink, the type specified ["+args.type+"] is not recognized."); + r = false; //unrecognized 'type' + } + return r; + } //seolink + + }, + + renderFormats : { + productLink : function($tag, data){ + var href="#!product/"; + if(data.bindData.useParentData){ + href += data.value.pid+"/"; + if(data.bindData.seoattr){ + href += data.value["%attribs"][data.bindData.seoattr]; + } + } + else { + href += data.value+"/"; + } + $tag.attr('href',href); + } + }, //renderFormats +//////////////////////////////////// UTIL [u] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + u : { + setHash : function(hash){ + if(_app.vars.showContentHashChange){ + dump('forcing a hash change'); + window.location.href = window.location.href.split("#")[0]+hash; + } + }, + productAnchor : function(pid, seo){ + return "#!product/"+pid+"/"+(seo ? encodeURIComponent(seo) : ''); + }, + categoryAnchor : function(path,seo) { + return "#!category/"+path+((seo) ? "/"+encodeURIComponent(seo) : ''); + }, + searchAnchor : function(type,value) { + var r; + if(type == 'tag') { + r = '#!search/tag/'+value; + } + else if(type == 'keywords') { + r = '#!search/keywords/'+value; + } +// ### FUTURE -> support ability to search for a match on a specific attribute. +// else if(type == 'attrib') { +// r = '#!search/attrib/' ... some key value pair. +// } + else { + //unrecognized type + } + return "#!category/"+path+((seo) ? "/"+encodeURIComponent(seo) : ''); + } + }, //u [utilities] + + e : { +/* + navigateTo : function($ele,P) { + if($ele.data('type')) { + switch($ele.data('type')) { + case 'product': + document.location.hash = _app.ext.store_routing.u.productAnchor($ele.data('pid')); + break; + case 'category': + document.location.hash = _app.ext.store_routing.u.categoryAnchor($ele.data('path')); + break; + default: + $("#globalMessaging").anymessage({"message":"In store_router.e.navigateTo, invalid data.type ["+$ele.data('type')+"] on trigger element.","gMessage":true}); + } + } + else { + + } + } +*/ + } //e [app Events] + } //r object. + return r; + } diff --git a/extensions/store_search.js b/extensions/store_search.js index 6e46990db..4cd114d6b 100644 --- a/extensions/store_search.js +++ b/extensions/store_search.js @@ -24,13 +24,17 @@ The functions here are designed to work with 'reasonable' size lists of categori */ -var store_search = function() { +var store_search = function(_app) { var r = { vars : { //a list of the templates used by this extension. //if this is a custom extension and you are loading system extensions (prodlist, etc), then load ALL templates you'll need here. - "ajaxRequest" : {} + "ajaxRequest" : {}, + "universalFilters":[ + {"has_child":{"type":"sku","query": {"range":{"available":{"gte":1}}}}}, //only return item w/ inventory + {"not" : {"term" : {"tags":"IS_DISCONTINUED"}}} + ] }, //////////////////////////////////// CALLS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ @@ -41,7 +45,7 @@ var store_search = function() { /* P is the params object. something like: var P = {} -P.mode = 'elastic-native'; +P.mode = 'elastic-search'; P.size = 250; P.filter = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_SALE'}} ] } } or instead of P.filter, you may have @@ -49,7 +53,31 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S */ appPublicProductSearch : { init : function(P,tagObj,Q) { -// app.u.dump("BEGIN app.ext.store_search.calls.appPublicSearch"); +// _app.u.dump("BEGIN _app.ext.store_search.calls.appPublicSearch"); + var universalFilters = $.extend(true, [], _app.ext.store_search.vars.universalFilters); + if(universalFilters.length){ + if(obj.filter){ + var tmp = obj.filter; + obj.filter = { + "and" : universalFilters + } + obj.filter.and.push(tmp); + } + else if(obj.query){ + var tmp = obj.query; + obj.query = { + "filtered" : { + "query" : tmp, + "filter" : { + "and" : universalFilters + } + } + } + } + else{ + //This is not going to end well, but let's let Elastic tell you that. + } + } this.dispatch(P,tagObj,Q) return 1; }, @@ -57,8 +85,8 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S P['_cmd'] = "appPublicSearch"; P.type = 'product'; P['_tag'] = tagObj; -// app.u.dump(P); - app.model.addDispatchToQ(P,Q); +// _app.u.dump(P); + _app.model.addDispatchToQ(P,Q); } }, //appPublicSearch @@ -66,15 +94,39 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S // to get a good handle on what datapointers should look like. appPublicSearch : { init : function(obj,tagObj,Q) { + var universalFilters = $.extend(true, [], _app.ext.store_search.vars.universalFilters); + if(universalFilters.length){ + if(obj.filter){ + var tmp = obj.filter; + obj.filter = { + "and" : universalFilters + } + obj.filter.and.push(tmp); + } + else if(obj.query){ + var tmp = obj.query; + obj.query = { + "filtered" : { + "query" : tmp, + "filter" : { + "and" : universalFilters + } + } + } + } + else{ + //This is not going to end well, but let's let Elastic tell you that. + } + } this.dispatch(obj,tagObj,Q) return 1; }, dispatch : function(obj,tagObj,Q) { obj['_cmd'] = "appPublicSearch"; obj['_tag'] = tagObj; -// app.u.dump("BEGIN app.ext.store_search.calls.appPublicSearch"); -// app.u.dump(obj); - app.model.addDispatchToQ(obj,Q); +// _app.u.dump("BEGIN _app.ext.store_search.calls.appPublicSearch"); +// _app.u.dump(obj); + _app.model.addDispatchToQ(obj,Q); } } //appPublicSearch @@ -95,14 +147,14 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S //the callback is auto-executed as part of the extensions loading process. init : { onSuccess : function() { -// app.u.dump('BEGIN app.ext.store_navcats.init.onSuccess '); +// _app.u.dump('BEGIN _app.ext.store_navcats.init.onSuccess '); var r = true; //return false if extension won't load for some reason (account config, dependencies, etc). return r; }, onError : function() { //errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. //you may or may not need it. - app.u.dump('BEGIN app.ext.store_navcats.callbacks.init.onError'); + _app.u.dump('BEGIN _app.ext.store_navcats.callbacks.init.onError'); } }, @@ -113,8 +165,7 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S // parentID, templateID (template used on each item in the results) and datapointer. handleElasticResults : { onSuccess : function(_rtag) { -// app.u.dump("BEGIN myRIA.callbacks.handleElasticResults.onSuccess."); - var L = app.data[_rtag.datapointer]['_count']; + var L = _app.data[_rtag.datapointer]['_count']; var $list = _rtag.list; if($list && $list.length) { @@ -127,15 +178,18 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S } else { var $parent; - if($list.is('tbody')) {$parent = $list.closest('table').parent(); app.u.dump("LIST is a tbody");} + if($list.is('tbody')) {$parent = $list.closest('table').parent(); _app.u.dump("LIST is a tbody");} else if($list.is('table')) {$parent = $list.parent();} else {$parent = $list.parent()} //put items into list (most likely a ul or tbody - $list.append(app.ext.store_search.u.getElasticResultsAsJQObject(_rtag)); //prioritize w/ getting product in front of buyer - if(app.ext.admin) { + $list.append(_app.ext.store_search.u.getElasticResultsAsJQObject(_rtag)); //prioritize w/ getting product in front of buyer + if(_rtag.title) { + $list.before("<h2 class='searchHeader'>"+_rtag.title+"</h2>"); + } + if(_app.ext.admin) { $list.hideLoading(); - app.ext.admin.u.handleAppEvents($parent); + _app.u.handleAppEvents($parent); } var EQ = $list.data('elastic-query'); //Elastic Query @@ -144,14 +198,15 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S delete _tag.pipeUUID; delete _tag.status; //the status would already be 'requesting' or 'completed', which means this request wouldn't run. - var $header = app.ext.store_search.u.buildResultsHeader($list,_rtag.datapointer), //# of results and keyword display. -// $sortMenu = app.ext.store_search.u.buildSortMenu($list,_rtag), //sorting options as ul - $pageMenu = app.ext.store_search.u.buildPagination($list,_tag), //pagination as ul - $multipage = app.ext.store_search.u.buildPaginationButtons($list,_tag), //next/prev buttons + var $header = _app.ext.store_search.u.buildResultsHeader($list,_rtag.datapointer), //# of results and keyword display. +// $sortMenu = _app.ext.store_search.u.buildSortMenu($list,_rtag), //sorting options as ul + $pageMenu = _app.ext.store_search.u.buildPagination($list,_tag), //pagination as ul + $multipage = _app.ext.store_search.u.buildPaginationButtons($list,_tag), //next/prev buttons $menuContainer = $("<div \/>").addClass('resultsMenuContainer'), //used to hold menus. imp for abs. positioning. $controlsContainer = $("<div \/>").addClass('ui-widget ui-widget-content resultsHeader clearfix ui-corner-bottom'); //used to hold menus and buttons. // $menuContainer.append($sortMenu); //sorting not working. commented out for now. !!! + $parent.find(".resultsHeader").remove(); //make sure headers don't stack when using pagination. // ### TODO -> test this. $header.prependTo($parent); //pageMenu will be false if there are no pages. If there's no pagination, no further output is needed. if($pageMenu) { @@ -166,9 +221,6 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S $pageMenu.menu(); // $sortMenu.menu(); } - - - } else { //no error gets thrown here. it is an acceptable use case to display search results w/ no multipage functionality. @@ -177,8 +229,12 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S } else { $('#globalMessaging').anymessage({'message':'In store_search.callbacks.handleElasticResults, $list ['+typeof _rtag.list+'] was not defined, not a jquery object ['+(_rtag.list instanceof jQuery)+'] or does not exist ['+_rtag.list.length+'].',gMessage:true}); - app.u.dump("handleElasticResults _rtag.list: "); app.u.dump(_rtag.list); + _app.u.dump("handleElasticResults _rtag.list: "); _app.u.dump(_rtag.list); } + +//this gets run whether there are results or not. It is the events responsibility to make sure results were returned. +// That way, it can handle a no-results action. + $list.trigger('listcomplete',_rtag); } } }, //callbacks @@ -194,23 +250,23 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S //list is the UL or whatever element type contains the list of product. - buildResultsHeader : function($list,datapointer) { -// app.u.dump("BEGIN store_search.u.buildMultipageHeader"); - + buildResultsHeader : function($list,datapointer,vars) { +// _app.u.dump("BEGIN store_search.u.buildMultipageHeader"); + vars = vars || {}; var $header = false, //will be a jquery object IF the necesarry data is present. EQ = $list.data('elastic-query'); //Elastic Query if(datapointer && $list && EQ) { - $header = $("<div \/>").addClass('ui-widget ui-widget-header resultsHeader clearfix ui-corner-top hideInMinimalMode'); + $header = $("<div \/>").addClass('ui-widget ui-widget-header resultsHeader clearfix ui-corner-top hideInMinimalMode'); // note - resultsHeader is used to search/replace any existing headers. if(EQ.query && EQ.query.query_string && EQ.query.query_string.query){ - $header.text(app.data[datapointer].hits.total+" Results for: "+EQ.query.query_string.query); + $header.text(_app.data[datapointer].hits.total+" Results for: "+EQ.query.query_string.query); } else { - $header.text(app.data[datapointer].hits.total+" Results for your query"); + $header.text(_app.data[datapointer].hits.total+" Results for your query"); } } else if(!EQ) { - app.u.dump("NOTICE! the search results container did not contain data('elastic-filter') so no multipage data is present.",'warn'); + _app.u.dump("NOTICE! the search results container did not contain data('elastic-filter') so no multipage data is present.",'warn'); } else if(!$list) { $('#globalMessaging').anymessage({'message':'In store_search.u.buildResultsHeader, no $list object specified','gMessage':true}) @@ -218,36 +274,35 @@ P.query = { 'and':{ 'filters':[ {'term':{'profile':'E31'}},{'term':{'tags':'IS_S else { $list.parent.anymessage({'message':'In store_search.u.buildResultsHeader, no datapointer specified','gMessage':true}); } - return $header; }, buildPaginationButtons : function($list,_rtag) { - app.u.dump("BEGIN store_search.u.buildPaginationButtons"); + _app.u.dump("BEGIN store_search.u.buildPaginationButtons"); var $controls, EQ = $list.data('elastic-query'); //Elastic Query -// app.u.dump(" -> EQ: "); app.u.dump(EQ); +// _app.u.dump(" -> EQ: "); _app.u.dump(EQ); if($list && EQ && _rtag && _rtag.datapointer) { -// app.u.dump("EQ: "); app.u.dump(EQ); - var data = app.data[_rtag.datapointer], //shortcut +// _app.u.dump("EQ: "); _app.u.dump(EQ); + var data = _app.data[_rtag.datapointer], //shortcut from = EQ.from || 0, pageInFocus = $list.data('page-in-focus') || 1, //start at 1, not zero, so page 1 = 1 totalPageCount = Math.ceil(data.hits.total / EQ.size) //total # of pages for this list. -app.u.dump(" -> pageInFocus: "+pageInFocus); +_app.u.dump(" -> pageInFocus: "+pageInFocus); $controls = $("<div \/>").addClass(''); //SANITY -> the classes on these buttons are used in quickstart. var $prevPageBtn = $("<button \/>").text("Previous Page").button({icons: {primary: "ui-icon-circle-triangle-w"},text: false}).addClass('prevPageButton').on('click.multipagePrev',function(event){ event.preventDefault(); - app.ext.store_search.u.changePage($list,(pageInFocus - 1),_rtag); + _app.ext.store_search.u.changePage($list,(pageInFocus - 1),_rtag); }); var $nextPageBtn = $("<button \/>").text("Next Page").button({icons: {primary: "ui-icon-circle-triangle-e"},text: false}).addClass('nextPageButton').on('click.multipageNext',function(event){ event.preventDefault(); - app.ext.store_search.u.changePage($list,(pageInFocus + 1),_rtag); + _app.ext.store_search.u.changePage($list,(pageInFocus + 1),_rtag); }); if(pageInFocus == 1) {$prevPageBtn.button('disable');} @@ -278,16 +333,16 @@ app.u.dump(" -> pageInFocus: "+pageInFocus); changePage : function($list,newPage,_tag) { if($list && newPage) { var EQ = $list.data('elastic-query'); //Elastic Query -// app.u.dump(" -> newPage: " + newPage); +// _app.u.dump(" -> newPage: " + newPage); if(EQ) { var query = EQ; - app.u.dump("EQ:"); - app.u.dump(EQ); +// _app.u.dump("EQ:"); +// _app.u.dump(EQ); //query.size = EQ.size; //use original size, not what's returned in buildSimple... query.from = (newPage - 1) * EQ.size; //page is passed in, which starts at 1. but elastic starts at 0. - app.ext.store_search.u.updateDataOnListElement($list,query,newPage); - app.ext.store_search.calls.appPublicSearch.init(query,_tag); - app.model.dispatchThis(); + _app.ext.store_search.u.updateDataOnListElement($list,query,newPage); + _app.ext.store_search.calls.appPublicSearch.init(query,_tag); + _app.model.dispatchThis(); } else { $('#globalMessaging').anymessage({'message':'In store_search.u.changePage, $list set but missing data(elastic-query).','gMessage':true}); @@ -304,12 +359,12 @@ app.u.dump(" -> pageInFocus: "+pageInFocus); var EQ = $list.data('elastic-query'); //Elastic Query if(EQ) { var pageInFocus = $list.data('page-in-focus') || 1, //start at 1, not zero, so page 1 = 1 - data = app.data[_tag.datapointer], + data = _app.data[_tag.datapointer], totalPageCount = Math.ceil(data.hits.total / EQ.size) //total # of pages for this list. if(totalPageCount <= 1) { //if there is only 1 page or something went wrong, don't show pagination. -// app.u.dump(" -> no pagination for results. totalPageCount: "+totalPageCount); +// _app.u.dump(" -> no pagination for results. totalPageCount: "+totalPageCount); } else { $pagination = $("<ul \/>").addClass('pagination resultsMenu'); @@ -322,7 +377,7 @@ app.u.dump(" -> pageInFocus: "+pageInFocus); $("a",$pages).each(function(){ $(this).on('click',function(event){ event.preventDefault(); - app.ext.store_search.u.changePage($list,$(this).data('page'),_tag); + _app.ext.store_search.u.changePage($list,$(this).data('page'),_tag); }) }); } @@ -355,17 +410,17 @@ app.u.dump(" -> pageInFocus: "+pageInFocus); $(this).on('click',function(event){ event.preventDefault(); - app.u.dump(" -> change sort order"); + _app.u.dump(" -> change sort order"); - var query = app.ext.store_search.u.buildElasticSimpleQuery(EQ.query.query_string); + var query = _app.ext.store_search.u.buildElasticSimpleQuery(EQ.query.query_string); query.size = EQ.size; //use original size, not what's returned in buildSimple... query.from = 0; query.sort = [{'base_price':{'order':'asc'}}]; - app.ext.store_search.u.updateDataOnListElement($list,query,1); + _app.ext.store_search.u.updateDataOnListElement($list,query,1); - app.ext.store_search.calls.appPublicSearch.init(query,_tag); - app.model.dispatchThis(); + _app.ext.store_search.calls.appPublicSearch.init(query,_tag); + _app.model.dispatchThis(); }); }) @@ -376,17 +431,17 @@ app.u.dump(" -> pageInFocus: "+pageInFocus); var keywordsArray = new Array(); keywordsArray = keywords.split(' '); -// app.u.dump(" -> number of words = "+keywordsArray.length); +// _app.u.dump(" -> number of words = "+keywordsArray.length); var permutations = this.getPermutationsOfArray(keywordsArray); -// app.u.dump(" -> number of permutations = "+permutations.length); +// _app.u.dump(" -> number of permutations = "+permutations.length); var L = permutations.length; var mode = $('#headerModeInput').val(); var catalog = $('#headerCatalog').val(); var thisKeyword; for(var i = 0; i < L; i += 1) { thisKeyword = this.getPermArrayIntoString(permutations[i]); - app.ext.store_search.calls.searchResult.init({"KEYWORDS":thisKeyword,"CATALOG":catalog,"MODE":mode},tagObj); + _app.ext.store_search.calls.searchResult.init({"KEYWORDS":thisKeyword,"CATALOG":catalog,"MODE":mode},tagObj); } }, //getAlternativeQueries @@ -396,7 +451,7 @@ app.u.dump(" -> pageInFocus: "+pageInFocus); for(var i = 0; i < a.length; i +=1) { r += a[i]+' '; } -// app.u.dump("permArrayToString = "+r); +// _app.u.dump("permArrayToString = "+r); return r; }, //pass in an array of keywords and all combinations will be returned. @@ -439,23 +494,24 @@ return combine(keywordsArray); Will return the results a jquery object for display. append the return from this function to your list (or other element) P should contain the following: -P.datapointer - pointer to where in app.data the results are stored. +P.datapointer - pointer to where in _app.data the results are stored. P.templateID - what productList template to use -P.parentID - The parent ID is used as the pointer in the multipage controls object. app.ext.store_prodlist.vars[POINTER] +P.parentID - The parent ID is used as the pointer in the multipage controls object. _app.ext.store_prodlist.vars[POINTER] #### note - not all these are used yet, but will be soon. */ getElasticResultsAsJQObject : function(P) { -// app.u.dump("BEGIN store_search.u.getElasticResultsAsJQObject ["+P.datapointer+"]") +// _app.u.dump("BEGIN store_search.u.getElasticResultsAsJQObject ["+P.datapointer+"]") var pid;//recycled shortcut to product id. - var L = app.data[P.datapointer]['_count']; + var L = _app.data[P.datapointer]['_count']; var $r = $("<ul />"); //when this was a blank jquery object, it didn't work. so instead, we append all content to this imaginary list, then just return the children. -// app.u.dump(" -> parentID: "+P.parentID); //resultsProductListContainer -// app.u.dump(" -> L: "+L); +// _app.u.dump(" -> parentID: "+P.parentID); //resultsProductListContainer +// _app.u.dump(" -> L: "+L); for(var i = 0; i < L; i += 1) { - pid = app.data[P.datapointer].hits.hits[i]['_id']; -// app.u.dump(" -> "+i+" pid: "+pid); - $r.append(app.renderFunctions.transmogrify({'id':pid,'pid':pid},P.templateID,app.data[P.datapointer].hits.hits[i]['_source'])); + pid = _app.data[P.datapointer].hits.hits[i]['_id']; +// _app.u.dump(" -> "+i+" pid: "+pid); + $r.append(new tlc().runTLC({'templateid':P.templateID,'dataset':_app.data[P.datapointer].hits.hits[i]['_source']}).attr('data-pid',pid).removeClass('loadingBG')); +// $r.append(_app.renderFunctions.transmogrify({'id':pid,'pid':pid},P.templateID,_app.data[P.datapointer].hits.hits[i]['_source'])); } return $r.children(); }, @@ -467,21 +523,31 @@ P.parentID - The parent ID is used as the pointer in the multipage controls obje var es = $.extend(true, {}, elasticsearch); es.type = 'product'; - es.mode = 'elastic-native'; + es.mode = 'elastic-search'; es.size = 250; - + return es; - }, + }, //Example of an obj would be: {'query':'some search string'} OR {'query':'some search string','fields':'prod_keywords'} buildElasticSimpleQuery : function(obj) { var query = {}; //what is returned. false if error occurs. if(obj && obj.query) { query.type = 'product'; - query.mode = 'elastic-native'; + query.mode = 'elastic-search'; query.size = 250; - query.query = {"query_string" : obj}; - } + query.query = { //{"query_string" : obj}; +/*Zephyr*/ "filtered": { + "query" : {"query_string" : obj}, + "filter" : { + "and" : [ + {"has_child":{"type":"sku","query": {"range":{"available":{"gte":1}}}}}, //only return item w/ inventory + {"not" : {"term" : {"tags":"IS_DISCONTINUED"}}} + ] + } + } + }; + } else { $('#globalMessaging').anymessage({'message':'In store_search.u.buildElasticSimpleQuery, obj.query was empty. ',gMessage:true}); query = false; @@ -489,13 +555,13 @@ P.parentID - The parent ID is used as the pointer in the multipage controls obje return query; }, -//not used by quickstart anymore. Still in use by analyzer and admin product editor. +//This is used by quickstart for simple tag and keyword searches as well as by analyzer and admin interface (product editor and probably finder). handleElasticSimpleQuery : function(keywords,_tag) { var qObj = this.buildElasticSimpleQuery({'query':keywords}); _tag = _tag || {}; _tag.datapointer = "appPublicSearch|"+keywords; - var r = app.ext.store_search.calls.appPublicSearch.init(qObj,_tag); - app.model.dispatchThis(); + var r = _app.ext.store_search.calls.appPublicSearch.init(qObj,_tag); + _app.model.dispatchThis(); return r; } @@ -505,4 +571,4 @@ P.parentID - The parent ID is used as the pointer in the multipage controls obje } //r object. return r; - } \ No newline at end of file + } diff --git a/extensions/store_seo.js b/extensions/store_seo.js new file mode 100644 index 000000000..0c8a5e31b --- /dev/null +++ b/extensions/store_seo.js @@ -0,0 +1,144 @@ +/* ************************************************************** + + Copyright 2013 Zoovy, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +************************************************************** */ + +/* +Service-Entrance Protocol is a test harness which can also be used for SEO. +It is briefly described here: +http://blog.commercerack.com/2014/05/the-significance-of-service-entrance.html + +The spider roughly executes these commands: + + +_robots.hello("MrRoboto/1.0"); // MrRoboto/1.0 is the user agent for the robot +_robots.ready(); // wait until this returns true +_robots.pop(10); // this says "give me 10 lines" to spider - lines are CR/LF separated +_robots.next("#!someuri-returned-by-pop"); // this will navigate to one of the lines returned by .pop(1); + +// now the test harness will loop while the content is loaded. periodically checking if the document is ready. +_robots.status(); // 100 it will loop, 200 is success +// once it's 200 + +// inside the anyCommerce App framework .status() will return 200 ONLY when: +_app.ext.quickstart.vars.showContentFinished = true; +_app.ext.quickstart.vars.showContentCompleteFired = true; + +// to see the status, it's necessary to change _app to "myApp" ex: +console.log(myApp.ext.quickstart.vars.showContentFinished); +console.log(myApp.ext.quickstart.vars.showContentCompleteFired); + +// GOTCHAS: +// this module likes to pass json *STRINGS* from .pop() +// if you're running from the command line [notice how it's escaped]: +// _robots.next('{"pageType":"category","navcat":".path.to.navcat"}'); +// + +*/ + + +var store_seo = function(_app) { + var theseTemplates = new Array(''); + var r = { + + +//////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + vars : { + defaultTitle : "", //Should not include any Prefix or Postfix + titlePrefix : "", + titlePostfix : "" + }, + + callbacks : { +//executed when extension is loaded. should include any validation that needs to occur. + init : { + onSuccess : function() { + var r = false; + + _app.templates.homepageTemplate.on('complete', function(event,$context,infoObj){_app.ext.store_seo.u.generateMeta(infoObj);}); + _app.templates.categoryTemplate.on('complete', function(event,$context,infoObj){_app.ext.store_seo.u.generateMeta(infoObj);}); + _app.templates.productTemplate.on('complete', function(event,$context,infoObj){_app.ext.store_seo.u.generateMeta(infoObj);}); + _app.templates.companyTemplate.on('complete', function(event,$context,infoObj){_app.ext.store_seo.u.generateMeta(infoObj);}); + _app.templates.customerTemplate.on('complete', function(event,$context,infoObj){_app.ext.store_seo.u.generateMeta(infoObj);}); + _app.templates.checkoutTemplate.on('complete', function(event,$context,infoObj){_app.ext.store_seo.u.generateMeta(infoObj);}); + _app.templates.cartTemplate.on('complete', function(event,$context,infoObj){_app.ext.store_seo.u.generateMeta(infoObj);}); + _app.templates.searchTemplate.on('complete', function(event,$context,infoObj){_app.ext.store_seo.u.generateMeta(infoObj);}); + + r = true; + + return r; + }, + onError : function() { + _app.u.dump('BEGIN store_seo.callbacks.init.onError'); + } + } + }, //callbacks + + + +//////////////////////////////////// ACTION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + a : { + + }, //Actions + +//////////////////////////////////// RENDERFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + renderFormats : { + + }, //renderFormats +//////////////////////////////////// UTIL [u] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + u : { + generateMeta : function(infoObj){ + var baseTitle = ''; + var desc = ''; + switch(infoObj.pageType){ + case "homepage" : + //Use Default Title + break; + case "category" : + break; + case "product" : + break; + case "company" : + break; + case "customer" : + break; + case "checkout" : + break; + case "cart" : + break; + case "search" : + break; + default : + break; + } + if(!baseTitle){ + baseTitle = _app.ext.store_seo.vars.defaultTitle; + } + + document.title = _app.ext.store_seo.vars.titlePrefix + title + _app.ext.store_seo.vars.titlePostfix; + $('meta[name=description]').attr('content', desc); + } + }, //u [utilities] + + e : { + } //e [app Events] + } //r object. + return r; + } diff --git a/extensions/store_tracking.js b/extensions/store_tracking.js new file mode 100644 index 000000000..7e744efe6 --- /dev/null +++ b/extensions/store_tracking.js @@ -0,0 +1,136 @@ +/* ************************************************************** + + Copyright 2013 Zoovy, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +************************************************************** */ + + + +// !!! -> TODO: replace 'username' in the line below with the merchants username. <- !!! + +var store_tracking = function(_app) { + var r = { + + +//////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + + + callbacks : { + init : { + onSuccess : function() { + var r = false; + + r = true; + + return r; + }, + onError : function() { + _app.u.dump('BEGIN store_tracking.callbacks.init.onError'); + } + }, + attachHandlers : { + onSuccess : function(){ + _app.ext.order_create.checkoutCompletes.push(function(P){ + if(P && P.datapointer && _app.data[P.datapointer] && _app.data[P.datapointer].order){ + var order = _app.data[P.datapointer].order; + var plugins = zGlobals.plugins; + + //analytics tracking + ga('ecommerce:addTransaction', { + 'id' : order.orderid, + 'revenue' : order.sum.item_total, + 'shipping' : order.sum.shp_total, + 'tax' : order.sum.tax_total + }); + for(var i in order['@ITEMS']){ + var item = order['@ITEMS'][i]; + ga('ecommerce:addItem', { + 'id' : order.orderid, + 'name' : item.prod_name, + 'sku' : item.sku, + 'price' : item.base_price, + 'qty' : item.qty, + }) + } + ga('ecommerce:send'); + + for(var i in plugins){ + if(_app.ext.store_tracking.trackers[i] && _app.ext.store_tracking.trackers[i].enable){ + _app.ext.store_tracking.trackers[i](order, plugins[i]); + } + } + } + }); + }, + onError : function() { + _app.u.dump('BEGIN store_tracking.callbacks.attachHandlers.onError'); + } + } + }, //callbacks + + trackers : { + "adwords.google.com" : function(order, plugin){ + var labels = plugin.google_conversion_label.split(','); + for(var i in labels){ + var globals = { + google_conversion_id : plugin.google_conversion_id, + google_conversion_language : "en", + google_conversion_format: "3", + google_conversion_color : "ffffff", + google_conversion_label : labels[i].replace(/^\s+|\s+$/g, ''), //trims label of whitespace + google_remarketing_only : "false", + } + if(plugin.dynamic_value){ + globals.google_conversion_value = order.sum.order_total; + } + _app.ext.store_tracking.u.addTrackingScript("//www.googleadservices.com/pagead/conversion.js", globals); + } + } + }, + + u : { + addTrackingScript : function(scripts, globals){ + //allow for convenient passing of a single string instead of an array + if(typeof scripts == "string"){scripts = [scripts];} + + var iframe = document.createElement("iframe"); + $(iframe).addClass("displayNone"); + $('body').append(iframe); + + //the iframe needs a timeout after being added to the DOM before we can access its contents + setTimeout(function(){ + if(globals){ + var paramScript = iframe.contentWindow.document.createElement("script"); + paramScript.type = "text/javascript"; + paramScript.text = ""; + for(var index in globals){ + paramScript.text += index+" = "+globals[index]+";"; + } + iframe.contentWindow.document.body.appendChild(paramScript); + } + for(var i in scripts){ + var script = iframe.contentWindow.document.createElement("script"); + script.type = "text/javascript"; + script.src = scripts[i]; + iframe.contentWindow.document.body.appendChild(script); + } + }, 250); + } + }, //u [utilities] + + } //r object. + return r; + } \ No newline at end of file diff --git a/extensions/store_zephyrapp.js b/extensions/store_zephyrapp.js new file mode 100644 index 000000000..57a615af5 --- /dev/null +++ b/extensions/store_zephyrapp.js @@ -0,0 +1,829 @@ +/* ************************************************************** + + Copyright 2013 Zoovy, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +************************************************************** */ + + + + + +var store_zephyrapp = function(_app) { + var theseTemplates = new Array(''); + var r = { + + +//////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + + + callbacks : { +//executed when extension is loaded. should include any validation that needs to occur. + init : { + onSuccess : function() { + var r = false; //return false if extension won't load for some reason (account config, dependencies, etc). + + + + + + + /* + + _app.rq.push(['templateFunction','productTemplate','onDeparts',function(P) { + var $container = $('#recentlyViewedItemsContainer'); + $container.show(); + $("ul",$container).empty(); //empty product list + $container.anycontent({data:_app.ext.myRIA.vars.session}); //build product list + }]); + + _app.rq.push(['templateFunction','categoryTemplate','onCompletes', function(P){ + var breadcrumb = P.navcat.split("."); + var topNavcat = "."+breadcrumb[1]; + $('#sideBarLeft [data-navcat="'+topNavcat+'"] .subCatList').show(); + }]); + + _app.rq.push(['templateFunction','categoryTemplate','onDeparts', function(P){ + var breadcrumb = P.navcat.split("."); + var topNavcat = "."+breadcrumb[1]; + $('#sideBarLeft [data-navcat="'+topNavcat+'"] .subCatList').hide(); + }]); + + + _app.rq.push(['templateFunction', 'productTemplate','onCompletes',function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('#sideBarRight').hide(); + $('#contentArea').removeClass('sideBarRightShow'); + $('#contentArea').addClass('sideBarRightHide'); + + $('.responsiveDropdown').hide(); + + $('.randomList', $context).each(function(){ + _app.ext.store_zephyr_app.u.randomizeList($(this)); + }); + }]); + + + _app.rq.push(['templateFunction', 'checkoutTemplate','onCompletes',function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('#sideBarRight').hide(); + $('#contentArea').removeClass('sideBarRightShow'); + $('#contentArea').addClass('sideBarRightHide'); + + $('.responsiveDropdown').hide(); + }]); + + _app.rq.push(['templateFunction', 'cartTemplate', 'onCompletes',function(P){ + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('.responsiveDropdown').hide(); + }]); + + _app.rq.push(['templateFunction', 'homepageTemplate','onCompletes',function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('#sideBarRight').show(); + $('#contentArea').removeClass('sideBarRightHide'); + $('#contentArea').addClass('sideBarRightShow'); + + $('.responsiveDropdown').show(); + + $('.randomList', $context).each(function(){ + _app.ext.store_zephyr_app.u.randomizeList($(this)); + }); + }]); + + _app.rq.push(['templateFunction', 'categoryTemplate','onCompletes',function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('#sideBarRight').show(); + $('#contentArea').removeClass('sideBarRightHide'); + $('#contentArea').addClass('sideBarRightShow'); + + $('.responsiveDropdown').show(); + }]); + + _app.rq.push(['templateFunction', 'searchTemplate','onCompletes',function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('#sideBarRight').show(); + $('#contentArea').removeClass('sideBarRightHide'); + $('#contentArea').addClass('sideBarRightShow'); + + $('.responsiveDropdown').show(); + }]); + + _app.rq.push(['templateFunction', 'customerTemplate','onCompletes',function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('#sideBarRight').show(); + $('#contentArea').removeClass('sideBarRightHide'); + $('#contentArea').addClass('sideBarRightShow'); + + $('.responsiveDropdown').hide(); + + if(P.show == "login" || P.show =="createaccount" || P.show == "recoverpassword"){ + $('.sideline', $context).hide(); + $('.mainColumn',$context).width("100%"); + } else{ + $('.sideline', $context).show(); + } + + }]); + + _app.rq.push(['templateFunction', 'companyTemplate','onCompletes',function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('#sideBarRight').show(); + $('#contentArea').removeClass('sideBarRightHide'); + $('#contentArea').addClass('sideBarRightShow'); + }]); + + $('.ddMenuBtn').on('click',function(event){ + _app.ext.store_zephyrapp.a.showDropDown($(this).parent()); + event.stopPropagation(); + }); + + _app.rq.push(['templateFunction', 'productTemplate','onCompletes',function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + + $('.childDropdown',$context).children().each(function(){ + var pid=$(this).val(); + if(pid){ + var $opt=$(this); + + var tagObj = { + "callback":function(rd){ + if(_app.ext.store_product.u.productIsPurchaseable(pid)){ + // do nothing muy bueno + } + else{ + $opt.attr('disabled','disabled'); + } + } + } + + _app.ext.store_product.calls.appProductGet.init(pid,tagObj,"immutable"); + _app.model.dispatchThis("immutable"); + } + }); + + $('.childDropdown',$context).on('change',function(event){ + var pid = $(this).val(); + $('.inventoryContainer',$context).empty().anycontent({"datapointer":"appProductGet|"+pid}) + }); + }]); + + + _app.rq.push(['templateFunction','customerTemplate','onCompletes',function(infoObj){ + if(infoObj.show == 'login' && infoObj.callback){ + $('#loginArticle form.loginForm').data('callback', infoObj.callback); + } + }]); + _app.rq.push(['templateFunction','customerTemplate','onDeparts',function(infoObj){ + $('#loginArticle form.loginForm').removeData('callback', infoObj.callback); + }]); + */ + r = true; + + return r; + + }, + + onError : function() { +//errors will get reported for this callback as part of the extensions loading. This is here for extra error handling purposes. +//you may or may not need it. + _app.u.dump('BEGIN admin_orders.callbacks.init.onError'); + } + }, + startExtension: { + onSuccess : function() { + /* + var temp = JSON.parse(_app.storageFunctions.readLocal('recentlyViewedItems')); + var oldTime = JSON.parse(_app.storageFunctions.readLocal('timeStamp')); + var d = new Date().getTime(); + if(d - oldTime > 90*24*60*60*1000) { + var expired = true; + } + else { + var expired = false; + } + if(temp && !expired){ + _app.ext.myRIA.vars.session.recentlyViewedItems = temp; + _app.u.dump(_app.ext.myRIA.vars.session.recentlyViewedItems); + var $container = $('#recentlyViewedItemsContainer'); + $container.show(); + $("ul",$container).empty(); //empty product list + $container.anycontent({data:_app.ext.myRIA.vars.session}); //build product list + } + */ + + var r = false; //return false if extension won't load for some reason (account config, dependencies, etc). + + +//bind a click action for the dropdown on the shop link. + $('#shopNowLink').on('click',function(){ + $(".shopButtonAttentionArrowCont").hide(); + $('.shopButtonAttentionArrowCont').data('clickOff',true).append(); + + if($('#tier1catContainer').data('sliderState')){} + else{ + $('#tier1catContainer').data('sliderState',false).append(); + } + + if($('#tier1catContainer').data('sliderState') === false){ + $('#tier1catContainer').slideDown(); + $('#tier1catContainer').data('sliderState',true).append(); + } + else if($('#tier1catContainer').data('sliderState') === true){ + $('#tier1catContainer').slideUp(); + $('#tier1catContainer').data('sliderState',false).append(); + } + + /*$( document ).one( "click", function() { + $('#tier1catContainer').slideUp(); + }); + */ + return false; + }); + + + //resize is executed continuously as the browser dimensions change. This function allows the code to be executed once, on finish (or pause) + $(window).resize(function() { + if(this.resizeTO) {clearTimeout(this.resizeTO);} + this.resizeTO = setTimeout(function() { + $(this).trigger('resizeEnd'); + }, 500); + }); + + $(window).bind('resizeEnd', function(P) { + //resize all the images in the visible content area based on srcset and new browser dimensions. + if(typeof handleSrcSetUpdate == 'function') { + // dump(" -----------> firing off resize event. length: "+$("#mainContentArea :visible:first").length+" and ID: "+$("#mainContentArea :visible:first").attr('id')); + handleSrcSetUpdate($("#mainContentArea :visible:first")) + } + + //css will handle the category list show/hide to some degree. + //however, if the browser was smaller than 1040 and the cats were toggled, an inline 'hide' would be present and cats wouldn't show up. over 1040, cats are always visible. + if($(window).width() >= 1040) { + $('#tier1catContainer').show(); + } + else { + $('#tier1catContainer').hide(); //may not need this. here in case width > 1040 and then scaled down. Cats would go into 'open' position. felt unnatural. + } + + //if a dialog is open, reposition it to the center of the screen. + $('.ui-dialog-content:visible').each(function(){ + $(this).dialog("option", "position", "center"); + }) + + }).trigger('resizeEnd'); + + _app.templates.homepageTemplate.on('complete.zephyr',function(event,$context,infoObj){ + $('.shopButtonAttentionArrowCont').data('clickOff',false).append(); + var loopDuration = 4000; + if($(window).width() < 1040) { + for(i = 0; i < 10; i++){ + loopDuration = loopDuration + 4000; + setTimeout((function (){ + if($(window).width() < 1040) { + if($('.shopButtonAttentionArrowCont').data('clickOff') === false){ + $(".shopButtonAttentionArrowCont").effect("shake"); + } + else{ + $(".shopButtonAttentionArrowCont").hide(); + } + } + else{ + $(".shopButtonAttentionArrowCont").hide(); + } + }), loopDuration); + } + } + }); + }, + onError : function() { + } + } + }, //callbacks + + + +//////////////////////////////////// ACTION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +//actions are functions triggered by a user interaction, such as a click/tap. +//these are going the way of the do do, in favor of app events. new extensions should have few (if any) actions. + a : { + + }, //Actions + +//////////////////////////////////// TLCFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + tlcFormats : { + + //this tlcformat gets run AFTER the image has been appended/replaced. It needs the data-attributes set. + srcset : function(data,thisTLC) { +// dump(" -> srcset data: "); dump(data,'dir'); + if(data.value) { + var argObj = thisTLC.args2obj(data.command.args,data.globals); //this creates an object of the args + var srcset = new Array(); +// dump(" -> argObj"); dump(argObj,'dir'); + if(argObj.views) { +// dump(" -> argObj.views IS set"); + var viewArr = argObj.views.split(','), L = viewArr.length; + for(var i = 0; i < L; i += 1) { + var obj = _app.u.kvp2Array(viewArr[i]), string = ''; + string = thisTLC.makeImageURL({'width':obj.w,'height':obj.h,'data-media':data.value,'data-bgcolor':'ffffff'}); + if(obj.vp) {string += " "+obj.vp;} + if(obj.dpi) {string += " "+obj.dpi;} + srcset.push(string); + } + data.globals.binds[data.globals.focusBind] = srcset.join(','); + } + } + return true; //continue processing tlc + }, + + converthtmllinks : function(data,thisTLC) { + var $content = $(data.globals.binds[data.globals.focusBind]); + $('a',$content).each(function(){ + var href = $(this).attr('href'); + if(!href) {} //no href? odd, but do nothing. + else if(href.charAt(0) == '#') {} //link is formatted correctly or an anchor. do nothing. + else { + $(this).attr('href',_app.ext.quickstart.u.getHashFromPageInfo(_app.ext.quickstart.u.detectRelevantInfoToPage(href))); + } + }); + data.globals.binds[data.globals.focusBind] = $content.html(); + return true; + }, + + //if the value is blank, null, empty, undefined , return false (stops tlc processing on this statement) + dwiwempty : function(data,thisTLC) { + var r = true; + //needs to be first or the blanket data.value will b hit and return true. + if(data.value === null) {r = false} + else if(data.value == 'ALT=&IMG=&LINK=') {r = false;} //this is what a blank banner attribute will be set to + else if(data.value === 0) {} + else if(data.value) {} + else { + r = false; + } + dump(" -> r: "+r); + return r; + }, + + //if the value is blank, null, empty, undefined , return false (stops tlc processing on this statement) + dwiwemptybanner : function(data,thisTLC) { + var r = true; + //needs to be first or the blanket data.value will b hit and return true. + if(data.value == 'ALT=&IMG=&LINK=') {r = false;} //this is what a blank banner attribute will be set to + else if(!data.value) {r = false;} + //banner element type w/ content populated. + else if(data.value.indexOf('IMG=') >=0 && data.value.indexOf('LINK=') >= 0) { + var obj = _app.u.kvp2Array(data.value); + if(obj && !obj.IMG) {r = false;} + } + else { + r = false; + } + return r; + }, + +//Generate a list of thumbnails, adding srcset along the way. +//the image size for 768 and 1024 should be the same, specifically for magic zoom. That way the click to put an alternate image into the primary spot uses a consistent size. + proddetailthumbs : function(data,thisTLC) { + if(data.value && data.value['zoovy:prod_image2']) { + var + $div = $("<div \/>"), + dim = 250, + bodyWidth = $(document.body).width(); //dimensions of the primary product image. Used to generate the 'rev' for MZP. + + if(bodyWidth >= 640) {dim = 350} + else if(bodyWidth >= 1100) {dim = 500} + else {} //use default. + for(var i = 1; i <= 20; i += 1) { + if(data.value['zoovy:prod_image'+i]) { + $("<a \/>",{'data-app-click':'store_zephyrapp|prodThumb2Primary','href':thisTLC.makeImageURL({'data-media':data.value['zoovy:prod_image'+i],'data-bgcolor':'FFFFFF'})}).addClass('noioscontextmenu').append($("<img \/>",{ + 'src':thisTLC.makeImageURL({'width':50,'height':50,'data-media':data.value['zoovy:prod_image'+i],'data-bgcolor':'FFFFFF'}), + 'data-media' : data.value['zoovy:prod_image'+i], + //the first srcset value should match the default height and width, then grow from there. + 'srcset' : thisTLC.makeImageURL({'width':50,'height':50,'data-media':data.value['zoovy:prod_image'+i],'data-bgcolor':'FFFFFF'})+" 760w 1x, "+thisTLC.makeImageURL({'width':100,'height':100,'data-media':data.value['zoovy:prod_image'+i],'data-bgcolor':'FFFFFF'})+" 1100w 1x" + }).addClass('productThumb')).appendTo($div); + +// NOTE -> iphone wasn't reacting well to the 2x. +// , "+thisTLC.makeImageURL({'width':200,'height':200,'data-media':data.value['zoovy:prod_image'+i],'data-bgcolor':'FFFFFF'})+" 1024w 2x + } + else {break;} //exit early once a 'blank' is found in the img list. + } + data.globals.binds[data.globals.focusBind] = $div.children(); + } + return true; + }, + + shiptimestable : function(data,thisTLC) { + + var + $table = $("<table \/>").addClass('shippingEstimates'), + montharray=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"), + shipMethods = new Array( + {"method":"Free/Standard Shipping","shiptime":"1-8 Business Days*","ddoi":8}, //ddoi is deliveryDateObjectIndex + {"method":"Fedex Home Delivery","shiptime":"1-5 Business Days*","ddoi":5}, + {"method":"Fedex Express Saver","shiptime":"1-3 Business Days*","ddoi":3}, + {"method":"Fedex 2-Day","shiptime":"1-2 Business Days*","ddoi":2}, + {"method":"Fedex Overnight ","shiptime":"1 Business Day*","verbage":"Next Day"}, + {"method":"USPS Priority**","shiptime":"1-4 Business Day*","ddoi":7} + ); + $table.append("<thead><tr><th>Shipping Method<\/th><th>Approximate Shipping Time<\/th><th>Est. Delivery Date<\/th><\/tr><\/thead>"); + $table.append("<tfoot><tr><td colspan='3' class='hint'>*Estimates do not take into account national holidays and other days which Fedex or USPS may not be working or may have restricted delivery services.<br>**USPS Delivery Service is based on the timescale of the Postal Service. Estimated Delivery Dates may change without notice depending on the US Postal Service.<\/td><\/tr><\/tfoot>"); + + // This script came over from his existing website. The eval was commented out by JT. + // var num = 1; + // var temparray = document.location.href.split("?"); + // eval(temparray[1]); + + function getDeliveryDateObj(businessDaysLeftForDelivery) { + var now = new Date(); + var dayOfTheWeek = now.getDay(); + var hour = now.getHours(); + //after 12, add 1 business day. +// this didn't work as expected. didn't take weekends into consideration. +// var calendarDays = (hour < 13) ? businessDaysLeftForDelivery : businessDaysLeftForDelivery+1; // * 201403 -> added a +1 day for after 12:00 + var calendarDays = businessDaysLeftForDelivery; + var deliveryDay = dayOfTheWeek + businessDaysLeftForDelivery; + if (deliveryDay >= 6) { + //deduct this-week days + businessDaysLeftForDelivery -= 6 - dayOfTheWeek; + //count this coming weekend + calendarDays += 2; + //how many whole weeks? + deliveryWeeks = Math.floor(businessDaysLeftForDelivery / 5); + //two days per weekend per week + calendarDays += deliveryWeeks * 2; + } + now.setTime(now.getTime() + calendarDays * 24 * 60 * 60 * 1000); + return now; + } + + function showDate(num) { + var d=getDeliveryDateObj(num); + return (montharray[d.getMonth()] + " " + d.getDate()); + }; + var today = showDate(1); + for(var i = 0; i < shipMethods.length; i += 1) { + $table.append("<tr><td>"+shipMethods[i].method+"<\/td><td>"+shipMethods[i].shiptime+"<\/td><td>"+today+" - "+(shipMethods[i].verbage ? shipMethods[i].verbage : showDate(shipMethods[i].ddoi))+"<\/td><\/tr>"); + } + data.globals.tags[data.globals.focusTag].append($table); + return false; //this is a pretty specific format. kill any further processing. + } + + }, + + +//////////////////////////////////// RENDERFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + +//renderFormats are what is used to actually output data. +//on a data-bind, format: is equal to a renderformat. extension: tells the rendering engine where to look for the renderFormat. +//that way, two render formats named the same (but in different extensions) don't overwrite each other. + renderFormats : { + prodChildOption: function($tag, data){ + $tag.val(data.value.pid); + if(data.value['%attribs']['amz:grp_varvalue']){ + $tag.text(data.value['%attribs']['amz:grp_varvalue']); + } + else{ + $tag.text(data.value['%attribs']['zoovy:prod_name']); + } + }, + inventoryAvailQty : function($tag,data){ + if(data.value['%attribs']['zoovy:grp_type'] == 'PARENT'){ + // do nothing + } + else { + var inv = _app.ext.store_product.u.getProductInventory(data.value.pid); + if(inv > 0){ + $tag.append('In Stock Now (Qty avail: '+inv+')'); + } + else{ + // Taking out for time being since we already have an out of stock msg + // $tag.append('This product is currently out of stock'); + } + } + }, + + inventoryAvailQtyCart : function($tag,data){ + if(data.value['%attribs']['zoovy:grp_type'] == 'PARENT'){ + // do nothing + } + else { + var inv = _app.ext.store_product.u.getProductInventory(data.value.product); + if(inv > 0){ + $tag.append('In Stock Now (Qty avail: '+inv+')'); + } + else{ + // Taking out for time being since we already have an out of stock msg + // $tag.append('This product is currently out of stock'); + } + } + } + + }, //renderFormats +//////////////////////////////////// UTIL [u] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +//utilities are typically functions that are exected by an event or action. +//any functions that are recycled should be here. + u : { + //ele will likely be an entire template object. This will add the show/hide button for revealing more content IF the child element (actual text container) has a height greater than $ele. + revealation : function($ele) { + dump("BEGIN revealation"); + $('.textBlockMaxHeight',$ele).each(function(index){ + var $container = $(this), $text = $("[data-textblock-role='content']",$container); + $container.attr("data-textblock-role",'container').css('position','relative'); //when the class is toggled off, position will be too. but relative positioning necessary for the button to be visible. + function handleHeight(i) { + i++; + if($text.outerHeight() > $container.height()) { + $("<p>").addClass('textFadeOut').append($("<button \/>").addClass('smallButton').text('Show More').attr('data-app-click','store_zephyrapp|revealation').button()).appendTo($container); + } + else if($text.outerHeight() == 0 && $container.height() == 0) { //because of how the animation is handled, height may not be able to be computed right away. + if(1 < 10) { + setTimeout(function(){handleHeight(i);},250); + } + else {} //ok, tried enough times. maybe these are just empty. + } + else {} //text block is shorter than container. that's okay too. + } + handleHeight(0); + }); + }, + //this is a function because it's called as part of the productTemplate onComplete as well as in prodThumb2Primary + applyZoom : function($primaryImage) { +// dump(" -> $primaryImage.length: "+$primaryImage.length); + //the zoom plugin needs to be executed on the parent element of the image because it needs to add children. + $primaryImage.parent().zoom({ + 'url' : $primaryImage.parent().attr('href'), + 'touch' : true, + onZoomIn : function(){ + //for small screens, slide content so the primary image is at the top of the viewport, ensuring the 'zoom' is visible. + if($(document.body).width() < 500) { + var $picsContainer = $(this).closest(".vidsAndPics"); + if($picsContainer.length) { + var tabHeight = $('ul:first',$picsContainer).outerHeight() || 0; + $('html, body').animate({scrollTop : ($picsContainer.position().top + tabHeight + $('#mastHead').outerHeight() + 10)},500); + dump(" --------------> from top: "+($picsContainer.position().top + tabHeight + $('#mastHead').outerHeight())); + } + } + $(this).closest(".vidsAndPics").find('.zoomToolZoomContainer').show(); + }, + onZoomOut : function(){ + $(this).closest(".vidsAndPics").find('.zoomToolZoomContainer').hide(); + }, + 'target' : $primaryImage.closest(".vidsAndPics").find('.zoomToolZoomContainer') + }); + }, + + //MZP is, unfortunately, very ID centric. This function is executed in a product template oncomplete. + //it will add an id to the primary image, which is used for the mzp.start() and the 'rel' on the thumbnails. + //the rel will be generated for the thumbnails as well, so that the correct is used. + //for this reason, the 768 and 1024 image sizes should be the same for the primary product pic (so switching from portrait to landscape works ok) +/* handleMZP : function($product,infoObj) { +// dump("BEGIN handleMZP"); + if($product instanceof jQuery) { + var $href = $("[data-app-role='primaryImageHref']:first",$product), ID; + if($href.length) { + //mzp gives the href an id. Can't rely on that tho, so just in case, if none is set we generate and append our own. + if($href.attr('id')) { + ID = $href.attr('id'); + } + else { + ID = 'mzpzoom_'+_app.u.guidGenerator(); + $href.attr('id',ID); + } + //the rel gets set there because we have the ID. the rev is generated at the thumbs tlcFormat so that resolution specific sizing is all in the same place. + $("[data-app-role='productThumbnailsContainer']:first",$product).find('a').each(function(){ + $(this).attr({'id':'jt_'+_app.u.guidGenerator(),'rel':'zoom-id:'+ID+";group:"+infoObj.pid+";"}); + MagicZoomPlus.refresh($(this).attr('id')); //without this, the thumbnail won't register itself as part of the MZP (after the first page load. odd). + }); + + if($(document.body).outerWidth() > 760) { + $href.attr('rel',"zoom-position: right; group:"+infoObj.pid+";"); + } + else { + $href.attr('rel',"zoom-position: bottom; group:"+infoObj.pid+";"); + } +// SANITY -> tried to specify a specific ID for the refresh and it did not work to well in FF. +//it would, more often than not, fail to init which resulted in an image click opening the image in the window/tab in focus. + MagicZoomPlus.refresh(); + } + else { + dump("Unable to find the href for the primary image within the product layout. MagicZoomPlus will not work properly.","warn") + } + } + else { + dump("$product not a valid jquery instance for handleMZP. MZP will likely not work quite right.",'warn'); + } + }, + */ + randomizeList : function($list){ + $list.children().shuffle(); + }, + cacheRecentlyViewedItems: function ($container){ + _app.u.dump ('Caching product to recently viewed'); + var d = new Date().getTime(); + _app.storageFunctions.writeLocal('recentlyViewedItems', _app.ext.myRIA.vars.session.recentlyViewedItems); + _app.storageFunctions.writeLocal('timeStamp',d);// Add timestamp + }, + addItemToCart : function($form,obj){ + var $childSelect = $('.prodChildren.active select', $form); + if($childSelect.length > 0){ + if($childSelect.val()){ + _app.calls.cartItemAppend.init({"sku":$childSelect.val(), "qty":$('input[name=qty]',$form).val()},{},'immutable'); + _app.model.destroy('cartDetail'); + _app.calls.cartDetail.init({'callback':function(rd){ + if(obj.action === "modal"){ + showContent('cart',obj); + } + }},'immutable'); + _app.model.dispatchThis('immutable'); + } + else { + $form.anymessage(_app.u.errMsgObject("You must select an option")); + } + } + else { + _app.ext.myRIA.u.addItemToCart($form, obj); + } + }, + loginFormSubmit : function($form){ + var formJSON = $form.serializeJSON(); + _app.u.dump(formJSON); + var errors = ''; + var callback = $form.data('callback') || function(){showContent('customer',{'show':'myaccount'});}; + if(_app.u.isValidEmail(formJSON.login) == false){ + errors += "Please provide a valid email address<br \/>"; + } + if(!formJSON.password) { + errors += "Please provide your password<br \/>"; + } + + if(errors == ''){ + _app.calls.appBuyerLogin.init({"login":formJSON.login,"password":formJSON.password},{'callback':function(tagObj){ + _app.vars.cid = _app.data[tagObj.datapointer].cid; + _app.ext.myRIA.u.handleLoginActions(); + callback(); + }}); + _app.calls.refreshCart.init({},'immutable'); //cart needs to be updated as part of authentication process. +// _app.calls.buyerProductLists.init('forgetme',{'callback':'handleForgetmeList','extension':'store_prodlist'},'immutable'); + + _app.model.dispatchThis('immutable'); + } + else { + $form.anymessage({'message':errors}); + } + } + }, //u [utilities] + +//app-events are added to an element through data-app-event="extensionName|functionName" +//right now, these are not fully supported, but they will be going forward. +//they're used heavily in the admin.html file. +//while no naming convention is stricly forced, +//when adding an event, be sure to do off('click.appEventName') and then on('click.appEventName') to ensure the same event is not double-added if app events were to get run again over the same template. + e : { + + prodThumb2Primary : function($ele,p) { + p.preventDefault(); + var $primaryImageHref = $ele.closest("[data-anytab-content='images']").find("[data-app-role='primaryImageHref']:first"); + if($primaryImageHref.length) { + //re-translate the href, which will update the srcset attribute et all, passing in the clicked media elements filename (media) as image1 + $primaryImageHref.parent().tlc({ + "verb":"translate", + "dataset":{'%attribs':{'zoovy:prod_image1':$('img',$ele).data('media')}} + }); + $primaryImageHref.trigger('zoom.destroy'); // remove zoom + myApp.ext.store_zephyrapp.u.applyZoom($('img',$primaryImageHref)); + handleSrcSetUpdate($primaryImageHref.parent()); //trigger srcset to load the correct size image. + } + else { + dump("In zephyr_storeapp.e.prodThumb2Primary, unable to local primary image href. zoom will not work.","warn"); + } + return false; + }, + + jump2 : function($ele,p) { + p.preventDefault(); + var $jump2 = $ele.closest(".isPageTemplate").find("[data-landing-point='"+$ele.data('jump2')+"']"); + $('html, body').animate({ + scrollTop: $jump2.offset().top + }, 2000); + return false; + }, + + //used on a select element where the option value is the pid. selecting the option goes to the pid page. + changePageByOptionValue : function($ele,p) { + p.preventDefault(); + document.location.hash = $ele.val(); + return false; + }, + + productAdd2Cart : function($ele,p) { + p.preventDefault(); + //the buildCartItemAppendObj needs a _cartid param in the form. + if($("input[name='_cartid']",$ele).length) {} + else { + $ele.append("<input type='hidden' name='_cartid' value='"+_app.model.fetchCartID()+"' \/>"); + } + + var cartObj = _app.ext.store_product.u.buildCartItemAppendObj($ele); + if(cartObj) { + _app.ext.cco.calls.cartItemAppend.init(cartObj,{},'immutable'); + + _app.model.destroy('cartDetail|'+cartObj._cartid); + _app.calls.cartDetail.init(cartObj._cartid,{'callback':function(rd){ + if(_app.model.responseHasErrors(rd)){ + $('#globalMessaging').anymessage({'message':rd}); + } + else { + if($ele.data('show') == 'inline') { + document.location.hash = '#!cart'; + } + else { + _app.ext.quickstart.u.showCartInModal({'templateID':'cartTemplate'}); + } + cartMessagePush(cartObj._cartid,'cart.itemAppend',_app.u.getWhitelistedObject(cartObj,['sku','pid','qty','quantity','%variations'])); + } + }},'immutable'); + _app.model.dispatchThis('immutable'); + + } + else {} //do nothing, the validation handles displaying the errors. + return false; + }, + + revealation : function($ele,p) { + p.preventDefault(); + var $container = $ele.closest("[data-textblock-role='container']"); + if($container.length) { + + if($container.attr('data-maxheight')) {} //only set this once. + else {$container.attr('data-maxheight',$container.css('max-height'));} //used to restore + + //text block is already 'open'. so close it. + if($ele.data('state') == 'open') { + $container.addClass('textBlockMaxHeight').css('padding-bottom','0');; //restore to default state. + $ele.data('state','closed').find('.ui-button-text').text('Show More'); + } + else { + $container.removeClass('textBlockMaxHeight').css('padding-bottom','2em'); //padding is to compensate for fadeout/button. + $ele.data('state','open').find('.ui-button-text').text('Show Less'); + } + } + else { + $('#globalMessaging').anymessage({"message":"For zephyr.e.revealation, no .textBlockMaxHeight found as parent of trigger element.","gMessage":true}); + } + return false; + }, + + authWithNoRedir : function($ele,p) { + p.preventDefault(); + _app.ext.quickstart.u.showLoginModal(); + $('#loginSuccessContainer').empty(); //empty any existing login messaging (errors/warnings/etc) +//this code is here instead of in showLoginModal (currently) because the 'showCustomer' code is bound to the 'close' on the modal. + $('<button>').attr('id','modalLoginContinueButton').text('Continue').button().click(function(){ + $('#loginFormForModal').dialog('close'); + }).appendTo($('#loginSuccessContainer')); + return false; + }, + + youtubeSwapExec : function($ele,p) { + p.preventDefault(); + if($ele.data('videoid')) { + var $target = $ele.closest("[data-app-role='videoTabContent']").find("[data-app-role='videoContainer']"); + $target.empty(); + _app.renderFormats.youtubevideo($target,{'value':$ele.data('videoid'),'bindData':{}}); + $ele.closest("[data-app-role='videoTabContent']").find('.ui-button').button('enable'); + $ele.button('disable'); + } + else { + $("#globalMessaging").anymessage({"message":"In store_zephyrapp.e.youtubeSwapExec, no videoid set on trigger element.","gMessage":true}); + } + return false; + } + + } //e [app Events] + } //r object. + return r; + } \ No newline at end of file diff --git a/extensions/tools_ab_testing.js b/extensions/tools_ab_testing.js index 837900dc8..2183eb76b 100644 --- a/extensions/tools_ab_testing.js +++ b/extensions/tools_ab_testing.js @@ -32,7 +32,7 @@ Add support for data-mining- hooks for google analytics tracking */ -var tools_ABtesting = function() { +var tools_ab_testing = function(_app) { var theseTemplates = new Array(''); var r = { @@ -56,10 +56,10 @@ var tools_ABtesting = function() { //DETERMINE EXPERIMENTAL GROUPS //Grab any stored groupings for user consistency (a user will experience the same feature on returning to the app) - var cachedGroupings = app.storageFunctions.readLocal(app.ext.tools_ABtesting.vars.localStorageKey); + var cachedGroupings = _app.model.readLocal(_app.ext.tools_ABtesting.vars.localStorageKey,'local'); //Delete the stored groupings. They will be rewritten after any non-existing groupings are assigned. - localStorage.removeItem(app.ext.tools_ABtesting.vars.localStorageKey); + _app.model.nukeLocal(_app.ext.tools_ABtesting.vars.localStorageKey,'local'); //if no value was present in localstorage, the storageFunctions attempts to readCookie instead //if no cookie is present, false is returned. In this case start fresh. @@ -68,20 +68,20 @@ var tools_ABtesting = function() { } - for(var key in app.ext.tools_ABtesting.vars.groupings){ + for(var key in _app.ext.tools_ABtesting.vars.groupings){ //load cached groupings. Replaces cached groupings that are outside current scope of the grouping - if(cachedGroupings[key] && cachedGroupings[key] < app.ext.tools_ABtesting.vars.groupings[key]){ - app.ext.tools_ABtesting.vars.groupings[key] = cachedGroupings[key]; + if(cachedGroupings[key] && cachedGroupings[key] < _app.ext.tools_ABtesting.vars.groupings[key]){ + _app.ext.tools_ABtesting.vars.groupings[key] = cachedGroupings[key]; } else{ //assign new grouping - app.ext.tools_ABtesting.vars.groupings[key] = Math.floor(Math.random()*app.ext.tools_ABtesting.vars.groupings[key]); - //app.u.dump(key+": "+app.ext.tools_ABtesting.vars.groupings[key]); + _app.ext.tools_ABtesting.vars.groupings[key] = Math.floor(Math.random()*_app.ext.tools_ABtesting.vars.groupings[key]); + //_app.u.dump(key+": "+_app.ext.tools_ABtesting.vars.groupings[key]); } } //re-write localStorage. Previously cached vars that have no grouping in the current extension are tossed, to avoid localStorage buildup. - app.storageFunctions.writeLocal(app.ext.tools_ABtesting.vars.localStorageKey, app.ext.tools_ABtesting.vars.groupings); + _app.model.writeLocal(_app.ext.tools_ABtesting.vars.localStorageKey, _app.ext.tools_ABtesting.vars.groupings); //if there is any functionality required for this extension to load, put it here. such as a check for async google, the FB object, etc. return false if dependencies are not present. don't check for other extensions. @@ -90,7 +90,7 @@ var tools_ABtesting = function() { return r; }, onError : function() { - app.u.dump('BEGIN tools_ABtesting.callbacks.init.onError'); + _app.u.dump('BEGIN tools_ABtesting.callbacks.init.onError'); } } }, //callbacks @@ -107,7 +107,7 @@ var tools_ABtesting = function() { renderFormats : { exampleABRenderFormat: function($tag, data){ - switch(app.ext.tools_ABtesting.vars.groupings.exampleFeature){ + switch(_app.ext.tools_ABtesting.vars.groupings.exampleFeature){ case 0: $tag.text("A: "+data.value); break; diff --git a/extensions/tools_animation.js b/extensions/tools_animation.js index 007857854..13167d9b1 100644 --- a/extensions/tools_animation.js +++ b/extensions/tools_animation.js @@ -19,7 +19,7 @@ -var tools_animation = function() { +var tools_animation = function(_app) { var theseTemplates = new Array(''); var r = { @@ -39,8 +39,8 @@ var tools_animation = function() { init : { onSuccess : function() { var r = false; - app.ext.tools_animation.vars.anims = {}; - app.ext.tools_animation.aq = {}; + _app.ext.tools_animation.vars.anims = {}; + _app.ext.tools_animation.aq = {}; //Must be accessed from the window namespace window.animFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || @@ -50,17 +50,17 @@ var tools_animation = function() { function(callback){ window.setTimeout(callback, 1000/60); }; - app.ext.tools_animation.u.animLoop(); + _app.ext.tools_animation.u.animLoop(); //Set up delegated events $('body').on('mouseenter.animation', '[data-animation-mouseenter]', function(){ var args = $(this).attr('data-animation-mouseenter'); var anim = args.split('?')[0]; - var params = app.u.kvp2Array(args.split('?')[1]); + var params = _app.u.kvp2Array(args.split('?')[1]); - app.ext.tools_animation.u.stopAnim(anim); - app.ext.tools_animation.u.startAnim(anim, params); + _app.ext.tools_animation.u.stopAnim(anim); + _app.ext.tools_animation.u.startAnim(anim, params); }); @@ -68,10 +68,10 @@ var tools_animation = function() { var args = $(this).attr('data-animation-mouseout'); var anim = args.split('?')[0]; - var params = app.u.kvp2Array(args.split('?')[1]); + var params = _app.u.kvp2Array(args.split('?')[1]); - app.ext.tools_animation.u.stopAnim(anim); - app.ext.tools_animation.u.startAnim(anim, params); + _app.ext.tools_animation.u.stopAnim(anim); + _app.ext.tools_animation.u.startAnim(anim, params); }); @@ -80,7 +80,7 @@ var tools_animation = function() { return r; }, onError : function() { - app.u.dump('BEGIN tools_animation.callbacks.init.onError'); + _app.u.dump('BEGIN tools_animation.callbacks.init.onError'); } } }, //callbacks @@ -106,7 +106,7 @@ var tools_animation = function() { } else { animation.currFrame = animation.frameCount-1; - app.ext.tools_animation.u.stopAnim(animKey); + _app.ext.tools_animation.u.stopAnim(animKey); if(animation.animCallback && typeof animation.animCallback == 'function'){ animation.animCallback(animation); } @@ -124,7 +124,7 @@ var tools_animation = function() { } else { animation.currFrame = 0; - app.ext.tools_animation.u.stopAnim(animKey); + _app.ext.tools_animation.u.stopAnim(animKey); if(animation.animCallback && typeof animation.animCallback == 'function'){ animation.animCallback(animation); } @@ -132,7 +132,7 @@ var tools_animation = function() { } }, stop : function(animation, time, delta, animKey){ - app.ext.tools_animation.u.stopAnim(animKey); + _app.ext.tools_animation.u.stopAnim(animKey); if(animation.animCallback && typeof animation.animCallback == 'function'){ animation.animCallback(animation); } @@ -172,12 +172,12 @@ var tools_animation = function() { startAnim : function(animation, params){ params = params || {}; - if(app.ext.tools_animation.vars.anims[animation]){ - if (params.animFunc && typeof params.animFunc == 'string' && app.ext.tools_animation.animations[params.animFunc]){ - params.animFunc = app.ext.tools_animation.animations[params.animFunc]; + if(_app.ext.tools_animation.vars.anims[animation]){ + if (params.animFunc && typeof params.animFunc == 'string' && _app.ext.tools_animation.animations[params.animFunc]){ + params.animFunc = _app.ext.tools_animation.animations[params.animFunc]; } - if (params.animCallback && typeof params.animCallback == 'string' && app.ext.tools_animation.animCallbacks[params.animCallback]){ - params.animCallback = app.ext.tools_animation.animCallbacks[params.animCallback]; + if (params.animCallback && typeof params.animCallback == 'string' && _app.ext.tools_animation.animCallbacks[params.animCallback]){ + params.animCallback = _app.ext.tools_animation.animCallbacks[params.animCallback]; } if(params.start){ params.currFrame = Number(params.start); @@ -185,18 +185,18 @@ var tools_animation = function() { } for(var p in params){ - app.ext.tools_animation.vars.anims[animation][p] = params[p]; + _app.ext.tools_animation.vars.anims[animation][p] = params[p]; } - app.ext.tools_animation.aq[animation] = app.ext.tools_animation.vars.anims[animation]; + _app.ext.tools_animation.aq[animation] = _app.ext.tools_animation.vars.anims[animation]; } else { - app.u.dump("-> ERROR app.ext.tools_animation.u.startAnim: Animation "+animation+" has not yet been loaded!"); + _app.u.dump("-> ERROR _app.ext.tools_animation.u.startAnim: Animation "+animation+" has not yet been loaded!"); } }, stopAnim : function(animation){ - delete app.ext.tools_animation.aq[animation]; + delete _app.ext.tools_animation.aq[animation]; }, loadAnim : function($tag, name, params){ @@ -224,56 +224,56 @@ var tools_animation = function() { if(params.animFunc && typeof params.animFunc == 'function'){ animation.animFunc = params.animFunc; } - else if (params.animFunc && typeof params.animFunc == 'string' && app.ext.tools_animation.animations[params.animFunc]){ - animation.animFunc = app.ext.tools_animation.animations[params.animFunc]; + else if (params.animFunc && typeof params.animFunc == 'string' && _app.ext.tools_animation.animations[params.animFunc]){ + animation.animFunc = _app.ext.tools_animation.animations[params.animFunc]; } if(params.animCallback && typeof params.animCallback == 'function'){ animation.animCallback = params.animCallback; } - else if (params.animCallback && typeof params.animCallback == 'string' && app.ext.tools_animation.animCallbacks[params.animCallback]){ - animation.animCallback = app.ext.tools_animation.animCallbacks[params.animCallback]; + else if (params.animCallback && typeof params.animCallback == 'string' && _app.ext.tools_animation.animCallbacks[params.animCallback]){ + animation.animCallback = _app.ext.tools_animation.animCallbacks[params.animCallback]; } var xpos = animation.x1 + (animation.currFrame * (animation.width + animation.xGap)); animation.$tag.css('background', 'url('+animation.imgsrc+') no-repeat '+(-1*xpos)+'px '+(-1*animation.y)+'px'); - app.ext.tools_animation.vars.anims[name] = animation; + _app.ext.tools_animation.vars.anims[name] = animation; } else { - app.u.dump("-> ERROR app.ext.tools_animation.u.loadAnim: Some required parameters were left out"); + _app.u.dump("-> ERROR _app.ext.tools_animation.u.loadAnim: Some required parameters were left out"); } }, animLoop : function(){ //Wake from our slumber - var newTime = app.ext.tools_animation.u.now(); - if(!app.ext.tools_animation.metrics.lastFPSTime){ - app.ext.tools_animation.metrics.lastFPSTime = newTime; + var newTime = _app.ext.tools_animation.u.now(); + if(!_app.ext.tools_animation.metrics.lastFPSTime){ + _app.ext.tools_animation.metrics.lastFPSTime = newTime; } //Delta in millis, so that frame duration can be specified in millis also - var delta = newTime - app.ext.tools_animation.metrics.lastTime + var delta = newTime - _app.ext.tools_animation.metrics.lastTime //Run the animations - for(var anim in app.ext.tools_animation.aq){ - //app.ext.tools_animation.u.update(app.ext.tools_animation.aq[anim], newTime, delta); - app.ext.tools_animation.aq[anim].animFunc(app.ext.tools_animation.aq[anim], newTime, delta, anim); + for(var anim in _app.ext.tools_animation.aq){ + //_app.ext.tools_animation.u.update(_app.ext.tools_animation.aq[anim], newTime, delta); + _app.ext.tools_animation.aq[anim].animFunc(_app.ext.tools_animation.aq[anim], newTime, delta, anim); } //Update an report metrics - app.ext.tools_animation.metrics.frames++ - app.ext.tools_animation.metrics.lastTime = newTime; + _app.ext.tools_animation.metrics.frames++ + _app.ext.tools_animation.metrics.lastTime = newTime; - if(newTime - app.ext.tools_animation.metrics.lastFPSTime >= 1000){ - app.ext.tools_animation.metrics.fps = app.ext.tools_animation.metrics.frames; - app.ext.tools_animation.metrics.frames = 0; - app.ext.tools_animation.metrics.lastFPSTime = newTime; - if(app.ext.tools_animation.metrics.dumpMetrics){ - app.u.dump("-> app.ext.tools_animation.metrics.fps at "+newTime+": "+app.ext.tools_animation.metrics.fps); + if(newTime - _app.ext.tools_animation.metrics.lastFPSTime >= 1000){ + _app.ext.tools_animation.metrics.fps = _app.ext.tools_animation.metrics.frames; + _app.ext.tools_animation.metrics.frames = 0; + _app.ext.tools_animation.metrics.lastFPSTime = newTime; + if(_app.ext.tools_animation.metrics.dumpMetrics){ + _app.u.dump("-> _app.ext.tools_animation.metrics.fps at "+newTime+": "+_app.ext.tools_animation.metrics.fps); } } - window.animFrame(app.ext.tools_animation.u.animLoop); + window.animFrame(_app.ext.tools_animation.u.animLoop); }, now : function(){ diff --git a/extensions/tools_magnificpopup/extension.js b/extensions/tools_magnificpopup/extension.js new file mode 100644 index 000000000..796b4a2ab --- /dev/null +++ b/extensions/tools_magnificpopup/extension.js @@ -0,0 +1,94 @@ +/* ************************************************************** + + Copyright 2013 Zoovy, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +************************************************************** */ + + + +// Intended as a free, open source alternative to 3rd party plugins like Magic Zoom Plus. +// Utilizes the Magnific Popup jQuery plugin: http://dimsemenov.com/plugins/magnific-popup/ + +var tools_magnificpopup = function(_app) { + var r = { + callbacks : { + init : { + onSuccess : function() { + var r = false; + + _app.u.loadResourceFile(['script',0,'extensions/tools_magnificpopup/magnificpopup/jquery.magnificpopup.js']); + _app.u.loadResourceFile(['css',0,'extensions/tools_magnificpopup/magnificpopup/magnificpopup.css','css-magnificpopup']); + + _app.rq.push (['templateFunction', 'productTemplate', 'onCompletes', function(P) { + var $context = $(_app.u.jqSelector('#',P.parentID)); + _app.ext.tools_magnificpopup.u.callMagnificPopup($context); + }]); + + r = true; + + return r; + }, + onError : function() { + _app.u.dump('BEGIN tools_magnificpopup.callbacks.init.onError'); + } + } + }, //callbacks + + a : { + + }, //a [actions] + + renderFormats : { + imageURL2Href : function($tag, data){ + _app.renderFormats.imageURL2Href($tag,data); + + $tag.attr('data-magnificpopup','imgLink'); + } + }, //renderFormats + + u : { + callMagnificPopup : function($context, attempts){ + attempts = attempts || 0; + if(typeof $.fn.magnificPopup !== "undefined"){ + + var $imgContainer = $('[data-magnificpopup=imgContainer]', $context); + $imgContainer.magnificPopup({ + delegate: 'a[data-magnificpopup=imgLink]', + type: 'image', + gallery: {enabled:true} + }); + + var $imgContainer = $('[data-magnificpopup=imgContainerResponsive]', $context); + $imgContainer.magnificPopup({ + delegate: 'a[data-magnificpopup=imgLink]', + type: 'image', + gallery: {enabled:true} + }); + } + else { + if(attempts > 40){ + _app.u.dump("Magnific Popup FAILED "); + } + else { + setTimeout(function(){_app.ext.tools_magnificpopup.u.callMagnificPopup($context, attempts+1);}, 250); + } + } + } + + } //u [utilities] + + } //r object. + return r; + } \ No newline at end of file diff --git a/extensions/tools_magnificpopup/magnificpopup/jquery.magnificpopup.js b/extensions/tools_magnificpopup/magnificpopup/jquery.magnificpopup.js new file mode 100644 index 000000000..4daeba962 --- /dev/null +++ b/extensions/tools_magnificpopup/magnificpopup/jquery.magnificpopup.js @@ -0,0 +1,2037 @@ +/*! Magnific Popup - v0.9.6 - 2013-10-01 +* http://dimsemenov.com/plugins/magnific-popup/ +* Copyright (c) 2013 Dmitry Semenov; */ +;(function($) { + +/*>>core*/ +/** + * + * Magnific Popup Core JS file + * + */ + + +/** + * Private static constants + */ +var CLOSE_EVENT = 'Close', + BEFORE_CLOSE_EVENT = 'BeforeClose', + AFTER_CLOSE_EVENT = 'AfterClose', + BEFORE_APPEND_EVENT = 'BeforeAppend', + MARKUP_PARSE_EVENT = 'MarkupParse', + OPEN_EVENT = 'Open', + CHANGE_EVENT = 'Change', + NS = 'mfp', + EVENT_NS = '.' + NS, + READY_CLASS = 'mfp-ready', + REMOVING_CLASS = 'mfp-removing', + PREVENT_CLOSE_CLASS = 'mfp-prevent-close'; + + +/** + * Private vars + */ +var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this' + MagnificPopup = function(){}, + _isJQ = !!(window.jQuery), + _prevStatus, + _window = $(window), + _body, + _document, + _prevContentType, + _wrapClasses, + _currPopupType; + + +/** + * Private functions + */ +var _mfpOn = function(name, f) { + mfp.ev.on(NS + name + EVENT_NS, f); + }, + _getEl = function(className, appendTo, html, raw) { + var el = document.createElement('div'); + el.className = 'mfp-'+className; + if(html) { + el.innerHTML = html; + } + if(!raw) { + el = $(el); + if(appendTo) { + el.appendTo(appendTo); + } + } else if(appendTo) { + appendTo.appendChild(el); + } + return el; + }, + _mfpTrigger = function(e, data) { + mfp.ev.triggerHandler(NS + e, data); + + if(mfp.st.callbacks) { + // converts "mfpEventName" to "eventName" callback and triggers it if it's present + e = e.charAt(0).toLowerCase() + e.slice(1); + if(mfp.st.callbacks[e]) { + mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]); + } + } + }, + _setFocus = function() { + (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus(); + }, + _getCloseBtn = function(type) { + if(type !== _currPopupType || !mfp.currTemplate.closeBtn) { + mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) ); + _currPopupType = type; + } + return mfp.currTemplate.closeBtn; + }, + // Initialize Magnific Popup only when called at least once + _checkInstance = function() { + if(!$.magnificPopup.instance) { + mfp = new MagnificPopup(); + mfp.init(); + $.magnificPopup.instance = mfp; + } + }, + // Check to close popup or not + // "target" is an element that was clicked + _checkIfClose = function(target) { + + if($(target).hasClass(PREVENT_CLOSE_CLASS)) { + return; + } + + var closeOnContent = mfp.st.closeOnContentClick; + var closeOnBg = mfp.st.closeOnBgClick; + + if(closeOnContent && closeOnBg) { + return true; + } else { + + // We close the popup if click is on close button or on preloader. Or if there is no content. + if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) { + return true; + } + + // if click is outside the content + if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) { + if(closeOnBg) { + // last check, if the clicked element is in DOM, (in case it's removed onclick) + if( $.contains(document, target) ) { + return true; + } + } + } else if(closeOnContent) { + return true; + } + + } + return false; + }, + // CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr + supportsTransitions = function() { + var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist + v = ['ms','O','Moz','Webkit']; // 'v' for vendor + + if( s['transition'] !== undefined ) { + return true; + } + + while( v.length ) { + if( v.pop() + 'Transition' in s ) { + return true; + } + } + + return false; + }; + + + +/** + * Public functions + */ +MagnificPopup.prototype = { + + constructor: MagnificPopup, + + /** + * Initializes Magnific Popup plugin. + * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed + */ + init: function() { + var appVersion = navigator.appVersion; + mfp.isIE7 = appVersion.indexOf("MSIE 7.") !== -1; + mfp.isIE8 = appVersion.indexOf("MSIE 8.") !== -1; + mfp.isLowIE = mfp.isIE7 || mfp.isIE8; + mfp.isAndroid = (/android/gi).test(appVersion); + mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion); + mfp.supportsTransition = supportsTransitions(); + + // We disable fixed positioned lightbox on devices that don't handle it nicely. + // If you know a better way of detecting this - let me know. + mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) ); + _body = $(document.body); + _document = $(document); + + mfp.popupsCache = {}; + }, + + /** + * Opens popup + * @param data [description] + */ + open: function(data) { + + var i; + + if(data.isObj === false) { + // convert jQuery collection to array to avoid conflicts later + mfp.items = data.items.toArray(); + + mfp.index = 0; + var items = data.items, + item; + for(i = 0; i < items.length; i++) { + item = items[i]; + if(item.parsed) { + item = item.el[0]; + } + if(item === data.el[0]) { + mfp.index = i; + break; + } + } + } else { + mfp.items = $.isArray(data.items) ? data.items : [data.items]; + mfp.index = data.index || 0; + } + + // if popup is already opened - we just update the content + if(mfp.isOpen) { + mfp.updateItemHTML(); + return; + } + + mfp.types = []; + _wrapClasses = ''; + if(data.mainEl && data.mainEl.length) { + mfp.ev = data.mainEl.eq(0); + } else { + mfp.ev = _document; + } + + if(data.key) { + if(!mfp.popupsCache[data.key]) { + mfp.popupsCache[data.key] = {}; + } + mfp.currTemplate = mfp.popupsCache[data.key]; + } else { + mfp.currTemplate = {}; + } + + + + mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); + mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos; + + if(mfp.st.modal) { + mfp.st.closeOnContentClick = false; + mfp.st.closeOnBgClick = false; + mfp.st.showCloseBtn = false; + mfp.st.enableEscapeKey = false; + } + + + // Building markup + // main containers are created only once + if(!mfp.bgOverlay) { + + // Dark overlay + mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() { + mfp.close(); + }); + + mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) { + if(_checkIfClose(e.target)) { + mfp.close(); + } + }); + + mfp.container = _getEl('container', mfp.wrap); + } + + mfp.contentContainer = _getEl('content'); + if(mfp.st.preloader) { + mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading); + } + + + // Initializing modules + var modules = $.magnificPopup.modules; + for(i = 0; i < modules.length; i++) { + var n = modules[i]; + n = n.charAt(0).toUpperCase() + n.slice(1); + mfp['init'+n].call(mfp); + } + _mfpTrigger('BeforeOpen'); + + + if(mfp.st.showCloseBtn) { + // Close button + if(!mfp.st.closeBtnInside) { + mfp.wrap.append( _getCloseBtn() ); + } else { + _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) { + values.close_replaceWith = _getCloseBtn(item.type); + }); + _wrapClasses += ' mfp-close-btn-in'; + } + } + + if(mfp.st.alignTop) { + _wrapClasses += ' mfp-align-top'; + } + + + + if(mfp.fixedContentPos) { + mfp.wrap.css({ + overflow: mfp.st.overflowY, + overflowX: 'hidden', + overflowY: mfp.st.overflowY + }); + } else { + mfp.wrap.css({ + top: _window.scrollTop(), + position: 'absolute' + }); + } + if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) { + mfp.bgOverlay.css({ + height: _document.height(), + position: 'absolute' + }); + } + + + + if(mfp.st.enableEscapeKey) { + // Close on ESC key + _document.on('keyup' + EVENT_NS, function(e) { + if(e.keyCode === 27) { + mfp.close(); + } + }); + } + + _window.on('resize' + EVENT_NS, function() { + mfp.updateSize(); + }); + + + if(!mfp.st.closeOnContentClick) { + _wrapClasses += ' mfp-auto-cursor'; + } + + if(_wrapClasses) + mfp.wrap.addClass(_wrapClasses); + + + // this triggers recalculation of layout, so we get it once to not to trigger twice + var windowHeight = mfp.wH = _window.height(); + + + var windowStyles = {}; + + if( mfp.fixedContentPos ) { + if(mfp._hasScrollBar(windowHeight)){ + var s = mfp._getScrollbarSize(); + if(s) { + windowStyles.paddingRight = s; + } + } + } + + if(mfp.fixedContentPos) { + if(!mfp.isIE7) { + windowStyles.overflow = 'hidden'; + } else { + // ie7 double-scroll bug + $('body, html').css('overflow', 'hidden'); + } + } + + + + var classesToadd = mfp.st.mainClass; + if(mfp.isIE7) { + classesToadd += ' mfp-ie7'; + } + if(classesToadd) { + mfp._addClassToMFP( classesToadd ); + } + + // add content + mfp.updateItemHTML(); + + _mfpTrigger('BuildControls'); + + + // remove scrollbar, add padding e.t.c + $('html').css(windowStyles); + + // add everything to DOM + mfp.bgOverlay.add(mfp.wrap).prependTo( document.body ); + + + + // Save last focused element + mfp._lastFocusedEl = document.activeElement; + + // Wait for next cycle to allow CSS transition + setTimeout(function() { + + if(mfp.content) { + mfp._addClassToMFP(READY_CLASS); + _setFocus(); + } else { + // if content is not defined (not loaded e.t.c) we add class only for BG + mfp.bgOverlay.addClass(READY_CLASS); + } + + // Trap the focus in popup + _document.on('focusin' + EVENT_NS, function (e) { + if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) { + _setFocus(); + return false; + } + }); + + }, 16); + + mfp.isOpen = true; + mfp.updateSize(windowHeight); + _mfpTrigger(OPEN_EVENT); + + return data; + }, + + /** + * Closes the popup + */ + close: function() { + if(!mfp.isOpen) return; + _mfpTrigger(BEFORE_CLOSE_EVENT); + + mfp.isOpen = false; + // for CSS3 animation + if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition ) { + mfp._addClassToMFP(REMOVING_CLASS); + setTimeout(function() { + mfp._close(); + }, mfp.st.removalDelay); + } else { + mfp._close(); + } + }, + + /** + * Helper for close() function + */ + _close: function() { + _mfpTrigger(CLOSE_EVENT); + + var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' '; + + mfp.bgOverlay.detach(); + mfp.wrap.detach(); + mfp.container.empty(); + + if(mfp.st.mainClass) { + classesToRemove += mfp.st.mainClass + ' '; + } + + mfp._removeClassFromMFP(classesToRemove); + + if(mfp.fixedContentPos) { + var windowStyles = {paddingRight: ''}; + if(mfp.isIE7) { + $('body, html').css('overflow', ''); + } else { + windowStyles.overflow = ''; + } + $('html').css(windowStyles); + } + + _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS); + mfp.ev.off(EVENT_NS); + + // clean up DOM elements that aren't removed + mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style'); + mfp.bgOverlay.attr('class', 'mfp-bg'); + mfp.container.attr('class', 'mfp-container'); + + // remove close button from target element + if(mfp.st.showCloseBtn && + (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) { + if(mfp.currTemplate.closeBtn) + mfp.currTemplate.closeBtn.detach(); + } + + + if(mfp._lastFocusedEl) { + $(mfp._lastFocusedEl).focus(); // put tab focus back + } + mfp.currItem = null; + mfp.content = null; + mfp.currTemplate = null; + mfp.prevHeight = 0; + + _mfpTrigger(AFTER_CLOSE_EVENT); + }, + + updateSize: function(winHeight) { + + if(mfp.isIOS) { + // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2 + var zoomLevel = document.documentElement.clientWidth / window.innerWidth; + var height = window.innerHeight * zoomLevel; + mfp.wrap.css('height', height); + mfp.wH = height; + } else { + mfp.wH = winHeight || _window.height(); + } + // Fixes #84: popup incorrectly positioned with position:relative on body + if(!mfp.fixedContentPos) { + mfp.wrap.css('height', mfp.wH); + } + + _mfpTrigger('Resize'); + + }, + + /** + * Set content of popup based on current index + */ + updateItemHTML: function() { + var item = mfp.items[mfp.index]; + + // Detach and perform modifications + mfp.contentContainer.detach(); + + if(mfp.content) + mfp.content.detach(); + + if(!item.parsed) { + item = mfp.parseEl( mfp.index ); + } + + var type = item.type; + + _mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]); + // BeforeChange event works like so: + // _mfpOn('BeforeChange', function(e, prevType, newType) { }); + + mfp.currItem = item; + + + + + + if(!mfp.currTemplate[type]) { + var markup = mfp.st[type] ? mfp.st[type].markup : false; + + // allows to modify markup + _mfpTrigger('FirstMarkupParse', markup); + + if(markup) { + mfp.currTemplate[type] = $(markup); + } else { + // if there is no markup found we just define that template is parsed + mfp.currTemplate[type] = true; + } + } + + if(_prevContentType && _prevContentType !== item.type) { + mfp.container.removeClass('mfp-'+_prevContentType+'-holder'); + } + + var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]); + mfp.appendContent(newContent, type); + + item.preloaded = true; + + _mfpTrigger(CHANGE_EVENT, item); + _prevContentType = item.type; + + // Append container back after its content changed + mfp.container.prepend(mfp.contentContainer); + + _mfpTrigger('AfterChange'); + }, + + + /** + * Set HTML content of popup + */ + appendContent: function(newContent, type) { + mfp.content = newContent; + + if(newContent) { + if(mfp.st.showCloseBtn && mfp.st.closeBtnInside && + mfp.currTemplate[type] === true) { + // if there is no markup, we just append close button element inside + if(!mfp.content.find('.mfp-close').length) { + mfp.content.append(_getCloseBtn()); + } + } else { + mfp.content = newContent; + } + } else { + mfp.content = ''; + } + + _mfpTrigger(BEFORE_APPEND_EVENT); + mfp.container.addClass('mfp-'+type+'-holder'); + + mfp.contentContainer.append(mfp.content); + }, + + + + + /** + * Creates Magnific Popup data object based on given data + * @param {int} index Index of item to parse + */ + parseEl: function(index) { + var item = mfp.items[index], + type = item.type; + + if(item.tagName) { + item = { el: $(item) }; + } else { + item = { data: item, src: item.src }; + } + + if(item.el) { + var types = mfp.types; + + // check for 'mfp-TYPE' class + for(var i = 0; i < types.length; i++) { + if( item.el.hasClass('mfp-'+types[i]) ) { + type = types[i]; + break; + } + } + + item.src = item.el.attr('data-mfp-src'); + if(!item.src) { + item.src = item.el.attr('href'); + } + } + + item.type = type || mfp.st.type || 'inline'; + item.index = index; + item.parsed = true; + mfp.items[index] = item; + _mfpTrigger('ElementParse', item); + + return mfp.items[index]; + }, + + + /** + * Initializes single popup or a group of popups + */ + addGroup: function(el, options) { + var eHandler = function(e) { + e.mfpEl = this; + mfp._openClick(e, el, options); + }; + + if(!options) { + options = {}; + } + + var eName = 'click.magnificPopup'; + options.mainEl = el; + + if(options.items) { + options.isObj = true; + el.off(eName).on(eName, eHandler); + } else { + options.isObj = false; + if(options.delegate) { + el.off(eName).on(eName, options.delegate , eHandler); + } else { + options.items = el; + el.off(eName).on(eName, eHandler); + } + } + }, + _openClick: function(e, el, options) { + var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick; + + + if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ) ) { + return; + } + + var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn; + + if(disableOn) { + if($.isFunction(disableOn)) { + if( !disableOn.call(mfp) ) { + return true; + } + } else { // else it's number + if( _window.width() < disableOn ) { + return true; + } + } + } + + if(e.type) { + e.preventDefault(); + + // This will prevent popup from closing if element is inside and popup is already opened + if(mfp.isOpen) { + e.stopPropagation(); + } + } + + + options.el = $(e.mfpEl); + if(options.delegate) { + options.items = el.find(options.delegate); + } + mfp.open(options); + }, + + + /** + * Updates text on preloader + */ + updateStatus: function(status, text) { + + if(mfp.preloader) { + if(_prevStatus !== status) { + mfp.container.removeClass('mfp-s-'+_prevStatus); + } + + if(!text && status === 'loading') { + text = mfp.st.tLoading; + } + + var data = { + status: status, + text: text + }; + // allows to modify status + _mfpTrigger('UpdateStatus', data); + + status = data.status; + text = data.text; + + mfp.preloader.html(text); + + mfp.preloader.find('a').on('click', function(e) { + e.stopImmediatePropagation(); + }); + + mfp.container.addClass('mfp-s-'+status); + _prevStatus = status; + } + }, + + + /* + "Private" helpers that aren't private at all + */ + _addClassToMFP: function(cName) { + mfp.bgOverlay.addClass(cName); + mfp.wrap.addClass(cName); + }, + _removeClassFromMFP: function(cName) { + this.bgOverlay.removeClass(cName); + mfp.wrap.removeClass(cName); + }, + _hasScrollBar: function(winHeight) { + return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) ); + }, + _parseMarkup: function(template, values, item) { + var arr; + if(item.data) { + values = $.extend(item.data, values); + } + _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] ); + + $.each(values, function(key, value) { + if(value === undefined || value === false) { + return true; + } + arr = key.split('_'); + if(arr.length > 1) { + var el = template.find(EVENT_NS + '-'+arr[0]); + + if(el.length > 0) { + var attr = arr[1]; + if(attr === 'replaceWith') { + if(el[0] !== value[0]) { + el.replaceWith(value); + } + } else if(attr === 'img') { + if(el.is('img')) { + el.attr('src', value); + } else { + el.replaceWith( '<img src="'+value+'" class="' + el.attr('class') + '" />' ); + } + } else { + el.attr(arr[1], value); + } + } + + } else { + template.find(EVENT_NS + '-'+key).html(value); + } + }); + }, + + _getScrollbarSize: function() { + // thx David + if(mfp.scrollbarSize === undefined) { + var scrollDiv = document.createElement("div"); + scrollDiv.id = "mfp-sbm"; + scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'; + document.body.appendChild(scrollDiv); + mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + } + return mfp.scrollbarSize; + } + +}; /* MagnificPopup core prototype end */ + + + + +/** + * Public static functions + */ +$.magnificPopup = { + instance: null, + proto: MagnificPopup.prototype, + modules: [], + + open: function(options, index) { + _checkInstance(); + + if(!options) { + options = {}; + } else { + options = $.extend(true, {}, options); + } + + + options.isObj = true; + options.index = index || 0; + return this.instance.open(options); + }, + + close: function() { + return $.magnificPopup.instance && $.magnificPopup.instance.close(); + }, + + registerModule: function(name, module) { + if(module.options) { + $.magnificPopup.defaults[name] = module.options; + } + $.extend(this.proto, module.proto); + this.modules.push(name); + }, + + defaults: { + + // Info about options is in docs: + // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options + + disableOn: 0, + + key: null, + + midClick: false, + + mainClass: '', + + preloader: true, + + focus: '', // CSS selector of input to focus after popup is opened + + closeOnContentClick: false, + + closeOnBgClick: true, + + closeBtnInside: true, + + showCloseBtn: true, + + enableEscapeKey: true, + + modal: false, + + alignTop: false, + + removalDelay: 0, + + fixedContentPos: 'auto', + + fixedBgPos: 'auto', + + overflowY: 'auto', + + closeMarkup: '<button title="%title%" type="button" class="mfp-close">×</button>', + + tClose: 'Close (Esc)', + + tLoading: 'Loading...' + + } +}; + + + +$.fn.magnificPopup = function(options) { + _checkInstance(); + + var jqEl = $(this); + + // We call some API method of first param is a string + if (typeof options === "string" ) { + + if(options === 'open') { + var items, + itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup, + index = parseInt(arguments[1], 10) || 0; + + if(itemOpts.items) { + items = itemOpts.items[index]; + } else { + items = jqEl; + if(itemOpts.delegate) { + items = items.find(itemOpts.delegate); + } + items = items.eq( index ); + } + mfp._openClick({mfpEl:items}, jqEl, itemOpts); + } else { + if(mfp.isOpen) + mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1)); + } + + } else { + // clone options obj + options = $.extend(true, {}, options); + + /* + * As Zepto doesn't support .data() method for objects + * and it works only in normal browsers + * we assign "options" object directly to the DOM element. FTW! + */ + if(_isJQ) { + jqEl.data('magnificPopup', options); + } else { + jqEl[0].magnificPopup = options; + } + + mfp.addGroup(jqEl, options); + + } + return jqEl; +}; + + +//Quick benchmark +/* +var start = performance.now(), + i, + rounds = 1000; + +for(i = 0; i < rounds; i++) { + +} +console.log('Test #1:', performance.now() - start); + +start = performance.now(); +for(i = 0; i < rounds; i++) { + +} +console.log('Test #2:', performance.now() - start); +*/ + + +/*>>core*/ + +/*>>inline*/ + +var INLINE_NS = 'inline', + _hiddenClass, + _inlinePlaceholder, + _lastInlineElement, + _putInlineElementsBack = function() { + if(_lastInlineElement) { + _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach(); + _lastInlineElement = null; + } + }; + +$.magnificPopup.registerModule(INLINE_NS, { + options: { + hiddenClass: 'hide', // will be appended with `mfp-` prefix + markup: '', + tNotFound: 'Content not found' + }, + proto: { + + initInline: function() { + mfp.types.push(INLINE_NS); + + _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() { + _putInlineElementsBack(); + }); + }, + + getInline: function(item, template) { + + _putInlineElementsBack(); + + if(item.src) { + var inlineSt = mfp.st.inline, + el = $(item.src); + + if(el.length) { + + // If target element has parent - we replace it with placeholder and put it back after popup is closed + var parent = el[0].parentNode; + if(parent && parent.tagName) { + if(!_inlinePlaceholder) { + _hiddenClass = inlineSt.hiddenClass; + _inlinePlaceholder = _getEl(_hiddenClass); + _hiddenClass = 'mfp-'+_hiddenClass; + } + // replace target inline element with placeholder + _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass); + } + + mfp.updateStatus('ready'); + } else { + mfp.updateStatus('error', inlineSt.tNotFound); + el = $('<div>'); + } + + item.inlineElement = el; + return el; + } + + mfp.updateStatus('ready'); + mfp._parseMarkup(template, {}, item); + return template; + } + } +}); + +/*>>inline*/ + +/*>>ajax*/ +var AJAX_NS = 'ajax', + _ajaxCur, + _removeAjaxCursor = function() { + if(_ajaxCur) { + _body.removeClass(_ajaxCur); + } + }, + _destroyAjaxRequest = function() { + _removeAjaxCursor(); + if(mfp.req) { + mfp.req.abort(); + } + }; + +$.magnificPopup.registerModule(AJAX_NS, { + + options: { + settings: null, + cursor: 'mfp-ajax-cur', + tError: '<a href="%url%">The content</a> could not be loaded.' + }, + + proto: { + initAjax: function() { + mfp.types.push(AJAX_NS); + _ajaxCur = mfp.st.ajax.cursor; + + _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest); + _mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest); + }, + getAjax: function(item) { + + if(_ajaxCur) + _body.addClass(_ajaxCur); + + mfp.updateStatus('loading'); + + var opts = $.extend({ + url: item.src, + success: function(data, textStatus, jqXHR) { + var temp = { + data:data, + xhr:jqXHR + }; + + _mfpTrigger('ParseAjax', temp); + + mfp.appendContent( $(temp.data), AJAX_NS ); + + item.finished = true; + + _removeAjaxCursor(); + + _setFocus(); + + setTimeout(function() { + mfp.wrap.addClass(READY_CLASS); + }, 16); + + mfp.updateStatus('ready'); + + _mfpTrigger('AjaxContentAdded'); + }, + error: function() { + _removeAjaxCursor(); + item.finished = item.loadError = true; + mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src)); + } + }, mfp.st.ajax.settings); + + mfp.req = $.ajax(opts); + + return ''; + } + } +}); + + + + + + + +/*>>ajax*/ + +/*>>image*/ +var _imgInterval, + _getTitle = function(item) { + if(item.data && item.data.title !== undefined) + return item.data.title; + + var src = mfp.st.image.titleSrc; + + if(src) { + if($.isFunction(src)) { + return src.call(mfp, item); + } else if(item.el) { + return item.el.attr(src) || ''; + } + } + return ''; + }; + +$.magnificPopup.registerModule('image', { + + options: { + markup: '<div class="mfp-figure">'+ + '<div class="mfp-close"></div>'+ + '<div class="mfp-img"></div>'+ + '<div class="mfp-bottom-bar">'+ + '<div class="mfp-title"></div>'+ + '<div class="mfp-counter"></div>'+ + '</div>'+ + '</div>', + cursor: 'mfp-zoom-out-cur', + titleSrc: 'title', + verticalFit: true, + tError: '<a href="%url%">The image</a> could not be loaded.' + }, + + proto: { + initImage: function() { + var imgSt = mfp.st.image, + ns = '.image'; + + mfp.types.push('image'); + + _mfpOn(OPEN_EVENT+ns, function() { + if(mfp.currItem.type === 'image' && imgSt.cursor) { + _body.addClass(imgSt.cursor); + } + }); + + _mfpOn(CLOSE_EVENT+ns, function() { + if(imgSt.cursor) { + _body.removeClass(imgSt.cursor); + } + _window.off('resize' + EVENT_NS); + }); + + _mfpOn('Resize'+ns, mfp.resizeImage); + if(mfp.isLowIE) { + _mfpOn('AfterChange', mfp.resizeImage); + } + }, + resizeImage: function() { + var item = mfp.currItem; + if(!item || !item.img) return; + + if(mfp.st.image.verticalFit) { + var decr = 0; + // fix box-sizing in ie7/8 + if(mfp.isLowIE) { + decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10); + } + item.img.css('max-height', mfp.wH-decr); + } + }, + _onImageHasSize: function(item) { + if(item.img) { + + item.hasSize = true; + + if(_imgInterval) { + clearInterval(_imgInterval); + } + + item.isCheckingImgSize = false; + + _mfpTrigger('ImageHasSize', item); + + if(item.imgHidden) { + if(mfp.content) + mfp.content.removeClass('mfp-loading'); + + item.imgHidden = false; + } + + } + }, + + /** + * Function that loops until the image has size to display elements that rely on it asap + */ + findImageSize: function(item) { + + var counter = 0, + img = item.img[0], + mfpSetInterval = function(delay) { + + if(_imgInterval) { + clearInterval(_imgInterval); + } + // decelerating interval that checks for size of an image + _imgInterval = setInterval(function() { + if(img.naturalWidth > 0) { + mfp._onImageHasSize(item); + return; + } + + if(counter > 200) { + clearInterval(_imgInterval); + } + + counter++; + if(counter === 3) { + mfpSetInterval(10); + } else if(counter === 40) { + mfpSetInterval(50); + } else if(counter === 100) { + mfpSetInterval(500); + } + }, delay); + }; + + mfpSetInterval(1); + }, + + getImage: function(item, template) { + + var guard = 0, + + // image load complete handler + onLoadComplete = function() { + if(item) { + if (item.img[0].complete) { + item.img.off('.mfploader'); + + if(item === mfp.currItem){ + mfp._onImageHasSize(item); + + mfp.updateStatus('ready'); + } + + item.hasSize = true; + item.loaded = true; + + _mfpTrigger('ImageLoadComplete'); + + } + else { + // if image complete check fails 200 times (20 sec), we assume that there was an error. + guard++; + if(guard < 200) { + setTimeout(onLoadComplete,100); + } else { + onLoadError(); + } + } + } + }, + + // image error handler + onLoadError = function() { + if(item) { + item.img.off('.mfploader'); + if(item === mfp.currItem){ + mfp._onImageHasSize(item); + mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); + } + + item.hasSize = true; + item.loaded = true; + item.loadError = true; + } + }, + imgSt = mfp.st.image; + + + var el = template.find('.mfp-img'); + if(el.length) { + var img = document.createElement('img'); + img.className = 'mfp-img'; + item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError); + img.src = item.src; + + // without clone() "error" event is not firing when IMG is replaced by new IMG + // TODO: find a way to avoid such cloning + if(el.is('img')) { + item.img = item.img.clone(); + } + if(item.img[0].naturalWidth > 0) { + item.hasSize = true; + } + } + + mfp._parseMarkup(template, { + title: _getTitle(item), + img_replaceWith: item.img + }, item); + + mfp.resizeImage(); + + if(item.hasSize) { + if(_imgInterval) clearInterval(_imgInterval); + + if(item.loadError) { + template.addClass('mfp-loading'); + mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); + } else { + template.removeClass('mfp-loading'); + mfp.updateStatus('ready'); + } + return template; + } + + mfp.updateStatus('loading'); + item.loading = true; + + if(!item.hasSize) { + item.imgHidden = true; + template.addClass('mfp-loading'); + mfp.findImageSize(item); + } + + return template; + } + } +}); + + + +/*>>image*/ + +/*>>zoom*/ +var hasMozTransform, + getHasMozTransform = function() { + if(hasMozTransform === undefined) { + hasMozTransform = document.createElement('p').style.MozTransform !== undefined; + } + return hasMozTransform; + }; + +$.magnificPopup.registerModule('zoom', { + + options: { + enabled: false, + easing: 'ease-in-out', + duration: 300, + opener: function(element) { + return element.is('img') ? element : element.find('img'); + } + }, + + proto: { + + initZoom: function() { + var zoomSt = mfp.st.zoom, + ns = '.zoom', + image; + + if(!zoomSt.enabled || !mfp.supportsTransition) { + return; + } + + var duration = zoomSt.duration, + getElToAnimate = function(image) { + var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'), + transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing, + cssObj = { + position: 'fixed', + zIndex: 9999, + left: 0, + top: 0, + '-webkit-backface-visibility': 'hidden' + }, + t = 'transition'; + + cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition; + + newImg.css(cssObj); + return newImg; + }, + showMainContent = function() { + mfp.content.css('visibility', 'visible'); + }, + openTimeout, + animatedImg; + + _mfpOn('BuildControls'+ns, function() { + if(mfp._allowZoom()) { + + clearTimeout(openTimeout); + mfp.content.css('visibility', 'hidden'); + + // Basically, all code below does is clones existing image, puts in on top of the current one and animated it + + image = mfp._getItemToZoom(); + + if(!image) { + showMainContent(); + return; + } + + animatedImg = getElToAnimate(image); + + animatedImg.css( mfp._getOffset() ); + + mfp.wrap.append(animatedImg); + + openTimeout = setTimeout(function() { + animatedImg.css( mfp._getOffset( true ) ); + openTimeout = setTimeout(function() { + + showMainContent(); + + setTimeout(function() { + animatedImg.remove(); + image = animatedImg = null; + _mfpTrigger('ZoomAnimationEnded'); + }, 16); // avoid blink when switching images + + }, duration); // this timeout equals animation duration + + }, 16); // by adding this timeout we avoid short glitch at the beginning of animation + + + // Lots of timeouts... + } + }); + _mfpOn(BEFORE_CLOSE_EVENT+ns, function() { + if(mfp._allowZoom()) { + + clearTimeout(openTimeout); + + mfp.st.removalDelay = duration; + + if(!image) { + image = mfp._getItemToZoom(); + if(!image) { + return; + } + animatedImg = getElToAnimate(image); + } + + + animatedImg.css( mfp._getOffset(true) ); + mfp.wrap.append(animatedImg); + mfp.content.css('visibility', 'hidden'); + + setTimeout(function() { + animatedImg.css( mfp._getOffset() ); + }, 16); + } + + }); + + _mfpOn(CLOSE_EVENT+ns, function() { + if(mfp._allowZoom()) { + showMainContent(); + if(animatedImg) { + animatedImg.remove(); + } + image = null; + } + }); + }, + + _allowZoom: function() { + return mfp.currItem.type === 'image'; + }, + + _getItemToZoom: function() { + if(mfp.currItem.hasSize) { + return mfp.currItem.img; + } else { + return false; + } + }, + + // Get element postion relative to viewport + _getOffset: function(isLarge) { + var el; + if(isLarge) { + el = mfp.currItem.img; + } else { + el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem); + } + + var offset = el.offset(); + var paddingTop = parseInt(el.css('padding-top'),10); + var paddingBottom = parseInt(el.css('padding-bottom'),10); + offset.top -= ( $(window).scrollTop() - paddingTop ); + + + /* + + Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa. + + */ + var obj = { + width: el.width(), + // fix Zepto height+padding issue + height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop + }; + + // I hate to do this, but there is no another option + if( getHasMozTransform() ) { + obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)'; + } else { + obj.left = offset.left; + obj.top = offset.top; + } + return obj; + } + + } +}); + + + +/*>>zoom*/ + +/*>>iframe*/ + +var IFRAME_NS = 'iframe', + _emptyPage = '//about:blank', + + _fixIframeBugs = function(isShowing) { + if(mfp.currTemplate[IFRAME_NS]) { + var el = mfp.currTemplate[IFRAME_NS].find('iframe'); + if(el.length) { + // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug + if(!isShowing) { + el[0].src = _emptyPage; + } + + // IE8 black screen bug fix + if(mfp.isIE8) { + el.css('display', isShowing ? 'block' : 'none'); + } + } + } + }; + +$.magnificPopup.registerModule(IFRAME_NS, { + + options: { + markup: '<div class="mfp-iframe-scaler">'+ + '<div class="mfp-close"></div>'+ + '<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+ + '</div>', + + srcAction: 'iframe_src', + + // we don't care and support only one default type of URL by default + patterns: { + youtube: { + index: 'youtube.com', + id: 'v=', + src: '//www.youtube.com/embed/%id%?autoplay=1' + }, + vimeo: { + index: 'vimeo.com/', + id: '/', + src: '//player.vimeo.com/video/%id%?autoplay=1' + }, + gmaps: { + index: '//maps.google.', + src: '%id%&output=embed' + } + } + }, + + proto: { + initIframe: function() { + mfp.types.push(IFRAME_NS); + + _mfpOn('BeforeChange', function(e, prevType, newType) { + if(prevType !== newType) { + if(prevType === IFRAME_NS) { + _fixIframeBugs(); // iframe if removed + } else if(newType === IFRAME_NS) { + _fixIframeBugs(true); // iframe is showing + } + }// else { + // iframe source is switched, don't do anything + //} + }); + + _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { + _fixIframeBugs(); + }); + }, + + getIframe: function(item, template) { + var embedSrc = item.src; + var iframeSt = mfp.st.iframe; + + $.each(iframeSt.patterns, function() { + if(embedSrc.indexOf( this.index ) > -1) { + if(this.id) { + if(typeof this.id === 'string') { + embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); + } else { + embedSrc = this.id.call( this, embedSrc ); + } + } + embedSrc = this.src.replace('%id%', embedSrc ); + return false; // break; + } + }); + + var dataObj = {}; + if(iframeSt.srcAction) { + dataObj[iframeSt.srcAction] = embedSrc; + } + mfp._parseMarkup(template, dataObj, item); + + mfp.updateStatus('ready'); + + return template; + } + } +}); + + + +/*>>iframe*/ + +/*>>gallery*/ +/** + * Get looped index depending on number of slides + */ +var _getLoopedId = function(index) { + var numSlides = mfp.items.length; + if(index > numSlides - 1) { + return index - numSlides; + } else if(index < 0) { + return numSlides + index; + } + return index; + }, + _replaceCurrTotal = function(text, curr, total) { + return text.replace('%curr%', curr + 1).replace('%total%', total); + }; + +$.magnificPopup.registerModule('gallery', { + + options: { + enabled: false, + arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>', + preload: [0,2], + navigateByImgClick: true, + arrows: true, + + tPrev: 'Previous (Left arrow key)', + tNext: 'Next (Right arrow key)', + tCounter: '%curr% of %total%' + }, + + proto: { + initGallery: function() { + + var gSt = mfp.st.gallery, + ns = '.mfp-gallery', + supportsFastClick = Boolean($.fn.mfpFastClick); + + mfp.direction = true; // true - next, false - prev + + if(!gSt || !gSt.enabled ) return false; + + _wrapClasses += ' mfp-gallery'; + + _mfpOn(OPEN_EVENT+ns, function() { + + if(gSt.navigateByImgClick) { + mfp.wrap.on('click'+ns, '.mfp-img', function() { + if(mfp.items.length > 1) { + mfp.next(); + return false; + } + }); + } + + _document.on('keydown'+ns, function(e) { + if (e.keyCode === 37) { + mfp.prev(); + } else if (e.keyCode === 39) { + mfp.next(); + } + }); + }); + + _mfpOn('UpdateStatus'+ns, function(e, data) { + if(data.text) { + data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); + } + }); + + _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { + var l = mfp.items.length; + values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; + }); + + _mfpOn('BuildControls' + ns, function() { + if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) { + var markup = gSt.arrowMarkup, + arrowLeft = mfp.arrowLeft = $( markup.replace('%title%', gSt.tPrev).replace('%dir%', 'left') ).addClass(PREVENT_CLOSE_CLASS), + arrowRight = mfp.arrowRight = $( markup.replace('%title%', gSt.tNext).replace('%dir%', 'right') ).addClass(PREVENT_CLOSE_CLASS); + + var eName = supportsFastClick ? 'mfpFastClick' : 'click'; + arrowLeft[eName](function() { + mfp.prev(); + }); + arrowRight[eName](function() { + mfp.next(); + }); + + // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b) + if(mfp.isIE7) { + _getEl('b', arrowLeft[0], false, true); + _getEl('a', arrowLeft[0], false, true); + _getEl('b', arrowRight[0], false, true); + _getEl('a', arrowRight[0], false, true); + } + + mfp.container.append(arrowLeft.add(arrowRight)); + } + }); + + _mfpOn(CHANGE_EVENT+ns, function() { + if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); + + mfp._preloadTimeout = setTimeout(function() { + mfp.preloadNearbyImages(); + mfp._preloadTimeout = null; + }, 16); + }); + + + _mfpOn(CLOSE_EVENT+ns, function() { + _document.off(ns); + mfp.wrap.off('click'+ns); + + if(mfp.arrowLeft && supportsFastClick) { + mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick(); + } + mfp.arrowRight = mfp.arrowLeft = null; + }); + + }, + next: function() { + mfp.direction = true; + mfp.index = _getLoopedId(mfp.index + 1); + mfp.updateItemHTML(); + }, + prev: function() { + mfp.direction = false; + mfp.index = _getLoopedId(mfp.index - 1); + mfp.updateItemHTML(); + }, + goTo: function(newIndex) { + mfp.direction = (newIndex >= mfp.index); + mfp.index = newIndex; + mfp.updateItemHTML(); + }, + preloadNearbyImages: function() { + var p = mfp.st.gallery.preload, + preloadBefore = Math.min(p[0], mfp.items.length), + preloadAfter = Math.min(p[1], mfp.items.length), + i; + + for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { + mfp._preloadItem(mfp.index+i); + } + for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { + mfp._preloadItem(mfp.index-i); + } + }, + _preloadItem: function(index) { + index = _getLoopedId(index); + + if(mfp.items[index].preloaded) { + return; + } + + var item = mfp.items[index]; + if(!item.parsed) { + item = mfp.parseEl( index ); + } + + _mfpTrigger('LazyLoad', item); + + if(item.type === 'image') { + item.img = $('<img class="mfp-img" />').on('load.mfploader', function() { + item.hasSize = true; + }).on('error.mfploader', function() { + item.hasSize = true; + item.loadError = true; + _mfpTrigger('LazyLoadError', item); + }).attr('src', item.src); + } + + + item.preloaded = true; + } + } +}); + +/* +Touch Support that might be implemented some day + +addSwipeGesture: function() { + var startX, + moved, + multipleTouches; + + return; + + var namespace = '.mfp', + addEventNames = function(pref, down, move, up, cancel) { + mfp._tStart = pref + down + namespace; + mfp._tMove = pref + move + namespace; + mfp._tEnd = pref + up + namespace; + mfp._tCancel = pref + cancel + namespace; + }; + + if(window.navigator.msPointerEnabled) { + addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel'); + } else if('ontouchstart' in window) { + addEventNames('touch', 'start', 'move', 'end', 'cancel'); + } else { + return; + } + _window.on(mfp._tStart, function(e) { + var oE = e.originalEvent; + multipleTouches = moved = false; + startX = oE.pageX || oE.changedTouches[0].pageX; + }).on(mfp._tMove, function(e) { + if(e.originalEvent.touches.length > 1) { + multipleTouches = e.originalEvent.touches.length; + } else { + //e.preventDefault(); + moved = true; + } + }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) { + if(moved && !multipleTouches) { + var oE = e.originalEvent, + diff = startX - (oE.pageX || oE.changedTouches[0].pageX); + + if(diff > 20) { + mfp.next(); + } else if(diff < -20) { + mfp.prev(); + } + } + }); +}, +*/ + + +/*>>gallery*/ + +/*>>retina*/ + +var RETINA_NS = 'retina'; + +$.magnificPopup.registerModule(RETINA_NS, { + options: { + replaceSrc: function(item) { + return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); + }, + ratio: 1 // Function or number. Set to 1 to disable. + }, + proto: { + initRetina: function() { + if(window.devicePixelRatio > 1) { + + var st = mfp.st.retina, + ratio = st.ratio; + + ratio = !isNaN(ratio) ? ratio : ratio(); + + if(ratio > 1) { + _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { + item.img.css({ + 'max-width': item.img[0].naturalWidth / ratio, + 'width': '100%' + }); + }); + _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { + item.src = st.replaceSrc(item, ratio); + }); + } + } + + } + } +}); + +/*>>retina*/ + +/*>>fastclick*/ +/** + * FastClick event implementation. (removes 300ms delay on touch devices) + * Based on https://developers.google.com/mobile/articles/fast_buttons + * + * You may use it outside the Magnific Popup by calling just: + * + * $('.your-el').mfpFastClick(function() { + * console.log('Clicked!'); + * }); + * + * To unbind: + * $('.your-el').destroyMfpFastClick(); + * + * + * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound. + * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick + * + */ + +(function() { + var ghostClickDelay = 1000, + supportsTouch = 'ontouchstart' in window, + unbindTouchMove = function() { + _window.off('touchmove'+ns+' touchend'+ns); + }, + eName = 'mfpFastClick', + ns = '.'+eName; + + + // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way + $.fn.mfpFastClick = function(callback) { + + return $(this).each(function() { + + var elem = $(this), + lock; + + if( supportsTouch ) { + + var timeout, + startX, + startY, + pointerMoved, + point, + numPointers; + + elem.on('touchstart' + ns, function(e) { + pointerMoved = false; + numPointers = 1; + + point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0]; + startX = point.clientX; + startY = point.clientY; + + _window.on('touchmove'+ns, function(e) { + point = e.originalEvent ? e.originalEvent.touches : e.touches; + numPointers = point.length; + point = point[0]; + if (Math.abs(point.clientX - startX) > 10 || + Math.abs(point.clientY - startY) > 10) { + pointerMoved = true; + unbindTouchMove(); + } + }).on('touchend'+ns, function(e) { + unbindTouchMove(); + if(pointerMoved || numPointers > 1) { + return; + } + lock = true; + e.preventDefault(); + clearTimeout(timeout); + timeout = setTimeout(function() { + lock = false; + }, ghostClickDelay); + callback(); + }); + }); + + } + + elem.on('click' + ns, function() { + if(!lock) { + callback(); + } + }); + }); + }; + + $.fn.destroyMfpFastClick = function() { + $(this).off('touchstart' + ns + ' click' + ns); + if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns); + }; +})(); + +/*>>fastclick*/ +})(window.jQuery || window.Zepto); \ No newline at end of file diff --git a/extensions/tools_magnificpopup/magnificpopup/jquery.magnificpopup.min.js b/extensions/tools_magnificpopup/magnificpopup/jquery.magnificpopup.min.js new file mode 100644 index 000000000..5d7c25cf1 --- /dev/null +++ b/extensions/tools_magnificpopup/magnificpopup/jquery.magnificpopup.min.js @@ -0,0 +1,4 @@ +/*! Magnific Popup - v0.9.6 - 2013-10-01 +* http://dimsemenov.com/plugins/magnific-popup/ +* Copyright (c) 2013 Dmitry Semenov; */ +(function(e){var t,n,i,o,r,a,s,l="Close",c="BeforeClose",d="AfterClose",u="BeforeAppend",p="MarkupParse",f="Open",m="Change",g="mfp",v="."+g,h="mfp-ready",C="mfp-removing",y="mfp-prevent-close",w=function(){},b=!!window.jQuery,I=e(window),x=function(e,n){t.ev.on(g+e+v,n)},k=function(t,n,i,o){var r=document.createElement("div");return r.className="mfp-"+t,i&&(r.innerHTML=i),o?n&&n.appendChild(r):(r=e(r),n&&r.appendTo(n)),r},T=function(n,i){t.ev.triggerHandler(g+n,i),t.st.callbacks&&(n=n.charAt(0).toLowerCase()+n.slice(1),t.st.callbacks[n]&&t.st.callbacks[n].apply(t,e.isArray(i)?i:[i]))},E=function(){(t.st.focus?t.content.find(t.st.focus).eq(0):t.wrap).focus()},S=function(n){return n===s&&t.currTemplate.closeBtn||(t.currTemplate.closeBtn=e(t.st.closeMarkup.replace("%title%",t.st.tClose)),s=n),t.currTemplate.closeBtn},P=function(){e.magnificPopup.instance||(t=new w,t.init(),e.magnificPopup.instance=t)},_=function(n){if(!e(n).hasClass(y)){var i=t.st.closeOnContentClick,o=t.st.closeOnBgClick;if(i&&o)return!0;if(!t.content||e(n).hasClass("mfp-close")||t.preloader&&n===t.preloader[0])return!0;if(n===t.content[0]||e.contains(t.content[0],n)){if(i)return!0}else if(o&&e.contains(document,n))return!0;return!1}},O=function(){var e=document.createElement("p").style,t=["ms","O","Moz","Webkit"];if(void 0!==e.transition)return!0;for(;t.length;)if(t.pop()+"Transition"in e)return!0;return!1};w.prototype={constructor:w,init:function(){var n=navigator.appVersion;t.isIE7=-1!==n.indexOf("MSIE 7."),t.isIE8=-1!==n.indexOf("MSIE 8."),t.isLowIE=t.isIE7||t.isIE8,t.isAndroid=/android/gi.test(n),t.isIOS=/iphone|ipad|ipod/gi.test(n),t.supportsTransition=O(),t.probablyMobile=t.isAndroid||t.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),i=e(document.body),o=e(document),t.popupsCache={}},open:function(n){var i;if(n.isObj===!1){t.items=n.items.toArray(),t.index=0;var r,s=n.items;for(i=0;s.length>i;i++)if(r=s[i],r.parsed&&(r=r.el[0]),r===n.el[0]){t.index=i;break}}else t.items=e.isArray(n.items)?n.items:[n.items],t.index=n.index||0;if(t.isOpen)return t.updateItemHTML(),void 0;t.types=[],a="",t.ev=n.mainEl&&n.mainEl.length?n.mainEl.eq(0):o,n.key?(t.popupsCache[n.key]||(t.popupsCache[n.key]={}),t.currTemplate=t.popupsCache[n.key]):t.currTemplate={},t.st=e.extend(!0,{},e.magnificPopup.defaults,n),t.fixedContentPos="auto"===t.st.fixedContentPos?!t.probablyMobile:t.st.fixedContentPos,t.st.modal&&(t.st.closeOnContentClick=!1,t.st.closeOnBgClick=!1,t.st.showCloseBtn=!1,t.st.enableEscapeKey=!1),t.bgOverlay||(t.bgOverlay=k("bg").on("click"+v,function(){t.close()}),t.wrap=k("wrap").attr("tabindex",-1).on("click"+v,function(e){_(e.target)&&t.close()}),t.container=k("container",t.wrap)),t.contentContainer=k("content"),t.st.preloader&&(t.preloader=k("preloader",t.container,t.st.tLoading));var l=e.magnificPopup.modules;for(i=0;l.length>i;i++){var c=l[i];c=c.charAt(0).toUpperCase()+c.slice(1),t["init"+c].call(t)}T("BeforeOpen"),t.st.showCloseBtn&&(t.st.closeBtnInside?(x(p,function(e,t,n,i){n.close_replaceWith=S(i.type)}),a+=" mfp-close-btn-in"):t.wrap.append(S())),t.st.alignTop&&(a+=" mfp-align-top"),t.fixedContentPos?t.wrap.css({overflow:t.st.overflowY,overflowX:"hidden",overflowY:t.st.overflowY}):t.wrap.css({top:I.scrollTop(),position:"absolute"}),(t.st.fixedBgPos===!1||"auto"===t.st.fixedBgPos&&!t.fixedContentPos)&&t.bgOverlay.css({height:o.height(),position:"absolute"}),t.st.enableEscapeKey&&o.on("keyup"+v,function(e){27===e.keyCode&&t.close()}),I.on("resize"+v,function(){t.updateSize()}),t.st.closeOnContentClick||(a+=" mfp-auto-cursor"),a&&t.wrap.addClass(a);var d=t.wH=I.height(),u={};if(t.fixedContentPos&&t._hasScrollBar(d)){var m=t._getScrollbarSize();m&&(u.paddingRight=m)}t.fixedContentPos&&(t.isIE7?e("body, html").css("overflow","hidden"):u.overflow="hidden");var g=t.st.mainClass;return t.isIE7&&(g+=" mfp-ie7"),g&&t._addClassToMFP(g),t.updateItemHTML(),T("BuildControls"),e("html").css(u),t.bgOverlay.add(t.wrap).prependTo(document.body),t._lastFocusedEl=document.activeElement,setTimeout(function(){t.content?(t._addClassToMFP(h),E()):t.bgOverlay.addClass(h),o.on("focusin"+v,function(n){return n.target===t.wrap[0]||e.contains(t.wrap[0],n.target)?void 0:(E(),!1)})},16),t.isOpen=!0,t.updateSize(d),T(f),n},close:function(){t.isOpen&&(T(c),t.isOpen=!1,t.st.removalDelay&&!t.isLowIE&&t.supportsTransition?(t._addClassToMFP(C),setTimeout(function(){t._close()},t.st.removalDelay)):t._close())},_close:function(){T(l);var n=C+" "+h+" ";if(t.bgOverlay.detach(),t.wrap.detach(),t.container.empty(),t.st.mainClass&&(n+=t.st.mainClass+" "),t._removeClassFromMFP(n),t.fixedContentPos){var i={paddingRight:""};t.isIE7?e("body, html").css("overflow",""):i.overflow="",e("html").css(i)}o.off("keyup"+v+" focusin"+v),t.ev.off(v),t.wrap.attr("class","mfp-wrap").removeAttr("style"),t.bgOverlay.attr("class","mfp-bg"),t.container.attr("class","mfp-container"),!t.st.showCloseBtn||t.st.closeBtnInside&&t.currTemplate[t.currItem.type]!==!0||t.currTemplate.closeBtn&&t.currTemplate.closeBtn.detach(),t._lastFocusedEl&&e(t._lastFocusedEl).focus(),t.currItem=null,t.content=null,t.currTemplate=null,t.prevHeight=0,T(d)},updateSize:function(e){if(t.isIOS){var n=document.documentElement.clientWidth/window.innerWidth,i=window.innerHeight*n;t.wrap.css("height",i),t.wH=i}else t.wH=e||I.height();t.fixedContentPos||t.wrap.css("height",t.wH),T("Resize")},updateItemHTML:function(){var n=t.items[t.index];t.contentContainer.detach(),t.content&&t.content.detach(),n.parsed||(n=t.parseEl(t.index));var i=n.type;if(T("BeforeChange",[t.currItem?t.currItem.type:"",i]),t.currItem=n,!t.currTemplate[i]){var o=t.st[i]?t.st[i].markup:!1;T("FirstMarkupParse",o),t.currTemplate[i]=o?e(o):!0}r&&r!==n.type&&t.container.removeClass("mfp-"+r+"-holder");var a=t["get"+i.charAt(0).toUpperCase()+i.slice(1)](n,t.currTemplate[i]);t.appendContent(a,i),n.preloaded=!0,T(m,n),r=n.type,t.container.prepend(t.contentContainer),T("AfterChange")},appendContent:function(e,n){t.content=e,e?t.st.showCloseBtn&&t.st.closeBtnInside&&t.currTemplate[n]===!0?t.content.find(".mfp-close").length||t.content.append(S()):t.content=e:t.content="",T(u),t.container.addClass("mfp-"+n+"-holder"),t.contentContainer.append(t.content)},parseEl:function(n){var i=t.items[n],o=i.type;if(i=i.tagName?{el:e(i)}:{data:i,src:i.src},i.el){for(var r=t.types,a=0;r.length>a;a++)if(i.el.hasClass("mfp-"+r[a])){o=r[a];break}i.src=i.el.attr("data-mfp-src"),i.src||(i.src=i.el.attr("href"))}return i.type=o||t.st.type||"inline",i.index=n,i.parsed=!0,t.items[n]=i,T("ElementParse",i),t.items[n]},addGroup:function(e,n){var i=function(i){i.mfpEl=this,t._openClick(i,e,n)};n||(n={});var o="click.magnificPopup";n.mainEl=e,n.items?(n.isObj=!0,e.off(o).on(o,i)):(n.isObj=!1,n.delegate?e.off(o).on(o,n.delegate,i):(n.items=e,e.off(o).on(o,i)))},_openClick:function(n,i,o){var r=void 0!==o.midClick?o.midClick:e.magnificPopup.defaults.midClick;if(r||2!==n.which&&!n.ctrlKey&&!n.metaKey){var a=void 0!==o.disableOn?o.disableOn:e.magnificPopup.defaults.disableOn;if(a)if(e.isFunction(a)){if(!a.call(t))return!0}else if(a>I.width())return!0;n.type&&(n.preventDefault(),t.isOpen&&n.stopPropagation()),o.el=e(n.mfpEl),o.delegate&&(o.items=i.find(o.delegate)),t.open(o)}},updateStatus:function(e,i){if(t.preloader){n!==e&&t.container.removeClass("mfp-s-"+n),i||"loading"!==e||(i=t.st.tLoading);var o={status:e,text:i};T("UpdateStatus",o),e=o.status,i=o.text,t.preloader.html(i),t.preloader.find("a").on("click",function(e){e.stopImmediatePropagation()}),t.container.addClass("mfp-s-"+e),n=e}},_addClassToMFP:function(e){t.bgOverlay.addClass(e),t.wrap.addClass(e)},_removeClassFromMFP:function(e){this.bgOverlay.removeClass(e),t.wrap.removeClass(e)},_hasScrollBar:function(e){return(t.isIE7?o.height():document.body.scrollHeight)>(e||I.height())},_parseMarkup:function(t,n,i){var o;i.data&&(n=e.extend(i.data,n)),T(p,[t,n,i]),e.each(n,function(e,n){if(void 0===n||n===!1)return!0;if(o=e.split("_"),o.length>1){var i=t.find(v+"-"+o[0]);if(i.length>0){var r=o[1];"replaceWith"===r?i[0]!==n[0]&&i.replaceWith(n):"img"===r?i.is("img")?i.attr("src",n):i.replaceWith('<img src="'+n+'" class="'+i.attr("class")+'" />'):i.attr(o[1],n)}}else t.find(v+"-"+e).html(n)})},_getScrollbarSize:function(){if(void 0===t.scrollbarSize){var e=document.createElement("div");e.id="mfp-sbm",e.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(e),t.scrollbarSize=e.offsetWidth-e.clientWidth,document.body.removeChild(e)}return t.scrollbarSize}},e.magnificPopup={instance:null,proto:w.prototype,modules:[],open:function(t,n){return P(),t=t?e.extend(!0,{},t):{},t.isObj=!0,t.index=n||0,this.instance.open(t)},close:function(){return e.magnificPopup.instance&&e.magnificPopup.instance.close()},registerModule:function(t,n){n.options&&(e.magnificPopup.defaults[t]=n.options),e.extend(this.proto,n.proto),this.modules.push(t)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">×</button>',tClose:"Close (Esc)",tLoading:"Loading..."}},e.fn.magnificPopup=function(n){P();var i=e(this);if("string"==typeof n)if("open"===n){var o,r=b?i.data("magnificPopup"):i[0].magnificPopup,a=parseInt(arguments[1],10)||0;r.items?o=r.items[a]:(o=i,r.delegate&&(o=o.find(r.delegate)),o=o.eq(a)),t._openClick({mfpEl:o},i,r)}else t.isOpen&&t[n].apply(t,Array.prototype.slice.call(arguments,1));else n=e.extend(!0,{},n),b?i.data("magnificPopup",n):i[0].magnificPopup=n,t.addGroup(i,n);return i};var z,M,B,H="inline",L=function(){B&&(M.after(B.addClass(z)).detach(),B=null)};e.magnificPopup.registerModule(H,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){t.types.push(H),x(l+"."+H,function(){L()})},getInline:function(n,i){if(L(),n.src){var o=t.st.inline,r=e(n.src);if(r.length){var a=r[0].parentNode;a&&a.tagName&&(M||(z=o.hiddenClass,M=k(z),z="mfp-"+z),B=r.after(M).detach().removeClass(z)),t.updateStatus("ready")}else t.updateStatus("error",o.tNotFound),r=e("<div>");return n.inlineElement=r,r}return t.updateStatus("ready"),t._parseMarkup(i,{},n),i}}});var A,F="ajax",j=function(){A&&i.removeClass(A)},N=function(){j(),t.req&&t.req.abort()};e.magnificPopup.registerModule(F,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){t.types.push(F),A=t.st.ajax.cursor,x(l+"."+F,N),x("BeforeChange."+F,N)},getAjax:function(n){A&&i.addClass(A),t.updateStatus("loading");var o=e.extend({url:n.src,success:function(i,o,r){var a={data:i,xhr:r};T("ParseAjax",a),t.appendContent(e(a.data),F),n.finished=!0,j(),E(),setTimeout(function(){t.wrap.addClass(h)},16),t.updateStatus("ready"),T("AjaxContentAdded")},error:function(){j(),n.finished=n.loadError=!0,t.updateStatus("error",t.st.ajax.tError.replace("%url%",n.src))}},t.st.ajax.settings);return t.req=e.ajax(o),""}}});var W,R=function(n){if(n.data&&void 0!==n.data.title)return n.data.title;var i=t.st.image.titleSrc;if(i){if(e.isFunction(i))return i.call(t,n);if(n.el)return n.el.attr(i)||""}return""};e.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><div class="mfp-img"></div><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var e=t.st.image,n=".image";t.types.push("image"),x(f+n,function(){"image"===t.currItem.type&&e.cursor&&i.addClass(e.cursor)}),x(l+n,function(){e.cursor&&i.removeClass(e.cursor),I.off("resize"+v)}),x("Resize"+n,t.resizeImage),t.isLowIE&&x("AfterChange",t.resizeImage)},resizeImage:function(){var e=t.currItem;if(e&&e.img&&t.st.image.verticalFit){var n=0;t.isLowIE&&(n=parseInt(e.img.css("padding-top"),10)+parseInt(e.img.css("padding-bottom"),10)),e.img.css("max-height",t.wH-n)}},_onImageHasSize:function(e){e.img&&(e.hasSize=!0,W&&clearInterval(W),e.isCheckingImgSize=!1,T("ImageHasSize",e),e.imgHidden&&(t.content&&t.content.removeClass("mfp-loading"),e.imgHidden=!1))},findImageSize:function(e){var n=0,i=e.img[0],o=function(r){W&&clearInterval(W),W=setInterval(function(){return i.naturalWidth>0?(t._onImageHasSize(e),void 0):(n>200&&clearInterval(W),n++,3===n?o(10):40===n?o(50):100===n&&o(500),void 0)},r)};o(1)},getImage:function(n,i){var o=0,r=function(){n&&(n.img[0].complete?(n.img.off(".mfploader"),n===t.currItem&&(t._onImageHasSize(n),t.updateStatus("ready")),n.hasSize=!0,n.loaded=!0,T("ImageLoadComplete")):(o++,200>o?setTimeout(r,100):a()))},a=function(){n&&(n.img.off(".mfploader"),n===t.currItem&&(t._onImageHasSize(n),t.updateStatus("error",s.tError.replace("%url%",n.src))),n.hasSize=!0,n.loaded=!0,n.loadError=!0)},s=t.st.image,l=i.find(".mfp-img");if(l.length){var c=document.createElement("img");c.className="mfp-img",n.img=e(c).on("load.mfploader",r).on("error.mfploader",a),c.src=n.src,l.is("img")&&(n.img=n.img.clone()),n.img[0].naturalWidth>0&&(n.hasSize=!0)}return t._parseMarkup(i,{title:R(n),img_replaceWith:n.img},n),t.resizeImage(),n.hasSize?(W&&clearInterval(W),n.loadError?(i.addClass("mfp-loading"),t.updateStatus("error",s.tError.replace("%url%",n.src))):(i.removeClass("mfp-loading"),t.updateStatus("ready")),i):(t.updateStatus("loading"),n.loading=!0,n.hasSize||(n.imgHidden=!0,i.addClass("mfp-loading"),t.findImageSize(n)),i)}}});var Z,q=function(){return void 0===Z&&(Z=void 0!==document.createElement("p").style.MozTransform),Z};e.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(e){return e.is("img")?e:e.find("img")}},proto:{initZoom:function(){var e,n=t.st.zoom,i=".zoom";if(n.enabled&&t.supportsTransition){var o,r,a=n.duration,s=function(e){var t=e.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),i="all "+n.duration/1e3+"s "+n.easing,o={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},r="transition";return o["-webkit-"+r]=o["-moz-"+r]=o["-o-"+r]=o[r]=i,t.css(o),t},d=function(){t.content.css("visibility","visible")};x("BuildControls"+i,function(){if(t._allowZoom()){if(clearTimeout(o),t.content.css("visibility","hidden"),e=t._getItemToZoom(),!e)return d(),void 0;r=s(e),r.css(t._getOffset()),t.wrap.append(r),o=setTimeout(function(){r.css(t._getOffset(!0)),o=setTimeout(function(){d(),setTimeout(function(){r.remove(),e=r=null,T("ZoomAnimationEnded")},16)},a)},16)}}),x(c+i,function(){if(t._allowZoom()){if(clearTimeout(o),t.st.removalDelay=a,!e){if(e=t._getItemToZoom(),!e)return;r=s(e)}r.css(t._getOffset(!0)),t.wrap.append(r),t.content.css("visibility","hidden"),setTimeout(function(){r.css(t._getOffset())},16)}}),x(l+i,function(){t._allowZoom()&&(d(),r&&r.remove(),e=null)})}},_allowZoom:function(){return"image"===t.currItem.type},_getItemToZoom:function(){return t.currItem.hasSize?t.currItem.img:!1},_getOffset:function(n){var i;i=n?t.currItem.img:t.st.zoom.opener(t.currItem.el||t.currItem);var o=i.offset(),r=parseInt(i.css("padding-top"),10),a=parseInt(i.css("padding-bottom"),10);o.top-=e(window).scrollTop()-r;var s={width:i.width(),height:(b?i.innerHeight():i[0].offsetHeight)-a-r};return q()?s["-moz-transform"]=s.transform="translate("+o.left+"px,"+o.top+"px)":(s.left=o.left,s.top=o.top),s}}});var D="iframe",K="//about:blank",Y=function(e){if(t.currTemplate[D]){var n=t.currTemplate[D].find("iframe");n.length&&(e||(n[0].src=K),t.isIE8&&n.css("display",e?"block":"none"))}};e.magnificPopup.registerModule(D,{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){t.types.push(D),x("BeforeChange",function(e,t,n){t!==n&&(t===D?Y():n===D&&Y(!0))}),x(l+"."+D,function(){Y()})},getIframe:function(n,i){var o=n.src,r=t.st.iframe;e.each(r.patterns,function(){return o.indexOf(this.index)>-1?(this.id&&(o="string"==typeof this.id?o.substr(o.lastIndexOf(this.id)+this.id.length,o.length):this.id.call(this,o)),o=this.src.replace("%id%",o),!1):void 0});var a={};return r.srcAction&&(a[r.srcAction]=o),t._parseMarkup(i,a,n),t.updateStatus("ready"),i}}});var U=function(e){var n=t.items.length;return e>n-1?e-n:0>e?n+e:e},G=function(e,t,n){return e.replace("%curr%",t+1).replace("%total%",n)};e.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var n=t.st.gallery,i=".mfp-gallery",r=Boolean(e.fn.mfpFastClick);return t.direction=!0,n&&n.enabled?(a+=" mfp-gallery",x(f+i,function(){n.navigateByImgClick&&t.wrap.on("click"+i,".mfp-img",function(){return t.items.length>1?(t.next(),!1):void 0}),o.on("keydown"+i,function(e){37===e.keyCode?t.prev():39===e.keyCode&&t.next()})}),x("UpdateStatus"+i,function(e,n){n.text&&(n.text=G(n.text,t.currItem.index,t.items.length))}),x(p+i,function(e,i,o,r){var a=t.items.length;o.counter=a>1?G(n.tCounter,r.index,a):""}),x("BuildControls"+i,function(){if(t.items.length>1&&n.arrows&&!t.arrowLeft){var i=n.arrowMarkup,o=t.arrowLeft=e(i.replace("%title%",n.tPrev).replace("%dir%","left")).addClass(y),a=t.arrowRight=e(i.replace("%title%",n.tNext).replace("%dir%","right")).addClass(y),s=r?"mfpFastClick":"click";o[s](function(){t.prev()}),a[s](function(){t.next()}),t.isIE7&&(k("b",o[0],!1,!0),k("a",o[0],!1,!0),k("b",a[0],!1,!0),k("a",a[0],!1,!0)),t.container.append(o.add(a))}}),x(m+i,function(){t._preloadTimeout&&clearTimeout(t._preloadTimeout),t._preloadTimeout=setTimeout(function(){t.preloadNearbyImages(),t._preloadTimeout=null},16)}),x(l+i,function(){o.off(i),t.wrap.off("click"+i),t.arrowLeft&&r&&t.arrowLeft.add(t.arrowRight).destroyMfpFastClick(),t.arrowRight=t.arrowLeft=null}),void 0):!1},next:function(){t.direction=!0,t.index=U(t.index+1),t.updateItemHTML()},prev:function(){t.direction=!1,t.index=U(t.index-1),t.updateItemHTML()},goTo:function(e){t.direction=e>=t.index,t.index=e,t.updateItemHTML()},preloadNearbyImages:function(){var e,n=t.st.gallery.preload,i=Math.min(n[0],t.items.length),o=Math.min(n[1],t.items.length);for(e=1;(t.direction?o:i)>=e;e++)t._preloadItem(t.index+e);for(e=1;(t.direction?i:o)>=e;e++)t._preloadItem(t.index-e)},_preloadItem:function(n){if(n=U(n),!t.items[n].preloaded){var i=t.items[n];i.parsed||(i=t.parseEl(n)),T("LazyLoad",i),"image"===i.type&&(i.img=e('<img class="mfp-img" />').on("load.mfploader",function(){i.hasSize=!0}).on("error.mfploader",function(){i.hasSize=!0,i.loadError=!0,T("LazyLoadError",i)}).attr("src",i.src)),i.preloaded=!0}}}});var X="retina";e.magnificPopup.registerModule(X,{options:{replaceSrc:function(e){return e.src.replace(/\.\w+$/,function(e){return"@2x"+e})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var e=t.st.retina,n=e.ratio;n=isNaN(n)?n():n,n>1&&(x("ImageHasSize."+X,function(e,t){t.img.css({"max-width":t.img[0].naturalWidth/n,width:"100%"})}),x("ElementParse."+X,function(t,i){i.src=e.replaceSrc(i,n)}))}}}}),function(){var t=1e3,n="ontouchstart"in window,i=function(){I.off("touchmove"+r+" touchend"+r)},o="mfpFastClick",r="."+o;e.fn.mfpFastClick=function(o){return e(this).each(function(){var a,s=e(this);if(n){var l,c,d,u,p,f;s.on("touchstart"+r,function(e){u=!1,f=1,p=e.originalEvent?e.originalEvent.touches[0]:e.touches[0],c=p.clientX,d=p.clientY,I.on("touchmove"+r,function(e){p=e.originalEvent?e.originalEvent.touches:e.touches,f=p.length,p=p[0],(Math.abs(p.clientX-c)>10||Math.abs(p.clientY-d)>10)&&(u=!0,i())}).on("touchend"+r,function(e){i(),u||f>1||(a=!0,e.preventDefault(),clearTimeout(l),l=setTimeout(function(){a=!1},t),o())})})}s.on("click"+r,function(){a||o()})})},e.fn.destroyMfpFastClick=function(){e(this).off("touchstart"+r+" click"+r),n&&I.off("touchmove"+r+" touchend"+r)}}()})(window.jQuery||window.Zepto); \ No newline at end of file diff --git a/extensions/tools_magnificpopup/magnificpopup/magnificpopup.css b/extensions/tools_magnificpopup/magnificpopup/magnificpopup.css new file mode 100644 index 000000000..2865003bc --- /dev/null +++ b/extensions/tools_magnificpopup/magnificpopup/magnificpopup.css @@ -0,0 +1,376 @@ +/* Magnific Popup CSS */ +.mfp-bg { + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1042; + overflow: hidden; + position: fixed; + background: #0b0b0b; + opacity: 0.8; + filter: alpha(opacity=80); } + +.mfp-wrap { + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1043; + position: fixed; + outline: none !important; + -webkit-backface-visibility: hidden; } + +.mfp-container { + text-align: center; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + padding: 0 8px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + +.mfp-container:before { + content: ''; + display: inline-block; + height: 100%; + vertical-align: middle; } + +.mfp-align-top .mfp-container:before { + display: none; } + +.mfp-content { + position: relative; + display: inline-block; + vertical-align: middle; + margin: 0 auto; + text-align: left; + z-index: 1045; } + +.mfp-inline-holder .mfp-content, +.mfp-ajax-holder .mfp-content { + width: 100%; + cursor: auto; } + +.mfp-ajax-cur { + cursor: progress; } + +.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close { + cursor: -moz-zoom-out; + cursor: -webkit-zoom-out; + cursor: zoom-out; } + +.mfp-zoom { + cursor: pointer; + cursor: -webkit-zoom-in; + cursor: -moz-zoom-in; + cursor: zoom-in; } + +.mfp-auto-cursor .mfp-content { + cursor: auto; } + +.mfp-close, +.mfp-arrow, +.mfp-preloader, +.mfp-counter { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; } + +.mfp-loading.mfp-figure { + display: none; } + +.mfp-hide { + display: none !important; } + +.mfp-preloader { + color: #cccccc; + position: absolute; + top: 50%; + width: auto; + text-align: center; + margin-top: -0.8em; + left: 8px; + right: 8px; + z-index: 1044; } + .mfp-preloader a { + color: #cccccc; } + .mfp-preloader a:hover { + color: white; } + +.mfp-s-ready .mfp-preloader { + display: none; } + +.mfp-s-error .mfp-content { + display: none; } + +button.mfp-close, button.mfp-arrow { + overflow: visible; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; + display: block; + padding: 0; + z-index: 1046; + -webkit-box-shadow: none; + box-shadow: none; } +button::-moz-focus-inner { + padding: 0; + border: 0; } + +.mfp-close { + width: 44px; + height: 44px; + line-height: 44px; + position: absolute; + right: 0; + top: 0; + text-decoration: none; + text-align: center; + opacity: 0.65; + padding: 0 0 18px 10px; + color: white; + font-style: normal; + font-size: 28px; + font-family: Arial, Baskerville, monospace; } + .mfp-close:hover, .mfp-close:focus { + opacity: 1; } + .mfp-close:active { + top: 1px; } + +.mfp-close-btn-in .mfp-close { + color: #333333; } + +.mfp-image-holder .mfp-close, +.mfp-iframe-holder .mfp-close { + color: white; + right: -6px; + text-align: right; + padding-right: 6px; + width: 100%; } + +.mfp-counter { + position: absolute; + top: 0; + right: 0; + color: #cccccc; + font-size: 12px; + line-height: 18px; } + +.mfp-arrow { + position: absolute; + opacity: 0.65; + margin: 0; + top: 50%; + margin-top: -55px; + padding: 0; + width: 90px; + height: 110px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + .mfp-arrow:active { + margin-top: -54px; } + .mfp-arrow:hover, .mfp-arrow:focus { + opacity: 1; } + .mfp-arrow:before, .mfp-arrow:after, + .mfp-arrow .mfp-b, + .mfp-arrow .mfp-a { + content: ''; + display: block; + width: 0; + height: 0; + position: absolute; + left: 0; + top: 0; + margin-top: 35px; + margin-left: 35px; + border: medium inset transparent; } + .mfp-arrow:after, + .mfp-arrow .mfp-a { + border-top-width: 13px; + border-bottom-width: 13px; + top: 8px; } + .mfp-arrow:before, + .mfp-arrow .mfp-b { + border-top-width: 21px; + border-bottom-width: 21px; } + +.mfp-arrow-left { + left: 0; } + .mfp-arrow-left:after, + .mfp-arrow-left .mfp-a { + border-right: 17px solid white; + margin-left: 31px; } + .mfp-arrow-left:before, + .mfp-arrow-left .mfp-b { + margin-left: 25px; + border-right: 27px solid #3f3f3f; } + +.mfp-arrow-right { + right: 0; } + .mfp-arrow-right:after, + .mfp-arrow-right .mfp-a { + border-left: 17px solid white; + margin-left: 39px; } + .mfp-arrow-right:before, + .mfp-arrow-right .mfp-b { + border-left: 27px solid #3f3f3f; } + +.mfp-iframe-holder { + padding-top: 40px; + padding-bottom: 40px; } + .mfp-iframe-holder .mfp-content { + line-height: 0; + width: 100%; + max-width: 900px; } + .mfp-iframe-holder .mfp-close { + top: -40px; } + +.mfp-iframe-scaler { + width: 100%; + height: 0; + overflow: hidden; + padding-top: 56.25%; } + .mfp-iframe-scaler iframe { + position: absolute; + display: block; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); + background: black; } + +/* Main image in popup */ +img.mfp-img { + width: auto; + max-width: 100%; + height: auto; + display: block; + line-height: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 40px 0 40px; + margin: 0 auto; } + +/* The shadow behind the image */ +.mfp-figure { + line-height: 0; } + .mfp-figure:after { + content: ''; + position: absolute; + left: 0; + top: 40px; + bottom: 40px; + display: block; + right: 0; + width: auto; + height: auto; + z-index: -1; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); + background: #444444; } + .mfp-figure small { + color: #bdbdbd; + display: block; + font-size: 12px; + line-height: 14px; } + +.mfp-bottom-bar { + margin-top: -36px; + position: absolute; + top: 100%; + left: 0; + width: 100%; + cursor: auto; } + +.mfp-title { + text-align: left; + line-height: 18px; + color: #f3f3f3; + word-wrap: break-word; + padding-right: 36px; } + +.mfp-image-holder .mfp-content { + max-width: 100%; } + +.mfp-gallery .mfp-image-holder .mfp-figure { + cursor: pointer; } + +@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) { + /** + * Remove all paddings around the image on small screen + */ + .mfp-img-mobile .mfp-image-holder { + padding-left: 0; + padding-right: 0; } + .mfp-img-mobile img.mfp-img { + padding: 0; } + .mfp-img-mobile .mfp-figure { + /* The shadow behind the image */ } + .mfp-img-mobile .mfp-figure:after { + top: 0; + bottom: 0; } + .mfp-img-mobile .mfp-figure small { + display: inline; + margin-left: 5px; } + .mfp-img-mobile .mfp-bottom-bar { + background: rgba(0, 0, 0, 0.6); + bottom: 0; + margin: 0; + top: auto; + padding: 3px 5px; + position: fixed; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + .mfp-img-mobile .mfp-bottom-bar:empty { + padding: 0; } + .mfp-img-mobile .mfp-counter { + right: 5px; + top: 3px; } + .mfp-img-mobile .mfp-close { + top: 0; + right: 0; + width: 35px; + height: 35px; + line-height: 35px; + background: rgba(0, 0, 0, 0.6); + position: fixed; + text-align: center; + padding: 0; } } +@media all and (max-width: 900px) { + .mfp-arrow { + -webkit-transform: scale(0.75); + transform: scale(0.75); } + + .mfp-arrow-left { + -webkit-transform-origin: 0; + transform-origin: 0; } + + .mfp-arrow-right { + -webkit-transform-origin: 100%; + transform-origin: 100%; } + + .mfp-container { + padding-left: 6px; + padding-right: 6px; } } +.mfp-ie7 .mfp-img { + padding: 0; } +.mfp-ie7 .mfp-bottom-bar { + width: 600px; + left: 50%; + margin-left: -300px; + margin-top: 5px; + padding-bottom: 5px; } +.mfp-ie7 .mfp-container { + padding: 0; } +.mfp-ie7 .mfp-content { + padding-top: 44px; } +.mfp-ie7 .mfp-close { + top: 0; + right: 0; + padding-top: 0; } diff --git a/extensions/tools_zoom/tools_zoom.js b/extensions/tools_zoom/tools_zoom.js new file mode 100644 index 000000000..4575cc243 --- /dev/null +++ b/extensions/tools_zoom/tools_zoom.js @@ -0,0 +1,273 @@ +/* ************************************************************** + + Copyright 2013 Zoovy, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +************************************************************** */ + + + +// Intended as a free, open source alternative to 3rd party plugins like Magic Zoom Plus. +// Utilizes the jQuery Zoom jQuery plugin: http://jacklmoore.com/zoom/ + +var tools_zoom = function() { + var theseTemplates = new Array(''); + var r = { + +//////////////////////////////////// CALLBACKS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + callbacks : { + init : { + onSuccess : function() { + var r = false; + + // app.u.loadResourceFile(['script',0,'extensions/tools_zoom/zoom/js/jquery.zoom.min.js']); + + r = true; + + return r; + }, + onError : function() { + app.u.dump('BEGIN tools_zoom.callbacks.init.onError'); + } + } + }, //callbacks + +//////////////////////////////////// ACTION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + a : { + }, //Actions +//////////////////////////////////// RENDERFORMATS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + renderFormats : { + +/**************************************** + +A renderformat for creating a magnified image of a product, and the ability to switch an image out +with thumbnails of up to 6 of it's alternate images. The images will be based on the product container +which renderformat element resides. + +This renderformat is intended to be on a stand-alone element such as a div. +ex: +<div data-bind="useParentData:true; format:imageZoom; extension:tools_zoom; isThumbs:1;" data-thumbclass='thumbCarousel' height='296' width='296' zheight='800' zwidth='800' theight='50' twidth='50'> + +Do not specify a var, ALWAYS set useParentData to true. + +bindData params: +required: + none +optional: + isThumbs - An indicator that thumbnail images should be created. 1 = true. + bgcolor - A background color to be passed to the app.u.makeImage call for all images. + isElastic - An indicator that the renderformat will be run on elastic results. 1 = true. + +data attributes: +required: + none +optional: + data-thumbclass - A class that will be added to the container that holds the thumbnails. + data-zoomclass - Indicates that the zoomed image should be created in a separate container. + It's value is added as a class to that container. + height - A height to be passed to the app.u.makeImage call for the main, standard size image. + width - A width to be passed to the app.u.makeImage call for the main, standard size image. + theight - A height to be passed to the app.u.makeImage call for the thumbnail image(s). + twidth - A width to be passed to the app.u.makeImage call for the thumbnail image(s). + zheight - A height to be passed to the app.u.makeImage call for the larger, zoom size image. + zwidth - TA width to be passed to the app.u.makeImage call for the larger, zoom size image. + +!!This extension will work with the tools_lightbox extension using the bindData params: hrefAttr, w, & h. + (doesn't actually use the extension for anything but to load the lightbox plugin, which could be done + independently of the extension this will be changed later) + + +****************************************/ + + imageZoom : function($tag, data) { + // app.u.dump('data.value:'); app.u.dump(data.value); app.u.dump('thumbclass'); app.u.dump($tag.data('thumbclass')); + var pid = app.u.makeSafeHTMLId(data.value.pid); + + //create containers & classes for images + var $mainImageCont = ('<div class="mainImageCont_'+data.value.pid+'"></div>'); + + //if the zoom will not be in the original image container, different properties are needed + if($tag.data('zoomclass')) { + var $zoomImageCont = ('<div class="displayNone '+$tag.data('zoomclass')+' '+$tag.data('zoomclass')+'_'+data.value.pid+'"></div>'); + var zoomImageClass = '.'+$tag.data('zoomclass')+'_'+data.value.pid; + var seperateZoomIn = function() {$(zoomImageClass).show();}; + var seperateZoomOut = function() {$(zoomImageClass).hide();}; + $tag.append($mainImageCont).append($zoomImageCont); + } + else { + var zoomImageClass = '.mainImageCont_'+data.value.pid; + $tag.append($mainImageCont) + } + $mainImageCont = $('.mainImageCont_'+data.value.pid,$tag); + + + //get bgcolor and image path, create main product image + var bgcolor = data.bindData.bgcolor ? data.bindData.bgcolor : 'ffffff' + // app.u.dump('data.bindData'); app.u.dump(data.bindData); + var image = data.bindData.isElastic ? data.value.images[0] : data.value['%attribs']['zoovy:prod_image1']; + var imageURL = app.u.makeImage({ + "name" : image, + "w" : $tag.attr('width'), + "h" : $tag.attr('height'), + "b" : bgcolor + }); + $mainImageCont.append('<img src="'+imageURL+'" />'); + //if lightbox is being used at href to main image (main images based on thumbs are done later) + if(data.bindData.hrefAttr) { + $tag.attr({'href':app.u.makeImage({'name':image,'w':data.bindData.w,'h':data.bindData.h,'b':data.bindData.b}),'rel':'lightbox[prodPageMain_'+pid+']'}) + } + + //create zoom image + var zoomURL = app.u.makeImage({ + "name" : image, + "w" : $tag.attr('zwidth'), + "h" : $tag.attr('zheight'), + "b" : bgcolor + }); + + + //enable zoom on main image, + //if a separate container is used for the zoom it is the target, + //and must be shown and hidden on mouseenter & mouseleave + if($tag.data('zoomclass')) { + $mainImageCont.zoom( + { + url : zoomURL, + on : 'mouseover', + duration : 500, + target : zoomImageClass, + onZoomIn : seperateZoomIn, + onZoomOut : seperateZoomOut + } + ); + } + //no separate container, no target or show/hide needed + else { + $mainImageCont.zoom( + { + url : zoomURL, + on : 'mouseover', + duration : 500 + } + ); + } + + //if isThumbs is set then add thumbnails, if not... don't. + //if no prod_image2, likely there are no thumbnails, don't create the container + //and fill it w/ a redundant image (may need a better check form the same image later). + if(data.bindData.isThumbs == 1 && data.value['%attribs']['zoovy:prod_image2']) { + + var $thumbImageCont = ('<div class="thumbImageCont '+$tag.data('thumbclass')+'"></div>'); + $tag.after($thumbImageCont) + $thumbImageCont = $('.thumbImageCont','#productTemplate_'+pid); + + //get product images, up to 6, and create thumbnails. + var thumbName; //recycled in loop + var tImages = ''; + for (var i = 1; i < 7; i +=1) { + thumbName = data.value['%attribs']['zoovy:prod_image'+i]; + + if(app.u.isSet(thumbName)) { +// app.u.dump(" -> "+i+": "+thumbName); + //make thumb and assign path as attr for use in swaping later + if(!data.bindData.hrefAttr) { //if lightbox isn't being used make thumb container an empty div + $thumbImageCont.append('<div><img src="'+app.u.makeImage({'tag':0,'name':thumbName,'w':$tag.attr('twidth'),'h':$tag.attr('theight'),'b':bgcolor})+'" data-imgsrc="'+thumbName+'"/></div>'); + } + else { //if lightbox is being used, make thumb container a anchor w/ lightbox attributes + var thumbImgObj = { + name : thumbName + }; + if(data.bindData.w){ thumbImgObj.w = data.bindData.w; } + if(data.bindData.h){ thumbImgObj.h = data.bindData.h; } + if(data.bindData.b){ thumbImgObj.b = data.bindData.b; } + + var thumbHREF = app.u.makeImage(thumbImgObj); + $thumbImageCont.append('<a href="'+thumbHREF+'" rel="lightbox[prodPageThumb_'+pid+']"><img src="'+app.u.makeImage({'tag':0,'name':thumbName,'w':$tag.attr('twidth'),'h':$tag.attr('theight'),'b':bgcolor})+'" data-imgsrc="'+thumbName+'"/></a>'); + } + } + } + if(data.bindData.hrefAttr) { + var mainName = ''; + for(i=2;i<6;i++) { + mainName = data.value['%attribs']['zoovy:prod_image'+i]; + if(app.u.isSet(mainName)){ +// app.u.dump("main name -> "+i+": "+mainName); + var mainImgObj = { + name : mainName + }; + if(data.bindData.w){ mainImgObj.w = data.bindData.w; } + if(data.bindData.h){ mainImgObj.h = data.bindData.h; } + if(data.bindData.b){ mainImgObj.b = data.bindData.b; } + + var mainHREF = app.u.makeImage(mainImgObj); + $tag.append('<a class=displayNone href="'+mainHREF+'" rel="lightbox[prodPageMain_'+pid+']"><img src="'+mainHREF+'" /></a>'); + } + } + } + + + //add mouseenter to each thumb to show it in the main image area + $('img',$thumbImageCont).each(function() { + $(this).on('mouseenter', function() { + $mainImageCont.trigger('zoom.destroy'); //kill zoom on main image + var newImage = $(this).attr('data-imgsrc'); //get path for thumb image +// app.u.dump('newImage'); app.u.dump(newImage); + //change image source for main image + var newHREF = app.u.makeImage({ + "name" : newImage, + "w" : $tag.attr('width'), + "h" : $tag.attr('height'), + "b" : bgcolor + }); + + $('img:first-child',$mainImageCont).attr('src', newHREF); + // $tag.attr({'href':newHREF,'rel':'lightbox[prodPage_'+pid+']'}); + + //make new zoom image + var newImageURL = app.u.makeImage({ + "name" : newImage, + "w" : $tag.attr('zwidth'), + "h" : $tag.attr('zheight'), + "b" : bgcolor + }); + + //start zoom on main image again + $mainImageCont.zoom( + { + url : newImageURL, + on : 'mouseover', + duration : 500 + } + ); + }); //mouseenter + }); //thumbnails + } + + } //imageZoom + + }, //renderFormats +//////////////////////////////////// UTIL [u] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + u : { + }, //u [utilities] +//////////////////////////////////// APP EVENT [e] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + + e : { + } //e [app Events] + } //r object. + return r; + } \ No newline at end of file diff --git a/extensions/tools_zoom/zoom/images/grab.cur b/extensions/tools_zoom/zoom/images/grab.cur new file mode 100644 index 000000000..fba3ddc80 Binary files /dev/null and b/extensions/tools_zoom/zoom/images/grab.cur differ diff --git a/extensions/tools_zoom/zoom/images/grabbed.cur b/extensions/tools_zoom/zoom/images/grabbed.cur new file mode 100644 index 000000000..41aaa62a5 Binary files /dev/null and b/extensions/tools_zoom/zoom/images/grabbed.cur differ diff --git a/extensions/tools_zoom/zoom/js/jquery.zoom.js b/extensions/tools_zoom/zoom/js/jquery.zoom.js new file mode 100644 index 000000000..774558b99 --- /dev/null +++ b/extensions/tools_zoom/zoom/js/jquery.zoom.js @@ -0,0 +1,224 @@ +/*! + Zoom v1.7.10 - 2013-10-16 + Enlarge images on click or mouseover. + (c) 2013 Jack Moore - http://www.jacklmoore.com/zoom + license: http://www.opensource.org/licenses/mit-license.php +*/ +(function ($) { + var defaults = { + url: false, + callback: false, + target: false, + duration: 120, + on: 'mouseover', // other options: grab, click, toggle + touch: true, // enables a touch fallback + onZoomIn: false, + onZoomOut: false + }; + + // Core Zoom Logic, independent of event listeners. + $.zoom = function(target, source, img) { + var targetHeight, + targetWidth, + sourceHeight, + sourceWidth, + xRatio, + yRatio, + offset, + position = $(target).css('position'); + + // The parent element needs positioning so that the zoomed element can be correctly positioned within. + $(target).css({ + position: /(absolute|fixed)/.test(position) ? position : 'relative', + overflow: 'hidden' + }); + + img.style.width = img.style.height = ''; + + $(img) + .addClass('zoomImg') + .css({ + position: 'absolute', + top: 0, + left: 0, + opacity: 0, + width: img.width, + height: img.height, + border: 'none', + maxWidth: 'none' + }) + .appendTo(target); + + return { + init: function() { + targetWidth = $(target).outerWidth(); + targetHeight = $(target).outerHeight(); + + if (source === target) { + sourceWidth = targetWidth; + sourceHeight = targetHeight; + } else { + sourceWidth = $(source).outerWidth(); + sourceHeight = $(source).outerHeight(); + } + + xRatio = (img.width - targetWidth) / sourceWidth; + yRatio = (img.height - targetHeight) / sourceHeight; + + offset = $(source).offset(); + }, + move: function (e) { + var left = (e.pageX - offset.left), + top = (e.pageY - offset.top); + + top = Math.max(Math.min(top, sourceHeight), 0); + left = Math.max(Math.min(left, sourceWidth), 0); + + img.style.left = (left * -xRatio) + 'px'; + img.style.top = (top * -yRatio) + 'px'; + } + }; + }; + + $.fn.zoom = function (options) { + return this.each(function () { + var + settings = $.extend({}, defaults, options || {}), + //target will display the zoomed image + target = settings.target || this, + //source will provide zoom location info (thumbnail) + source = this, + img = document.createElement('img'), + $img = $(img), + mousemove = 'mousemove.zoom', + clicked = false, + touched = false, + $urlElement; + + // If a url wasn't specified, look for an image element. + if (!settings.url) { + $urlElement = $(source).find('img'); + if ($urlElement[0]) { + settings.url = $urlElement.data('src') || $urlElement.attr('src'); + } + if (!settings.url) { + return; + } + } + + img.onload = function () { + var zoom = $.zoom(target, source, img); + + function start(e) { + zoom.init(); + zoom.move(e); + + // Skip the fade-in for IE8 and lower since it chokes on fading-in + // and changing position based on mousemovement at the same time. + $img.stop() + .fadeTo($.support.opacity ? settings.duration : 0, 1, $.isFunction(settings.onZoomIn) ? settings.onZoomIn.call(img) : false); + } + + function stop() { + $img.stop() + .fadeTo(settings.duration, 0, $.isFunction(settings.onZoomOut) ? settings.onZoomOut.call(img) : false); + } + + // Mouse events + if (settings.on === 'grab') { + $(source) + .on('mousedown.zoom', + function (e) { + if (e.which === 1) { + $(document).one('mouseup.zoom', + function () { + stop(); + + $(document).off(mousemove, zoom.move); + } + ); + + start(e); + + $(document).on(mousemove, zoom.move); + + e.preventDefault(); + } + } + ); + } else if (settings.on === 'click') { + $(source).on('click.zoom', + function (e) { + if (clicked) { + // bubble the event up to the document to trigger the unbind. + return; + } else { + clicked = true; + start(e); + $(document).on(mousemove, zoom.move); + $(document).one('click.zoom', + function () { + stop(); + clicked = false; + $(document).off(mousemove, zoom.move); + } + ); + return false; + } + } + ); + } else if (settings.on === 'toggle') { + $(source).on('click.zoom', + function (e) { + if (clicked) { + stop(); + } else { + start(e); + } + clicked = !clicked; + } + ); + } else if (settings.on === 'mouseover') { + zoom.init(); // Preemptively call init because IE7 will fire the mousemove handler before the hover handler. + + $(source) + .on('mouseenter.zoom', start) + .on('mouseleave.zoom', stop) + .on(mousemove, zoom.move); + } + + // Touch fallback + if (settings.touch) { + $(source) + .on('touchstart.zoom', function (e) { + e.preventDefault(); + if (touched) { + touched = false; + stop(); + } else { + touched = true; + start( e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] ); + } + }) + .on('touchmove.zoom', function (e) { + e.preventDefault(); + zoom.move( e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] ); + }); + } + + if ($.isFunction(settings.callback)) { + settings.callback.call(img); + } + }; + + img.src = settings.url; + + $(source).one('zoom.destroy', function(){ + $(source).off(".zoom"); + $img.remove(); + }); + }); + }; + + $.fn.zoom.defaults = defaults; +}(window.jQuery)); diff --git a/extensions/tools_zoom/zoom/js/jquery.zoom.min.js b/extensions/tools_zoom/zoom/js/jquery.zoom.min.js new file mode 100644 index 000000000..1d08a85b1 --- /dev/null +++ b/extensions/tools_zoom/zoom/js/jquery.zoom.min.js @@ -0,0 +1,7 @@ +/*! + Zoom v1.7.10 - 2013-10-16 + Enlarge images on click or mouseover. + (c) 2013 Jack Moore - http://www.jacklmoore.com/zoom + license: http://www.opensource.org/licenses/mit-license.php +*/ +(function(o){var t={url:!1,callback:!1,target:!1,duration:120,on:"mouseover",touch:!0,onZoomIn:!1,onZoomOut:!1};o.zoom=function(t,n,e){var i,u,c,a,m,r,l,s=o(t).css("position");return o(t).css({position:/(absolute|fixed)/.test(s)?s:"relative",overflow:"hidden"}),e.style.width=e.style.height="",o(e).addClass("zoomImg").css({position:"absolute",top:0,left:0,opacity:0,width:e.width,height:e.height,border:"none",maxWidth:"none"}).appendTo(t),{init:function(){u=o(t).outerWidth(),i=o(t).outerHeight(),n===t?(a=u,c=i):(a=o(n).outerWidth(),c=o(n).outerHeight()),m=(e.width-u)/a,r=(e.height-i)/c,l=o(n).offset()},move:function(o){var t=o.pageX-l.left,n=o.pageY-l.top;n=Math.max(Math.min(n,c),0),t=Math.max(Math.min(t,a),0),e.style.left=t*-m+"px",e.style.top=n*-r+"px"}}},o.fn.zoom=function(n){return this.each(function(){var e,i=o.extend({},t,n||{}),u=i.target||this,c=this,a=document.createElement("img"),m=o(a),r="mousemove.zoom",l=!1,s=!1;(i.url||(e=o(c).find("img"),e[0]&&(i.url=e.data("src")||e.attr("src")),i.url))&&(a.onload=function(){function t(t){e.init(),e.move(t),m.stop().fadeTo(o.support.opacity?i.duration:0,1,o.isFunction(i.onZoomIn)?i.onZoomIn.call(a):!1)}function n(){m.stop().fadeTo(i.duration,0,o.isFunction(i.onZoomOut)?i.onZoomOut.call(a):!1)}var e=o.zoom(u,c,a);"grab"===i.on?o(c).on("mousedown.zoom",function(i){1===i.which&&(o(document).one("mouseup.zoom",function(){n(),o(document).off(r,e.move)}),t(i),o(document).on(r,e.move),i.preventDefault())}):"click"===i.on?o(c).on("click.zoom",function(i){return l?void 0:(l=!0,t(i),o(document).on(r,e.move),o(document).one("click.zoom",function(){n(),l=!1,o(document).off(r,e.move)}),!1)}):"toggle"===i.on?o(c).on("click.zoom",function(o){l?n():t(o),l=!l}):"mouseover"===i.on&&(e.init(),o(c).on("mouseenter.zoom",t).on("mouseleave.zoom",n).on(r,e.move)),i.touch&&o(c).on("touchstart.zoom",function(o){o.preventDefault(),s?(s=!1,n()):(s=!0,t(o.originalEvent.touches[0]||o.originalEvent.changedTouches[0]))}).on("touchmove.zoom",function(o){o.preventDefault(),e.move(o.originalEvent.touches[0]||o.originalEvent.changedTouches[0])}),o.isFunction(i.callback)&&i.callback.call(a)},a.src=i.url,o(c).one("zoom.destroy",function(){o(c).off(".zoom"),m.remove()}))})},o.fn.zoom.defaults=t})(window.jQuery); \ No newline at end of file diff --git a/extensions/tools_zoom/zoom/readme.md b/extensions/tools_zoom/zoom/readme.md new file mode 100644 index 000000000..2e9b8e64e --- /dev/null +++ b/extensions/tools_zoom/zoom/readme.md @@ -0,0 +1,66 @@ +## About Zoom + +A small jQuery plugin for zooming images on mouseover or mousedown. See the [project page](http://jacklmoore.com/zoom/) for documentation and a demonstration. Released under the [MIT license](http://www.opensource.org/licenses/mit-license.php). + +## Changelog: + +### v1.7.10 - 2013/10/16 +* Fixed bug relating to the size of the target element when using the target property (Fixes #35) + +### v1.7.9 - 2013/10/16 +* Added simple fallback for touch events (Fixes #37 #39) +* Renamed minified file to jquery.zoom.min.js to match jQuery's convention. + +### v1.7.8 - 2013/7/30 +* Will use data-src attribute if present before checking for the presence of an src attribute. + +### v1.7.7 - 2013/7/14 +* Restricted grab to just the left-mouse-button on mousedown + +### v1.7.6 - 2013/6/24 +* Fixed misnamed onZoomOut callback + +### v1.7.5 - 2013/6/19 +* Fixed a bug with absolutely or fixed position target elements +* Set the value of `this` to be zoom-image element for the onZoomIn and onZoomOut callbacks + +### v1.7.4 - 2013/6/18 +* Namespaced events to assist unbinding events. +* Added destroy event to unbind zoom events & remove created img element. Example: + $('.example').trigger('zoom.destroy'); +* Added onZoomIn and onZoomOut callbacks + +### v1.7.3 - 2013/6/10 +* Fixing mistake made in previous commit + +### v1.7.2 - 2013/6/6 +* Replaced new Image() with document.createElement('img') to avoid a potential bug in Chrome 27. + +### v1.7.1 - 2013/3/12 +* Replaced jQuery shorthand methods with on() in anticipation of jQuery 2.0 + +### v1.7.0 - 2013/1/31 +* Added 'toggle' behavior to zoom in/out on click. Example: $('#example').zoom({ on:'toggle' }); +* Removed the icon property in favor of just using CSS. + +### v1.6.0 - 2013/1/22 +* Created $.zoom which contains the positioning logic, so that users can write custom controls or event handling. + +### v1.5.0 - 2012/11/19 +* Added 'target' property for specifying the element that displays the zoomed image. + +### v1.4.0 - 2012/9/29 +* Changed API & added option to activate on click. + +### v1.3.0 - 2011/12/21 +* Added 'callback' property that will execute a callback function once the image has loaded. +* Fixed a bug relating to the 'grab' property + +### v1.2.0 - 2011/11/15 +* Fixed a positioning bug + +### v1.1.0 - 2011/11/15 +* Added 'grab' property + +### v1.0.0 - 2011/11/11 +* First release \ No newline at end of file diff --git a/images/1_newcolors_spire_hopper_sidebanner.jpg b/images/1_newcolors_spire_hopper_sidebanner.jpg new file mode 100644 index 000000000..d742c101f Binary files /dev/null and b/images/1_newcolors_spire_hopper_sidebanner.jpg differ diff --git a/images/1oakley_sunglass_blowout_sidebanner.jpg b/images/1oakley_sunglass_blowout_sidebanner.jpg new file mode 100644 index 000000000..428f63030 Binary files /dev/null and b/images/1oakley_sunglass_blowout_sidebanner.jpg differ diff --git a/images/2014_empire_sidebanner.jpg b/images/2014_empire_sidebanner.jpg new file mode 100644 index 000000000..e3fa15fb3 Binary files /dev/null and b/images/2014_empire_sidebanner.jpg differ diff --git a/images/43holiday_return_shipping_sidebanner.jpg b/images/43holiday_return_shipping_sidebanner.jpg new file mode 100644 index 000000000..2d8f2277a Binary files /dev/null and b/images/43holiday_return_shipping_sidebanner.jpg differ diff --git a/images/4647-r.gif b/images/4647-r.gif new file mode 100644 index 000000000..fe52dfdf5 Binary files /dev/null and b/images/4647-r.gif differ diff --git a/images/PaintballArrowBlue--App_ShopButton_helper.png b/images/PaintballArrowBlue--App_ShopButton_helper.png new file mode 100644 index 000000000..da5968c63 Binary files /dev/null and b/images/PaintballArrowBlue--App_ShopButton_helper.png differ diff --git a/images/Red-ARROW-white-stroke--App_ShopButton_helper---70x200.png b/images/Red-ARROW-white-stroke--App_ShopButton_helper---70x200.png new file mode 100644 index 000000000..fc4e45672 Binary files /dev/null and b/images/Red-ARROW-white-stroke--App_ShopButton_helper---70x200.png differ diff --git a/images/addtocart_btn_mobile.jpg b/images/addtocart_btn_mobile.jpg new file mode 100644 index 000000000..08d2eccac Binary files /dev/null and b/images/addtocart_btn_mobile.jpg differ diff --git a/images/animated-overlay.gif b/images/animated-overlay.gif new file mode 100644 index 000000000..d441f75eb Binary files /dev/null and b/images/animated-overlay.gif differ diff --git a/images/blank.gif b/images/blank.gif new file mode 100644 index 000000000..02451babc Binary files /dev/null and b/images/blank.gif differ diff --git a/images/blog-125x45.png b/images/blog-125x45.png new file mode 100644 index 000000000..1ed71645e Binary files /dev/null and b/images/blog-125x45.png differ diff --git a/images/childoption-icon.jpg b/images/childoption-icon.jpg new file mode 100644 index 000000000..82335d6c6 Binary files /dev/null and b/images/childoption-icon.jpg differ diff --git a/images/ddmenubtn_bg.jpg b/images/ddmenubtn_bg.jpg new file mode 100644 index 000000000..193cda96b Binary files /dev/null and b/images/ddmenubtn_bg.jpg differ diff --git a/images/dye_2014_sidebanner_template.jpg b/images/dye_2014_sidebanner_template.jpg new file mode 100644 index 000000000..ad7f9b070 Binary files /dev/null and b/images/dye_2014_sidebanner_template.jpg differ diff --git a/images/early_black_friday_sale_slideshow.jpg b/images/early_black_friday_sale_slideshow.jpg new file mode 100644 index 000000000..a68d67b9f Binary files /dev/null and b/images/early_black_friday_sale_slideshow.jpg differ diff --git a/images/eclipse_shop.jpg b/images/eclipse_shop.jpg new file mode 100644 index 000000000..688ef7a26 Binary files /dev/null and b/images/eclipse_shop.jpg differ diff --git a/images/empire_fbrand002.jpg b/images/empire_fbrand002.jpg new file mode 100644 index 000000000..7182be5c3 Binary files /dev/null and b/images/empire_fbrand002.jpg differ diff --git a/images/favicon.ico b/images/favicon.ico new file mode 100644 index 000000000..15ffe5cd2 Binary files /dev/null and b/images/favicon.ico differ diff --git a/images/freeshipping_cart.jpg b/images/freeshipping_cart.jpg new file mode 100644 index 000000000..a2cbecca3 Binary files /dev/null and b/images/freeshipping_cart.jpg differ diff --git a/images/freeshipping_icon.jpg b/images/freeshipping_icon.jpg new file mode 100644 index 000000000..40893116a Binary files /dev/null and b/images/freeshipping_icon.jpg differ diff --git a/images/great_buys_title004.jpg b/images/great_buys_title004.jpg new file mode 100644 index 000000000..d2f593c5a Binary files /dev/null and b/images/great_buys_title004.jpg differ diff --git a/images/holiday_azodin_packages_slideshow.jpg b/images/holiday_azodin_packages_slideshow.jpg new file mode 100644 index 000000000..13bd064cf Binary files /dev/null and b/images/holiday_azodin_packages_slideshow.jpg differ diff --git a/images/holiday_proto_packages_slideshow.jpg b/images/holiday_proto_packages_slideshow.jpg new file mode 100644 index 000000000..38fecf965 Binary files /dev/null and b/images/holiday_proto_packages_slideshow.jpg differ diff --git a/images/kingman_spyder_paintball.jpg b/images/kingman_spyder_paintball.jpg new file mode 100644 index 000000000..39a120f9a Binary files /dev/null and b/images/kingman_spyder_paintball.jpg differ diff --git a/images/klr_hkarmy_mask_preorder_sidebanner.jpg b/images/klr_hkarmy_mask_preorder_sidebanner.jpg new file mode 100644 index 000000000..d962f9dba Binary files /dev/null and b/images/klr_hkarmy_mask_preorder_sidebanner.jpg differ diff --git a/images/kount-seal-20090918_88x35.gif b/images/kount-seal-20090918_88x35.gif new file mode 100644 index 000000000..621f97b3c Binary files /dev/null and b/images/kount-seal-20090918_88x35.gif differ diff --git a/images/live-chat.gif b/images/live-chat.gif new file mode 100644 index 000000000..0f67fc840 Binary files /dev/null and b/images/live-chat.gif differ diff --git a/images/loginbtn_bg.jpg b/images/loginbtn_bg.jpg new file mode 100644 index 000000000..5eb34634c Binary files /dev/null and b/images/loginbtn_bg.jpg differ diff --git a/images/mcafee-secure.gif b/images/mcafee-secure.gif new file mode 100644 index 000000000..3c6524054 Binary files /dev/null and b/images/mcafee-secure.gif differ diff --git a/images/myspace-32x32.png b/images/myspace-32x32.png new file mode 100644 index 000000000..064d42f36 Binary files /dev/null and b/images/myspace-32x32.png differ diff --git a/images/ninja_sidebanner_template.jpg b/images/ninja_sidebanner_template.jpg new file mode 100644 index 000000000..52fe98ca5 Binary files /dev/null and b/images/ninja_sidebanner_template.jpg differ diff --git a/images/package_deals_slideshow_template.jpg b/images/package_deals_slideshow_template.jpg new file mode 100644 index 000000000..80dbc0240 Binary files /dev/null and b/images/package_deals_slideshow_template.jpg differ diff --git a/images/prodlist_arrow.png b/images/prodlist_arrow.png new file mode 100644 index 000000000..e37e71f63 Binary files /dev/null and b/images/prodlist_arrow.png differ diff --git a/images/rapidssl-90x50.gif b/images/rapidssl-90x50.gif new file mode 100644 index 000000000..19d7903d4 Binary files /dev/null and b/images/rapidssl-90x50.gif differ diff --git a/images/removebtn_bg.jpg b/images/removebtn_bg.jpg new file mode 100644 index 000000000..0ae95a85c Binary files /dev/null and b/images/removebtn_bg.jpg differ diff --git a/images/searchbtn.jpg b/images/searchbtn.jpg new file mode 100644 index 000000000..0e15a899e Binary files /dev/null and b/images/searchbtn.jpg differ diff --git a/images/searchbtn_orange.jpg b/images/searchbtn_orange.jpg new file mode 100644 index 000000000..ed56cd419 Binary files /dev/null and b/images/searchbtn_orange.jpg differ diff --git a/images/sidebar_banners.jpg b/images/sidebar_banners.jpg new file mode 100644 index 000000000..da56806b5 Binary files /dev/null and b/images/sidebar_banners.jpg differ diff --git a/images/social_sprite.png b/images/social_sprite.png new file mode 100644 index 000000000..8e52ba74f Binary files /dev/null and b/images/social_sprite.png differ diff --git a/images/spire260_zephyr.jpg b/images/spire260_zephyr.jpg new file mode 100644 index 000000000..55853b0ba Binary files /dev/null and b/images/spire260_zephyr.jpg differ diff --git a/images/sprites.png b/images/sprites.png new file mode 100644 index 000000000..75ae325e0 Binary files /dev/null and b/images/sprites.png differ diff --git a/images/st.gif b/images/st.gif new file mode 100644 index 000000000..5dc177f51 Binary files /dev/null and b/images/st.gif differ diff --git a/images/starbadge.tf100.lg.gif b/images/starbadge.tf100.lg.gif new file mode 100644 index 000000000..60f8e9fab Binary files /dev/null and b/images/starbadge.tf100.lg.gif differ diff --git a/images/subcatlist_bg.jpg b/images/subcatlist_bg.jpg new file mode 100644 index 000000000..023daef46 Binary files /dev/null and b/images/subcatlist_bg.jpg differ diff --git a/images/team_infamous_paintball_sidebanner_template.jpg b/images/team_infamous_paintball_sidebanner_template.jpg new file mode 100644 index 000000000..0580573ba Binary files /dev/null and b/images/team_infamous_paintball_sidebanner_template.jpg differ diff --git a/images/topbar_carticon.png b/images/topbar_carticon.png new file mode 100644 index 000000000..613f5c303 Binary files /dev/null and b/images/topbar_carticon.png differ diff --git a/images/topbar_customericon.png b/images/topbar_customericon.png new file mode 100644 index 000000000..dcd83340d Binary files /dev/null and b/images/topbar_customericon.png differ diff --git a/images/topbar_logosection_bg.jpg b/images/topbar_logosection_bg.jpg new file mode 100644 index 000000000..b83e5e073 Binary files /dev/null and b/images/topbar_logosection_bg.jpg differ diff --git a/images/topbar_search_bg.jpg b/images/topbar_search_bg.jpg new file mode 100644 index 000000000..530392bc0 Binary files /dev/null and b/images/topbar_search_bg.jpg differ diff --git a/images/topbar_searchicon.png b/images/topbar_searchicon.png new file mode 100644 index 000000000..393e48a90 Binary files /dev/null and b/images/topbar_searchicon.png differ diff --git a/images/topbar_topnav_bg.jpg b/images/topbar_topnav_bg.jpg new file mode 100644 index 000000000..d1aad6ea6 Binary files /dev/null and b/images/topbar_topnav_bg.jpg differ diff --git a/images/ui-bg_diagonals-small_55_a4d0f9_40x40.png b/images/ui-bg_diagonals-small_55_a4d0f9_40x40.png new file mode 100644 index 000000000..1961025a9 Binary files /dev/null and b/images/ui-bg_diagonals-small_55_a4d0f9_40x40.png differ diff --git a/images/ui-bg_diagonals-small_95_fef1ec_40x40.png b/images/ui-bg_diagonals-small_95_fef1ec_40x40.png new file mode 100644 index 000000000..da75b2413 Binary files /dev/null and b/images/ui-bg_diagonals-small_95_fef1ec_40x40.png differ diff --git a/images/ui-bg_diagonals-thick_20_7c7c7c_40x40.png b/images/ui-bg_diagonals-thick_20_7c7c7c_40x40.png new file mode 100644 index 000000000..488df02bb Binary files /dev/null and b/images/ui-bg_diagonals-thick_20_7c7c7c_40x40.png differ diff --git a/images/ui-bg_flat_0_7c7c7c_40x100.png b/images/ui-bg_flat_0_7c7c7c_40x100.png new file mode 100644 index 000000000..de5c7a128 Binary files /dev/null and b/images/ui-bg_flat_0_7c7c7c_40x100.png differ diff --git a/images/ui-bg_flat_55_e4f1fd_40x100.png b/images/ui-bg_flat_55_e4f1fd_40x100.png new file mode 100644 index 000000000..f2e0be90d Binary files /dev/null and b/images/ui-bg_flat_55_e4f1fd_40x100.png differ diff --git a/images/ui-bg_flat_65_ffffff_40x100.png b/images/ui-bg_flat_65_ffffff_40x100.png new file mode 100644 index 000000000..9b11bb83d Binary files /dev/null and b/images/ui-bg_flat_65_ffffff_40x100.png differ diff --git a/images/ui-bg_flat_75_707070_40x100.png b/images/ui-bg_flat_75_707070_40x100.png new file mode 100644 index 000000000..586b63dde Binary files /dev/null and b/images/ui-bg_flat_75_707070_40x100.png differ diff --git a/images/ui-bg_flat_75_d7d7d7_40x100.png b/images/ui-bg_flat_75_d7d7d7_40x100.png new file mode 100644 index 000000000..f9522ab74 Binary files /dev/null and b/images/ui-bg_flat_75_d7d7d7_40x100.png differ diff --git a/images/ui-bg_flat_75_f5f5f5_40x100.png b/images/ui-bg_flat_75_f5f5f5_40x100.png new file mode 100644 index 000000000..1e9c3b13c Binary files /dev/null and b/images/ui-bg_flat_75_f5f5f5_40x100.png differ diff --git a/images/ui-bg_flat_75_ffffff_40x100.png b/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 000000000..8bdcbdf06 Binary files /dev/null and b/images/ui-bg_flat_75_ffffff_40x100.png differ diff --git a/images/ui-icons_0778dd_256x240.png b/images/ui-icons_0778dd_256x240.png new file mode 100644 index 000000000..7da752764 Binary files /dev/null and b/images/ui-icons_0778dd_256x240.png differ diff --git a/images/ui-icons_0f4d82_256x240.png b/images/ui-icons_0f4d82_256x240.png new file mode 100644 index 000000000..650752445 Binary files /dev/null and b/images/ui-icons_0f4d82_256x240.png differ diff --git a/images/ui-icons_444444_256x240.png b/images/ui-icons_444444_256x240.png new file mode 100644 index 000000000..a957b5e56 Binary files /dev/null and b/images/ui-icons_444444_256x240.png differ diff --git a/images/ui-icons_6b6b6b_256x240.png b/images/ui-icons_6b6b6b_256x240.png new file mode 100644 index 000000000..ad7417ea5 Binary files /dev/null and b/images/ui-icons_6b6b6b_256x240.png differ diff --git a/images/ui-icons_aa0000_256x240.png b/images/ui-icons_aa0000_256x240.png new file mode 100644 index 000000000..7466cc67f Binary files /dev/null and b/images/ui-icons_aa0000_256x240.png differ diff --git a/images/ui-icons_ee1c23_256x240.png b/images/ui-icons_ee1c23_256x240.png new file mode 100644 index 000000000..83b27de2b Binary files /dev/null and b/images/ui-icons_ee1c23_256x240.png differ diff --git a/images/ui-icons_ffffff_256x240.png b/images/ui-icons_ffffff_256x240.png new file mode 100644 index 000000000..4f624bb2b Binary files /dev/null and b/images/ui-icons_ffffff_256x240.png differ diff --git a/images/valken_fbrand002.jpg b/images/valken_fbrand002.jpg new file mode 100644 index 000000000..0093e62bf Binary files /dev/null and b/images/valken_fbrand002.jpg differ diff --git a/images/virtue_vio_goggles_preorder_sidebanner_template.jpg b/images/virtue_vio_goggles_preorder_sidebanner_template.jpg new file mode 100644 index 000000000..8ba78e89a Binary files /dev/null and b/images/virtue_vio_goggles_preorder_sidebanner_template.jpg differ diff --git a/images/white_arrow.png b/images/white_arrow.png new file mode 100644 index 000000000..2f2c07307 Binary files /dev/null and b/images/white_arrow.png differ diff --git a/images/wide_banners/2empire_bt_tht_slideshow_template.jpg b/images/wide_banners/2empire_bt_tht_slideshow_template.jpg new file mode 100644 index 000000000..7375a61ba Binary files /dev/null and b/images/wide_banners/2empire_bt_tht_slideshow_template.jpg differ diff --git a/images/wide_banners/azodin_kdii_slideshow_template.jpg b/images/wide_banners/azodin_kdii_slideshow_template.jpg new file mode 100644 index 000000000..302662078 Binary files /dev/null and b/images/wide_banners/azodin_kdii_slideshow_template.jpg differ diff --git a/images/wide_banners/azodinbanner.jpg b/images/wide_banners/azodinbanner.jpg new file mode 100644 index 000000000..9a3d0ec7f Binary files /dev/null and b/images/wide_banners/azodinbanner.jpg differ diff --git a/images/wide_banners/dye_2014_slideshow.jpg b/images/wide_banners/dye_2014_slideshow.jpg new file mode 100644 index 000000000..4023d971b Binary files /dev/null and b/images/wide_banners/dye_2014_slideshow.jpg differ diff --git a/images/wide_banners/empire_minigs_slideshow.jpg b/images/wide_banners/empire_minigs_slideshow.jpg new file mode 100644 index 000000000..6e86f1819 Binary files /dev/null and b/images/wide_banners/empire_minigs_slideshow.jpg differ diff --git a/images/wide_banners/tippmanmilitary.jpg b/images/wide_banners/tippmanmilitary.jpg new file mode 100644 index 000000000..f98072b5f Binary files /dev/null and b/images/wide_banners/tippmanmilitary.jpg differ diff --git a/images/wide_banners/vio_homepage_slideshow.jpg b/images/wide_banners/vio_homepage_slideshow.jpg new file mode 100644 index 000000000..140f1d39e Binary files /dev/null and b/images/wide_banners/vio_homepage_slideshow.jpg differ diff --git a/images/wordpress-32x32.png b/images/wordpress-32x32.png new file mode 100644 index 000000000..f564c4300 Binary files /dev/null and b/images/wordpress-32x32.png differ diff --git a/images/wrapper_freeship100_header001.png b/images/wrapper_freeship100_header001.png new file mode 100644 index 000000000..aabe4c858 Binary files /dev/null and b/images/wrapper_freeship100_header001.png differ diff --git a/images/youtube-32x32.png b/images/youtube-32x32.png new file mode 100644 index 000000000..94bd76603 Binary files /dev/null and b/images/youtube-32x32.png differ diff --git a/images/zephyr_logo.png b/images/zephyr_logo.png new file mode 100644 index 000000000..85629f7ca Binary files /dev/null and b/images/zephyr_logo.png differ diff --git a/images/zephyr_logo_small.png b/images/zephyr_logo_small.png new file mode 100644 index 000000000..037326708 Binary files /dev/null and b/images/zephyr_logo_small.png differ diff --git a/images/zephyr_reviewsprite.png b/images/zephyr_reviewsprite.png new file mode 100644 index 000000000..cf39b4e4a Binary files /dev/null and b/images/zephyr_reviewsprite.png differ diff --git a/images/zephyr_tags.png b/images/zephyr_tags.png new file mode 100644 index 000000000..05b76e310 Binary files /dev/null and b/images/zephyr_tags.png differ diff --git a/images/zs09_add_to_cart.jpg b/images/zs09_add_to_cart.jpg new file mode 100644 index 000000000..1cd0ba23c Binary files /dev/null and b/images/zs09_add_to_cart.jpg differ diff --git a/images/zs09_p_btn_arrdate-156x31.jpg b/images/zs09_p_btn_arrdate-156x31.jpg new file mode 100644 index 000000000..00e421685 Binary files /dev/null and b/images/zs09_p_btn_arrdate-156x31.jpg differ diff --git a/images/zs10_body_bg-2000x16.gif b/images/zs10_body_bg-2000x16.gif new file mode 100644 index 000000000..72044b187 Binary files /dev/null and b/images/zs10_body_bg-2000x16.gif differ diff --git a/images/zs10_menu_weeklyspecials3-109x23.gif b/images/zs10_menu_weeklyspecials3-109x23.gif new file mode 100644 index 000000000..6cd93d414 Binary files /dev/null and b/images/zs10_menu_weeklyspecials3-109x23.gif differ diff --git a/images/zs11_h_title_bg-1x25.jpg b/images/zs11_h_title_bg-1x25.jpg new file mode 100644 index 000000000..1014a9430 Binary files /dev/null and b/images/zs11_h_title_bg-1x25.jpg differ diff --git a/images/zs12_packages-109x23.gif b/images/zs12_packages-109x23.gif new file mode 100644 index 000000000..bfcb7962d Binary files /dev/null and b/images/zs12_packages-109x23.gif differ diff --git a/images/zs_btn_search-48x18.gif b/images/zs_btn_search-48x18.gif new file mode 100644 index 000000000..bd3da543d Binary files /dev/null and b/images/zs_btn_search-48x18.gif differ diff --git a/images/zs_buyersguide-94x23.gif b/images/zs_buyersguide-94x23.gif new file mode 100644 index 000000000..33591cf4a Binary files /dev/null and b/images/zs_buyersguide-94x23.gif differ diff --git a/images/zs_cat_hdr1-183x30.gif b/images/zs_cat_hdr1-183x30.gif new file mode 100644 index 000000000..a20b34302 Binary files /dev/null and b/images/zs_cat_hdr1-183x30.gif differ diff --git a/images/zs_cat_hdr2-183x30.gif b/images/zs_cat_hdr2-183x30.gif new file mode 100644 index 000000000..9c74e04f0 Binary files /dev/null and b/images/zs_cat_hdr2-183x30.gif differ diff --git a/images/zs_clearanceitem-107x23.gif b/images/zs_clearanceitem-107x23.gif new file mode 100644 index 000000000..c19c8e7d1 Binary files /dev/null and b/images/zs_clearanceitem-107x23.gif differ diff --git a/images/zs_helpdek-117x22.gif b/images/zs_helpdek-117x22.gif new file mode 100644 index 000000000..8810ac0c4 Binary files /dev/null and b/images/zs_helpdek-117x22.gif differ diff --git a/images/zs_login_hdr-183x30.gif b/images/zs_login_hdr-183x30.gif new file mode 100644 index 000000000..d9c69ba85 Binary files /dev/null and b/images/zs_login_hdr-183x30.gif differ diff --git a/images/zs_mycart-78x25.gif b/images/zs_mycart-78x25.gif new file mode 100644 index 000000000..8c58d527f Binary files /dev/null and b/images/zs_mycart-78x25.gif differ diff --git a/images/zs_new_cat_arrow-8x12.gif b/images/zs_new_cat_arrow-8x12.gif new file mode 100644 index 000000000..30ac120db Binary files /dev/null and b/images/zs_new_cat_arrow-8x12.gif differ diff --git a/images/zs_new_footer3_bg-1x114.jpg b/images/zs_new_footer3_bg-1x114.jpg new file mode 100644 index 000000000..2a5ce12f6 Binary files /dev/null and b/images/zs_new_footer3_bg-1x114.jpg differ diff --git a/images/zs_newitems-81x23.gif b/images/zs_newitems-81x23.gif new file mode 100644 index 000000000..9a9393b76 Binary files /dev/null and b/images/zs_newitems-81x23.gif differ diff --git a/images/zs_phone_icn-11x17.gif b/images/zs_phone_icn-11x17.gif new file mode 100644 index 000000000..6d4e4a8b3 Binary files /dev/null and b/images/zs_phone_icn-11x17.gif differ diff --git a/images/zs_prd_tit_mid-1x59.gif b/images/zs_prd_tit_mid-1x59.gif new file mode 100644 index 000000000..19463c37b Binary files /dev/null and b/images/zs_prd_tit_mid-1x59.gif differ diff --git a/images/zs_prd_tit_right-17x59.gif b/images/zs_prd_tit_right-17x59.gif new file mode 100644 index 000000000..2ec1e8f78 Binary files /dev/null and b/images/zs_prd_tit_right-17x59.gif differ diff --git a/images/zs_recent_header-183x26.gif b/images/zs_recent_header-183x26.gif new file mode 100644 index 000000000..7d0e3503e Binary files /dev/null and b/images/zs_recent_header-183x26.gif differ diff --git a/images/zs_signinbtn-58x17.gif b/images/zs_signinbtn-58x17.gif new file mode 100644 index 000000000..7f8056f9a Binary files /dev/null and b/images/zs_signinbtn-58x17.gif differ diff --git a/images/zs_tit_youmaylike-194x26.gif b/images/zs_tit_youmaylike-194x26.gif new file mode 100644 index 000000000..288e9d48f Binary files /dev/null and b/images/zs_tit_youmaylike-194x26.gif differ diff --git a/images/zs_topnavchecko-188x18.gif b/images/zs_topnavchecko-188x18.gif new file mode 100644 index 000000000..302cb766d Binary files /dev/null and b/images/zs_topnavchecko-188x18.gif differ diff --git a/includes.js b/includes.js index 45d395162..07bafa175 100644 --- a/includes.js +++ b/includes.js @@ -1,5 +1,37 @@ //this file merges three formerly separate files: variations.js, json2.js and wiki.js +// POLYFILL FOR MAP. required for peg. +// *** 201402 -> added to make peg more backwards compatible (run in IE8) +if (!Array.prototype.map) +{ + Array.prototype.map = function(fun /*, thisArg */) + { + "use strict"; + + if (this === void 0 || this === null) + throw new TypeError(); + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") + throw new TypeError(); + + var res = new Array(len); + var thisArg = arguments.length >= 2 ? arguments[1] : void 0; + for (var i = 0; i < len; i++) + { + // NOTE: Absolute correctness would demand Object.defineProperty + // be used. But this method is fairly new, and failure is + // possible only if Object.prototype or Array.prototype + // has a property |i| (very unlikely), so use a less-correct + // but more portable alternative. + if (i in t) + res[i] = fun.call(thisArg, t[i], i, t); + } + + return res; + }; +} /* @@ -61,7 +93,7 @@ initialize: function(pogs,o) { this.invCheck = o.invCheck ? o.invCheck : false; //set to true and a simple inventory check occurs on add to cart. this.imgClassName = o.imgClassName ? o.imgClassName : 'sogImage'; //allows a css class to be set on images (for things like magicZoom) this.sku = o.sku; // -// app.u.dump('inventory check = '+this.invCheck+' and className = '+this.imgClassName); +// dump('inventory check = '+this.invCheck+' and className = '+this.imgClassName); this.handlers = {}; this.addHandler("type","text","renderOptionTEXT"); @@ -113,12 +145,12 @@ getOptionByID: function(id) { //upgraded to jquery. renderOptionSELECT: function(pog) { -// app.u.dump('BEGIN renderOptionSELECT for pog '+pog.id+' and safe id = '+safeid); +// dump('BEGIN renderOptionSELECT for pog'); dump(pog); var pogid = pog.id; var $parentDiv = $("<span \/>"); var $selectList = $("<select>").attr({"name":pogid}); var i = 0; - var len = pog['@options'].length; + var len = $.isEmptyObject(pog['@options']) ? 0 : pog['@options'].length; var selOption; //used to hold each option added to the select var optionTxt; @@ -139,8 +171,8 @@ renderOptionSELECT: function(pog) { i++; } -// app.u.dump(" -> pogid: "+pogid); -// app.u.dump(" -> pog hint: "+pog['ghint']); +// dump(" -> pogid: "+pogid); +// dump(" -> pog hint: "+pog['ghint']); $selectList.appendTo($parentDiv); if(pog['ghint']) {$parentDiv.append(pogs.showHintIcon(pogid,pog['ghint']))} return $parentDiv; @@ -155,7 +187,7 @@ renderOptionBIGLIST: function(pog) { var selOptions = ''; var lastOptGrp,selValues; var inc = 0; - var len = pog['@options'].length; + var len = $.isEmptyObject(pog['@options']) ? 0 : pog['@options'].length; var $parentDiv = $("<span \/>"); var $selectList = $("<select \/>").attr({"name":pogid}).addClass("zform_select zform_biglist"); //sets the first options on both select lists. @@ -191,7 +223,7 @@ check if at iteration 1 (inc = 0) each time in the loop. this is gives us a tigh } selOptions += "<\/optgroup>"; -// app.u.dump(selOptions); +// dump(selOptions); $selectList.append(selOptions).appendTo($parentDiv); //append optgroups. @@ -204,15 +236,15 @@ check if at iteration 1 (inc = 0) each time in the loop. this is gives us a tigh //upgraded to jquery. renderOptionIMGSELECT: function(pog) { -// app.u.dump('BEGIN renderOptionIMGSELECT for pog '+pog.id); +// dump('BEGIN renderOptionIMGSELECT for pog '+pog.id); var pogid = pog.id; var $parentDiv = $("<span \/>").addClass('imgSelectContainer'); var $selectList = $("<select>").attr({"name":pogid}).addClass('zform_select').bind('change', function(e){ var thumbnail = $("option:selected",$(this)).attr('data-thumbnail'); - $(this).closest('.imgSelectContainer').find('img').attr('src',app.u.makeImage({"w":pog.width,"h":pog.height,"name":thumbnail,"b":"FFFFFF","tag":false,"lib":app.username})); + $(this).closest('.imgSelectContainer').find('img').attr('src',makeImage({"w":pog.width,"h":pog.height,"name":thumbnail,"b":"FFFFFF","tag":false})); }); var i = 0; - var len = pog['@options'].length; + var len = $.isEmptyObject(pog['@options']) ? 0 : pog['@options'].length; var selOption; //used to hold each option added to the select var optionTxt; @@ -237,10 +269,10 @@ renderOptionIMGSELECT: function(pog) { if(pog['ghint']) {$parentDiv.append(pogs.showHintIcon(pogid,pog['ghint']))} - $imageDiv = $('<div>').addClass('imageselect_image'); - $imageDiv.html(app.u.makeImage({"w":pog.width,"h":pog.height,"name":"blank.gif","b":"FFFFFF","tag":true,"lib":app.username,"id":"selectImg_"+pogid})); + var $imageDiv = $('<div>').addClass('imageselect_image'); + $imageDiv.html(makeImage({"w":pog.width,"h":pog.height,"name":"blank.gif","b":"FFFFFF","tag":true,"id":"selectImg_"+pogid})); $imageDiv.appendTo($parentDiv); -// app.u.dump('END renderOptionIMGSELECT for pog '+pog.id); +// dump('END renderOptionIMGSELECT for pog '+pog.id); return $parentDiv; }, @@ -253,7 +285,7 @@ renderOptionRADIO: function(pog) { //display ? with hint in hidden div IF ghint is set if(pog['ghint']) {$parentDiv.append(pogs.showHintIcon(pogid,pog['ghint']))} var i = 0; - var len = pog['@options'].length; + var len = $.isEmptyObject(pog['@options']) ? 0 : pog['@options'].length; while (i < len) { $parentDiv.append($("<label \/>").append($('<input>').attr({type: "radio", name: pogid, value: pog['@options'][i]['v']})).append(pog['@options'][i]['prompt'])); i++; @@ -282,7 +314,7 @@ renderOptionHIDDEN: function(pog) { var pogid = pog.id; //hidden attributes don't need a label. !!! //cant set the value to null in IE because it will literally write out 'undefined'. this statement should handle undefined, defined and blank just fine. - var defaultValue = app.u.isSet(pog['default']) ? pog['default'] : ""; + var defaultValue = pog['default'] ? pog['default'] : ""; var $parentDiv = $("<span \/>"); //Creates the 'hidden input' form field in the DOM which is used to let the cart know that the checkbox element was present and it's absense in the form post means it wasn't checked. $parentDiv.append($('<input>').attr({type: "hidden", name: pogid, value: defaultValue})); @@ -303,7 +335,7 @@ renderOptionATTRIBS: function(pog) { renderOptionTEXT: function(pog) { var pogid = pog.id; //cant set the value to null in IE because it will literally write out 'undefined'. this statement should handle undefined, defined and blank just fine. - var defaultValue = app.u.isSet(pog['default']) ? pog['default'] : ""; + var defaultValue = pog['default'] ? pog['default'] : ""; var $parentDiv = $("<span \/>"); //Creates the 'hidden input' form field in the DOM which is used to let the cart know that the checkbox element was present and it's absense in the form post means it wasn't checked. var $textbox = $('<input>').attr({type: "text", name: pogid, value: defaultValue}); @@ -325,7 +357,7 @@ renderOptionTEXT: function(pog) { renderOptionCALENDAR: function(pog) { var pogid = pog.id; - var defaultValue = app.u.isSet(pog['default']) ? pog['default'] : ""; + var defaultValue = pog['default'] ? pog['default'] : ""; var $parentDiv = $("<span \/>"); var $textbox = $('<input>').attr({type: "text", name:pogid, value: defaultValue}).addClass('zform_textbox').datepicker({altFormat: "DD, d MM, yy"}); @@ -349,7 +381,7 @@ renderOptionCALENDAR: function(pog) { renderOptionNUMBER: function(pog) { var pogid = pog.id; //cant set the value to null in IE because it will literally write out 'undefined'. this statement should handle undefined, defined and blank just fine. - var defaultValue = app.u.isSet(pog['default']) ? pog['default'] : ""; + var defaultValue = pog['default'] ? pog['default'] : ""; var $parentDiv = $("<span \/>"); //right now, 'number' isn't widely supported, so a JS regex is added to strip non numeric characters var $textbox = $('<input>').attr({type: "number", name: pogid, value: defaultValue}).keyup(function(){ @@ -374,7 +406,7 @@ renderOptionNUMBER: function(pog) { renderOptionTEXTAREA: function(pog) { var pogid = pog.id; //cant set the value to null in IE because it will literally write out 'undefined'. this statement should handle undefined, defined and blank just fine. - var defaultValue = app.u.isSet(pog['default']) ? pog['default'] : ""; + var defaultValue = pog['default'] ? pog['default'] : ""; var $parentDiv = $("<span \/>"); //Creates the 'hidden input' form field in the DOM which is used to let the cart know that the checkbox element was present and it's absense in the form post means it wasn't checked. var $textbox = $('<textarea>').attr({name: pogid, value: defaultValue}); @@ -408,9 +440,9 @@ renderOptionIMGGRID: function(pog) { var radioLabel; //used to create the radio button label. var thumbnail; //guess what this holds var i = 0; - var len = pog['@options'].length; + var len = $.isEmptyObject(pog['@options']) ? 0 : pog['@options'].length; while (i < len) { - thumbnail = app.u.makeImage({"w":pog.width,"h":pog.height,"name":pog['@options'][i]['img'],"b":"FFFFFF","tag":true,"lib":app.username}); + thumbnail = makeImage({"w":pog.width,"h":pog.height,"name":pog['@options'][i]['img'],"b":"FFFFFF","tag":true}); radioLabel = "<label>"+pog['@options'][i]['prompt']+"<\/label>"; $radioInput = $('<input>').attr({type: "radio", name: pogid, value: pog['@options'][i]['v']}); $parentDiv.append(thumbnail).append($radioInput).append(radioLabel).wrap("<div class='floatLeft'><\/div>");; @@ -428,7 +460,7 @@ renderOptionUNKNOWN: function(pog) { // !!! this'll need fixin showHintIcon : function(pogid,pogHint) { -// app.u.dump("BEGIN variations.showHintIcon"); +// dump("BEGIN variations.showHintIcon"); return "<span class='ghint_qmark_container'><a href='#' onclick='$(this).parent().next().toggle(); return false;' class='ghint_qmark'>?<\/a></span><div style='display:none;' class='zhint'>"+pogHint+"</div>"; }, @@ -1006,18 +1038,18 @@ this was necessary because otherwise the converted html was output as <a href... suffix = phrase; } - + dump(' -> operation: '+operation+' and linkCmdPointer'+linkCmdPointer+' and suffix: '+suffix+' and phrase: '+phrase); switch(operation) { case ":url" : - if(linkCmdPointer && !$.isEmptyObject(app.ext[linkCmdPointer].wiki) && typeof app.ext[linkCmdPointer].wiki[":url"] == 'function') - output = app.ext[linkCmdPointer].wiki[":url"](suffix,phrase) + if(linkCmdPointer && !$.isEmptyObject($._app.ext[linkCmdPointer].wiki) && typeof $._app.ext[linkCmdPointer].wiki[":url"] == 'function') + output = $._app.ext[linkCmdPointer].wiki[":url"](suffix,phrase) else output = "<a href=\""+suffix+"\" target='_blank'>"+phrase+"</a>"; break; case ":search" : - if(linkCmdPointer && !$.isEmptyObject(app.ext[linkCmdPointer].wiki) && typeof app.ext[linkCmdPointer].wiki[":search"] == 'function') - output = app.ext[linkCmdPointer].wiki[":search"](suffix,phrase); + if(linkCmdPointer && !$.isEmptyObject($._app.ext[linkCmdPointer].wiki) && typeof $._app.ext[linkCmdPointer].wiki[":search"] == 'function') + output = $._app.ext[linkCmdPointer].wiki[":search"](suffix,phrase); else output = "<a href=\""+domain+"search.cgis?KEYWORDS="+suffix+"\">"+phrase+"</a>"; break; @@ -1025,50 +1057,50 @@ this was necessary because otherwise the converted html was output as <a href... case ":category" : if(suffix.indexOf('.') != 0) {suffix = "."+suffix} //make sure category suffixes (safe id) start with . - if(linkCmdPointer && !$.isEmptyObject(app.ext[linkCmdPointer].wiki) && typeof app.ext[linkCmdPointer].wiki[":category"] == 'function') - output = app.ext[linkCmdPointer].wiki[":category"](suffix,phrase); + if(linkCmdPointer && !$.isEmptyObject($._app.ext[linkCmdPointer].wiki) && typeof $._app.ext[linkCmdPointer].wiki[":category"] == 'function') + output = $._app.ext[linkCmdPointer].wiki[":category"](suffix,phrase); else output = "<a href=\""+domain+"/category/"+suffix+"/\">"+phrase+"</a>"; break case ":product" : - if(linkCmdPointer && !$.isEmptyObject(app.ext[linkCmdPointer].wiki) && typeof app.ext[linkCmdPointer].wiki[":product"] == 'function') - output = app.ext[linkCmdPointer].wiki[":product"](suffix,phrase) + if(linkCmdPointer && !$.isEmptyObject($._app.ext[linkCmdPointer].wiki) && typeof $._app.ext[linkCmdPointer].wiki[":product"] == 'function') + output = $._app.ext[linkCmdPointer].wiki[":product"](suffix,phrase) else output = "<a href=\""+domain+"/product/"+suffix+"/\">"+phrase+"</a>" break; case ":customer" : - if(linkCmdPointer && !$.isEmptyObject(app.ext[linkCmdPointer].wiki) && typeof app.ext[linkCmdPointer].wiki[":customer"] == 'function') - output = app.ext[linkCmdPointer].wiki[":customer"](suffix,phrase) + if(linkCmdPointer && !$.isEmptyObject($._app.ext[linkCmdPointer].wiki) && typeof $._app.ext[linkCmdPointer].wiki[":customer"] == 'function') + output = $._app.ext[linkCmdPointer].wiki[":customer"](suffix,phrase) else output = "<a href=\""+domain+"/customer/"+suffix+"/\">"+phrase+"</a>" break; case ":popup" : -// app.u.dump(":popup suffix: "+suffix); - if(linkCmdPointer && !$.isEmptyObject(app.ext[linkCmdPointer].wiki) && typeof app.ext[linkCmdPointer].wiki[":popup"] == 'function') - output = app.ext[linkCmdPointer].wiki[":popup"](suffix,phrase) +// dump(":popup suffix: "+suffix); + if(linkCmdPointer && !$.isEmptyObject($._app.ext[linkCmdPointer].wiki) && typeof $._app.ext[linkCmdPointer].wiki[":popup"] == 'function') + output = $._app.ext[linkCmdPointer].wiki[":popup"](suffix,phrase) else output = "<a href=\""+suffix+"\" target='popup'>"+phrase+"</a>"; break; case ":policy" : - if(linkCmdPointer && !$.isEmptyObject(app.ext[linkCmdPointer].wiki) && typeof app.ext[linkCmdPointer].wiki[":policy"] == 'function') - output = app.ext[linkCmdPointer].wiki[":policy"](suffix,phrase) + if(linkCmdPointer && !$.isEmptyObject($._app.ext[linkCmdPointer].wiki) && typeof $._app.ext[linkCmdPointer].wiki[":policy"] == 'function') + output = $._app.ext[linkCmdPointer].wiki[":policy"](suffix,phrase) else output = "<a href=\""+domain+"/policy/"+suffix+"/\">"+phrase+"</a>" break; case ":app" : - if(linkCmdPointer && !$.isEmptyObject(app.ext[linkCmdPointer].wiki) && typeof app.ext[linkCmdPointer].wiki[":app"] == 'function') - output = app.ext[linkCmdPointer].wiki[":app"](suffix,phrase) + if(linkCmdPointer && !$.isEmptyObject($._app.ext[linkCmdPointer].wiki) && typeof $._app.ext[linkCmdPointer].wiki[":app"] == 'function') + output = $._app.ext[linkCmdPointer].wiki[":app"](suffix,phrase) else { - app.u.dump("WARNING! no app handle/token specified (required per app): "+chunk); + dump("WARNING! no app handle/token specified (required per app): "+chunk); output = phrase; } break; @@ -1157,7 +1189,7 @@ $.fn.serializeJSON = function(options){ $(options.selector,$form).each(function(){ var val; -// app.u.dump(" -> this.type: "+this.type); +// dump(" -> this.type: "+this.type); if(!this.name){return}; //early exit if name not set, which is required. if ('radio' === this.type) { @@ -1171,7 +1203,7 @@ $.fn.serializeJSON = function(options){ var optionsArr = new Array(); // 'this' loses meaning in the option loop, so a var is created and set after. $('option',$(this)).each(function(){ var $option = $(this); - // app.u.dump(" -> $option.prop('selected'): "+$option.prop('selected')); + // dump(" -> $option.prop('selected'): "+$option.prop('selected')); if($option.prop('selected')) { optionsArr.push($option.val()); } @@ -1590,6 +1622,7 @@ if (!this.JSON) { if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); } @@ -1658,7 +1691,7 @@ jQuery.extend(imgSlider.prototype, { this.pause = 200; //first pic has been displayed, so start rotation quickly. this.handleAnime(); //start the slideshow this.pause = 3500; //used to determine length of time before slide leaves. takes into account time it takes to slide in (but not depart) -// app.u.dump(this); +// dump(this); }, getWidth : function(){ var r = 0; //what is returned. sum width; diff --git a/index.html b/index.html new file mode 100644 index 000000000..3000b2f9b --- /dev/null +++ b/index.html @@ -0,0 +1,1915 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8"> + +<title>Cheap Paintball Guns and Paintball Gear - Zephyr Paintball Supplies + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                          + +
                                                          + +
                                                          +

                                                          DUCK! We're Loading... :)

                                                          + +
                                                          +
                                                          +
                                                          +
                                                          0% Complete
                                                          +
                                                          +
                                                          +
                                                          + + + + +
                                                          +
                                                          + +
                                                          +
                                                          +
                                                          +
                                                          + + + + + +
                                                          + +
                                                          +
                                                          +
                                                          on orders
                                                          over $100
                                                          +
                                                          + FREE SHIPPING +
                                                          + + + + + +
                                                          + Questions? Call Us + 1.877.814.4297 +
                                                          + + + + +
                                                          + +
                                                          +
                                                          + + + + + + + + + + + + +
                                                          + + + + + + +
                                                          + +
                                                          + +
                                                          + + +
                                                          +
                                                          +
                                                          + +
                                                          + Click here for your chance to win $50.00! +
                                                          + +
                                                          + + + +
                                                          + + + + + + + + + + + + + + +
                                                          +
                                                          +
                                                          +
                                                          +
                                                          +
                                                          + + +
                                                          + +
                                                          + + +
                                                          +
                                                          +
                                                          + + + + + + + + + + + + + + + + + + + +
                                                          + + + + + + + +
                                                          +
                                                          +
                                                          +
                                                          + +
                                                          +
                                                          +
                                                          +
                                                          +
                                                          +
                                                          + +
                                                          +
                                                          + + +
                                                          +

                                                          Featured Items

                                                          +
                                                            +
                                                            + + +
                                                            +
                                                            + +

                                                            About Zephyr Paintball

                                                            +

                                                            ZephyrPaintball.com is your one stop paintball store for Cheap Paintball Gear and Airsoft Gear at affordable prices. In a hurry to get your Paintball Gear? We have you covered! All orders placed by 2pm Pacific ship the same day and most orders arrive within 1-4 business days. We have great sale prices and a helpful customer service staff. We are proud to be your one stop Paintball shop for your Paintball Gear and Airsoft needs with a wide variety of product just a click away. Whether you're looking for a Paintball Guns, Paintball Masks, Paintball Gun Upgrades, Paintball Air Tanks, Paintball Supplies, Airsoft Guns and gear, It's in stock and ready to ship. Just check the live inventory to see if what you want is in stock.

                                                            +

                                                            Zephyr Sports was founded in 2004 as a Paintball Shop to serve you the avid Paintball and Airsoft player. Zephyr carries a huge selection of Paintball Gear Bags, Paintball Harnesses, Paintball Guns and Paintball Hoppers. We carry a complete line of paintball equipment with only the finest products made from top quality manufacturers. Some of these brands include: Dye Paintball, JT Sports, kingman Spyder, Tippmann, Pure Energy, Empire Paintball] BT Paintball, TechT, Alien, Proto Paintball Guns, Dangerous Power, Azodin and Planet Eclipse. In 2005 we expanded to carry Airsoft. We currently carry a full line of Airsoft Guns including Airsoft Rifles, Airsoft Pistols, BBs, pistol holsters, Protective Gear and many other products to meet your airsoft needs.

                                                            + +

                                                            ZephyrPaintball.com Store Offers Free Shipping over $100 on Paintball Guns and Paintball Packages and supplies at the lowest prices on the web. New to Paintball? We offer the most complete line of Paintball Packages for the beginner or tournament player to get you on the field . Not sure what you need? Be sure to check out our Paintball Gear Buyers Guide as well as our live chat for a quick answer from an experienced Paintball or Airsoft player. If you're a hardcore Paintball tournament or scenario player we carry all the gear you could ever want.

                                                            +

                                                            Paintball Games

                                                            +

                                                            There are various different games that can be played to keep you paintball games entertaining. Capture the flag, elimination, hold the fort are popular at our local fields. Capture the flag - In the game, paintball players are separated in two teams, a flag can either be put in the middle of the field, or a flag can be put at the home base of each team. The idea is to capture the flag without getting shot and return it to your home base. This game is always a challenge since as soon as you grab the flag, you are now the target of every remaining player on the opposing team.

                                                            +

                                                            Elimination - The is the standard game of paintball. You choose two sides, blow the whistle and shoot the opponent until every player is eliminated, or a set time period expires. This is the easiest game to play and is great when you have a large group of people.

                                                            +

                                                            Hold the fort - One of my favorite games of paintball. In capture the fort, you have two teams, one whose job is is to hold a fort or base of some kind for a set period of time. The opposing team has to take over the fort before the time limit ends. Depending on the strength of the cover on the field, you can allow a player to respawm or stagger the team sizes at the beginning of the game.

                                                            +

                                                            Let's take a look at the paintball gear to get you in the game.

                                                            +

                                                            Paintball Goggles

                                                            +

                                                            Your Paintball Mask should be your top priority. You goggles are not the place to go cheap . If your Goggles fog up, your out of the game. When you are looking at the design of a paintball goggle that is more expensive it typically becomes lighter and smaller for easy maneuvering, provides more padding, thermal lenses for fog resistance and more ventilation. While an entry level Paintball mask will get you on the field, spring for a mask with a thermal lens (starting at about $35) for an enjoyable fog free day on the field.

                                                            +

                                                            Sly Googles - The Sly Profit was released in 2011. This revolutionary new mask is a great addition to your paintball gear bag. With Thermal Lenses, Dual Mask Strap for just the right fit along with plenty of padding and protection, the Profit Goggle is a great new top of the line choice. Just released by Sly Paintball in 2012, The Sly Annex takes some of the great feature from the Profit including a thermal Lens for less than $40.

                                                            +

                                                            Empire Goggles - Tournament level Empire masks include the Empire Event ZN Goggle as well as new Empire E-flex goggle. For an Entry Level Paintball goggle, check out the Empire Vidar Goggle. Thermal lens and comfort for about $50 with Empire Quality.

                                                            +

                                                            Dye Paintball Goggles - Dye Paintball is the Lexus of tournament Paintball Gear. The Dye I4 Paintball Goggle builds on the long history of Dye invision goggles. This 4th Generation goggle has one of the slimmest profiles which is great for keeping the gun tight to your face and out of the line of paint. Want to save a few bucks? The Dye I3 Pro is still available in limited quantities. A full line of replacement lenses are available from Amber to mirror and more.

                                                            +

                                                            JT Paintball Masks are known for their reliability as well as design & comfort. The JT Spectra series are well known for being affordable and durable. Their flexible design allows balls to bounce which keep you in the game for as long as possible. Single or Thermal lenses depending on which model.Full Coverage Goggles also available. The great thing about the JT goggles is that the lenses can be easily changed out for a thermal lens for the ultimate anti-fog setup.

                                                            +

                                                            V Force Goggles - VForce makes great goggles for all levels of paintball. From the high end V force Profiler and V force Grill to the entry level pro vantage, Vforce make some of the most spherically correct goggles for clear vision throughout your entire paintball game.

                                                            +

                                                            Tippmann Paintball Masks - Tippmann is finally making there own masks. The leader in entry level paintball guns now has a full line of goggles for the field or the mid level player.

                                                            +

                                                            Paintball Tanks

                                                            +

                                                            Your paintball gun isn't going to shoot itself! There are basically two different types of tanks used for paintball. Co2 is the standard for entry level players. It is cheap and easy to get. Co2 tanks start at about $20. One drawback to co2 is that it is very rough on your paintball gun. Co2 is stored as a liquid in your tank, to shoot your gun it needs to convert to a gas. depending on the angle you are holding your gun, weather conditions, and your rate of fire, you may end up getting liquid co2 into your paintball marker and shooting snow out of the barrel. This makes for a very inconsistent shot and is difficult on the internals of your paintball gun. The other type of tank is a compressed air or HPA tank. HPA tanks store high pressure air at 3000 - 4500 psi and have a regulator on the tank to control the flow of air in the range of 500 to 800 psi. Compressed air tanks are significantly more expensive due to the costs of the regulator as well as the bottle that needs to hold alot of pressure. Aluminum HPA tanks start at $40 and will hold 3000 PSI and weigh about the same as a 20oz co2 tank. Carbon fiber tanks will hold 4500 PSI

                                                            +

                                                            Ninja Paintball Tanks - Proudly made in the USA. Ninja has made some of the best compressed air bottles in the industry for years. Cutting edge regulator technology and some of the lightest bottles. Spend the extra few bucks on ninja and support made in the USA.

                                                            +

                                                            Paintball Hoppers

                                                            +

                                                            Have to make sure your loader keeps up with your spiffy new paintball gun. A good quality paintball hopper will consistently feed paintballs to your paintball gun with no breaks, jams or mis feeds. Hoppers start with a basic gravity feed hopper. These as you guessed just use the force of gravity to feed paintballs into your gun. While this will keep up with entry level semi auto paintball guns, these won't quite cut it as you move into electronic paintball guns. For those guns you will need to get an electric paintball loader. Electric hoppers start at about 8 BPS (balls per second) up to 50+ BPS with the Dye Rotor. Do your research and if you can afford a good Paintball hopper like the Halo Too, Prophecy Z2 or Valken V-max it's worth spending the money up front instead of having to buy another Paintball loader down the road. Released in 2012 is the new Virtue Spire. Virtue has been known as the best upgrade board manufacturer. Finally they have there own product. The virtue spire brings unsurpassed speed with the spire feed. Super gentle on the most brittle paint.

                                                            +

                                                            Paintball Harnesses

                                                            +

                                                            Your gonna need more paintballs than you can hold in your hopper. Your paintball gear must include a good paintball harness will carry plenty of pods full of extra paint. Harnesses that say +1 i.e 2+1, 4+1 etc typically will also be able to hold paintball tanks also. With you tank on your back, you will need a remote coil to attach the tank to your marker. If speedball is more your style you will want a pack with the notation 3+2, 4+3, 5+4, etc. The first number will be the number of rigid pod holders, the second number will be the number of pods help in elastic straps to get all the paintballs you need on the field. Dye Harnesses and Empire Harnesses are the leaders in tournament style Pod carriers. Be sure to our NXE harness section for a mix of entry and tournament levels harnesses.

                                                            +

                                                            Paintball Gear Bags

                                                            +

                                                            A Paintball gear bag to carry all your paintball supplies makes life much easier. One place to put all your paintball gear for a long day of play. A good Paintball Gear bag will have plenty of room to store a few Paintball Guns as well as your goggles, paintball tanks, harness, pods and tools. Your best bet is to get a wheeled gear bag. Planet Eclipse Bag Eclipse Bags are some of the nicest made. Plenty of room to store all your gear as well as some pretty sweet designs. The Big Daddy of Paintball gear bags is the Dye Navigator. This bag even splits in two to make air travel easy.

                                                            +

                                                            Paintball Clothing & Apparel

                                                            +

                                                            Although jeans and a sweatshirt may work for your first few times playing paintball, your going to want to invest in some good paintball gear. We carry a complete line of cheap paintball clothing as well as high end tournament gear. Paintball pants and a jersey are a good start. A good set of paintball clothing will be much more comfortable, cool as well as giving you a few extra bounces. Plus you won't destroy clothes you may want to wear again.

                                                            +

                                                            Paintball Pants - We carry paintball pants prices start at $40 and go up to about $180 . A good set of pants will provide padding for your hips, knees, and the family jewels. Dye Pants come with padded knees that typically do not require you to wear knee pads. Plenty of soft padding for your legs and hips that will give you an extra bounce or two when you need it the most. Looking for a basic entry level paintball pant? The Valken Fate Pants have you covered. Although these do not have padding, at $40 they will allow you to have a lot more mobility and save you a pair of jeans.

                                                            +

                                                            Paintball Jerseys - Starting at about $30 and go up to $100, paintball jerseys offer a range of features for the avid paintball player. Padded elbows, shoulders and chest help with the pain of the close shots whil giving you a few bounces when you need them most. Durable material is not going to rip and can put up with a ton of abuse. Plus you look like you know what your doing. Basically the higher you step up in price range, the more and better features you get. Thicker padding, better designs, more breathable, etc.

                                                            +

                                                            Paintball Upgrades

                                                            +

                                                            + The Zephyr Paintball Shop also carries a wide variety of Paintball Upgrades that include Paintball Barrels, Triggers, Virtue Boards and many other accessories to improve the look and performance of your paintball gun. For barrels there are many different brands & sizes but here at Zephyr we offer great beginner barrels such as the J&J Ceramic Barrel & more advanced barrels such as the Dye Ultralite Barrel & of course the extremely light and accurate Deadlywind Barrel.

                                                            +

                                                            Our leading manufacturer of Boards comes from Virtue Paintball. Virtue Boards are known for giving your paintball gun a major boost in performance. Most electronic guns have only a few operating modes such as Semi-Automatic, Full Auto & some type of burst. With the Virtue Board there are many more modes to play around with. Having these options gives you the advantage over other players. Keeping you firing at a fast rate and for a much longer game time with its increase in battery life. This is just one example of the high performance boards that we offer. You can check out other boards such as Tadao & Hater that both offer something to look forward to.

                                                            +

                                                            There is so much more we offer beyond paintball guns and upgrades. Our Paintball store contains a wide variety of Paintball Tanks Including Co2 Tanks,Paintball Air Tank, Paintball Loader, Paintball Harness, Paintball Clothing & Paintball Protective gear are all available for all types of players. We understand the importance of individuality. All players have different needs, some want to be as compact as possible for speed ball types of fields. Which means smaller tank, lighter jersey/pants, low profile loader. Some players take a different view on the game and don't have the same concern as being compact but rather need to blend in with their environment for tactical game play. Some may want to play in the woods or a jungle type field that get the best use out of baggy camo paintball pants, realistic paintball guns & tactical vest to hold extra ammo and parts. There are many options with Paintball and that's why Zephyr is here to get you placed where you are most comfortable.

                                                            +

                                                            Paintball has grown so much in the last decade and there is no doubt that there is much more you can do to customize your appearance, your gun, your comfort, and your overall paintball experience. At Zephyr we make sure all Paintball related items are available for our customers. Paintball products are constantly being released and we take it upon ourselves to make sure our site has the newest and greatest on hand. Our user-friendly website makes it easier than ever to navigate your way through this wonderful experience. If you don't see something you are looking for it might still be there but in a category that was looked over, so remember you can always email us and/or call us with any questions or concerns to help your online experience be quick and simple.

                                                            +

                                                            At ZephyrPaintball.com, we welcome all feedback to help us stay strong and grow as a company. Our customers are most important to us, so never hesitate to let us know how you feel. All comments are important and needed so we as your supplier have an honest, open relationship for your internet experience. You can send us an email at sales@zephyrsports.com or give us a ring at 877-814-4297. Visit our Paintball Blog. We also stay active with Google+ & Facebook add us, follow us, + us and befriend us!

                                                            +
                                                            +
                                                            +
                                                            + + +
                                                            +
                                                            +
                                                            Click Here for Your Chance to
                                                            + Win $50.00! +
                                                            + + + + + +
                                                            + + +
                                                            + +
                                                            + +
                                                            + + + + + + + + + + + +
                                                            + + + +
                                                            + +
                                                            + + + + + + +
                                                            + + + + + + + + +

                                                            + +
                                                            + + + + + + + + + + + + + +
                                                            + + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                              +
                                                              + +
                                                              +

                                                              Featured Items

                                                              +
                                                                +
                                                                + + +
                                                                +
                                                                +
                                                                + + +
                                                                +
                                                                + +
                                                                + + +
                                                                + + + + +
                                                                + +
                                                                + + + + + + + + + + + + + + + +
                                                                + +
                                                                + +
                                                                +
                                                                + +
                                                                +
                                                                + + +
                                                                + +
                                                                + + + +
                                                                + + +
                                                                + + + + + + + + + + + + + + + + + + + + + + + +
                                                                + + + +

                                                                + +
                                                                + +
                                                                + +
                                                                + +
                                                                +
                                                                + +
                                                                Mfg:
                                                                +
                                                                + + +
                                                                + +
                                                                + + +
                                                                +
                                                                +
                                                                + + +
                                                                +
                                                                +
                                                                + + + + + +
                                                                +
                                                                + +
                                                                + + +
                                                                +
                                                                +
                                                                +
                                                                + +
                                                                +

                                                                + MSRP: + +

                                                                +

                                                                +
                                                                + + +
                                                                + +
                                                                + + +
                                                                +
                                                                +
                                                                +
                                                                +
                                                                +
                                                                +
                                                                + +
                                                                +

                                                                Description

                                                                +
                                                                +
                                                                + + +
                                                                +
                                                                +
                                                                +
                                                                + +
                                                                + +
                                                                +

                                                                Related Product

                                                                + + + +
                                                                + +
                                                                +
                                                                + + +
                                                                + Write Review +

                                                                Customer Reviews

                                                                +
                                                                +
                                                                +
                                                                + + +
                                                                +
                                                                +
                                                                +
                                                                  +
                                                                  + +
                                                                  + + + + + +
                                                                  + +
                                                                  + + + + + + + + + + + + + + + + + + +
                                                                  + +

                                                                  Oops! We have a Problem! The page you are trying to reach does not exist. Our developers have been informed and will fix this. To continue shopping, hit the back button or just use our search to find the product you want.

                                                                  + +
                                                                  + + + + + + + + + + + + + + + + + + + +
                                                                    + +
                                                                  + + + + +
                                                                  + +
                                                                  + +
                                                                  + +
                                                                  + +
                                                                  +

                                                                  About Zephyr

                                                                  +

                                                                  ZephyrPaintball.com delivers Paintball and Airsoft Gear at affordable prices on Paintball Guns, Paintball Goggles, Gun Upgrades, Air Systems, Airsoft Equipment and much more gear. Zephyr Sports was founded in 2003 as an internet retailer focusing on the sport of Paintball. We carry a complete line of paintball equipment with only the finest products made from top quality manufacturers. Through ZephyrAirsoft.com you will find many types of Airsoft Rifles, Pistols, Ammo, Gas, Holsters, Protective Gear and many other products to meet your airsoft needs. Whether it is related to Paintball, Airsoft, Camelbaks, or Sunglasses, we want all options available for our customers.

                                                                  +

                                                                  We understand the importance of individuality. All players have different needs, some want to be as compact as possible for speed ball types of fields. Which means smaller tank, lighter jersey/pants, low profile loader. Some players take a different view on the game and don't have the same concern as being compact but rather need to blend in with their environment for tactical game play. Some may want to play in the woods or a jungle type field that get the best use out of baggy camo pants, realistic paintball guns & tactical vest to hold extra ammo and parts. There are many options with Paintball and that's why Zephyr is here to get you placed where you are most comfortable.

                                                                  +

                                                                  Paintball has grown so much in the last decade and there is no doubt that there is much more you can do to customize your appearance, your gun, your comfort, and your overall paintball experience. At Zephyr we make sure all Paintball related items are available for our customers. Paintball products are constantly being released and we take it upon ourselves to make sure our site has the newest and greatest on hand. Our user-friendly website makes it easier than ever to navigate your way through this wonderful experience. If you don't see something you are looking for it might still be there but in a category that was looked over, so remember you can always email us and/or call us with any questions or concerns to help your online experience be quick and simple.

                                                                  +

                                                                  At Zephyr, we welcome all feedback to help us stay strong and grow as a company. Our customers are most important to us, so never hesitate to let us know how you feel. All comments are important and needed so we as your supplier have an honest, open relationship for your internet experience. You can send us an email at sales@zephyrsports.com or give us a ring at 877-814-4297.

                                                                  +
                                                                  + + +
                                                                  +

                                                                  Contact Information

                                                                  + + +
                                                                  +

                                                                  Our customer service hours are Mon - Fri 9-5 PST. You can contact us by phone or electronically once you are logged in.

                                                                  +

                                                                  Click here to log in or create an account

                                                                  +
                                                                  + +
                                                                  +
                                                                  + +

                                                                  We can be reached Mon - Fri 9-5 Pacific at sales@zephyrpaintball.com or 805-275-2040

                                                                  +
                                                                  +
                                                                  + +
                                                                  + Contact Us +
                                                                  + + + + +
                                                                  +
                                                                  +
                                                                  +
                                                                  +
                                                                  + + +
                                                                  +

                                                                  Retail Store

                                                                  + +

                                                                  Storefront Hours

                                                                  +

                                                                  +Sunday: 9:00 - 2:00 Dec - June Only
                                                                  +Monday: 10:00 - 5:30
                                                                  +Tuesday: 10:00 - 5:00
                                                                  +Wednesday: 10:00 - 5:00
                                                                  +Thursday: 10:00 - 5:30
                                                                  +Friday: 10:00 - 5:30
                                                                  +Saturday: 8:30 - 5:00 +

                                                                  + +

                                                                  Phone: 805-275-2040

                                                                  + +

                                                                  Zephyr Sports started out in Paintball back in 2004 and has continued to expand ever since. What was a garage operation selling things here and there on Ebay as a hobby has grown exponentially for the past 10+ years. Zephyr is always striving to make their customer's shopping experience as painless and simple as possible.

                                                                  + +

                                                                  Come get your CO2 and Compressed Air Tanks filled here. Includes Scuba Tanks (air not suitable for diving)

                                                                  + +

                                                                  Our New Store is now open for business at 2978 Seaborg Ave. Ventura, CA 93003. The new location is 3 times the size of the old store for our vast inventory of Paintball, and Airsoft products. Come in and see the brand new location and the 2,100 sq foot show room! You can get directions through Google here:
                                                                  + Zephyr Directions +

                                                                  +
                                                                  + + +
                                                                  + + + +
                                                                  +

                                                                  Frequently Asked Questions

                                                                  +
                                                                  +
                                                                  + + + + +
                                                                  +

                                                                  Payment Policy

                                                                  +

                                                                  What are My Payment Choices? You have several payment options to choose from when shopping at Zephyr. We accept all major credit cards which include; Visa, MasterCard, American Express and Discover. You may also choose PayPal. We do NOT accept checks or international credit cards.

                                                                  + +

                                                                  When Will My Credit Card be Charged? Your card will be charged as we send your order to the warehouse for processing.

                                                                  + +

                                                                  When Will My Credit Appear on My Account? Credit will typically appear back on the card within 5-7 business days of cancellation. If you are returning and item then it will take 5-7 business days from when we receive and process your return.

                                                                  + +

                                                                  I Have Questions About My Charges. If you have a question about any charges or credits on your account, you may want to contact your financial institution first. If you have any other questions at that point, please give us a call at 877-814-4297.

                                                                  + +

                                                                  Do I Have to Pay Sales Tax? You do not have to pay sales tax unless you live in California.

                                                                  + +

                                                                  Low Price GuaranteeWe will provide store credit when we drop a price on an exact item within 30 days of an online order. This must be on the exact size and color of the item ordered! If we no longer have the specific size or color in stock, then we will not provide the credit. The store credit will be equal to the difference in price.

                                                                  + +
                                                                  + + +
                                                                  +

                                                                  Privacy Statement

                                                                  +

                                                                  About this Privacy Policy:

                                                                  + +
                                                                  Zephyr Sports tracks IP Addresses
                                                                  +

                                                                  Your IP address is used to help diagnose problems with our server, and to administer the Web site, in addition your IP address is used to help identify you and your shopping cart (in conjunction with a cookie.) We also use cookies to deliver content specific to your interests and to save your password so you don't have to re-enter it each time you visit our site.

                                                                  + + +

                                                                  This site may contains links to other sites.

                                                                  +

                                                                  Zephyr Sports is not responsible for the privacy practices or the content of such Web sites, unless otherwise specified below your information is never shared with other companies.

                                                                  + +

                                                                  This site requires Unique Identifiers.

                                                                  +

                                                                  This site uses an order form for customers to request information, products, and services, it also collects visitor's contact information (like their email address), in some circumstances their unique identifiers (like their pets name, or mothers maiden name), and financial information (like their account or credit card numbers). Contact information from the order form is used to send orders and information about our company to customers. The customer's contact information is also used to get in touch with the visitor when necessary. Users may opt-out of receiving future informational mailings; see the choice/opt-out section below, users may NOT opt out of receiving order notifications, or other contacts which are deemed essential by Zephyr Sports.

                                                                  + +

                                                                  This site requires Financial Information.

                                                                  +

                                                                  Financial information that is collected is used to bill the customer for products and services. Unique identifiers (such as pets name, and mothers maiden name) are collected from Web site visitors to verify the user's identity.

                                                                  + +

                                                                  This site may have Surveys and/or Contests.

                                                                  +

                                                                  Our online surveys ask visitors for contact information (like their email address). We use contact data from our surveys to send the user information about our company. The customer's contact information is also used to contact the visitor when necessary. Users may opt-out of receiving future mailings; see the choice/opt-out section below. This site may also run contests in which case we may ask visitors for contact information (like their email address). Generally this information is used to verify eligibility, however we may also use contact data from our contests to send users information about this Company. The customer's contact information is also used to contact the visitor when necessary (for example winners). Users may opt-out of receiving future mailings; see the choice/opt-out section below. Financial information that is collected from our users is used to check the users' qualifications for registration and bill the user for products and services.

                                                                  + + +

                                                                  Third Party Cookies

                                                                  +

                                                                  Third party vendors, including Google, use cookies to serve the badge on the website and to serve ads based on a user's prior visits to the website. Users may opt out of Google's use of cookies by visiting the Google advertising opt-out page.

                                                                  + +

                                                                  This site may contain Public Forums

                                                                  +

                                                                  This site may include chat rooms, forums, message boards, and/or news groups available to its users. Please remember that any information that is disclosed in these areas becomes public information and you should exercise caution when deciding to disclose your personal information.

                                                                  + +

                                                                  About our System Security

                                                                  +

                                                                  This site has security measures in place to protect the loss, misuse and alteration of the information under our control. Information is stored behind a firewall, against a password protected database system. Whenever sensitive information is accessed it is transmitted using strong SSL encryption. this Company may keep a copy of your information on its own system using Zoovy's WebAPI system, this system may have its own security measures in place.

                                                                  + +

                                                                  This site provides the choice to Opt In or Out

                                                                  +

                                                                  Our site provides users the opportunity to opt-out of receiving communications from us at the point where we request information about the visitor. This site gives users the following options for removing their information from our database to not receive future communications or to no longer receive our service. Each time an information email is distributed, you have the option to use unique unsubscribe url which is attached to each outgoing email. Customers may unsubscribe at any time by simply logging into their accounts.

                                                                  + +

                                                                  We provide the ability to Correct/Update YOUR information.

                                                                  +

                                                                  This site gives users the following options for changing and modifying information previously provided. Simply visit the customer login area of this website.

                                                                  + +
                                                                  + + + + +
                                                                  +

                                                                  Return Policy

                                                                  + +

                                                                  What is the Zephyr Return Policy? Zephyr Sports will accept most returns on unopened items for up to 30 days after the invoice date. Returns are for products that you do not wish to keep and must have zero appearance of being opened or used. If we have sent you an incorrect product or size, we will happily help you to return the product.

                                                                  + +

                                                                  We do not accept defective merchandise for return. Please contact the manufacturer of any product in question that did not work. We will be glad to help you contact any manufacturer in question.

                                                                  + +

                                                                  A 15% restocking fee will be charged on all returns requesting a refund. However, this fee will be waived if store credit is chosen. The restocking fee will not be waived if we did indeed send you the correct product you ordered.

                                                                  + +

                                                                  Most guns cannot be returned after they have been opened. The manufacturer will handle all warranty issues, including issues directly out of the box. The manufacturer will typically be able to talk you through any issues you are having over the phone without having to send the item in for repair. In the event that you do have to send the marker in for repair, Zephyr Sports will issue store credit to cover your shipping costs to warranty an item, if the issue is out of the box. To request this, fax or e-mail a copy of your shipping receipt and include your order # to 805-293-8717 or sales@zephyrsports.com. We will process a store credit to cover the shipping cost.

                                                                  + +

                                                                  If you would like to exchange a product for a different size, color, or product all together, all that we require is that the product be returned to us in exactly the same condition it was sent. It must be unused and contain the original packaging intact. The customer assumes any shipping cost both to our warehouse and back to the customer.

                                                                  + +

                                                                  Our Returns & Exchanges section is specially designed to speed up the process of filing and following up on any return or exchange request. By taking the time to read through our policies and follow the information provided, we will be better able to serve you and quickly resolve any issue that may arise.

                                                                  + +

                                                                  Returns & Exchanges are reserved for customers whom received the incorrect product or who received the correct product ordered but wish to return for refund, return for store credit, or exchange.

                                                                  + +

                                                                  Any return or exchange will be processed at the time we receive the item(s) in question. We are obligated to verify that any claim for return or exchange is valid before moving forward with any kind of refund, credit, or exchange. Please allow 5-7 business days for any refund or credit to show on your credit statement or account.

                                                                  + +

                                                                  Note: If we receive your item and confirm that it is the correct product ordered by you, up to a 15% restocking fee will be assessed before any refund or exchange is given. It is the responsibility of you (the customer) to verify that you order a product you truly want. If you ever have any question about a product before you order, please give us a call at 805-275-2040.

                                                                  + + +

                                                                  I received the Wrong Product. If you have received the wrong product please call us at 805-275-2040. We will be glad to help you straighten this out. Do not attempt to use or open the product as any claim for return will be void. We allow claims to be filed up to 30 calendar days after the delivery date; any claim made after 30 calendar days is considered void.

                                                                  + +

                                                                  To streamline the process and make sure you receive the correct product as fast as possible, we advise you to call our customer service department. Please have your invoice readily available as our representatives will need to verify information listed on your order invoice.

                                                                  + +

                                                                  Once our customer service representatives verify your claim that the incorrect product was shipped to you, we will promptly email a FedEx shipping label to cover any shipping cost. Our reps will also be glad to help you locate your local FedEx drop-off/pick-up location. Once we receive the product and confirm that it was shipped incorrectly, we will then ship the correct product to you via a similar means as the original order. Our reps should give you a RMA number to clearly print on the outside of the box; be sure to follow these instructions or your package may be refused.

                                                                  + +

                                                                  If you are unable to receive a FedEx shipping label, please include a copy of any receipt detailing shipping costs. Once received and confirmed, we will then reimburse your shipping cost via store credit to your account. Reimbursements will only be authorized for standard ground shipping. If you decide to ship by any other means, we will only reimburse up to a maximum of the determined FedEx ground cost.

                                                                  + +

                                                                  Note: If we receive your item and confirm that it is the correct product ordered by you and no mistake was made, we will then require you to pay for shipping back to you. If you would like to exchange the product, please read the above return/exchange policy.

                                                                  + +

                                                                  I Received Someone Else's Order. If you have received someone Else's order please give us a call at 805-275-2040.

                                                                  + +

                                                                  We appreciate the honesty and integrity of our customer base. It is because of you that our business has continuously been able to offer the lowest prices anywhere.

                                                                  + +

                                                                  My Order is Missing an Item(s). If your order is missing an item or you received an incorrect quantity, please immediately contact our customer service department at 805-275-2040. We allow claims to be filed up to 30 calendar days after the delivery date; any claim made after 30 calendar days is considered void.

                                                                  + +

                                                                  To streamline the process and make sure you receive any product in question as quickly as possible, we advise you to call our customer service department. Please have your invoice readily available as our representatives will need to verify information listed on your order invoice.

                                                                  + +

                                                                  Once your claim is filed, our representatives will then research the claim by verifying the weight received by FedEx as well as confirm items pulled & packed for your order. If indeed we failed to ship any product in question, we will promptly send out your item(s) via a similar shipping method as the original order at no additional charges to you.

                                                                  + +

                                                                  In the event that we did in fact pull, pack, and ship all items ordered, it is likely that your package was tampered with while in transit. In this case we will handle your claim on a case by case basis to help resolve any issues. Be aware that it is our policy to file a claim with FedEx for packages that may have been tampered with during transit.

                                                                  + +
                                                                  + + + +
                                                                  +

                                                                  Shipping Information

                                                                  +

                                                                  Does My Shipping and Billing Addresses Have to Match? For fraud protection purposes, we require that all address information must match what is on file with the credit card company. If you are shipping to an address other than your billing address, the shipping address must also be listed with your financial institution as an alternate shipping address. This can easily be done by calling the number on your statement or the back of your credit card. It only takes a few minutes and does not affect your billing information at all. If both addresses are on file with the credit card company, you still may be contacted to verify your address.

                                                                  +

                                                                  If this is the case, please give us a call at 805-275-2040 so that we can manually verify your addresses with the credit card company. If your financial institution cannot verify your address with us, you will be contacted via email or phone call. If we are unable to verify your address within 10 days, your order will be cancelled.

                                                                  + +

                                                                  How Much is Shipping? After you place your items in your shopping cart, all you need to do is enter you zip code in the shipping calculator on the shopping cart page to receive shipping quotes.

                                                                  + +

                                                                  International ShippingAfter you place your items in your shopping cart, international customers will have to enter their entire address in order to receive a shipping quote.

                                                                  + + +

                                                                  Does My Package Require a Signature? Orders over $250 will require an adult to be present to sign for the package. If your order is less than $250 and there is a safe place to leave your package, the carrier may leave the package if no one is available at time of delivery. This decision is made by your local carrier and Zephyr Sports cannot be responsible for packages lost in transit. We will assist in filing a lost package claim with the carrier.

                                                                  + +

                                                                  When you shop with Zephyr, you get great service and fast shipping. We know how anxious you are after you place an order and we will get your order out as soon possible. Orders placed by 2 p.m. pst are typically shipped out the same day. (Orders placed over the weekend will ship the next business day) On rare occasions, weekend orders may not ship until Tuesday due to the large volume of orders. If you need to have your order on a certain day, please choose the method that will have it arrive one day early. In the event that one or more of the items from your order is out of stock, you will be notified via telephone or email. You have 3 days from that point to contact us, or we will refund and remove the out of stock items, and ship the rest of the order.

                                                                  + +

                                                                  Free Zephyr Shipping Zephyr Sports offers Free shipping to the United States in certain cases. Items shipped using economy shipping will be shipped via Fedex or USPS at our choice. Additional shipping charges might apply when shipping to an APO/FPO address. Shipping times will vary from 1-day in southern California, to 6 days on the east coast. Please not that weekends are not counted as shipping days. Please upgrade to Fedex shipping if you require faster shipping. USPS orders will receive a delivery confirmation number. This will only give you delivery confirmation and will not allow you to track your package along the way. USPS shipping does not include any insurance. We recommend you upgrade to Fedex shipping whenever possible. If you choose Economy shipping, you cannot choose the shipping method.

                                                                  + +

                                                                  FedEx Shipping Our preferred method of shipping is Fedex. Fedex delivers Monday through Friday and does not pickup or deliver on the weekends. We ship Fedex Home Delivery, 3-day air, 2-day air and standard next day. Fedex will attempt to deliver three times. If you miss all three of these attempts, then Fedex will hold your package for seven days and also send you a postcard to inform you of its arrival. If you fail to collect this package within the set period then it will get returned to us. Zephyr Sports will hold your package for fifteen days. Please note that if this happens we will charge you for re-shipping. If you fail to collect your package within fifteen days, we will refund your account and withhold all shipping fees as well as a 15% restocking fee.

                                                                  + +

                                                                  Insurance If no insurance is selected, Zephyr Sports will not be responsible for any damaged, lost or stolen merchandise (etc). If no insurance is selected FedEx packages will be shipped with only USD 100.00 insured.

                                                                  + +

                                                                  Can I Pick Up My Order? This option is no longer available. If you live close by or are in the area feel free to stop by our storefront and do some shopping: 2978 Seaborg Ave Ventura, CA., 93003

                                                                  + +

                                                                  Can I Track My Package? Yes you can. As long as you entered a valid e-mail address during checkout, you will receive an e-mail with tracking information. Please be sure to check your spam filter as these e-mails tend to get caught in these filters.

                                                                  + +

                                                                  Free Zephyr Shipping. When you place an order over $100(excluding taxes and handling) you can receive Free Zephyr Shipping or get Home Delivery for ONLY $3! No rebates, No hassles! Just place the items you wish to order in your shopping cart and type in your zip code and the shipping rates will pop up. Free Zephyr Shipping and Home Delivery should be one of the options to choose from. Fedex Home Delivery only delivers to the United States and only delivers Tuesday through Saturday.

                                                                  +
                                                                    +
                                                                  • Applies only to the contiguous 48 states
                                                                  • +
                                                                  • Applies only to internet orders (Phone orders ship free for orders over $350)
                                                                  • +
                                                                  • Applies only to orders placed directly through www.zephyrpaintball.com (excludes ebay and amazon orders)
                                                                  • +
                                                                  • Excludes P.O. Boxes
                                                                  • +
                                                                  + + +
                                                                  + +
                                                                  + +
                                                                  + + + +
                                                                  + + + +
                                                                  + +
                                                                  +

                                                                  Subscribe to our Newsletter and Save!

                                                                  +
                                                                  +
                                                                  + + + +
                                                                  + +
                                                                  + + + +
                                                                  +
                                                                  + + + +
                                                                  +

                                                                  Create an Account!

                                                                  +
                                                                  +
                                                                  +

                                                                  Not Resistered Yet?

                                                                  +

                                                                  Here are a few reasons to join:

                                                                  +
                                                                  +
                                                                  +

                                                                  Easy Checkout

                                                                  +

                                                                  Save information like billing/shipping address to expedite the checkout process.

                                                                  +
                                                                  +
                                                                  +

                                                                  Order Tracking and History

                                                                  +

                                                                  View and track your orders online, easily.

                                                                  +
                                                                  +
                                                                  +

                                                                  Sign up for exclusive offers

                                                                  +

                                                                  Join our newsletters to gain access to limited time offers, exclusives and sales!

                                                                  +
                                                                  +
                                                                  +
                                                                  + +
                                                                  + + + + + + + +
                                                                  + +
                                                                  + +
                                                                  +
                                                                  + + + +
                                                                  +

                                                                  Manage your Subscriptions

                                                                  + +
                                                                  + +
                                                                  + +
                                                                  + +
                                                                  + +
                                                                  +

                                                                  My Account

                                                                  + +
                                                                  + +
                                                                  +
                                                                  +

                                                                  Billing Address(es)

                                                                  +
                                                                  +
                                                                  + + + +
                                                                  + +
                                                                  +
                                                                  +

                                                                  Shipping Address(es)

                                                                  +
                                                                  +
                                                                  + + +
                                                                  + + +
                                                                  + + +
                                                                  + + +
                                                                  +

                                                                  Order History

                                                                  +
                                                                  +
                                                                  + + +
                                                                  +
                                                                  +
                                                                  + +
                                                                  +

                                                                  Change Password

                                                                  +
                                                                  +
                                                                  +

                                                                  For passwords, we recommend using mixed case, at least one number and one special character.

                                                                  +
                                                                  + + +
                                                                  +
                                                                  +
                                                                  +
                                                                  + + +
                                                                  +

                                                                  List Manager

                                                                  + +
                                                                  + +
                                                                  + +
                                                                  +

                                                                  Your 'Forget Me' list

                                                                  +

                                                                  Items on this list will not show up anywhere on the site. Use it for items you never want to see again. If you add an item to the list by mistake, use this page to remove it from the list and it will start re-appearing during your shopping experience.

                                                                  +
                                                                    +
                                                                  +
                                                                  + +
                                                                  + +
                                                                  + + + +

                                                                  + + + +
                                                                  + +
                                                                  + + + +
                                                                  + +
                                                                  + +
                                                                    +
                                                                    + +
                                                                    + + + + + + + + + + + +
                                                                    +
                                                                    + + + + + +
                                                                    + +
                                                                    + + + + + + + + + + +
                                                                    +
                                                                    + + + + + + + + + +
                                                                    + +
                                                                    + +
                                                                    +
                                                                      +
                                                                      + +
                                                                      +
                                                                      +
                                                                      + + Cart Totals +
                                                                      +
                                                                      + +
                                                                      + +
                                                                      + +
                                                                      + +
                                                                      + +
                                                                      + +
                                                                      +
                                                                      +
                                                                      + +
                                                                      + +
                                                                      + +
                                                                      +

                                                                      Shipping:

                                                                      + +
                                                                      + +
                                                                      + +
                                                                        +
                                                                        + +
                                                                        + + + + + + + + + Secure Checkout + + Fast and Safe In-Store Checkout + + + +
                                                                        + +
                                                                        + + +
                                                                        + + +
                                                                        +
                                                                        +
                                                                        +
                                                                        + + + + + + + + + + + + + +
                                                                          +
                                                                        • + + + + + +
                                                                          + + + +
                                                                          + +
                                                                          + qty: + + + + +
                                                                          + +
                                                                          +
                                                                        • +
                                                                        + + + + + + + + + + + + + + + +
                                                                          +
                                                                        • + + +

                                                                          +
                                                                          +
                                                                          +
                                                                        • +
                                                                        + + + + + +
                                                                        + + + + + + +
                                                                        + + + + + +
                                                                        +
                                                                        + + + + + + + + + + +
                                                                        + +
                                                                        +

                                                                        Please Click here to log in or create an account to write a review.

                                                                        +
                                                                        + +
                                                                        + + + + + + + + + + + + + + + +
                                                                        +
                                                                        + + + + + + + + + +
                                                                        + +
                                                                        + + + +
                                                                        + +
                                                                        + +
                                                                        + + + + + + + + +
                                                                        + +
                                                                        + + +
                                                                        + +
                                                                        + +
                                                                        + + +
                                                                        +
                                                                        +
                                                                        +
                                                                        + + + + + +
                                                                        + +
                                                                        + + +
                                                                        +
                                                                        +
                                                                        +
                                                                        + + + + +
                                                                        +
                                                                        + +
                                                                        + + + +
                                                                        + +
                                                                        + + +
                                                                        +
                                                                        +
                                                                        +
                                                                        + + + + +
                                                                        + +
                                                                        + +
                                                                        + + + + +
                                                                        + +
                                                                        +
                                                                        + + +
                                                                        +

                                                                        +

                                                                        +
                                                                        +
                                                                        + +
                                                                        + +
                                                                        + +
                                                                        + + + + +
                                                                        +
                                                                        +
                                                                        + + + +
                                                                        +
                                                                        +
                                                                        + +
                                                                        + + + + +
                                                                        +
                                                                        +
                                                                        + + + +
                                                                        +
                                                                        +
                                                                        + +
                                                                        + +
                                                                        +
                                                                          + + +
                                                                          +
                                                                          + + +
                                                                          + + + + + + + + + + + + + + + +
                                                                          + + + + + + + + + + +
                                                                          + + + + +

                                                                          + +
                                                                          +
                                                                          + + +
                                                                          + Account Login + + +
                                                                          + +
                                                                          +
                                                                          +
                                                                          + +
                                                                          +
                                                                          +
                                                                          +
                                                                          + Recover Password + +
                                                                          +
                                                                          +
                                                                          +
                                                                          + + +
                                                                          + + +
                                                                          + +
                                                                          + +
                                                                          + + + diff --git a/jquery-1.10.2.js b/jquery-1.10.2.js new file mode 100644 index 000000000..c5c648255 --- /dev/null +++ b/jquery-1.10.2.js @@ -0,0 +1,9789 @@ +/*! + * jQuery JavaScript Library v1.10.2 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03T13:48Z + */ +(function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "
                                                                          "; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
                                                                          a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
                                                                          t
                                                                          "; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
                                                                          "; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
                                                                          ", "
                                                                          " ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
                                                                          " ], + tr: [ 2, "", "
                                                                          " ], + col: [ 2, "", "
                                                                          " ], + td: [ 3, "", "
                                                                          " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
                                                                          ", "
                                                                          " ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
                                                                          " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("\n\n\n", + "head_title" : "Dye Rotor Paintball Loader | Dye Rotor Hopper | Dye Rotor Loader", + "top_description3" : "The Dye Rotor Paintball Loader is standard in tournament paintball loaders. The Dye Rotor is lightweight only requiring three AA batteries. The Low profile of the Dye Rotor keeps the center of gravity and hopper tight to the gun. The tool-less design of the rotor loader allows for easy maintenance and cleaning. at 50+ BPS, the rotor will keep up with any gun and battery life is amazing with 50,000+ shots on a set of batteries possible.", + "page_title" : "Buy Dye Rotor Paintball Loader Online On Sale Now" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.slap_watches" : { + "meta_keywords" : "nixon watches,nixon watch,time teller,player,51-30,watches Nixon,Nixon Player,lodown,banks,rotolog,scout", + "meta_description" : "Nixon Watches - Zephyr Carries a complete of watches from Nixon. Get your Nixon watch today with free shipping at Zephyr Sports. From the Player to the Time Teller we have you covered", + "page_title" : "Nixon Watches Free Shipping at Zephyr Sports", + "head_title" : "Nixon Watches | Nixon Watch | Watches Nixon" + }, + ".3packagespecials.unity_paintball_gun_packages" : { + "head_title" : "Unity Paintball Packages | Unity Paintball Gun Packages" + }, + ".casual_clothing.mens_clothing.hats.proto_hats" : { + "meta_keywords" : "Proto Hats,Proto caps,Proto baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Proto Hats - Zephyr carries a complete line of Proto Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Proto", + "page_title" : "Buy Proto Hats On Sale & Free Shipping", + "head_title" : "Proto Hats | Proto Caps | Proto Baseball Hats" + }, + ".scenarioupgrades.tactical_vests.maddog_tactical_vests" : {}, + ".apparel.gloves.dye_paintball_gloves" : { + "meta_keywords" : "Dye paintball gloves, dye meta gloves, fingerless paintball gloves", + "meta_description" : "Dye Paintball Gloves - The Dye Meta half finger paintball glove is the top of the line glove from Dye. No need to cut the fingers off your gloves, Th Dye Meta comes ready to go.", + "page_title" : "", + "head_title" : "Dye Paintball Gloves | Dye Meta Gloves" + }, + ".markerupgrades.invert_upgrades.invert_mini_maintenance_kits" : { + "meta_description" : "Invert Mini Repair Kits - Buy your Mini Replacement Parts Online at Zephyr Paintball for Less today. Free Shipping on Mini Parts Kit Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert Mini Repair Kits Online On Sale Now", + "head_title" : "Invert Mini Repair Kits | Mini Replacement Parts | Mini Parts Kit " + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_mechanical_sights" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft sights | air gun sights | sights" + }, + ".casual_clothing.mens_clothing.hats.dgk_hats" : { + "meta_description" : "DGK Hats - Buy your DGK Baseball Hats At Zephyr Sports for Less Today! We carry a complete line of DGK Caps at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on DGK Hats @ Zephyr Sports", + "head_title" : "DGK Hats | DGK Baseball Hats | DGK Caps" + }, + ".testing_help_desk.buyers_guide" : { + "hd_answer_two" : "You can search our site by using the search bar or you can use the provided category sections on the left of the site.", + "hd_answer_four" : "One of our policies is to verify all orders over five hundred dollars. That order will not be processed until the order has been verified with customer. If we are unable to verify with customer right away this might delay processing of the order. But that this is necessary to protect all parties involved.", + "hd_question_three" : "How Do I Navigate the Site?", + "hd_question_four" : "Large Order Verification", + "hd_topic_listing" : "» How do I use a coupon or promo code?
                                                                          \n» How do I find a product?
                                                                          \n» How do I navigate the site?
                                                                          \n
                                                                          » Large Order Verification", + "hd_topic" : "Buyer's Guide", + "hd_question_one" : "How Do I Use a Coupon or Promo Code?", + "hd_btn" : "images/site_specific/backto_helpdesk", + "hd_answer_three" : "Use the categories on the left of our site to browse the various different sections. From there they will go into subcategories which can lead to more subcategories. If you are looking for a particular brand you can use our Pro Shops section.", + "hd_question_two" : "How Do I Find a Product?", + "hd_answer_one" : "When going to your shopping cart there is a brown stripe right above your subtotal which is where you can enter your coupon/promo code, then proceed to press enter. If you have any item/product from the manufacturers of Dye, Proto, Smart Parts or DLX in your shopping cart the promo code will not work. These manufacturers have a strict MAP policy and by providing a discount on their products would break this policy.\n\n\n\n\nThe [[Free Items]:popup=http://www.zephyrpaintball.com/category/promotion_codes/] will not work with a promo code. At this time it is either one or the other.", + "hd_link" : "/category/testing_help_desk " + }, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories.valken_molle_vest_accessories" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".goggles.vforce" : { + "meta_keywords" : "Goggles V Force, Paintball Mask V Force, Paintball V Force Mask, Paintball Mask, V Force, V Force Mask, Paintball Goggles, Paintball Masks, Paintball Equipment", + "meta_description" : "Goggles V Force - Visit ZephyrPaintball for the lowest prices on Paintball V Force masks and other equipment.", + "head_title" : "Goggles V Force | Paintball Mask V Force | Paintball V Force Mask", + "page_title" : "Buy Goggles V Force Online On Sale Now", + "sortby_var" : "V-Force Goggle Type", + "zoovy:banner01" : "banners/paintball/headers/goggleaccessories_header001", + "banner01_link" : "/category/goggles.1goggle_accesories.v_force_goggle_accesories/?sortby=!zoovy:base_price", + "page_head" : "" + }, + ".markers.bob_long_paintball_guns" : { + "meta_keywords" : "Bob Long Paintball Guns, Bob Long Paintball Markers, Paintball Bob Long, marq, vice, closer, rapper, protege paintball gun", + "banner1" : "", + "meta_description" : "Bob Long Paintball Guns - The father of tournament Paintall guns. From the Alias to the Rapper, Bob Long has the Paintball Markers to keep your tournament team on the podium", + "page_title" : "Buy Bob Long Paintball Guns Online On Sale Now", + "head_title" : "Bob Long Paintball Guns | Bob Long Paintball Markers | Paintball Bob Long" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_variable_power_scopes.bushnell_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsoft.airsoft_guns.classic_army_airsoft_guns" : { + "meta_description" : "Classic Army Airsoft Guns - Buy your Classic Army Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Classic Army M15A4 at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Classic Army Airsoft Guns On Sale & Free Shipping", + "head_title" : "Classic Army Airsoft Guns | Classic Army Airsoft Rifles | Classic Army M15A4", + "description" : "" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_rolling_gear_bags" : { + "meta_description" : "Oakley Rolling Gear Bags - Buy your Oakley Luggage At Zephyr Sports for Less Today! We carry a complete line of Rolling Oakley Bags at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Oakley Rolling Gear Bags Ship Free @ Zephyr Sports ", + "head_title" : "Oakley Rolling Gear Bags | Oakley Luggage | Rolling Oakley Bags" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_inner_barrels.mad_bull_airsoft_upgradbarrels" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Mad Bull Barrel | Mad Bull Inner Barrel | Mad Bull Airsoft Barrels" + }, + ".loaders.genx_global_paintball_loaders" : {}, + ".harnessesbags.packs___harnesses.sly_paintball_harnesses" : { + "meta_keywords" : "sly paintball harness,sly harness,sly pod pack,sly pro merc", + "meta_description" : "Sly Paintball Harness - Zephyr carries a complete line of Sly Paintball Harnesses include the Pro Merc Line. The Sly Pod Pack will supply all the paint you need for a long came.", + "top_description" : "Sly Paintball Harnesses are now available at Zephyr Paintball. We stock the full line of Pro-Merc Harnesses in both the 3+4 and 4+5 format. Plenty of colors of each Sly harness are available to match your team. You know sly quality apparel, Sly harnesses are top quality. Built to last and comfortable with some of the best looks in the sport. Get your Sly Harness while they last as these are typically only available once a year. When they're gone they're gone till the new version comes out next year.", + "page_title" : "Buy Sly Paintball Harness Online On Sale Now", + "head_title" : "Sly Paintball Harness | Sly Harness | Sly Pod Pack" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.firepower_gas_airsoft_guns" : { + "meta_description" : "Firepower Airsoft Guns - Buy your Firepower AirsoftAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Firepower Airsoft Guns On Sale & Free Shipping", + "head_title" : "Firepower Airsoft Guns | Firepower Airsoft" + }, + ".casual_clothing.mens_clothing.hats.nixon_hats" : { + "meta_keywords" : "Nixon Hats,Nixon caps,Nixon baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Nixon Hats - Zephyr carries a complete line of Nixon Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Nixon", + "page_title" : "Nixon Hats on Sale at Zephyr", + "head_title" : "Nixon Hats | Nixon Caps | Nixon Baseball Hats" + }, + ".airsoft.airsoft_spare_magazines.bb_speed_loaders" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Speed Loader | Speed Loader | Airsoft Loaders" + }, + ".barrels.barrels_by_manufacturer.sly_paintball_barrels" : { + "meta_keywords" : "sly paintball barrels, sly carbon fiber, sly barrel backs, sly carbon tips, sly barrel kit, sly individual backs, sly pro barrel", + "meta_description" : "Sly Paintball Barrels - Sly Carbon Fiber - SLY Barrel Backs - Buy your Online at Zephyr Paintball for Less today. Free Shipping on Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Sly Paintball Barrels - Sly Carbon Fiber - SLY Barrel Backs Online On Sale Now", + "head_title" : "Sly Paintball Barrels - Sly Carbon Fiber - SLY Barrel Backs" + }, + ".casual_clothing.womens_clothing.ladies_rash_guards.dakine_ladies_rash_guards" : {}, + ".misc_items" : { + "subcat1_header" : "Miscellaneous Categories", + "meta_keywords" : "miscellaneous, parts, repair, repairs, paintball, miscellaneous parts, miscellaneous repair, paintball repair kits, repair kits, miscellaneous items, tools, miscellaneous tools", + "meta_description" : "Batteries, gun repair kits, lube and tools is what you will find in here. All the necessities you need to keep that gun of yours performing like the day you got it.", + "prodlist2_title" : "Featured Items", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/misc_header.jpg\"", + "banner1" : "banners/09_headers/main_categories/misc_items_001", + "page_title" : "", + "head_title" : "Miscellaneous Parts | Miscellaneous Items | Repair Kits", + "page_head" : "" + }, + ".casual_clothing.womens_clothing.ladies_beanies.neff_ladies_beanies" : {}, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.32" : {}, + ".airsystems.tankcovers.proto_paintball_bottle_covers" : { + "meta_description" : "Proto Cover - Buy your Proto Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Proto Paintball Bottle Cover Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Proto Cover Online On Sale Now", + "head_title" : "Proto Cover | Proto Tank Cover | Proto Paintball Bottle Cover" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.empire_heat_paintballs" : {}, + ".casual_clothing.mens_clothing.shorts.vans_shorts" : { + "meta_description" : "Vans Shorts - Zephyr stocks a complete line of Vans Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Vans needs. ", + "page_title" : "Vans Shorts with Free Shipping at Zephyr", + "head_title" : "Vans Shorts | Vans Board Shorts" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.vans_pants_and_jeans" : { + "meta_description" : "Vans Pants - Buy your Vans JeansOnline At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Vans Pants & Jeans Ship Free", + "head_title" : "Vans Pants | Vans Jeans" + }, + ".airsoft.tactical_airsoft_gear.tactical_thigh_rigs" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_rim_runner_hydration_packs" : {}, + ".zlinks" : { + "meta_keywords" : "", + "meta_description" : "", + "page_title" : "", + "description" : "\r\n\r\n\r\n\r\n

                                                                          Warranty Information and Other Links

                                                                           

                                                                          www.Tippmann.com\r\n                  \r\n1-800-533-4831
                                                                          \r\nwww.Kingman.com                    \r\n1-888-KINGMAN
                                                                          \r\nwww.Deadonpaintball.com         \r\n1-866-DEADON1
                                                                          \r\nwww.Smartparts.com                 \r\n1-724-539-2660

                                                                           

                                                                           

                                                                          Other Links
                                                                          \r\nwww.extremethings.com\r\nFor the extreme athlete in all of you

                                                                          \r\nPaintball Guns paintball Blog to keep \r\nyou up to day on everything paintball
                                                                          \r\n\r\n\"TopPaintballSites.net\"\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.1p90_style_aeg_airsoft_guns" : { + "meta_description" : "E90 Airsoft Guns - Buy your Airsoft E90 At Zephyr Sports for Less Today! We carry a complete line of E90 AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy E90 Airsoft Guns On Sale & Free Shipping", + "head_title" : "E90 Airsoft Guns |Airsoft E90 |E90 AEG" + }, + ".airsoft.airsoft_guns.airsoft_bb_launchers___shells" : { + "meta_description" : "Airsoft Grenade Launchers - Buy your Airsoft Grenade Shells At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Grenade Launchers On Sale & Free Shipping", + "head_title" : "Airsoft Grenade Launchers |Airsoft Grenade Shells" + }, + ".skateboard_gear.complete_skateboards" : { + "meta_keywords" : "complete skateboards, complete skateboard, longboard completes, completes,Skate Board", + "meta_description" : "Complete Skateboards - Get Your next complete skateboard at Zephyr with Free Shipping. Everything from complete longboards to cheap complete skateboards. Real Time Inventory on all Skate Boards", + "page_title" : "Complete Skateboards Real Time Inventory Free Shipping", + "head_title" : "Complete Skateboards | Complete SkateBoard | Skate Board" + }, + ".airsoft.tactical_airsoft_gear.tactical_scarves" : {}, + ".sponsorship.sponsor_only_specials.team_sponsorship_packages.bt_team_packages" : {}, + ".markers.macdev_paintball_guns.macdev_droid_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray-ban_rb4165_justin_sunglasses" : {}, + ".categoryapparel.jerseys.planet_eclipse_paintball_jerseys" : {}, + ".casual_clothing.womens_clothing.ladies_purses_and_bags.nixon_ladies_purses_and_bags" : {}, + ".safetygear.kneeelbowpads.hk_army" : {}, + ".markerupgrades.smartparts.ion_xe_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "add2_link" : "/category/markerupgrades.feednecks.nxt_feednecks/", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".3packagespecials.pihrana_paintball_packages" : { + "top_html_focus" : "", + "top_html" : "", + "meta_description" : "Pihrana Paintball Packages - Buy your Pirhana Paintball Guns Kits Online at Zephyr Paintball for Less today. Free Shipping on Pihrana Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Pihrana Paintball Packages Online On Sale Now", + "head_title" : "Pihrana Paintball Packages | Pirhana Paintball Guns Kits | Pihrana Paintball Markers" + }, + ".shop_by_brand.hurley_clothing_clothes_apparel_buy_online" : {}, + ".markers.us_army_paintball_guns.us_army_alpha_tactical_paintball_guns" : { + "meta_keywords" : "Tippmann Alpha Black Tactical,Tippmann Army Alpha,Army Tippmann Alpha Tactical Elite,us army,us army alpha, us army tactical elite", + "meta_description" : "Tippmann Alpha Black Tactical Elite - Buy your Tippmann Army Alpha Elite Online at Zephyr Paintball for Less today. Free Shipping on Army Tippmann Alpha Tactical Trust Zephyr for all your Paintball Needs", + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=&LINK=", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.us_army_paintball_packages.us_army_alpha_tactical_paintball_gun_packages/", + "zoovy:banner02" : "", + "page_title" : "Buy Tippmann Alpha Black Tactical Elite Online On Sale Now", + "head_title" : "Tippmann Alpha Black Tactical | Tippmann Army Alpha | Army Tippmann Alpha Tactical Elite" + }, + ".proto_rail_paintball_guns.z_proto_rail_upgrades__" : {}, + ".casual_clothing.mens_clothing.beanies.fox_beanies" : {}, + ".casual_clothing.z-sunglasses.revo_sunglasses.revo_abyss_sunglasses" : { + "meta_description" : "Revo Abyss Sunglasses - Zephyr Sports carries a complete line of Abyss Revo Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Revo Abyss Sun Glasses Online Today.", + "page_title" : "Revo Abyss Sunglasses On Sale Free Shipping", + "head_title" : "Revo Abyss Sunglasses | Abyss Revo Sunglasses Free Shipping | Buy Revo Abyss Sun Glasses" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_vista_ft_hydration_packs" : {}, + ".markers.gog_paintball_guns" : { + "subcat1_header" : "Gog Paintball Guns", + "meta_keywords" : "gog paintball guns,envy,xtcy,g1,smart parts gog,markers", + "meta_description" : "GOG Paintball Guns - Smart Parts is Back. New and Improved. The Gog Envy Paintball Marker and G1 Tactical Marker are the first releases from GOG. The GOG EXTCY is slated for early 2011 Release. Get yours for less with free shipping at Zephyr Paintball.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.gog_paintball_packages/", + "description" : "=Introducing the Brand New 2011 line of GoG Paintball Guns!!!=\n\n\n\n\nSomething here for everyone... Entry Level, More Experienced, and Mil/Sim Styled Markers. The full line of GoG Paintball Guns showcase standard stock features that will compete right out of the box. Don't believe us?? Check out the specs below and get in the game with GoG Paintball!\n\n\n\n\n\n\n\n\n==GoG eXTCY Paintball Guns==\n\n\n\n\nWith Up-To-Date Technology, The GoG eXTCY features a lot of bang for not so much buck! At only $249.95, the all new GoG eXTCY Paintball Gun is great for any level paintball player! This lightweight design employs a full metal aluminum alloy structure making it easy to maneuver and built to last! \nStandard features like Anti-Chop eyes, the Max-Flow R vertical regulator and removable eye covers yield less time chopping paint and more time spent taking out the competition! \nMost importantly, this marker fires 20+ balls per second straight out of the box and is equipped with a stock board fully capable of various firing modes including: semi auto, fully auto, 3 shot burst, PSP and BillyBall! \nDon't stress about the mess, maintaining your paintball gun has never been easier with the all new Bolt Out Back design! Take your eXTCY apart in minutes rather than hours and you'll even be able to put it back together. \n\n\n\n\n\n\n\n\n==GoG G1 Paintball Marker==\n\n\n\n\n2011's first new Military Sim Scenario/Woodsball Paintball Gun. Priced at only $249.95, the G1 is great for any paintball enthusiast! \nWith 7 different accessory rails and built using high quality 6000 series aluminum with high grade composite materials, the G1 is one of the most durable and customizable paintball guns on the market! \nStraight out of the box, the G1 shoots 11 Balls Per Second and can easily be upgraded to shoot up to 25 BPS. \nLow battery operated! With just a standard 9-Volt battery, the GoG G1 paintball gun will easily rock out at least 20,000 shots... That's more than 10 boxes of paint on one fresh battery! \nA unique feature on this military sim gun is the offset adjustable feedneck. This allows for various scopes and/or top rail accessories to be more effective than ever! This really enables all your scenario upgrades to play a bigger role in your success on the field! \nUnmatched Stock Accuracy! With a precision machined 14 inch tactical paintball barrel standard on the G1, you'll have no use for any other aftermarket barrels! \nThe GoG G1 is guaranteed to perform with either HPA or C02 and is fully equipped with the Max-Flow R vertical regulator firing each shot more consistent than the last! \nGet your Scenario Paintball Game On with the G1 from GoG Paintball! \n\n\n\n\n\n\n\n\n==GoG Envy Paintball Gun==\n\n\n\n\nReliable, Affordable, and Effective! \nDesigned for entry level and field rental players, the GoG Envy will hold up against some of the best guns in paintball! Straight out of the box, the GoG Envy shoots a solid 11 Balls Per Second and can easily be upgraded to shoot up to 25BPS. The stock board on this baby is fully capable of various firing modes including: semi auto, fully auto, 3 shot burst, PSP and BillBall! Easy maintainability with its Bolt Out Back design allows for full gun cleaning (inside and out) in minutes rather than hours after a full day at the field. Guaranteed to perform with either C02 or HPA, the GoG Envy is also equipped with the Max-Flow R vertical regulator. This enables its user consistent shooting all day! Not only consistent shooting, but also the GoG Envy comes with a 2 point adjustable trigger which gives the user the ability to adjust the length and feel of each trigger pull. Couple that with the option to use any Smart Parts threaded paintball barrel (Ion, Impulse, NXY Shocker) and you are set to dominate the competition on the field regardless of your playing level! Only $199.95! ", + "head_title" : "GOG Paintball Guns Envy | Gog G1 Paintball Markers | Gog EXTCY Paintball Gun", + "top_description3" : "Gog Paintball - The reincarnation of Smart Parts is here. New improved paintball guns including the Gog Extcy, Gog G1 Tactical and Gog Envy. Starting at 11bps, the GOG line of paintball guns is upgradeable to 25 BPS with a blackheart board and a qev. Gog paintball guns will run off of co2 or compressed air tanks and use an impulse threaded barrel.", + "page_title" : "Buy GOG Paintball Guns Envy Online On Sale Now", + "sortby_var" : "Gun Type" + }, + ".markers.angel_sports_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_monster_pup_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley monster pup sunglasses,polarized oakley monster pup sunglasses", + "meta_description" : "Oakley Monster Pup Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Monster Pup and Polarized Oakley Monster Pup Sunglasses on Sale! ", + "page_title" : "Oakley Monster Pup Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Monster Pup Sunglasses | Monster Pup Oakley Sunglasses" + }, + ".airsystems.tankcovers.bottle_covers_by_tank_size" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_pavilion_sunglasses" : { + "meta_description" : "Smith Optics Pavillion Sunglasses - Zephyr Sports carries a complete line of Pavillion Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Pavillion Sun Glasses Online Today.", + "page_title" : "Smith Optics Pavillion Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Pavillion Sunglasses | Pavillion Smith Sunglasses Free Shipping | Buy Smith Pavillion Sun Glasses" + }, + ".casual_clothing.mens_clothing.watches.vestal_watches" : { + "meta_keywords" : "Vestal,Vestal Watches,Vestal Apparel,vestal watch,mens watches,watches for men,", + "meta_description" : "Vestal Watches - Zephyr Sports carries an array of watches for men. Vestal is a leading designer of mens watches showcased all over the world. Whether its style, or class, Vestal is the watch to wear. ", + "page_title" : "Vestal Watches", + "head_title" : "Vestal | Vestal Watches | Mens Watches" + }, + ".markers.unity" : { + "meta_keywords" : "Unity Paintball, Unity Paintball Guns, Unity Prime, Unity Prime Paintball Gun, Unity Paintball Marker, Unity Prime Marker, Unity Prime Paintball marker, Cheap Paintball Guns, Cheap Paintball Markers, Starter Paintball Gun, Prime Paintball Gun, Prime Marker", + "meta_description" : "Unity Paintball is the company behind the Unity Paintball Guns, and the Unity Prime Paintball Gun. Their first gun is a reliable gun perfect for the player that is just now making an entrance to the paintball scene. ", + "top_description2" : "==Unity==\nUnity Paintball is a new name in the world of paintball, but the foundation of the company has been in the business for over 20 years. Backed by the knowledge and expertise of one of Paintball's best brains, they are proud to release the Unity Prime. ", + "page_title" : "Buy Unity Paintball Guns On Sale", + "head_title" : "Unity Paintball | Unity Paintball Guns | Unity Prime Paintball Guns", + "description" : "The goal of Unity Paintball is to provide a reliable gun that will not break the bank, and they have done just that with the Unity Prime. The Unity Prime is perfect for anybody starting out in the game of paintball." + }, + ".casual_clothing.mens_clothing.shorts.rothco_shorts" : { + "meta_description" : "Rothco Shorts - Zephyr stocks a complete line of Rothco Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Rothco needs. ", + "page_title" : "Rothco Shorts with Free Shipping at Zephyr", + "head_title" : "Rothco Shorts | Rothco Board Shorts" + }, + ".2clearance.clearance_jerseys_apparel.under_5" : { + "head_title" : "Sale Paintball Clothes | Clearance Paintball Clothes | Paintball Clothes Sale" + }, + ".markers.cheap_paintball_guns" : { + "meta_description" : "Cheap Paintball Guns - Buy your Cheap Paintball Markers Online at Zephyr Paintball for Less today. Free Shipping on Cheap Paintball Trust Zephyr for all your Paintball Needs", + "top_description" : "==Entry Level Markers for CHEAP!==\n\nA little paintball for everyone! Full line of Entry level paintball markers. Kingman, Spyder, JT USA, Dynasty, Pirahna, Tippmann and more! Play Paintball without breaking the bank! Reliable, durable and great Paintball guns for under $100. Just starting out?? No Problem! Zephyr has you covered! Paintball Packages available with everything you need to get in the game and compete! Don't miss out now, Save with Zephyr Sports!", + "page_title" : "Buy Cheap Paintball Guns Online On Sale Now", + "head_title" : "Cheap Paintball Guns | Cheap Paintball Markers | Cheap Paintball", + "banner01_link" : "/category/3packagespecials/", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001" + }, + ".airsoft.airsoft_guns.kjw_airsoft_guns" : { + "meta_description" : "KJW Airsoft Guns - Buy your KJW Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of KJW AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy KJW Airsoft Guns On Sale & Free Shipping", + "head_title" : "KJW Airsoft Guns | KJW Airsoft Rifles | KJW AEG" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_axe_watches" : { + "meta_keywords" : "Nixon watches,nixon 51-30 watch,nixon watch,nixon 51-30 chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon 51-30 Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon 51-30 Chrono Watches", + "head_title" : "Nixon Axe Watches | Nixon Axe Chrono Watch | Nixon 5130" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.double_eagle_spring_airsoft_guns" : { + "meta_description" : "Double Eagle Airsoft Guns - Buy your Double Eagle Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Double Eagle Spring Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Double Eagle Airsoft Guns On Sale & Free Shipping", + "head_title" : "Double Eagle Airsoft Guns | Double Eagle Airsoft Rifles | Double Eagle Spring Airsoft Gun" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_flip_side_sunglasses" : {}, + ".goggles.spyder_paintball_masks" : { + "meta_keywords" : "spyder mask,spyder paintball masks,spyder highlite,highlite masks,spyder avant mask,spyder paintball goggles", + "meta_description" : "Spyder paintball mask - Complete line of paintball goggles available from Spyder. Get your Spyder avant and highlite paintball goggles at Zephyr Paintball today", + "top_description" : "Spyder paintball masks are a perfect match for your Spyder paintball gun. Whether your looking for an entry level set of paintball goggles or a thermal mask, Spyder has you covered. The entry level spyder avant mask includes a single pane anti fog lens while the higher end highlite google includes a dual pane thermal lens for the ultimate in fog free paintball play.", + "page_title" : "Spyder Paintball Mask Sale!", + "head_title" : "Spyder Paintball Masks | Spyder Mask" + }, + ".apparel.knee___elbow_pads" : { + "zoovy:banner_image_01" : "banners/categories/safetygear_banner01.jpg", + "page_title" : "", + "head_title" : "Paintball Protective Gear | Protective Paintball Gear | Paintball Knee Pads" + }, + ".markerupgrades.bt_designs_upgrades.bt_paintball_maintenance_kits" : { + "meta_description" : "BT Combat Maintenance Kits - Buy your Empire BT Repair Kits Online at Zephyr Paintball for Less today. Free Shipping on BT Parts Kit Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy BT Combat Maintenance Kits Online On Sale Now", + "head_title" : "BT Combat Maintenance Kits | Empire BT Repair Kits | BT Parts Kit" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.etek_4_paintball_guns" : {}, + ".apparel.gloves.eclipse_paintball_gloves" : { + "meta_keywords" : "Eclipse gauntlet gloves, eclipse paintball gloves, paintball gloves", + "meta_description" : "Eclipse Paintball Gloves - The Eclipse Gauntlet Gloves come in full and half finger styles. Zephyr carries a complete line of Eclipse gear at the best prices on the web.", + "page_title" : "", + "head_title" : "Eclipse Gauntlet Gloves | Eclipse Paintball Gloves" + }, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_csl_paintball_guns" : { + "meta_description" : "Ego CSL - Buy your Planet Eclipse Ego CSL Paintball Gun Online at Zephyr Paintball for Less today. Free Shipping on Eclipse CSL Ego Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Ego CSL Online On Sale Now", + "head_title" : "Ego CSL | Planet Eclipse Ego CSL Paintball Gun | Eclipse CSL Ego" + }, + ".apparel.pants.dyepants.dye_c14_paintball_pants" : { + "top_html_focus" : "" + }, + ".scenarioupgrades.tactical_vests.tippmann_tactical_vests" : {}, + ".misc_items.water_bottles.sigg_water_bottles" : {}, + ".casual_clothing.mens_clothing.shirts.electric_shirts_and_flannels" : {}, + ".safetygear.condor_tactical" : {}, + ".safetygear.kneeelbowpads.kingmanjava" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_hazmat_backpacks" : { + "meta_description" : "Oakley Hazmat Backpack - Buy your Oakley Hazmat Bag At Zephyr Sports for Less Today! We carry a complete line of Hazmat Oakley Backpack at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Hazmat Backpack On Sale & Free Shipping", + "head_title" : "Oakley Hazmat Backpack | Oakley Hazmat Bag | Hazmat Oakley Backpack" + }, + ".harnessesbags.backpacks.511_tactical_backpack___bags" : {}, + ".airsystems.tank_o_rings" : { + "meta_description" : "Paintball O-Rings - Buy your Orings for Paintball Online at Zephyr Paintball for Less today. Free Shipping on Paintball O Rings Repair Kits Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball O-Rings Online On Sale Now", + "head_title" : "Paintball O-Rings | Orings for Paintball | Paintball O Rings Repair Kits" + }, + ".1historical_products.paintball.paintball_guns" : {}, + ".markers.btdesignspaintballguns.bt_designs_starter_packages" : { + "prodlist1_header" : "Battle Tested Paintball Gun Packages", + "prodlist_custom" : "&SORTBY=PRICE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_tanks.empire_paintball_tanks" : {}, + ".maddog.ion_upgrades.ion_triggers" : {}, + ".markerupgrades.smartparts.ion.triggers.shocktech_ion_triggers" : {}, + ".markerupgrades.tippmann.tippmann_x7_upgrades.tippmann_x7_scenario_barrels" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_icon_backpacks" : { + "meta_description" : "Oackley Icon Backpacks - Buy your Oakley Icon Bag At Zephyr Sports for Less Today! We carry a complete line of Icon Oakley Back Pack at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oackley Icon Backpacks On Sale & Free Shipping", + "head_title" : "Oackley Icon Backpacks | Oakley Icon Bag | Icon Oakley Back Pack" + }, + ".markerupgrades.rampingchipsboards.advantage_pb.virtue_oled_upgrade_boards" : { + "meta_description" : "Oled Virtue - Buy your Oled Virtue Boards Online at Zephyr Paintball for Less today. Free Shipping on Virtue Oled Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Oled Virtue Online On Sale Now", + "head_title" : "Oled Virtue | Oled Virtue Boards | Virtue Oled" + }, + ".apparel.shoes.dc_skate_shoes" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4133_barn_burner_sunglasses" : { + "meta_description" : "Arnette Barn Burner Sunglasses - Buy your Arnette 4133 Barn Burner At Zephyr Sports for Less Today! We carry a complete line of Barn Burner Arnette Sunglasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Arnette Barn Burner Sunglasses On Sale & Free Shipping", + "head_title" : "Arnette Barn Burner Sunglasses | Arnette 4133 Barn Burner | Barn Burner Arnette Sunglasses" + }, + ".harnessesbags.tubes.zephyr_paintball_pods" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_water_bottles.___camelbak_podium_water_bottles" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_altitude_backpacks" : {}, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_gear_sets" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Gears | Airsoft Gear Sets | Airsoft Guns Gears" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_hsx_sunglasses" : { + "meta_description" : "Spy Optics HSX Sunglasses - Zephyr Sports carries a complete line of HSX Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy HSX Sun Glasses Online Today.", + "page_title" : "Spy Optics HSX Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics HSX Sunglasses | HSX Spy Sunglasses Free Shipping | Buy Spy HSX Sun Glasses" + }, + ".shop_by_brand.hakkotsu_airsoft" : {}, + ".apparel.pants.hk_army_paintball_pants" : { + "meta_keywords" : "hk army paintball pants,hk army pants,hardline pro pants,hk paintball pants,hardline pro paintball pants", + "meta_description" : "HK Army Hardline Paintball Pants - HK Army pants are here. The Hardline pants are the first edition from HK Army. Tournament level paintball pants that won't break the bank.", + "top_description" : "The HK Army Hardline Pro Paintball Pants have arrived. HK Army has thrown a ton of features in theses pants with the style we all expect from HK Army. The Hardline Pro pants have attitude and plenty of padding to keep you comfortable throughout a day of play.", + "page_title" : "HK Army Hardline Pro Paintball Pants", + "head_title" : "HK Army Paintball Pants | HK Hardline Pro Pants | HK Army Pants", + "zoovy:banner01" : "banners/paintball/slideshow/hk_army_hardline_slideshow.jpg" + }, + ".casual_clothing.mens_clothing.shirts.vans_shirts" : { + "meta_description" : "Vans Flannel Shirts - Buy your Vans Polo Shirts Online At Zephyr Sports for Less Today! We carry a complete line of Vans Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Vans Shirts & Flannels Ship Free", + "head_title" : "Vans Flannel Shirts | Vans Polo Shirts | Vans Shirts" + }, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_mosteez_sunglasses" : {}, + ".casual_clothing.womens_clothing.accessories" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_fuel_cell_sunglasses" : { + "meta_description" : "Oakley fuel Cell Sunglasses - Buy your Fuel Cell Oakley Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Oakley Fuel Cell at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley fuel Cell Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley fuel Cell Sunglasses | Fuel Cell Oakley Sunglasses | Oakley Fuel Cell" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.1_search_by_size.2_medium" : {}, + ".2clearance.clearance_jerseys___apparel.clearance_pants" : { + "head_title" : "Sale Paintball Pants | Clearance Paintball Pants | Paintball Pants Sale" + }, + ".black_friday_paintball_and_airsoft_deals.paintball_guns___packages" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_ohm_sunglasses" : { + "meta_description" : "Electric OHM Sunglasses - Zephyr Sports carries a complete line of Electric OHM Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric OHM Online Today.", + "page_title" : "Electric OHM Sunglasses On Sale Free Shipping", + "head_title" : "Electric OHM Sunglasses | Electric OHM Sun Glasses | Sunglasses Electric OHM" + }, + ".goggles.1goggle_accesories.extreme_rage__pcs_goggle_accesories" : { + "meta_description" : "Extreme Rage Lens - Buy your Extreme Rage Thermal Lens Online at Zephyr Paintball for Less today. Free Shipping on Extreme Rage Replacement Lens Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Extreme Rage Lens Online On Sale Now", + "head_title" : "Extreme Rage Lens | Extreme Rage Thermal Lens | Extreme Rage Replacement Lens" + }, + ".maddog.eclipse_upgrades" : {}, + ".markerupgrades.feednecks.nxt_feednecks" : { + "meta_description" : "Shocker NXT Feed Necks - Buy your Feednecks for NXT Online at Zephyr Paintball for Less today. Free Shipping on NXT Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Shocker NXT Feed Necks Online On Sale Now", + "head_title" : "Shocker NXT Feed Necks | Feednecks for NXT | NXT Feed" + }, + ".goggles.1goggle_accesories.proto_goggle_accesories" : { + "meta_description" : "Proto Lens - Buy your Proto Thermal Lens Online at Zephyr Paintball for Less today. Free Shipping on Proto Replacement Lens Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Proto Lens Online On Sale Now", + "head_title" : "Proto Lens | Proto Thermal Lens | Proto Replacement Lens" + }, + ".casual_clothing.mens_clothing.belts.dgk_belts" : { + "meta_keywords" : "DGK Belts,DGK Belt Buckle,DGK Belts,DGK webbed belt", + "meta_description" : "DGK Belts - We carry the complete line of DGK Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "DGK Belts on Sale Now!", + "head_title" : "DGK Mens Belts | Aplinestars Belts" + }, + ".airsoft.shop_by_brand.we_airsoft" : {}, + ".shop_by_brand.guerrilla_air" : { + "top_html" : "", + "meta_description" : "Guerrilla Air - Buy your Guerilla Air At Zephyr Sports for Less Today! We carry a complete line of Air Guerilla at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=Guerrilla Air. . . High Performance Paintball Systems=\n\nThe core of Guerrilla Air's success and popularity is based on the knowledge and experience gained throughout the years which dates back to their start as Air America and continues to evolve. Their goal is to explore new ways to innovate Paintball technology necessary to improve performance. Guerilla Air strives to enhance the player experience and improve existing technology to perform better and ensure safety is never sacrificed.\n\n\nGuerrilla Air has always been and always will be focused on developing new designs that are more efficient, smaller, lighter and compact; yet offer increased performance without compromise. This methodology of dynamic high performance design is fully realized in our line of MYTH regulators. Recognized by the Paintball community around the world as the most innovative regulator and air systems available today!", + "page_title" : "Buy Guerrilla Air On Sale & Free Shipping", + "head_title" : "Guerrilla Air | Guerilla Air | Air Guerilla", + "zoovy:banner01" : "banners/paintball/headers/guerilla_air_header.jpg", + "description" : "Guerrilla Air is committed to design and develop products that prioritize performance and improve the thrill of the sport and the safety of players.\n\n\nTheir commitment runs deep, developing relationships with Distributors, Dealers and Players for the long-term. Gaining your trust to stay true to Air Guerrilla is what they strive for everyday.\n\n\nGuerrila Air works hard to ensure 100% satisfaction. They take great pride in everything they do to support those that are as Paintball passionate as they are. Always thinking outside the box to offer innovative products to take the sport of Paintball past where it stands today to make it more exciting for tomorrow.\n\n\nBottom line; they are players, they sponsor teams and support the continued growth of Paintball with innovation, quality and a personal approach to customer service.\n\n\nGuerrilla Air's passion for Paintball is never ending, as is our commitment to you.\n" + }, + ".markers.dangerous_power_paintball_guns.dangerous_power_espionage_e1_paintball_gun" : { + "meta_keywords" : "Dangerous Power E1,Dangerous Power Paintball,Dangerous Power Evolution,DP E1,E1 Paintball Gun,Dangerous Power E1 Paintball Marker,Dangerous Power Evolution Paintball Gun,", + "meta_description" : "Dangerous Power E1 - Get your E1 Paintball Gun now with Free Shipping @ ZephyrPaintball.com. Dangerous Power Evolution 1 Paintball Guns starting at 209.95! ", + "top_description2" : "The Dangerous Power E1 touches the fine points of Dangerous Power's accomplishments and performance. The Dangerous Power E1 features a micro-switch board capable of firing in Semi-auto mode & Full-auto fire modes capped at 25 bps. The dangerous power e1 has a high pressure regulator for a consistent shot. The dump valve bolt system on the dangerous power e1 for increased efficiency (more shots per tank). The Dangerous Power E1 features an autococker threaded barrel and a dm threaded feedneck. The E1 paintball gun reguires a compressed air tank for operation and is not compatible with Co2.\n", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.dangerous_power_paintball_packages/?sortby=zoovy:prod_name", + "description" : "=Dangerous Power E1 Features=\nThe entire operation system utilizes only 2 moving parts and six o-rings for maximum dependability and ease of maintenance / repair! (Fewer o-rings minimize 'bolt stick' due to less friction upon initial fire, and lessens the chance of first shot drop off)\n*Easy access to the bolt and assembly with provided tools. Only one screw to remove!\n*Signature Dangerous Power oversized grip frame enables user to purchase and customize grips.\n*Autococker threaded barrel.\n*Lightweight, 3-D milled body - entire marker, complete with ASA, feedneck, barrel and a 9V battery weighs in at only 1.9 pounds!\n*Low operating pressure (200psi) - ideal for even the most brittle tournament paint.\n*Built with an In-house custom designed solenoid, made to withstand extreme pressure for maximum reliability.\n*With the simple press of a button, you can toggle between: Semi-Auto, Full-Auto and Eyes On/Off modes on the E1.\n*9.5\" Single Barrel\n*Slide'n Lock Feedneck\n*Reinforced E1 Eye Cover\n*Reinforced Back Cap\n*Slim Profile Twist-Knob ASA\n*3-Point Trigger adjustment\n*Operating Pressure Regulator (OPR)\n*Dangerous Power E1 uses a DM Feedneck\n\n\n=Optimum Performance at a Lower Price=\nThe E1 touches the fine points of Dangerous Power's accomplishments and performance. The E1's strengthened core is constructed of our distinguished & popular \"Dump-Valve System\" & is equipped with a micro-switch board capable of firing in Semi-auto mode & Full-auto fire modes capped at 25 bps. \n=High Pressure Regulator=\nThe E1's high pressure regulator is composed of the G3's highly accurate OPR system & internals. The E1's OPR's operation is service-friendly & easy to maintain. \nDump Valve Bolt System\nThe E1's Dump Valve system is one of the finest and very efficient firing systems for Dangerous Power's spool valve markers. Maintenance for the fire assembly is simple & is constructed of 2 moving parts. The E1's fire assembly and operation proceeds from the G3's heritage, DP's greatest achievement. \n\n=Specifications=\n*Length: 15.38inches / 390.8mm\n*Height: 7.58inches / 192.5mm\n*Weight: 869g / 1.91lbs (w/ battery)\n*Operating Pressure: 200psi/280bps\n\n=Dangerous Power Warranty=\n\nTo the initial retail purchaser, to be free from defect in original materials and/or workmanship for twelve (12) months from the original date of purchase, with the following exceptions: \nDisposable parts (batteries, o-rings, seals, micro switch, air pressure hose, rubber and/or plastic material parts, etc.) are not included in this limited lifetime warranty.\nElectronic parts on this marker are fully warranted for 30 days from the original date of purchase.\nBolt and striker systems of this marker are fully warranted for 6 months from the original date of purchase.\nSurface damages (scratches and nicks) or operation failure due to accident, neglect, modification, normal wear, operator error, maintenance by anyone other than an authorized dealer or agent, misuse, improper disassembly and reassembly, are expressly not covered under this warranty.", + "htmlvids" : "\t\t

                                                                          \n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
                                                                          \n\t", + "head_title" : "Dangerous Power E1 | E1 Paintball Gun | Dangerous Power Evolution", + "page_title" : "Buy Dangerous Power E1 Online On Sale Now" + }, + ".barrels.barrels_by_manufacturer.eclipse_paintball_barrels" : { + "meta_keywords" : "eclipse paintball barrels, eclipse shaft, eclipse barrel kit, eclipse barrel backs, eclipse one piece shaft", + "meta_description" : "Eclipse Paintball Barrels - Buy your Eclipse Shaft Online at Zephyr Paintball for Less today. Free Shipping on Eclipse Barrel Kit Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Eclipse Paintball Barrels Online On Sale Now", + "head_title" : "Eclipse Paintball Barrels | Eclipse Shaft | Eclipse Barrel Kit" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray-ban_rb3362_cockpit_sunglasses" : { + "meta_description" : "Ray Ban Cockpit Sunglasses - Zephyr Sports carries a complete line of Cockpit Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Cockpit Sun Glasses Online Today.", + "page_title" : "Ray Ban Cockpit Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Cockpit Sunglasses | Cockpit Ray Ban Sunglasses | RayBan Cockpit Sun Glasses" + }, + ".casual_clothing.mens_clothing.tank_tops.nixon_tank_tops" : { + "meta_description" : "Nixon Tank Tops - Buy your Nixon Jersey Tank Tops At Zephyr Sports for Less Today! We carry a complete line of Nixon Mens Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Mens Jersey Tank Tops at Zephyr Sports", + "head_title" : "Nixon Tank Tops | Nixon Jersey Tank Tops | Nixon Mens Tank Tops" + }, + ".goggles.jt_usa_goggles" : { + "meta_keywords" : "JT Goggles Masks, JT Paintball Goggles, JT Paintball Mask, JT Goggles, JT Mask, Goggles Mask, Paintball Goggles, Paintball Mask, Paintball Equipment", + "meta_description" : "JT Goggles Masks - JT paintball goggles and masks are just some of the many paintball accessories available online at ZephyrPaintball.com.", + "zoovy:banner01" : "banners/paintball/headers/goggleaccessories_header001", + "banner01_link" : "/category/goggles.1goggle_accesories.jt_usa_goggle_accesories.jt_lenses/?sortby=zoovy:prod_name", + "description" : "", + "page_title" : "Buy JT Paintball Goggles Online On Sale Now", + "head_title" : "JT Paintball Goggles | Cheap JT Paintball Mask| JT Goggles Mask", + "sortby_var" : "JT Goggle Type", + "page_head" : "" + }, + ".markers.dangerous_power_paintball_guns.dangerous_power_g3_spec_r_paintball_guns" : { + "meta_keywords" : "Dangerous Power G3,G3 Spec-R Paintball Gun,Dangerous Power G3 Spec R,paintball gear,paintball,paintball guns,paintball marker,dangerous power paintball,dangerous power g3 paintball gun,", + "meta_description" : "All New Dangerous Power G3 Spec-R Paintball Gun - Dangerous Power has finally released the G3 Spec-R Paintball gun. Considered one of the smallest and lightest paintball markers in the industry. The G3 Spec-R is loaded with a host of features! Multiple tournament firing modes, fully programmable microswitch board, and an O-ring bolt design making high marker maintainence a thing of the past! \r Get in the game with Dangerous Power G3 Spec-R Paintball Guns.", + "top_description2" : "=Dangerous Power G3 Spec-R=\n\nAfter weeks of anticipation and assumptions, the all new Dangerous Power G3 Spec-R is ready to be released. We retained all the great aspects that made the G3 a paintball house hold name but listened to all the advice the fans gave.\nThe Dangerous Power G3 was one of the smallest and lightest markers in paintball, and the DP went ahead and made it even smaller and lighter. Weighing in at less that 1.8lbs,(barrel and battery included) that officially makes the G3 Spec-R the lightest paintball marker around. Even though smaller and lighter, the Spec-R does not sacrifice comfort or performance. Following the same \"dump valve\" design, the G3 Spec-R offers an o-ring-less bolt design that not only increases the efficiency but also the longevity of the o-rings, in addition, the G3 Spec-R comes stocked with a fully programmable micro-switch board that offers all the necessary tournament modes and ability to adjust multiple set points. Combine the board with our fully adjustable magnetic ball bearing trigger to get the G3 Spec-R ready for all players, at any level!", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "prodlist1_header" : "Dangerous Power G3 Spec-R Paintball Guns", + "banner01_link" : "/category/3packagespecials.dangerous_power_paintball_packages/?sortby=zoovy:prod_name ", + "htmlvids" : "", + "head_title" : "Dangerous Power G3 | G3 Spec-R Paintball Gun | Dangerous Power G3 Spec R", + "page_title" : "Buy Dangerous Power G3 Online On Sale Now" + }, + ".markers.tippmann.tippmann_packages.tippmann_a_5_packages" : { + "meta_keywords" : "tippmann a5 packages, tippmann a5 sniper packages, tippmann A5 kits, cheap tippmann packages, tippmann a-5 package, tippmann scenario package, tippmann packages", + "banner1" : "banners/a5_packs_header", + "meta_description" : "If you are looking for a Tippmann A-5 with the complete setup. Mask, Tank, Hopper & Harness - Zephyr has what you are looking for!", + "page_title" : "Buy Tippmann A5 Packages Online On Sale Now", + "head_title" : "Tippmann A5 Packages | Tippman A5 Sniper Packages | Tippmann A 5 Kits" + }, + ".skateboard_gear.skateboard_wheels.globe_skateboard_wheels" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_vol_sunglasses" : { + "meta_description" : "Electric Vol Sunglasses - Zephyr Sports carries a complete line of Electric Vol Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Vol Online Today.", + "page_title" : "Electric Vol Sunglasses On Sale Free Shipping", + "head_title" : "Electric Vol Sunglasses | Electric Vol Sun Glasses | Sunglasses Electric Vol" + }, + ".harnessesbags.packs___harnesses.proto_pod_packs" : { + "meta_keywords" : "proto harness, proto paintball harness, proto pack, proto pod harness, proto pod pack, proto fighter harness, proto fighter, proto paintball pod harness", + "banner1" : "", + "meta_description" : "Proto Paintball Harness - Zephyr carries a complete line of proto pod pack including the new Proto fighter harness. Proto is known for high quality stylish paintball gear at an affordable price", + "page_title" : "Buy Proto Paintball Harness Online On Sale Now", + "head_title" : "Proto Paintball Harness | Proto Pod Pack | Proto Paintball Pack" + }, + ".shop_by_brand.ninja_paintball" : { + "meta_description" : "Ninja Paintball - Buy your Ninja Air Tanks At Zephyr Sports for Less Today! We carry a complete line of Ninja Remote at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=Ninja Paintball Proudly Made in The USA=\n\nAt the heart of every good Paintball Marker is one thing. It's not a barrel. It's not a trigger system, and it's not a hopper. It's Ninja paintball and more specifically Ninja Air tanks. Ninja compressed air products are the hottest stuff paintball has seen in a while, and it will make your gun shoot harder, faster and more reliably. Hook a Ninja tank to a Ninja remote and you will be rock'n the field in no time. Get your Ninja system and show your buds who's serious about Paintball. \n", + "top_description" : "", + "page_title" : "Buy Ninja Paintball On Sale & Free Shipping", + "head_title" : "Ninja Paintball | Ninja Air Tanks | Ninja Remote", + "zoovy:banner01" : "", + "description" : "=Ninja, the right kind of Air=\n\n==Ninja's commitment==\nNinja has committed to paintball harder than most couples commit to marriage. They create the finest product to make sure you are getting ample compression with each shot. Ninja strives to create the best, lightest and most efficient products the Paintball market has ever seen.\n\n\n==Air Systems==\nMost Ninja systems come standard with \n\n* SRT piston –Sonic Recharge Technology piston – plated aluminum piston that produces an industry leading recharge rate and virtually eliminates reg shoot down.\n\n* SPA – Shim Pressure Adjustment- change output pressure by adding or removing shims, not springs or pistons.\n\n* MFV – Mini Fill Valve – Non wrist digging, low profile design fill valve\n\n* And all are completely capable of being rebuilt by the end user.\n\n==Ninja Remotes==\n These coils are Extremely flexible, Designed by paintball players, have an Aluminum NINJA slide check, Are Fully assembled and ready to go, have 3000 psi working pressure coiled hose and Will work with any paintball Air system or CO2 bottle.\n\n\n\n\n" + }, + ".casual_clothing.mens_clothing.shoes.converse_skate_shoes" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.sony_piiq_headphones" : { + "meta_keywords" : "Sony PIIQ Headphones,Sony PIIQ Head Phones, Sony PIIQ Audio", + "meta_description" : "Sony PIIQ Headphones - Zephyr stock a complete line of Sony PIIQ Head Phones. For the ultimate Audio experience buy your Sony PIIQ at Zephyr Today", + "page_title" : "Sony PIIQ Headphones with Free Shipping at Zephyr", + "head_title" : "Sony PIIQ Headphones | Sony PIIQ Head Phones" + }, + ".shop_by_brand.aps_airsoft" : {}, + ".airsoft.airsoft_apparel.camoflouge_pants" : {}, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests.maddog_tactical_vests" : {}, + ".apparel.jerseys.planet_eclipse_paintball_jerseys" : { + "meta_keywords" : "Discount Planet Eclipse Paintball Jersey, Cheap Planet Eclipse Paintball Jerseys, Planet Eclipse Paint Ball Jerseys, Planet Eclipse, Planet Eclipse Paintball Jersey, Discount Paintball Jerseys, Cheap Paintball Jerseys, Planet Eclipse Paintball Equipment, Planet Eclipse Paintball Supplies", + "meta_description" : "Discount Planet Eclipse Paintball Jersey - Shop for cheap Planet Eclipse paintball jerseys online at ZephyrPaintball.com, the best site for low priced paintball equipment and supplies.", + "description2" : "\n\n\n\n\n ", + "banner1" : "", + "page_title" : "Planet Eclipse Distortion and Elusion Jerseys", + "head_title" : "Discount Planet Eclipse Paintball Jersey | Cheap Planet Eclipse Paintball Jerseys | Planet Eclipse Paint Ball Jerseys", + "page_head" : "", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".dye_rotor_paintball_loader.dye_rotor_quick_feeds" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.full_clip_holsters" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markerupgrades.smartparts.sp1_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "add2_link" : "/category/markerupgrades.feednecks.nxt_feednecks/", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".0001a_christmas_sale.0010" : { + "banner1" : "banners/holiday/holiday_specials_btn_10_003", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=30&SHOWSKU=&" + }, + ".airsoft.airsoft_guns.tokyo_marui_airsoft_guns" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "description" : "" + }, + ".casual_clothing.mens_clothing.sweatshirts.electric_sweatshirts" : { + "meta_description" : "Electric Sweatshirts - Buy your Electric Hoodies At Zephyr Sports for Less Today! We carry a complete line of Electric Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Electric Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Electric Sweatshirts | Electric Hoodies | Electric Hoody" + }, + ".airsoft.airsoft_apparel.camoflouge_t_shirts" : {}, + ".casual_clothing.mens_clothing.sweatshirts.plan_b_sweatshirts" : { + "meta_description" : "Plan B Sweatshirts - Buy your Plan B Hoodies At Zephyr Sports for Less Today! We carry a complete line of Plan B Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Plan B Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Plan B Sweatshirts | Plan B Hoodies | Plan B Hoody" + }, + ".casual_clothing.mens_clothing.tshirts.anti_hero_t-shirts" : { + "meta_keywords" : "Anti Hero T Shirts,Anti Hero shirts,free shipping,Anti Hero TShirt", + "meta_description" : "Anti Hero T Shirts - Zephyr carries a complete line of Anti Hero Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Anti Hero T Shirts at Zephyr", + "head_title" : "Anti Hero T Shirts | Anti Hero Shirts | AntiHero TShirt" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_loaders" : {}, + ".casual_clothing.mens_clothing.shoes.etnies_shoes" : { + "meta_description" : "Etnies Shoes - Buy your Etnies Mens Shoes At Zephyr Sports for Less Today! We carry a complete line of Etnies Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Etnies Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Etnies Shoes | Etnies Mens Shoes | Etnies Skate Shoes" + }, + ".casual_clothing.mens_clothing.sandals.globe_sandals" : {}, + ".airsoft.airsoft_gun_magazines.spring_pistol_magazines" : {}, + ".2clearance.paintball_clearance_gear.clearance_barrels" : { + "head_title" : "Sale Paintball Barrels | Clearance Paintball Barrels | Paintball Barrels Sale" + }, + ".casual_clothing.mens_clothing.socks.element_socks" : { + "meta_keywords" : "Element socks,Element mens socks,Element men socks", + "meta_description" : "Element Socks - Zephyr stocks a complete line of Element Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Element needs. ", + "page_title" : "Element Socks on Sale at Zephyr", + "head_title" : "Element Socks | Element Mens Socks" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_kids_hydration_packs.camelbak_mini-mule_hydration_packs" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_re-run_watches" : { + "meta_keywords" : "Nixon watches,Nixon re-run watch,nixon watch,nixon re-run,nixon re run watch,re-run watches,re run watch,mens watches,mens watch,nixon,", + "meta_description" : "Nixon Watches - Brand new Nixon Re-Run Watch Available now @ Zephyr! Nixon Re-Run Watches are full of a host of cool features. Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Re-Run Watches", + "head_title" : "Nixon Re-Run Watches | Nixon Re-Run Watch | Nixon Re-Run" + }, + ".loaders.tippmann_paintball_hoppers" : { + "meta_description" : "Tippmann Paintball Loaders - Buy your Tippmann Al 200 Online at Zephyr Paintball for Less today. Free Shipping on Sl 200 Paintball Loader Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann Paintball Loaders Online On Sale Now", + "head_title" : "Tippmann Paintball Loaders | Tippmann Al 200 | Sl 200 Paintball Loader" + }, + ".casual_clothing.mens_clothing.tank_tops" : { + "meta_description" : "Mens Tank Tops - Buy your Mens Jerseys At Zephyr Sports for Less Today! We carry a complete line of Mens Jersey Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Mens Tank Tops @Zephyrsports.com", + "head_title" : "Mens Tank Tops | Mens Jerseys | Mens Jersey Tank Tops" + }, + ".markerupgrades.smartparts.smart_parts_nerve_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "add2_link" : "/category/markerupgrades.feednecks.impulse_ion_sft_feednecks/", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".markerupgrades.rampingchipsboards.tadao_paintball_upgrade_boards" : { + "meta_description" : "Tadao Boards - Buy your Tadao Board Paintball Online at Zephyr Paintball for Less today. Free Shipping on Tadao Paintball Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tadao Boards Online On Sale Now", + "head_title" : "Tadao Boards | Tadao Board Paintball | Tadao Paintball Boards" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_bugeye_backpacks" : { + "meta_description" : "Oakley Bugeye Backpacks - Buy your Oakley Bugeye At Zephyr Sports for Less Today! We carry a complete line of Oakley Bugey Backpack at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Bugeye Backpacks On Sale & Free Shipping", + "head_title" : "Oakley Bugeye Backpacks | Oakley Bugeye | Oakley Bugey Backpack" + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones.neff_headphones" : { + "meta_description" : "Neff Headphones - Buy your Neff Head PhonesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Neff Headphones Low Prices Free Shipping", + "head_title" : "Neff Headphones | Neff Head Phones" + }, + ".markers.btdesignspaintballguns.bt_tm_15_paintball_guns" : { + "meta_keywords" : "BT TM-15 Paintball Gun,BT TM 15 Paintball Marker,BT TM-15,BT paintball gear,paintball guns,BT Paintball Markers,BT Paintball Guns", + "htmlvids" : "", + "meta_description" : "BT TM-15 Paintball Gun - Free Shipping on all BT TM 15 Paintball Markers. The BT TM-15 is ultimate choice for any woodsball or mil-sim paintball player. Loads of BT paintball gear to upgrade and customize your BT Paintball Marker. Get in the game today with BT Paintball Guns!", + "top_description" : "The BT TM-15 Paintball Gun is the ultimate choice for any woodsball or mil-sim paintball enthusiast. Its high performance magnesium body is ultra strong, yet light enough for all-day action. Equipped with features usually found on much more expensive markers, the BT TM15 features a true electropneumatic operating system as well as reduced sound signature for stealth firing in any of the multiple firing modes. The BT Tm-15 comes standard with multiple Picatinny rails to make accessory options nearly endless. The Tm-15 has an internal airline operation similiar to the mini to eliminates external hoses. Plus, front and rear sights ensure you get your shot. ", + "page_title" : "Buy BT TM-15 Paintball Gun Online On Sale Now", + "head_title" : "BT TM-15 Paintball Gun | BT TM 15 Paintball Marker | BT Paintball Guns", + "description" : "=BT TM-15 Features:=\n\n* High Performance, Ultra Strong, Lightweight Magnesium Body.\n* Bolt Out Back Design for Easy Cleaning and Maintenance.\n* Modern Styling.\n* True Electropneumatic Operating System.\n* Shift-On-The-Fly, 4-Position Recreational Firing Mode Switch.\n* Multiple Firing Modes: Semi/PSP/NXL/Millennium.\n* Stealth Body Design Works in Conjunction with the Barrel to Reduce Sound Signature.\n* 14 Barrel with Sound Signature Reduction Porting.\n* Flip-Up Front and Rear Sights.\n* Clamping Feed Elbow.\n* Universal, Mini Style Barrel Threads.\n* Single-Finger Trigger (Double Trigger Kit Available).\n* Multiple Picatinny Rails Allow for Extra Accessories.\n* Quick-Change Battery in the Removable Magazine.\n* Collapsible/Adjustable Rear Stock.\n* Low Pressure Operation (200psi).\n* No External Hoses; Internal Airline Operation.\n" + }, + ".safetygear.kneeelbowpads.vents_knee___elbow_pads" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_running_hydration_packs" : { + "meta_description" : "Camelbak Kids Packs - Buy your Kids CamelbaksAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Kids Packs On Sale & Free Shipping", + "head_title" : "Camelbak Kids Packs | Kids Camelbaks" + }, + ".misc_items.tournament_accesories" : {}, + ".casual_clothing.mens_clothing.hats.dye_hats" : { + "meta_keywords" : "Dye Hats,Dye caps,Dye baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Dye Hats - Zephyr carries a complete line of Dye Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Dye", + "page_title" : "Dye Hats on Sale at Zephyr", + "head_title" : "Dye Hats | Dye Caps | Dye Baseball Hats" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.empire_event_paintball_masks" : {}, + ".markerupgrades.tippmann.a5.tippmann_a_5_factory_repair_parts" : { + "top_html_focus" : "\"Tippmann\n" + }, + ".barrels.freakbarrels.freakbarrelfronts" : {}, + ".1-product_reviews" : { + "dynimage1" : "images=banners/airsoft/slideshow/review_contest_slideshow_v2.jpg\nlinks=\npauses=100\nblank_behavior=none\n", + "top_html" : "Zephyr Sports is giving away a King Arms Magpul M4 on 11/15/11. To enter you need to review any product on our websites; Zephyr Sports, Zephyr Airsoft, or Zephyr Paintball. The more reviews you write, the better chance you have to win. All reviews must be at least 100 words long and informative. You should own or have used the product you are reviewing. A sample product review and further instructions for entering the contest are below. Your review does not have to be positive as long as it is informative. If you don't like a products, let us know the reasons why. One winner will be chosen with the best review (good or bad) by the zephyr staff. If you are under 18, you will need your parents approval prior to receiving your prize.", + "htmlvids" : "", + "top_description" : "Congratulations to our 11/15/11 review contest winner Cameron R. who won a King Arms Magpul MOE M4 (yes, delicious)!!! He did a great job with reviewing countless products with very knowledgeable info and we look forward to running many more contests like this in the future! Thank you to everyone who put forth an effort, and keep your eyes peeled for more contests like this." + }, + ".dye_i4_paintball_goggle_mask.paintball_blog.dye_ultralite_barrel_system" : {}, + ".casual_clothing.mens_clothing.sweatshirts.dgk_sweatshirts" : { + "meta_description" : "DGK Sweatshirts - Buy your DGK Hoodies At Zephyr Sports for Less Today! We carry a complete line of DGK Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DGK Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "DGK Sweatshirts | DGK Hoodies | DGK Hoody" + }, + "$bb_s" : {}, + ".scenarioupgrades.binoculars_and_spotting_scopes" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.31" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_vests___belts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsoft.slingshots" : { + "meta_keywords" : "wrist slingshot,slingshots,slingshot ammo,slingshot bands,crosman,daisy,marksman,hunting slingshots,trumark,", + "meta_description" : "Zephyr Sports now carries everything Slingshot! Wrist Slingshots, Hunting Slingshots, slingshot ammo, replacement slingshot bands, and more! Slingshots by top brands like Marksman, Daisy, Trumark, and Crosman! ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.1_oakley_womens_polarized_sunglasses" : { + "meta_description" : "Oakley Womens Polarized Sunglasses - Zephyr Sports carries a complete line of Womens Polarized Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Polarized Womens Sun Glasses Online Today.", + "page_title" : "Oakley Womens Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Oakley Womens Polarized Sunglasses | Womens Polarized Oakley Sunglasses | Oakley Polarized Womens Sun Glasses" + }, + ".markerupgrades.tippmann.a5.scenarioupgrades.a_5_sight_rails" : {}, + ".casual_clothing.mens_clothing.shorts.quicksilver_shorts" : { + "meta_description" : "Quicksilver Board Shorts - Buy your Quicksilver Shorts At Zephyr Sports for Less Today! We carry a complete line of Quicksilver Boardshorts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Quicksilver Boardshorts Ship Free at Zephyr Sports", + "head_title" : "Quicksilver Board Shorts | Quicksilver Shorts | Quicksilver Boardshorts" + }, + ".casual_clothing.mens_clothing.tank_tops.hk_army_tank_tops" : { + "meta_description" : "HK Army Tank Tops - Buy your HK Army Jersey Tank Tops At Zephyr Sports for Less Today! We carry a complete line of HK Army Mens Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "HK Army Mens Jersey Tank Tops at Zephyr Sports", + "head_title" : "HK Army Tank Tops | HK Army Jersey Tank Tops | HK Army Mens Tank Tops" + }, + ".barrels.freakbarrels.freakbarrelbacks" : {}, + ".zephyr.zephyr_day_paintball_event" : { + "btn_title" : "Buy Tickets Online", + "htmlvids" : "", + "top_description" : "Play paintball All Day with the Zephyr Staff For CHEAP! Discounted entry includes Pizza and Soda Lunch as well as a raffle ticket for a chance to win a BRAND NEW Proto Rail w/ Dye Rotor Hopper Combo! Buy Tickets Now! Rentals Available! Discounted Paint Available for Preorder. Gear Up w/ Zephyr!" + }, + ".airsystems.nitrogentanks.tippmann_compressed_air_tanks" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_fixed_power_scopes.nc_star_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".harnessesbags.backpacks.element_backpacks" : { + "meta_keywords" : "element skateboard,element backpack,element bag,element backpacks,element bags,element online,element mohave backpack,element stuff,dakine element backpack,element messenger bag,element back pack,element skateboard backpack\r ", + "meta_description" : "Element Backpacks - Zephyr Sports carries the largest selection of backpacks, duffle bags, messenger bags, laptop cases and more including the full line of Element Bags. Low Prices Free Shipping over $50 and hassle free returns. Buy your Element backpack today.", + "page_title" : "Element Backpack On Sale & Free Shipping", + "head_title" : "Element Backpack | Element Bags | Element Backpacks" + }, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories.condor_tactical_molle_accessories" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.lakai_beanies" : { + "meta_keywords" : "Lakai beanie,Lakai hat,Lakai beanies,Lakai caps,Lakai 686,Lakai headwear,Lakai cuff visor beanie,Lakai beanie hat,Lakai visor beanie,Lakai visor beanies", + "meta_description" : "Lakai Deanie - Surf style with Lakai Beanies available now at Zephyr Sports. Get your Lakai hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Lakai Beanies on Sale at Zephyr Today", + "head_title" : "Lakai Beanie | Lakai Hat | Lakai Beanies" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.spitfire_youth_t_shirts" : {}, + ".casual_clothing.mens_clothing.shorts.north_face_shorts" : { + "meta_description" : "North Face Shorts - Zephyr stocks a complete line of North Face Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your North Face needs. ", + "page_title" : "North Face Shorts with Free Shipping at Zephyr", + "head_title" : "North Face Shorts | North Face Board Shorts" + }, + ".markers.smartparts.smart_parts_sp1_paintball_guns" : {}, + ".casual_clothing.mens_clothing.sandals.etnies_sandals" : { + "meta_description" : "Etnies Sandals - Buy your Mens Etnies Sandals At Zephyr Sports for Less Today! We carry a complete line of Etnies Flip Flops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Etnies Sandals On Sale at Zephyr Sports", + "head_title" : "Etnies Sandals | Mens Etnies Sandals | Etnies Flip Flops" + }, + ".2clearance.mens_clothing.sweatshirts" : { + "head_title" : "Sale Sweatshirts | Clearance Sweatshirts" + }, + ".markerupgrades.us_army_upgrades.front_grips" : {}, + ".casual_clothing.womens_clothing.ladies_purses_and_bags.oakley_ladies_purses_and_bags" : {}, + ".casual_clothing.mens_clothing.wallets.krooked_wallets" : { + "meta_description" : "Krooked Wallets - Buy your Krooked Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Krooked Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Krooked Wallets on Sale @ Zephyr Sports", + "head_title" : "Krooked Wallets | Krooked Mens Wallets | Krooked Wallet" + }, + ".casual_clothing.mens_clothing.watches.g_shock_watches" : {}, + ".paintball.paintball_guns.kingman_spyder_paintball_guns.spyder_fenix_paintball_guns" : {}, + ".casual_clothing.mens_clothing.hats" : { + "meta_description" : "Mens Hats - Buy your Skate Caps At Zephyr Sports for Less Today! We carry a complete line of Baseball Hats at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Mens Hats On Sale & Free Shipping", + "head_title" : "Mens Hats | Skate Caps | Baseball Hats" + }, + ".shop_by_brand.matix_clothing" : { + "top_description2" : "=Matix, by skateboarders, for skateboarders=\n\nMatix Apparel was founded by pro skateboarders Daewon Song and Tim Gavin, tired of clothes disintegrating upon contact with concrete. Since 1998, all\nMatix clothes are designed and constructed for durability. Never ones to be closed-minded, Matix has also naturally embraced the likes of surf and snow talent as family members equally dedicated to the cause of progress. With this in mind, Matix Apparel team members like Marc Johnson, Daewon Song, and Gabe Kling all actively inspire the Matix styling. Marc Sweaters tested the bounds of color theory, Ashers redefined fleece construction, and Matix denim maintains the roots of quality and the integrity. \n", + "head_title" : "Matix Apparel | Matix Clothes | Matix Apparel", + "description" : "=Matix, by skateboarders, for skateboarders=\n\n==History==\nMatix has been around for over ten years now and they are still doing just fine. Their clothing was inspired by the skaters need to have durable, concrete resistant clothing. So a couple of pros, Daewon Song and Tim Gavin, got together and made a company dedicated to keeping skateboarders from having to buy multiple pairs of pants every week. Matix was born, and they are better than ever. \n\n==Product==\nMatix clothing is the most durable and most stylish clothing you will ever wear. Try Matix and you will never go back to the shredded flimsy clothes of yesterday. Matix takes pride in design to whole new level. They're fresh graphics and colors wont have you bored either. \n\n==Environmental==\nMatix believes in taking care of the earth we use to shred, so they constantly sponsor trash clean ups and they even include a trash bag in their board shorts just in case you want to take initiative. \n" + }, + ".harnessesbags.paintball_gear_bags.virtue_gear_bags" : { + "meta_description" : "Virtue Paintball Gear Bags - Buy your Virtue Backpacks Online at Zephyr Paintball for Less today. Free Shipping on Virtue Bags Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Virtue Paintball Gear Bags Online On Sale Now", + "head_title" : "Virtue Paintball Gear Bags | Virtue Backpacks | Virtue Bags" + }, + ".markers.smartparts.epiphany_paintball_guns" : {}, + ".loaders.hopper_accesories.hk_army_loader_accessories" : { + "meta_keywords" : "speedfeed, speed feed, hk army speed feed, rotor speed feed, paintball speed feed, hk army paintball, hk epic speedfeed, hk army, hk", + "meta_description" : "The HK Epic Speedfeed gives you a faster reloading time with less paint spilled on the field!", + "top_description" : "==HK ARMY EPIC Speed Feeds==\n\nThe Epic Speed Feed has been engineered to deliver what many have tried but have continuously failed... the ability to have both fast fills and no spills! Utilizing precise measurements and advanced materials the Epic delivers the perfect blend for the player. Paint will easily load pod after pod while being resistant enough to keep the paint within the loader. Beyond the design of the feed system, the Epic is built using a shatter resistant thermoplastic resin, and it comes equipped with a removable rain lid. A true feed system that will work always and last forever.", + "page_title" : "Buy Exalt Epic Speed Feed Online Now", + "head_title" : "Exalt Speed Feed | Rotor Speed Feed | Paintball Speed Feed" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.neff_ladies_t_shirts" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.ak47_aeg_airsoft_magazines" : {}, + ".apparel.pants.planet_eclipse_paintball_pants" : { + "meta_keywords" : "Discount Planet Eclipse Paintball Jersey, Cheap Planet Eclipse Paintball Jerseys, Planet Eclipse Paint Ball Jerseys, Planet Eclipse, Planet Eclipse Paintball Pants, Discount Paintball Pants, Cheap Paintball Pants, Planet Eclipse Paintball Equipment, Planet Eclipse Paintball Supplies", + "banner1" : "", + "meta_description" : "Discount Planet Eclipse Paintball Pants - Shop for cheap Planet Eclipse paintball Pants online at ZephyrPaintball.com, the best site for low priced paintball equipment and supplies.", + "page_title" : "", + "head_title" : "Discount Planet Eclipse Paintball Jersey | Cheap Planet Eclipse Paintball Pants | Planet Eclipse Paint Ball Pants", + "page_head" : "Discount Planet Eclipse Paintball Pants - Cheap Planet Eclipse Paintball Pants - Planet Eclipse Paint Ball Pants" + }, + ".casual_clothing.mens_clothing.hats.metal_mulisha_hats" : { + "meta_keywords" : "Metal Mulisha Hats,Metal Mulisha caps,Metal Mulisha baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Metal Mulisha Hats - Zephyr carries a complete line of Metal Mulisha Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Metal Mulisha", + "page_title" : "Metal Mulisha Hats on Sale at Zephyr", + "head_title" : "Metal Mulisha Hats | Metal Mulisha Caps | Metal Mulisha Baseball Hats" + }, + ".skateboard_gear.complete_skateboards.1_complete_skateboards_by_size_" : { + "meta_description" : "Search Complete Skateboards by Size - Buy your At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Search Complete Skateboards by Size at Zephyr", + "head_title" : "Search Complete Skateboards by Size" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.fly_girls.fly_girls_beverly_fly" : { + "meta_keywords" : "Fly Girls Sunglasses,women's sunglasses, womens sunglasses,Beverly Fly sunglasses", + "meta_description" : "Fly Girls Beverly Sunglasses now available @ Zephyr! Be the next Fly Girl to rock a pair of Black Flys womens sunglasses! Select Styles of these women's sunglasses by fly girl available in multiple colors!", + "page_title" : "Fly Girls Beverly Fly Sunglasses On Sale & Free Shipping", + "head_title" : "Fly Girls Beverly Fly Sunglasses | Flygirls Sunglasses | Fly Girls Eyewear" + }, + ".airsoft.airsoft_guns" : { + "meta_keywords" : "airsoft guns, airsoft gun, air soft guns, cheap airsoft gun for sale, airsoft guns for sale,airsoftguns", + "meta_description" : "Airsoft Guns - Zephyr Sports carries a complete line of Airsoft guns for sale at the lowest prices on the web. Free shipping. Shop All Brands and Types of Airsoft Gun and Supplies. Cheapest AirsoftGuns Online, highest quality around.\r ", + "description" : "All Airsoft replica BB guns include a safety orange muzzle tip in accordance with Federal law. Any attempt to remove the orange tip is a violation of Federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/Country and local jurisdiction. We are not repsonsible for items confiscated in customs. You Must be 18 to Purchase Airsoft items.", + "top_html_focus" : "
                                                                          \n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                          \n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n
                                                                          \n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n
                                                                          \n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n
                                                                          ", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Guns | AirsoftGuns for Sale | Airsoft Rifles Gun", + "sortby_var" : "Airsoft Gun Type" + }, + ".return_request.conditions_of_purchase" : { + "description" : "Return Policy & Procedure
                                                                          \nWe offer a 30-Day Money Back Guarantee on all new and unused merchandise in its original packaging, (paintballs excluded).

                                                                          \nPlease Note:
                                                                          \n
                                                                            \n
                                                                          • All returns are subject to a 15% restocking fee
                                                                          • \n
                                                                          • Restocking fee may be waived if Store Credit is preferred
                                                                          • \n
                                                                          • Used products may not be returned. Use is defined as any attempt to open packaging, fire, install, wear or wash.
                                                                          • \n
                                                                          • If you were shipped the incorrect item or an item that differed from the invoice, please note this under the \"Reason for Return\" section of the RMA request form. This is so you receive the appropriate RMA number.
                                                                          • \n
                                                                          • All Manufactures provide at least a 90-day (some offer 1 year) full parts and labor warranty on guns.
                                                                          • \n
                                                                          • All purchasers of paintball markers must be 18 years of age. Purchasers agree to abide to all local laws and regulations in their area.
                                                                          • \n
                                                                          • Purchasers are responsible for all importation taxes and duties imposed.
                                                                          • \n
                                                                          • We will not accept exchanges / returns on defective merchandise, please contact the manufacturer.
                                                                          • \n
                                                                          • Shipping costs for returns are the responsibility of the purchaser. Shipping will be charged on returns that received free shipping. Shipping costs will not be refunded on returns or refused packages
                                                                          • \n
                                                                          • No returns accepted without RMA (Return Merchandise Authorization) number.
                                                                          • \n

                                                                          \nFeel free to contact our office at 877.814.4297 with any questions or concerns. Zephyr Sports will not be held responsible for any typographical errors made when filling out the RMA request Form. Paintball Guns are not toys and should be handled as such. Airsoft guns are required to have the tip (1/4 inch) of the barrel permanently colored in blaze orange or red.

                                                                          \nAll pricing is listed in U.S. Dollars (USD$)." + }, + ".markerupgrades.kingmanspyder.feednecks.spyder_feed_necks___holes" : {}, + ".casual_clothing.mens_clothing.jackets.1_search_by_size.5-xx-large" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_dirk_sunglasses" : { + "meta_description" : "Spy Optics Dirk Sunglasses - Zephyr Sports carries a complete line of Dirk Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Dirk Sun Glasses Online Today.", + "page_title" : "Spy Optics Dirk Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Dirk Sunglasses | Dirk Spy Sunglasses Free Shipping | Buy Spy Dirk Sun Glasses" + }, + ".buyers_guide.airsoft.airsoft_rifles" : { + "answer_01" : "Entry level AEGs are often referred to as Sportline models. These AEGs often have plastic bodies and pot metal or plastic gearboxes. The plastic models are fine for backyard shooting or other recreational activities but are not as reliable and will not last as long as an AEG with a metal gearbox. Many companies such as Classic Army, G&G, Echo1, and Kalashnikov have various beginner airsoft guns for a good price.", + "answer_03" : "Plastic gear boxes tend to wear down after multiple uses. The teeth of the gears will slowly chip away and break off. Jamming in a gun cannot often lead to the gears breaking as well. Having a metal gear box has many advantages. Though more expensive, they are very effective. They are more sophisticated and advanced than plastic gear boxes and use almost the same technology as used real firearms. Metal gears also give more realistic weight to the gun. Additionally, metal gearboxes are easier to repair and upgrade as most retailers sell the parts to the gearboxes.", + "html_01" : "

                                                                          FAQ (Frequently Asked Questions)

                                                                          \n\n\n\n\n\n\n\n\n\n\n
                                                                          Entry level airsoft electric gunsHigh end airsoft electric guns
                                                                          The difference between a plastic and metal gear boxHigh capacity magazines
                                                                          ", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002", + "question_02" : "High End AEGs", + "answer_04" : "All AEGS, entry level to high end, have what is called high capacity magazines. They can hold anywhere from 300-600 bbs depending on the gun. AEGs need high cap mags because of their ability to shoot hundreds of bbs per minute. It is an easy to use and innovative way to feed bbs into your airsoft gun. How do they work you ask? Under spring tension, bbs are fed from a storage well up a feed tube and into the airsoft gun. To properly load the magazine, open the bb well door on top of the magazine. Then using a funnel or carefully placed hand, fill the bb well all the way to the top. Be careful not to overfill the well or try to force the door closed as it may break. Locate the winding wheel on the bottom of the magazine and wind the ratchet wheel until you start to hear a 'double-click'. Once you insert the magazine into the AEG magazine well, you should hear the bbs charge into the gun's feed point. You are now ready to fire away! When shooting the gun, you must remember to constantly wind the wheel to keep a consistant feed from the magazine to the gun.", + "text_01" : "Looking for an airsoft rifle? Well you've come to the right place. We have a wide selection of rifles for those just getting into the sport and for those with years of experience. There is a lot that goes into choosing the right rifle for you and this article we will outline the differences. \n\n\nThere are three types of airsoft rifles: Spring rifles, electric rifles, commonly referred to as AEGs (Airsoft Electric Guns) and Gas Blow back rifles that operate off of gas pressure.\n\n\nSpring powered airsoft rifles are single shot guns that use energy stored in a spring to push the bb down the barrel of the rifle. You must cock the gun prior to each shot much like you would a real bolt-action rifle. This is done by pulling back the bolt, which in turn compresses the spring and readies the gun for firing. These guns do not use any batteries or gas and are incapable of going full or semi-automatic. Crosman carries a great line of beginner spring airsoft rifles.\n\n\nElectric airsoft guns (AEGs) usually use rechargeable batteries to drive an electric motor in order to fire a bb. They have the option to go semi and full auto. Electric rifles are the most popular and commonly used airsoft guns on the field. These guns often attain muzzle velocities between 150 and 650 feet per second (fps). Rate of fire (roF) depends on the gun itself but varies from 100 to 6000 rounds per minute.\n\n\nGas blow back rifles, or GBBRs, are airsoft rifles that operate similar to how airsoft gas pistols do. Utilizing compressed gases in the tank or magazine, this gas is released to fire the BB and cycle the rifle's action. These are the most realistic replicas in airsoft, operating and function almost exactly like their counterparts.", + "question_01" : "Entry Level AEGs", + "answer_02" : "Higher end AEGs include such brands as Echo 1, KWA, King Arms and Classic Army. The objective of these companies is to make the most realistic, durable, longest lasting guns on the market with the highest performance. With their latest innovations to sport of airsoft, such as blowback AEGs by G&G, they are sure to be around a long time. These guns are built with metal gear boxes and most often times, metal bodies. They are meant for long time use, but may need a bit more care than entry level plastic AEGs. Lubing the gun's internal parts after every couple uses is recommended for GBBRs, or firing in Semi auto to reset the gear boxes a couple times before storing an AEG.", + "question_03" : "What is the difference between a plastic gear box and a metal gear box?", + "title_01" : "Airsoft Rifles", + "question_04" : "High Capacity Magazines", + "return_link" : "/category/buyers_guide.airsoft/" + }, + ".airsoft.tactical_airsoft_gear.airsoft_tactical_belts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".safetygear.kneeelbowpads.valken_knee_and_elbow_pads" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.511_tactical_holsters" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_running_hydration_packs.camelbak_fairfax_hydration_packs" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_crankshaft_sunglasses" : {}, + ".backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_zoid_hydration_packs" : {}, + ".markers.inspire_bfg_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_tech_xl_sunglasses" : { + "meta_description" : "Electric Tech XL Sunglasses - Zephyr Sports carries a complete line of Electric Tech XL Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Tech XL Online Today.", + "page_title" : "Electric Tech XL Sunglasses On Sale Free Shipping", + "head_title" : "Electric Tech XL Sunglasses | Electric Tech XL Sun Glasses | Sunglasses Electric Tech XL" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_shaker_sunglasses" : { + "meta_description" : "Electric Shaker Sunglasses - Zephyr Sports carries a complete line of Electric Shaker Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Shaker Online Today.", + "page_title" : "Electric Shaker Sunglasses On Sale Free Shipping", + "head_title" : "Electric Shaker Sunglasses | Electric Shaker Sun Glasses | Sunglasses Electric Shaker" + }, + ".dye_rotor_paintball_loader.dye_rotor_replacement_parts" : {}, + ".paintballs.gi_milsim_paintballs" : {}, + ".casual_clothing.mens_clothing.sweatshirts.alpinestars_sweatshirts" : { + "meta_keywords" : "Alpinestars Sweatshirts,alpinestars Hoodies,zip hoodie, Alpine Stars Sweatshirt", + "meta_description" : "Alpinestars Sweatshirts - On sale now at Zephyr Sports. Get your Alpinestars Hoodies with Free Shipping and easy returns at Zephyr today", + "page_title" : "Alpinestars Sweatshirts & Hoodies Ship Free at Zephyr", + "head_title" : "Alpinestars Sweatshirts | Alpinestars Hoodies" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_papa_g_sunglasses" : { + "meta_keywords" : "Von Zipper Papa G sunglasses,VZ Papa G, Von Zipper polarized sunglasses,Von Zipper Papa G,VZ Papa G glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Papa G Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Papa G sunglasses now! For Von Zipper Papa G glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Papa G On Sale & Free Shipping", + "head_title" : "Von Zipper Papa G | Von Zipper Papa G Sunglasses | VonZipper Papa G Sunglasses" + }, + ".harnessesbags.tubes.allen_paintball_products" : {}, + ".casual_clothing.z_shoes_and_footwear.oakley_shoes" : {}, + ".casual_clothing.mens_clothing.sweatshirts.metal_mulisha_hoodies" : { + "meta_description" : "Metal Mulisha Sweatshirts - Buy your Metal Mulisha Hoodies At Zephyr Sports for Less Today! We carry a complete line of Metal Mulisha Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Metal Mulisha Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Metal Mulisha Sweatshirts | Metal Mulisha Hoodies | Metal Mulisha Hoody" + }, + ".casual_clothing.youth_clothing.youth_rash_guards.dakine_youth_rash_guards" : {}, + ".goggles.vents_paintball_goggles" : { + "meta_keywords" : "avatar goggles, vents paintball goggles, thermal paintball mask, cheap paintball mask, new paintball goggles", + "meta_description" : "Vents paintball Goggles - Huge selection of cheap paintball goggles in stock at Zephyr Paintball. Free shipping on avatar goggles on orders over $100 including paintballs.", + "page_title" : "Buy Vents Paintball Goggles Online On Sale Now", + "head_title" : "Vents Paintball Goggles | Avatar Goggles | Cheap Paintball Goggles" + }, + ".markerupgrades.proto_matrix_rail_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add2_link" : "/category/markerupgrades.feednecks.matrix_feeds/", + "buttonname_02" : "", + "banner4" : "", + "zoovy:banner01" : "banners/paintball/headers/autococker_threaded_barrels.jpg", + "buttonname_01" : "", + "banner01_link" : "/category/barrels.autococker/", + "banner3" : "zephyr_buttons/feedneck_btn001", + "add1_link" : "/category/barrels.autococker/" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_ysignature_series" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley signature series sunglasses,oakley signature series", + "meta_description" : "Oakley Signature Series Sunglasses Now Available @ Zephyr! Get your Polarized Oakley Signature Series Sunglasses now! Oakley Mens sunglasses available in select styles; Signature Series Sunglasses available with polarized lenses by Oakley! ", + "page_title" : "Oakley Signature Series Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Signature Series Sunglasses | Signature Series Oakley Sunglasses" + }, + ".apparel.shoes.element_skate_shoes" : {}, + ".apparel.shoes.dekline_mens_shoes" : {}, + ".markerupgrades.autococker.bolts" : {}, + ".testing_help_desk.shipping" : { + "hd_answer_four" : "When you shop with Zephyr Sports, you get great service and fast shipping. We know how anxious you are after you place an order and we will get your order out as soon possible. Approved orders placed by 2 p.m. pst Monday though Friday are shipped out the same day. (Orders placed over the weekend will ship the next business day) On rare occasions, weekend orders may not ship until Tuesday due to the large volume of orders. Weekends and holidays are not counted as shipping days by any of our carriers. If you need to have your order on a certain day, please choose the method that will have it arrive one day early. In the event that one or more of the items from your order is out of stock, you will be notified via telephone or email. You have 3 days from that point to contact us, or we will refund and remove the out of stock items, and ship the rest of the order.\n\n\n==Zephyr Free Shipping==\nZephyr Sports offers Free shipping to the continental United States on orders over $100. (P.O. Boxes addresses are excluded.) Items shipped using Free shipping will be shipped via Fedex or USPS at our choice and will include a tracking number. Shipping times will vary from 1 to 10 days depending on shipping method. Please upgrade to Fedex shipping if you require faster shipping. USPS order will receive a delivery confirmation number. This will only give you delivery confirmation and will not allow you to track your package along the way. USPS shipping does not include any insurance. We recommend you upgrade to Fedex shipping whenever possible. If you choose Free shipping, you cannot choose the shipping method.\n\n\n==FedEx Shipping==\nOur preferred method of shipping is Fedex. Fedex delivers Tues through Saturday. We ship Fedex Home Delivery, 3-day air, 2-day air and standard next day. Fedex will attempt to deliver three times. If you miss all three of these attempts, then Fedex will hold your package for seven days and also send you a postcard to inform you of its arrival. If you fail to collect this package within the set period then it will get returned to us. Zephyr Sports will hold your package for fifteen days. Please note that if this happens we will charge you for re-shipping. If you fail to collect your package within fifteen days, we will refund your account and withhold all shipping fees as well as a 15% restocking fee.\n\n\n==Insurance==\nIf no insurance is selected, Zephyr Sports will not be responsible for any damaged, lost or stolen merchandise (etc). If no insurance is selected FedEx packages will be shipped with only USD 100.00 insured.", + "hd_question_three" : "Does My Package Require a Signature?", + "hd_question_four" : "When Will My Order Ship?", + "hd_question_eight" : "", + "html" : "%HD_HTML%", + "hd_answer_three" : "Orders over $250 will require an adult to be present to sign for the package. If your order is less than $250 and there is a safe place to leave your package, the carrier may leave the package if no one is available at time of delivery. This decision is made by your local carrier and Zephyr Sports cannot be responsible for packages lost in transit. We will assist in filing a lost package claim with the carrier.", + "hd_question_two" : "How Much is Shipping?", + "hd_answer_two" : "==Domestic shipping==\nAfter you place your items in your shopping cart, all you need to do is enter you zip code in the shipping calculator on the shopping cart page to receive shipping quotes.\n\n\n==International Shipping==\nAfter you place your items in your shopping cart, international customers will have to enter their entire address in order to receive a shipping quote. Ebay will not allow us to ship internationally; To order internationally, please use our direct website or call our customer service department.", + "hd_question_six" : "Can I Track My Package?", + "hd_question_seven" : "Free Zephyr Shipping.", + "hd_question_five" : "Can I Pick Up My Order?", + "hd_topic_listing" : "» Does my shipping and billing addresses have to match?
                                                                          \n» How much is shipping?
                                                                          \n» Does my package require a signature?
                                                                          \n» When will my order ship?
                                                                          \n» Can I pick up my order?
                                                                          \n» Can I track my package?
                                                                          \n» Free Zephyr Shipping.
                                                                          \n» Holiday Shipping Deadlines
                                                                          ", + "hd_topic" : "Shipping", + "hd_question_one" : "Does My Shipping and Billing Addresses Have to Match?", + "hd_answer_five" : "This option is no longer available. If you live close by or are in the area feel free to stop by our storefront and do some shopping.\n\n\n2978 Seaborg Ave.\n\nVentura, CA., 93003", + "hd_btn" : "images/site_specific/backto_helpdesk", + "hd_answer_eight" : "", + "hd_link" : "/category/testing_help_desk ", + "hd_answer_one" : "For fraud protection purposes, we require that all address information must match what is on file with the credit card company. If you are shipping to an address other than your billing address, the shipping address must also be listed with your financial institution as an alternate shipping address. This can easily be done by calling the number on your statement or the back of your credit card. It only takes a few minutes and does not affect your billing information at all. If both addresses are on file with the credit card company, you still may be contacted to verify your address.\n\n\nIf this is the case, please give us a call at 877-814-4297 so that we can manually verify your addresses with the credit card company. If your financial institution cannot verify your address with us, you will be contacted via email or phone call. If we are unable to verify your address within 10 days, your order will be cancelled.", + "hd_answer_six" : "Yes you can. As long as you entered a valid e-mail address during checkout, you will receive an e-mail with tracking information. Please be sure to check your spam filter as these e-mails tend to get caught in these filters. You can also login to your [[account]:url=https://ssl.zoovy.com/zephyrsports/login.cgis] to track your package. Your login is your e-mail address and a password that you received when you placed your order. If you have forgotten your password, you will be able to retrieve your password from this screen also.", + "shipping_time_detials" : "images/site_specific/check_estimated_delivery_date_btn003.png", + "hd_answer_seven" : "When you place an order over $100 (excluding taxes) you can receive Free Zephyr Shipping or get Home Delivery for ONLY $3.00! No rebates, No hassles! Just place the items you wish to order in your shopping cart and type in your zip code and the shipping rates will pop up. Zephyr Free Shipping will be one of the options to choose from. FedEx Home Delivery only delivers to the United States. Home Delivery only delivers Tuesday through Saturday.\n\n\nApplies only to the contiguous 48 states\n\n\nApplies only to internet orders (Phone orders ship free for orders over $250)\n\n\nApplies only to orders placed directly through www.zephyrpaintball.com \n\n\nExcludes P.O. Boxes" + }, + ".airsoft.airsoft_batteries___chargers.lithium_ion_airsoft_batteries" : { + "meta_description" : "Lithium Ion Airsoft Batteries - Zephyr Sports carries a complete line of Lipo Airsoft Batteries with free shipping over $75. Get your Lithium Airsoft Batteries today.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "11.1 LIPO Airsoft Batteries |Lipo Airsoft Batteries 11.1 | 11.1 Lipo Upgrade Battery" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_loaders.dye_rotor_paintball_loader" : {}, + ".casual_clothing.z_shoes_and_footwear.i_path_shoes" : {}, + ".casual_clothing.womens_clothing.ladies_sandals.metal_mulisha_ladies_sandals" : {}, + ".casual_clothing.mens_clothing.hats.anti_hero_hats" : { + "meta_keywords" : "Anti Hero Hats,Anti Hero caps,Anti Hero baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Anti Hero Hats - Zephyr carries a complete line of Anti Hero Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Anti Hero", + "page_title" : "Anti Hero Hats on Sale at Zephyr", + "head_title" : "Anti Hero Hats | Anti Hero Caps | Anti Hero Baseball Hats" + }, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_sl94_paintball_guns" : { + "htmlvids" : "" + }, + ".shop_by_brand.maddog_sports" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tMADDOG SPORTS EQUIPMENT\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n" + }, + ".apparel.pants.valken_paintball_pants.valken_redemption_paintball_pants" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_player_watches" : { + "meta_keywords" : "Nixon Watches,nixon player watch,nixon watch,nixon player,player nixon watch,player watch,nixon,mens watch", + "meta_description" : "Nixon Watches - Brand New Nixon Player watch available now @ Zephyr! Nixon Player watches feature a host of high-end qualities. Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Player Watch", + "head_title" : "Nixon Player Watches | Nixon Player Watch | Nixon Player" + }, + ".casual_clothing.z-sunglasses.revo_sunglasses.revo_discern_sunglasses" : { + "meta_description" : "Revo Discern Sunglasses - Zephyr Sports carries a complete line of Discern Revo Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Revo Discern Sun Glasses Online Today.", + "page_title" : "Revo Discern Sunglasses On Sale Free Shipping", + "head_title" : "Revo Discern Sunglasses | Discern Revo Sunglasses Free Shipping | Buy Revo Discern Sun Glasses" + }, + ".casual_clothing.mens_clothing.hats.young___reckless" : { + "meta_description" : "Young & Reckless Hats - Buy your Young & Reckless Baseball Hats Online At Zephyr Sports for Less Today! We carry a complete line of Young & Reckless Caps at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Young & Reckless Hats @ Zephyr Sports", + "head_title" : "Young & Reckless Hats | Young & Reckless Baseball Hats | Young & Reckless Caps" + }, + ".casual_clothing.mens_clothing.shorts.o_neill_shorts" : { + "meta_description" : "O'Neill Board Shorts - Buy your O'Neill Shorts At Zephyr Sports for Less Today! We carry a complete line of O'Neill Boardshorts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "O'Neill Boardshorts Ship Free at Zephyr Sports", + "head_title" : "O'Neill Board Shorts | O'Neill Shorts | O'Neill Boardshorts" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_alpha_sunglasses" : { + "meta_description" : "Spy Optics Alpha Sunglasses - Zephyr Sports carries a complete line of Alpha Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Alpha Sun Glasses Online Today.", + "page_title" : "Spy Optics Alpha Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Alpha Sunglasses | Alpha Spy Sunglasses Free Shipping | Buy Spy Alpha Sun Glasses" + }, + ".barrels.autococker" : { + "meta_keywords" : "autococker paintball barrels, autococker threaded barrels, cocker barrels", + "meta_description" : "Autococker Paintball Barrels - Zephyr carries a complet line of Autococker threaded barrels, the most popular style in paintball. Used by top manufacturers including Dye, Proto, Eclipse, Bob Long and more", + "page_title" : "Buy Autococker Paintball Barrels Online On Sale Now", + "head_title" : "Autococker Paintball Barrels | Autococker Threaded Barrels | Cocker Paintballs Barrels", + "sortby_var" : "Autococker Barrel Type" + }, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_renegade_series_baseball_gloves" : { + "head_title" : "Rawlings Renegade Series Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".scenarioupgrades.slings" : {}, + ".backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_stoaway_hydration_packs_" : {}, + ".skateboard_gear.complete_skateboards.speed_demons_complete_skateboards" : { + "meta_keywords" : "Speed Demons Skateboard, Speed Demon Skateboards, Speed Demons skateboard\r ", + "meta_description" : "Speed Demons Skateboard - Be apart of Speed Demon Skateboards @ Zephyr Sports! Everything Speed Demons skateboard has to offer all @ Zephyr!\r ", + "page_title" : "Buy Speed Demon Skateboards On Sale & Free Shipping", + "head_title" : "Speed Demon Skateboards | Speed Demon Boards | Speed Demon Complete Skateboard" + }, + ".harnessesbags.packs___harnesses.tippmann_paintball_vests" : { + "meta_description" : "Tippmann Paintball Harnesses - Buy your Tippmann Paintball Vest Online at Zephyr Paintball for Less today. Free Shipping on Tippmann Pod Pack Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann Paintball Harnesses Online On Sale Now", + "head_title" : "Tippmann Paintball Harnesses | Tippmann Paintball Vest | Tippmann Pod Pack" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_dirty_mo_sunglasses" : { + "meta_keywords" : "spy dirty mo sunglasses,spy dirty mo,spy dirty mo polarized sunglasses,spy optic dirty mo,spy dirty mo glasses", + "meta_description" : "Spy Dirty Mo Sunglasses - Zephyr carries a complete line of Spy Optic Dirty Mo Sunglassess including the Spy Dirty Mo Polarized line of sunglasses. With Free shipping, a 30 day satisfaction guarantee and 1 year breakage protection, Zephyr Sports is your Spy Optics headquarter!", + "page_title" : "Buy Spy Dirty Mo Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Dirty Mo Sunglasses | Spy Optics Dirty Mo Sunglasses | Dirty Mo Spy Sunglasses" + }, + ".shop_by_brand.hater" : { + "top_html" : "\n\n\n\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tHATER PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tHATER CASUAL APPAREL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          ", + "meta_description" : "Hater Paintball - Buy your Haters T Shirts At Zephyr Sports for Less Today! We carry a complete line of Hater Clothing at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Hater Paintball On Sale & Free Shipping", + "head_title" : "Hater Paintball | Haters T Shirts | Hater Clothing" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.classic_army_airsoft_guns.classic_army_full_metal_aeg_airsoft_guns" : { + "meta_description" : "Classic Army Airsoft is one of the most respected manufactures of high-end airsoft products in the world. Their dedication to using only the best materials and quality machining have given them the reputation as a leading innovator in airsoft equipment. Their rifles are made with full metal bodies and are designed to a 1:1 scale. Classic Army is the first company in the airsoft industry to achieve the international safety certificate (CE) for airsoft products. Zephyr Sports carries a grip of Classic army airsoft pistols including AEG 's, spring powered, gas powered, and co2 powered airsoft guns! ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Classic Army- Classic Army Airsoft On Sale & Free Shipping", + "head_title" : "Classic Army- Classic Army Airsoft | Classic Army Airsoft Gun" + }, + ".zzz_affiliate_program" : { + "banner1" : "banners/09_headers/main_categories/affliate_program_001", + "description" : "=Affiliate Program=\nZephyrPaintball.com Affiliate Program provides paintball or extreme sports websites with the opportunity to earn money by turning their site visitors into ZephyrPaintball.com customers.\n\n\nWhen a visitor to your site clicks on a link that points to ZephyrPaintball.com a cookie with your unique tracking information is placed on their computer. Commission Junction is a respected industry leader that has a state of the art tracking system. 100% of your results are monitored. This information is accessible to you 24 hours a day through this trusted third party's web-site.\n\n\nThere is no fee to join our program or Commission Junction. Affiliate commission rates start at 5% and you can earn up to 10% depending on your monthly sales.\n\n\nClick Here To [[Sign Up]:popup=https://signup.cj.com/member/brandedPublisherSignUp.do?air_refmerchantid=2395586]" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_loaders.virtue_spire_paintball_loaders" : {}, + ".casual_clothing.mens_clothing.belts.oakley_belts" : { + "meta_keywords" : "Oakley Belts,Oakley Belt Buckle,Oakley Belts,Oakley webbed belt", + "meta_description" : "Oakley Belts - We carry the complete line of Oakley Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Oakley Belts on Sale Now!", + "head_title" : "Oakley Mens Belts | Aplinestars Belts" + }, + ".casual_clothing.mens_clothing.belts.krooked_belts" : { + "meta_keywords" : "Krooked Belts,Krooked Belt Buckle,Krooked Belts,Krooked webbed belt", + "meta_description" : "Krooked Belts - We carry the complete line of Krooked Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Krooked Belts on Sale Now!", + "head_title" : "Krooked Mens Belts | Aplinestars Belts" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_rifles" : { + "head_title" : "KWA Airsoft Rifles | HWA AEG Airsoft Guns" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.kwa_gas_airsoft_guns" : { + "meta_keywords" : "KWA Airsoft Guns,KWA Airsoft Pistols,kwa pistols,kwa gun,m9 airsoft gun,green gas pistol, blowback pistol,", + "meta_description" : "KWA Pistols - Zephyr carries a complete line of KWA Airsoft Guns including KWA Gas pistols. KWA Guns make a perfect sidearm for your next airsoft day on the field. With low prices and free shipping we won't be beat ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "KWA Pistols with Free Shipping", + "head_title" : "KWA Airsoft Guns | KWA Pistols | KWA Guns" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_dawn_patrol_sunglasses" : { + "meta_description" : "Maui Jim Dawn Patrol Sunglasses - Zephyr Sports carries a complete line of Maui Jim Dawn Patrol Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Dawn Patrol Online Today.", + "page_title" : "Maui Jim Dawn Patrol Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Dawn Patrol Sunglasses | Maui Jim Dawn Patrol Sun Glasses | Sunglasses Maui Jim Dawn Patrol" + }, + ".casual_clothing.mens_clothing.shorts.enjoi_shorts" : {}, + ".casual_clothing.womens_clothing.ladies_pants.ladies_oakley_pants" : {}, + ".scenarioupgrades.flashlights___laser_sights.walther" : {}, + ".markers.btdesignspaintballguns.bt_combat_paintball_guns" : { + "meta_keywords" : "bt4 paintball markers,bt4 paintball guns,bt4 combat sniper,bt4 custom,bt 4 combat paintball marker,bt4 combat marker,bt4 combat paintball gun,bt4 barrel,bt 4 combat paintball gun,bt4 paintball marker,tippmann bt4,bt combat marker,bt combat paintball gun,bt4 marker,bt4 combat paintball,bt4 gun,bt4 paintball gun,bt combat paintball,bt4 paintball,bt4 combat,bt slice,bt combat slice,bt combat paintball gun\r ", + "meta_description" : "BT Combat Paintball Guns - The BT combat and BT Slice are one of the most affordable entry level paintball guns on the market today. The BT4 Combat Paintball Marker is fully upgradeable and as reliable as you could ask for. Looking for a little more firepower? Check out the BT Combat ERC. Free Shipping on BT Combat from Zephyr Today", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.empire_paintball_packages.empire_bt.combat/", + "description" : "=BT Combat Features:=\n* Tournament legal external velocity adjuster.\n* Removable grip frame for quick and easy upgrades.\n* Easily accepts expansion chambers, vertical and horizontal bottle adapters.\n* Works with CO2 or Compressed air.\n* Stainless steel bottomline.\n* Impact resistant baked on coating.\n* Dual Picatinny mounting rails meet Military Standard 1913.\n* Modular trigger system.\n* 1 year full parts and labor warranty.\n* Slide-Away TM Feedport for easy cleaning, maintenance\n* Light weight balanced construction.\n* Adjustable vertical front grip.\n* Selecta-Barrel TM adapter allows use of multiple barrel threads.\n\n\n=BT Combat Paintball Gun Specs=\n* Caliber: .68\n* Action: Semi-Automatic\n* Powered: CO2 or Compressed Air(HP Output)\n* Cycle Rate: 13BPS\n* Main Body Material: Aluminium\n* Accuracy Range: 150+ft\n* Tippmann A5 Threaded stock barrel\n\n\nThe BT 4 Combat comes with a removable barrel system. This feature allows the user to select a barrel that is suitable for the playing conditions. Standard barrels are mirror honed with a step-bore and porting and stock length is 8 inches. \n\n\n=BT Slice Paintball Gun=\nThe BT Combat Slice has all of the great features of the standard BT combat paintball gun, but add the ability to complete field strip the marker with the use of only two pins. Maintenance on the BT Slice has never been easier. Be sure to watch the BT Slice video to see these features in action.\n\n\n=BT ERC Paintball Gun=\nThe BT ERC takes the stock BT combat marker and includes some of the most popular upgrades. The ERC includes the the BT electronic grip frame, BT Rip clip electronic loader and the BT Apex barrel. ", + "top_html_focus" : "", + "head_title" : "BT Combat Paintball Guns | BT Combat | BT Slice Paintball Gun", + "page_title" : "Buy BT Combat Paintball Guns Online On Sale Now", + "top_description3" : "The BT 4 Combat is the marker that started the BT4 Series. It's the perfect scenario or woodsball Paintball gun which allows you to build the perfect one-of-a-kind beast. Fully upgradeable, the BT Combat is the scenario marker by which others are judged. This reliable and accurate marker is the obvious choice for use in your scenario or woodsball event. The front grip is removable and the military standard dual Picatinny rails accept many tactical upgrades like optics and other accessories like the BT Flashsight. The trigger system can be enhanced with by installing the Double Trigger and Electronic Grip Frame to increase your rate of fire. Be sure to check out the new BT Slice for easy field stripping and maintenance. With available upgrades like the HALO powered Rip Clip and Apex Barrel system, the BT4 Combat is the core of our successful BT4 line of markers. If you are looking to customize your paintball gun, start with the BT4 Combat and open a world of realistically styled marker configurations. Step into Combat with BT Paintball. " + }, + ".airsoft.airsoft_guns.gameface_airsoft_guns" : { + "meta_description" : "Game Face Airsoft Guns - Buy your Gameface Airsoft At Zephyr Sports for Less Today! We carry a complete line of Crosman Gameface at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Game Face Airsoft Guns On Sale & Free Shipping", + "head_title" : "Game Face Airsoft Guns | Gameface Airsoft | Crosman Gameface", + "description" : "" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.camelbak_hawg_nv_hydration_packs" : {}, + ".markerupgrades.dye_dam_upgrades_and_accessories.dye_dam_foregrips_and_shrouds" : {}, + ".casual_clothing.z-sunglasses.metal_mulisha_sunglasses" : { + "meta_description" : "Metal Mulisha Sunglasses Metal Mulisha Eyewear - Zephyr Sports carries a complete line of Metal Mulisha Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Metal Mulisha Sunglasses Metal Mulisha Eyewear On Sale Free Shipping", + "head_title" : "Metal Mulisha Sunglasses Metal Mulisha Eyewear | Metal Mulisha Sun Glasses" + }, + ".casual_clothing.youth_clothing.youth_shorts" : {}, + ".safetygear.neck_protectors" : { + "meta_description" : "Paintball Neck protection is not just for rookies any more. Most of the tournament pros these days are wearing a neck protector from Dye, Planet Eclipse or Empire.", + "top_description" : "Paintball Neck protection is no longer just for the rookies! Current neck protectors are comfortable and actually look good. No more painful welts on the neck. Checkout what the pros are wearing from Dye and Eclipse.", + "page_title" : "Paintball Neck Protection", + "head_title" : "Paintball Neck Protector | Neck Protection" + }, + ".harnessesbags.backpacks.foundation_backpacks" : { + "meta_keywords" : "foundation skateboards,skateboards foundation,foundation backpack,foundation back packs,foundation backpacks,foundation small backpack,foundation clothing\n", + "page_title" : "Foundation Backpacks On Sale & Free Shipping", + "head_title" : "Foundation Backpacks | Foundation Back Packs | Foundation Bags" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_variable_power_scopes.nikon_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".safetygear.exalt" : { + "meta_keywords" : "tournament protection, exalt thrasher protection, form fit design, silicone weave", + "meta_description" : "The Exalt Thrasher elbow pads and slide shorts give you the protection for a professional level of play using tri-layer padding to soften impacts and a moisture wicking breathable material that keeps you dry and comfortable.", + "top_description" : "== Exalt Thrasher Elbow Pads & Slide Shorts ==", + "top_description3" : "The new Exalt Thrasher Slide Shorts and Elbow Pads give players the protection for a professional level of play while being super light and ultra comfortable.\n\n\n= Exalt Thrasher Features: =\n* Moisture wicking breathable material keep you dry and comfortable.\n* Tri-level padding softens impacts and may give you a few \"lucky\" bounces.\n* Compression fit design prevents lactic acid build up, increasing your endurance.\n* Silicone printed waist band keeps these in place while sliding.\n* Articulating hip profile design allows full protection when hip sliding while not restricting movement when running.\n* Silicone weave bicep cuff & thumb cuff keep the elbow pad in place.\n", + "page_title" : "Exalt Thrasher Elbow Pads & Slide Shorts", + "head_title" : "Exalt Thrasher Elbow Pads & Slide Shorts", + "zoovy:banner01" : "banners/paintball/slideshow/1_exalt_thrasher_pads_slideshow_template.jpg" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_zero_sunglasses" : { + "meta_keywords" : "Oakley Zero Sunglasses,Zero oakley sunglasses,oakley Zero, Zero polarized sunglasses", + "meta_description" : "Oakley Zero Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Zero and Polarized Oakley Zero Sunglasses on Sale! ", + "page_title" : "Oakley Zero Sunglasses with Free Shipping", + "head_title" : "Oakley Zero Sunglasses | Zero Oakley Sunglassses" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses" : { + "meta_keywords" : "Von Zipper sunglasses,VZ, Von Zipper polarized sunglasses,Von Zipper,VZ glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ sunglasses now! For all Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Sunglasses | VonZipper Sunglasses | VZ Sunglasses" + }, + ".skateboard_gear.complete_skateboards.1_complete_skateboards_by_size_.76__complete_skateboards" : {}, + ".dye_i4_paintball_goggle_mask.paintball_blog.dye_rotor_paintball_loader" : {}, + ".casual_clothing.z-sunglasses" : { + "meta_keywords" : "Sunglasses,mens sunglasses,polarized sunglasses,designer,rayban,eyewear,men's sunglasses,womens ,arnette,black flys,dragon sunglasses,oakley,ray ban,spy optics,von zipper,aviators sunglasses,Gatorz,smith optics,Hoven,Mui Jim", + "meta_description" : "Protect your Eyes w/Sunglasses @ Zephyr! We carry the best brands including RayBan,Revo,Hoven, Arnette, Black Flys, Dragon,Gatorz,Maui Jim,Smith Oakley, Smith, Spy Optics, Von Zipper, and More! Men's and Women's Sunglasses available!", + "page_title" : "Designer Sunglasses - Ship Free at Zephyr", + "head_title" : "Sunglasses | Mens Sunglasses | Polarized Sunglasses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_ten_mens_sunglasses" : { + "meta_keywords" : "Oakley Ten Sunglasses,Ten oakley sunglasses,oakley Ten, Ten polarized sunglasses", + "meta_description" : "Oakley Ten Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Ten and Polarized Oakley Ten Sunglasses on Sale! ", + "page_title" : "Oakley Ten Sunglasses with Free Shipping", + "head_title" : "Oakley Ten Sunglasses | Ten Oakley Sunglassses" + }, + ".markers.valken_paintball_guns.valken_sw-1_paintball_guns" : {}, + ".airsystems.nitrogentanks.zephyr_nitrogen_tanks." : {}, + ".casual_clothing.z_shoes_and_footwear.1shoe_accessories" : {}, + ".loaders.hopper_accesories.hopper_upgrade_boards" : {}, + ".misc_items.gun_maintenance_tools" : { + "meta_keywords" : "tech matt, paintball gun tools, paintball tech matt, paintball o-rings", + "page_title" : "", + "head_title" : "Tech Matt | Paintball Gun Tools | Paintball Tech Matt" + }, + ".casual_clothing.mens_clothing.boots.rothco_boots" : { + "meta_keywords" : "Rothco boots,Rothco boots,Rothco tactical boots,Rothco assault boot,Rothco sabot boot, Rothco Work boot,duty boot,leather boot,police boot,miltary boot", + "meta_description" : "Rothco Boots - Get you Mens Rothco Boots at Zephyr today. Free Shipping on all Rothco Tactical Boots. We support Active Duty Military and Police", + "page_title" : "Rothco Boots with Free Shipping at Zephyr", + "head_title" : "Rothco Boots | Rothco Mens Boots | Rothco Tactical Boot" + }, + ".markerupgrades.bob_long_upgrades.bob_long_trigger_upgrades" : { + "meta_description" : "Bob Long Trigger Upgrades - Buy your Marq Victory Triggers Online at Zephyr Paintball for Less today. Free Shipping on Intimidator Triggers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Bob Long Trigger Upgrades Online On Sale Now", + "head_title" : "Bob Long Trigger Upgrades | Marq Victory Triggers | Intimidator Triggers" + }, + ".apparel.pants.dyepants.dye_c13_paintball_pants" : { + "meta_description" : "Dye C13 Paintball Pants - Just released from Dye for 2013, the C13 pants are available in 7 colors with lots of new features. The Dye C13 Pants are li8ghter and more durable than ever before. Trust Dye for the best paintball pants on the market.", + "top_description" : "Dye C13 Paintball Pants have been released. Lots of new colors from the leader in tournament level paintball pants. The Dye C13 is lighter and built to last. Step up to the Cadillac of paintball pants with the New Dye Pants.", + "page_title" : "Dye C13 Paintball Pants Ship Free", + "head_title" : "Dye C13 Paintball Pants | Dye C13 Pants | 2013 Dye Paintball Pants", + "description" : "With double stitching and a mix of 400d and 200d nylon combine to make the new Bomb-Proof C13 Dye's most durable pant. With Dye's 100% 400d nylon knee you are guaranteed the most consistent weave and strength available. Dye's nylon blend has a higher durability rating than most Kevlar's out there. With Bomb-Proof Construction you can slide, dive, crawl, and roll with confidence. Dye's Old School Fit gear has been inspired by the previous generations of Core pants we have done. The culmination of 10 years of endless testing has allowed us to construct the most functional and advanced gear ever. A Hyper Flex harness stabilizing back yoke. This helps keep your harness right where you want it.\n\n\nThe all-new Dye C13 Pant is the result of close collaboration among pro athletes, material experts, and designers. Manufactured with features like Breathable Assembly, Pigsticker Protection, and Bombproof Construction. A Hyper-Flex harness-stabilizing back yoke, double stitched flex-paneled ballistic 400 D nylon knees, adjustable waist and cuffs, a reinforced saddle seat, and responsive air-foam padding in sensitive areas. Dye's Prevent Breathable Assembly method maximizes airflow throughout your playing gear, keeping air circulating to keep you cool. It is designed to disperse the heat away from all parts of your body. While the Breathable Assembly keeps you cool it also maintains a barrier between you and the elements.\n\n\n=Dye C13 Paintball Pants Features:=\n\n*Weight: 2.08 lbs\n*Industrial rivet button\n*Durable YKK zipper\n*Air foam crotch protection\n*Custom DYE 50/50 lycra-nylon crotch venting\n*Ballistic double stitched 400d & 200d knee protection\n*Adjustable waist with smaller hip buckle\n*Tournament air dry loop\n*Hyper flex yoke featuring dye's custom venting\n*Pigsticker 200d hip protection\n*Dual fuzzy stick pockets\n*Reinforced triple stitched saddle seat\n*Inside and Rear nylon Prevent venting to keep you cool\n*Adjustable drawstring ankle cuffs\n" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.36" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_service_backpacks" : { + "meta_description" : "Oakley Service Backpacks - Buy your Service Oakley PacksAt Zephyr Sports for Less Today! We carry a complete line of Oakley Service Bags at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Oakley Service Backpacks Ship Free @ Zephyr Sports ", + "head_title" : "Oakley Service Backpacks | Service Oakley Packs| Oakley Service Bags" + }, + ".casual_clothing.mens_clothing.tshirts.dickies_t-shirts" : { + "meta_keywords" : "Dickies T Shirts,Dickies shirts,free shipping,Dickies TShirt", + "meta_description" : "Dickies T Shirts - Zephyr carries a complete line of Dickies Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Dickies T Shirts at Zephyr", + "head_title" : "Dickies T Shirts | Dickies Shirts | Dickies TShirt" + }, + ".casual_clothing.z-sunglasses.gatorz_sunglasses" : { + "meta_keywords" : "gatorz,gatorz sunglasses,sunglasses gatorz,gatorz radiator,gatorz wraptor,gatorz radiator sunglasses,gatorz eyewear,gatorz glasses,gatorz lenses,gatorz sun glasses\r ", + "meta_description" : "Gatorz Sunglasses - Zephyr sports carries a complete line of Sunglasses Gatorz with Free shipping on all sunglasses. Get your Gatorz eyewear and other Designer Sunglasses for less from Zephyr Today.", + "page_title" : "Gatorz Sunglasses On Sale & Free Shipping", + "head_title" : "Gatorz Sunglasses | Sunglasses Gatorz | Gatorz Eyewear" + }, + ".casual_clothing.mens_clothing.socks.srh_socks" : { + "meta_keywords" : "SRH socks,SRH mens socks,SRH men socks", + "meta_description" : "SRH Socks - Zephyr stocks a complete line of SRH Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your SRH needs. ", + "page_title" : "SRH Socks on Sale at Zephyr", + "head_title" : "SRH Socks | SRH Mens Socks" + }, + ".casual_clothing.mens_clothing.tshirts" : { + "meta_description" : "Mens T Shirts - Buy your Tshirts At Zephyr Sports for Less Today! We carry a complete line of Surf & Skate T Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Mens T Shirts on Sale at Zephyr Sports", + "head_title" : "Mens T Shirts | Tshirts | Surf & Skate T Shirts" + }, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.condor_tactical_holsters" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_pants.dye_c13_paintball_pants" : {}, + ".2clearance.clearance_jerseys___apparel.clearance_headwear" : { + "head_title" : "Sale Paintball Headbands | Clearance Paintball Headbands | Paintball Headbands Sale" + }, + ".harnessesbags.paintball_gear_bags.proto_gear_bags___backpacks" : { + "meta_keywords" : "proto paintball bags, proto gear bags, proto paintball gear bags, paintball proto bags, proto bags, proto duffle bags, proto duffle, proto backpacks, proto paintball backpacks", + "meta_description" : "Proto Gear Bags - Buy your Proto Paintball Bags Online at Zephyr Paintball for Less today. Free Shipping on Paintball Proto Bags Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Proto Gear Bags Online On Sale Now", + "head_title" : "Proto Gear Bags | Proto Paintball Bags | Paintball Proto Bags" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb4148_caribbean_sunglasses" : { + "meta_description" : "Ray Ban Carribean Sunglasses - Zephyr Sports carries a complete line of Carribean Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Carribean Sun Glasses Online Today.", + "page_title" : "Ray Ban Carribean Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Carribean Sunglasses | Carribean Ray Ban Sunglasses | RayBan Carribean Sun Glasses" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_pants.eclipse" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_hardshell_backpacks" : {}, + ".casual_clothing.mens_clothing.wallets.fox_wallets" : { + "meta_description" : "Fox Wallets - Buy your Fox Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Fox Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Fox Wallets on Sale @ Zephyr Sports", + "head_title" : "Fox Wallets | Fox Mens Wallets | Fox Wallet" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_confront_women_s_sunglasses" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_knoxville_sunglasses" : { + "meta_description" : "Electric Knoxville Sunglasses - Zephyr Sports carries a complete line of Electric Knoxville Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Knoxville Online Today.", + "page_title" : "Electric Knoxville Sunglasses On Sale Free Shipping", + "head_title" : "Electric Knoxville Sunglasses | Electric Knoxville Sun Glasses | Sunglasses Electric Knoxville" + }, + ".skateboard_gear.skateboard_decks.anti_hero_skateboard_decks" : { + "meta_keywords" : "anti hero skateboards,anti hero decks,anti hero Skate decks,cheap skate decks,anti hero boards,skateboarding equipment,skateboarding gear", + "meta_description" : "Anti Hero Skateboards - Zephyr Sports is your Anti Hero Headquarters! Anti Hero Decks, Complete Anti Hero Skateboards, and much More! Choose from a grip of Anti Hero boards, Cheap Skate Decks, and others; throw some other Skateboarding equipment on there like some Trucks, maybe some Bones Bearings and get ready to Ride! Zephyr Sports has all your Skateboarding gear!", + "head_title" : "Anti Hero Skateboards | Anti Hero Skateboard Equipment | Anti Hero Boards" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_frenzy_sunglasses" : { + "meta_description" : "Arnette Frenzy Sunglasses - Zephyr Sports carries a complete line of Frenzy Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Frenzy Sun Glasses Online Today.", + "page_title" : "Arnette Frenzy Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Frenzy Sunglasses | Frenzy Arnette Sunglasses | Arnette Frenzy Sun Glasses" + }, + ".airsoft.airsoft_guns.socom_airsoft_guns" : { + "meta_description" : "Socom Airsoft Guns - Buy your Socom Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Socom Airsoft Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Socom Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Socom Airsoft Guns | Socom Airsoft Rifles | Socom Airsoft Pistols", + "description" : "" + }, + ".harnessesbags.backpacks.ogio_backpacks.ogio_laptop_bags" : { + "meta_keywords" : "ogio laptop bags,ogio laptop backpack,ogio backpack,ogio laptop bag,ogio,ogio travel bags,ogio laptop,Ogio Laptop Bag,Ogio Backpacks, Ogio Laptop Backpack,l", + "meta_description" : "Ogio Laptop Bag - Ogio Backpacks - Ogio Laptop Backpack Zephyr Sports is a leading distributor of Ogio Backpacks! Ogio bags have plenty of space for all your stuff! Ogio laptop bags are specifically designed to protect and hold your most precious valuables while on the move! Ogio Backpacks are super durable made from top quality materials! Take em on the road with you or in the Air, Ogio travel bags can go anywhere! ", + "page_title" : "Ogio Laptop Bag On Sale & Free Shipping", + "head_title" : "Ogio Laptop Bag | Ogio Backpacks | Ogio Laptop Backpack " + }, + ".scenarioupgrades.pistol_holsters" : {}, + ".airsoft.airsoft_guns.famas_airsoft_guns" : { + "meta_keywords" : "Famas Airsoft Rifles,Famas airsoft guns,AEG rifles,shotgun,Famas", + "meta_description" : "Specifically designed for long range shots, these specialty airsoft rifles use high performance BB's for better accuracy. Built for defending an objective or player by having support systems (SAW) to focus on your target. Zephyr Sports is a leading distributor of Famas Airsoft guns! We carry a wide variety of Famas airsoft AEG rifles, shotguns, and more! Get your Famas AEG 's @ Zephyr Sports!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Famas Airsoft Rifles On Sale & Free Shipping", + "head_title" : "Famas Airsoft Rifles | Famas Airsoft Guns" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markerupgrades.tippmann" : { + "meta_keywords" : "tippmann upgrades,buy online now,tippmann 98 a5 a-5 x7 upgrade,tippmann custom 98 upgrade,98 custom parts", + "meta_description" : "Tippmann Upgrades - Zephyr Paintball is your one stop shop for all things Tippmann. Upgrades for your custom 98, a5, X7 and TPX Pistol. We carry custom 98 upgrades from all the top manufacturers", + "top_description" : "Tippmann are the most upgradeable [[Paintball Guns]:url=http://www.zephyrpaintball.com/category/markers/] in the world. Probably part of the reason they are the most popular entry level paintball markers.\n\n\nLooking to Upgrade your [[Tippmann]:url=http://www.zephyrpaintball.com/category/markers.tippmann/]? Zephyr Paintball carries a complete line of Tippman upgrades to outfit your Tipmann 98, X7, A5 or the new [[Tippmann Tipx pistol]:url=http://www.zephyrpaintball.com/category/markers.tippmann.tippmann_tpx_pistol/]. Whether it's a new barrel, tactical stock or trigger upgrades, Zephyr Paintball is your one stop shop for eveything Tippmann.\n\n\nYou can trick out your tippmann for a full military look like an M16 or Ak47, or increase your firepower with an e-grip or Response trigger upgrade. Be sure to check out the Tippmann Flatline Barrel for that extra bit of distance on your shots.\n\n", + "page_title" : "Buy Tippmann 98 A5 A-5 X7 Upgrades Online Now", + "head_title" : "Tippmann Upgrades | Tippmann 98 A5 A-5 X7 X-7 Upgrade | Custom 98 Upgrades" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.1ak47_style_aeg_airsoft_guns" : { + "meta_description" : "AK47 Airsoft Guns - Buy your AK 47 Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of Airsoft AK at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy AK47 Airsoft Guns On Sale & Free Shipping", + "head_title" : "AK47 Airsoft Guns |AK 47 Airsoft Guns |Airsoft AK" + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.aug_airsoft_guns" : { + "meta_description" : "AUG Airsoft Guns - Buy your Airsoft AUG Guns At Zephyr Sports for Less Today! We carry a complete line of AUG AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy AUG Airsoft Guns On Sale & Free Shipping", + "head_title" : "AUG Airsoft Guns | Airsoft AUG Guns |AUG AEG" + }, + ".casual_clothing.mens_clothing.wallets.alpinestars_wallets" : { + "meta_description" : "Alpinestars Wallets - Buy your Alpinestars Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Alpinestars Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Alpinestars Wallets on Sale @ Zephyr Sports", + "head_title" : "Alpinestars Wallets | Alpinestars Mens Wallets | Alpinestars Wallet" + }, + ".3packagespecials.gog_paintball_packages.g1_packages" : { + "head_title" : "Gog G1 Paintball Packages | Gog G1 Paintball Gun Packages" + }, + ".markerupgrades.invert_upgrades.invert_mini_upgrade_triggers" : { + "meta_description" : "Invert Triggers - Buy your Mini Upgrade Trigger Online at Zephyr Paintball for Less today. Free Shipping on Invert Mini Trigger Upgrades Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert Triggers Online On Sale Now", + "head_title" : "Invert Triggers | Mini Upgrade Trigger | Invert Mini Trigger Upgrades" + }, + ".safetygear.goggles.dye" : { + "head_title" : "Dye Paintball Goggles | Dye I4 Google,Dye thermal paintball mask", + "prodlist1" : "&SORTBY=NONE&FORMAT=THUMB&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".airsoft.airsoft_upgrades.airsoft_grease_and_lube" : { + "meta_description" : "Airsoft Grease - Buy your Airsoft Lube At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Grease On Sale & Free Shipping", + "head_title" : "Airsoft Grease |Airsoft Lube" + }, + ".barrels.freakbarrels.fullfreakbarrels" : {}, + ".apparel.jerseys.empire_paintball_jerseys.empire_azn_paintball_jerseys" : {}, + ".airsoft.tactical_airsoft_gear.camoflouge_pants.propper_tactical" : {}, + ".goggles.tippmann_paintball_masks" : {}, + ".testing_help_desk.about_zephyr_sports" : { + "hd_answer_two" : "You can view our privacy policy by [[CLICKING HERE]:url=/privacy.cgis].", + "hd_question_three" : "Why Shop at Zephyr Sports?", + "hd_question_four" : "Job Opportunities", + "hd_topic_listing" : "» Contact Us
                                                                          \n» Privacy Policy
                                                                          \n» Why Shop at Zephyr Sports?
                                                                          \n» Job Opportunities
                                                                          ", + "hd_topic" : "About Zephyr Sports", + "hd_question_one" : "Contact Us", + "hd_btn" : "images/site_specific/backto_helpdesk", + "hd_answer_three" : "Zephyr Sports has paintball and airsoft gear with low prices and free shipping on paintball guns, paintball goggles, airsoft equipment and gear. Zephyr Sports was founded in 2003 as an internet retailer focusing on the sport of paintball. In 2005 we expanded to carry airsoft equipment. We carry a complete line of paintball guns, paintball goggles, hats, hoodies, jerseys, paintballs, paintball field gear and accessories for the sport. Dye, JT USA, Kingman, Tippmann, PMI, Empire, Zap, Nelson, Maddog Designz, Proto, Pure Energy, Smart Parts and Worrgames represent just a few of the paintball brands we carry. We strive for a smooth and pain free internet buying experience with every purchase. If you haven't tried us yet, ask some of your friends and you're sure to find another satisfied customer. Feel free to give us a call at 877-814-4297 to become another satisfied Zephyr customer. Visit our [[Forums]:popup=http://forums.zephyrsports.com] & our [[Blog]:popup=http://blog.zephyrsports.com].", + "hd_question_two" : "Privacy Policy", + "hd_answer_one" : "Call us at 877-814-4297 or 805-275-2040. \n\n\n\n\n[[CLICK HERE TO EMAIL US]:url=/contact_us.cgis].\n\n\n\n\nOur address is:\n\n\n4535 McGrath St. Suite A\n\n\nVentura, CA., 93003\n\n\nUSA\n\n\n\n\nView us on Google Maps", + "hd_link" : "/category/testing_help_desk" + }, + ".shop_by_brand.tanked" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tTANKED PAINTBALL PLAYER'S APPAREL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tTANKED PAINTBALL CASUAL APPAREL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n", + "top_description2" : "=Tanked, Play till you Drop=\n\nTanked Paintball is responsible for the best and longest lasting pants, jerseys and clothing in the sport. Tanked thrives off of the companies ability to create a product that will not only exceed the industry standard but also your expectations. Try tanked jerseys and tanked pants for a spin and you will never go back to the ways of your old crappy jeans again. This stuff rocks! Check out our wide selection below. ", + "head_title" : "Tanked | Tanked paintball | Tanked pants", + "description" : "=Tanked, Play till you drop=\n\n==Foundation==\nTanked paintball was created for the player and by the player. Tanked wants to make sure that you get quality performance that lasts and performs to your every expectation. Tanked makes their jerseys and pants with extreme precision. Their design team caters to all your needs, whether they are for woods ball or your next big tournament. Try tanked and you will know why they are one of the largest international paintball companies around. \n\n==Pants==\nTanked pants are some of the sweetest and most protective pants around. With their superior lightweight construction and cordura knee pads for increased durability and protection, you know that you have a great pair of pants when you try these on. \n\n==Clothing==\nTanked clothing is simple, diverse in nature and just plain cool. Tanked's design crew believes in creating clothing that suits a casual day in the city, or a product for the paintball enthusiast. Try Tanked clothing and carry with you a badge of paintball design only known by the hardcore. \n" + }, + ".casual_clothing.mens_clothing.shorts.von_zipper_shorts" : { + "meta_description" : "Von Zipper Shorts - Zephyr stocks a complete line of Von Zipper Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Von Zipper needs. ", + "page_title" : "Von Zipper Shorts with Free Shipping at Zephyr", + "head_title" : "Von Zipper Shorts | Von Zipper Board Shorts" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_vega_watches" : {}, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsystems.tankcovers.nxe_nitro_tank_covers" : { + "meta_description" : "NXe Cover - Buy your NXe Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Nxe Paintball Bottle Cover Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy NXe Cover Online On Sale Now", + "head_title" : "NXe Cover | NXe Tank Cover | Nxe Paintball Bottle Cover" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_barrels" : {}, + ".casual_clothing.mens_clothing.tank_tops.famous_stars_and_straps_tank_tops" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs.camelbak_charm_hydration_packs" : {}, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_sonix_paintball_gun_packages" : { + "meta_description" : "Spyder Sonix Paintball Packages - Buy your Sonix Spyder Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder Sonix Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Sonix Paintball Packages Online On Sale Now", + "head_title" : "Spyder Sonix Paintball Packages | Sonix Spyder Paintball Guns Kit | Spyder Sonix Paintball Guns" + }, + ".markers.planet_eclipse_ego_paintball_guns.custom_ego_s___geo_s" : {}, + ".apparel.shoes.1_search_by_color.brown_mens_shoes" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_highstreet_sunglasses" : { + "meta_keywords" : "Ray Ban Highstreet Sunglasses ,Ray Bans,Ray Ban Sunglasses", + "meta_description" : "Ray Ban Highstreet Sunglasses - Zephyr Sports carries a complete line of Highstreet Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Highstreet Sun Glasses Online Today.", + "page_title" : "Ray Ban Highstreet Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Highstreet Sunglasses | Highstreet Ray Ban Sunglasses | RayBan Highstreet Sun Glasses" + }, + ".airsoft.tactical_airsoft_gear.camoflouge_shorts" : { + "meta_keywords" : "camouflage shorts,airsoft shorts,military shorts", + "meta_description" : "Camouflage Shorts. These vintage shorts are made for one purpose, comfort. Camouflage shorts are a great alternative choice on hot days or when your own your down time. Cargo pockets still allow you to carry any necessary items on your person while maintaining a lightweight and durable design. Some models include a waste-band drawstring and are made from cotton for a soft feel.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_kitchen_sink_backpacks" : { + "meta_keywords" : "oakley kitchen sink,kitchen sink bags, kitchen sink backpack", + "meta_description" : "Oakley Kitchen Sink Backpack - You guessed it, This bag from Oakley has just about everything except the Kitchen Sink. Zephyr Stocks the complete line of Oakley Kitchen Sink Bags. Because just ordinary will not do", + "page_title" : "Oakley Kitchen Sink Backpack Free Shipping", + "head_title" : "Oakley Kitchen Sink Backpack | Oakley Kitchen Sink Bag | Kitchen Sink Oakley Bag" + }, + ".2clearance.mens_clothing" : { + "head_title" : "Clearance Mens Clothing | Sale Mens Clothes" + }, + ".2clearance.paintball_clearance_gear.clearance_bottle_covers" : { + "head_title" : "Sale Paintball Bottle Covers | Clearance Paintball Tank Covers | Paintball Bottle Covers Sale" + }, + ".dye_rotor_paintball_loader.dye_rotor_loader" : { + "html" : "", + "description" : "For a full selection of the most popular paintball loaders check out some of these popular products.\n[[Empire Prophecy Z2]:popup=http://www.zephyrpaintball.com/category/loaders.empire.empire_prophecy_z2_paintball_hopper_loader/]\n[[Halo Too]:popup=http://www.zephyrpaintball.com/category/loaders.empire.empire_halo_too_paintball_hoppers_loaders/]\n[[Virtue Spire]:popup=http://www.zephyrpaintball.com/category/loaders.virtue_spire_paintball_loaders/]\n" + }, + ".casual_clothing.mens_clothing.sweatshirts.famous_stars_and_straps_sweatshirts" : { + "meta_description" : "Famous Sweatshirts - Buy your Famous Hoodies At Zephyr Sports for Less Today! We carry a complete line of Famous Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Famous Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Famous Sweatshirts | Famous Hoodies | Famous Hoody" + }, + ".casual_clothing.mens_clothing.shirts.fallen_shirts" : { + "meta_description" : "Fallen Flannel Shirts - Buy your Fallen Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Fallen Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Fallen Shirts & Flannels Ship Free", + "head_title" : "Fallen Flannel Shirts | Fallen Polo Shirts | Fallen Shirts" + }, + ".paintball.player_apparel.paintball_gloves.empire_paintball_gloves" : {}, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories" : { + "meta_keywords" : "airsoft accessories, airsoft attachments, vest attachments", + "meta_description" : "Molle Based Airsoft Vest Accessories. Any accessories you could possibly want to attach to your vest are available here. Simple velcro design makes adding any accessories to you vest easy. Once you pick your vest, come here to find anything you may need including a gps pocket, map pocket, water pouch, etc. All designed to match and coordinate with your current vest.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.metal_mulisha_ladies_tank_tops" : {}, + ".markers.gog_paintball_guns.ecstacy_extcy_paintball_guns_" : { + "meta_keywords" : "gog extcy,extcy paintball guns,extcy paintball marker,extcy gog,extcy marker,gog ecstasy", + "meta_description" : "GOG Paintball Guns eXTCY - Buy your Gog eXTCY Paintball Markers Online at Zephyr Paintball for Less today. Free Shipping on Gog eXTCY Paintball Gun Trust Zephyr for all your Paintball Needs", + "top_description2" : "Gog eXTCY Paintball Guns - With Up-To-Date Technology, The GoG eXTCY features a lot of bang for the buck! At only $249.95, the all new GoG eXTCY is great for any level paintball player! The lightweight design employs a full metal aluminum alloy structure making it easy to maneuver and built to last! The Gog eXTCY includes standard features like Anti-Chop eyes and the Max-Flow R vertical regulator. Removeable eye covers make for easy cleaning. Most importantly, the Gog eXTCY fires 20+ paintballs per second straight out of the box, equipped with a stock board fully capable of various firing modes including: semi auto, fully auto, 3 shot burst, PSP and BillyBall! Don't stress about the mess, maintaining your paintball gun has never been easier with the all new bolt out back design! Take your eXTCY apart in minutes rather than hours and you'll even be able to put it back together. \n", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.gog_paintball_packages/?sortby=RANDOM", + "description" : "The Gog eXTCY uses an Ion/Impulse threaded barrel and shocker nxt feedneck to allow for easy upgrades. The eXCTY paintball gun is built to run on either co2 or Compressed air so you can use whatever tank you happen to have although as always you will get better performance from compressed air.", + "page_title" : "Buy GOG Paintball Guns eXTCY Online On Sale Now", + "head_title" : "GOG Paintball Guns eXTCY | Gog eXTCY Paintball Markers | Gog eXTCY Paintball Gun" + }, + ".buyers_guide.airsoft.aisoft_pistols" : { + "question_05" : "How do I use a gas gun?", + "answer_03" : "Gas airsoft guns require the use of a gas propellant (usually green gas or HFC 134a). Both are powered by gas usually stored in the magazine. There are two types of gas pistols; \"non-blowback\" and \"blowback\". In a non-blowback gas pistol, the gas only serves as pushing the BB forward while the slide stays in a fixed position. In a gas blowback pistol, the gas pushes the bb as well as the slide. Non-blowback pistols are more efficient because they do not require as much gas to push the slide but blowback pistols actually simulate a real firearm's operation. Also, there is no need to re-cock these guns as they reset for the next shot as well. KWA is the premier manufacturer of high end airsoft gas pistols.", + "html_01" : "

                                                                          FAQ (Frequently Asked Questions)

                                                                          \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                          What is a spring pistol?What is a CO2 pistol?
                                                                          What is a gas pistol?What kind of gas should I use with my pistol?
                                                                          How do I use a gas gun?What is a propane adapter and what are its advantages for a gas gun?
                                                                          ", + "answer_05" : "First, remove the magazine from the pistol by pushing the magazine release. Then turn the magazine and the canister upside down with the canister on top and proceed to insert the nozzle into the magazine. Filling time depends on the mag capacity but usually takes anywhere from 3-6 seconds. After loading the green gas into the magazine, load the BBs by pulling down the magazine spring and insert the BBs. Next, simply insert the magazine into the gun, cock it and it is ready to fire!\n\n\nRemember to always keep the slide and all moving parts of the gun lubricated with Silicone oil. Do not use any other kind of lubricant for they may damage the gun permanently. Be sure to spray silicone oil into the top nozzle of the magazine after about 5 magazine uses. By pressing the valve and spraying a small amount of oil into the exhaust valve, you are keeping the seals and o-rings of the gun lubed for a lifetime of use. When storing a gas magazine, do not keep it fully charged or completely empty. Keep just enough green gas in it to fire about 2 or 3 rounds. This will help keep the o-rings properly lubricated while in storage.", + "question_02" : "What is a CO2 pistol?", + "answer_04" : "Green Gas is the standard that most people use in gas airsoft guns. It is stored as liquid and once released, turns into gas. HFC-134A gas consists of silicone and propane. It is slightly less powerful than Green Gas, therefore not as popular. Although, there are some models of guns only suitable for use with HFC-134A gas. Green Gas can be too strong and may destroy those types of guns.", + "answer_02" : "A co2 pistol is powered by a single disposable 12gram co2 cartridge. The cartridge is either located in the grip, magazine or under the barrel of the gun. Once the cylinder is punctured, the liquid becomes a pressurized gas that fills the chamber of the gun. After each shot the chamber resets itself and is ready for the next shot. No need to cock the gun before each shot. Some co2 pistols have the ability to be blowback. Excess air from the co2 cartridge is used to move the slide back after each shot mimicking the action of a real firearm. Popular brands of co2 airsoft pistols include Sig Sauer, Smith & Wesson and Colt.", + "question_03" : "What is a gas pistol?", + "answer_06" : "A propane adaptor allows you to use propane with your gas pistol instead of green gas. The only difference is you need use silicone oil when using propane since it has been determined that all green gas is, is propane and silicone oil mixed together. Propane adapters are very easy to use and a hot commodity in today's market seeing as propane is not as costly as green gas. \n\n\nAlso remember to always use high quality BBs with your airsoft pistol. The use of .12g BBs is not recommended for high end airsoft guns. Using such ammo often voids the warranty and could potentially harm the gun. Be sure to always try to use .20g or heavier BBs. It will make a huge difference in terms of performance. Better accuracy, no jams...what more could you ask for? To learn more about selecting the right BBs for your airsoft gun and to see what we have available, check out our buyer's guide for airsoft BBs at Zephyr University.", + "question_06" : "What is a Propane Adapter and what are its advantages for a gas gun?", + "question_04" : "What kind of gas should I use with my pistol?", + "return_link" : "/category/buyers_guide.airsoft/", + "answer_01" : "Spring pistols must be cocked each time in order to fire a BB. They do not require any batteries or gas and are great for entry level players. They are not too powerful and are fun for everyday shooting. Some popular starter brands of spring airsoft pistols include Crosman and TSD Sports.", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002", + "question_01" : "What is a spring pistol?", + "text_01" : "Zephyr Sports carries a huge line of airsoft pistols. Whether you're just getting started or are an advanced airsoft aficionado, we have a great selection ranging from spring pistols to gas blowback pistols to choose from.", + "title_01" : "Airsoft Pistols" + }, + ".casual_clothing.youth_clothing.youth_shirts" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_pants.empire_contact_tw_paintball_pants" : {}, + ".casual_clothing.mens_clothing.shirts.nixon_shirts_and_flannels" : { + "meta_description" : "Nixon Flannel Shirts - Buy your Nixon Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Nixon Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Shirts & Flannels Ship Free", + "head_title" : "Nixon Flannel Shirts | Nixon Polo Shirts | Nixon Shirts" + }, + ".airsoft.sponsorship" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.womens_clothing.ladies_hats" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.limited_edition_von_zipper_sunglasses" : { + "meta_description" : "Von Zipper Limited Edition Sunglasses - Zephyr Sports carries a complete line of Buy Limited Edition Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Limited Edition Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Limited Edition Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Limited Edition Sunglasses | Buy Limited Edition Von Zipper Sunglasses | Von Zipper Limited Edition Sunglasses Free Shipping" + }, + ".casual_clothing.mens_clothing.jackets.oakley_jackets" : { + "meta_description" : "Oakley Jackets - Buy your Oakley Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Oakley Jackets with Free Shipping", + "head_title" : "Oakley Jackets | Oakley Mens Jackets" + }, + ".1-holiday_specials" : { + "top_html_focus" : "For all you last minute shoppers. We are offering 50% off Expedited shipping methods From 12/16 through 12/22 at 2PM. Just use the promo code XMAS during checkout to see the discounted rates. This is valid only on orders placed through the web. Excludes Paintballs and phone orders.", + "dynimage1" : "images=banners/storewide/newsletters/discount_fedexpress_newsletter001\nlinks=\npauses=2000\nblank_behavior=none\n", + "description" : "=Cannot be combined with other coupons / Discounts=" + }, + ".casual_clothing.mens_clothing.beanies.neff_beanies.neff_daily_beanies" : { + "meta_description" : "Neff Daily Beanies - Buy your Beanies Neff DailyAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Neff Daily Beanies @ Zephyr Sports", + "head_title" : "Neff Daily Beanies | Beanies Neff Daily" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb3430_active_lifestyle_sunglasses" : { + "meta_description" : "Ray Ban Active Lifestyle Sunglasses - Zephyr Sports carries a complete line of Active Lifestyle Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Active Lifestyle Sun Glasses Online Today.", + "page_title" : "Ray Ban Active Lifestyle Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Active Lifestyle Sunglasses | Active Lifestyle Ray Ban Sunglasses | RayBan Active Lifestyle Sun Glasses" + }, + ".casual_clothing.youth_clothing.youth_hats.electric_youth_hats" : {}, + ".casual_clothing.z-sunglasses.spitfire_sunglasses" : {}, + ".airsoft.airsoft_guns.airsoft_bb_launchers___shells.mad_bull_grenades" : { + "head_title" : "Mad Bull Airsoft Grenades | Mad Bull Grenade" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_m-frame_sunglasses.oakley_m_frame_strike_sunglasses" : { + "meta_description" : "Oakley M Frame Strike Sunglasses - Zephyr Sports carries a complete line of M Frame Strike Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley M Frame Strike Sun Glasses Online Today.", + "page_title" : "Oakley M Frame Strike Sunglasses On Sale Free Shipping", + "head_title" : "Oakley M Frame Strike Sunglasses | M Frame Strike Oakley Sunglasses | Oakley M Frame Strike Sun Glasses" + }, + ".barrels.barrels_by_manufacturer.deadly_wind_paintball_barrels.deadlywind_fibur-x_barrels_and_kits" : { + "top_description" : "==Deadlywind Fibur-X Barrels==\nThe Deadlywind Fibur-X carbon fiber barrels are ultra-lightweight, accurate, and quiet. They utilize the Freak(tm) replaceable inserts, so one barrel and a few inserts will do the job of multiple barrels. And with the ability to affordably swap to different threads, the Fibur-X has you covered!\n\n\nThe Fibur-X barrel system consists of three parts- The thread adapter to match your gun type, a carbon fiber \"main-barrel\" which is the main part of the barrel (sets the length), and a Freak insert which sets the bore of the barrel. Note- You MUST use a Smart Parts, GoG, Luxe, or Empire \"Freak\" insert with this barrel.\n\n\nWeighing in at an average 64 grams (77 grams with insert), the Fibur-X is 2x to 4x lighter than other replaceable insert barrels. And it it is strong enough to be driven over with a car (Yes, it was done - No we do not suggest you try it on purpose!)\n\n\nUnlike other carbon fiber barrels, the Fibur-X barrel is built with a unique 3 layer construction. 2x2 satin Twill external, uni-direction fibers laid up in a strong multi-vector pattern, and then a super slick \"Silkfiber\" inside that can be safely swabbed. CNC align-bored segment for the insert area, CNC-ported with 3 rows of straight ports, and then hand-assembled and quality checked-- You can't get any more accurate.\n\n\nYou must have at least a \"Thread Adapter\", a \"Main Barrel\", and a \"Freak insert\" to use this barrel system." + }, + ".markerupgrades.dangerous_power_upgrades.dangerous_power_bolt_upgrades" : { + "meta_description" : "Dangerous Power Upgrade Bolts - Buy your Techt G4 Bolts Online at Zephyr Paintball for Less today. Free Shipping on Dangerous Power Bolt Upgrades Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dangerous Power Upgrade Bolts Online On Sale Now", + "head_title" : "Dangerous Power Upgrade Bolts | Techt G4 Bolts | Dangerous Power Bolt Upgrades" + }, + ".apparel.shoes.fallen_shoes" : {}, + ".markers.us_army_paintball_guns.us_army_carver_one_paintball_guns" : { + "meta_keywords" : "us army carver one,tippmann carver one,tipmann,tippman,us army paintball gun,carver one gun,paintball marker", + "meta_description" : "US Army Carver One - Buy your Tippmann Carver One Online at Zephyr Paintball for Less today. Free Shipping on Carver One Paintball Guns Trust Zephyr for all your Paintball Needs", + "top_description" : "The US Army Carver One from Tippmann sports. The Tippmann Carver One brings you all the reliability of the Tippmann 98 internals with a sleek new body with pelenty of picatinny rails for an easy upgrade. The Tippmann carver one includes an 8.5\" Tippmann 98 threaded barrel with a built in foregrip, sights and sling mount. The US army Carver one is an all aluminum die cast receiver and is built to take a beating. A semi automatic and electronic version are available.", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.us_army_paintball_packages.us_army_carver_one_packages/", + "description" : "The US Army Carver one is a fully licensed product with all the cool army logos included. The Tippmann carver one will run off of co2 or compressed air. The carver one uses an offset feed system to allow full use of the top picatinny rail. The Tippmann Carver one is a great gun for any scenario player who doesn't want to spend a ton of time maintaining there marker. A few drops of oil and a wipedown and your ready to play again.", + "top_html_focus" : "", + "htmlvids" : "", + "head_title" : "US Army Carver One | Tippmann Carver One | Carver One Paintball Guns", + "page_title" : "Buy US Army Carver One Online On Sale Now" + }, + ".airsystems.regulators" : { + "meta_keywords" : "paintball regulator, paintball regulators, pressure paintball regulator,paintball gun regulators,custom products regulator, CP reg", + "meta_description" : "Paintball Regulator - Zephyr has a complete line of Paintball regulators from Dye, Custom Products, Empire, Tippmann & More. If you need a new pressure paintball regulator, Zephyr has what you need", + "page_title" : "Buy Paintball Regulator Online On Sale Now", + "head_title" : "Paintball Regulator | Paintball Regulators | Pressure Paintball Regulator" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.freestyle_watches" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_prowler_sunglasses" : { + "meta_keywords" : "Von Zipper Prowler sunglasses,VZ Prowler, Von Zipper polarized sunglasses,Von Zipper Prowler,VZ Prowler glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Prowler Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Prowler sunglasses now! For Von Zipper Prowler glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Prowler Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Prowler Sunglasses | VonZipper Prowler Sunglasses" + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones" : { + "meta_description" : "Headphones - Buy your Ear BudsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Headphones On Sale & Free Shipping", + "head_title" : "Headphones | Ear Buds" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_flynn_sunglasses" : { + "meta_description" : "Spy Optics Flynn Sunglasses - Zephyr Sports carries a complete line of Flynn Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Flynn Sun Glasses Online Today.", + "page_title" : "Spy Optics Flynn Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Flynn Sunglasses | Flynn Spy Sunglasses Free Shipping | Buy Spy Flynn Sun Glasses" + }, + ".2clearance.clearance_jerseys___apparel.clearance_sweatshirts" : { + "head_title" : "Sale Paintball Sweatshirts | Clearance Paintball Sweatshirts | Paintball Sweatshirts Sale" + }, + ".markerupgrades.planet_eclipse_etha_upgrades" : {}, + ".markers.btdesignspaintballguns.bt_tm7_paintball_guns" : { + "meta_keywords" : "Battle Tested TM7,bt tm-7, tm7 paintball gun, TM-7 Marker, BT Paintball,TM7 paintball gun,tm-7 paintball gun\r ", + "htmlvids" : "\n\n", + "meta_description" : "BT TM7 Paintball Gun - The hottest Tactical Paintball Gun From Empire Battle Tested. Get your Battle Tested TM-7 from Zephyr today with Free Shipping. TM7 Paintball Marker on sale now at Zephyr", + "top_description" : "The BT TM-7 utilizes Mini Technology to inflict maximum force from a marker of minimal size. Don't be fooled by the size of the TM-7's exterior; it can hang with the big boys and is by no means a lightweight. Once you hold this marker and pull the trigger, you won't want to put it down. Its lightweight, yet durable construction is perfect for close quarters or long-range combat. This is the marker that just may have people rethink the way they looked at Mil-Sim paintball markers.", + "page_title" : "Buy BT TM7 Paintball Guns Online On Sale Now", + "head_title" : "BT TM-7 Paintball Guns | Battle Tested TM-7 | TM7 Paintball Marker", + "description" : "Mounting cool accessories is simple with the BT TM-7 paintball gun. The multiple Picatinny rails will fit optics, sights, lasers, flashlights, or anything needed to improve your experience. The lightweight construction matched with the folding Foregrip and adjustable stock allow for comfortable all-day play. Like the Mini, the TM-7 has no external hoses, giving it a clean look and the authentic feel of the real-world firearm it's based on. No paintball gun has the look and technology to match the TM-7 while in the field. Watch your opponents run when you switch to full auto using the shift-on-the-fly selector lever. Command the battlefield with the TM-7 from BT Paintball Designs.\n\n\n=Features:=\n\n* Mini Technology Inside\n* Shift-On-The-Fly, 4-Position Mode Switch\n* Multiple, Extensive Firing Modes Including Semi/Burst/Full-Auto\n* Multiple Picatinny Rails Allow For Extra Accessories\n* Adjustable, Multi-Position Stock\n* Collapsible/Adjustable Front Grip\n* Low Pressure Operation\n* No External Hoses; Internal Airline Operation\n* Additional Modes: NPPL/PSP/NXL/Millennium\n* Universal Mini-Style Barrel Threads\n" + }, + ".harnessesbags.backpacks.spitfire_backpacks" : { + "meta_description" : "Spitfire Backpacks - Buy your Spitfire Bags At Zephyr Sports for Less Today! We carry a complete line of Spitfire Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Spitfire Backpacks & Bags Ship Free ", + "head_title" : "Spitfire Backpacks | Spitfire Bags |Spitfire Luggage" + }, + ".goggles.1goggle_accesories" : { + "meta_description" : "Paintball Goggle Lenses - Buy your Replacement Paintball Lens Online at Zephyr Paintball for Less today. Free Shipping on Thermal Paintball Lens Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Goggle Lenses Online On Sale Now", + "head_title" : "Paintball Goggle Lenses |Replacement Paintball Lens | Thermal Paintball Lens" + }, + ".casual_clothing.mens_clothing.belts.matix_belts" : { + "meta_keywords" : "Matix Belts,Matix Belt Buckle,Matix Belts,Matix webbed belt", + "meta_description" : "Matix Belts - We carry the complete line of Matix Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Matix Belts on Sale Now!", + "head_title" : "Matix Mens Belts | Aplinestars Belts" + }, + ".airsystems.nitrogentanks.invert_nitrogen_tanks" : { + "meta_keywords" : "invert tank, invert paintball tank, compressed air tank, cheap invert tank, cheap paintball tank, invert compressed tank, invert nitrogen tank, white invert tank, 56ci tank", + "meta_description" : "Light, Compact tank at an affordable price! Top quality carbon fiber tank that makes your paintball experience an all day adventure", + "page_title" : "Buy Invert Tank Online On Sale Now", + "head_title" : "Invert Tank | Compressed Air Invert Tank | Cheap Air Tank" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_fly_swatter_sunglasses" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys Fly Swatter Sunglasses", + "meta_description" : "Black Flys Flyswatter Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Flys Fly Swatter Sunglasses." + }, + ".goggles.jt_usa_goggles.jt_usa_goggle_accesories" : {}, + ".casual_clothing.mens_clothing.shirts.hurley_shirts" : { + "meta_description" : "Hurley Flannel Shirts - Buy your Hurley Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Hurley Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Hurley Shirts & Flannels Ship Free", + "head_title" : "Hurley Flannel Shirts | Hurley Polo Shirts | Hurley Shirts" + }, + ".goggles.1goggle_accesories.jt_usa_goggle_accesories.jt_goggle_straps" : { + "meta_description" : "JT Goggle straps - Buy your JT Goggles Online at Zephyr Paintball for Less today. Free Shipping on straps for JT Mask Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy JT Goggle straps Online On Sale Now", + "head_title" : "JT Goggle straps | JT Goggles | straps for JT Mask" + }, + ".airsoft.shop_by_brand.ics_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".harnessesbags.packs___harnesses.custom_products_paintball_pod_packs" : { + "meta_keywords" : "custom products harness, cp harness, cp paintball harness, cp advantage harness, custom products advantage, advantage paintball harness", + "meta_description" : "Custom Products Harness - Buy your CP Harness Online at Zephyr Paintball for Less today. Free Shipping on CP Paintball Harness Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Custom Products Harness Online On Sale Now", + "head_title" : "Custom Products Harness | CP Harness | CP Paintball Harness" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_style_switch_sunglasses" : {}, + ".markerupgrades.us_army_upgrades.sights_and_lasers" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.kr3w_watches" : {}, + ".casual_clothing.womens_clothing.ladies_t_shirts.1-search_by_size" : {}, + ".airsoft.airsoft_apparel.hats" : {}, + ".airsoft.shop_by_brand.g_g_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "G&G Airsoft guns | G&G airsoft | G&G airsoft m4" + }, + ".markerupgrades.kingmanspyder.bolts" : { + "meta_description" : "Spyder Upgrade Bolts - Buy your Spyder Performance Bolt Online at Zephyr Paintball for Less today. Free Shipping on Bolt Replacement Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Upgrade Bolts Online On Sale Now", + "head_title" : "Spyder Upgrade Bolts | Spyder Performance Bolt | Bolt Replacement" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_grifter_sunglasses" : { + "meta_description" : "Smith Optics Grifter Sunglasses - Zephyr Sports carries a complete line of Grifter Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Grifter Sun Glasses Online Today.", + "page_title" : "Smith Optics Grifter Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Grifter Sunglasses | Grifter Smith Sunglasses Free Shipping | Buy Smith Grifter Sun Glasses" + }, + ".markers.dye_matrix_paintball_guns" : { + "meta_keywords" : "dye dm paintball guns,dye nt paintball gun,nt paintball marker,dm11,dm10,dm12,DM13,DM 13,DM14,DM 14, dm 11, dm 12, 2012 Dye NT, Dye NT Paintball Guns", + "meta_description" : "Dye Dm 13 Paintball Guns - We carry a complete line of Paintball guns and gear from the leader in Paintball. Dye Dm 12 Paintball Markers have been the top tournament gun for years. Check out the Dye DM12, DM13 and more at Zephyr Paintball.", + "top_description" : "n 1994, world renown professional paintball player, Dave Youngblood, began making barrels in a garage with Earon Carter of Carter Machine. In the short span of time from '94 to '09, Dave has transformed DYE, or \"Dave Youngblood Enterprises\", into the pinnacle of performance paintball products. It all started with a single barrel, the Boomstick. It's name is relative to the effect it had on the industry as a whole. Now Dye offers anything and everything for the sport, from socks and squeegees to high end markers, electronic loaders, and goggle systems. Today, Dye continues to innovate within the sport of paintball; constantly raising the bar and releasing revolutionary products", + "prodlist1_header" : "Dye Paintball Guns", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/dm8_7_header.jpg\"", + "banner1" : "banners/categories/guns/dye1_banner", + "htmlvids" : "
                                                                          \n\n
                                                                          ", + "head_title" : "Dye Dm 12 13 Paintball Guns | Dye Dm Paintball Markers | Dye Paintball Guns", + "page_title" : "Dye Dm 13 Paintball Gun Ship Free at Zephyr Paintball", + "sortby_var" : "Dye Gun Type" + }, + ".harnessesbags.backpacks.grenade" : {}, + ".casual_clothing.mens_clothing.tshirts.oakley_t_shirts" : { + "meta_keywords" : "oakley clothing,oakley shirts,oakley usa,oakley t-shirts,oakley tshirts,oakley tee shirts,oakley tshirt,oakley tee shirt,oakley tee,oakley tees", + "meta_description" : "Oakley Shirts - Complete selection of Oakley T Shirts on sale now at Zephyr Sports. Free Shipping over $25 and hassle free returns. Buy your Oakley Clothing today", + "page_title" : "Oakley Shirts On Sale & Free Shipping", + "head_title" : "Oakley Shirts | Oakley T Shirts | Oakley Clothing" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_steelcat_watches" : { + "meta_keywords" : "Nixon watches,nixon Steelcat watch,nixon watch,nixon Steelcat chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Steelcat Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Steelcat Chrono Watches", + "head_title" : "Nixon Steelcat Watches | Nixon Steelcat Chrono Watch | Nixon 5130" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_technician_sunglasses" : { + "meta_description" : "Electric Technician Sunglasses - Zephyr Sports carries a complete line of Electric Technician Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Technician Online Today.", + "page_title" : "Electric Technician Sunglasses On Sale Free Shipping", + "head_title" : "Electric Technician Sunglasses | Electric Technician Sun Glasses | Sunglasses Electric Technician" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts" : { + "meta_description" : "Oakley Replacement Parts - Zephyr Sports carries a complete line of Oakley Parts At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Replacement Lenses Online Today.", + "page_title" : "Buy Oakley Replacement Parts On Sale & Free Shipping", + "head_title" : "Oakley Replacement Parts | Oakley Parts | Oakley Replacement Lenses" + }, + ".airsoft.tactical_airsoft_gear.tactical_thigh_rigs.511_tactical_thigh_rigs" : {}, + ".apparel.shoes.globe_shoes" : {}, + ".google_plus_contest" : { + "top_html_focus" : "
                                                                          \n\n\n
                                                                          \n\n
                                                                          \nWinner will be chosen 3/15/13. Be sure to +1 and Follow ZephyrPaintball.com for your chance to WIN!
                                                                          ", + "top_description" : "", + "banner01_link" : "https://plus.google.com/117817758904099645312", + "zoovy:banner01" : "banners/paintball/newsletters/google_plus_z2.jpg" + }, + ".casual_clothing.womens_clothing.ladies_beanies.oakley_womens_beanies" : {}, + "." : {}, + ".markerupgrades.tippmann.tippmann_x7_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/scenarioupgrades.flashlights___laser_sights/", + "meta_description" : "Tippmann X7 Upgrades - Buy your X-7 Upgrades Online at Zephyr Paintball for Less today. Free Shipping on Upgrades for Tippmann X7 Trust Zephyr for all your Paintball Needs", + "buttonname_01" : "", + "banner3" : "zephyr_buttons/slings_btn001", + "buttonname_03" : "", + "add2_link" : "/category/scenarioupgrades.slings/", + "buttonname_02" : "", + "zs_banner_right1" : "ALT=TechT+X7+Barrel&IMG=banners%2fpaintball%2fside_banners%2ftecht_ifitbore_sidebanner002&LINK=%25SESSION%25http%3a%2f%2fwww%2ezephyrpaintball%2ecom%2fproduct%2fPB%2dTT%2dIFITA5X76", + "banner4" : "zephyr_buttons/flashlight_btn001", + "head_title" : "Tippmann X7 Upgrades | X-7 Upgrades | Upgrades for Tippmann X7", + "page_title" : "Buy Tippmann X7 Upgrades Online On Sale Now", + "add1_link" : "/category/barrels.tippmanna5/" + }, + ".harnessesbags.backpacks.dakine_backpacks" : { + "meta_keywords" : "dakine backpacks,dakine bags, dakine luggage,dakine bag,backpack,surf backpack,dakine gear", + "meta_description" : "Dakine Backpacks - Full line of Dakine Bags on Sale now at Zephyr Sports. Free Shipping available on Dakine Luggage.", + "page_title" : "Dakine Backpacks, Bags & Luggage at Zephyr Sports", + "head_title" : "Dakine Backpacks | Dakine Bags | Dakine Luggage" + }, + ".casual_clothing.womens_clothing.ladies_shirts" : {}, + ".casual_clothing.mens_clothing.tshirts.infamous" : {}, + ".casual_clothing.mens_clothing.hats.matix_hats" : { + "meta_keywords" : "Matix Hats,Matix caps,Matix baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Matix Hats - Zephyr carries a complete line of Matix Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Matix", + "page_title" : "Matix Hats on Sale at Zephyr", + "head_title" : "Matix Hats | Matix Caps | Matix Baseball Hats" + }, + ".casual_clothing.mens_clothing.shirts.c1rca_shirts" : { + "meta_description" : "Circa Flannel Shirts - Buy your Circa Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Circa Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Circa Shirts & Flannels Ship Free", + "head_title" : "Circa Flannel Shirts | Circa Polo Shirts | Circa Shirts" + }, + ".casual_clothing.mens_clothing.watches.polar_watches" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_base_load_backpacks" : {}, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_patrol_polarized_sunglasses" : { + "meta_description" : "Suncloud Patrol Polarized Sunglasses - Zephyr Sports carries a complete line of Patrol Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Patrol Sun Glasses Online Today.", + "page_title" : "Suncloud Patrol Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Patrol Polarized Sunglasses | Patrol Suncloud Sunglasses Free Shipping | Buy Suncloud Patrol Sun Glasses" + }, + ".barrels.smartparts" : {}, + ".loaders.empire.empire_scion_paintball_loader" : { + "meta_description" : "Empire Scion Paintball Loader - Just released from Empire. The Empire Scion has a Halo type body with internals similar to the prophecy. The Empire Scion Paintball Hopper Will begin Shipping in Late November. Buy yours first at Zephyr Paintball.", + "top_description" : "=Empire SCION Paintball Loader=\nThe Empire Scion is the newest addition to the very dominant line of Empire Paintball Loaders on the market. It features a shell similar to the Halo, with a tool-less battery compartment so you can change your battery on the fly! It is also compatible with standard Halo accessories and shells. Typically retails for $99.95, however Empire has just dropped the price! Buy today and SAVE $20!", + "page_title" : "Empire Scion Paintball Loader", + "head_title" : "Empire Scion Paintball Loader | Empire Scion Paintball Hopper", + "zoovy:banner01" : "banners/paintball/slideshow/empire_scion_paintball_hopper_slideshow.jpg", + "description" : "==Features:==\n\n*Tool-less battery Compartment\n*Large drive carrier system for consistent and faster feeding\n*Low battery indicator\n*Gentle on brittle paint\n*Infrared sensors provide automatic ball jam clearance\n*6 adjustable speed settings\n*Break Beam Eyes: Detects any shell color and only loads when it sees movement\n*Includes built-in rip-drive for manual feeding\n*Integrated freeway anti-jam\n*Works well with reballs\n*Compatible with standard Halo accessories and shells" + }, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_barrel_extensions___adapters" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Suppressors | Barrel Extension Airsoft | Airsoft Barrel Extensions" + }, + ".markerupgrades.smartparts.shocker" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add4_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "add3_link" : "/category/markerupgrades.feednecks.impulse_ion_sft_feednecks/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/nxt_feed_btn001", + "buttonname_03" : "SFT Feednecks", + "add2_link" : "/category/markerupgrades.feednecks.nxt_feednecks/", + "buttonname_02" : "NXT Feednecks", + "banner4" : "zephyr_buttons/ion_feed_btn001", + "buttonname_04" : "Grips", + "banner5" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".markers.empire_axe_paintball_guns.empire_vanquish_paintball_guns" : { + "meta_description" : "Empire Vanquish Paintball Gun - Finally a tournament level paintball marker from empire. The Vanquish is set to arrive in early march. Specs on the vanquish are just being released but we expect this to be one of the hottest paintball markers of 2013", + "top_description2" : "", + "top_description" : "Finally a tournament level paintball gun from empire. The Empire Vanquish can be fully taken apart with a single allen Key. The vanquish is currently expected to ship in mid June in limited quantities.", + "zoovy:banner01" : "", + "banner01_link" : "http://www.zephyrpaintball.com/category/markers.empire_axe_paintball_guns.empire_vanquish_paintball_guns/", + "description" : "You've probably seen the sneek peaks on the web as the pros tested the new vanquish. Here's the rundown...\n\n=Hardware Features:=\n* Pressure Balanced Spool Valve Firing Engine\n* Temperature Compensated Precision Pressure Sensor for Onscreen Pressure Readout- No External Gauge Needed\n* Spring Assisted Bolt is Soft on Paint\n* Carbon Fiber Super Freak Barrel Kit with Five Inserts\n* Widescreen OLED Display with Super Bright 2000:1 Contrast Ratio\n* 5-way Joystick Navigation Control\n* Blue Laser Breech Sensor System\n* Push Button Bolt Removal with Hinged Frame for ultra quick maintenance\n* 4-way Adjustable Dual-Bearing Trigger with Low force Trigger Switch\n* All adjustments and Maintenance requires only the 3/32\" hex wrench\n* Nano Watt XLP Flash microcontroller performing up to 16 MIPS (million instructions per second) provides highly accurate timing while not eating your battery\n* 2.7KHz Beeper to provide audio feedback\n\n\n=SOFTWARE FEATURES=\n* \"Slick Assistant\" lubricant monitoring system alerts you when you need to lube you gun.\n* 4/C Eye compatible out of the box\n* Marker to PC enabled out of the box with no special accessories needed. Upgrade firmware, change settings, and make custom boot screens with the included PC software\n* RF Upgradeable for seamless marker to loader communication\n* Interrupt based firmware gives an ultra responsive feel when firing. Virtually no lag time between trigger pull and response time\n* Super intuitive menu system that makes changing setting quick and easy\n* 3 Customizable User Configurations to quickly and easy switch style of play in seconds\n* Training mode with Beeper feedback for users to practice their trigger speed without need for air and paintballs.\n* User adjustable Anti-Bolt Stick settings makes first shot drop off a thing of the past\n* Preset tournament firing modes to keep you legal at any major tournament series\n* Customizable ramping and full-auto modes to max out your markers performance\n* Resettable shot counter\n* Calculated Average and Peak ROF's achieved displayed on screen.", + "page_title" : "Empire Vanquish Paintball Marker On Sale", + "head_title" : "Empire Vanquish Paintball Gun | Vanquish Paintball Marker" + }, + ".markers.kingmanspyder.spyder_mr1_paintball_guns" : { + "meta_description" : "Spyder MR1 Paintball Guns - Buy your MR1 Spyder Paintball Marker Online at Zephyr Paintball for Less today. Free Shipping on MR1 Paintball Gun Trust Zephyr for all your Paintball Needs", + "top_description2" : "The Spyder MR1 paintball gun brings a tactical look and feel to a solid entry level marker. The Spyder MR1 features a durable aluminum body built to take a beating. The MR1 includes a removeable stock as well as a double trigger to increase your rate of fire. The Spyder MR1 is built to run offof co2 or compressed air so you can use whatever kind of paintball tank you happen to have. ", + "page_title" : "Buy Spyder MR1 Paintball Guns Online On Sale Now", + "head_title" : "Spyder MR1 Paintball Guns | MR1 Spyder Paintball Marker | MR1 Paintball Gun", + "banner02_link" : "http://www.zephyrpaintball.com/category/3packagespecials.kingman_spyder_paintball_packages.spyder_mr1_paintball_gun_packages/", + "description" : "Zephyr carries a complete line of Spyder MR1 guns and packages at the best prices on the web. The spyder mr1 has a side mount feed to accomodate mounting sights and scopes on the top mount picatinny rail. The spyder mr1 will run off of co2 or HPA and uses a spyder threaded paintball barrel to allow for easy barrel upgrades down the road. The stock spyder mr1 trigger is 12\". The MR1 has a matte finish and an all aluminum body and trigger frame to withstand the rigors of paintball. ", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.bravo_airsoft_guns" : { + "meta_description" : "Brave Airsoft Guns - Buy your Brave Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Brave Spring Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Brave Airsoft Guns On Sale & Free Shipping", + "head_title" : "Brave Airsoft Guns | Brave Airsoft Rifles | Brave Spring Airsoft Gun" + }, + ".barrels.barrels_by_manufacturer.custom_products_paintball_barrels.cp_tactical_barrels_and_accessories" : { + "prodlist1_header" : "CP Tactical Barrels and Accessories" + }, + ".markerupgrades.grips_and_grip_panels.grips_by_frame" : {}, + ".harnessesbags" : { + "meta_keywords" : "Paintball Gun Bag, Paintball Harness, Paintball Bags, Paintball Gun, Paint Ball Gun, Paint Ball Harness, Paint Ball Bag, Paintball Equipment, Paintball Supplies, bags", + "ad3_link" : "%SESSION%/category/harnessesbags.backpacks.eclipse_backpacks/", + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=&LINK=Sly+Harness+Sale", + "prodlist2_title" : "Featured Items & Accessories", + "ad2" : "banners/paintball/side_banners/maddog_pro_harness_sidebanner_aslowas.jpg", + "page_title" : "Buy Paintball Gun Bag Online On Sale Now", + "ad2_link" : "%SESSION%/category/harnessesbags.packs___harnesses.maddog_designz_paintball_pod_packs/", + "subcat1_header" : "", + "meta_description" : "So you just got all that new gear and have no where to put it. That sounds like it could be a problem. But we are here to help. We have a full line of gear bags designed specifically for your paintball needs. And while your in here, do not forget to pick up a harness. How else are you gonna carry all that paint on the field!", + "ad1" : "banners/paintball/side_banners/dye_paintball_harness_sidebanner_template.jpg", + "zoovy:banner01" : "", + "banner01_link" : "", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/harnesses_header.jpg\"", + "banner1" : "banners/09_headers/main_categories/harnesses_bags_001", + "ad3" : "banners/paintball/side_banners/pe_gear_bags_sidebanner_template.jpg", + "ad1_link" : "%SESSION%/category/harnessesbags.packs___harnesses.dye_pod_packs/", + "head_title" : "Paintball Gun Bag | Paintball Harness | Paintball Bags", + "page_head" : "" + }, + ".airsoft.tactical_airsoft_gear.camoflouge_pants.rothco_bdu_pants" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_tice_sunglasses" : { + "meta_keywords" : "Spy Tice sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Tice Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy optic eyewear with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Tice Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Tice Sunglasses | Spy Optics Tice Sunglasses" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray-ban_rb4154_sunglasses" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys.empire_clearance_paintball_jerseys" : {}, + ".casual_clothing.womens_clothing.ladies_wallets" : {}, + ".casual_clothing.mens_clothing.tshirts.young___reckless_t_shirts" : { + "meta_keywords" : "young and reckless,young & Reckless, clothing, apparel", + "meta_description" : "Young & Reckless T Shirts - Zephyr carries a complete line of Young and Reckless clothing with low prices and free shipping.", + "page_title" : "Young & Reckless T Shirts", + "head_title" : "Young & Reckless T Shirts | Young and Reckless Clothing" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_tactical_hydration_packs" : { + "meta_description" : "Camelbak Mountain Bike Packs - Buy your At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Mountain Bike PacksOn Sale & Free Shipping", + "head_title" : "Camelbak Mountain Bike Packs" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_haymaker_sunglasses" : { + "meta_keywords" : "Spy Haymaker sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Haymaker Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy optic eyewear with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Haymaker Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Haymaker Sunglasses | Spy Optics Haymaker Sunglasses | Haymaker Spy Sunglasses Black" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.empire_sniper_pump" : {}, + ".2clearance.clearance_jerseys___apparel.clearance_t_shirts" : { + "head_title" : "Sale Paintball T Shirts | Clearance Paintball T Shirts | Paintball T Shirts Sale" + }, + ".casual_clothing.mens_clothing.sweatshirts.volcom_sweatshirts" : { + "meta_description" : "Volcom Sweatshirts - Buy your Volcom Hoodies Online At Zephyr Sports for Less Today! We carry a complete line of Volcom Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Volcom Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Volcom Sweatshirts | Volcom Hoodies | Volcom Hoody" + }, + ".paintball.paintball_guns.planet_eclipse_ego_paintball_guns.planet_eclipse_ego_lv1_paintball_guns" : {}, + ".apparel.shoes.i_path_shoes" : {}, + ".barrels.spyder.18_21__spyder_paintball_barrels" : { + "meta_description" : "Spyder 2 piece Barrels - Buy your Spyder Sniper Barrels Online at Zephyr Paintball for Less today. Free Shipping on Spyder Tactical Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder 2 piece Barrels Online On Sale Now", + "head_title" : "Spyder 2 piece Barrels | Spyder Sniper Barrels | Spyder Tactical Barrels" + }, + ".2clearance.airsoft.guns" : {}, + ".casual_clothing.womens_clothing.ladies_purses_and_bags" : {}, + ".casual_clothing.womens_clothing.ladies_purses_and_bags.srh_ladies_purses" : {}, + ".airsoft.buyers_guide.aisoft_pistols" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Buyers Guide - Airsoft Pistols" + }, + ".casual_clothing.mens_clothing.tshirts.famous_stars_and_straps_t_shirts" : { + "meta_keywords" : "Famous Stars & Straps T Shirts,Famous Stars & Straps shirts,free shipping,Famous Stars & Straps TShirt", + "meta_description" : "Famous Stars & Straps T Shirts - Zephyr carries a complete line of Famous Stars & Straps Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Famous Stars & Straps T Shirts at Zephyr", + "head_title" : "Famous Stars & Straps T Shirts | Famous Stars & Straps Shirts | Alpine Stars TShirt" + }, + ".airsoft.airsoft_accessories" : { + "meta_keywords" : "cheap airsoft,Classic Army,sigsauer,crosman,airsoft magazines,extra mags,airsoft targets,airsoft slings,airsoft holsters,airsoft scopes,airsoft sights,Spring powered airsoft,Gas powered airsoft,C02 powered airsoft,Electic airsoft guns,rc airsoft cars,rc airsoft tanks", + "meta_description" : "Cheap Airsoft - Zephyr Sports has all your Airsoft Accessories! Everything from extra air soft magazines to airsoft sights, scopes, holsters and slings! RC airsoft cars and RC airsoft Tanks! Cheap prices for high quality, straight from manufacturer Airsoft Essentials! We carry top airsoft brands like Classic Army, SigSauer, Crosman, and more! Zephyr Sports Check it out! Doesn't matter if you're looking for Spring powered, Gas powered, C02 powered, or Electic airsoft guns, We got it all and the extra mags to reload with!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Accessories | Gear for Airsoft | Acessories Airsoft Holsters" + }, + ".airsystems.tankcovers.tanked_paintball_bottle_covers" : { + "meta_description" : "Tanked Cover - Buy your Tanked Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Tanked Paintball Bottle Cover Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tanked Cover Online On Sale Now", + "head_title" : "Tanked Cover | Tanked Tank Cover | Tanked Paintball Bottle Cover" + }, + ".skateboard_gear.skateboard_longboards.sector_9_longboard_skateboards" : { + "meta_keywords" : "Sector 9 Longboard Skateboards,sector 9 longboard,sector 9 longboards,Longboard Complete,Longboarding Skateboarding,longboarding skateboard,complete longboards,skateboards longboard,longboard skateboard complete,longboarding skateboards,longboard decks,", + "meta_description" : "Sector 9 Longboard Skateboards - Zephyr Sports is your longboading skateboarding outlet! Whether you're building your own sector 9 longboard skateboard or already have a sector 9 longboard complete in mind, Zephyr is the place to be! Zephyr Carries a grip of longboarding skateboards accessories! Sector 9 Skateboards longboard, Complete longboards, Sector 9 longboard decks, long board trucks, skateboard bearings and more all @ Zephyr Sports! ", + "page_title" : "Buy Sector 9 Longboard Skateboards On Sale & Free Shipping", + "head_title" : "Sector 9 Longboard Skateboards | Longboard Complete | Longboarding Skateboarding" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_variable_power_scopes.barska_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".shop_by_brand.virtue_paintball" : { + "top_html" : "\n\n \n \n \n \n\n
                                                                          \n
                                                                          \n Virtue Gun Upgrades\n \n
                                                                          \n
                                                                          \n
                                                                          \n Virtue Hopper Upgrades\n \n
                                                                          \n
                                                                          \n
                                                                          \n Virtue Softgoods\n \n
                                                                          \n
                                                                          \n
                                                                          \n Virtue Spire\n \n
                                                                          \n
                                                                          ", + "meta_description" : "Virtue Paintball - Zephyr Sports carries a complete line of Paintball Virtue At the lowest prices on the web with free shipping and easy returns. Buy your Virtue Paintball Board Online Today.", + "top_description2" : "=Virtue. . . DESTROY THE COMPETITION=\n\nVirtue Paintball... Their name and reputation very much proceeds this awesome company. Everyone from pro teams and players like the Russian Legion, Tampa Bay Damage, and the famous Oliver \"Ollie\" Lang, use Virtue boards in their markers. This company has brought a new element to the game. Everyone was now capable of shooting at speeds never thought possible with most markers... making them more air efficient so you can play longer. Also adding more firing modes and features to markers, that previously couldn't keep up with the higher end guns. Virtue has done it all!\n\n\n==Virtue==\n* Virtue boards are at the front of the technological wave in paintball products\n* Lifetime warranty\n* Unbeatable Customer Service\n* Virtue Boards are used by top pros around the world\n* Ease of Use\n* Tech support available at various National Level Tournaments\n\n\n=Tournament Legal=", + "page_title" : "Virtue Paintball On Sale Free Shipping", + "head_title" : "Virtue Paintball | Paintball Virtue | Virtue Paintball Board", + "description" : "Barrels, bolts, triggers...the same old upgrades, using the same old technology. Virtue is the only upgrade that actually replaces your gun's engine, improving performance at every level. Virtue is the only accessory in paintball guarenteed to UPGRADE your gun's engine. Virtue Paintball specializes in developing the most advanced aftermarket paintball gun upgrades to meet the demands of today's players. \n\n\n=Virtue products are simple drop in upgrades, and instantly boost your markers performance.=\n\n\nAll of Virtues products are designed by an expert staff of programmers and engineers. Top amateur and professional players from around the world have served as their beta testers to ensure that their final products are the best on the market! " + }, + ".apparel.shoes.1search_by_size.l_men_s_size_11_shoes" : {}, + ".loaders.hopper_accesories.virtue_spire_loader_accessories" : {}, + ".scenarioupgrades.flashlights___laser_sights.crosman" : {}, + ".casual_clothing.mens_clothing.tshirts.rvca_t_shirts" : { + "meta_keywords" : "RVCA T Shirts,RVCA shirts,free shipping,RVCA TShirt", + "meta_description" : "RVCA T Shirts - Zephyr carries a complete line of RVCA Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "RVCA T Shirts at Zephyr", + "head_title" : "RVCA T Shirts | RVCA Shirts | RVCA TShirt" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.enjoi_pants_and_jeans" : { + "meta_keywords" : "enjoi clothing,enjoi jeans,enjoi clothes,enjoi apparel,enjoi pants,enjoi sharted pants,enjoi sharted pant,enjoi skinny jeans,enjoi panda jean,enjoi panda straight jean,enjoi panda jeans,enjoi panda straight jeans\n", + "meta_description" : "Enjoi Jeans - Zephyr Sports carries a complete line of Enjoi Pants to get you ready for school. Be sure to check out our other Enjoi Clothing and remember we offer free shipping on orders over $75 and easy returns", + "page_title" : "Enjoi Jeans On Sale & Free Shipping", + "head_title" : "Enjoi Jeans | Enjoi Pants | Enjoi Clothing" + }, + ".3packagespecials.planet_eclipse_package_specials" : { + "meta_description" : "Planet Eclipse Etek Paintball Packages - Buy your Planet Eclipse Etek Paintball Guns Kits Online at Zephyr Paintball for Less today. Free Shipping on Eclipse Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Planet Eclipse Etek Paintball Packages Online On Sale Now", + "head_title" : "Planet Eclipse Etek Paintball Packages | Planet Eclipse Etek Paintball Guns Kits | Eclipse Paintball Markers" + }, + ".casual_clothing.womens_clothing.ladies_sweatshirts" : {}, + ".safetygear.kneeelbowpads.nxe_knee___elbow_pads" : {}, + ".harnessesbags.backpacks.1_shop_by_bag_style.kids_packs" : {}, + ".baseball" : { + "meta_keywords" : "baseball softball gear, baseball glove,helmet,batting gloves,first base glove,catchers mitt,rawlings,little league,catchers mask,baseball equipment", + "meta_description" : "Baseball & Softball Gear - Zephyr now carries a complete line of baseball gloves and baseball bats. From little league to college to coed softball, we have you covered.Baseball Equipment ships free at Zephyr Sports", + "page_title" : "Baseball & Softball Gear @ Zephyr with Free Shipping", + "head_title" : "Baseball Softball Gear | Baseball Equipment | Baseball Gloves" + }, + ".markers.btdesignspaintballguns.empire_bt_combat_slice_paintball_guns" : { + "meta_keywords" : "bt, battle tested, paintball, guns, markers, bt4, bt-4, slice, combat slice, gear, bt 4, ", + "meta_description" : "BT Combat Slice Paintball Gun - The hottest Tactical Paintball Gun From Empire Battle Tested. Get your BT Markers from Zephyr today with Free Shipping. Empire Markers on sale now at Zephyr!", + "top_description" : "==Empire Battle Tested BT-4 Combat Slice Paintball Gun==\n\n\nThe BT Slice has arrived. With all of the great features of the original BT Combat, plus the ability to field strip without tools. The Bt Slice paintball gun is a great entry level scenario gun with the ability to be upgraded down the road. The BT Combat Slice can be upgraded with the BT Combat electronic trigger frame as well as the BT Rip clip electronic loader. The Bt Slice also has a tippmann a5 threaded barrel for an easy barrel upgrade down the road.", + "zoovy:banner01" : "", + "description" : "Empire BT Slice Combat Paintball Gun\n\nThe all new BT4 Slice Combat paintball gun was designed to be easy to maintain and preform well. When your gun malfunctions it can mean an entire day of paintballing wasted. With the new tool-less design of the BT4 Slice, hours of maintenance turn into minutes. Everything is easily accessible after removing one tool-less pin. \n\n\n=BT Slice Features:=\n*Field strippable design - simply remove ONE tool-less pin and the markers opens up for maintenance like a clamshell\n*Marker Maintenance can be performed in the field while under air pressure\n*Redesigned shells for tool-less access to all internals\n*Reduced BT Slice Picatinny rails for easier cleanup\n*Bolt on foregrip - position adjustable\n*AR-15 style T-cocking handle - no side opening for paint and dirt to enter\n*Redesigned BT Slice trigger guard accommodates hands with gloves\n*BT Combat Electronic ready grip frame", + "top_html_focus" : "", + "page_title" : "Buy BT Paintball Guns On Sale Online Now", + "head_title" : "BT Paintball Guns | BT Markers | Empire Markers" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.crosman_airsoft_guns" : {}, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_heart_of_the_hide_hoh_baseball_gloves" : { + "head_title" : "Rawlings Heart Of The Hide Hoh Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".airsoft.airsoft_bbs_ammo.airsoft_grenades_and_mines" : { + "meta_description" : "Airsoft Grenades - Airsoft Land Maines - Airsoft BB Grenade", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Grenades | Airoft Shower Grenades |Landmines for Airsoft" + }, + ".shop_by_brand.tippmann" : { + "top_html" : "
                                                                          \n\t\n
                                                                          \n\n
                                                                          \n\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tGuns\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tPackages\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tOther Gear\n\t\n
                                                                          \n
                                                                          ", + "meta_description" : "Tippmann Paintball - Zephyr Sports carries a complete line of Tippmann Paintball At the lowest prices on the web with free shipping and easy returns. Buy your Paintball Tippmann Online Today.", + "top_description2" : "=Tippman, be a pro=\n\nThe foundations of the Tippman company are based on their commitment to their customer, and their desire to provide you with premium products and technology. Tippmann Paintball has the best understanding of paintball of all of the paintball manufacturers hands down. Tippmann specializes in providing an outstanding product to all potential users. Most of the staff at Tippmann Pros are actually members of the Tippmann family, and paintball has always been a prominent aspect of their lives. Tippman knows paintball and how to make a proper product. Look at Zephyr's Tippman paintball product and you will find what you've been missing out on. Get your paintball on!", + "page_title" : "Tippmann Paintball On Sale Free Shipping", + "head_title" : "Tippmann Paintball | Tippmann Paintball | Paintball Tippmann", + "zoovy:banner01" : "banners/paintball/headers/tippmann_newlsetter.jpg", + "description" : "=Tippman, Be a pro=\n\n==Tippman, run by family==\nNick Tippman, Dylan Tippman, and Eli Tippman run one of the largest and most popular paintball guns on Earth. Tippman is a friendly and outgoing company, but when it comes to creating the product, they are all business. They also have a sweet gig going with the U.S. Army, where they are able to manufacture guns specific for Mil-Sim. \n\n\n==Alpha Black==\nThe Alpha Black is a marker designed in partnership with, and fully licensed for, the U.S. Army - and is used by soldiers for training. It has four variations, with the basic model consisting of a marker and barrel. The \"e-basic\" model comes with an electronic firing mode, while the \"tactical\" model (which resembles an M4A1 carbine) includes a stock and handle. The \"tactical electric\" improves upon the \"tactical\" by adding an electric firing mode.\n\n==Custom Pro==\nThe Tippmann Custom Pro was an upgraded version of the 98 Custom aimed at entry level speed ball play. It features a double trigger , drop-forward (which moves the tank down and forward, changing the center of gravity and allowing a tighter setup), 11 inch high performance stone-honed barrel, and Anti-chop technology. The marker also features a scratch resistant powdercoat, and utilizes the E-Trigger system.\n\n==Cyclone Feed System==\nMuch like the Response Trigger System, the Cyclone Feed System uses the excess gas from firing the marker to cycle a feeding mechanism providing up to 15 b.p.s. (Some have tested the unit at 20+ Balls Per Second with some commercially available modifications). In comparison with conventional hoppers, the Cyclone has a much wider mouth, holding multiple paintballs in the feeding mechanism even without a hopper.\n\nAs a shot is fired, excess (normally waste) gas from the shot is scavenged through the side of the marker via a banjo fitting (a T-type fitting is required for use with the response trigger system). The gas is utilized to rotate the cyclone as the marker re-cocks, force feeding a paintball into the chamber. The Cyclone Feed System comes standard on the Tippmann A-5 and an enhanced version comes on the X-7. The advent of the Cyclone Feed System marks the first widely used, non-electronic, agitated hopper. The lack of electronics means the user can expose the system to moisture (rain, snow, etc.) which would interfere or destroy other, mechanical systems.\n\n==E-Trigger==\nThe E-Trigger is an electronic means of firing the marker. Utilizing battery operated components, the E-Trigger replaces the trigger function, to where the trigger simply closes a micro switch. The switch sends a signal to a small circuit board, activating a solenoid. The solenoid uses a push rod to actuate the sear in this system. The board has multiple firing modes, allowing semi-automatic, burst, automatic and other modes. The term E-Trigger is usually applied to the system in the 98 Custom and Alpha Black, while the term E-Grip is applied to the A-5 and X-7 markers, because they use a removable grip frame that contains all the electronics.\n\n\n" + }, + ".casual_clothing.mens_clothing.shorts.volcom_shorts" : { + "meta_description" : "Volcom Shorts - Zephyr stocks a complete line of Volcom Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Volcom needs. ", + "page_title" : "Volcom Shorts with Free Shipping at Zephyr", + "head_title" : "Volcom Shorts | Volcom Board Shorts" + }, + ".airsystems.dropforwards.planet_eclipse_asa_s" : { + "meta_description" : "Planet Eclipse ASA - Buy your Ego ASA Online at Zephyr Paintball for Less today. Free Shipping on Etek On Off Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Planet Eclipse ASA Online On Sale Now", + "head_title" : "Planet Eclipse ASA | Ego ASA | Etek On Off" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.aeg_standard_capacity_mags" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Magazines | Airsoft Mags | Standard Cap Mags" + }, + ".loaders.invert_paintball_hoppers" : { + "meta_keywords" : "Invert Halo too, invert paintball hoppers, invert loaders, invert hoppers, halo too hopper, halo too loader, invert halo hopper, invert paintball loader, invert reloader hopper, invert rolader paintball hopper, Invert Halo Too", + "meta_description" : "Invert Paintball Hoppers - Now in Stock at Zephyr the Invert Halo Too Loader and invert reloader paintball loader. Check out the entire line now", + "top_description" : "The Empire Invert Halo Too paintball loader is one of the best mid level paintball hoppers on the market. Empire took the halo B loader and worked the kinks out of it and brought it back at a lower price point. at 20+BPS, the Halo too will keep up with any tournament gun on the market. The halo too is sound activated and uses the ultra quiet belt drive coupled with the freeway anti-jam for a consistent feed. The halo too will accept halo compatible speed feeds and runs off of 6 aa batteries.", + "page_title" : "Buy Invert Paintball Hoppers Online On Sale Now", + "head_title" : "Invert Paintball Hoppers | Invert Halo Too Loader | Invert Reloader Paintball loader", + "sortby_var" : "Invert Hopper Type", + "description" : "The Halo too can be upgraded with a rip drive to allow manual operation in case of a jam. The halo too comes in matte black, camo and white version are rumored to be on the way. The halo too was originally released under the invert brand name but has since been rebranded as the [[empire halo too]:url=/category/loaders.empire.empire_halo_too_paintball_hoppers_loaders/]. No change to the hopper besides a new logo. We've left both categories since people are still used to hearing Invert halo too. " + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.optics_and_flashlight_mounts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys.bt" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.26" : {}, + ".3packagespecials.dye_paintball_package_specials.dye_nt_package_specials" : { + "meta_description" : "Dye NT Paintball Packages - Buy your NT Dye Paintball Kits Online at Zephyr Paintball for Less today. Free Shipping on Dye NT Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye NT Paintball Packages Online On Sale Now", + "head_title" : "Dye NT Paintball Packages | NT Dye Paintball Kits | Dye NT Paintball Guns" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.1-search_by_size" : {}, + ".airsoft.airsoft_safety.airsoft_goggles.valken_airsoft_goggles" : {}, + ".1historical_products.paintball.paintball_goggles" : {}, + ".casual_clothing.youth_clothing.youth_hats.metal_mulisha_hats" : {}, + ".casual_clothing.womens_clothing.ladies_sunglasses" : {}, + ".barrels.barrels_by_manufacturer.bt_designs_paintball_barrels" : { + "meta_keywords" : "bt barrels, bt scenario barrels, bt paintball barrels, bt scenario paintball barrels, bt-47 barrels, bt-16 barrels, scenario barrels, woods ball barrels,BT Apex Barrels,Apex 2,apex flatline", + "meta_description" : "BT Barrels - BT Battle Tested Paintball Barrels and more available from Zephyr Paintball. Get your Apex or Apex2 today at the lowest prices on the web with Free Shipping.", + "top_description" : "Whether your opponent takes cover behind a tree, bunker or rock you will now be able to send them fleeing back to their base camp. The APEX Barrel system is redefining how the game is played. With unmatched distance along with accuracy you will be able to hit more targets than ever before. The APEX adds spin to the ball by adjusting a small mechanism located near the front end of the barrel. By adjusting the trajectory of the ball's flight path, you immediately gain the edge over your opponents in the battlefield.", + "page_title" : "Buy BT Barrels Online On Sale Now", + "head_title" : "BT Barrels | BT Apex Barrels | BT Paintball Barrels" + }, + ".paintballs.hk_army_paintballs" : { + "meta_keywords" : "HK, HK ARMY, HK Army Paintballs, tournament paintballs, paintball equipment,", + "meta_description" : "HK Army Paintballs - Buy your tournament paintballs Online at Zephyr Paintball for Less today. Free Shipping on HK Army Paintballs! Trust Zephyr for all your Paintball Needs.", + "page_title" : "Buy HK Army Paintballs Online On Sale Now", + "head_title" : "HK Army Paintballs | HK Army Paint | Tournament Paintballs" + }, + ".goggles.genx_paintball_goggles" : { + "meta_description" : "Genx Paintball Goggles - Buy your Genx Paintball Masks Online at Zephyr Paintball for Less today. Free Shipping on Genx Paintball Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Genx Paintball Goggles Online On Sale Now", + "head_title" : "Genx Paintball Goggles | Genx Paintball Masks | Genx Paintball" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.uhc_gas_airsoft_guns" : { + "meta_description" : "UHC Airsoft Guns - Buy your UHC Airsoft Pistols Online At Zephyr Sports for Less Today! We carry a complete line of UHC Airsoft Revolver at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy UHC Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "UHC Airsoft Guns | UHC Airsoft Pistols | UHC Airsoft Revolver" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_m-frame_sunglasses.oakley_m_frame_sweep_sunglasses" : { + "meta_description" : "Oakley M Frame Sweep Sunglasses - Zephyr Sports carries a complete line of M Frame Sweep Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley M Frame Sweep Sun Glasses Online Today.", + "page_title" : "Oakley M Frame Sweep Sunglasses On Sale Free Shipping", + "head_title" : "Oakley M Frame Sweep Sunglasses | M Frame Sweep Oakley Sunglasses | Oakley M Frame Sweep Sun Glasses" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_flyblockers" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys Flyblocker Sunglasses", + "meta_description" : "Black Flys Flyblockers Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Flys Flyblocker Sunglasses.", + "head_title" : "Black Flys Flyblockers Sunglasses | Black Flys Sunglasses" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.aftermath_spring_rifles" : { + "head_title" : "Aftermath Airsoft Guns | Aftermath Airsoft Rifles" + }, + ".airsystems.nitrogentanks.ninja_paintball_tanks.ninja_pro_paintball_tanks" : { + "meta_keywords" : "ninja, paintball, tanks, compressed air tanks, ninja paintball, air, tank, paintball nitro tank, carbon fiber, 800psi, 700psi, 550psi, 450psi", + "meta_description" : "NInja Pro Paintball Tanks - Compressed air Ninja tanks from Zephyr are proudly made in the USA. Get Ninja Paintball gear at Zephyr today with Free Shipping. Paintball tanks on sale now at Zephyr!", + "top_description" : "", + "zoovy:banner01" : "", + "zoovy:banner02" : "banners/paintball/newsletters/2_ninja_protanks_newsletter", + "description" : "==Ninja Paintball Pro Regulator==\n\n\nNinja has released their newest high-performance regulator, the Ninja PRO. The PRO is the first of Ninja's regulators to include Twist Technology, a new feature that allows users to \"twist\" their regulator to relocate the fill nipple and gauge to wherever you want it. The Ninja PRO is also offered as an SLP (Super Low Pressure - 300psi) regulator. The new Ninja PRO is made in the USA and we expect to have them in stock and shipping by Mid-March!!!\n\n\n=Specifications:=\n\n\n* Made in the USA. Manufactured and assembled in their factory in Crystal Lake, IL.\n* Twist Technology (360 Degree Adjustability) - Twist technology allows you to simply and quickly align the fill nipple and gauge to the position of your choice, without disassembling your regulator.\n* 2nd Generation SRT (Sonic Recharge Technology) Piston provides rapid recharge rates that virtually eliminate regulator shootdown.\n* New micro fill nipple with a lower profile design.\n* 4-way pressure adjustment. You can achieve 800psi, 700psi, 550psi, or 450psi which gives you a full range of pressure adjustments to work with any marker.", + "htmlvids" : "", + "head_title" : "Ninja Tank | Ninja Paintball | Paintball Tank", + "page_title" : "Buy On Sale NInja Pro Paintball Tanks Online Now", + "top_description3" : "" + }, + ".casual_clothing.mens_clothing.shoes.dekline_mens_shoes" : { + "meta_keywords" : "dekline,dekline shoes,dekline shoe,dekline skate shoes,dekline footwear,dekline skateboard shoes,dekline derby shoes,dekline villain shoes,dekline belmont shoes,dekline skate shoe,dekline belmont shoe,dekline captain skate shoe,dekline sneakers", + "meta_description" : "Dekline Shoes - Zephyr Sports carries a complete line of Dekline Skate Shoes with Free shipping on all shoes. Get your Dekline Shoe at Zephyr Today.", + "page_title" : "Dekline Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Dekline Shoes | Dekline Skate Shoes | Dekline Shoe" + }, + ".shop_by_brand.power_balance_fitness_bands" : { + "top_description2" : "==Power balance, Take the edge==\n\nPower balance bracelets can give you the competitive edge you need for any competition. Whether it's paintball, air soft, skateboarding, surfing, running, cycling,baseball, basketball, tennis or anything! Try Power Balance wristbands and see what all the buzz is about! Power balance bands will maximize your potential, no matter the game. ", + "top_description" : "Power Balance is Performance Technology designed to work with your body’s natural energy field. Founded by athletes, Power Balance is a favorite among elite athletes for whom balance, strength and flexibility are important. Power Balance is based on the idea of optimizing the body’s natural energy flow, similar to concepts behind many Eastern philosophies. The hologram in Power Balance is designed to resonate with and respond to the natural energy field of the body. ", + "head_title" : "Power Balance Bracelets | Power Balance Bands | Power Balance Wrist band", + "description" : "==Power balance, Take the edge==\n\n==What is Power Balance?==\nMade by athletes for athletes, Power Balance is a favorite among elite competitors, weekend warriors and every day fitness enthusiasts.\n\n==What Does It Do?==\nPower Balance contains a thin polyester film hologram, which reacts differently for each person. Give it a try and see what it does for you.\n\n==How Does the Hologram Work?==\nThe thin polyester film hologram is programmed through a proprietary process, which is designed to mimic Eastern philosophies that have been around for hundreds of years.\n\n==What Do Power Balance Users Say?==\nPower Balance athletes believe in the product-for them, performance is critical to this success. The numbers of users continue to grow -try it for yourself!\n\n==Why Was Power Balance Created?==\nThe company was created out of the principle that the founders wanted everyone, no matter what their level of activity, to maximize their potential and live life to the fullest.\n\n==What Do Professional Athletes Say?==\nWe have heard from fitness professionals, athletes, coaches and personal trainers who tell us they have experienced benefits from Power Balance for themselves, their clients and teams.\n\n==Where/How is It Made?==\nPower Balance products are programmed in the United States. The silicone/neoprene wristbands are manufactured in China.\n\n==How Long Does it Last?==\nThe holograms are designed to last indefinitely.\n\n==Will the Wristbands Work for Everyone?==\nWhile we have received testimonials and responses from around the world about how Power Balance has helped people, there is no assurance it can work for everyone. That’s why we offer a no-questions-asked, money-back guarantee: If you’re not satisfied, just return the product within 30 days with proof of purchase.\n\n==Are There Any Differences Between Power Balance Products?==\nNo, it is simply a matter of personal preference.\n\n==Can My Wristband Get Wet?==\nYes.\n\n==Does the Product Need to Touch My Skin?==\nNo.\n\n==Does It Matter Which Wrist I Wear My Wristband On?==\nNo.\n\n==What If I Feel No Effect Or Think It Doesn't Work?==\nThe product can be worn risk-free for 30 days and returned anytime within that period with a receipt." + }, + ".skateboard_gear" : { + "meta_keywords" : "skateboards,skateboarding equipment,skateboard gear,skateboard decks,skate boards,skate board,skate boards,skateboard equipment", + "meta_description" : "Skateboarding Equipment, Skateboard decks, skateboard gear,ETC!- Get all of your Skateboard equipment @ Zephyr! Zephyr Sports is your one stop shop for everything skate board related! ", + "page_title" : "Buy Skateboards Decks On Sale & Free Shipping", + "head_title" : "Skateboards Decks | Skateboarding Equipment | Skateboard Gear" + }, + ".casual_clothing.mens_clothing.rash_guards.hurley_rash_guards" : { + "meta_description" : "Hurley Rash Guards - Buy your Hurley Surf ShirtsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Hurley Rash Guards at Zephyr Sports", + "head_title" : "Hurley Rash Guards | Hurley Surf Shirts" + }, + ".airsoft.airsoft_apparel.tactical_boots" : {}, + ".zzzz_field_locator" : { + "img_001_link" : "http://www.greatdayofplay.net/fieldlocator.php", + "img_002_link" : "http://www.giantpaintball.com/new/", + "img_005_link" : "http://www.giantpaintball.com/new/ ", + "img_001" : "field_locator/field_locator_image_001", + "img_003" : "field_locator/field_locator_image_003", + "img_005" : "field_locator/field_locator_image_005", + "img_002" : "field_locator/field_locator_image_002", + "img_004_link" : "http://www.giantpaintball.com/new/index.php?option=com_content&view=category&layout=blog&id=18&Itemid=55", + "img_003_link" : "http://www.giantpaintball.com/new/index.php?option=com_content&view=section&layout=blog&id=4&Itemid=45", + "img_004" : "field_locator/field_locator_image_004" + }, + ".paintball.paintball_goggles.1goggle_accesories" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_quanta_sunglasses" : {}, + ".casual_clothing.z_shoes_and_footwear.reebok" : {}, + ".airsoft.airsoft_guns.1_shop_by_gun_type.thompson_sub_machine_guns" : { + "meta_description" : "Thompson Airsoft Guns - Buy your Airsoft Tommy Gun At Zephyr Sports for Less Today! We carry a complete line of Thompson M1A1 at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "Below are replica Airsoft Thompson Sub Machine Guns. The original Thompson is an American submachine gun, invented by John T. Thompson in 1919, that became infamous during the Prohibition era. It was a common sight in the media of the time, being used by both law enforcement officers and criminals. The Thompson was also known informally as: the \"TSMG\", the \"Tommy Gun\", the \"Trench Broom\", the \"Trench Sweeper\", the \"Chicago Piano\", the \"Chicago Typewriter\", and the \"Chopper\".\n\n\n\n\nThe Thompson was favored by soldiers, criminals and police alike for its ergonomics, compactness, large .45 ACP cartridge, reliability, and high volume of automatic fire. It has since gained popularity among civilian collectors for its historical significance.\n\n\n\n\n", + "page_title" : "Buy Thompson Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Thompson Airsoft Guns |Airsoft Tommy Gun |Thompson M1A1", + "description" : "" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_neccesity_womens_sunglasses" : { + "meta_keywords" : "Oakley Neccesity Womens Sunglasses,Neccesity Womens oakley sunglasses,oakley Neccesity Womens, Neccesity Womens polarized sunglasses", + "meta_description" : "Oakley Neccesity Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Neccesity Womens and Polarized Oakley Neccesity Womens Sunglasses on Sale! ", + "page_title" : "Oakley Neccesity Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Neccesity Womens Sunglasses | Neccesity Womens Oakley Sunglassses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_polarized_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized oakley sunglasses,oakley Polarized, Polarized sunglasses", + "meta_description" : "Oakley Polarized Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Polarized and Polarized Oakley Sunglasses on Sale! ", + "page_title" : "Oakley Polarized Sunglasses with Free Shipping", + "head_title" : "Oakley Polarized Sunglasses | Polarized Oakley Sunglassses" + }, + ".2clearance.clearance_air_systems" : { + "meta_keywords" : "clearance tanks, clearance paintball tanks, clearance air systems, clearance compressed air tanks, cheap paintball tanks, cheap compressed air tanks, cheap drop forwards", + "page_title" : "", + "head_title" : "Clearance Tanks | Cheap Paintball Tanks | Clearance Paintball Tanks" + }, + ".barrels.barrels_by_manufacturer.dye_paintball_barrels.dye_barrel_tips" : { + "meta_description" : "Dye Ultralite Tips - Buy your Dye UL Paintball Barrels Online at Zephyr Paintball for Less today. Free Shipping on Dye Ultralite Barrel Tip Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Ultralite Tips Online On Sale Now", + "head_title" : "Dye Ultralite Tips| Dye UL Paintball Barrels | Dye Ultralite Barrel Tip" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.1_search_by_size.3_medium_ladies_tank_tops" : {}, + ".casual_clothing.mens_clothing.belts.electric_belts" : { + "meta_keywords" : "Electric Belts,Electric Belt Buckle,Electric Belts,Electric webbed belt", + "meta_description" : "Electric Belts - We carry the complete line of Electric Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Electric Belts on Sale Now!", + "head_title" : "Electric Mens Belts | Aplinestars Belts" + }, + ".safetygear.goggles" : { + "meta_keywords" : "Cheap Paintball Masks, Paintball Goggles, Paintball Mask Goggles, Paintball Masks, Discount Paintball Masks, Discount Paintball Goggles, Discount Paintball Mask Goggles, Discount Paintball Accessories, Discount Paintball Equipment", + "meta_description" : "Paintball Mask Goggles - Zephyr Paintball offers a wide variety of cheap paintball masks, paintball goggles, and other paintball equipment.", + "page_title" : "Buy Cheap Paintball Masks Online On Sale Now", + "head_title" : "Cheap Paintball Masks | Paintball Goggles | Paintball Mask Goggles" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_echo_charlie_backpacks" : { + "meta_description" : "Oakley Echo Charlie Backpacks - Buy your Oakley Echo Charlie Bag At Zephyr Sports for Less Today! We carry a complete line of Echo Charlie Backpack at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Echo Charlie Backpacks On Sale & Free Shipping", + "head_title" : "Oakley Echo Charlie Backpacks | Oakley Echo Charlie Bag | Echo Charlie Backpack" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb4057_sunglasses" : { + "meta_keywords" : "Ray Ban RB4057 Sunglasses ,Ray Bans,Ray Ban Sunglasses", + "meta_description" : "Ray Ban RB4057 Sunglasses are now available @ Zephyr Sports! Made in Italy, these Ray Ban Sunglasses have style and quality above all else! Backed with a manufacturers warranty, these Rayban Sunglasses are a classic look that never fades! These Ray Bans are available in various colors, check em out @ Zephyr Sports!", + "page_title" : "Buy Ray-Ban RB4057 Sunglasses On Sale & Free Shipping", + "head_title" : "Ray-Ban RB4057 Sunglasses | RayBan RB4057 Sunglasses | Ray Ban RB 4057 Sunglasses" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_logan_sunglasses" : { + "meta_keywords" : "spy logan sunglasses,spy logan,spy logan polarized sunglasses,spy optic Logan,Spy Logan glasses", + "meta_description" : "Spy Logan Sunglasses - Zephyr carries a complete line of Spy Optic Logan Sunglassess including the Spy Logan Polarized line of sunglasses. With Free shipping, a 30 day satisfaction guarantee and 1 year breakage protection, Zephyr Sports is your Spy Optics headquarter!", + "page_title" : "Buy Spy Logan Sunglasses -Spy Logan Polarized Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Logan Sunglasses -Spy Logan Polarized Sunglasses | Spy Optics Logan Sunglasses" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_sonic_fly_sunglasses" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys Sonic Sunglasses", + "meta_description" : "Black Flys Sonic Fly 2 Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Fly Sonic Fly 2 Sunglasses.", + "head_title" : "Black Flys Sonic Fly 2 Sunglasses | Black Flys Sunglasses" + }, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_ruin_sunglasses" : { + "meta_description" : "Anarchy Ruin Sunglasses - Zephyr Sports carries a complete line of Anarchy Ruin Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Ruin Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Ruin Sunglasses | Anarchy Ruin Sun Glasses" + }, + ".casual_clothing.womens_clothing.ladies_sweatshirts.nixon_ladies_sweatshirts" : {}, + ".paintballs.genx" : {}, + ".safetygear.goggles.extreme_rage_goggles" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.g36c_aeg_airosft_gun_mags" : {}, + ".casual_clothing.youth_clothing.youth_t_shirts.element_t-shirts" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_flak_jacket_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley flak jacket sunglasses,oakley polarized flak jacket sunglasses,polarized oakley flak jacket sunglasses", + "meta_description" : "Oakley Flak Jacket Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Flak Jacket sunglasses and Polarized Oakley Flak Jacket Sunglasses on Sale!", + "page_title" : "Oakley Flak Jacket Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Flak Jacket Sunglasses | Oakley Flak Jacket Polarized Sunglasses" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_trinity_hydration_packs" : {}, + ".paintballs.xo_paintballs" : {}, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_pistol_vertical_grip" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Foregrips | Airsoft Pistol Grips | Pistol Grips Airsoft" + }, + ".markers.bob_long_paintball_guns.bob_long_marq_7_paintball_guns" : { + "meta_keywords" : "Bob long,bob long paintball,paintball guns,Bob Long Victory Ripper Paintball Gun,victory ripper,bob long victory,cheap bob long,paintball gun,paintball marker,paintball equipment", + "meta_description" : "Bob Long Victory Ripper Paintball Guns @ Zephyr! Full line of bob long paintball guns. Bob Long paintball gun accessories available! Pick up your Bob Long Victory Ripper today! Choose Zephyr for all your Paintball Equipment!", + "page_title" : "Buy Bob Long Paintball Online On Sale Now", + "head_title" : "Bob Long Paintball | Bob Long | Bob Long Victory Ripper" + }, + ".shop_by_brand.proto" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tPROTO PLAYER'S APPAREL\n\t\n
                                                                          \n
                                                                          \n \n \n
                                                                          \n\tPROTO CASUAL APPAREL\n\t\n
                                                                          \n
                                                                          \n\n\n\n\n\n\n", + "meta_description" : "Proto Paintball - Buy your Proto Paintball Guns At Zephyr Sports for Less Today! We carry a complete line of Proto Paintball Markers at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=Proto, a new way to roll=\n\nProto Paintball is a leading designer of top quality paintball gear. Sister company to Dye Precision Paintball, Proto has taken on its own feel the last few years. Proto Paintball has been turning out tournament grade paintball markers at the best prices in the paintball market. Proto Matrix Rail Paintball guns are competitive markers that won't break the bank! Proto Paintball Markers offer a host of features that won't let you down in the heat of the battle! Buy Proto Paintball Guns today and dominate tomorrow!", + "page_title" : "Buy Proto Paintball On Sale & Free Shipping", + "head_title" : "Proto Paintball | Proto Paintball Guns | Proto Paintball Markers", + "description" : "=Proto, a new way to roll=\n\n==Proto, originally a sister company of Dye paintball is moving out and on its own. Now a top designer and innovator in the world of paintball, Proto has found it's own and is thriving. Look for new Proto Markers like the Proto Rail and Proto Reflex Rail. \n\n==Proto Reflex Rail==\nHigh-end performance in a durable and reliable setup. The Proto Reflex Rail is for the serious competitor, featuring Boost Forward Technology, giving you a cushioned push on the ball and delayed bolt speed for increased air efficiency and high rate of fire. REDESIGNED FOR 2011 the all-new 3-D milling, color coded seals for simplified maintenance, and a host of other features make the 2011 Reflex Rail the gun of choice. The durable Reflex Rail solenoid features consistent airflow, and with a dwell of 18 milliseconds, you get super fast cycle speeds. The small, light Hyper3 In-Line Air Regulator comes standard. The Hyper3 regulator provides high flow and smooth velocity adjustment, with non-slip grip rings. The ultimate in ergonomic comfort, the Ultralite Frame with fully adjustable trigger, comes standard on the Rail. The solid construction consists of an aluminum body, bolt, Ultralite Frame and trigger. We've designed the Rail with the goal of providing you with top-level performance at a reasonable price. \n\n==Proto Rail==\nTaking over the field, the Proto Rail is your stepping stone to greatness. High-end performance in a durable and reliable setup, the Proto Rail is for the serious competitor. Featuring Boost Forward Technology, giving you a cushioned push on the ball and delayed bolt speed for increased air efficiency and high rate of fire.\nAll new 3-D milling, color coded seals for simplified maintenance, and a host of other features make the Rail the gun of choice. The durable Rail solenoid features consistent airflow, and with a dwell of 40 milliseconds, you get super fast cycle speeds. The small, light Hyper3 \nIn-Line Air Regulator comes standard. The Hyper3 regulator provides high flow and smooth velocity adjustment, with non-slip grip rings. The ultimate in ergonomic comfort, the Ultralite 45 Frame with fully adjustable trigger, comes standard on the Rail. The solid construction consists of an aluminum body, bolt, Ultralite 45 Frame and trigger. Proto has designed the Rail with the goal of providing you with top-level performance at a reasonable price.\n\n==Proto Jersey==\nYour jersey is the most visible piece of gear on the field; now enter the Proto Jersey. A jersey full of design and function to keep you at the top of your game. We’ve increased the mesh venting overall to cool you down faster. Patent Pending silicone injection improves aim stability and keeps your tank in the sweet spot. Featuring quilted padding on the shoulders, elbows and forearms, the Proto Jersey keeps you protected. Elastic cuffs feature thumb locks to keep your jersey from riding up when diving into cover. The Proto jersey features no-fade sublimation graphics so the style keeps up with your game.\n\n==Proto Pant==\nStep into a pant that’s going to perform, a pant that’s going to take a beating, a pant engineered specifically for paintball. The Proto pant has its foundation in these principles. Lightweight and fast, these pants let you charge the field, while inner leg venting keeps you cool under fire. Reinforced stitching for the longevity of your gear. Padded knees, crotch and yoke for extra protection. Added bonuses like a swab pocket, adjustable cuffs and side Velcro closures to name a few. The sublimated paneling on the sides keeps bright and clean after washing. We spared no ounce of our paintball experience when designing the new Proto Pant. Go out and get dirty, be aggressive, and know that your pants will keep up with you." + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_lustre_sunglasses" : { + "meta_description" : "Arnette Lustre Sunglasses - Zephyr Sports carries a complete line of Lustre Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Lustre Sun Glasses Online Today.", + "page_title" : "Arnette Lustre Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Lustre Sunglasses | Lustre Arnette Sunglasses | Arnette Lustre Sun Glasses" + }, + ".categoryloaders.hopper_accesories" : {}, + ".casual_clothing.mens_clothing.hats.lrg_hats" : { + "meta_keywords" : "LRG Hats,LRG caps,LRG baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "LRG Hats - Zephyr carries a complete line of LRG Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything LRG", + "page_title" : "LRG Hats on Sale at Zephyr", + "head_title" : "LRG Hats | LRG Caps | LRG Baseball Hats" + }, + ".misc_items.cameras_and_video_systems" : {}, + ".3packagespecials.kingman_spyder_paintball_packages.kingman_spyder_mrx_elite_paintball_packages" : { + "meta_keywords" : "Spyder paintball gun, woodsball gun, woodsball marker, Spyder MRX, Spyder MRX Elite, Spyder woodsball, spyder markers, spyder elite marker, spyder elite paintball gun, woodsball markers, woodsball paintball gun, woodsball, military simulation paintball guns, DLS, Dual Loading System, Mag Fed paintball gun, paintball magazine, paintball packages, paintball kit", + "htmlvids" : "", + "meta_description" : "The Spyder MRX Elite Paintball gun is an excellent woodsball marker for the player looking for the most realist military simulation. the DLS (Dual Loading System) allows you to use both a hopper and the guns 10 round magazine to spray paint.", + "top_description2" : "The Spyder MRX Elite is a tactical powerhouse featuring the brand new \"DLS\" Dual Loading System. This unique patent pending system enables you to interchange your loading system with a quick turn of the barrel; allowing the user to switch between a traditional upper load feed system and all new 10-round lower magazine feed system during play. The extensive list of included MRX Accessories delivers a realistic military look allowing the player to experience a true Mil-Sim feel making it a must-have marker for scenario paintball players.", + "page_title" : "Buy Spyder MRX Elite On Sale & Free Shipping", + "head_title" : "Spyder Paintball MRX Elite Gun | Woodsball Marker | Spyder MRX", + "zoovy:banner02" : "banners/paintball/newsletters/spyder_mrx_elite_banner" + }, + ".casual_clothing.mens_clothing.shorts.proto_shorts" : { + "meta_description" : "Proto Shorts - Zephyr stocks a complete line of Proto Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Proto needs. ", + "page_title" : "Proto Shorts with Free Shipping at Zephyr", + "head_title" : "Proto Shorts | Proto Board Shorts" + }, + ".casual_clothing.z-sunglasses.zephyr_sports_sunglasses" : { + "banner01_link" : "/product/ZPHR-0810-SUNNIE-PRT/Zephyr-Sports-Limited-Edition-Summer-Sunnies.html", + "zoovy:banner01" : "banners/sunglasses/slideshow/zephyr_sunglasses_slideshow_template.jpg" + }, + ".casual_clothing.mens_clothing.socks.dgk_socks" : { + "meta_description" : "DGK Socks - Buy your DGK Skate Socks At Zephyr Sports for Less Today! We carry a complete line of DGK Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DGK Mens Socks at Zephyr Sports", + "head_title" : "DGK Socks | DGK Skate Socks | DGK Mens Socks" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_51-30_watches" : { + "meta_keywords" : "Nixon watches,nixon 51-30 watch,nixon watch,nixon 51-30 chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon 51-30 Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon 51-30 Chrono Watches", + "head_title" : "Nixon 51-30 Watches | Nixon 51-30 Chrono Watch | Nixon 5130" + }, + ".airsystems.dropforwards.custom_products_drops___cradles.custom_products_drop_forwards___rails" : { + "meta_description" : "Custom Products Drop Forward - Buy your Cp Drop Online at Zephyr Paintball for Less today. Free Shipping on CP Drops Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Custom Products Drop Forward Online On Sale Now", + "head_title" : "Custom Products Drop Forward | Cp Drop | CP Drops" + }, + ".casual_clothing.womens_clothing.ladies_pants" : {}, + ".casual_clothing.mens_clothing.jackets.srh_jackets" : { + "meta_description" : "SRH Jackets - Buy your SRH Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On SRH Jackets with Free Shipping", + "head_title" : "SRH Jackets | SRH Mens Jackets" + }, + ".1newitems.2009_azodin_gear" : {}, + ".airsoft.slingshots.1slingshots" : { + "meta_keywords" : "slingshots, airsoft slingshots, paintball slingshots, firepower sling shots, sling shots, sling shot, trumark", + "meta_description" : "Slingshot paintball has increased its popularity due to the low cost and the variation of strategy involved in the game. These slingshots are composed of a lightweight solid steel frame for maximum durability and easy quick release action with reinforced surgical tubing. Other than paintballs, steel marbles can also be used but advised for target practice only.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.shorts.dakine_shorts" : { + "meta_description" : "AlpineStars Shorts - Zephyr stocks a complete line of Alpinestars Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Alpinestars needs. ", + "page_title" : "Alpinestars Shorts with Free Shipping at Zephyr", + "head_title" : "Dakine Shorts | Dakine Board Shorts" + }, + ".3packagespecials.kingman_spyder_paintball_packages.kingman_training_pistol_packages" : { + "meta_description" : "Kingman Training Paintball Guns Packages - Buy your Kingman Paintball Pistols Starter Kits Online at Zephyr Paintball for Less today. Free Shipping on Spyder Kingman Training Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Kingman Training Paintball Guns Packages Online On Sale Now", + "head_title" : "Kingman Training Paintball Guns Packages |Kingman Paintball Pistols Starter Kits | Spyder Kingman Training Markers" + }, + ".airsoft.tactical_airsoft_gear.tactical_slings" : {}, + ".harnessesbags.backpacks.toy_machine_backpacks" : { + "meta_description" : "Toy Machine Backpack - Buy your Toy Machine Back PackOnline At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Toy Machine Backpack Now! On Sale & Free Shipping", + "head_title" : "Toy Machine Backpack | Toy Machine Back Pack" + }, + ".barrels.barreladapters" : { + "meta_description" : "Paintball Barrel Adapter - Buy your Adapters for Paintball Barrels Online at Zephyr Paintball for Less today. Free Shipping on Barrel Thread Adpater Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Barrel Adapter Online On Sale Now", + "head_title" : "Paintball Barrel Adapter | Adapters for Paintball Barrels |Barrel Thread Adpater" + }, + ".markerupgrades.kingmanspyder.spyder_vs_upgrades.spyder_vs_feed_necks" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.oakley_watches" : { + "meta_keywords" : "Oakley watches,Oakley watch,time teller,watches Oakley", + "meta_description" : "Oakley Watches - Zephyr Carries a complete of watches from Oakley. Get your Oakley watch today with free shipping at Zephyr Sports. From the Player to the Time Teller we have you covered", + "page_title" : "Oakley Watches Free Shipping at Zephyr Sports", + "head_title" : "Oakley Watches | Oakley Watch | Watches Oakley" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_borough_sunglasses" : { + "meta_description" : "Spy Optics Borough Sunglasses - Zephyr Sports carries a complete line of Borough Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Borough Sun Glasses Online Today.", + "page_title" : "Spy Optics Borough Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Borough Sunglasses | Borough Spy Sunglasses Free Shipping | Buy Spy Borough Sun Glasses" + }, + ".markerupgrades.empire_upgrades.empire_mini_parts_and_upgrades" : {}, + ".casual_clothing.womens_clothing.ladies_shoes" : {}, + ".barrels.spyder.12__spyder_paintball_barrels" : { + "meta_description" : "12 inch Spyder Paintball Barrels - Buy your 12\" Spyder Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Spyder Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 12 inch Spyder Paintball Barrels Online On Sale Now", + "head_title" : "12 inch Spyder Paintball Barrels | 12\" Spyder Threaded Upgrade | Spyder Paintballs Barrels" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.socom_gear_gas_airsoft_guns" : { + "meta_description" : "Socom Gear Airsoft Guns - Buy your Socom Gear Airsoft PistolAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Socom Gear Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Socom Gear Airsoft Guns | Socom Gear Airsoft Pistol" + }, + ".skateboard_gear.complete_skateboards.blind_complete_skateboards" : { + "meta_keywords" : "Blind Complete Skateboards,Blind skateboards,blind skateboarding, blind skate boards,skate board,blind complete,skateboard decks,skate board deck ", + "meta_description" : "Blind Complete Skateboards - So Cals largest selection of Blind Skateboards with free shipping over $75. Get all of your Blind skateboarding gear at Zephyr Sports Today. Phone orders welcome 805-275-2040", + "head_title" : "Blind Complete Skateboards | Blind Skateboards | Blind Skateboarding" + }, + ".markers.smartparts.epiphany_paintball_guns.epiphany_package_kits" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_spencer_watches" : { + "meta_description" : "Nixon Spencer Watches - Buy your Nixon Spencer Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Spencer at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Spencer Watches", + "head_title" : "Nixon Spencer Watches | Nixon Spencer Watch | Nixon Spencer" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.1_mp5_style_aeg_airsoft_guns" : { + "meta_description" : "SMG MP5 Airsoft Guns - Buy your Airsoft SMG MP5 At Zephyr Sports for Less Today! We carry a complete line of SMG MP5 AEG Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy SMG MP5 Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "SMG MP5 Airsoft Guns |Airsoft SMG MP5 |SMG MP5 AEG Airsoft Gun" + }, + ".airsoft.tactical_airsoft_gear.head_gear.voodoo_tactical_head_gear" : { + "meta_keywords" : "voodoo tactical head gear,voodoo headbands,vo", + "meta_description" : "Voodoo Tactical headwear - Zephyr carries a complet line of voodoo tactical headbands and headwraps to protect you in the big game. Low prices Free Shipping, great customer service. Trust Zephyr", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_yoko_sunglasses" : { + "meta_description" : "Spy Yoko Sunglasses - Buy your Yoko Spy Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Spy Yoko at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Spy Yoko Sunglasses Now! On Sale & Free Shipping", + "head_title" : "Spy Yoko Sunglasses | Yoko Spy Sunglasses | Spy Yoko" + }, + ".casual_clothing.mens_clothing.sweatshirts.circa_sweatshirts" : {}, + ".airsystems.dropforwards.deadonpaintball" : {}, + ".harnessesbags.backpacks.camelback_backpacks" : { + "meta_keywords" : "camelbak pack,camelbak mule hydration pack,camelbak packs,camelbak backpacks,camelbak hydration packs,camelbak 100oz,camelbak hydrobak hydration pack,camelbak hydration backpack,camelback backpack,camelback backpacks,camelbak hydration system,camelbak sale,camelbak bags,camelback packs,camelback hydration pack,discount camelbak,camel back hydration pack,camelback hydration system,camel back backpacks", + "meta_description" : "Camelbak Packs - Zephyr Sports carries a complete line of Camelbak backpacks and Camelbak Hydration Packs. We offer free shipping over $25 along with the lowest prices on the web.", + "page_title" : "Buy Camelbak Hydration Pack and Backpacks Free Shipping", + "head_title" : "Camelbak Packs | Camelbak Backpacks | Camelbak Hydration Packs" + }, + ".1newsletter.facebook" : { + "description" : "\n\n\n" + }, + ".markers.kingmanspyder.spyder_mr100_paintball_guns" : { + "meta_keywords" : "spyder mr100,spyder paintball guns,spyder mr 100,mr100 paintball gun,spyder mr100 pro,spyder mr100 package,starter kit", + "meta_description" : "Spyder MR100 paintball gun on sale now! The zephyr Spyder MR100 sale will get you in the game for less. Be sure to check out our Spyder mr 100 starter packages. Get in the game an play!", + "top_description" : "\n", + "banner02_link" : "http://www.zephyrpaintball.com/category/3packagespecials.kingman_spyder_paintball_packages.spyder_mr100_paintball_gun_packages/", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001", + "description" : "The Spyder MR100 is a tactical look marker for the entry level paintball player. The spyder mr100 is a semi auto gun meaning it has no electronics and no batteries to replace. The mr100 has spyder's patent pending eko valve system allowing you to shoot up to 1500 shots off of a 20 oz Co2 tank. The Spyder MR100 is also compatible with compressed air or HPA tanks.\n\n\nThe spyder mr100 has a high impact polymer clamping feedneck to keep you hopper snug on your gun. All colors of the spyder mr100 have a matte annodized finished to keep your marker looking sharp. The grip from on the spyder mr 100 is all aluminum with a stock double trigger to make rapid firing easy. The volocity on the MR100 is easily adjustable with a one piece velocity adjuster / spring guide. On the side of the spyder mr100 is an aluminum picatinny rail system to mount any stock or scope of your liking for the ultimate military look. The bolt on the Mr100 is a top cocking pull pin design with a wuick release pin for easy bolt removal for cleaning.\n\n\nSpyder has done a good job of building a solid entry level gun in the Spyder mr100. At less than $100 you get a lot of paintball gun for your money. Why rent when you can own the Spyder MR100 from Zephyr Paintball today. Be sure to check out all of our Spyder MR100 packages.", + "head_title" : "Spyder MR100 Paintball Gun | Spyder MR100 Sale | Spyder MR 100", + "page_title" : "Spyder MR100 Paintball Gun Sale at Zephyr Paintball", + "top_description3" : "The new Spyder paintball line for 2012 is looking pretty sweet! The new Spyder MR100 is no exception. The MR 100 will come in 3 colors, Olive, Black and Silver. The MR100 operates on CO2 or compressed air, and has a couple rails for you to mount accessories on. Oh yeah, did we mention the spyder mr100 paintball gun will sell for under $100?!" + }, + ".markerupgrades.smartparts.shocker.shocker_boards___electronics" : {}, + ".harnessesbags.paintball_gear_bags.bt_gear_bags___backpacks" : { + "meta_description" : "Empire BT Paintball Bags - Buy your Bt Gear Bags Online at Zephyr Paintball for Less today. Free Shipping on Battle Tested Backpacks Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire BT Paintball Bags Online On Sale Now", + "head_title" : "Empire BT Paintball Bags | Bt Gear Bags | Battle Tested Backpacks" + }, + ".casual_clothing.z_shoes_and_footwear.olukai_sandals" : {}, + ".markers.kingmanspyder.spyder_fenix_paintball_guns" : { + "meta_keywords" : "spyder fenix,fenix paintball,spider fenix,spyder fenix,paintball gun,kingman spyder fenix,spyder fenix parts,kingman spyder fenix acs,spyder fenix manual,spyder fenix upgrades,2012 spyder fenix", + "meta_description" : "Kingman Spyder Fenix Paintball Gun - 2012 Spyder Fenix now shipping at Zephyr Sports. Get your Kingman Spyder Fenix with free shipping at Zephyr today. ", + "top_description2" : "Kingman's Spyder Fenix Paintball Marker has arrived! The only electronic Spyder paintball gun for the year is here and packed with plenty of features out of the box. The Fenix is a great entry level electronic gun for the paintball player looking for a little more firepower than your standard rental gun. The Spyder fenix comes stock with the leap 2 board and electronic break beam anti chop eyes to keep the paint flying down field. The latest version of the Fenix features an adjustable trigger to get just the perfect feel as well as a high rate of fire to keep launching paintballs down field. The Spyder Fenix includes an aluminum clamping feed neck to keep your hopper securely fastened to you gun during the game. The stock barrel is a spyder threaded 11\" barrel that will provide the accuracy you need to take out opposing players.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "%SESSION%/category/3packagespecials.kingman_spyder_paintball_packages.spyder_fenix_paintball_gun_packages/", + "description" : "===The new 2012 Spyder Fenix Electronic Paintball Gun is Here!!===\n\n\nThis new Spyder Fenix is the latest addition to Spyder's storied line of Electronic paintball guns. These babies are in stock and ready to go! Pick one up and get in the game!\n\n\n=2012 Spyder Fenix Paintball Gun Features:=\n\n*Eko Valve System (Patent Pending) shoots up to 1600 shots from a 20oz CO2 Tank\n*Break Beam Eye (Anti-Chop System)\n*Leap II Circuit Board with Rear Facing Color Access Mode Display (CAMD)\n*Dual Ball Detents with Aluminum Eye Covers\n*Quick Release Bolt\n*11\" Micro Ported Barrel\n*Aluminum Clamping Collar Feedneck\n*3 Way Adjustable Magnetic Response \"Sabre\" Trigger\n*Recessed Dual Texture Grip Panels\n*High Impact Polymer Trigger Frame\n*Adjustable Inline Regulator\n*Standard Thread Vertical Adapter\n*Steel Braided Hose\n*External Velocity Adjuster", + "page_title" : "Spyder Fenix Ships Free at Zephyr Paintball", + "head_title" : "Spyder Fenix | 2012 Spyder Fenix Paintball Gun" + }, + ".markerupgrades.dye_dam_upgrades_and_accessories.dye_dam_repair_kits" : {}, + ".shop_by_brand.extreme_rage" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tEXTREME RAGE PAINTBALL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n", + "top_description2" : "=Extreme Rage, get your game on!=\n\nExtreme rage paintball offers some of the best intermediate and beginner guns on the market today! Take a look at the Extreme Rage ER3, arguably the best entry level gun in the sport. Try out any of Zephyr's selection of Extreme rage paintball guns and you are sure to find that you will be hooked from there. These guns are simple, strong and the best for those seeking to get into the sport. \n\n", + "head_title" : "Extreme Rage Paintball | Rage Extreme | Extreme Rage er3", + "description" : "=Extreme Rage, get your game on!=\n\n==The ER3==\nThe ER3 paintball marker is the perfect choice for the beginner paintball player. This marker is ready to shoot right out of the box, just plug a loader into the clamping feedneck, attach the air source and you're ready to rock-and-roll. Load in the paintballs and you'll hit your target every time with our accurate, aluminum barrel. The rugged construction will keep this gun firing long after others quit and the simple design allows for quick and easy maintenance. \n\n==Hoppers==\nExtreme rage hoppers are some of the best performing and best quality for price hoppers around! If you're not willing to invest in a very expensive hopper just yet, Extreme Rage will give you quality without cost. \n" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.colt_gas_airsoft_guns" : { + "meta_description" : "Colt Airsoft Guns - Buy your Colt Airsoft PistolAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Colt Airsoft Guns On Sale & Free Shipping", + "head_title" : "Colt Airsoft Guns | Colt Airsoft Pistol" + }, + ".shop_by_brand.hoven_sunglasses" : {}, + ".casual_clothing.mens_clothing.watches.oakley_watches" : {}, + ".harnessesbags.backpacks.fox_racing_backpacks_and_bags" : {}, + ".casual_clothing.mens_clothing.shirts.1_search_by_size.4_x-large" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_fixed_power_scopes.leapers_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markers.dangerous_power_paintball_guns.dangerous_power_rev_i_paintball_gun" : { + "meta_keywords" : "dangerous power rev-i, rev-i paintball gun, dp rev-i, revi paintball gun, dangerous power gun", + "meta_description" : "The Dangerous Power Rev-i paintball gun brings you the latest in technology with its user friendly OLED board, high performance barrels and light weight setup", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "prodlist1_header" : "Dangerous Power Rev I Paintball Guns", + "banner01_link" : "/category/3packagespecials.dangerous_power_paintball_packages/?sortby=zoovy:prod_name ", + "description" : "The Dangerous Power Rev-i paintball gun (pronounced Revy) represents the latest and greatest in technology by being one of the best innovative paintball guns on the market. Players have never been so in touch with their own Paintball gun till now; with its see through design for close attention to the o-rings and bolt, swiveling rake style to sling style adjustable trigger, pressure gauge located on the back of the gun and much more to impress. Taking a look internally we will find one of the best designed boards with a 35+ Balls Per Second capability. No need for dip switches; so don’t even think about opening your grips to change modes. The simplicity of the OLED board is astonishing, designed by APE; you get a user friendly interface that will not disappoint. The bolt is a one piece, one moving part design being light and efficient. It is also easily removable down the front of the barrel with just a few turns by a provided Allen Wrench. Experience being in control with every aspect of your gun weather it is adjusting the trigger, changing barrels and even programming the board to your specific needs.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n==Air efficiency?==\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n68ci 4500psi compressed air tank allows around 1000 shots\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n45ci 4500psi compressed air tank allows around 700 shots\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n==What Threads??==\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nYes, the Rev-I is [[Autococker]:url= http://www.zephyrpaintball.com/category/barrels.autococker/] compatible for your barrels of choice. What’s great about the Rev-i it already comes with an accurate two piece barrel that offers a 14” front & 16” front. Depending on which Paint you like to use it also comes with 3 barrel backs: .689, .685, .693\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n==High or Low Pressure?==\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[[Compressed Air]:url=http://www.zephyrpaintball.com/category/airsystems.nitrogentanks/] is a requirement. This gun will NOT work on CO2. The Rev-I operates on 150psi. High or Low pressure will both work fine on the Rev-i\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n==What about Maintenance?==\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nBeing durable and consistence in performance, opening the gun for maintenance will be rarely needed. Given something needs repairing or changing the manual included gives step by step instructions on everything that you will ever need to know how to do with your Rev-i. With incredible colored pictures the guide to complete dissemble has never been so easy\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n==What comes in the box?==\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nCustom leather case\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDP Barrel Cover\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nOwner’s Manual\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nReplacement o-rings\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDP-40 Lube\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nAllen Key Set\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nAluminum Bolt Window\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nDP Key Chain\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n14” & 16” Barrel Tip\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n3 Barrel Backs: .689, .685, .693", + "page_title" : "Buy Dangerous Power Rev Online On Sale Now", + "head_title" : "Dangerous Power Rev|I | Rev|I Paintball Gun, DP Rev|I Paintball Gun" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.30" : {}, + ".2clearance.clearance_upgrades.clearance_feednecks" : { + "head_title" : "Sale Paintball Feednecks | Clearance Paintball Feednecks | Paintball Feednecks Sale" + }, + ".casual_clothing.mens_clothing.tshirts.alien_workshop" : { + "meta_description" : "Alien Workshop T Shirts - Buy your Alien Workshop Tshirts At Zephyr Sports for Less Today! We carry a complete line of Alien Workshop Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Alien Workshop T Shirts @ Zephyr Sports", + "head_title" : "Alien Workshop T Shirts | Alien Workshop Tshirts | Alien Workshop Shirts" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_full_house_sunglasses" : { + "meta_keywords" : "Arnette Sunglasses, arnette polarized, arnette sunglass, Arnette Eyewear", + "meta_description" : "Arnette Sunglasses - Check out the Full House Arnette Sunglasses! Polarized Sunglasses! Arnette eyewear available @ Zephyr Sports!", + "head_title" : "Arnette Full House Sunglasses | Arnette Full House Polarized | Arnette Full House" + }, + ".airsoft.airsoft_safety.airsoft_goggles" : { + "meta_description" : "Airsoft Goggles - Buy your Airsoft Safety Goggles At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Goggles On Sale & Free Shipping", + "head_title" : "Airsoft Goggles | Airsoft Safety Goggles" + }, + ".shop_by_brand.defcon_tactical_gear" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns.hfc_gas_airsoft_guns" : { + "meta_description" : "HFC Airsoft Guns - Buy your HFC Airsoft Pistols At Zephyr Sports for Less Today! We carry a complete line of HFC Gas Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy HFC Airsoft Guns On Sale & Free Shipping", + "head_title" : "HFC Airsoft Guns | HFC Airsoft Pistols |HFC Gas Pistols" + }, + ".1newitems.2009_tippmann_gear" : {}, + ".3packagespecials.empire_paintball_packages.empire_bt.combat" : { + "head_title" : "Empire BT Combat Paintball Packages | Empire BT Combat Paintball Gun Packages" + }, + ".apparel.gloves.spyder_paintball_gloves" : { + "page_title" : "", + "head_title" : "Spyder Paintball Gloves | Gloves Spyder |Spyder Paintballing Gloves" + }, + ".harnessesbags.packs___harnesses.v-tac_paintball_harnesses___vests" : { + "meta_description" : "Valken V-Tac Paintball Harness - Buy your Valken V Tac Pod Belts Online at Zephyr Paintball for Less today. Free Shipping on Valken Vtac Paintball Pod Packs Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Valken V-Tac Paintball Harness Online On Sale Now", + "head_title" : "Valken V-Tac Paintball Harness | Valken V Tac Pod Belts | Valken Vtac Paintball Pod Packs" + }, + ".casual_clothing.womens_clothing.ladies_sunglasses.metal_mulisha_women_s_sunglasses" : {}, + ".maddog.spyder_upgrades.spyder_stocks" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_spencer_watches" : { + "meta_description" : "Nixon Spencer Watches - Buy your Nixon Spencer Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Spencer at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Spencer Watches", + "head_title" : "Nixon Spencer Watches | Nixon Spencer Watch | Nixon Spencer" + }, + ".markerupgrades.smartparts.impulse.triggers" : {}, + ".2clearance.skateboards.skateboard_trucks" : {}, + ".casual_clothing.mens_clothing.shirts.alpinestars_shirts___flannels" : { + "meta_description" : "Alpinestars Flannel Shirts - Buy your Alpinestars Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Alpinestars Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Alpinestars Shirts & Flannels Ship Free", + "head_title" : "Alpinestars Flannel Shirts | Alpinestars Polo Shirts | Alpinestars Shirts" + }, + ".airsoft.shop_by_brand.uhc" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_housing_watches" : { + "meta_keywords" : "Nixon watches,nixon tide watch,nixon watch,nixon Outsider watch,Outsider watch,nixon,mens watches,", + "meta_description" : "Nixon Watches - Brand New Nixon Outsider Watches on sale now @ Zephyr! The new Nixon Outsider watch showcases a host of features with all kinds of Tide information and other Specs! Pick up your Nixon Watch today and never as for the time again! ", + "page_title" : "Nixon Outsider Watch", + "head_title" : "Nixon Outsider Watches | Nixon Outsider Watch | Nixon Outsider" + }, + ".casual_clothing.mens_clothing.shirts" : { + "meta_description" : "Flannel Shirts - Buy your Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Mens Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Mens Flannel & Polo Shirts on Sale", + "head_title" : "Flannel Shirts | Polo Shirts | Mens Shirts" + }, + ".markerupgrades.tippmann.a5.tippmann_a5_paintball_gun_schematic" : { + "top_html_focus" : "\"\"", + "meta_keywords" : "tippmann a5 manual, tippmann a5 teardown, tippmann a5 parts, fix tippmann a5, tippmann a5 replacement parts", + "meta_description" : "Taken straight from the manual, this teardown for the Tippmann A5 is perfect for finding out exactly what part of your gun you need to replace.", + "page_title" : "Tippmann A5 Paintball Gun Teardown" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_wit_watches" : {}, + ".markerupgrades.smartparts.impulse.bolts" : {}, + ".markerupgrades.kingmanspyder.spyder_factory_repair_parts" : { + "meta_description" : "Spyder Repair Kits - Buy your Kingman Spyder Replacement Parts Online at Zephyr Paintball for Less today. Free Shipping on Spyder Parts Kit Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Repair Kits Online On Sale Now", + "head_title" : "Spyder Repair Kits | Kingman Spyder Replacement Parts | Spyder Parts Kit " + }, + ".casual_clothing.mens_clothing.hats.arbor_hats" : {}, + ".markers.azodin.azodin_ats_paintball_guns" : { + "meta_description" : "Azodin ATS Paintball Guns - Buy your Azodin ATS Painball Markers Online at Zephyr Paintball for Less today. Free Shipping on Azodin ATS Trust Zephyr for all your Paintball Needs", + "top_description" : "The Azodin ATS and ATS+ are Azodin's answer to scenario paintball. Same great internals from Azodin with a sweet tactical look. Both the Azodin ATS and Azodin ATS+ tactical paintball guns include the same internals with the only difference being looks. The Azodin ATS comes in either a digi camo or black aluminum body with black aluminum front grip, polymer grip frame, barrel, feedneck and asa. The Azodin ATs includes integrated picatinny rails across the top with polymer rails mounted on either side of the marker for additional attachments. The ATS includes a 12\" Spyder threaded tactical barrel. The Azodin ATS series uses a top cocking quick release delrin bolt with double ball detents to reduce chopping. The Azodin ATS operates on co2 or compressed air.\nThe Azodin ATS+ takes the features of the ATS and adds in an adjustable M16 style stock, front pistol grip as well as an aluminum shroud with with four picatinny rails for to attach anything your heart desires.", + "page_title" : "Buy Azodin ATS Paintball Guns Online On Sale Now", + "head_title" : "Azodin ATS Paintball Guns | Azodin ATS Painball Markers | Azodin ATS ", + "description" : "Be sure to check out all of our great Azodin ATS and azodin ATS+ packages that include everything you need to get on the field except air and paintballs. All of our co2 and air tanks ship empty to comply with DOT regulations." + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_headwear.smart_parts_clearance_headwear" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_barrels.bt_apex_paintball_barrels" : {}, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_consultant_sunglasses" : { + "meta_description" : "Anarchy Consultant Sunglasses - Zephyr Sports carries a complete line of Anarchy Consultant Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Consultant Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Consultant Sunglasses | Anarchy Consultant Sun Glasses" + }, + ".airsoft.airsoft_guns.aftermath_airsoft_guns" : { + "meta_description" : "Aftermath Airsoft Guns - Buy your Aftermath Airsoft At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Aftermath Airsoft Guns On Sale & Free Shipping", + "head_title" : "Aftermath Airsoft Guns | Aftermath Airsoft", + "description" : "" + }, + ".apparel.pants.smart_parts_paintball_pants" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.spitfire_headphones" : { + "meta_keywords" : "Spitfire Headphones,Spitfire Head Phones, Spitfire Audio", + "meta_description" : "Spitfire Headphones - Zephyr stock a complete line of Spitfire Head Phones. For the ultimate Audio experience buy your Spitfire at Zephyr Today", + "page_title" : "Spitfire Headphones with Free Shipping at Zephyr", + "head_title" : "Spitfire Headphones | Spitfire Head Phones" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_discreet_womens_sunglasses" : { + "meta_keywords" : "Oakley Discreet Womens Sunglasses,Discreet Womens oakley sunglasses,oakley Discreet Womens, Discreet Womens polarized sunglasses", + "meta_description" : "Oakley Discreet Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Discreet Womens and Polarized Oakley Discreet Womens Sunglasses on Sale! ", + "page_title" : "Oakley Discreet Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Discreet Womens Sunglasses | Discreet Womens Oakley Sunglassses" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_corporal_watches" : {}, + ".shop_by_brand.valken" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tVALKEN PLAYER'S APPAREL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tVALKEN PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          ", + "meta_description" : "Valken Paintball - Zephyr Sports carries a complete line of Valken Pants At the lowest prices on the web with free shipping and easy returns. Buy your Valken Jersey Online Today.", + "top_description2" : "=Valken, Everything Paintball=\n\nValken paintball has been creating clothing for Woods ball and tournament ball for a long time now, and it shows. They've evolved from a company that was primarily based in paint to a company that has moved into clothing, protective gear, and harnesses. Valken is one of the most competitive Paintball industries on the market today because of their pride in craftsmanship and their wide selection on overall awesome products. You'll definitely want to check out the whole line of Valken Products while you are on Zephyr including; Valken pants, Valken Jerseys, Valken Paintballs, and Valken protective equipment. And when you have all your new Valken stuff, get out in that field and play the best game of Paintball you ever have!\n", + "page_title" : "Valken Paintball On Sale Free Shipping", + "head_title" : "Valken Paintball | Valken Pants | Valken Jersey", + "description" : "=Valken, everything paintball=\n\n==Dedication, It's what Valken does==\n\nAt Valken, dedication is nothing less than complete customer satisfaction while striving to maintain a healthy growth for the sport of Paintball in a positive, productive way. That means producing the highest quality products at fair and competitive prices. That means becoming the number one paintball product specialist. That means maximizing experiences for the people Valken caters to; you. By combining years of experience and knowledge with a unique, raw edge and toughness, Valken brings to the sport of paintball a freshness that has been sorely lacking these past few years. By combining years of experience and knowledge with a unique, raw edge and toughness, Valken brings to the sport of paintball a freshness that has been sorely lacking these past few years. The past few years have been tremendous for us here at Valken and the response from dealers and players alike has only further served to embolden us for the future. Valken continues to perfect their product model to help the player now and in the future. Valken is growing and looking forward to serving the paintball community for years and years to come.\n\n\n==V-max, evidence of pride==\nNew technology went into the V-max Paintball loader, which boasts up to 30+ balls per second, a super light weight, tool-less dis-assembly, and one-touch on and off switch with LED display. Check out these hoppers today, and soon you will be the most feared player on the field. \n\n==V-tac, A new way to wear==\nThis V-tac material is breathable, lightweight, available in an assortment of prizes, and adjustable. The V-tac series took our years of experience designing tournament paintball gear and combined them with modern military technologies and rugged mil-spec materials to create the ultimate scenario paintball line: V-TAC.\n\nThe result is innovations the woodsball world has never seen. Our gear resembles traditional BDU's but performs to the level of high-end tournament gear and beyond. We offer the largest variety of the most popular camo patterns (ACU, MARPAT, Tiger Stripe, V-Cam, Tactical, & Woodland). No proprietary camo here. This means that you won’t get stuck with camouflage that doesn’t match the rest of your gear.\n\n==Valken protective Equipment==\nProtect yourself with Valken's full line of protective equipment that includes Chest protectors, Body Armour, Slide shorts, elbow and knee pads, gloves and even neck guards. Most pads are made with high quality impact foam that absorbs the shock of the paintball and recoils it, so you only feel pressure. No more nasty bruises from Tournaments! Pads are made from Neoprene, breathable mesh, moisture wicking cloth and are anatomically fitted to pre-fit your arms, legs, torso, or whatever!\n\n==Paint==\nValken makes the world's most popular paint with six brands to choose from Redemption, Graffiti, Crusade, Breach, fate, zing and Infiniti. All of these are high quality, brittle shelled paint that breaks reliably on the target for when you are out with your friends, or out in a high stakes tournament. The paint is bright and thick, so when it breaks on your target there will be no misconception that they are OUT! \n\n\n" + }, + ".markerupgrades.smartparts.impulse" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "add2_link" : "/category/markerupgrades.feednecks.impulse_ion_sft_feednecks/", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".airsoft.airsoft_batteries___chargers.peq_boxes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airoft PEQ Boxes | PEQ Battery Boxes | Tactical Airsoft Batteries" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_the_ride_watches" : { + "meta_keywords" : "Nixon watches,nixon The Ride watch,nixon watch,nixon The Ride chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon The Ride Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon The Ride Chrono Watches", + "head_title" : "Nixon The Ride Watches | Nixon The Ride Chrono Watch | Nixon 5130" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_hop_up" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Hop up airsoft | Airsoft hop up | Hop up airsoft guns" + }, + ".skateboard_gear.skateboarding_videos.blind_skateboard_videos" : { + "meta_description" : "Blind Skate Videos - Zephyr Sports carries a complete line of Blind Skateboard Videos At the lowest prices on the web with free shipping and easy returns. Buy your Blind Skate Boarding Videos Online Today.", + "page_title" : "Blind Skate Videos On Sale Free Shipping", + "head_title" : "Blind Skate Videos | Blind Skateboard Videos | Blind Skate Boarding Videos" + }, + "$homepage_products" : {}, + ".casual_clothing.womens_clothing.ladies_t_shirts.1-search_by_size.5_x-large_ladies_t_shirts" : {}, + ".casual_clothing.mens_clothing.tshirts.electric_t_shirts" : { + "meta_keywords" : "Electric T Shirts,Electric shirts,free shipping,Electric TShirt", + "meta_description" : "Electric T Shirts - Zephyr carries a complete line of Electric Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Electric T Shirts at Zephyr", + "head_title" : "Electric T Shirts | Electric Shirts | Electric TShirt" + }, + ".paintballs.rrison_paintballs" : { + "htmlvids" : "\n\n\n", + "top_description2" : "", + "zoovy:banner01" : "banners/paintball/headers/rrison_header.jpg", + "description" : "== RRison Paintballs ==\n\nRRison Paintball was established in 2012 in the golden foothills of Livermore, ca. They are a young company looking to make a positive impact on the sport, while always keeping the player in mind. Simply, offering customers the highest quality ball you can get for the price you pay. By using top quality ingredients we can give you a ball with greater accuracy, a truer trajectory, thick fill, and better break. RRison is run by players that play tournament, rec ball, and woodsball. This means we know what kind of paint you would want for each situation, and have a good understanding of what characteristics make a great paintball. No matter what style you play, or what level you play at, we have the top quality ball for you . Rrison is “The all American paintball” and “Americas premiere practice paint for teams.” RRison Paintball is one of the only paintball manufacturers that are still truly made in America. Support your local paintball. Support the USA. RRison Paint features 3 grades: The Force, Haze, & Pure! Pick up a box and let us know what you think!\n\n\n= The Force: =\nField-Basic Grade. 100% PEG. Two tone shell with a bright fill. Force offers foliage penetration with maximum breakability. This is a virgin material ball unlike most other rec.field grade paintballs. Virgin materials allow us to offer players an overall superior paintball that is rounder, more accurate,, with better markability, and less barrel breakage which makes for a better experience. Works well in all weather conditions above 40 degrees Fahrenheit. Great ball for Tactical, Woodsball, and Rec ball. Works well in mag fed guns.\n\n\n= Rrise: =\nField-Basic Grade. 100% PEG. One tone shell with a bright fill. RRise offers foliage penetration with maximum breakability. This is a virgin material ball unlike most other rec.field grade paintballs. Virgin materials allow us to offer players an overall superior paintball that is rounder, more accurate,, with better markability, and less barrel breakage which makes for a better experience. Works well in all weather conditions above 40 degrees Fahrenheit. Great ball for Tactical, Woodsball, and Rec ball. Works well in mag fed guns.\n\n\n= Haze: =\nHigh quality paintball designed for Competition, Scenario, Speedball, and Rec ball. With a premium thick, bright, hard to wipe fill, even the worst referee can't miss it! Haze's superior round shell offers the best trajectory and long range breakability with extreme accuracy. RRison paintballs are made for precision performance using only the highest quality materials. Haze works well in all marker types in a dry or wet weather conditions above 40 degrees Fahrenheit. \n\n\n= Pure =\nWhen an edge is what you want, Pure is what you need. Pure is made from the highest quality materials to give you the performance you demand. Advanced encapsulation technique molds a high quality shell with a scented thick \"no wipe\" fill, that delivers truer trajectory with maximum breakability and unchallenged accuracy. Great for tournament, practice, speedball, and pump! 100% PEG. Pure Accuracy. Pure Adrenaline. Pure Addiction." + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.empire_all_star_paintballs" : {}, + ".airsoft.buyers_guide.airsoft_rifles" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Buyers Guide - Airsoft Rifles and AEG's" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_pants.invert_clearance_paintball_pants" : {}, + ".shop_by_brand.airsoft_innovations" : {}, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests.defcon_gear_tactical_vests" : {}, + ".markerupgrades.smartparts.ion_xe_upgrades.ion_xe_bolts" : {}, + ".markers.cci_paintball_guns" : { + "meta_keywords" : "CCI Paintball Guns,Phantom Pump Paintball Guns,CCI Phantom Pump Paintball,paintball gear,paintball equipment,cci paintball,pump paintball,stock class,", + "meta_description" : "CCI Phantom Pump Paintball - Pump Paintball is a whole game in itself! Get in the game with CCI Pump Paintball Guns! Showcase your own skill by playing pump paintball! Affordable CCI Paintball gear in stock and ready to ship out! Showcase your skill by playing pump with CCI Phantom Pump Paintball Guns!", + "page_title" : "Buy CCI Paintball Guns Online On Sale Now", + "head_title" : "CCI Paintball Guns | Phantom Pump Paintball Guns | CCI Phantom Pump Paintball", + "sortby_var" : "CCI Pump Type", + "prodlist1_header" : "", + "description" : "==Pump Paintball is a whole game in itself! Feel the power of pump now with CCI Phantom Pump Paintball Guns!==\n\n\nThe Phantom is a .68 caliber, pump action CO2 powered gun designed to fire paintballs at 200 to 300 fps (feet per second) as accurately as possible to mark the aiming point with the splat of a paintball. \n\n\nThe Phantom cocks and loads a paintball when the pump is pulled fully back and returned to its full forward position. Squeezing the trigger releases the hammer striking the power tube allowing a blast of CO2 to fire a paintball. The design of the trigger firing mechanism allows a rapid fire capability. With constant pull on the trigger, the gun fires with each pump action. \n\n\nOver the years CCI has changed and improved their product and now offer various configuration and colors of The Phantom pump action paintball guns. All pump action guns can be converted from gravity feed to stock class configuration. \nStock Class showcases the skill of the player and structures the play to a more sportsman like game. \n\n\nStock Class is a specific configuration that has the feed tube parallel to the breech requiring a tilting to load a paintball ( rock and cock). The stock class paintball gun is power by a single 12 gram CO2 powerlet that is held in place by a knob or housing that has to be completely removed to change the 12 gram powerlet. \n" + }, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_status_sunglasses" : { + "meta_description" : "Anarchy Status Sunglasses - Zephyr Sports carries a complete line of Anarchy Status Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Status Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Status Sunglasses | Anarchy Status Sun Glasses" + }, + ".airsoft.airsoft_bbs_ammo.35_and_larger_sniper_airsoft_ammo" : { + "meta_description" : "Sniper Airsoft Ammo available at Zephyr Sports. When you play sniper, you need a BB designed just for your style of play. Sniper Airsoft Ammo is available from multiple vendors in .35 Gram and larger sizing.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Sniper Airsoft BB's | .40 BBs for Airsoft Sniper | Heavy Weight Airsoft BB .36" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.dc_pants_and_jeans" : { + "meta_description" : "DC Pants - Buy your DC Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DC Pants & Jeans Ship Free", + "head_title" : "DC Pants | DC Jeans" + }, + ".airsoft.slingshots.slingshot_ammo" : { + "meta_keywords" : "sling shot ammo, slingshot ammo, steel balls, palco sports ammo, palco sports slingshot, white marbles, palco sling shot", + "meta_description" : "Don’t forget to grab a bag or two! Steel balls are the most accurate type of slingshot ammo due to the symmetrical structure. White marbles are also a great selection for their “tracer” ability. The light reflects off the ball making it easy to see the ammo fly through the air and hit your target dead on! These types are also completely reusable. ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_pants" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.aeg_drum_and_box_mags" : {}, + ".airsoft.airsoft_guns.vegas_force_airsoft_guns" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "description" : "" + }, + ".2clearance.1-black_friday" : { + "zs11_banner_wslideshow_slide1" : "ALT=2012+Sly+Paintball+Gear+BLOWOUT%21%21%21+SAVE+25%25+OFF%21&IMG=black_friday%2fslideshows%2f1353612118__1_sly_25off_slideshow%2ejpg&LINK=%25SESSION%25%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3d2012%2bsly%26x%3d0%26y%3d0", + "top_description" : "==BLACK FRIDAY==\n\nLoads of discounted items! Take a look at some of the highlights this year...\n\n", + "zoovy:banner01" : "", + "zs11_banner_wslideshow_slide3" : "ALT=Save+%2450+on+Selected+Dye+Rotor+Hoppers%21%21&IMG=black_friday%2fslideshows%2f1353611802__bf_dye_rotor_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2floaders%2edye_paintball_loaders%2f%3fsortby%3dzoovy%253Abase_price%26size%3d", + "zs11_banner_wslideshow_slide4" : "ALT=SAVE+on+Planet+Eclipse+EVX+Jerseys%21%21&IMG=black_friday%2fslideshows%2f1353611918__eclipse_evx_jerseys_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2fapparel%2ejerseys%2eplanet_eclipse_paintball_jerseys%2f", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "zs11_banner_wslideshow_slide5" : "ALT=Dangerous+Power+G4+on+SALE+NOW%21&IMG=black_friday%2fslideshows%2f1353613594__dangerous_powerg4%2ejpg&LINK=%25SESSION%25%2fcategory%2fmarkers%2edangerous_power_paintball_guns%2edangerous_power_g4_paintball_guns%2f", + "head_title" : "Black Friday Paintball Sale | Paintball Black Friday", + "sortby_var" : "Sport", + "zs11_banner_wslideshow_slide2" : "ALT=Planet+Eclipse+EGO+PRICE+DROP%21%21%21+Save+%24250%21&IMG=black_friday%2fslideshows%2f1353611822__bf_ego11_price_drop%2ejpg&LINK=%25SESSION%25%2fcategory%2fmarkers%2eplanet_eclipse_ego_paintball_guns%2eeclipse_ego_11_paintball_guns%2f" + }, + ".skateboard_gear.skateboard_longboards.lax" : { + "meta_description" : "LAX Longboards - Zephyr Sports carries a complete line of LAX Longboard Skateboards LAX Skateboards Longboards At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "LAX Longboards On Sale Free Shipping", + "head_title" : "LAX Longboards | LAX Longboard Skateboards LAX Skateboards Longboards" + }, + ".casual_clothing.womens_clothing.ladies_dresses" : {}, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.d_x-large" : {}, + ".airsoft.shop_by_brand.umarex_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Umarex | airsoft umarex | Umarex air guns" + }, + ".casual_clothing.mens_clothing.jackets.alpinestars_jackets" : { + "meta_description" : "Alpinestars Jackets - Buy your Alpine Stars Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Alpinestars Jackets with Free Shipping", + "head_title" : "Alpinestars Jackets | Alpine Stars Jackets" + }, + ".snowboard_gear.snowboard_goggles" : { + "meta_keywords" : "oakley goggles,vz goggles,snowboard goggles,goggles oakley,vonzipper goggles,goggles von zipper,von zipper fenom,porkchop goggles,sizzle von zipper,von zipper dojo, bushwick goggles, Spy goggles,oakley a frame,spy snowboard goggles", + "meta_description" : "Snowboard Goggles available at Zephyr Sports - Huge selection of snowboard goggles from Von Zipper, Spy, Oakley, Dragon and more. Get your snowboard goggles at Zephyr Today with Free Shipping over $75", + "page_title" : "Snowboard Goggles On Sale & Free Shipping", + "head_title" : "Snowboard Goggles | Von Zipper Goggles | Oakley Goggles" + }, + ".airsystems.tankcovers.valken_bottle_covers" : { + "meta_description" : "Valken Cover - Buy your Valken Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Valken Paintball Bottle Cover Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Valken Cover Online On Sale Now", + "head_title" : "Valken Cover | Valken Tank Cover | Valken Paintball Bottle Cover" + }, + ".casual_clothing.mens_clothing.sweatshirts.bones_sweatshirts" : { + "meta_description" : "Bones Sweatshirts - Buy your Bones Hoodies At Zephyr Sports for Less Today! We carry a complete line of Bones Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Bones Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Bones Sweatshirts | Bones Hoodies | Bones Hoody" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_glory_days_sunglasses" : {}, + ".casual_clothing.womens_clothing.ladies_t_shirts.arbor" : {}, + ".markers.viewloader_paintball_guns" : { + "banner1" : "banners/categories/guns/viewloader_banner.jpg", + "meta_description" : "Viewloader Paintball Guns - Buy your Viewloader Paintball Marker Online at Zephyr Paintball for Less today. Free Shipping on Vl Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Viewloader Paintball Guns Online On Sale Now", + "head_title" : "Viewloader Paintball Guns | Viewloader Paintball Marker | Vl Paintball Guns" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_undercover_sunglasses" : { + "meta_description" : "Arnette Undercover Sunglasses - Zephyr Sports carries a complete line of Undercover Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Undercover Sun Glasses Online Today.", + "page_title" : "Arnette Undercover Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Undercover Sunglasses | Undercover Arnette Sunglasses | Arnette Undercover Sun Glasses" + }, + ".snowboard_gear.snowboard_goggles.z_snow_goggle_cases" : { + "meta_description" : "Snow Goggle Cases - Buy your Snowboard Goggle CaseAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Snow Goggle Cases Now! On Sale & Free Shipping", + "head_title" : "Snow Goggle Cases | Snowboard Goggle Case" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.crosman_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".shop_by_brand.umarex" : { + "meta_description" : "Umarex Airsoft - Zephyr Sports carries a complete line of Umarex H&K At the lowest prices on the web with free shipping and easy returns. Buy your Umarex .22 Online Today.", + "top_description2" : "Umarex... there is no one in the airsoft or air rifle world that doesn't know that name. Umarex and Umarex USA Inc. have become one of the most popular and recognizable brands in the business. Umarex Airsoft has become a global superpower with it's exclusive license for H&K (Heckler & Koch) products, which are some of the most popular gun styles in the world. Umarex boasts that it has the perfect sporting arms for any customer, and well... when you look at the variety of exceptional products that they offer. You can't help but agree with them. \n\n\n=Umarex...The Home Of Shooting Since 1972=", + "page_title" : "Umarex Airsoft On Sale Free Shipping", + "head_title" : "Umarex Airsoft | Umarex H&K | Umarex .22", + "description" : "Umarex USA, Inc. began with the Umarex Group’s acquisition of RUAG Ammotec USA (Dynamit Nobel), North American marketers of the famous RWS brand of premium adult airguns. Later named Umarex USA and combined with the world class products from German based Umarex, the parent company of Walther Firearms, Umarex USA has quickly become one of the premier providers of airguns and airgun accessories to North America.\n\n\n==Umarex USA... Zeroed In==\n\n\nDesigning, developing, and marketing sport shooting products under the RWS, Walther, Hämmerli, Beretta, Colt, Smith & Wesson, H&K, Ruger, Browning, Makarov, Tactical Force, Magnum Research, and Combat Zone brands, Umarex USA offers world-class products for multiple product categories including adult airguns and air rifles, BB and pellet pistols, Umarex airsoft guns, specialized airgun optics, performance airgun ammunition, airgun accessories, tactical training paintball guns and small bore firearms including Colt .22 Tactical Rimfire rifles and 1911 pistols, HK .22 rifles, and RWS premium .22 rimfire ammunition.\n\n\nUmarex USA moved into a new 117,000 square foot facility in July of 2010, located at Chaffee Crossing in Fort Smith, Arkansas. The new facility is home to its warehousing and distribution operations as well as its corporate offices, which include marketing, sales and a fully staffed customer service department that handles product refurbishment, warranty work and technical advice. Future operations at this facility will also include manufacturing." + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_highwire_25_hydration_packs" : {}, + ".apparel.shoes.1_search_by_color" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.1_-von_zipper_frosteez_collection" : {}, + ".shop_by_brand.ray_ban" : { + "top_description2" : "=Ray Ban Sunglasses, Classic.= \n\nEveryone knows the difference between ray-ban and the rest. Ray-Ban's are genuinely high quality product that have been around for an incredible 70 + years. When you buy ray ban, you are getting a product high in quality and high in technology. Because these glasses have been around so long they have a feel to them that can only be acquired through age. Like fine wine, Ray Ban Eye wear never exudes an elegance that can only be described as timeless. ", + "head_title" : "Rayban Sunglasses | Ray Ban Sunglasses | Ray Ban Eyewear", + "description" : "=Ray Ban, Classic=\n\n==History==\nRay-Bans were first created in 1936. The idea of Ray Bans began some years earlier when Lieutenant John A. Macready returned from a balloon flying adventure and complained that the sun had permanently damaged his eyes. He contacted Bausch & Lomb asking them to create sunglasses that would provide protection and also look elegant. On May 7, 1937, Bausch & Lomb took out the patent. The prototype, known as Anti-Glare, had an extremely light frame weighing 150 grams. They were made of gold-plated metal with green lenses made of mineral glass to filter out infrared and ultraviolet rays. Pilots in the United States Army Air Corps immediately adopted the sunglasses and Ray-Ban was born.\n\n==Lenses==\nRay Ban has created a number of different lenses for each of their glasses. Each of the lenses are equipped with their own form of technology to suit every life style. The High Contrast Brown Lenses are made for a military design that allows for the maximum amount of clarity and protection. These lenses are made to block out blue light and most commonly used for driving and action sports. The Neutral Grey lenses are recommended for reduced eye strain and to see color as it truly is. Polarized lenses were created to reduce the amount of reflected light into your eyes. Lastly, Light Adaptive lenses are designed to adjust to all different amounts of light. The lenses will turn dark when excessive light is present and lighter when there is not as much light.\n\n\n==Frames==\nRay Ban has two primary types of frames available. The first is a titanium frame that is comfortable and flexible to wear. Secondly, there is the Memo-Ray frame. This frame is studier and more durable. It is designed for all types of activity." + }, + ".markerupgrades.tippmann.model98customandpro.tippmann_98_expansion_chamber_and_grips" : { + "prodlist1_header" : "Tippmann Custom 98 Expansion Chambers & Grips" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_barrels.deadlywind_carbon_fiber_barrels" : {}, + ".casual_clothing.womens_clothing.ladies_hats.dakine_ladies_hats" : {}, + ".casual_clothing.mens_clothing.shirts.neff_shirts" : { + "meta_description" : "Neff Flannel Shirts - Buy your Neff Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Neff Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Neff Shirts & Flannels Ship Free", + "head_title" : "Neff Flannel Shirts | Neff Polo Shirts | Neff Shirts" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_resevoirs_and_accesories_" : { + "meta_description" : "Camelbak Hiking Packs - Buy your Camelbak Day PacksAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Hiking Packs On Sale & Free Shipping", + "head_title" : "Camelbak Hiking Packs | Camelbak Day Packs" + }, + ".airsoft.buyers_guide" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Paintball and Airsoft Buyers Guide" + }, + ".harnessesbags.packs___harnesses.bt_tactical_vest___accesories" : { + "meta_keywords" : "bt tactical vest, bt paintball vest, camo paintball vests, paintball vests, bt camo paintball vests, tactical vests, bt vest, camo vest ", + "meta_description" : "BT Tactical Vest - Buy your BT Paintball Vests Online at Zephyr Paintball for Less today. Free Shipping on Camo Paintball Vests Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy BT Tactical Vest Online On Sale Now", + "head_title" : "BT Tactical Vest | BT Paintball Vests | Camo Paintball Vests" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.bt_delta_elite_paintball_guns" : {}, + ".harnessesbags.backpacks.ogio_backpacks.ogio_backpacks" : { + "meta_keywords" : "Ogio Backpacks, Ogio Back Packs, Ogio packs, Ogio bags,Ogio backpack,Ogio pack,travel bags,Ogio Laptop Bag, Ogio Laptop Backpack", + "meta_description" : "Zephyr Sports is a leading distributor of Ogio Backpacks! Ogio Back Packs are top quality travel bags with more than enough space for all your stuff! Carry your stuff in style with Ogio packs! All Ogio bags are made from durable materials able to withstand the toughest of travels! Grab your Ogio Backpack today and get a move on!", + "page_title" : "Ogio Backpack On Sale & Free Shipping", + "head_title" : "Ogio Backpack | Ogio Bags | Ogio Backpacks" + }, + ".casual_clothing.mens_clothing.beanies.arbor_beanies" : { + "meta_keywords" : "Arbor beanie,Arbor hat,Arbor beanies,Arbor caps,Arbor 686,Arbor headwear,Arbor cuff visor beanie,Arbor beanie hat,Arbor visor beanie,Arbor visor beanies", + "meta_description" : "Arbor Deanie - Surf style with Arbor Beanies available now at Zephyr Sports. Get your Arbor hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Arbor Beanies on Sale at Zephyr Today", + "head_title" : "Arbor Beanie | Arbor Hat | Arbor Beanies" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses", + "meta_description" : "Oakley Polarized Sunglasses now available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Jacket Sunglasses, Oakley Antix Sunglasses, Oakley Ballistic Sunglasses, Oakley Eyepatch Sunglasses, Oakley Fives Squared Sunglasses, Oakley Flak Jacket Sunglasses, Oakley Gascan Sunglasses, Oakley Hijinx Sunglasses, Oakley Inmate Sunglasses, Oakley Monster Dog Sunglasses, Oakley Monster Pup Sunglasses, Oakley Oil Rig Sunglasses, Oakley Radar Pitch Sunglasses, Oakley Sideways Sunglasses, and Oakley Straight Jacket Sunglasses on sale! ", + "page_title" : "Oakley Polarized Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Polarized Sunglasses | Oakleys Sunglasses | Oakley Jacket Sunglasses" + }, + ".casual_clothing.mens_clothing.shirts.fmf_shirts_and_flannels" : {}, + ".markers.gog_paintball_guns.gog_enmey_paintball_guns" : { + "meta_description" : "GOG eNMEy Paintball Guns - Gog has just release the eNMEy. An entry levelk paintball gun priced about $150. With features of much more expensive guns, the GOG eNMey paintball marker will be the new standard in entry level paintball guns", + "top_description" : "", + "page_title" : "GOG eNMEy Paintball Guns at Zephyr Paintball", + "head_title" : "GOG eNMEy Paintball Guns | GOG Enemy Paintball Markers | GOG eNMEy", + "description" : "==Keep your friends close, but your eNMEy closer.==\n\nGOG Paintball will be unveiling the all-new eNMEy paintball marker at the 2012 PSP Paintball World Cup. Featuring an integrated regulator and pneumatic spool valve combined with an entry-level price tag, the eNMEy is poised to deliver better performance to new players and improved reliability with reduced maintenance to field owners.\n\n\nIn 1995 paintball technology was redefined by the release of the Shocker electro-pneumatic paintgun. In 2005, the Ion re-defined the paintball marketplace by bringing the tournament level performance of an electro-pneumatic paintgun into the price range of the average paintball player. Now, the creative minds behind the Shocker and Ion are changing the face of paintball again with the eNMEy.\n\n\nThe benefits of a spool valve design have been well known to tournament paintball players for years. Now GOG PaintballTM is excited to build this technology into a paintball marker within the reach of a first-time player.\n\n\n\"From the beginning, we've focused on giving the player more value for their investment in the game,\" says GOG's Adam Gardner. \"You really have to shoot the eNMEy to see why we're so excited. The pneumatic trigger we've designed has a pull that is short, crisp and fast, so the marker shoots smooth as silk. This is a whole new level of performance for this price range. People just don't expect a marker that isn't electronic to shoot this well.\"\n\n\n=eNMEy Features:=\n* True Pneumatic Design - No hammer, no sear, no metal-on-metal wear points - for field rental use, there are no batteries to worry about.\n* Regulated Low Pressure Operation – A vertical regulator stabilizes gas pressure for consistent operation. Running at 160 psi nominal, the eNMEy is consistent and smooth with little to no recoil.\n* CO2 Compatible - An integrated relief valve completely protects the valve components from pressure spikes associated with liquid CO2.\n* Spool Valve Design - This tournament proven system delivers both speed and accuracy.\n* Simple Maintenance - The eNMEy's main valve and bolt can be removed, cleaned, inspected and reassembled in seconds.\n* Low-Force Anti-Chop - The low force behind the eNMEy's bolt allows it to bounce back from mis-fed paintballs, reducing the chance of a break in the breech.\n* Composite/Aluminum Components - With a machined aluminum receiver under a protective polymer shell, the eNMEy is both lightweight and durable.\n* Lifetime Warranty to original purchaser - Enough Said. We want you to be confident in your purchase. Some restrictions and exclusions apply. See warranty for details.\n* Electropneumatic Upgrade Path - Not to be confused with \"sear tripper\" electronic grip frames for hammer-and-spring paintball markers, the optional eNMEy electronic trigger upgrade provides true electropneumatic operation for increased rates of fire, more firing modes and an even lighter trigger pull." + }, + ".casual_clothing.mens_clothing.hats.blind_hats" : { + "meta_keywords" : "Blind Hats,Blind caps,Blind baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Blind Hats - Zephyr carries a complete line of Blind Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Blind", + "page_title" : "Blind Hats on Sale at Zephyr", + "head_title" : "Blind Hats | Blind Caps | Blind Baseball Hats" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.polar_watches" : { + "meta_keywords" : "Polar watches,Polar watch,time teller,watches Polar", + "meta_description" : "Polar Watches - Zephyr Carries a complete of watches from Polar. Get your Polar watch today with free shipping at Zephyr Sports. From the Player to the Time Teller we have you covered", + "page_title" : "Polar Watches Free Shipping at Zephyr Sports", + "head_title" : "Polar Watches | Polar Watch | Watches Polar" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_time_teller_p_watches" : { + "meta_keywords" : "nixon watches,nixon time teller,nixon time teller p,nixon time-teller p,nixon,nixon watch,mens watch,mens watches,nixon time-teller,nixon", + "meta_description" : "Nixon Watches - Brand New Nixon Time Teller P Watch @ Zephyr. Nixon Time-Teller P Watches keep life simple. Basic analog features! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Time Teller P Watch", + "head_title" : "Nixon Time Teller Watches | Nixon Time Teller Watch | Nixon Time Teller" + }, + ".safetygear.proto" : {}, + ".casual_clothing.mens_clothing.shorts.sullen_shorts" : { + "meta_description" : "Sullen Shorts - Buy your Sullen Board ShortsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Sullen Shorts with Free Shipping at Zephyr", + "head_title" : "Sullen Shorts | Sullen Board Shorts" + }, + ".misc_items.water_bottles" : {}, + ".casual_clothing.mens_clothing.belts.billabong_belts" : { + "meta_description" : "Billabong Belts - Buy your Billabong Mens Belts At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on BILLABONG BELTS @ Zephyr Sports", + "head_title" : "Billabong Belts | Billabong Mens Belts | Belts Billabong" + }, + ".apparel.shoes.1search_by_size" : {}, + ".airsoft.airsoft_guns.leapers_utg_airsoft_guns" : { + "meta_description" : "UTG Airsoft Guns - Buy your UTG Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of UTG AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy UTG Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "UTG Airsoft Guns | UTG Airsoft Rifles | UTG AEG" + }, + ".markerupgrades.bt_designs_upgrades.bt_paintball_foregrips" : {}, + ".apparel.shoes.1_search_by_color.white_mens_shoes" : {}, + ".casual_clothing.mens_clothing.shoes.srh_shoes" : { + "meta_description" : "SRH Skate Shoes - Buy your SRH ShoesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "SRH Shoes Ship Free at Zephyr Sports", + "head_title" : "SRH Skate Shoes | SRH Shoes" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.enjoi_youth_sweatshirts" : {}, + ".casual_clothing.z_unisex_clothing_accesories.cell_phone_cases.incase_cell_phone_cases" : { + "meta_description" : "InCase Phone Cases - Buy your InCase Iphone CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "InCase Phone Cases", + "head_title" : "InCase Phone Cases | InCase Iphone Cases" + }, + "$co2_bottles" : {}, + ".casual_clothing.womens_clothing.accessories.audio___headphones" : {}, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_canoes_sunglasses" : { + "meta_description" : "Maui Jim Canoes Sunglasses - Zephyr Sports carries a complete line of Maui Jim Canoes Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Canoes Online Today.", + "page_title" : "Maui Jim Canoes Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Canoes Sunglasses | Maui Jim Canoes Sun Glasses | Sunglasses Maui Jim Canoes" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.70_oz_mountain_bike_hydration_packs" : {}, + ".airsystems.nitrogentanks.wgp_nitrogen_tanks" : {}, + ".apparel.head_bands_and_wraps.contract_killer_head_bands___wraps" : {}, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_voodoo_sunglasses" : {}, + ".shop_by_brand.classic_army" : { + "meta_keywords" : "classic army,classic army airsoft,classic army airsoft guns,g36,g36k,mp5k,sa58,steyr aug,aug a2,dragunov", + "meta_description" : "Classic Army - Classic Army Airsoft Guns are some of the highest quality and most upgradeable guns in airsoft today. Zephyr carries a complete line of classic army Guns and gear", + "top_description2" : "=Destroy the Competition with Classic Army=\n\nClassic army has been engineering and manufacturing Airsoft guns for an impressive 12 years. Their product never ceases to amaze either. This company is one of the best and highest rated companies for the manufacturing of Airsoft weapons ever. Classic Army Airsoft guns will be reliable, functional, dependable, and look and feel just like the real thing. Classic army will keep you in the game no matter the conditions. They have a weapon for your every need, whether it be an M24 SOCOM sniper rifle or a fully automatic Steyr Aug. You will kill as soon as you pick one of these things up. ", + "page_title" : "Classic Army Airsoft Ships Free at Zephyr", + "head_title" : "Classic Army | Classic Army Airsoft Guns", + "description" : "=Destroy the Competition with Classic Army=\n\n==Choosing Classic Army==\n\nClassic Army began as a company with a vision to create an affordable, and high quality AEG system with the best full metal bodies available worldwide. Today, they are a huge player in the Airsoft world with multiple licenses from real steel producers like Arsenal, Armalite, B&T, Steyr, and Schwaben Arms to produce airsoft replicas that look and feel just like the real thing. Classic Army's ever expanding inventory encapsulates all ranges of airsoft enthusiasts from beginners to Veterans. Classic Army provides a dedicated workforce that offers total performance with the highest quality product that can be created. Classic army is a company that listens to it's customers and innovates depending on what the customers want. With multiple new technoloogies and features, Classic Army has something for everyone. \n\n==Full Metal Bodies==\nClassic Army believes in a solid base for their guns, and that why they choose top use manufactured steel, aluminum and alloys for all of their products from AEG's to pistols and rifles. Their Full Metal bodies are some of the most durable and damage resistant bodies on the planet. \n\n==Highest Quality Motors==\nFrom Motors to strings and gears, Classic Army spares no though when thinking about performance. These Guns CRANK. In the motors the Magnets are extremely strong, the pinion rotation is unbelievably smooth, and overall craftsmanship around the terminals and brushes is exceptional.\n\n==Superior Gearboxes==\nFor high powered guns, these gearboxes preform like no other. These metal gearboxes are for the high performing weapons, where guns are shooting at ranges of above 450 FPS. These are designed to be abused, but they are also so tough they don't even care. With high quality pistons and reinforced casing around the cylinder head, you can drop whatever spring you want in here and they will rip. \n\n==Every accessory, Ever==\nAdaptors, barrels, flash hiders, bolt catches, bipods, battery accessories and adaptors, mags, cylinders, eye wear, handguards, grips and everything inbetween. Classic army has something for everyone." + }, + ".markerupgrades.dlx___luxe_upgrades" : {}, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_octane_sunglasses" : { + "meta_description" : "Gatorz Octane Sunglasses - Zephyr Sports carries a complete line of Gatorz Octane Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Gatorz Octane Online Today.", + "page_title" : "Gatorz Octane Sunglasses On Sale Free Shipping", + "head_title" : "Gatorz Octane Sunglasses | Gatorz Octane Sun Glasses | Sunglasses Gatorz Octane" + }, + ".apparel.pants.valken_paintball_pants.valken_fate_paintball_pants" : { + "meta_keywords" : "valken fate,fate paintball pants,grey,red,olive,blue, valken fate paintball pants", + "meta_description" : "Valken Fate Pants - Valken Fate are great entry level paintball pants. For $40 they can't be beat. Buy your Fate Paintball Pants online at ZephyrPaintball.com", + "page_title" : "Valken Fate Pants On Sale Now", + "head_title" : "Valken Fate Pants | Valken Fate | Fate Paintball Pants" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.empire_axe_paintball_guns" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_womens_backpacks" : { + "meta_description" : "Oakley Womens Backpacks - Buy your Oakley Womens Bags At Zephyr Sports for Less Today! We carry a complete line of Womens Oakley Backpack at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Womens Backpacks On Sale & Free Shipping", + "head_title" : "Oakley Womens Backpacks | Oakley Womens Bags | Womens Oakley Backpack" + }, + ".casual_clothing.mens_clothing.sweatshirts.element_sweatshirts" : { + "meta_description" : "Element Sweatshirts - Buy your Element Hooded Sweatshirt At Zephyr Sports for Less Today! We carry a complete line of Element Hoodie at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Element Sweatshirts On Sale & Free Shipping", + "head_title" : "Element Sweatshirts | Element Hooded Sweatshirt | Element Hoodie" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_method_sunglasses" : { + "meta_description" : "Smith Optics Method Sunglasses - Zephyr Sports carries a complete line of Method Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Method Sun Glasses Online Today.", + "page_title" : "Smith Optics Method Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Method Sunglasses | Method Smith Sunglasses Free Shipping | Buy Smith Method Sun Glasses" + }, + ".casual_clothing.mens_clothing.sweatshirts.reef_sweatshirts" : { + "meta_description" : "Reef Sweatshirts - Buy your Reef Hoodies At Zephyr Sports for Less Today! We carry a complete line of Reef Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Reef Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Reef Sweatshirts | Reef Hoodies | Reef Hoody" + }, + ".casual_clothing.mens_clothing.tshirts.dakine_t_shirts" : { + "meta_keywords" : "Dakine T Shirts,Dakine shirts,free shipping,Dakine TShirt", + "meta_description" : "Dakine T Shirts - Zephyr carries a complete line of Dakine Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Dakine T Shirts at Zephyr", + "head_title" : "Dakine T Shirts | Dakine Shirts | Dakine TShirt" + }, + ".dye_i4_paintball_goggle_mask.o_-_airsoft_product_review" : {}, + ".2clearance.clearance_barrels" : { + "meta_keywords" : "clearance paintball barrels, cheap barrels, cheap dye barrels, clearance barrels", + "page_title" : "", + "head_title" : "Clearance Paintball Barrels | Discount Paintball Barrels | Cheap Dye Barrels" + }, + ".markerupgrades.feednecks.intimidator_feednecks" : { + "meta_description" : "Intimidator Feed Necks - Buy your Feednecks for Intimidator Online at Zephyr Paintball for Less today. Free Shipping on Intimidator Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Intimidator Feed Necks Online On Sale Now", + "head_title" : "Intimidator Feed Necks | Feednecks for Intimidator | Intimidator Feed" + }, + ".airsystems.hosesfittings.stainless_steel_hoses___fittings" : { + "meta_description" : "Co2 Paintball Hoses - Buy your Stainless Steel Paintball Hose Online at Zephyr Paintball for Less today. Free Shipping on Stainless Hose for Paintball Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Co2 Paintball Hoses Online On Sale Now", + "head_title" : "Co2 Paintball Hoses |Stainless Steel Paintball Hose | Stainless Hose for Paintball" + }, + ".markerupgrades.kingmanspyder.kingman_spyder_air_accesories" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.camelbak_magic_hydration_packs" : {}, + ".casual_clothing.mens_clothing.sweatshirts.c1rca_circa_sweatshirts" : { + "meta_description" : "Circa Sweatshirts - Buy your Circa Hoodies At Zephyr Sports for Less Today! We carry a complete line of Circa Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Circa Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Circa Sweatshirts | Circa Hoodies | Circa Hoody" + }, + ".casual_clothing" : { + "dynimage1" : "images=banners/clothing/slideshow/matixapparel_big_10_6_11,banners/clothing/newsletters/alpinestars_tshirts_newsletter001,banners/clothing/slideshow/nixon_newprod_slideshow001,banners/clothing/slideshow/neff_has_landed_big_10_7_11,banners/sunglasses/slideshow/oakleyfrogskins_001\nlinks=%SESSION%/results.cgis?catalog=MFG&root=.&keywords=matix&x=0&y=0,%SESSION%/category/casual_clothing.mens_clothing.tshirts.alpinestars_t_shirts/,%SESSION%/category/casual_clothing.mens_clothing.watches/,%SESSION%/category/casual_clothing.mens_clothing.beanies.neff_beanies/,%SESSION%/category/casual_clothing.z-sunglasses.oakley_sunglasses.oakley_frogskins_sunglasses/\npauses=4000,4000,4000,4000,4000\nblank_behavior=none\n", + "meta_keywords" : "skate clothing,surf clothing online,skate clothesskate clothes,skate shoes mens,men's clothing,womens shirts,sweatshirts,tshirts,mens hats,hooded sweatshirts,casual,ladies,apparel,hoodies,tshirt,belts,socks,wallets,watches,beanies,t-shirts,watches,freestyle,nixon,oakley,foundation,toy machine,ladies tank tops,sunglasses,shoes", + "meta_description" : "Skate Clothes at Zephyr Sports.A grip of casual apparel by top brands! Oakley, Von Zipper, Tanked, Toy Machine, Hater, Foundation to name a few... All kinds of skate & Surf clothing for Men, Ladies, and Youth! Men's Tshirts, Women's shirts, hooded sweatshirts, hats, belts, socks, beanies, wallets, ladies tank tops, sunglasses and more! Watches by Freestyle and Nixon! Get your clothing online today @ Zephyr Sports!", + "page_title" : "Buy Skate Clothing On Sale & Free Shipping", + "head_title" : "Skate Clothing | Surf Clothing Online | Skate Clothes", + "page_head" : "" + }, + ".casual_clothing.mens_clothing.tshirts.smith_optics_t_shirts" : { + "meta_keywords" : "Smith T Shirts,Smith shirts,free shipping,Smith TShirt", + "meta_description" : "Smith T Shirts - Zephyr carries a complete line of Smith Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Smith T Shirts at Zephyr", + "head_title" : "Smith T Shirts | Smith Shirts | Smith Optics TShirt" + }, + ".casual_clothing.mens_clothing.sweatshirts.dye_sweatshirts" : { + "meta_description" : "Dye Paintball Sweatshirts - Buy your Dye Sweatshirt At Zephyr Sports for Less Today! We carry a complete line of Dye Paintball Hoodie at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Dye Paintball Sweatshirts On Sale & Free Shipping", + "head_title" : "Dye Paintball Sweatshirts | Dye Sweatshirt | Dye Paintball Hoodie" + }, + ".1newitems.2009_bob_long_gear" : {}, + ".casual_clothing.mens_clothing.socks.vans_socks" : { + "meta_keywords" : "Vans socks,Vans mens socks,Vans men socks", + "meta_description" : "Vans Socks - Zephyr stocks a complete line of Vans Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Vans needs. ", + "page_title" : "Vans Socks on Sale at Zephyr", + "head_title" : "Vans Socks | Vans Mens Socks" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys.invert_clearance_paintball_jerseys" : {}, + ".markerupgrades.smartparts.ion.bodykits.smart_parts_ion_body_kits" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_alter_ego_4125_sunglasses" : { + "meta_description" : "Arnette Alter Ego Sunglasses - Buy your Arnette 4125 Alter Ego At Zephyr Sports for Less Today! We carry a complete line of Alter Ego Arnette Sunglasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Arnette Alter Ego Sunglasses On Sale & Free Shipping", + "head_title" : "Arnette Alter Ego Sunglasses | Arnette 4125 Alter Ego | Alter Ego Arnette Sunglasses" + }, + ".markerupgrades.angel.angel_grips" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_snark_sunglasses" : { + "meta_keywords" : "Von Zipper Snark sunglasses,VZ Snark,Von Zipper polarized sunglasses,Von Zipper Snark,VZ Snark glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Snark Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Snark sunglasses now! For Von Zipper Snark glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Snark Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Snark Sunglasses | VonZipper Snark Sunglasses | VZ Snark Sunglasses" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.etek_3_paintball_guns" : {}, + ".airsoft.airsoft_guns.g_g_armamant_airsoft_rifles" : { + "meta_keywords" : "G&G Armament,AEG rifles,high-end AEG rifles,AK47,UMG,MP5,M16,G&G airsoft,airsoft aeg,airsoft guns,", + "meta_description" : "G&G Armament. G&G Armament is a leading designer in high-end AEG rifles. Offering a wide variety of replicas including the AK47, UMG, MP5, M16, and much more. Check out all their airsoft AEG 's! They also offer many variations of different popular rifles. Here you will find both plastic and metal body styles. G&G is a great choice for avid airsoft players looking for high-end, top of the line airsoft guns.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "G&G M14 Airsoft Guns On Sale & Free Shipping", + "head_title" : "G&G M14 Airsoft Guns | G&G M4 | G&G Armament Airsoft" + }, + ".markers.alien_paintball_guns" : { + "meta_keywords" : "alien paintball, alien paintball guns, alien paintball markers, alien tournament paintball guns, alien tournament paintball markers, invasion paintball guns, alien invasion paintball guns, alien invasion paintball markers, invasion paintball guns, invasion paintball markers", + "meta_description" : "Alien Paintball - Zephyr Sports is now stocking Alien Paintball guns. These tournament paintball guns offer superior performance priced competitively against other high-level markers.", + "top_description2" : "==Alien Paintball Guns==\nAlien guns are among the lightest of the full size guns, with a solid feel, comfortable grip frame, excellent balance and easy handling. Alien triggers are fast and smooth. Alien Markers have a solid feel with walls that are visibly thicker than guns of similar weight. Because the guns are modular, each piece can be minimized for a lightweight but full strength design. The low pressure regulator of Alien Paintball guns provides a quieter, calmer, and more accurate shot. Every Alien gun is exceptionally calm and very fast. They are smooth, light, and accurate, and the quality of manufacturing and use of the best parts is evident throughout each marker.", + "zoovy:banner02" : "banners/paintball/headers/alien_banner", + "description" : "Alien Paintball is a well respected name in tournament level play. Their guns offer some of the best performance for the price, and are notorious for wiping out the competition. In the heat of a firefight, you need a gun that can out-preform your opponents, and that is what you get with Alien Paintball guns. They are lightweight, calm, and accurate, so while your opponent is losing his cool trying to fill up his hopper, you can spray him with paint and take your team to the podium.", + "page_title" : "Buy Alien Paintball Guns On Sale & Free Shipping", + "top_description3" : "", + "head_title" : "Alien Paintball | Alien Paintball Guns | Tournament Paintball guns" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.uhc_spring_airsoft_guns" : { + "meta_description" : "UHC Airsoft Guns - Buy your UHC Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of UHC Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy UHC Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "UHC Airsoft Guns | UHC Airsoft Rifles | UHC Spring Airsoft Guns" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_lock_up_sunglasses" : { + "meta_keywords" : "Arnette Sunglasses, arnette polarized, arnette sunglass, Arnette Eyewear, Arnette Lens", + "meta_description" : "Arnette 3045 Lock Up Sunglasses- High Quality Arnette Lens, Polarized Sunglasses are the way to go! The Arnette Lock Up Sunglasses are the latest in Arnette Eyewear!", + "head_title" : "Arnette Lock Up Sunglasses | Arnette 3045 Lock Up Sunglasses" + }, + ".casual_clothing.z_unisex_clothing_accesories.cell_phone_cases" : { + "meta_description" : "Cell Phone Cases - Buy your Iphone Cases At Zephyr Sports for Less Today! We carry a complete line of Phone Cases at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Iphone & Cell Phone Cases on Sale", + "head_title" : "Cell Phone Cases | Iphone Cases | Phone Cases" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.ak47_aeg_airosft_gun_mags" : {}, + ".apparel.pants.dyepants.dye_ultralite_paintball_pants" : { + "top_html_focus" : "", + "meta_description" : "Dye Ultralite Paintball Pants - The ultimate in high end paintball pants. 4 way stretch, breathable and insanely lightweight. The Dye Ultralite pants will be worn by the top pro teams in 2013 and are available at Zephyr Paintball.", + "page_title" : "Dye Ultralite Paintball Pants", + "head_title" : "Dye Ultralite Paintball Pants | Ultralite Pants" + }, + ".shop_by_brand.srh_apparel" : {}, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes" : { + "meta_description" : "Airsoft Scopes - Buy your Airsoft Rifle Scopes At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Scopes On Sale & Free Shipping", + "head_title" : "Airsoft Scopes | Airsoft Rifle Scopes" + }, + ".apparel.jerseys.bt_paintball_jerseys" : { + "meta_keywords" : "camo paintball jersey, bt paintball jersey, bt pro jersey", + "meta_description" : "Camo Paintball Jerseys - BT Camo Paintball jersey including the bt pro jersey. Camo flouge paintball jerseys from Battle tested paintball", + "page_title" : "", + "head_title" : "Camo Paintball Jersey | BT Paintball Jersey | BT Pro Jersey" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_disguise_womens_sunglasses" : { + "meta_keywords" : "Oakley Disquise Womens Sunglasses,Disquise Womens oakley sunglasses,oakley Disquise Womens, Disquise Womens polarized sunglasses", + "meta_description" : "Oakley Disquise Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Disquise Womens and Polarized Oakley Disquise Womens Sunglasses on Sale! ", + "page_title" : "Oakley Disquise Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Disquise Womens Sunglasses | Disquise Womens Oakley Sunglassses" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.bushnell_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.shoes.vox_shoes" : { + "meta_description" : "Vox Shoes - Buy your Vox Mens Shoes Online At Zephyr Sports for Less Today! We carry a complete line of Vox Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Vox Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Vox Shoes | Vox Mens Shoes | Vox Skate Shoes" + }, + ".airsystems.dropforwards.lapco" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_fives_squared_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley fives squared sunglasses,polarized oakley fives squared sunglasses", + "meta_description" : "Oakley Fives Squared Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Fives Squared and Fives Squared Polarized Oakley Sunglasses on Sale!", + "page_title" : "Oakley Fives Squared Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Fives Squared Sunglasses | Oakley Sunglasses Fives Squared" + }, + ".airsoft.airsoft_guns.walther_airsoft_guns" : { + "meta_description" : "Walther Airsoft Guns - Buy your Walther Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of Walther Airsoft Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Walther Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Walther Airsoft Guns | Walther Airsoft Rifles | Walther Airsoft Pistols", + "description" : "" + }, + ".paintballs.wpn_paintballs" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_frogskins_sunglasses" : { + "meta_keywords" : "oakley frogskins,oakley frogskin,frogskins,frogskins oakley,oakley frog skins,oakley frogskin sunglasses", + "meta_description" : "Oakley Frogskins - They're back! The original dual lens glasses from Oakley. Frogskin Oakleys were the first dual lens sunglass oakley ever made. Oakley Frog Skins 80's style along with Oakley's top notch quality available at Zephyr Sports with Free SHipping today", + "page_title" : "Oakley Frogskins Free Shipping at Zephyr", + "head_title" : "Oakley Frogskins | Frogskins Oakley | Oakley Frog Skins" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.c_large" : {}, + ".buyers_guide" : { + "answer_01" : "The Airsoft section currently covers: Pistols, Rifles, BBs & Ammo, and Batteries & Chargers.", + "answer_03" : "", + "html_01" : "

                                                                          FAQ (Frequently Asked Questions)

                                                                          \n\n\n\n\n\n\n
                                                                          What is covered in the Airsoft section?What is covered in the Paintball section?
                                                                          ", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002", + "question_02" : "What is covered in the Paintball section?", + "answer_04" : "", + "text_01" : "Welcome to the Zephyr Buyer's Guide. In the following sections you will be able to find information about our products as well as find answers to common questions.\n\n\nTo use this guide, follow the sections above to navigate to the sport and product type you would like to learn more about. Use this guide to help you shop or educate yourself or others on different topics within the various sports or activities of interest.\n\n\nWithin each section you will find common questions and answers as well as an overall topic overview. To help you navigate quickly to the information you need, you can follow the links listed in the FAQ navbar located on each page.\n\n\nThe Buyer's Guide is a continuing project and will updated frequently.", + "question_01" : "What is covered in the Airsoft section?", + "answer_02" : "The paintball section is currently being updated and will provide information on a multitude of paintball products.", + "question_03" : "", + "title_01" : "What is the Buyer's Guide", + "top_description3" : "Are you looking for an information before you buy your first Paintball or Airsoft Gun? Or maybe just some more information about an upgrade your looking for. Zephyr University provides a complete buyers guide to answer all your questions. With years in the Paintball and Airsoft business, we've received a few questions from our customers. In Zephyr University, we attempted to answer as many of these questions as possible for our customers. Find the item that's just right for your requirements. Zephyr University is a great research tool and will help bring you up to speed fast. All the articles featured on this page are written by our knowledgeable Product Specialists. Find out the basics of each type of product that we sell and match the planned use of the instrument with price range. You will even get specific product selection suggestions! Choose your interest below to get started at Zephyr University", + "question_04" : "", + "return_link" : "" + }, + ".casual_clothing.mens_clothing.sweatshirts.arbor_sweatshirts" : { + "meta_description" : "Arbor Sweatshirts - Buy your Arbor Hoodies At Zephyr Sports for Less Today! We carry a complete line of Arbor Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Arbor Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Arbor Sweatshirts | Arbor Hoodies | Arbor Hoody" + }, + ".shop_by_brand.ogio" : {}, + ".markerupgrades.rampingchipsboards.advantage_pb.virtue_standard_upgrade_boards" : { + "meta_description" : "Virtue Boards - Buy your Virtue Board Paintball Online at Zephyr Paintball for Less today. Free Shipping on Virtue Paintball Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Virtue Boards Online On Sale Now", + "head_title" : "Virtue Boards | Virtue Board Paintball | Virtue Paintball Boards" + }, + ".markerupgrades.tippmann.a5.tippmann_a_5_feed_upgrades" : {}, + ".casual_clothing.mens_clothing.jackets.element_jackets" : { + "meta_description" : "Element Jackets - Buy your Element Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Element Jackets with Free Shipping", + "head_title" : "Element Jackets | Element Mens Jackets" + }, + ".casual_clothing.mens_clothing.wallets.enjoi_wallets" : { + "meta_description" : "Enjoi Wallets - Buy your Enjoi Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Enjoi Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Enjoi Wallets on Sale @ Zephyr Sports", + "head_title" : "Enjoi Wallets | Enjoi Mens Wallets | Enjoi Wallet" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.evil_paintballs" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.colt_spring_airsoft_guns" : { + "meta_description" : "Colt Airsoft Guns - Buy your Colt Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Colt Spring Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Colt Airsoft Guns On Sale & Free Shipping", + "head_title" : "Colt Airsoft Guns | Colt Airsoft Rifles | Colt Spring Airsoft Gun" + }, + ".casual_clothing.mens_clothing.accessories.cell_phone_cases.oakley_cell_phone_cases" : { + "meta_description" : "Oakley Phone Cases - Buy your Oakley Iphone CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Oakley Iphone Cases", + "head_title" : "Oakley Phone Cases | Oakley Iphone Cases" + }, + ".goggles.1goggle_accesories.jt_usa_goggle_accesories" : { + "meta_description" : "JT USA Lens - Buy your JT USA Thermal Lens Online at Zephyr Paintball for Less today. Free Shipping on JT USA Replacement Lens Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy JT USA Lens Online On Sale Now", + "head_title" : "JT USA Lens | JT USA Thermal Lens | JT USA Replacement Lens" + }, + ".goggles.1goggle_accesories.dye_goggle_accesories" : { + "meta_description" : "Dye Lens, Dye I4 Lens, Dye Paintball Lens, Dye Replacement lens, dye thermal lens, dye mirror lens, dye i3 lens", + "page_title" : "Buy Dye I4 Lens Online On Sale Now", + "head_title" : "Dye I4 Lens | Dye Thermal Lens | Dye Replacement Lens" + }, + ".airsoft.tactical_airsoft_gear.head_gear.zephyr_tactical_head_gear" : {}, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_flash_hider" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Flash Hiders | Flash Hider Airsoft | M4 M14 Flash Hiders" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_showtime_sunglasses" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_kids_hydration_packs.camelbak_scout_hydration_packs" : {}, + ".markerupgrades.empire_upgrades.empire_axe_parts_and_upgrades" : {}, + ".apparel.head_bands_and_wraps.proto_paintball_head_bands___wraps" : {}, + ".casual_clothing.womens_clothing.ladies_t_shirts.metal_mulisha_ladies_t_shirts" : {}, + ".snowboard_gear.snowboard_goggles.smith_optics_ski_and_snowboard_goggles" : { + "meta_keywords" : "smith snowboard goggles,smith ski goggles,smith snow goggles,smith phenom,heiress,knowlwedge otc,smith scope pro,smith winter goggles", + "meta_description" : "Smith Snowboard Goggles - Smith Ski Goggles now Available at Zephyr Sports. We carry a full line of Smith Snow Goggles with Free Shipping and Real Time Inventory.", + "page_title" : "Smith Snowboard Goggles Free Shipping at Zephyr", + "head_title" : "Smith Snowboard Goggles | Smith Ski Goggles | Smith Snow Goggles" + }, + ".apparel.shoes.1_search_by_color.pink_mens_shoes" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_quatro_watches" : {}, + ".casual_clothing.mens_clothing.tshirts.arbor_t_shirts" : { + "meta_keywords" : "Arbor T Shirts,Arbor shirts,free shipping,Arbor TShirt", + "meta_description" : "Arbor T Shirts - Zephyr carries a complete line of Arbor Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Arbor T Shirts at Zephyr", + "head_title" : "Arbor T Shirts | Arbor Shirts | Arbor TShirt" + }, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_" : { + "meta_description" : "Anarchy Sunglasses - Zephyr Sports carries a complete line of Anarchy Eyewear At the lowest prices on the web with free shipping and easy returns. Buy your Anarchy Sun Glasses Online Today.", + "page_title" : "Anarchy Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Sunglasses | Anarchy Eyewear | Anarchy Sun Glasses" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray-ban_rb3471_youngster_sunglasses" : {}, + ".buyers_guide.paintball.paintball_hoppers" : { + "top_html" : "", + "top_description2" : "Purchasing a Paintball loader can be a difficult proposition if you do not know exactly what you are looking for. We have an extensive selection of both high-end and basic [[Paintball loaders]:url=http:/category/loaders/] to choose from, not to mention everything in between! Here's a little run down of some hopper basics along with highlight of some of the hoppers we carry.\n\n\n=Entry Level Gravity Feed Hoppers=\nOn the cheap side, better yet ~ beginner stage, we have your standard [[Gravity fed paintball loader]:url=http:/category/loaders/]. Various different companies make your standard 200 round gravity feed hopper and there really is no performance difference between all of the versions out there. Basically they will all have a similar shape and feed as fast as one another. This loader is good entry level compatible with all paintball guns on the market. However, being gravity fed, it will only feed as fast as the [[paintballs]:url=http:/category/paintballs/] drop. Gravity feed hoppers usually consist of a 200 round container complete with a lid. With a maximum feed rate of 8BPS, these hoppers may become jammed as too many balls accumulate above the tube. Of course when this occurs, rocking the gun gently should successfully dislodge any jammed paintballs. We do not recommend that you use electronic [[paintball guns]:url=http:/category/markers/] with gravity fed hoppers as the gun will typically shoot faster than the [[hopper]:url=http:/category/loaders/] can feed resulting in chopped paint and a disappointing day at the field. A new take on the gravity feed hopper that was just released this year is the [[Proto Primo loader]:url=http:/category/loaders.proto_paintball_loaders/]. The Innovative Positive Feed Shelf provides a minimal friction, gravity feed solution allowing you to achieve high rates of fire while drastically reducing paint jams.\n\n\n=Entry Level Electronic Hoppers=\nThis level of [[Paintball Hoppers]:url=http:/category/loaders/] typically have an automatic agitation to help increase the feed of paint to your [[paintball marker]:url=http:/category/markers/]. Paintball feed rates typically range from 10 to 15 bps. This level is fast enough to keep up with most paintball guns up to about the $150 range. In this category we have the [[Extreme Rage Overdrive]:url=/category/loaders.extreme_rage_paintball_hoppers/], [[Viewloader Force]:url=/category/loaders.viewloader/] and [[Tippmann paintball hoppers]:url=/category/loaders.tippmann_paintball_hoppers/]. These loaders are both inexpensive and effective for any player on a budget. Being electronically agitated, these hoppers provide a constant flow of paintballs to the gun at roughly 10-15 balls per second. These are good options for any type of player who does not have a ton of money but wants an effective electronic loader for their gun. Some of the drawbacks to this level of hopper will be higher noise levels, constant agitation (your hopper will constantly be running when you turn it on whether your gun is firing or not). This tends to run down your batteries if you do not remember to turn off your hopper.\n\n\n=Mid Level Electronic Paintball Loaders=\nWith increased price come a bit of a performance increase. Hoppers in this range will feed 15 to 25+ BPS along with having either a sound activated or eye activated feed system. \n\n==Eye Activated feed==\n- Eye Activated hoppers have a vision eye similar to what is found on higher end paintball guns. If the eye senses that there is no paint in the feed tube, it will feed, if it senses that you are not firing, the motor is shut off. This saves a lot of battery life as well as reducing broken paint in the hopper when it is trying to feed but your gun is not firing. The [[invert Halo Too]:url=/category/loaders.invert_paintball_hoppers/], [[Viewloader Evolution 3 & 4]:url=/category/loaders.viewloader/]and [[Spyder Fasta Loaders]:url=/category/loaders.kingman_paintball_loaders/]are examples of eye activated hoppers in this category\n\n==Sound Activated Feed==\nThe feed motor on these hoppers are activated by the sound of your paintball marker firing. The thought being that they only feed when you are firing your marker and need paint. This technology was designed before the newer electronic guns were designed. Many Paintball guns like the [[Invert Mini]:url=http:/category/markers.invert_paintball_guns/] and [[Dangerous Power G4]:url=http:/category/markers.dangerous_power_paintball_guns.dangerous_power_g4_paintball_guns/] may actually be too quiet for the sound sensor to pick up that your gun us firing without adjusting the sound sensitivity. If you are not the type of person who like to read manuals or tinker than a sound activated hopper may not be for you. The [[Extreme Rage Sonic DB]:url=/category/loaders.extreme_rage_paintball_hoppers/] and Empire Reloader B are examples of Sound Activated Paintball Hoppers.\n\nBoth styles of Mid Range [[Paintball Loaders]:url=/category/loaders/] provide incredible speed with precision monitoring and anti chop technology. These hopper provide enough performance to satisfy the casual paintball player with a fast consistent Hopper to provide a full day of play at your local field.\n\n\n=High End Electronic Paintball Loaders=\n\n\nWhether your a Paintball Tournament player, or just need to have the best Paintball Gear. These Paintball Loaders are the fastest on the market with the most advanced technology available today. With feed rates ranging from 20 to 50+ Balls per second, your hopper will no longer be what limits your firing rate.\n\n=The Halo hopper=\nLike most other high end paintball loaders,the Halo B line of Loaders is EYE activated which entirely does away with chopped balls! That, along with its ‘stock’ 22+ BPS firing rate enables its user to fire at will and own the competition! The Halo B line of hoppers features a belt drive technology that reduces ball breakage by reducing the pressure on paint in the hopper. The Halo B also features a spring loaded drive cone to further reduce ball breakage while still allow the loader to have a high feed burst when need for short spurts during a game. If 22+ BPS doesn’t get you excited, check out the higher end Halo B upgraded V35 boards ramping up your firing abilities to 35+ Balls per second!\n\n\n=Pinokio Paintball Loader=\nThe all new Pinokio Paintball hoppers give you options on the field! They feature a removable nose piece which allows you to hold an additional 170 balls in the hopper. Pair that with its remarkable speed, and you’ve got yourself one of the hottest loaders on the market! At 30+ ball per second, rate of fire your speed is well covered. And even with all this speed, No need to worry… The Pinokio has the ability to go through 37+ cases of paint on just 2 nine volt batteries making it one of the most eco-friendly hoppers out there! On another note – Mike Paxson, a true professional on the field, plays with the Pinokio Hopper. If a Dye Ironman player like Mike has no problems using it then surely it can be trusted.\n\n\nIs your paintball gun going hungry out there on the field?? View Loader paintball hoppers won’t starve your marker no matter how fast you shoot! At the forefront of paintball hopper technology, View Loader prides themselves on making the best darn hoppers around! With already upgraded stock features like the Z-board and JVON flexible blades for better feed and a curved door for faster fills, View loader truly sets themselves aside from the competitors! The best part about View Loader hoppers is that adding one to your arsenal won’t even break the bank! View Loader gives high-end abilities without having to go over that already-tight paintball budget!\n\n\nAnd last but certainly not least, DYE Paintball’s latest and greatest paintball hopper yet.. the all new DYE Rotor! With unmatched aesthetics, the Dye Rotor does more than just look good! REVOLUTIONARY PATENTED ROTOR TECHNOLOGY - The ROTOR LOADER far exceeds pro level feed requirements with an ever impressive 50+ balls per second feed rate. No need to even speculate, just try to beat this beast on the field!Battery performance on this baby is insane with 50K+ shots recorded before they got tired of counting.\n\n\nSo there you have it, start with your paintball marker and go from there! Whether you’re looking to upgrade you’re already-sick set-up with a high-end terror of a paintball hopper or simply just getting started, ZephyrPaintball.com has everything you need to get in the game and dominate! " + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_precept_sunglasses" : { + "meta_description" : "Smith Optics Precept Sunglasses - Zephyr Sports carries a complete line of Precept Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Precept Sun Glasses Online Today.", + "page_title" : "Smith Optics Precept Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Precept Sunglasses | Precept Smith Sunglasses Free Shipping | Buy Smith Precept Sun Glasses" + }, + ".1newsletter.twitter" : {}, + ".maddog" : { + "description" : "" + }, + ".shop_by_brand.tenergy_batteries" : {}, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_springs" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "AEG Springs | Airsoft springs | Airsoft Gun Spring" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_eyepatch_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley eyepatch sunglasses, polarized oakley eyepatch sunglasses", + "meta_description" : "Oakley Eyepatch Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Eyepatch and Eyepatch Polarized Oakley Sunglasses on Sale!", + "page_title" : "Oakley Eyepatch Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Eyepatch Sunglasses | Oakley Eyepatch Sunglasses Polarized" + }, + ".casual_clothing.mens_clothing.tshirts.real_t_shirts" : { + "meta_keywords" : "Real T Shirts,Real shirts,free shipping,Real TShirt", + "meta_description" : "Real T Shirts - Zephyr carries a complete line of Real Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Real T Shirts at Zephyr", + "head_title" : "Real T Shirts | Real Shirts | Real Skate TShirt" + }, + ".apparel.gloves.proto_paintball_gloves" : { + "meta_keywords" : "proto paintball gloves,glove proto paintball,2009 proto gloves", + "meta_description" : "Proto Paintball gloves - Protect your hands with a pair of gloves proto today. No more cut up hands and fingers from a day at the field. ", + "page_title" : "", + "head_title" : "Proto Paintball Gloves | Gloves Proto |Proto Paintballing Gloves", + "prodlist1_header" : "Proto Paintball Gloves" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.young___restless_t_shirts" : {}, + ".casual_clothing.mens_clothing.hats.electric_hats" : { + "meta_keywords" : "Electric Hats,Electric caps,Electric baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Electric Hats - Zephyr carries a complete line of Electric Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Electric", + "page_title" : "Electric Hats on Sale at Zephyr", + "head_title" : "Electric Hats | Electric Caps | Electric Baseball Hats" + }, + ".casual_clothing.mens_clothing.boots" : { + "meta_keywords" : "oakley boots, oakley si boots, work boots, military boots, dessert boots,converse boots, military footwear,hiking boots,Cheap Boots", + "meta_description" : "Military Boots - Zephyr stocks a complete line of Work Boots from the top manufacturers including Oakley, Converse, Danner,and more. Get your Cheap Boots at Zephyr with Free SHipping", + "page_title" : "Military and Works Boots at Zephyr Sports", + "head_title" : "Military Boots | Work Boots | Cheap Boots" + }, + ".airsystems.fill_stations" : { + "meta_description" : "Paintball Fill Station - Buy your CO2 Fill Station Online at Zephyr Paintball for Less today. Free Shipping on HPA Fill Station Trust Zephyr for all your Paintball Needs", + "top_description" : "Tired of paying a fortune to fill up all your co2 tanks? All you need is a bulk co2 tank that can be picked up at a local welding supply company. Be sure to ask for a tank with a dip tube. Once you have your Bulk Co2 tank, all you need is one of our co2 fill stations and a scale and your set. Be sure to read and follow all instructions and always use a scale to make sure you don't overfill your tank. ", + "page_title" : "Buy Paintball Fill Station Online On Sale Now", + "head_title" : "Paintball Fill Station | CO2 Fill Station | HPA Fill Station" + }, + ".2clearance.skateboards.completes" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_lunch_boxes" : {}, + ".casual_clothing.mens_clothing.tank_tops.infamous_paintball" : {}, + ".markerupgrades.smartparts.ion.ion_electronics_upgrades" : {}, + ".videos_page.prophecy_videos" : { + "htmlvids" : "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n
                                                                          " + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4139_hold_up_sunglasses" : { + "meta_description" : "Arnette Hold Up Sunglasses - Buy your Arnette 4139 Hold Up At Zephyr Sports for Less Today! We carry a complete line of Hold Up Arnette Sunglasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Arnette Hold Up Sunglasses On Sale & Free Shipping", + "head_title" : "Arnette Hold Up Sunglasses | Arnette 4139 Hold Up | Hold Up Arnette Sunglasses" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_tanks" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_scissorkick" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.camelbak_mule_hydration_packs" : {}, + ".airsoft.airsoft_batteries___chargers.108v_airsoft_battery_packs" : { + "meta_description" : "10.8 Volt Rechargeable Airsoft Batteries available at Zephyr Sports. We Stock a complete line of Airsoft Batteries from all the top manufacturers", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "10.8V Airsoft Batteries | 10.8 Battery for Airsoft | Upgrade Replacement Airsoft Battery" + }, + ".casual_clothing.mens_clothing.sandals" : { + "meta_description" : "Mens Sandals - Buy your Mens Flip Flops At Zephyr Sports for Less Today! We carry a complete line of Flipflops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Mens Sandals @ Zephyr Sports", + "head_title" : "Mens Sandals | Mens Flip Flops | Flipflops" + }, + ".airsoft.shop_by_brand.voodoo_tactical" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Voodoo tactical gear | Voodoo airsoft | Voodoo Paintball" + }, + ".misc_items.batteries" : { + "meta_keywords" : "energy paintball batteries, energy batteries, paintball batteries", + "page_title" : "", + "head_title" : "Energy Paintball Battieries | Energy Batteries | Paintball Batteries", + "description" : "Energy Paintball is a brand of Paintball Batteries. Their batteries have been developed to answer exactly to specific needs of loaders and markers, which uses a lot of energy. They've turned to their development team of engineers and professional athletes to bring to you the most advanced paintball batteries." + }, + ".casual_clothing.womens_clothing.ladies_shirts.hostility_ladies_shirts" : {}, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_murdock_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon murdock sunglasses", + "meta_description" : "Dragon Murdock Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Murdock Sunglasses" + }, + ".airsoft.shop_by_brand.bravo_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".scenarioupgrades.tactical_vests.dye_tactical_vests" : {}, + ".markerupgrades.kingmanspyder.scenarioupgrades" : { + "meta_description" : "Spyder Stocks - Buy your Spyder Tactical Stock Online at Zephyr Paintball for Less today. Free Shipping on Stock for Spyder Paintball Gun Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Stocks Online On Sale Now", + "head_title" : "Spyder Stocks | Spyder Tactical Stock | Stock for Spyder Paintball Gun" + }, + ".casual_clothing.z-sunglasses.hk_army" : {}, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.dangerous_power_grip_panel" : {}, + ".markers.lapco_paintball_guns" : { + "meta_description" : "Lapco Grey Ghost - Buy your Lapco Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Lapco Pump Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Lapco Grey Ghost Online On Sale Now", + "head_title" : "Lapco Grey Ghost | Lapco Paintball Guns | Lapco Pump Paintball Guns" + }, + ".casual_clothing.z_unisex_clothing_accesories.keychains" : {}, + ".markerupgrades.smartparts.eos_upgrades.eos_bolts" : {}, + ".casual_clothing.mens_clothing.accessories.audio___headphones.nixon_headphones.nixon_wire_headphones" : {}, + ".casual_clothing.mens_clothing.socks.oakley_socks" : { + "meta_keywords" : "Oakley socks,Oakley mens socks,Oakley men socks", + "meta_description" : "Oakley Socks - Zephyr stocks a complete line of Oakley Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Oakley needs. ", + "page_title" : "Oakley Socks on Sale at Zephyr", + "head_title" : "Oakley Socks | Oakley Mens Socks" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_tonette_sunglasses" : { + "meta_description" : "Electric Tonette Sunglasses - Zephyr Sports carries a complete line of Electric Tonette Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Tonette Online Today.", + "page_title" : "Electric Tonette Sunglasses On Sale Free Shipping", + "head_title" : "Electric Tonette Sunglasses | Electric Tonette Sun Glasses | Sunglasses Electric Tonette" + }, + ".casual_clothing.womens_clothing.ladies_shirts.metal_mulisha_ladies_shirts" : {}, + ".harnessesbags.backpacks.1_shop_by_bag_style.rolling_backpacks" : {}, + ".shop_by_brand.rap_4_paintball" : { + "top_description2" : "==Rap 4 Paintball, realism has a whole new meaning==\n\nRap 4 paintball guns are the most realistic scenario weapons paintball has to offer. Rap 4 offers weapons with a new sense of the word realistic. These guns are indistinguishable on the field. With Co2 powered 18 round mags, scenario games were never this hardcore. Try Rap 4 products and look at Zephyr's line up of products. Rap 4, try the best and forget the rest. ", + "head_title" : "Rap 4 paintball | Rap 4 | Rap 4 paintball guns", + "description" : "==Rap 4, Realisim has a whole new meaning==\n\nRap 4 products bring something new to the table. Realistic paintball guns is what Rap 4 specializes in because of the intimidation factor, the performance and the fun of holding something that is nearly indistinguishable form the real thing. \n\n==NEW 2011 RAP4 Tactical MOLLE Paintball Vests==\nNEW RAP4 Tactical MOLLE Paintball Vests for Airsoft, paintball and Tactical training. The new MOLLE Tactical Paintball Vests can be organized to accommodate paintball pods, standard AR magazine, standard MP5 magazine, all sizes of CO2 cylinders and air tanks (HPA). The vest pouches are interchangeable and can be very easily configured to the user's requirements. The Tactical MOLLE Vest is designed with the MOLLE webbing system for better security for your pouches. The MOLLE webbing system is a multi-position hook system that enables you to attach the MOLLE pouches in the position of your choice. Read complete story.\n\n==New RAP4 Under Vests And Body Armor BDU==\nNew lightweight and breathable woodland camo BDU to be worn under body armor. RAP4's bold new layer of protection for your most important piece of equipment: your body. The new RAP4 Under Body Armor BDU is specifically designed to keep you comfortable, protected from the environment, and well concealed. Read complete story.\n\n==Land Warrior II Wireless Digital Video Recorder==\nLand Warrior II digital video recorder - your best solution for capturing game footage with full audio, as a marker-mounted camera, helmet-mounted camera, handheld unit or even mounted to your tank. Following the success of the original Land Warrior Wireless Video Camera, engineers took user feedback and made an even lighter and more adaptable digital recorder: the brand new Land Warrior II. Read complete story." + }, + ".casual_clothing.mens_clothing.hats.north_face_hats" : { + "meta_keywords" : "North Face Hats,North Face caps,North Face baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "North Face Hats - Zephyr carries a complete line of North Face Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything North Face", + "page_title" : "North Face Hats on Sale at Zephyr", + "head_title" : "North Face Hats | North Face Caps | North Face Baseball Hats" + }, + ".apparel.head_bands_and_wraps.voodoo_tactical_headband_and_heawraps" : {}, + ".markerupgrades.rampingchipsboards.advantage_pb" : { + "meta_description" : "Virtue Boards - Buy your Virtue Oled Board Online at Zephyr Paintball for Less today. Free Shipping on Virtue Paintball Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Virtue Boards Online On Sale Now", + "head_title" : "Virtue Boards | Virtue Oled Board | Virtue Paintball Boards" + }, + ".scenarioupgrades.camo_goggles" : { + "meta_keywords" : "camo paintball goggles,camo paintball,camo gear,camo paintball masks,camoflouge mask,camo goggles,paintball mask", + "meta_description" : "Camo Paintball Goggles - Huge selection of Camo Paintball Masks on sale at Zephyr Paintball. Always the lowest prices and free shipping over $100. Get your Camo Paintball Gear Today", + "page_title" : "Buy Camo Paintball Goggles Online On Sale Now", + "head_title" : "Camo Paintball Goggles | Camo Paintball | Camo Paintball Masks" + }, + ".airsoft.airsoft_spare_magazines.spring_pistol_magazines" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Pistol Mags | Spring Airsoft Pistol Mags | Mags for Spring Airsoft Pistol" + }, + ".loaders.hopper_accesories.dye_loader_accesories.dye_rotor_replacement_shells" : { + "meta_description" : "Dye Rotor Shells - Buy your Dye Rotor Replacement Shell Online at Zephyr Paintball for Less today. Free Shipping on Dye Rotor High Capacity Shells Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Rotor Shells Online On Sale Now", + "head_title" : "Dye Rotor Shells | Dye Rotor Replacement Shell | Dye Rotor High Capacity Shells" + }, + ".goggles" : { + "meta_keywords" : "Cheap Paintball Masks, Paintball Goggles, Discount Paintball Masks, Discount Paintball mask Goggles, Discount Paintball Equipment, paintball masks,Thermal Paintball Mask goggles,Sly Profit,Dye I4,Paintball goggle,Cheap Paintball Gear", + "ad3_link" : "/category/goggles.hk_army_paintball_masks/", + "add3_link" : "/category/goggles.empire_vents_goggles/", + "zs11_banner_wslideshow_slide1" : "ALT=FREE+Dye+I4+w%2f+Proto+Reflex+Rail+%26+Rotor+Combo%21&IMG=&LINK=%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3dREFLEXI4PROMO%26x%3d39%26y%3d0%26sortby%3dzoovy%3abase_price", + "prodlist2_title" : "Featured Goggles & Accessories", + "ad2" : "banners/paintball/side_banners/sly_profit_goggles_sidebanner.jpg", + "banner4" : "banners/sm_promo/empire_eventzn_small_header_001.jpg", + "3widead_title" : "", + "page_title" : "Buy Paintball Masks Online On Sale Now", + "zs11_banner_wslideshow_slide2" : "ALT=Cheap+Dye+I4+w%2f+Dye+UL+Pant+%26+Jersey+Combo%21&IMG=&LINK=%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3d25ULI4%26x%3d12%26y%3d9", + "ad2_link" : "/category/goggles.sly_profit_paintball_goggles/", + "add1_link" : "/category/goggles.dye/", + "banner2" : "banners/sm_promo/dye_i4_small_header_001.jpg", + "subcat1_header" : "", + "meta_description" : "Paintball Masks for Less at Zephyr Paintball. Largest selection, Lowest Prices Guaranteed. Free Shipping on orders over $100. Paintball Goggles, everyone needs them to play. So why not get them here. We carry all the latest styles and accessories that you could ever need including Thermal Paintball Goggles.", + "banner02_link" : "/category/goggles.save_phace_paintball_goggles/", + "ad1" : "banners/paintball/side_banners/virtue_vio_sidebanner.jpg", + "prodlist1_header" : "", + "banner01_link" : "/category/goggles.virtue/", + "zoovy:banner01" : "", + "zoovy:banner02" : "banners/paintball/slideshow/saave_phace_slideshow.jpg", + "description" : "", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "ad3" : "banners/paintball/side_banners/klr_hkarmy_mask_preorder_sidebanner.jpg", + "banner1" : "", + "htmlvids" : "", + "htmllinks" : "You might think finding the perfect paintball mask is the least of your worries but actually its one of the main priorities in finding the perfect setup for \nyour paintball experience. Not just for the looks or comfort, but for the safety of yourself. Now you may be browsing through and notice that the price \nsomewhat varies between the different types of masks. Well, when you are looking at the design of paintball goggles that is more expensive it becomes \nlighter, provides more padding, better fog resistance and more ventilation. Let's start with a basic mask. \n\n\nThe [[Proto EL]:url=/category/goggles.proto.proto_el_paintball_goggles/] is a basic starter mask that may not be the most comfortable but will do the job by protecting your noggin. It provides a woven goggles strap that you can adjust for the perfect fit. There is foam padding for the ears. Throughout the mask there are tiny holes for ventilation to help with fogging. The Proto EL has a single lens that is Anti-fog, but not thermal. Depending on where you live could decide if a single lens will work or not. If you live in a very humid area a thermal Lens, which is a dual pane lens (makes it anti-fog) would be the more accurate choice so you don't have to worry about fogging while in game. \n\n\nA higher end thermal mask is the [[Empire Events]:url=/category/goggles.empire_vents_goggles/] The Events would fall in the category of a high end mask. What makes this mask worth more than the Proto EL? The Empire Events are lighter, have SOFT EARS for more padding, greater ventilation and a Thermal lens. The lens itself is very easy to remove. An active player might find that changing the lens is a big deal for them. Being active and playing once or twice a week you may run into more wear on your lenses. Also, the Events are a very low profile mask which is preferable especially for tournament play. You want a light thin design to keep yourself away from being a big target and also for easy maneuvering which makes the Events the better choice.\n\nThe [[Dye I4]:url=/category/goggles.dye/] is the hottest mask in paintball currently. Ultra lightweight with an insanely small profile, it's perfect for tournament players. Players with large faces and or chins may have some issue though as your chin may extend beyond that mask which could lead to some painful shots.\n\nBe sure to check out the new Sly Profit. Released in Summer of 2010 this thermal Mask is one of the best we've seen. Great fit, Dual goggle Straps along with being lightweight and breathable make the [[Sly Profit]:url=/category/goggles.sly_profit_paintball_goggles/] a top choice for the demanding paintball player.\n\nCan I wear my glasses while I play? What's great about some of the paintball masks that we carry is that they provide enough room for your eye glasses. A \ngood choice for eye glasses is the [[V-force Profiler]:url=category/goggles.vforce.v_force_profiler_paintball_goggles/] mask. With the bug eyed lens on the Profiler you have enough room to wear your eye glasses while being comfortable. JT and V-force are usually a good choice if you wear glasses. \n", + "ad1_link" : "/category/goggles.virtue/", + "head_title" : "Paintball Masks | Paintball Goggles | Thermal Paintball Goggles Masks", + "page_head" : "" + }, + ".airsystems.regulators.km_column" : { + "meta_description" : "KM Column Regulator Cover - Buy your Column KM Cover Online at Zephyr Paintball for Less today. Free Shipping on KM Straps Column Reg Cover Trust Zephyr for all your Paintball Needs", + "top_description2" : "The new KM Straps Column inline regulator grips are now available from Zephyr Paintball! These new grips fit most any marker inline regulator, Planet Eclipse, DYE, MacDev, Angel, CP, Vanguard, BobLong, Luxe, etc. Available in multiple colors to match your marker or team color, or any of the KM Spine feeds. Match all colors or mix it up! The KM Straps Column grip gives you better control of the marker, your hands wont slip or have to grip the hard aluminum reg\nulator when your hands are dirty or oily from paint. They fit nice and tight to the regs and are easy to clean, stain-proof and wont crack or fade.", + "top_description" : "", + "page_title" : "Buy KM Column Regulator Cover Online On Sale Now", + "head_title" : "KM Column Regulator Cover | Column KM Cover | KM Straps Column Reg Cover", + "zoovy:banner01" : "banners/paintball/headers/km_straps_header" + }, + ".markerupgrades.automag_upgrades" : {}, + ".markers.btdesignspaintballguns.empire_bt_d_fender_paintball_marker" : { + "htmlvids" : "", + "top_description" : "== BT D*fender Paintball Marker ==\nThe innovative genius of Empire Paintball has been at it again with the creation of the Empire BT D*Fender. This radical design moves the loader from off the top of the marker and places it within the stock of this bullpup-style masterpiece. The D*Fender has ultra-strong, lightweight magnesium shells with the high performance guts of our markers and a Z2 loader inside. Reduce your silhouette and never take a hit on your loader again. Forget its name, with the D*Fender in your hands, you'll attack!", + "description" : "= Features: =\n* High performance paintball marker with integrated loader\n* Magnesium shells for high strength and light weight\n* Break Beam Eyes in breech prevent ball chops\n* Selector switch with 5 Firing modes – Semi, Burst, Ramping, Full Auto and Select Fire\n* On/Off Regulator with easy-to-mount T-Slot rail\n* Smooth, programmable bearing trigger with 3-way adjustment\n* Removable side Picatinny rails and top Picatinny rails for accessories\n\n= Functions: =\n* Inline pressure controlled poppet firing engine offers accurate fire and smooth shooting\n* Proven Z2 loader performance with auto anti-jam\n* Loader activates upon trigger pull, so constant feeding is guaranteed\n* Capable of firing 20bps with continuous loading\n* Self calibrating loader speed sensor\n* Tool-less basic maintenance/battery change\n* Battery level indicator\n* 6 AA Operation for all electronics\n\n= Included Items: =\n* Includes both a standard magnetic lid and speed feed lid\n* Ported, aluminum barrel with three Super Freak inserts (.680, .685, .690)\n* Additional Super Freak Apex2 barrel that creates shots that curve onto targets\n* Multi-position sling adapter for those long treks to the battlefield" + }, + ".markers.empire_axe_paintball_guns" : { + "meta_keywords" : "empire axe paintball guns,axe paintball gun,axe paintball marker, invert, axe, mini, bt,empire paintball gun", + "meta_description" : "Empire Paintball Guns - The hottest new marker from Empire, the Empire Axe Paintball Marker. Be sure to check out the Empire mini, sniper pump as well as all the new Empire bt gun. Buy them first at Zephyr with Free Shipping", + "top_description" : " Check Out All that Empire Paintball has to offer! Empire paintball covers paintball across the board, no matter your playing style! Woodsball, tournament play, etc.!! Empire Paintball is a worldwide leader in the manufacturing of premium paintball markers. Current models dominating the fields are the Empire Axe, New Empire Mini, Empire Sniper Pump, the newly renovated Empire Resurrection, and now paintball's hottest high end marker the Empire Vanquish. Check Specs, pics, videos and more below! ", + "page_title" : "Buy Empire Paintball Guns Online On Sale Now", + "head_title" : "Empire Paintball Guns | Axe Paintball Gun | Axe Paintball Marker", + "banner01_link" : "%SESSION%/results.cgis?catalog=HOMEPAGE&keywords=KEEHOLIDAY&x=5&y=8", + "zoovy:banner01" : "" + }, + "$leaveempty" : {}, + ".markers.pmi_paintball_guns.pirhana_paintball_packages" : { + "prodlist1_header" : "PMI Pirahna Paintball Gun Packages", + "prodlist_custom" : "&SORTBY=PRICE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&" + }, + ".airsoft.buyers_guide.airsoft_bbs" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Buyers Guide - Airsoft BB's" + }, + ".apparel.gloves.paintball_gloves_by_size.4.large_paintball_gloves" : { + "page_title" : "", + "head_title" : "Large Paintball Gloves | Large Gloves for Paintball | Large Paintballing Gloves" + }, + ".backpacks.camelback_backpacks.camelbak_winter_hydration_packs.women_s_camelbak_scorpion_hydration_packs" : {}, + ".apparel.gloves.empire_paintball_gloves" : { + "meta_keywords" : "empire paintball gloves,paintball glove,empire contact gloves,empire ltd gloves,fingerless paintball gloves", + "meta_description" : "Empire Paintball Gloves - Empire Contact Gloves on sale at Zephyr Now. Free Shipping on orders over $100. Get your Empire LTD Paintball Gloves at Zephyr Paintball Now", + "page_title" : "", + "head_title" : "Empire Paintball Gloves | Empire Contact Gloves | Empire LTD Gloves" + }, + ".apparel.jerseys.v-tac_paintball_jerseys" : { + "page_title" : "", + "head_title" : "V|Tac Camo Paintball Jerseys | VTAC Camo Jersey | VTAC Paintball", + "sortby_var" : "Camo Pattern", + "prodlist1_header" : "Valken V-Tac Paintball Jerseys" + }, + ".apparel.pants.rothco_bdu_pants" : {}, + ".markerupgrades.proto_slg_upgrades.proto_slg_triggers" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.proto_el_paintball_masks" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_editor_sunglasses" : { + "meta_description" : "Smith Optics Editor Sunglasses - Zephyr Sports carries a complete line of Editor Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Editor Sun Glasses Online Today.", + "page_title" : "Smith Optics Editor Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Editor Sunglasses | Editor Smith Sunglasses Free Shipping | Buy Smith Editor Sun Glasses" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.echo_1_electric_airsoft_rifles.m4___m16_echo_1_airsoft_guns" : { + "meta_description" : "Echo1 Sub Gun - Buy your Echo 1 Airsoft Sub Machine GunAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Echo1 Sub Gun On Sale & Free Shipping", + "head_title" : "Echo1 Sub Gun | Echo 1 Airsoft Sub Machine Gun" + }, + ".casual_clothing.youth_clothing.youth_hats" : {}, + ".empire_prophecy_paintball_loader.empire_prophecy_z2_paintball_loader" : {}, + ".goggles.gi_sportz_paintball_goggles" : {}, + ".markerupgrades.invert_upgrades.boards" : { + "meta_keywords" : "invert mini board,mini virtue board,invert mini ramping board", + "meta_description" : "Invert Mini Board - Buy your Mini Virtue Board Online at Zephyr Paintball for Less today. Free Shipping on Invert Mini Upgrade Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert Mini Board Online On Sale Now", + "head_title" : "Invert Mini Board | Mini Virtue Board | Invert Mini Upgrade Boards" + }, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_ego_10_paintball_guns" : { + "htmlvids" : "", + "meta_description" : "Ego 10 - Buy your Planet Eclipse Ego 10 Paintball Gun Online at Zephyr Paintball for Less today. Free Shipping on Eclipse 2010 Ego Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Ego 10 Online On Sale Now", + "head_title" : "Ego 10 | Planet Eclipse Ego 10 Paintball Gun | Eclipse 2010 Ego" + }, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_i_am_sunglasses" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.ak47_style_aeg_airsoft_magazines" : {}, + ".airsoft.airsoft_apparel.head_gear.full_clip_head_gear" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns2" : { + "meta_keywords" : "C02 Airsoft Guns,Co2 pistols,blow back,non blow back,full metal,airsoft pistol,Cheap Co2 airsoft guns,Co2 airsoft gun", + "meta_description" : "These pistols operate off of 12 gram Co2 cartridges that hold enough Co2 to fire the guns through multiple reloads. Co2 pistols come in both blow back and non blow back as well as full metal or plastic bodies. Similar to green gas, the magazine of the pistol holds both the BBs as well as the Co2 cartridge. Co2 cartridges are an inexpensive way to power an airsoft pistol. For Cheap Co2 airsoft guns, choose Zephyr Sports!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft CO2 Guns | Co2 Airsoft Pistols", + "description" : "" + }, + ".goggles.angel_eye_paintball_goggles" : { + "meta_keywords" : "angel eyes,angel paintball mask,angel paintball goggle,angel eyes paintball goggles", + "meta_description" : "Angel Paintball Mask - Buy your Angel Eyes Paintball Goggle Online at Zephyr Paintball for Less today. Free Shipping on Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Angel Paintball Mask Online On Sale Now", + "head_title" : "Angel Paintball Mask | Angel Eyes Paintball Goggle" + }, + ".casual_clothing.mens_clothing.socks.dvs_socks" : { + "meta_keywords" : "DVS socks,DVS mens socks,DVS men socks", + "meta_description" : "DVS Socks - Zephyr stocks a complete line of DVS Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your DVS needs. ", + "page_title" : "DVS Socks on Sale at Zephyr", + "head_title" : "DVS Socks | DVS Mens Socks | DVS Skate Socks" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_water_bottles.___camelbak_better_bottle_stainless_water_bottles" : {}, + ".barrels.barrels_by_manufacturer.proto_paintball_barrels" : { + "meta_keywords" : "proto paintball barrels, proto barrels, proto barrel backs, proto 1 piece barrel, proto tips, proto back, proto paintball back", + "page_title" : "", + "head_title" : "Proto Paintball Barrels | Proto Barrels | Proto Barrel Backs", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/proto_2piece.jpg\"" + }, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns.delta" : { + "meta_keywords" : "bt delta elite paintball guns,delta elite paintball marker,delta elite paintball", + "meta_description" : "BT Delta Elite Paintball - Buy your BT Delta Elite Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Delta Elite Paintball Marker Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy BT Delta Elite Paintball Guns Online On Sale Now", + "head_title" : "BT Delta Elite Paintball | BT Delta Elite Paintball Guns | Delta Elite Paintball Marker", + "banner02_link" : "/category/3packagespecials.empire_paintball_packages.empire_bt.delta/", + "description" : "The Delta Elite paintball gun has an adjustable stock for a comfortable fit and adjustable range rear sight for accurate shooting. The small, compact size is perfect for Close Quarters combat and the rate of fire will ensure you emerge victorious. The Delta Elite is tough, its baked on coating can withstand impacts and the quality construction assures it will continue to fire. Whether using CO2 or compressed Air, the Delta Elite paintball gun give you the edge over the opposition and guarantee your day will be fun. \n\n\n=Features:=\n\n* Lightweight, Balanced Construction\n* Impact-Resistant, Baked-On Coating\n* Adjustable Stock\n* Works with CO2 or Compressed Air BT Apex Barrel\n* Multi-step trajectory control\n* Allows extended range (even in wooded areas)\n* Offers left hook, right hook or \"drop shot\" curves BT Electronic Grip Frame\n* Double finger trigger\n* Semi-Auto, 10, 13 PSP ramping, 10, 13 NXL full-auto \n* BT Rip Clip with HALO Technology\n* Sound-activated, force-feed loader\n* Holds over 200 paintballs\n", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001" + }, + ".sponsorship.team_sponsorship_packages" : {}, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_sovereign_sunglasses" : { + "meta_description" : "Anarchy Sovereign Sunglasses - Zephyr Sports carries a complete line of Anarchy Sovereign Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Sovereign Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Sovereign Sunglasses | Anarchy Sovereign Sun Glasses" + }, + ".airsoft.tactical_airsoft_gear.airsoft_laser_sights" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.belts.fmf_belts" : { + "meta_description" : "FMF Belts - Buy your FMF Mens BeltsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on FMF BELTS @ Zephyr Sports", + "head_title" : "FMF Belts | FMF Mens Belts | Mens Belt FMF" + }, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.bb_grenade_launchers___shells" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Grenade Launchers | Airsoft Launchers | Grenade Launcher for Airsoft" + }, + ".markers.paintball_pistols" : { + "meta_keywords" : "Paintball pistol,paintball pistols,paintball hand gun,sidearm,tippmann tpx,tiberius t8,8.1,Umarex .43 cal", + "meta_description" : "Paintball Pistols - Don't be left out empty handed. Carry a Paintball Pistol into battle and you'll be ready when you run out of paint. Zephyr Carries a complete line of pistols from Tippmann, Kingmann, Tiberius Arms, BT and More.", + "top_description" : "Looking for a sidearm to back you up in the heat of the battle?! Search no more! Complete line of Paintball Pistols across a wide range of top manufacturers! Kingman, Tiberius Arms, BT Battle Tested, Tippmann, Umarex, Rap 4 and more! Full supply of specially gauged paintball pistol projectiles, magazines, holsters and other accessories. Don't fall short on the field, gear up and always be prepared with your own back up plan!", + "page_title" : "Buy Paintball Pistols Online On Sale Now", + "head_title" : "Paintball Pistols | Paintball Pistol | 68 Cal Paintball Pistol", + "description" : "==Tiberius Arms T8.1==\nThe new standard for paintball pistols. The T8.1 comes equipped to fire the revolutionary new First Strike projectiles, in addition to standard .68 caliber paintballs. The new hard anodized, solid aluminum upper receiver allows a remote to be attached directly to the marker (optional remote kit required) and provides unmatched durability. Player's will also appreciate the removable under-mount tac-rail, side dovetailed iron sights, and dual rubber detents that improve versatility and performance. The transformation wasn't complete without upgrading the magazine a lightweight, all metal mag that field strips for cleaning in seconds, and features a low profile tool-less quick puncture for changing 12 grams on the fly. Consider the bar raised!\n\n\n==BT SA-17==\nBold profile and big performance. Built on the successful US-P platform, this new paintball pistol has a precision milled aluminum body for durability and a new spring feed system that can feed forwards or backwards. Utilizing full-size internals means this gun will perform like the big boy it is and dominate your opponents on the field. Featuring multiple Picatinny rails, the SA-17 is designed with a military-inspired look and can accept cool aftermarket accessories. The quick change CO2 system and easy feed tube loading means you won't get caught short when the enemy counterattacks. Grab a SA-17 and remember that size matters when the game is on the line.\n\n\n==Tippmann TPX==\nThe new TPX .68 Caliber Paintball Pistol boasts an innovative, compact design, specially engineered to be lightweight, easy to maintain, customizable, and best of all, dependable. To take the performance of the TPX to a new level, the pistol will now include two of the new Tru-Feed Straight Stack magazines. The new Tru-Feed Magazine uses a straight feed, low tension spring system that allows the player to use a wider variety of paint and is less affected by hot or humid conditions.\n\n\n==UMAREX P99 RAM==\nThe Walther P99 Real Action Marker Paintball pistol is the ultimate in reality training. RAM products are replicas of the actual firearm and utilize clips containing either .43 caliber paintballs or .43 caliber rubber balls. Rubber balls are commonly used for military, police, or other authority training. This P99 RAM is powered by one 12g CO2 capsule. It looks, feels and shoots with great accuracy just like the real P99 for virtual reality paintball. Comes in a foam-lined, black, hard plastic gun case. Additional .43 caliber magazines are available. RAM markers are used extensively in milsim (military simulation) and police force training situations.\n\n\n \n==Rap 4 Combat==\nThe RAM Combat Pistol is made in the likeness of one of the most popular duty sidearms. This Real Action Marker is authentic in weight, feel, and action, right down to the realistic kick of its blowback slide. The Combat Pistol can quickly and accurately shoot .43 caliber paintballs or rubber training rounds at a range of 50-70 ft.\nThis RAM Combat Pistol is the most compact paintball pistol ever made, and is designed to be compatible with standard duty holsters. For law enforcement training, the Combat Pistol affords officers the ability to train as realistically as it gets. The Combat Pistol allows officers to use the duty gear they already have, and allows them to incorporate their training - weapon control, carry and hand positions, even point of aim - as if they are in a real situation.\nThe RAM Combat Pistol can also be used as a paintball gaming pistol for close-range combat and backup. When your other marker is too big to carry through the SWAT House, go for the Combat Pistol and own the scenario. It features an integrated accessory rail and a drop-free 8-shot magazine. The Combat Pistol fits duty and tactical holsters, and is powered by a single 12 gram CO2 cylinder located in the grip.\n\n" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_aura_sunglasses" : { + "meta_description" : "Smith Optics Aura Sunglasses - Zephyr Sports carries a complete line of Aura Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Aura Sun Glasses Online Today.", + "page_title" : "Smith Optics Aura Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Aura Sunglasses | Aura Smith Sunglasses Free Shipping | Buy Smith Aura Sun Glasses" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_axis_watches" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.sly_profit_paintball_masks" : {}, + ".scenarioupgrades.tactical_vests.v-tac_vests_and_accessories" : {}, + ".airsoft.shop_by_brand.condor_tactical" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".apparel.knee___elbow_pads.valken_knee_and_elbow_pads" : { + "page_title" : "", + "head_title" : "Valken Elbow Pads | Valken Knee Pads | Valken Paintball Protection" + }, + ".maddog.autococker_upgrades" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_screw_sunglasses" : {}, + ".sponsorship.sponsor_only_specials.guns_and_gear" : {}, + ".paintballs.dye_paintballs" : {}, + ".apparel.knee___elbow_pads.dye_knee___elbow_pads" : { + "page_title" : "", + "head_title" : "Dye Core Elbow Pads | Dye Core knee Pads | Dye Elbow Pads", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".apparel.jerseys.dyejerseys.dye_ultralite_paintball_jerseys" : { + "top_html_focus" : "", + "meta_description" : "Dye Ultralite Paintball Jersey - Once againe Dye revolutionizes paintball clothing with the limited edition ultralite jersey. Four way stretch gives you comfort and breathability in a paintball jersey that has never been seen before. Buy your Dye Utralite gear at Zephyr Paintball.", + "top_description" : "The Dye Ultralite Paintball Jersey brings four way stretch and comfort to paintball. You've seen four way stretch in Boardshorts, Now brings that comfort to paintball. Wear what the pros wear with the Limited Edition Dye Ultralite series paintball jersey.", + "page_title" : "Dye Ultralite Paintball Jersey at Zephyr Paintball", + "head_title" : "Dye Ultralite Paintball Jersey | Dye Ultralite Jersey" + }, + ".3packagespecials.empire_paintball_packages.empire_bt.delta" : { + "meta_keywords" : "BT 4 Delta Paintball,BT-4 Delta Paintball Guns,Delta Elite Paintball Marker,paintball gear,paintball guns,BT Paintball,BT Combat Slice, ERC", + "meta_description" : "BT-4 Delta Paintball Gun - Battle Tested Delta Paintball Guns are high quality, super durable paintball guns! Lightweight and reliable paintball markers that won't let you down! Customize and complete your BT Delta Elite Paintball Gun with BT Paintball Gear; loads of marker upgrades and scenario accessories available!", + "top_description" : "For the scenario or woodsball player who wants realism, BT Paintball offers the BT4 Delta paintball gun. Based on the MP5, most recognizable submachine gun in the world, BT has created a compact, accurate paintball marker that looks like it should be carried by SEALs. The Delta paintball gun has a lightweight, balanced construction for all day play and an adjustable stock for a comfortable firing position. The clamping feedneck will accept loaders without the need for tools, or upgrade to a BT Rip Clip for HALO powered force feed loading. The Delta gun has a modular trigger, so taking it apart for cleaning is simple, and easily upgrades to the Double Trigger or the Electronic Grip Frame for increased firepower. The compact BT4 Delta is an accurate, reliable paintball gun with an authentic look that will help you and your team reign supreme on the battlefield.", + "page_title" : "Buy BT Delta Paintball Packages Free Shipping @ZephyrPaintball", + "head_title" : "Empire BT Delta Elite Paintball Guns Markers and Packages", + "description" : "=Features:=\n\n* Slide-Away feedport for easy cleaning and maintenance.\n* Lightweight, balanced construction\n* Impact-resistant, backed-on coating\n* Modular trigger system\n* Adjustable stock\n* Upgradeable to accept BT Rip-Clip and BT Electronic Grip Frame\n* Removable grip frame for quick and easy upgrades\n* Works with CO2 or compressed air" + }, + ".loaders.hopper_accesories.dye_loader_accesories.dye_rotor_color_accent_kits" : { + "meta_description" : "Dye Rotor Color Kits - Buy your Dye Rotor Color Accent Kits Online at Zephyr Paintball for Less today. Free Shipping on Rotor Accesory Kits Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Rotor Color Kits Online On Sale Now", + "head_title" : "Dye Rotor Color Kits | Dye Rotor Color Accent Kits | Rotor Accesory Kits" + }, + ".apparel.knee___elbow_pads.empire_knee___elbow_pads" : { + "page_title" : "", + "head_title" : "Empire Elbow Pads | Empire Knee Pads | Empire Paintball Protection" + }, + ".airsoft.airsoft_bbs_ammo.game_face_airsoft_bbs" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 Gameface Airsoft Bio BBs | .25 Gram Gameface Airsoft Pellets | .20 G Game Face Biodegradeable Ammo for Airsoft Guns" + }, + ".apparel.head_bands_and_wraps.virtue_headbands_and_wraps" : { + "head_title" : "Virtue Headband | Virtue Headwrap | Virtue Head Band" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_fixed_power_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Centerpoint scope | scope centerpoint | " + }, + "$bob_export" : {}, + ".casual_clothing.mens_clothing.watches.lrg_watches" : {}, + ".harnessesbags.backpacks.1_shop_by_bag_style.harnessesbags.backpacks" : {}, + ".casual_clothing.mens_clothing.jackets.anti_hero_jackets" : { + "meta_description" : "Anti Hero Jackets - Buy your Anti Hero Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Anti Hero Jackets with Free Shipping", + "head_title" : "Anti Hero Jackets | Anti Hero Mens Jackets | Antihero Skate Jackets" + }, + ".airsystems.tankcovers.bottle_covers_by_tank_size.88_to_92_ci_bottle_covers" : { + "meta_description" : "88 92ci Tank Cover - Buy your 88 Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on 92 Paintball Bottle Covers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 88 92ci Tank Cover Online On Sale Now", + "head_title" : "88 92ci Tank Cover | 88 Tank Cover | 92 Paintball Bottle Covers" + }, + "$nateslistaug8" : {}, + ".casual_clothing.z_unisex_clothing_accesories.stickers.hk_army_stickers" : {}, + "barrels.barrels_by_manufacturer.dye_paintball_barrels.dye_barrel_tips" : {}, + ".airsoft.airsoft_bbs_ammo.umarex_elite_force_airsoft_bb_s" : { + "head_title" : "Elire Force BB's | Elite Force Bio BB" + }, + ".casual_clothing.mens_clothing.jackets.dye_jackets" : { + "meta_description" : "Dye Jackets - Buy your Dye Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Dye Jackets with Free Shipping", + "head_title" : "Dye Jackets | Dye Mens Jackets" + }, + ".3packagespecials.gryphon_starter_packages" : { + "meta_description" : "Tippmann Gryphon Paintball Guns Packages - Buy your Gryphon Starter Kits Online at Zephyr Paintball for Less today. Free Shipping on Gryphon Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann Gryphon Paintball Guns Packages Online On Sale Now", + "head_title" : "Tippmann Gryphon Paintball Guns Packages | Gryphon Starter Kits | Gryphon Paintball Markers" + }, + ".airsoft.airsoft_gun_magazines.bb_speed_loaders" : {}, + ".airsoft.airsoft_apparel.camoflouge_shorts" : {}, + ".2clearance.clearance_knee___elbow_pads" : { + "head_title" : "Sale Paintball Knee Elbow Pads | Clearance Paintball Knee Elbow Pads | Paintball Knee Elbow Pads Sale" + }, + ".paintball.paintball_guns.planet_eclipse_ego_paintball_guns.planet_eclipse_etha_paintball_guns" : {}, + ".scenarioupgrades.tactical_vests.dye_tactical_vests.dye_tactical_vest_accessories" : {}, + ".barrels.barrels_by_manufacturer.inception_designs_paintball_barrels" : { + "meta_keywords" : "inception barrels, inception paintball barrels, inception barrel backs, cheap paintball barrels, inception designs paintball barrels, inception barrel kits, inception barrel tips, barrel back, barrel tips, barrel fronts, inception paintball, full inception barrels, complete paintball barrels, raw inception barrels, matte black inception barrels", + "meta_description" : "Inception Designs Paintball Barrels - Mix and Match with Inception Paintball Barrels! Barrel tips, barrel backs, and complete barrel kits available! Buy Inception Designs Paintball Barrels today @ Zephyr Paintball!", + "top_description" : "The Stella Barrel system has arrived! Designed to be gentle on paint, consistent, efficient, quiet and as accurate as a paintball gun barrel can be. Constructed of CNC'd 6061 Aluminum, the Stella barrel system is the ultimate choice for superiority in customization and accuracy.\n\n\nMix, match, and create the perfect barrel for your marker! Customize everything from the length to the bore size! Inception Designs is all about the development of new, innovative paintball equipment and offer the finest gear for paintball athletes; all made right here in America!", + "page_title" : "Buy Inception Paintball Barrels Online On Sale Now", + "head_title" : "Inception Designs Paintball Barrels | Inception Paintball Barrel | Inception Paintball Barrel Backs" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.fallen_pants_and_jeans" : { + "meta_description" : "Fallen Pants - Buy your Fallen Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Fallen Pants & Jeans Ship Free", + "head_title" : "Fallen Pants | Fallen Jeans" + }, + ".001a_zephyr_paintball_sports_promotions_deals_sales.t9_marker___conversion_kit" : { + "prodlist2_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=LIST%3A%24leaveempty&ALTERNATE=0&SHOWSKU=&", + "prodlist1_header" : "SAVE $70.00 - Buy any T9 Marker & Get the Conversion Kit for $69.95", + "zoovy:banner01" : "banners/categories/t9_conversionkit_discount_header.jpg", + "prodlist_custom" : "&SORTBY=PRICE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&", + "description" : "===First Strike Conversion Kit Details:===\n\n\nUtilizing a combination of aerodynamic shape and fin stabilization technology, First Strike projectiles maintain their velocity longer. The result is 50% greater range and unrivaled accuracy. Finally players have an alternative to accuracy by volume or backspin gimmicks that simply change trajectory. Become one of the first true paintball snipers with First Strike.\n\n\n=First Strike Paintball Features:=\n*Fin Stabilized - Self-rifling provides superior range and accuracy.\n*Brittle Polystyrene Shell - Allows breakage on targets at extended range. Withstands extreme temperatures, moisture and humidity. Photodegradable and environmentally friendly.\n*Ultra-Thick Fill - Superior marking and visibility.\n*.68 Caliber - Compliant with ASTM safety requirements.\n*Accurate at 100 yards \n\n=T9 Conversion Kit Features:=\n*Conversion kits still allow firing of standard paintballs.\n*T9's can use standard paintballs in the hopper and First Strike in the magazine.\n*Users can select the type of projectile being fired during a game.\n*Includes Barrel, Mag, Bolt, and Ammo." + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts.oakley_replacement_lenses.oakley_gas_can_replacement_lenses" : { + "meta_description" : "Oakley Gas Can Lenses - Zephyr Sports carries a complete line of Gas Can Oakley Replacement Lenses At the lowest prices on the web with free shipping and easy returns. Buy your Gas Can Oakley Lenses Online Today.", + "page_title" : "Oakley Gas Can Lenses On Sale Free Shipping", + "head_title" : "Oakley Gas Can Lenses | Gas Can Oakley Replacement Lenses | Gas Can Oakley Lenses" + }, + ".safetygear.nxe_paintball_protective_gear" : {}, + ".markerupgrades.grips_and_grip_panels.empire_paintball_grips" : {}, + ".safetygear" : { + "subcat1_header" : "", + "meta_keywords" : "Paintball protective gear, paintball padding, paintball protection, chest protector, knee pads, elbow pads, paintball gear, safety gear, paint ball gear, cheap paintball gear, safety, safety gear", + "top_html" : "
                                                                          \n\t
                                                                          \n\t\t\n\t\t\n\t
                                                                          \n
                                                                          ", + "meta_description" : "Paintball Protection - Get all your Paintball Protective Gear at Zephyr Today. Free Shipping Low Prices. Play Smart, Play Safe with your safety Gear from the worlds largest paintball store.", + "zoovy:banner_image_01" : "banners/categories/safetygear_banner01", + "banner02_link" : "/category/goggles/", + "zoovy:banner01" : "", + "zoovy:banner02" : "banners/paintball/headers/safety__goggles", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/safety_header.jpg\"", + "dynimage1" : "images=banners/paintball/slideshow/safe_pb_protective_gear\nlinks=\npauses=2000\nblank_behavior=none\n", + "top_html_focus" : "", + "banner1" : "banners/09_headers/main_categories/safety_gear_001", + "head_title" : "Paintball Protection | Paintball Protective Gear | Safety Gear", + "page_title" : "Paintball Protective Gear on Sale at Zephyr", + "sortby_var" : "Category", + "page_head" : "" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_maui_cat_iii_sunglasses" : { + "meta_description" : "Maui Jim Maui Cat Sunglasses - Zephyr Sports carries a complete line of Maui Jim Maui Cat Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Maui Cat Online Today.", + "page_title" : "Maui Jim Maui Cat Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Maui Cat Sunglasses | Maui Jim Maui Cat Sun Glasses | Sunglasses Maui Jim Maui Cat" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_barrels.tippmann_flatline_barrels" : {}, + ".markerupgrades.tippmann.model98customandpro.tippmann_98_factory_repair_parts" : {}, + ".barrels.spyder.16__spyder_paintball_barrels" : { + "meta_description" : "16 inch Spyder Paintball Barrels - Buy your 16\" Spyder Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Spyder Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 16 inch Spyder Paintball Barrels Online On Sale Now", + "head_title" : "16 inch Spyder Paintball Barrels | 16\" Spyder Threaded Upgrade | Spyder Paintballs Barrels" + }, + ".airsoft.airsoft_guns.wg_airsoft_guns" : { + "meta_description" : "WG Airsoft Guns - Buy your WG Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of WG AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy WG Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "WG Airsoft Guns | WG Airsoft Rifles | WG AEG" + }, + ".airsoft.airsoft_apparel" : {}, + ".markers.dangerous_power_paintball_guns" : { + "meta_keywords" : "Dangerous Power, Dangerous Power G3 Paintball Guns, Dangerous Power Paintball Guns, Dangerous Power Guns, Dangerous power markers, Cheap Dangerous Power, G3 paintball marker, Revi Paintball gun", + "meta_description" : "Dangerous Power Paintball - The new marker from dangerous power brings tournament performance at an entry level price. The Dangerous Power G3 Paintball guns is one of the lightest most efficient markers on the tournament scene today", + "top_description2" : "", + "top_description" : "==Dangerous Power Paintball==\n\nDangerous Power Paintball was created by a team of world class engineers who share a vision in creating the most innovative, groundbreaking products the paintball industry has ever seen. Whether you choose the incredibly value packed Fusion, the sleek new F8, the ultra-rare Threshold, or the cutting edge simplicity offered by the G3, you can play with confidence knowing that you possess one of the world's finest engineered products. ", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.dangerous_power_paintball_packages/", + "description" : "==Dangerous Power E1 Paintball Gun==\n\nThe Dangerous Power E1 Paintball Gun will be released in Mid December. We will begin taking pre-orders Shortly. The Dangerous Power E1 will be available in Black/Black & Blue/Black.\nOptimum Performance at a Lower Price The E1 touches the fine points of Dangerous Power's accomplishments and performance. The E1's strengthened core is constructed of our distinguished & popular \"Dump-Valve System\" & is equipped with a micro-switch board capable of firing in Semi-auto mode & Full-auto fire modes capped at 25 bps. High Pressure Regulator The E1's high pressure regulator is composed of the G3's highly accurate OPR system & internals. The E1's OPR's operation is service-friendly & easy to maintain. Dump Valve Bolt System The E1's Dump Valve system is one of the finest and very efficient firing systems for Dangerous Power's spool valve markers. Maintenance for the fire assembly is simple & is constructed of 2 moving parts. The E1's fire assembly and operation proceeds from the G3's heritage, DP's greatest achievement.\n\n\n==Dangerous POwer Fusion FX Paintball Gun==\n\nThe long awaited FX finally takes a stand and delivers dangerous and cutting edge technology to the Fusion Series. The Fusion FX takes a prideful stand and fierce introduction for the new decade! Through intricate design and development, the Fusion series conjures powerful attributes making it a new class of Dangerous Power markers.\nFrom superior quality, the FX's newly designed internals ensure dominating performance. The slim striker system's compact performance aims to deliver efficiency and accuracy. The lightweight body and internals ensures quick mobility for a fast response time.\nThe OLED micro-switch board is capable of programming tournament modes and much more. The Fusion X grasps the balance of raw power, accuracy, and mobility all at an affordable price. Dangerous Power is proud to unleash the new generation of Fusions - The FX. \n\n\n==Dangerous Power G3 Spec R Paintball Gun==\n\nAfter weeks of anticipation and assumptions, the all new Dangerous Power G3 Spec-R is ready to be released. We retained all the great aspects that made the G3 a paintball house hold name but listened to all the advice the fans gave.\n\nThe Dangerous Power G3 was one of the smallest and lightest markers in paintball, and the DP went ahead and made it even smaller and lighter. Weighing in at less that 1.8lbs,(barrel and battery included) that officially makes the G3 Spec-R the lightest paintball marker around. Even though smaller and lighter, the Spec-R does not sacrifice comfort or performance. Following the same \"dump valve\" design, the G3 Spec-R offers an o-ring-less bolt design that not only increases the efficiency but also the longevity of the o-rings, in addition, the G3 Spec-R comes stocked with a fully programmable micro-switch board that offers all the necessary tournament modes and ability to adjust multiple set points. Combine the board with our fully adjustable magnetic ball bearing trigger to get the G3 Spec-R ready for all players, at any level! \n\n\n==Dangerous Power G4 Paintball Gun==\n\nThe G4 has now arrived and invokes the triumphs and prosperity of Dangerous Power's advanced engineering through its innovations and master craftsmanship. The G-Series is reborn and leaves the competition in its wake. The G4 weighs in at 1.79lbs including barrel, RAPS ASA, low-profile clamping feedneck, & battery. The G4 has adapted the Spec-R's accuracy and efficiency by utilizing the O-ring-less bolt system. The O-ring-less bolt not only improves the G4's performance, but also decreases O-ring wear and tear resulting in less maintenance! The G4 demands precision and comfort by adopting the Rev-I's four-way trigger adjustment including the breakaway magnetic trigger. The G4 includes a new, fully engineered, spring-assisted regulator increasing its accuracy and durability. Dangerous Power Engineering has enforced qualities in the G4 to adapt to change and overcome any scenario by implementing a fully programmable micro-switch board for every player's preference. Presenting strength, power and dexterity guarantees fulfillment with the G4.\n\n\n==Dangerous Power Rev-I Paintball Gun==\n\nThe Dangerous Power Rev-i paintball gun (pronounced Revy) represents the latest and greatest in technology by being one of the best innovative paintball guns on the market. Players have never been so in touch with their own Paintball gun till now; with its see through design for close attention to the o-rings and bolt, swiveling rake style to sling style adjustable trigger, pressure gauge located on the back of the gun and much more to impress. Taking a look internally we will find one of the best designed boards with a 35+ Balls Per Second capability. No need for dip switches; so don't even think about opening your grips to change modes. The simplicity of the OLED board is astonishing, designed by APE; you get a user friendly interface that will not disappoint. The bolt is a one piece, one moving part design being light and efficient. It is also easily removable down the front of the barrel with just a few turns by a provided Allen Wrench. Experience being in control with every aspect of your gun weather it is adjusting the trigger, changing barrels and even programming the board to your specific needs. ", + "page_title" : "Buy Dangerous Power Online On Sale Now", + "head_title" : "Dangerous Power | Dangerous Power Paintball Guns | Dangerous Power Paintball Marker", + "sortby_var" : "Dangerous Power Gun Type" + }, + ".casual_clothing.mens_clothing.socks.matix_socks" : { + "meta_keywords" : "Matix socks,Matix mens socks,Matix men socks", + "meta_description" : "Matix Socks - Zephyr stocks a complete line of Matix Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Matix needs. ", + "page_title" : "Matix Socks on Sale at Zephyr", + "head_title" : "Matix Socks | Matix Mens Socks" + }, + ".barrels.barrels_by_manufacturer.dye_paintball_barrels" : { + "meta_keywords" : "dye ultralite, dye paintball barrels, dye ultralite barrels, dye barrel backs, dye barrel tips, light paintball barrels, dye paintball barrels, dye autococker back, dye spyder back", + "meta_description" : "Dye barrels are one of the most accurate barrels on the market. Used by many pros, it's chosen for its aluminum construction that gives a lightweight advantage.", + "zoovy:banner01" : "", + "description" : "The DYE Ultralite Paintball barrel is the favorite of today's top pros. The Ultralite is chosen for its all aluminum light weight advantage and dead on accuracy. It is also a very popular custom paintball barrel upgrade because its aluminum construction offers the ability to be anodized to match any gun color. It is made with the same precision quality that you can expect from DYE as the leader in barrel manufacturing. \n\n\n\n\nBe sure to remember that you need a Dye Ultralight barrel back and barrel tip to complete the Dye Ultralight paintball barrel system. Ultralight barrels are available for Autococker, Spyder, Impulse/Ion, and Tippmann threaded paintball guns.", + "banner1" : "banners/categories/dye_barrel_header_001.jpg", + "page_title" : "Buy Dye Ultralite Online On Sale Now", + "head_title" : "Dye Ultralite | Dye Paintball Barrels | Dye Ultralite Barrels", + "sortby_var" : "Dye Ultralight Barrel Type" + }, + ".markers.cci_paintball_guns.cci_stock_class_paintball_guns" : {}, + ".casual_clothing.mens_clothing.beanies.north_face_beanies" : { + "meta_keywords" : "North Face beanie,North Face hat,North Face beanies,North Face caps,North Face 686,North Face headwear,North Face cuff visor beanie,North Face beanie hat,North Face visor beanie,North Face visor beanies", + "meta_description" : "North Face Deanie - Surf style with North Face Beanies available now at Zephyr Sports. Get your North Face hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "North Face Beanies on Sale at Zephyr Today", + "head_title" : "North Face Beanie | North Face Hat | North Face Beanies" + }, + ".casual_clothing.mens_clothing.belts.enjoi_belts" : { + "meta_keywords" : "Enjoi Belts,Enjoi Belt,Enjoi Skate Belt,enjoi panda belt,enjoi mens belt", + "meta_description" : "Enjoi Belts - Huge selection of Enjoi Skate Belts available online at Zephyr Sports. Always the best price, Always free shipping over $75. Buy your Enjoi Belt online Now!", + "page_title" : "Enjoi Skate Belts on Sale at Zephyr Now", + "head_title" : "Enjoi Belts | Enjoi Belt | Enjoi Skate Belt" + }, + ".apparel.knee___elbow_pads.planet_eclipse_knee___elbow_pads" : { + "page_title" : "", + "head_title" : "Planet Eclipse Elbow Pads | Planet Eclipse Knee Pads | Planet Eclipse Paintball Protection" + }, + ".casual_clothing.mens_clothing.hats.quicksilver_hats" : { + "meta_keywords" : "Quicksilver Hats,Quicksilver caps,Quicksilver baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Quicksilver Hats - Zephyr carries a complete line of Quicksilver Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Quicksilver", + "page_title" : "Quicksilver Hats on Sale at Zephyr", + "head_title" : "Quicksilver Hats | Quicksilver Caps | Quicksilver Baseball Hats" + }, + "$featureditems" : {}, + "$squeegees" : {}, + ".casual_clothing.z_shoes_and_footwear.metal_mulisha_shoes_and_sandals" : {}, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels.freak_barrel_system.freak_barrel_backs" : { + "page_title" : "", + "head_title" : "Freak Barrel Back | Freak Paintball Barrels | Freak Barrel Kits" + }, + ".markers.tippmann.tippmann_cronus_paintball_guns" : { + "meta_keywords" : "tippmann Cronus paintball guns, cronus tippmann paintball guns, tippmann cronus marker, tipman, tippman, tipmann paintball gear,tippman cronus paintball gun, tippmann kronus gun, tippmann cronnus, tippmann", + "meta_description" : "Tippmann Cronus Paintball Guns - Zephyr brings you the leader in scenraio paintball guns. Cronus paintball guns offer affordable performance from a scenario marker.", + "page_title" : "Buy Tippmann Cronus Paintball Guns Online On Sale Now", + "head_title" : "Tippmann Cronus Paintball Guns | Cronus Tippmann Paintball Guns | Tippmann Cronus Marker" + }, + ".1historical_products.paintball.paintball_upgrades" : {}, + ".airsoft.airsoft_bbs_ammo" : { + "meta_keywords" : "bio bbs,biodegradable bbs,biodegradable ammo,.12 gram bb,airsoft bb,airsoft ammo\r .20 gram bb,.25 gram bb,.30 gram bbs,metal bbs\r airsoft paintballs, paintball bbs, paintballs\r ", + "meta_description" : "Airsoft Ammo - Airsoft BBs - Zephyr Sports carries all the airsoft ammo available! Biodegradable bbs come in .12 gram bbs, .20 gram bbs, .25 bbs, and .30 gram bbs! Shoot these 6mm airsoft BB's today and they're gone tomorrow! Combine airsoft and paintball and what do you get?! Airsoft Paintballs! These paint filled BB's work great with most Airsoft BB guns. For when you can't get into the real came, use Airsoft paintballs!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft BBs | BBs for Airsoft | 6mm BB s Airsoft Pellets" + }, + ".casual_clothing.mens_clothing.hats.hurley_hats" : { + "meta_keywords" : "Hurley Hats,Hurley caps,Hurley baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Hurley Hats - Zephyr carries a complete line of Hurley Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Hurley", + "page_title" : "Hurley Hats on Sale at Zephyr", + "head_title" : "Hurley Hats | Hurley Caps | Hurley Baseball Hats" + }, + ".casual_clothing.z-sunglasses.fox_racing_sunglasses" : {}, + ".casual_clothing.mens_clothing.beanies.burton_beanies" : { + "meta_keywords" : "Burton beanie,Burton hat,Burton beanies,Burton caps,Burton 686,Burton headwear,Burton cuff visor beanie,Burton beanie hat,Burton visor beanie,Burton visor beanies", + "meta_description" : "Burton Deanie - Surf style with Burton Beanies available now at Zephyr Sports. Get your Burton hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Burton Beanies on Sale at Zephyr Today", + "head_title" : "Burton Beanie | Burton Hat | Burton Beanies" + }, + ".casual_clothing.mens_clothing.hats.oakley_hats" : { + "meta_keywords" : "Oakley Hats,Oakley caps,Oakley baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Oakley Hats - Zephyr carries a complete line of Oakley Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Oakley", + "page_title" : "Oakley Hats on Sale at Zephyr", + "head_title" : "Oakley Hats | Oakley Caps | Oakley Baseball Hats" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_fixed_power_scopes.nc_star_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "NC Star Scopes | NC Star light | NC Star red dot" + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.ak47_airsoft_guns" : { + "meta_description" : "AK47 Airsoft Guns - Buy your AK 47 Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of Airsoft AK at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "The original AK-47 was one of the first true assault rifles. Even after six decades the model and its variants remain the most widely used and popular assault rifles in the world because of its durability, low production cost, and ease of use. It has been manufactured in many countries and has seen service with regular armed forces as well as irregular, revolutionary and terrorist organizations worldwide. \n\n\nThe AK-47 was the basis for developing many other types of individual and crew-served firearms. More AK-type rifles have been produced than all other assault rifles combined.", + "page_title" : "Buy AK47 Airsoft Guns On Sale & Free Shipping", + "head_title" : "AK47 Airsoft Guns |AK 47 Airsoft Guns |Airsoft AK", + "description" : "" + }, + ".airsoft.airsoft_bbs_ammo.asg_bb_s" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_flak_pack_backpacks" : { + "meta_description" : "Oakley Flak Pack - Buy your Oakley Flack Pack Backpack At Zephyr Sports for Less Today! We carry a complete line of Flak Pack Backpacks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Flak Pack On Sale & Free Shipping", + "head_title" : "Oakley Flak Pack | Oakley Flack Pack Backpack | Flak Pack Backpacks" + }, + ".casual_clothing.mens_clothing.belts.eclipse_belts" : { + "meta_keywords" : "eclipse paintball belt,eclipse belts,eclipse belt,planet eclipse belt", + "meta_description" : "Eclipse Belt - Huge selection of Eclipse Belts available online at Zephyr Sports. Always the best price, Always free shipping over $75. Buy online Now!", + "page_title" : "Eclipse Belt On Sale & Free Shipping", + "head_title" : "Eclipse Belt | Eclipse Belts" + }, + ".shop_by_brand.magpul" : {}, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_speedtrap_polarized_sunglasses" : { + "meta_description" : "Suncloud Speedtrap Polarized Sunglasses - Zephyr Sports carries a complete line of Speedtrap Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Speedtrap Sun Glasses Online Today.", + "page_title" : "Suncloud Speedtrap Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Speedtrap Polarized Sunglasses | Speedtrap Suncloud Sunglasses Free Shipping | Buy Suncloud Speedtrap Sun Glasses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_m2_frame_sunglasses" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4132_full_house_xl_sunglasses" : { + "meta_description" : "Arnette Full House XL Sunglasses - Buy your Arnetter Full House XL At Zephyr Sports for Less Today! We carry a complete line of XL Full House Sunglasses 4132 at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Arnette Full House XL Sunglasses On Sale & Free Shipping", + "head_title" : "Arnette Full House XL Sunglasses | Arnetter Full House XL | XL Full House Sunglasses 4132" + }, + ".markerupgrades.proto_matrix_rail_upgrades.proto_rail_triggers/" : {}, + ".markerupgrades.planet_eclipse_ego_upgrades.ego_feed_necks" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_garage_rock_sunglasses" : {}, + ".markerupgrades.planet_eclipse_etek_upgrades.eclipse_etek_bolts" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_revolution_backpacks" : { + "meta_description" : "Oakley Revolution Backpacks - Buy your Oakley Revolution Bag At Zephyr Sports for Less Today! We carry a complete line of Revolution Oakley Back Pack at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Revolution Backpacks On Sale & Free Shipping", + "head_title" : "Oakley Revolution Backpacks | Oakley Revolution Bag | Revolution Oakley Back Pack" + }, + ".dye_rotor_paintball_loader" : {}, + ".markers" : { + "meta_keywords" : "Paintball Guns,Paintball Markers,Discount Paintball, guns for sale,best paintball guns,buy paintball,Discount,Cheap Clearance,tippmann,spyder,scnario", + "ad3_link" : "%SESSION%/category/markers.1-electronic_paintball_guns_markers/", + "add3_link" : "/category/markers.dye_matrix_paintball_guns.dye_dm8_paintball_guns/", + "top_10_title" : "images/site_specific/most_popular_test_002.jpg", + "description2" : "Zephyr Paintball has Paintball Guns from all the top manufacturers. Smart parts, Kingman Spyder, Tippmann, Proto, and More.We will match competitors prices on all in stock Paintball guns.", + "zs11_banner_wslideshow_slide3" : "ALT=PRICE+DROP%21%21%21+Dye+DM+13+Tournament+Paintball+Guns+On+SALE%21&IMG=banners%2fpaintball%2fslideshow%2fdye_dm13_paintball_makers_slideshow_template%2ejpg&LINK=%25SESSION%25%2fcategory%2fmarkers%2edye_matrix_paintball_guns%2edye_dm13_paintball_guns%2f", + "zs_banner_right1" : "ALT=&IMG=&LINK=", + "banner4" : "banners/categories/small_header/dm8_pricedrop_849_small_header_002.jpg", + "page_title" : "Buy Paintball Guns Online On Sale Now", + "zs_banner_right2" : "ALT=BT+Omega+Paintball+Gun&IMG=&LINK=%25SESSION%25%2fcategory%2fmarkers%2ebtdesignspaintballguns%2ebt_omega_paintball_guns%2f", + "ad2_link" : "%SESSION%/category/markers.cheap_paintball_guns/", + "zs11_banner_wslideshow_slide2" : "ALT=Tippmann+Crossover+Paintball+Marker+On+SALE+Now%21&IMG=banners%2fpaintball%2fslideshow%2f1_tippmann_crossover_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2fmarkers%2etippmann%2etippmann_crossover_paintball_guns%2f", + "add1_link" : "/category/markers.dangerous_power_paintball_guns.dangerous_power_rev_i_paintball_gun/", + "subcat1_header" : "Paintball Gun Categories", + "meta_description" : "All Paintball Guns on Sale! So many choices when it comes to paintball guns. Paintball Markers for Speedball vs. scenario? Pump vs. electric? Which one do I get? Don't be afraid, just give us call at 805-275-2040 and we can help you choose your next cheap paintball gun. ", + "top_description" : "Shopping for Paintball Guns? Zephyr Paintball has you covered. We stock a complete line of paintball markers from all the top vendors at the lowest prices on the web. Check out what we have on sale today or chat with the staff from Zephyr to choose the ultimate paintball gun for you.", + "ad1" : "banners/paintball/side_banners/1_semi_auto_paintball_guns_sidebanner.jpg", + "description" : "==Paintball Guns==\n\n\nZephyr Paintball keeps in stock the full line of paintball guns, paintball markers, Package sets and starter kits for the paintball enthusiast. We have been in the paintball business since 2004. We are paintball players who know the sports and have played paintball for years. Needs some help choosing the right gear? Give us a call or use our live chat to get all of your questions answered. Our paintball shop carries a full line of Paintball Guns from Azodin, Dangerous Power,BT Paintball, Dye, Empire Paintball, Proto, Spyder,Tippmann, Tiberius, JT USA, Gog, Smart Parts, Invert and Planet Eclipse paintball markers, as well as other discount paintball Guns and paintball markers. Our line of Paintball guns continue to grow daily with the BT TM7, Tippmann X7 Phenom, Custom 98, and Tippmann A5, as well as Planet Eclipse guns the Etha, Etek 4, Ego and Geo. For Dye and Proto we have the DM, DAM, Dye NT, Proto Rail and Proto Reflex Rail.\n\n\n=Semi Automatic Paintball Guns=\nCheap Paintball Guns are typically of the Semi Auto variety. Ranging from $40 up to about $150, Semi-auto paintball guns will fire as fast as you can pull the trigger. Limited to around 5-10 BPS (Balls per second) these are great entry level paintball guns when you are playing against pump paintball guns or other semi auto markers. Don't expect to keep up with Electronic guns though.\n\n\n=Electronic or Automatic Paintball Guns=\nWhen your looking for firepower, you need to go with an electronic paintball gun. Using an Electronic board to increase your rate of fire will give you the firepower to spray your friends with a wall of paintballs. Automatic paintball guns start around $100 and range up to $2000. some of the features of the different markers include electronic vision eyes so the pinabtll gun will only fire when you have paintballs in the chamber to reduce the chances of chopping paint. As you move to the higher price point in this category, you have multiple and programmable firing modes, full auto, 3 shot burst as well as NPPL, PSP and other tournament modes. You can adjust your rate of fire, dwell and numerous other settings. For most people, you'll never need the high end tournament paintball guns, but if your willing to spend the extra money you will be amazed at the difference.\n\n=Alien Paintball Guns=\nA small US based company, the Alien Invasion is there flagship product. Current pricing on the alien invasion is $499. At this price they are a steal. This is a marker that just a few months ago sold for $700. The invasion features a hoseless design, no macro lines or steal hoses to get in your way. The invasion operates at a low 70 psi for ultra smooth operation and almost no kick. Did I mention that this comes stock with a hater board? Typically that's a $100 upgrade from a stock gun. Take another look at the invasion, you won't be dissapointed.\n\n\n=Azodin Paintball Guns=\nAzodin makes a great line of entry to mid level paintball guns. Perfect to get you in the game through entry level tournament play. \nThe Azodin Kaos Paintball gun is their entry level Semi Automatic paintball marker that will run on compressed air or CO2. A solid gun for the beginner that is a vast improvement over renting a paintball gun at your local field. The Azodin Kaos as well as most other Azoding paintball guns use an autococker threaded paintball barrel and Impulse/ Ion threaded feedneck to make for easy upgrades. The Kaos comes in multiple colors as well as the Kaos D with he Zero Recoil System and the Kaos Pump for all of you old school pump paintball gun fans. Looking for a more tactical look? take a look at the azodin ATS (Azodin Tactical Series) and ATS+. A Semi Automatic paintball gun similar to the kaos, but with a nice tactical look along with rails and stock upgrades to mimic you favorite military gun. With the Azodin Blitz, you get into the first of the Electronic Azodin guns. The Azodin Blitz has a high performance valve for unequaled efficiency, accuracy and rate of fire. The Azodin Blitz comes in multiple colors and includes the new improved Zen II circuit board to extend battery life. With multiple pre-programmed firing modes and the ability to customize your modes at your local shop using the AZ editor, your set for the future. At roughly $150, you get alot of bang for the buck out of thie entry level paintball gun. The top of the line Paintball marker for Azodin is the Azodin Zenith. The Zenith paintball gun has Azodinz Zero recoil system which includes the feather striker system. The feather striker system is about 30% lighter than a traditional striker reducing recoil and increasing your firing rate. The Azodin Zenith also boasts the Zen2 board for unlimited programmability.\n\n=Dye Paintball Guns=\nDye is the ultimate in high end tournament and scenario paintball guns. Dye currently makes two guns, the DM series, currently the DM13 and the Dye DAM Dye Assault Matrix. The DM sells for about $1400 and is designed for the high level tournament player, or someone who wants the ultimate firepower at there local field. In 2012, Dye entered the scenario market with the Dye DAM. The Dye Dam allows hopper or magazine fed operation and is a thing of beauty. Dye paintball guns are engineered for the highest level of paintball. maximum rates of fire can exceed 25 BPS when you want to spray your opponents.\n\n=Proto Paintball Guns=\nProto guns are low to mid range starting at $250 and going to 500+. Proto is know for the [[Proto Rail]:url=%SESSION%/category/markers.protopaintballguns/] paintball gun. the Rail currently comes in two versions, the standard proto rail runs about $250 and is a solid entry level paintball gun out of the box. be sure to only use compressed air on any proto paintball guns. The standard rail has a max rate of fire of 15bps. The upgrade from the proto rail is the proto reflex rail. Starting at $500, the reflex rail includes the popular ultralight grip frame and is ready to rock your next paintball tournament.\n\n=Spyder Paintball Guns=\n[[Spyder Paintball]:url=/category/shop_by_brand.spyder/] is one of the top manufacturers of entry level paintball guns. If your first paintball gun wasn't a Tippmann 98, it probably was a Spyder. Spyder makes a broad range of paintball markers for the entry level player, all the way up to rec level tournament play. Entry level guns from spyder include the following Semi Automatic guns. The spyder Sonix\n[[Spyder Sonix]:url=/category/markers.kingmanspyder/], MR1, Victor, and Xtra are all semi-automatic and great hassle free beginner guns. Don't expect these guns to compete against the firepower of an Electronic Paintball gun. Spyder's Electronic line of guns include the [[Spyder Fenix]:url=/category/markers.kingmanspyder.spyder_fenix_paintball_guns/], MR4 and Electra. These markers will shoot significantly faster with programmable electronic triggers. Typically all tournament modes will be included PSP, NPPL, etc(See Product Specific details) Spyder Guns will allow you to use either Co2 or Compressed Air although We always recommends HPA or compressed air tanks for a more enjoyable paintball experience. \nIn 2012 Spyder released a new line of markers. The Hammer 7 is a composite pump for all you old school player. The pump is mag fed and will accept both standard .68 cal paintball and tiberius arms first strike rounds. The Spyder MRX allows you to choose from mag fed or hopper fed operation. An elite version is available with a bunch of tactical upgrades included. The latest version of the MR series, the MR5 was released in both a semi auto and electronic version. This also includes hopper or mag fed operation with the choice of standard paintballs or first strike rounds.\n\n\n[[Tippmann Paintball Guns]:url=%SESSION%/category/markers.tippmann/]\nTippmann makes the most common entry level paintball guns in the game. If you've rented at your local field you probably have used some version of the tippmann 98. The tipmann 98 is the gold standard in rental guns. The 98 is also designed to allow you to upgrade down the road with an electronic grip, response trigger, flatline barrel or any other tippmann 98 threaded barrel on the market. The 98 is rock solid and I've even heard plenty of cases of them being run over by cars and still working. Although i wouldn't recommend you try it.\n\n\n==Paintball Gun Questions and Answers==\n\n\n= - Q What kind of hopper do I need for my paintball gun.=\n A - Unless you have a tippmann paintball gun with a cyclone feed or BT paintball gun with the Rip Clip, you will use a standard paintball loader. If you have a tippmann or bt, your choices will be limited to a gravity fed hopper that will clearly says it is cyclone feed compatible. All other paintball guns will use a standard paintball hopper, just choose gravity fed if 3-6 BPS is sufficient for your paintball marker. Electronic hoppers start at 8-12 BPS and go all the way up to 50+BPS with the Dye Rotor.\n\n\n= - Q - Can or Should I upgrade the barrel on my Paintball Gun?=\n A - Yes, the paintball barrel is typically the first upgrade you want to make on any paintball gun priced below $500. The stock barrel on these paintball guns is typically decent, but for the best performance you will want to upgrade to a barrel that allows you to adjust the bore or internal size of the barrel to match your paintballs. Paintballs tend to vary slightly from batch to batch and even depending on humidity and temperature. Higher end barrels like the Dye Ultralight, Deadlywind carbon fiber, Smart Parts Freak and Empire Super Freak System are highly recommended. Just make sure you check what thread type is on your gun. The most popular paintball gun barrel threads include autococker, spyder, tippmann 98, tippmann A5/X7 and Ion / Impulse / Smart Parts thread. All of the paintball guns on our site should list the barrel type on the product and category pages for reference.\n\n= - Q What do I need to buy with my Paintball gun to play paintball?=\n A - When you buy your first set of paintball gear, there's a few things you'll need. First of all, you need a paintball mask to keep you safe on the field. You will also need to buy a loader to hold the paintballs, a tank to provide gas to your gun as well as some paintballs. You may also want a harness to carry some extra paint for those long games. Zephyr offers a complete line of paintball packages to get you on the field and ready to play without the hassle of knowing. \n\n\n\nHow about scenario paintball? We stock a full line of scenario paintball guns and gear you will need to get in the game. Zephyr Paintball will price match other online paintball stores on all in stock merchandise on cheap paintball guns or any paintball gear. We are the online leader in discount paintball. Just call 805-275-2040.", + "zoovy:banner02" : "banners/paintball/headers/1_pumpguns_header001.jpg", + "zs11_banner_wslideshow_slide5" : "ALT=Dye+DM14+Paintball+Markers+Available+NOW%21&IMG=banners%2fpaintball%2fslideshow%2fdye_dm14_slideshow_template%2ejpg&LINK=%25SESSION%25%2fcategory%2fmarkers%2edye_matrix_paintball_guns%2edye_dm14_paintball_guns%2f", + "page_head" : "", + "top_html" : "", + "zs11_banner_wslideshow_slide1" : "ALT=Proto+Reflex+Rail+%2b+Dye+Rotor+%3d+FREE+Dye+I4+Goggle%21&IMG=&LINK=%25SESSION%25%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3dREFLEXI4PROMO%26x%3d39%26y%3d0", + "prodlist2_title" : "Featured Paintball Guns", + "banner3" : "banners/categories/small_header/ego8_pricedrop_001.jpg", + "slideshow_01" : "images=banners/sm_promo/dangerous_power_revi_001,banners/sm_promo/proto_09_slg_small_header_001\nlinks=,\npauses=5000,5000\nblank_behavior=none\n", + "ad2" : "banners/paintball/side_banners/pb_entry_level_guns_jpg.jpg", + "3widead_title" : "", + "banner2" : "banners/sm_promo/dangerous_power_revi_001", + "banner02_link" : "%SESSION%/category/markers.pump_paintball_guns/", + "prodlist1" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&", + "zs11_banner_wslideshow_slide4" : "ALT=Azodin+Zenith+II+Paintball+Markers+JUST+RELEASED%21&IMG=banners%2fpaintball%2fslideshow%2fazodin_zii_paintball_markers_slideshow_template%2ejpg&LINK=%25SESSION%25%2fproduct%2fAZDN%2d2010%2dZII%2dPRT%2fAzodin%2dZenith%2dII%2dPaintball%2dGun%2ehtml", + "dynimage1" : "images=banners/paintball/slideshow/1_invert_mini_gunslideshow.jpg,banners/paintball/slideshow/1_bt_omegatactical_gunslideshow.jpg,banners/paintball/slideshow/spyder_fenix_slideshow.jpg,banners/paintball/slideshow/kingman_spyder_mrx_slideshow.jpg,banners/paintball/slideshow/1_tippmann_a5_gunslideshow_template.jpg\nlinks=/category/markers.invert_paintball_guns/,/category/markers.btdesignspaintballguns.bt_omega_paintball_guns/,/category/markers.kingmanspyder.spyder_fenix_paintball_guns/,/category/markers.kingmanspyder.spyder_mrx_paintball_guns/,/category/markers.tippmann.a5/\npauses=8000,8000,8000,8000,8000\nblank_behavior=none\n", + "add2_link" : "http://www.zephyrpaintball.com/category/markers.planet_eclipse_ego_paintball_guns.planet_eclipse_ego_paintball_guns/", + "ad3" : "banners/paintball/side_banners/electronic_paintball_guns_sidebanner.jpg", + "banner1" : "banners/09_headers/main_categories/paintball_guns_001", + "htmllinks" : "", + "ad1_link" : "%SESSION%/category/markers.1_-_semi_auto_paintball_guns_markers/", + "head_title" : "Paintball Guns | Paintball Markers | Cheap Paintball Gun", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".scenarioupgrades.rails_and_mounts" : {}, + ".harnessesbags.backpacks.billabong_backpacks" : { + "meta_description" : "Billabong Backpacks - Buy your Billabong Bags At Zephyr Sports for Less Today! We carry a complete line of Billabong Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "!Billabong Backpacks & Bags Ship Free ", + "head_title" : "Billabong Backpacks | Billabong Bags |Billabong Luggage" + }, + ".sponsorship" : { + "description" : "=Personal Paintball Sponsorships now Available=\n\n\nWhether you're new to the game or a tournament veteran, we would like to support you in your paintball endeavors. So, please e-mail your completed resume to sponsorship@zephyrpaintball.com.\n\n\nPlease include the following information in your resume: \n*Playing history\n*Current team\n*Current division/level\n*Future tournaments you will be playing in\n*How you plan to support ZephyrPaintball.com / Zephyrsports.com. \n=*Team Web Page / Youtube Channel (A link to Zephyr Paintball on your webpage is required for sponsorship)=\n\n\nIt is very important that you take your time and put a little bit of effort into this, as it will greatly increase your chances of acquiring sponsorship from Zephyr Sports.\n\nSponsored players receive special pricing across our entire store as well as monthly specials on the hottest paintball gear. \n\n\n\nThanks for your time,\n\nZephyrPaintball.com\n\n=If you are under the age of 18, please request approval from your parents/guardians before applying for sponsorship.=\n\n\n=Please note that our customer service people cannot answer any sponsorship questions, so please do not call or live chat to find out about your sponsorship or details.=", + "zoovy:banner02" : "banners/paintball/headers/zephyr_sponsorship_header001.jpg" + }, + ".airsoft.tactical_airsoft_gear.hats" : { + "meta_keywords" : "camouflage hats,airsoft hats,military hats", + "meta_description" : "Camouflage Hats. complete your outfit with a standard issue boonie hat offered in a range of camouflage patterns. These hats are a great value and are made to the governments specifications. Made from a polyester/cotton material, these hats include screened side vents. They also include branch loops and a chin strap. On hot days or when you need to keep your profile low, a camouflage hat is a great addition to any uniform or playing gear.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".apparel.shoes.dvs_shoes" : {}, + ".airsoft.airsoft_guns.airsoft_bb_launchers___shells.airsoft_innovations_impact_tornado_airsoft_grenades" : { + "head_title" : "Tornado Grenades | Airosft Innovations Tornado" + }, + ".markerupgrades.smartparts.ion.triggers.trinity_paintball_ion_triggers" : {}, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.33" : {}, + ".casual_clothing.mens_clothing.sweatshirts.empire_sweatshirts" : { + "meta_description" : "Empire Sweatshirts - Buy your Empire Hoodies At Zephyr Sports for Less Today! We carry a complete line of Empire Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Empire Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Empire Sweatshirts | Empire Hoodies | Empire Hoody" + }, + ".casual_clothing.mens_clothing.hats.cliche_hats" : { + "meta_keywords" : "Cliche Hats,Cliche caps,Cliche baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Cliche Hats - Zephyr carries a complete line of Cliche Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Cliche", + "page_title" : "Cliche Hats on Sale at Zephyr", + "head_title" : "Cliche Hats | Cliche Caps | Cliche Baseball Hats" + }, + ".markerupgrades.invert_upgrades.invert_mini_asa_s" : {}, + ".shop_by_brand.madbull_airsoft" : {}, + ".harnessesbags.backpacks.valken_bags_and_backpacks" : { + "meta_description" : "Valken Backpacks - Buy your Valken Bags Online At Zephyr Sports for Less Today! We carry a complete line of Valken Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Valken Backpacks & Bags Ship Free ", + "head_title" : "Valken Backpacks | Valken Bags |Valken Luggage" + }, + ".casual_clothing.mens_clothing.shoes" : { + "meta_keywords" : "skate shoes,vans shoes,skate shoe,osiris shoes,skateboard shoes,etnies shoes,circa shoes,dvs shoes,globe shoes,dc shoes shoes,adio shoes,fallen shoes,skateboarding shoes,emerica shoes,es shoes,lakai shoes,dc shoes skate,dekline,skater shoes,etnies shoe,cheap skate shoes,etnies skate shoes,element shoes,skate shoes adio,dvs skate shoes,kids skate shoes,emerica skate shoes,skate shoes emerica,emerica shoe,skate shoes sale,lakai shoe,es skate shoes,lakai skate shoes,globe skate shoes\r ", + "meta_description" : "Skate Shoes - Free Shipping on all Mens Shoes from Zephyr Sports. Lowest Price on skateboard shoes from Globe, Dekline, DC, Emerica, ES, Lakai, Adio, Etnies, Vox, Fallen and much more.", + "page_title" : "Buy Skate Shoes On Sale & Free Shipping", + "head_title" : "Skate Shoes | Mens Shoes | Skateboard Shoes" + }, + ".harnessesbags.paintball_gear_bags.smart_parts_gear_bags___back_packs" : {}, + ".casual_clothing.z-sunglasses.bolle_sunglasses" : { + "meta_description" : "Bolle Sunglasses - Buy your Bolley Eyewear At Zephyr Sports for Less Today! We carry a complete line of Bolle Sun Glasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Bolle Sunglasses On Sale Free Shipping", + "head_title" : "Bolle Sunglasses | Bolley Eyewear | Bolle Sun Glasses" + }, + ".casual_clothing.mens_clothing.shorts.srh_shorts" : { + "meta_description" : "SRH Board Shorts - Buy your SRH Shorts At Zephyr Sports for Less Today! We carry a complete line of SRH Boardshorts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "SRH Boardshorts Ship Free at Zephyr Sports", + "head_title" : "SRH Board Shorts | SRH Shorts | SRH Boardshorts" + }, + ".markerupgrades.pump_gun_upgrades" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_steelcat_watches" : {}, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_bearings" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Bushings | Airsoft Bearings | Airsoft Upgrade Bushing Bearings" + }, + ".airsystems.dropforwards.trinity" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.elite_force_aeg_airsoft_guns" : {}, + ".casual_clothing.mens_clothing.hats.empire_hats" : { + "meta_keywords" : "Empire Hats,Empire caps,Empire baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Empire Hats - Zephyr carries a complete line of Empire Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Empire", + "page_title" : "Empire Hats on Sale at Zephyr", + "head_title" : "Empire Hats | Empire Caps | Empire Baseball Hats" + }, + ".markerupgrades.tippmann.tippmann_ft-12" : {}, + ".goggles.empire_vents_goggles" : { + "meta_keywords" : "Empire ZN Paintball Goggles, event paintball goggles, Empire thermal paintball mask, Cheap paintball mask, Empire paintball gear, ZN Empire, event ZN,empire vents ,empire vents mask,mask empire event,empire event mask,empire e-vent mask,empire eflex,empire e-flex ", + "meta_description" : "Empire Events Paintball masks - Hot new paintball Goggles from Empire. The top of the line Empire E-flex Thermal paintball goggles. For tournaments or recreational play, Empire Paintball goggles are the best choice", + "top_description2" : "Empire Paintball Masks offer unparalleled performance to keep you fog free in the game. Empire Masks feature thermal anti fog lenses soft ears and a flexible mask design to get the most bounces. From the Empire helix, to the vidar, event and the new E-flex, Empire has a paintball goggle for everyone.", + "zoovy:banner01" : "banners/paintball/headers/goggleaccessories_header001", + "banner01_link" : "/category/goggles.1goggle_accesories.vents_goggle_accesories/?sortby=!zoovy:base_price", + "description" : "Empire E-flex - Just released for 2012 the Empire E-flex is the latest and greatest from Empire. Some have called this a mix betweeen the JT spectra series masks and the Empire event. The Empire Eflex uses the same thermal lenses as the Event. The mask bottom on the Empire E-flex is removeable and interchangeable with any of the JT Flex skirts or Spectra frames. The foam on the Eflex is insanely comfortable. No more complaints about the Spectra foam. A micro fiber bag is included to keep your Empire E-flex mask protected when done playing.\n\n\nEmpire Events - The Events have been out for a few years now but still offer a top of the line paintball mask with thermal lenses, soft ears and flexible mouth guard. The Empire Events come in a full line of colors to suit just about anyone's style. The vents on the Events goggle are specially designed to be breathable and project your voice through the field so teammates can hear you. A quick change lens system allows you to take your goggle apart in seconds for easy cleaning and lens replacement.\n\n\nEmpire Vidar Mask - Released in early 2012, the Empire Vidar is a mid level mask that give you alot of value for the money. Priced at about $50 you get a thermal JT Spectra style lens with 206 degrees of vision along with a silicone embedded strap to keep the goggles on your head. Plenty of venting on the Empire Vidar keeps you cool throughout the game and the soft chin and mouth guard give you a few extra bounces to stay in the game.", + "page_title" : "Buy Empire Events Paintball Goggles Online On Sale Now", + "head_title" : "Empire Events Paintball Mask | Empire Event Goggles | Empire E-flex", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.smg_mp5_airsoft_guns" : { + "meta_description" : "SMG MP5 Airsoft Guns - Buy your Airsoft SMG MP5 At Zephyr Sports for Less Today! We carry a complete line of SMG MP5 AEG Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "Below are replica SMG MP5 Airsoft Guns. The original SMG MP5 is a 9mm submachine gun of German design, developed in the 1960s by a team of engineers from the German small arms manufacturer Heckler & Koch. The primary version of the MP5 is a lightweight, air-cooled, selective fire delayed blowback operated 9x19mm Parabellum weapon with a roller-delayed bolt. \n\n\nThe MP5 is currently one of the most widely used submachine guns in the world, having been adopted by numerous law enforcement agencies and special forces groups.", + "page_title" : "Buy SMG MP5 Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "SMG MP5 Airsoft Guns |Airsoft SMG MP5 |SMG MP5 AEG Airsoft Gun", + "description" : "" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.sig_sauer_airsoft_guns" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_infinite_hero_sunglasses" : { + "meta_keywords" : "Oakley Infinite Hero Sunglasses,Infinite Hero oakley sunglasses,oakley Infinite Hero, Infinite Hero polarized sunglasses", + "meta_description" : "Oakley Infinite Hero Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Infinite Hero and Polarized Oakley Infinite Hero Sunglasses on Sale! ", + "page_title" : "Oakley Infinite Hero Sunglasses with Free Shipping", + "head_title" : "Oakley Infinite Hero Sunglasses | Infinite Hero Oakley Sunglassses" + }, + ".testing_help_desk.returns" : { + "hd_answer_four" : "Wrong color? Wrong Size? Need it Fast? Zephyr now offers Rapid Exchange!\n\n\nRapid exchange is only available for New & Unopened Items.\n\n\nZephyr Sports will accept returns on most unopened items for up to 60 days after the invoice date. No RMA required for new unused and unopened items. Returns must have zero appearance of being used. All tags and packaging must be intact. All warranty cards, instructions and accessories must be included as well. Any items sent back with obvious signs of use/wear will either be denied or charged a minimum 25% restocking fee as well as a shipping deduction if free shipping was received on the original order. \n\n\n\n==Step 1:==\n\nPlace your order for the new items you want.\n\n\n==Step 2:==\n\nSend your return to: \n\n=Zephyr Sports=\n=Attn: Returns - 1067=\n=2970 Seaborg Ave.=\n=Ventura, CA 93003=\n\n\nYou must include a copy of your invoice for quick processing. Failure to include your invoice will delay returns processing.\n\n\n==Step 3:==\n\nZephyr Sports will process a refund/store credit for your return. In order to receive a full refund for your return, the replacement order must match or exceed the value of your original item(s) ordered.\n\n\nPlease allow 3-5 business days to process your return. Paypal refunds will show on your account immediately. Credit card refunds take 2-4 business days for your bank to process.", + "hd_question_three" : "NEW & UNOPENED - Returns for Refund", + "hd_question_four" : "NEW & UNOPENED - RAPID EXCHANGE", + "hd_question_eight" : "I received the Wrong Product.", + "hd_answer_three" : "=New & Unopened Items=\nZephyr Sports will accept returns on most unopened items for up to 60 days after the invoice date. No RMA required for new unused and unopened items. Returns must have zero appearance of being used. All tags and packaging must be intact. All warranty cards, instructions and accessories must be included as well. Any items sent back with obvious signs of use/wear will either be denied or charged a minimum 25% restocking fee as well as a shipping deduction if free shipping was received on the original order.\n\n\n==Step 1:==\n\n===Return your brand new gear within 60 days to:===\n\n=Zephyr Sports=\n=Attn: Returns - 1099=\n=2970 Seaborg Ave.=\n=Ventura, CA 93003=\n\n\nReturns for a refund are subject to a 15% restock fee. Free shipping fees from your original order may also be deducted from refund total. Restock Fees will be waived if you choose store credit.\n\n\nYou must include a copy of your invoice for quick processing. Failure to include your invoice will delay returns processing.\n\n\n=Return Shipping=\n\n\nCustomer is responsible for all return shipping. All returns must be properly packaged (Do not slap a shipping label on the retail packaging). We suggest shipping via Insured FedEx with a signature required. Zephyr Sports is not responsible for packages lost in transit.\n\n\n==Step 2:==\n\nAs soon as we receive your return we will inspect your package and process your return. Please allow 3-5 business days to process your return. Paypal refunds will show on your account immediately. Credit card refunds take 2-4 business days for your bank to process.\n\n\n=Exclusions=\nThe following items cannot be returned under any circumstances.\nPaintballs, Slide Shorts, Undergarments, Ladies Swimwear, Socks. Other exclusions may apply.\n", + "guide_01" : "\n
                                                                          \n\n", + "hd_answer_nine" : "If your order is missing an item or you received an incorrect quantity, please immediately contact our customer service department at 805-275-2040. Missing or Incorrect product claims must be made within 5 business days of Package Receipt.\n\n\nTo streamline the process and make sure you receive any product in question as quickly as possible, we advise you to call our customer service department. Please have your invoice readily available as our representatives will need to verify information listed on your order invoice.\n\n\nOnce your claim is filed, our representatives will then research the claim. This will include verifying shipment weight as well as an inventory count. Please allow 24-48 hours for your claim to be researched. When we have come to a conclusion you will be contacted by a rep, and if we failed to ship any product in question, we will promptly send out your item(s) at no additional charges to you.\n", + "hd_question_two" : "NEW & UNOPENED - Exchanges / Returns for Store Credit", + "hd_answer_two" : "==Returns for Store Credit / Exchanges==\n\nZephyr Sports will accept returns on most unopened items for up to 60 days after the invoice date. No RMA required for new unused and unopened items. Returns must have zero appearance of being used. All tags and packaging must be intact. All warranty cards, instructions and accessories must be included as well. Any items sent back with obvious signs of use/wear will either be denied or charged a minimum 25% restocking fee as well as a shipping deduction if free shipping was received on the original order.\n\n\nAll returns for Store Credit / Exchanges will be issued via Zephyr Gift Card. Customer is responsible for the shipping costs to return products to us. We will issue a gift card for the amount of your returned item(s), then you will be able to place your order directly on our website using the gift card emailed to you.\n\n\n==Step 1:==\n\nReturn your brand new gear within 60 days to: \n\n=Zephyr Sports=\n=Attn: Returns - 1055=\n=2970 Seaborg Ave.=\n=Ventura, CA 93003=\n\n\nYou must include a copy of your invoice for quick processing. Failure to include your invoice will delay returns processing.\n\n\n=Return Shipping=\nCustomer is responsible for all return shipping. All returns must be properly packaged (Do not slap a shipping label on the retail packaging). We suggest shipping via Insured FedEx with a signature required. Zephyr Sports is not responsible for packages lost in transit.\n\n\n==Step 2:==\n\nAs soon as we receive your return we will inspect your package and process your return. Please allow 3-5 business days to process your return as well as your refund / Store Credit.\n\n\n=Exclusions=\nThe following items cannot be returned under any circumstances.\nPaintballs, Slide Shorts, Undergarments, Ladies Swimwear, Socks. Other exclusions may apply.\n", + "hd_question_six" : "Used Item Return Policy", + "hd_question_five" : "DOA - Manufacturers Defects", + "hd_topic_listing" : "» What is the Zephyr Return Policy?
                                                                          \n» NEW & UNOPENED - Exchanges / Returns for Store Credit
                                                                          \n» NEW & UNOPENED - Returns for Refund
                                                                          \n» NEW & UNOPENED - RAPID EXCHANGE
                                                                          \n» DOA - Manufacturers Defects
                                                                          \n» Used Item Return Policy
                                                                          \n» I received the wrong product
                                                                          \n» My Order is Missing an Item(s).
                                                                          ", + "hd_topic" : "Returns", + "hd_question_one" : "What is the Zephyr Return Policy?", + "hd_answer_five" : "At Zephyr Sports we know the occasional manufacturer defect is bound to happen for out of the box items. While we know this can be a hindrance, we unfortunately have no way to test every product before it leaves our warehouse. If you have a warranty issue within 30 days of your purchase, we have techs on standby to help you work through any issues you may have with your new gear.\n\n\nAll defective products require an RMA which you can obtain by; e-mailing us at rma@zephyrsports.com, calling us at 805-275-2040 or using our online Live Chat function above to speak with a returns specialist. If we are unable to solve the issues we will take care of getting your product back and repair / replace at our discretion. \n\n\n=Issues After 30 Days:=\nManufacturer's warranties will cover any product issues after this initial 30 day period. Feel free to contact us if you need help getting in touch with a manufacturer.", + "hd_btn" : "images/site_specific/backto_helpdesk", + "hd_answer_eight" : "If you have received the wrong product please call us at 805-275-2040. We will gladly help you solve any issues in a timely manner. Do not attempt to use or open the product as this will void the claim for return. We allow claims to be filed up to 5 Business days after the delivery date. Any claim made after 5 Business days is considered void and may not be honored. \n\n\nTo streamline the process and make sure you receive the correct product as fast as possible, we advise you to call our customer service department. Please have your invoice readily available as our representatives will need to verify information listed on your order invoice.\n\n\nOnce our customer service representatives verify your claim that the incorrect product was shipped to you, we will promptly email a FedEx shipping label for you to return your item(s). Be sure to clearly write the RMA provided by our reps on the outside of your return package. Failure to write the RMA on the outside of the package will delay your return processing. If you are not sure where your local FedEx facility is, our reps will gladly help you locate the nearest FedEx drop-off/pick-up location. Once we receive the product and confirm that it was shipped incorrectly, we will ship the correct product to you.\n\n\nIf you are unable to receive a FedEx shipping label, please include a copy of any receipt detailing shipping costs. Once received and confirmed, we will then reimburse your shipping cost via store credit to your account. Reimbursements will only be authorized for standard ground shipping. If you decide to ship by any other means, we will only reimburse up to a maximum of the determined FedEx ground cost.\n", + "hd_link" : "/category/testing_help_desk ", + "hd_answer_one" : "\n» New & Unopened items
                                                                          \n\nZephyr Sports will accept returns on most unopened items for up to 60 days after the invoice date. No RMA required for new unused and unopened items. Returns must have zero appearance of being used. All tags and packaging must be intact. All warranty cards, instructions and accessories must be included as well. Any items sent back with obvious signs of use/wear will either be denied or charged a minimum 25% restocking fee as well as a shipping deduction if free shipping was received on the original order.\n\n\n» DOA (Dead on Arrival) & Manufacturers Defects
                                                                          \n\nWe will assist with all DOA (Dead on Arrival) and Manufacturers defects for 30 days from the original date of purchase. Please contact our customer service department at 805-275-2040 so we may assist you with your issues. We will do some basic troubleshooting to attempt to solve your Issue. If we are unable to solve the issues we will take care of getting your product back and repair / replace at our discretion. All returns for DOA and Defects require prior authorization prior to being returned to Zephyr Sports.\n\n\n=Return Shipping=\nCustomer is responsible for all return shipping. All returns must be properly packaged (Do not slap a shipping label on the retail packaging). We suggest shipping via Insured fedex with a signature required. Zephyr Sports is not responsible for packages lost in transit.\n\n\n\n=Exclusions=\nThe following items cannot be returned under any circumstances.\nPaintballs, Slide Shorts, Undergarments, Ladies Swimwear, Socks. Other exclusions may apply.\n", + "hd_answer_six" : "Used items returned to Zephyr Sports are subject to restock fees of up to 75%. All used products require an RMA and prior approval before returns will be accepted. Click here and fill out the return form. Once you have it filled out, e-mail it to rma@zephyrsports.com and it will be reviewed and your RMA will be provided. Please allow 2-3 business days for us to process your RMA.", + "hd_question_nine" : "My Order is Missing an Item(s)." + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.dye_dm13_paintball_gun" : {}, + ".apparel.jerseys" : { + "meta_keywords" : "Cheap Paintball Jerseys, Discounted Paintball Jerseys, Pro Paintball Jerseys, Cheap Paintball, Paintball Jerseys, Discount Paintball, Paintball Supplies, Paintball Accessories, Paintball Equipment, dye c11", + "ad3_link" : "/category/apparel.jerseys.dyejerseys.dye_c14_paintball_jerseys/", + "add3_link" : "/category/apparel.jerseys.tanked_paintball_jerseys/", + "ad2" : "banners/paintball/side_banners/valken_vtac_jerseys_sidebanner.jpg", + "banner4" : "banners/sm_promo/tanked_09_jerseys_price_drop.png", + "page_title" : "", + "3widead_title" : "Popular Paintball Jerseys", + "ad2_link" : "/category/apparel.jerseys.v-tac_paintball_jerseys/", + "add1_link" : "/category/apparel.jerseys.protojerseys/", + "subcat1_header" : "Paintball Jersey Categories", + "banner2" : "banners/sm_promo/proto_09_jersey_price_drop.png", + "meta_description" : "Cheap Paintball Jerseys - Get the lowest prices on discounted paintball jerseys online at ZephyrPaintball.com.", + "top_description" : "Ready to look like a real paintball player? It's time for a Paintball Jersey. Zephyr carries a complete line of paintball jerseys to get you on the field and looking good. A good paintball jersey will be comfortable on the field, look good, and give you a few extra bounces. Paintball Jerseys are typically worn at least a size big, I wear an XL t shirt, but wear a XXL paintball jersey. It gives me room to move on the field and I get a few extra bounces when I get hit on a loose jersey.", + "ad1" : "banners/paintball/side_banners/2014_empire_sidebanner.jpg", + "description" : "While looking for the perfect Paintball Jersey you will find many different sizes and designs. Most jerseys are adult sized and run baggier than an adult men’s t-shirt. If you wear a Men’s Medium and go with a Medium Jersey it will be baggy but may not be baggy enough; so you may want to skip a size and go for the Large. Having your jersey baggy is much better than a tight fit since the tighter it is the more likely the ball is going to break and the impact of the paintball will be greatly noticed. Baggy = more chances of bounces which means less bruises and more game time. Prices can range from $20-$70 depending on what brand you are looking at. What’s the difference? The more expensive the Jersey gets the more you are going to get reinforced padding, ventilation, hand protection and other protection advantages. Most Jerseys have some sort of padding on the shoulders, elbows and chest. You will find this with [[Dye Jerseys]:url=/category/apparel.jerseys.dyejerseys/] and [[Eclipse Jerseys]:url=/category/apparel.jerseys.planet_eclipse_paintball_jerseys/] jerseys. Dye jerseys use responsive air foam that are always in the proper position of your arms and shoulders which means the pads will move with you while maneuvering. Ventilation is vital! The multiple holes on the jersey push the heat out to the sides and under the arms, keeping the area around your chest cool. Eclipse makes the [[Distortion Jersey]:url=/category/apparel.jerseys.planet_eclipse_paintball_jerseys/]. This jersey is popular due to its design. Not only do these jerseys look amazing but their structure is amazing as well. They have foam padding for protection, mesh venting for air circulation and all the necessary reinforcements in the shoulders, elbows and sides for the ultimate protection. Now these jerseys are great but you may be looking for something a little cheaper. Not to worry – you can still have a comfortable paintball jersey that is affordable. The Empire Prevail and Valken Fate jerseys are great entry level jerseys. Both have great ventilation and a comfortable feel. The prevail jerseys are light and durable with padded elbow pads that is great for just getting into paintball where the game play won’t be so rough. The Valken fate are a basic entry level jersey, no extra padding or features here, but for $30 can ya complain? ", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "banner1" : "banners/09_headers/main_categories/paintball_jerseys_001.png", + "ad3" : "banners/paintball/side_banners/dye_2014_sidebanner_template.jpg", + "ad1_link" : "/category/apparel.jerseys.empire_paintball_jerseys/", + "head_title" : "Cheap Paintball Jerseys | Discounted Paintball Jerseys | Pro Paintball Jerseys", + "page_head" : " " + }, + ".goggles.save_phace_paintball_goggles.marks-a-lot_series" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.echo_1_airsoft_guns" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_rosebud_sunglasses" : { + "meta_description" : "Von Zipper Rosebud Sunglasses - Zephyr Sports carries a complete line of Buy Rosebud Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Rosebud Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Rosebud Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Rosebud Sunglasses | Buy Rosebud Von Zipper Sunglasses | Von Zipper Rosebud Sunglasses Free Shipping" + }, + ".markerupgrades.smartparts.epiphany.epiphany_bolts" : {}, + ".buyers_guide.airsoft" : { + "title_01" : "What is Airsoft?", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002", + "return_link" : "/category/buyers_guide/", + "text_01" : "Airsoft is primarily a recreational activity with replica firearms that shoot plastic BBs that are often used for personal collection, gaming (similar to paintball), or professional training purposes (military simulations, a.k.a. MilSim, and police training exercises). A primary difference between airsoft guns and BB guns is that an airsoft gun uses a 6mm or 8mm plastic pellet and has a muzzle velocity of typically less than 180 meters per second (600 feet); which is generally considered safe when used in a controlled environment and with safety equipment like protective eyewear. Another distinguishing factor between BB guns and airsoft guns is that airsoft guns generally have some sort of \"hop-up\" mechanism that creates a back-spin on the BB to increase its accuracy and effective range. This hop-up feature is needed due to the light weight of the plastic pellet causing the plastic BB to otherwise fly uncontrollably, reducing its effective range.\n\n\nAirsoft games vary greatly in style and composition depending on location, budget, and the quantity of participants but often range from short-term skirmishes and organized scenarios to military simulations and historical reenactments. Gaming with Combat situations on a mock battlefield mainly involve the use of common military tactics to achieve the objectives set in each game. Participants typically use varying types of airsoft weaponry along with either real or replica military gear and uniforms." + }, + ".snowboard_gear.snowboard_goggles.electric_snowboard_goggles" : { + "meta_keywords" : "Electric snow goggles,electric ski goggles,electric eg2,electric egk,electric eg goggles,electric snowboard goggles", + "meta_description" : "Electric Snow Goggles - Get your Electric Snowboard Goggles from Zephyr Today. Huge Selection Real Time Inventory with Free Shipping on Electric Ski Goggles. ", + "page_title" : "Electric Snow Goggles with Free Shipping at Zephyr", + "head_title" : "Electric Snow Goggles | Electric Snowboard Goggles | Electric Ski Goggles" + }, + ".markerupgrades.planet_eclipse_ego_upgrades.ego_bolts" : { + "htmlvids" : "" + }, + ".barrels.autococker.14__autococker_paintball_barrels" : { + "meta_description" : "14 inch Autococker Paintball Barrels - Buy your 14\" Autococker Threaded Barrels Online at Zephyr Paintball for Less today. Free Shipping on Cocker Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 14 inch Autococker Paintball Barrels Online On Sale Now", + "head_title" : "14 inch Autococker Paintball Barrels | 14\" Autococker Threaded Barrels | Cocker Paintballs Barrels" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_the_ride_watches" : {}, + ".casual_clothing.mens_clothing.tank_tops.1-search_by_size.5-xx-large" : {}, + ".airsoft.slingshots.replacement_slingshot_bands" : { + "meta_keywords" : "replacement slingshot bands, sling shot band, rubber sling shot bands, tubular bands, replacement rubber, sling shot accessories", + "meta_description" : "As durable as they are, it’s still possible for the slingshots band to ware down or even snap. Easy to install replacement bands are available in Normal and Heavy pull tensions that fit all slingshots powered by tubular type bands.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.m4_airsoft_guns" : { + "head_title" : "M4 Airsoft Guns | Airsoft M4 Rifle" + }, + ".casual_clothing.mens_clothing.socks.jox_sox_men_s_socks" : { + "meta_keywords" : "Jox Sox socks,Jox Sox mens socks,Jox Sox men socks", + "meta_description" : "Jox Sox Socks - Zephyr stocks a complete line of Jox Sox Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Jox Sox needs. ", + "page_title" : "Jox Sox Socks on Sale at Zephyr", + "head_title" : "Jox Sox Socks | Jox Sox Mens Socks" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.mp_40_aeg_airsoft_magazines" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.rothco_pants_and_jeans" : { + "meta_description" : "Rothco Pants - Buy your Rothco Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Rothco Pants & Jeans Ship Free", + "head_title" : "Rothco Pants | Rothco Jeans" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_m-frame_sunglasses.oakley_m_frame_heater_sunglasses" : { + "meta_description" : "Oakley M Frame Heater Sunglasses - Buy your Oakley Heater Sunglasses At Zephyr Sports for Less Today! We carry a complete line of M Frame Heater Oakley Sunglasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley M Frame Heater Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley M Frame Heater Sunglasses | Oakley Heater Sunglasses | M Frame Heater Oakley Sunglasses" + }, + ".snowboard_gear.snowboard_goggles.electric_snowboard_goggles.electric_eg2_snow_goggles" : { + "meta_description" : "Electric EG2 Goggles - Zephyr Sports carries a complete line of EG2 Electric Goggles At the lowest prices on the web with free shipping and easy returns. Buy your Electric Goggles EG2 Online Today.", + "page_title" : "Electric EG2 Goggles On Sale Free Shipping", + "head_title" : "Electric EG2 Goggles | EG2 Electric Goggles | Electric Goggles EG2" + }, + ".markerupgrades.smartparts.ion.feednecks" : {}, + ".3packagespecials.us_army_paintball_packages.us_army_alpha_tactical_paintball_gun_packages" : { + "meta_description" : "US Army Packages - Buy your Alpha Tactical Package Online at Zephyr Paintball for Less today. Free Shipping on US Army Alpha Package Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy US Army Packages Online On Sale Now", + "head_title" : "US Army Packages | Alpha Tactical Package | US Army Alpha Package" + }, + ".casual_clothing.mens_clothing.beanies.quicksilver_beanies" : { + "meta_description" : "Quicksilver Beanies - Buy your Beanies QuicksilverAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on QUICKSILVER BEANIES @ Zephyr Sports", + "head_title" : "Quicksilver Beanies | Beanies Quicksilver" + }, + ".scenarioupgrades.barrels.tippmann_98_tactical_barrels" : {}, + ".casual_clothing.mens_clothing.beanies.rvca_beanies" : { + "meta_description" : "RVCA Beanies - Buy your Beanies RVCAAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on RVCA BEANIES @ Zephyr Sports", + "head_title" : "RVCA Beanies | Beanies RVCA" + }, + ".harnessesbags.packs___harnesses.maddog_designz_paintball_pod_packs" : { + "meta_description" : "Maddog Paintball Harness - Buy your Maddog Sports Pod Pack Online at Zephyr Paintball for Less today. Free Shipping on Maddog Paintball Packs Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Maddog Paintball Harness Online On Sale Now", + "head_title" : "Maddog Paintball Harness | Maddog Sports Pod Pack | Maddog Paintball Packs", + "prodlist1_header" : "Maddog Sports Harnesses" + }, + ".skateboard_gear.skateboard_longboards" : { + "meta_keywords" : "longboarding skateboarding,longboard complete,longboarding skateboard,complete longboards,longboard skateboard complete,sector nine longboard,sector 9 longboard skateboard,Arbor Longboards,Carver Longboards,Gravity longboards,", + "meta_description" : "Complete Longboards - Zephyr Sports is the new longboarding skateboarding stop to shop! Wide Range of Longboard Complete skateboards, sector nine longboards, longboard decks, etc! A grip of different longboard skateboard completes by top longboard companies; Sector 9 longboards, Arbor Longboards, Carver Longboards, Gravity longboards, and more! And don't forget! Longboarding accessories like carving trucks, skateboard bearings and other skateboard accessories all available @ Zephyr Sports!", + "page_title" : "Longboard Skateboard On Sale & Free Shipping", + "head_title" : "Longboard Skateboard | Longboard Complete | Skateboard Longboards" + }, + ".apparel.gloves.condor_tactical_gloves" : {}, + ".2clearance.1-dye_rotor___i4_sale" : { + "top_description" : "", + "head_title" : "Dye Rotor Loader Sale | Dye I4 Mask Sale" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.echo_1_airsoft_guns.m4___m16_echo_1_airsoft_guns" : {}, + ".markerupgrades.smartparts.epiphany" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "add2_link" : "/category/markerupgrades.feednecks.impulse_ion_sft_feednecks/", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".casual_clothing.mens_clothing.tshirts.pig_t_shirts" : { + "meta_description" : "Pig Skate Shirts - Buy your Pig Wheels Shirts At Zephyr Sports for Less Today! We carry a complete line of Pig Skate Clothing at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Pig Skate Shirts On Sale & Free Shipping", + "head_title" : "Pig Skate Shirts | Pig Wheels Shirts | Pig Skate Clothing" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.kwa_aeg_electric_airsoft_rifles" : { + "meta_description" : "KWA Airsoft Guns - Buy your KWA Airsoft Rifle At Zephyr Sports for Less Today! We carry a complete line of KWA Airsoft AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy KWA Airsoft Guns On Sale & Free Shipping", + "head_title" : "KWA Airsoft Guns | KWA Airsoft Rifle | KWA Airsoft AEG" + }, + ".casual_clothing.mens_clothing.beanies.proto_beanies" : { + "meta_keywords" : "Proto beanie,Proto hat,Proto beanies,Proto caps,Proto 686,Proto headwear,Proto cuff visor beanie,Proto beanie hat,Proto visor beanie,Proto visor beanies", + "meta_description" : "Proto Deanie - Surf style with Proto Beanies available now at Zephyr Sports. Get your Proto hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Buy Proto Beanie On Sale & Free Shipping", + "head_title" : "Proto Beanie | Proto Hat | Proto Beanies" + }, + ".markerupgrades.tippmann.a5.triggersgrips" : { + "meta_description" : "Tippmann A5 Triggers - Buy your A5 Triggers Online at Zephyr Paintball for Less today. Free Shipping on A-5 Response Trigger Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann A5 Triggers Online On Sale Now", + "head_title" : "Tippmann A5 Triggers |A5 Triggers | A-5 Response Trigger" + }, + ".empire_prophecy_paintball_loader" : {}, + ".airsoft.airsoft_guns.firepower_airsoft_guns" : { + "meta_keywords" : "Firepower airsoft guns,spring pistols,electronic rifles,replica airsoft,cheap airsoft guns,", + "meta_description" : "Firepower Airsoft Guns. Firepower offers a wide range of airsoft guns from spring pistols to electronic rifles. Their affordable prices make them a great choice for anyone looking to get into airsoft, or the budget conscience shopper. Firepower replica airsoft products are great renditions of the real life counter-parts and provide a realist look and feel for any enthusiast. For cheap airsoft guns, Choose Firepower @ Zephyr!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Firepower Airsoft Guns On Sale & Free Shipping", + "head_title" : "Firepower Airsoft Guns | Firepower Soft Air Gun | Firepower Air Soft Guns", + "description" : "" + }, + ".barrels.barrels_by_manufacturer.invert_paintball_barrels" : { + "meta_keywords" : "invert paintball barrels, invert carbon fiber barrels, invert night stick, night stick paintball barrel, invert barrels, carbon fiber night stick", + "meta_description" : "Invert Paintball Barrels - Buy your Invert Carbon Fiber Barrels Online at Zephyr Paintball for Less today. Free Shipping on Invert Night Stick Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert Paintball Barrels Online On Sale Now", + "head_title" : "Invert Paintball Barrels | Invert Carbon Fiber Barrels | Invert Night Stick" + }, + ".markerupgrades.e.markerupgrades.invert_upgradesmpire_upgrades" : {}, + ".airsoft.optical_and_flashlight_upgrades.optics_and_flashlight_mounts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Tactical flashlight mounts | Flashlight mount | Tactical mounts" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.echo_1_electric_airsoft_rifles.mp5_echo_1_airsoft_guns" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Echo 1 Mp5 | Echo1 MP5 | MP5 Echo 1" + }, + ".shop_by_brand.propper" : {}, + ".apparel.pants.propper_bdu_pants" : {}, + ".airsoft.airsoft_guns.1_shop_by_gun_type.m16_airsoft_guns" : { + "meta_description" : "M16 Airsoft Guns - Buy your Airsoft M16 At Zephyr Sports for Less Today! We carry a complete line of M16 AEG Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "Below are replica M16 Airsoft Rifles. The original M16 entered United States Army service and was put into action for jungle warfare in South Vietnam in 1963, becoming the standard U.S. rifle of the Vietnam War by 1969, replacing the M14 rifle in that role. Since the Vietnam War, the M16 rifle family has been the primary infantry rifle of the U.S. military. The M16 is in use by 15 NATO countries and more than 80 countries world wide. Together, numerous companies in the United States, Canada, and China have produced more than 8,000,000 rifles of all variants making it the most manufactured rifle in the world. Approximately 90% are still in operation. ", + "page_title" : "Buy M16 Airsoft Guns On Sale & Free Shipping", + "head_title" : "M16 Airsoft Guns |Airsoft M16 |M16 AEG Airsoft Gun", + "description" : "" + }, + "$2009_products" : {}, + ".airsoft.airsoft_guns.airsoft_bb_launchers___shells.ics" : {}, + ".casual_clothing.mens_clothing.belts.hurley_belts" : { + "meta_description" : "Hurley Belts - Buy your Hurley Mens BeltsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on HURLEY BELTS @ Zephyr Sports", + "head_title" : "Hurley Belts | Hurley Mens Belts" + }, + ".shop_by_brand.action_sport_games" : { + "zoovy:banner01" : "banners/airsoft/headers/1asg_header.jpg" + }, + ".casual_clothing.mens_clothing.hats.spitfire_hats" : { + "meta_keywords" : "Spitfire Hats,Spitfire caps,Spitfire baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Spitfire Hats - Zephyr carries a complete line of Spitfire Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Spitfire", + "page_title" : "Spitfire Hats on Sale at Zephyr", + "head_title" : "Spitfire Hats | Spitfire Caps | Spitfire Baseball Hats" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_unit_watches" : {}, + ".3packagespecials.starter_packs" : { + "meta_description" : "Paintball Packages - Buy your Paintball Guns Kits Online at Zephyr Paintball for Less today. Free Shipping on Paintball Starter Kits Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Packages Online On Sale Now", + "head_title" : "Paintball Packages |Paintball Guns Kits | Paintball Starter Kits" + }, + ".shop_by_brand.kjw_airsoft" : {}, + ".casual_clothing.z_unisex_clothing_accesories.stickers.grenade_stickers" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_tactical_belts.utg_tactical_belts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_pilot_sunglasses" : { + "meta_description" : "Maui Jim Pilot Sunglasses - Zephyr Sports carries a complete line of Maui Jim Pilot Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Pilot Online Today.", + "page_title" : "Maui Jim Pilot Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Pilot Sunglasses | Maui Jim Pilot Sun Glasses | Sunglasses Maui Jim Pilot" + }, + ".loaders.hopper_accesories.feed_elbows" : { + "meta_description" : "Paintball Feed Elbows - Buy your 45 Degree Paintball Elbow Online at Zephyr Paintball for Less today. Free Shipping on Paintball Gun Loader Elbow Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Feed Elbows Online On Sale Now", + "head_title" : "Paintball Feed Elbows | 45 Degree Paintball Elbow | Paintball Gun Loader Elbow" + }, + ".markerupgrades.smartparts.ion.triggers.warrior_paintball_ion_triggers" : {}, + ".airsoft.airsoft_safety.airsoft_goggles.save_phace_goggles" : { + "head_title" : "Save Phace Goggles | Save Phace Airsoft Masks | Save Phace Masks" + }, + ".harnessesbags.tubes" : { + "meta_keywords" : "Paintball Pods, Paintball Pod Harness, Paintball Pod Packs, Paintball Pod, Paintball Harness, Paintball Packs, Pod Packs, Pod Harness, Paintball Tubes", + "meta_description" : "Paintball Pods - Get the best prices on paintball pod packs and harnesses online at ZephyrPaintball.com.", + "page_title" : "Buy Paintball Pods Online On Sale Now", + "head_title" : "Paintball Pods | Paintball Pod Harness | Paintball Pod Packs", + "page_head" : "" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.heckler___koch_aeg_airsoft_guns" : { + "meta_description" : "Heckler and Koch Airsoft Guns - Buy your H&K Airsoft MP5At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Heckler and Koch Airsoft Guns On Sale & Free Shipping", + "head_title" : "Heckler and Koch Airsoft Guns | H&K Airsoft MP5" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.eclipse_ladies_t_shirts" : {}, + ".scenarioupgrades.flashlights___laser_sights.daisy" : {}, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_body_kits" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Body Kits | AEG Body Kits" + }, + ".airsoft.tactical_airsoft_gear.head_gear.condor_tactical" : {}, + ".3packagespecials.azodin_paintball_packages.azodin_kaos_packages" : { + "meta_description" : "Azodin Kaos Paintball Packages - Buy your Azodin Kaos Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Kaos Azodin Marker Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Azodin Kaos Paintball Packages Online On Sale Now", + "head_title" : "Azodin Kaos Paintball Packages | Azodin Kaos Paintball Guns | Kaos Azodin Marker" + }, + ".casual_clothing.mens_clothing.shorts.reef_shorts" : { + "meta_description" : "Reef Shorts - Zephyr stocks a complete line of Reef Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Reef needs. ", + "page_title" : "Reef Shorts with Free Shipping at Zephyr", + "head_title" : "Reef Shorts | Reef Board Shorts" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_streetman_backpack" : {}, + ".markerupgrades.rampingchipsboards.hater_paintball_hatred_boards" : { + "meta_description" : "Hater Boards - Buy your Hater Board Paintball Online at Zephyr Paintball for Less today. Free Shipping on Hater Paintball Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Hater Boards Online On Sale Now", + "head_title" : "Hater Boards | Hater Board Paintball | Hater Paintball Boards" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_kmp9" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.echo_1_airsoft_guns.specialty_echo_1_airsoft_guns" : {}, + ".harnessesbags.backpacks.smith_optics_backpacks___bags" : {}, + ".markerupgrades.smartparts.ion.bodykits.trinity_sick_ion_body_kits" : {}, + ".barrels.barrels_by_manufacturer.custom_products_paintball_barrels.1_piece_classic_barrels" : {}, + ".airsoft.shop_by_brand.leapers___utg" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Leapers | leapers scope | Leapers UTG" + }, + ".scenarioupgrades.camelback_hydration_systems" : {}, + ".casual_clothing.youth_clothing.youth_sweatshirts.1_search_by_size.4_x-large" : {}, + ".black_friday_paintball_and_airsoft_deals.loaders___accessories" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_fly_9000_sunglasses" : {}, + ".3packagespecials.kingman_spyder_paintball_packages.kingman_spyder_mrx_paintball_gun_packages_" : { + "meta_keywords" : "Spyder paintball gun, woodsball gun, woodsball marker, Spyder MRX, Spyder MRX Elite, Spyder woodsball, spyder markers, spyder elite marker, spyder elite paintball gun, woodsball markers, woodsball paintball gun, woodsball, military simulation paintball guns, DLS, Dual Loading System, Mag Fed paintball gun, paintball magazine, paintball packages, paintball kit", + "meta_description" : "The Spyder MRX Paintball gun is an excellent woodsball marker for the player looking for the most realist military simulation. the DLS (Dual Loading System) allows you to use both a hopper and the guns 10 round magazine to spray paint. Pick up a Spyder Paintball Gun today at Zephyr!", + "page_title" : "Buy Online Spyder MRX On Sale & Free Shipping", + "head_title" : "Spyder Paintball Gun | Woodsball Marker | Spyder MRX" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_zapparel" : { + "meta_keywords" : "Oakley Sunglasses,Oakleys,oakley mens sunglasses,oakley jacket sunglasses,Oakley Polarized sunglasses,Oakley Jacket Sunglasses,Oakley Antix Sunglasses,Oakley Ballistic Sunglasses,Oakley Eyepatch Sunglasses,Oakley Fives Squared Sunglasses,Oakley Flak Jacket Sunglasses,Oakley Gascan Sunglasses,Oakley Hijinx Sunglasses,Oakley Inmate Sunglasses,Oakley Monster Dog Sunglasses,Oakley Monster Pup Sunglasses,Oakley Oil Rig Sunglasses,Oakley Radar Pitch Sunglasses,Oakley Sideways Sunglasses,Oakley Straight Jacket Sunglasses ", + "meta_description" : "Oakley Sunglasses now available @ Zephyr! Get your brand new Oakleys now! Oakley Mens sunglasses available in select styles; Oakley Jacket Sunglasses, Oakley Antix Sunglasses, Oakley Ballistic Sunglasses, Oakley Eyepatch Sunglasses, Oakley Fives Squared Sunglasses, Oakley Flak Jacket Sunglasses, Oakley Gascan Sunglasses, Oakley Hijinx Sunglasses, Oakley Inmate Sunglasses, Oakley Monster Dog Sunglasses, Oakley Monster Pup Sunglasses, Oakley Oil Rig Sunglasses, Oakley Radar Pitch Sunglasses, Oakley Sideways Sunglasses, and Oakley Straight Jacket Sunglasses on sale! Oakley Polarized Sunglasses available as well!!" + }, + "$newitems" : {}, + ".markerupgrades.grips_and_grip_panels" : {}, + ".loaders.hopper_accesories.odyssey_halo_accesories.halo_laser_eyes" : { + "meta_description" : "HaLO Upgrade Boards - Buy your Virtue Halo Board Victory 35 Online at Zephyr Paintball for Less today. Free Shipping on Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy HaLO Upgrade Boards Online On Sale Now", + "head_title" : "HaLO Upgrade Boards | Virtue Halo Board Victory 35" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_flashlights" : { + "meta_description" : "Airsoft Flashlights - Buy your Tactical Flashlights At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Flashlights On Sale & Free Shipping", + "head_title" : "Airsoft Flashlights | Tactical Flashlights" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_outsider_watches" : { + "meta_description" : "Nixon Outsider Watches - Buy your Nixon Outsider Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Outsider at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Outsider Watches", + "head_title" : "Nixon Outsider Watches | Nixon Outsider Watch | Nixon Outsider" + }, + ".casual_clothing.mens_clothing.sweatshirts.spy_optic_sweatshirts" : { + "meta_description" : "Spy Sweatshirts - Buy your Spy Hoodies At Zephyr Sports for Less Today! We carry a complete line of Spy Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Spy Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Spy Sweatshirts | Spy Hoodies | Spy Hoody" + }, + ".shop_by_brand.dangerous_power" : { + "meta_keywords" : "dangerous power,e1,g3,g4,dangerous power paintball,dangerous power paintball guns,revi,markers", + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tDANGEROUS POWER PAINTBALL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n\n", + "meta_description" : "Dangerous Power - Arguably one of the best manufacturer of entry level to mid range Tournament Paintball Guns. Dangerous Power Paintball Guns give you some of the best bang for the buck. Trust Dangerous Power Paintball to get you on the field for less at Zephyr Sports.", + "top_description2" : "=With Dangerous Power, Comes Dangerous Resposibility=\n\nDangerous Power Paintball was founded on the bases of creating a high quality, no compromise Paintball marker. In 2006 the world was introduced to the fusion, and since then DP has been creating only the highest quality Paintball product. Dangerous Power specializes in making beautiful Markers out of lightweight alloys. Dangerous Power paintball guns are constantly being created and innovated to be more effective, lighter-weight and pack a punch! ", + "page_title" : "Dangerous Power Paintball Ships Free at Zephyr Sports", + "head_title" : "Dangerous Power | Dangerous Power Paintball Guns", + "description" : "=With Dangerous Power comes Dangerous Responsibility=\n\n==About Dangeous Power==\nDangeous Power strives to make quality Paintball products at affordable prices. They know everyone can't break the bank when attempting to buy a new gun, so they have created multiple series of ridiculously high quality guns at prices that won't require you to cash in your 401K. These products speak for themselves, really. With all the technology and innovation available in these guns, you don't need anything more. These are reliable, cost-effective and awesome looking products. Take a look for yourself. \n\n\n==The DP E1==\nDangerous Power announces the newest addition to the DP arsenal, the E1. Through DP's master craftsmanship and high performance, the E1 brings enlightenment & supreme power in its class. The E1 utilizes the dump-valve & G3 firing system, the perfect system designed for all levels of experience. The qualities and features cannot be beat for its price. The E1's lightweight design, efficient regulating pressure system, ease of operation & maintenance emphasizes high-efficient performance backed with reinforced durability.\n\n==The DP G4==\nThe G4 has now arrived and invokes the triumphs and prosperity of Dangerous Power’s advanced engineering through its innovations and master craftsmanship. The G-Series is reborn and leaves the competition in its wake. The G4 weighs in at 1.79lbs including barrel, RAPS ASA, low-profile clamping feedneck, & battery. The G4 has adapted the Spec-R’s accuracy and efficiency by utilizing the O-ring-less bolt system. The O-ring-less bolt not only improves the G4’s performance, but also decreases O-ring wear and tear resulting in less maintenance! The G4 demands precision and comfort by adopting the Rev-I’s four-way trigger adjustment including the breakaway magnetic trigger. The G4 includes a new, fully engineered, spring-assisted regulator increasing its accuracy and durability. Dangerous Power Engineering has enforced qualities in the G4 to adapt to change and overcome any scenario by implementing a fully programmable micro-switch board for every player’s preference. \n\n==The Dangerous Power Fusion X==\nWith Reinforced Fire-valves, Ballistic Rams, Low pressure regulators, Switchblade triggers, Mulch-adjustable triggers, and even Rapid air pressure systems The Fusion X takes a prideful stand and fierce introduction for the new decade! Through intricate design and development, the Fusion series conjures powerful attributes making it a new class of Dangerous Power markers. From superior quality, the FX's newly designed internals ensure dominating performance. The slim striker system's compact performance aims to deliver efficiency and accuracy. The lightweight body and internals ensures quick mobility for a fast response time." + }, + ".airsoft.airsoft_guns.tactical_force_airsoft_guns" : { + "meta_description" : "Tactical Force Airsoft Guns - Buy your Tactical Force Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Tactical Force AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Tactical Force Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Tactical Force Airsoft Guns | Tactical Force Airsoft Rifles | Tactical Force AEG", + "description" : "" + }, + ".airsystems.dropforwards.newdesignz" : { + "meta_description" : "New Designz ASA - Buy your New Designz Thread Saver ASA Online at Zephyr Paintball for Less today. Free Shipping on Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy New Designz ASA Online On Sale Now", + "head_title" : "New Designz ASA | New Designz Thread Saver ASA" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.1-search_by_size.1-small" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.1m4_style_aeg_airsoft_guns" : { + "meta_description" : "M4 Airsoft Guns - Buy your Airsoft M4 At Zephyr Sports for Less Today! We carry a complete line of M4 AEG Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy M4 Airsoft Guns On Sale & Free Shipping", + "head_title" : "M4 Airsoft Guns |Airsoft M4 |M4 AEG Airsoft Gun" + }, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.utg_tactical_holsters" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsoft.airsoft_safety.airsoft_glasses" : { + "meta_description" : "Airsoft Safety Glasses - Buy your Airsoft Glasses At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Safety Glasses On Sale & Free Shipping", + "head_title" : "Airsoft Safety Glasses | Airsoft Glasses" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_variable_power_scopes.barska_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.tank_tops.oakley_tank_tops" : { + "meta_description" : "Oakley Tank Tops - Buy your Oakley Jersey Tank Tops At Zephyr Sports for Less Today! We carry a complete line of Oakley Mens Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Oakley Mens Jersey Tank Tops at Zephyr Sports", + "head_title" : "Oakley Tank Tops | Oakley Jersey Tank Tops | Oakley Mens Tank Tops" + }, + ".skateboard_gear.complete_skateboards.1_complete_skateboards_by_size_.75__complete_skateboards" : {}, + ".baseball.baseball_bats" : { + "meta_description" : "Baseball Bats - Buy your Softball Bats At Zephyr Sports for Less Today! We carry a complete line of Little League Bats at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Baseball and Softball Bats on Sale Now", + "head_title" : "Baseball Bats | Softball Bats | Little League Bats" + }, + ".casual_clothing.mens_clothing.sandals.volcom_sandals" : { + "meta_description" : "Volcom Sandals - Buy your Mens Volcom Sandals Online At Zephyr Sports for Less Today! We carry a complete line of Volcom Flip Flops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Volcom Sandals On Sale at Zephyr Sports", + "head_title" : "Volcom Sandals | Mens Volcom Sandals | Volcom Flip Flops" + }, + ".loaders.hopper_accesories.dye_loader_accesories.soft_cycles" : {}, + ".apparel.head_bands_and_wraps.full_clip_head_bands_and_wraps" : {}, + ".2clearance.1-black_friday.airsoft" : { + "head_title" : "Black Friday Airsoft Sale | Airsoft Black Friday" + }, + ".shop_by_brand.eclipse_paintball" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tGuns\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tPackages\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tPlaying Gear\n\t\n
                                                                          \n
                                                                          ", + "meta_description" : "Planet Eclipse - Buy your Planet Eclipse Ego At Zephyr Sports for Less Today! We carry a complete line of Eclipse Paintball at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "", + "page_title" : "Buy Planet Eclipse On Sale & Free Shipping", + "head_title" : "Planet Eclipse | Planet Eclipse Ego | Eclipse Paintball", + "description" : "The journey started around 94', in a little retail store called Paintball Planet in Manchester England with little more than 3 staff and limited stock but with a great deal of passion to get ballers the newest and best paintball equipment available.\n\n\nThe inception of the Eblade around 2002 (an electronic upgrade for the autococker) saw the birth of a new era for Paintball Planet due to its un-stoppable presence we quickly built a name for quality and reliability a value that they cherish today above all else.\n\n\nThey bare now creating quality, reliable, equipment, accessories and leading industry electronic paintball markers such as the Ego, Geo, Etek, SL, and equipment that all carry one name Planet Eclipse. They pride themselves on their un-paralleled customer service and technical support and today more than ever the mission and the passion is the same. With offices in the UK and the US and tech staff from all over the world Planet Eclipse is now responsible for some of the finest award winning, kick ass paintball products to hit the paintball field, whatever your arena!\n", + "zoovy:banner02" : "banners/paintball/headers/planet_eclipse_banner.jpg" + }, + ".police_and_military_gear.universal_molle_accesories.condor_tactical" : {}, + ".sponsorship.sponsor_only_specials.team_sponsorship_packages" : {}, + ".shop_by_brand.major_paintball" : {}, + ".casual_clothing.z_unisex_clothing_accesories.stickers.fox_racing_stickers" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.krooked_headphones" : { + "meta_keywords" : "Krooked Headphones,Krooked Head Phones, Krooked Audio", + "meta_description" : "Krooked Headphones - Zephyr stock a complete line of Krooked Head Phones. For the ultimate Audio experience buy your Krooked at Zephyr Today", + "page_title" : "Krooked Headphones with Free Shipping at Zephyr", + "head_title" : "Krooked Headphones | Krooked Head Phones | Headphones Krooked" + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_fame_sunglasses" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_water_bottles.camelbak_better_bottle_classic_water_bottles" : {}, + ".airsystems.nitrogentanks.hk_army_nitrogen_tanks" : { + "meta_keywords" : "HK Army Air Systems,HK Army Paintball Tanks,Paintball HPA Compressed Air Tanks,nitrogen tanks,HK Army,paintball compressed air tank,paintball tanks,air tanks,air tank,compressed air,", + "htmlvids" : "", + "meta_description" : "HK Army Air Systems! Top of the line Paintball Compressed Air Tanks by HK Army. These are brand new HPA Tanks / Nitrogen Tanks with custom HK Army graphics! Get in the Game and dominate with HK Army Paintball Tanks.", + "top_description" : "== HK ARMY AIR SYSTEMS ==\n\nThe freshest in bottle graphics paired with an ultra-consistent, precision designed and engineered regulator. Pumping out a solid, consistent high-pressure output, the HK Army Air system is built to perform while looking good! ", + "page_title" : "Buy HK Army Paintball Tanks Online On Sale Now", + "head_title" : "HK Army Air Systems | HK Army Paintball Tanks | Paintball HPA Compressed Air Tanks " + }, + ".markers.tippmann.tippmann_x7_paintball_guns" : { + "banner2" : "", + "meta_keywords" : "tippmann x7 paintball guns,X7 Phenom,tippmann x7 markers, x7 paintball gun,x7 response trigger, x7 paintball markers, x7 marker, tippmann x7 with e-grip, tippmann x-7, tippmann x-7 paintball gun", + "meta_description" : "Tippmann X7 Phenom Paintball Guns - Zephyr is the leader in X7 Phenom. Whether you are looking for standard X7 Paintball markers or one of our M16, AK47 or other upgraded military markers from tippmann we have you covered. X7 Phenom Paintball Guns feature the tippmann cyclone feed system for unparalleled performance without batteries. On Sale at Zephyr Now", + "top_description" : "The Tippmann X7 Phenom is one of the most durable paintball guns on the market. Throw it, step on it, dunk it in water, cover it in dirt, tie it to the back of your truck and drag it for 4 miles. Actually, don't do the last one. If you did though, I'd bet it would stay in tact. The durability is not the only thing great about this gun. The X7 Phenom is completely customizable. Give it that realistic look and feel with modifications such as the AK47, M16, UMP and others. If you are looking for the ultimate Tippmann paintball gun, than the X7 Phenom is your gun for its consistency in shots, air efficiency and overall performance. The X7 Phenom is available in a mechanical as well as an electronic version.", + "description" : "==How's the performance?==\n\n\nLike the Tippmann A5, the Tippmann X7 Phenom is equipped with a Cyclone Feed for quick feeding action that makes every shot count. If you are new to this concept - the cyclone feed uses the excess air every time your gun is fired to feed paintballs into the chamber. The X7 Cyclone is actually faster than the Tippmann A5 version which has been one of the noticeable differences due to its redesigned parts. Also, the new low profile X7 Hopper provides a clean view along the top of the marker. The Tippmann X7 Phenom will work fine on both CO2 & Compressed air tanks. With compressed air you will get more consistency in your shots vs. CO2 that doesn't expand into gas very well if it's too cold outside. \n\n\n==What Upgrades are available?==\n\n\nMuch like the other Tippmann paintball guns there are many accessories for making your X7 look and feel exactly how you want it too. The X7 Phenom Paintball Gun is fully upgradeable whether you purchased the mechanical or the electronic version. Semi-automatic can be simple and fun but there may be times when you want to switch over into a burst or full auto mode. What's great about paintball you never know what type of game you are thrown into and by having the E-grip this allows you to experience all different types of games.\n\n\n==What Barrels are available?==\n\n\nThe Tippmann X7 Phenom shares the same thread as the Tippmann A5. Much like the other flatline barrels for the Tippmann A5/Custom 98 the [[X7 Flatline Barrel]:url=/product/PB-TIP-X7FLAT/Tippmann_X7_Flatline_Barrel.html] takes the lead in the best performing barrel. Giving a back spin on the paintball increases your range and accuracy. The Flatline barrel will not disappoint. Being one of the highest recommended barrels on the market makes it an easy choice. This new look Flatline is integrated into the markers design with picatinny railing for many available accessories. There are many other [[X7 Barrels]:url=/category/barrels.tippmanna5/] available that all differentiate in size, weight & look. If you need further assistance looking for a barrel please don't hesitate to chat with us or phone us for more information.\n", + "banner2_link" : "", + "top_html_focus" : "", + "htmlvids" : "
                                                                          \n
                                                                          ", + "head_title" : "Tippmann X7 Phenom Paintball Guns | X7 Phenom | X7 Phenom Paintball Markers", + "page_title" : "Buy Tippmann X7 Phenom Paintball Guns Online On Sale Now" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.crosman_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_antix_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley antix polarized sunglasses,oakley antix,antix oakley glasses,", + "meta_description" : "Oakley Antix Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Antix and Antix Polarized Oakley Sunglasses on Sale!", + "page_title" : "Oakley Antix Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Antix Sunglasses | Antix Oakley Sunglasses | Oakley Antix Polarized Sunglasses" + }, + ".paintball.paintball_hopper_loaders" : {}, + ".safetygear.kneeelbowpads.planet_eclipse_knee___elbow_pads" : {}, + ".apparel.jerseys.dyejerseys.dye_c14_paintball_jerseys" : { + "top_html_focus" : "" + }, + ".casual_clothing.mens_clothing.shirts.analog_shirts" : { + "meta_description" : "Analog Flannel Shirts - Buy your Analog Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Analog Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Analog Shirts & Flannels Ship Free", + "head_title" : "Analog Flannel Shirts | Analog Polo Shirts | Analog Shirts" + }, + ".shop_by_brand.nc_star" : { + "meta_description" : "NCStar Scopes - Buy your NC Star Scopes At Zephyr Sports for Less Today! We carry a complete line of NC Star Sights at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=YOU ONLY GET ONE SHOT... MAKE IT NcSTAR!= \t\n\n\nFor 12 years, NcSTAR has manufactured and provided optics for a few of the leading brand names in the optics industry. Within that time period, New Century gained the expertise and knowledge of the optics market. By 1997, a new and competitive brand hit the market known as NcStar, the fastest growing optics company in the world.", + "page_title" : "Buy NCStar Scopes On Sale & Free Shipping", + "head_title" : "NCStar Scopes | NC Star Scopes | NC Star Sights", + "description" : "Founded in 1997, NcSTAR’s mission is to consistently provide reasonable priced, quality optics with innovative design, superb customer service, and strong dealer partnerships. NcStar optics are built to high quality control standards and are designed to deliver a lifetime of satisfaction. NcStar optics is the preferred choice of many professional users, armed forces, and consumers ranging from air soft to wildlife observation all over the world. So whether you are an expert marksman or novice, NcStar has something for everyone.\n\n\n=NcSTAR:=\n* Manufactures and provides NcSTAR products to meet any budget for any dealer.\n* Provides drop shipment to your customers. Let our warehouse be your warehouse!\n* Provides tech support for both dealers and consumers.\n* Original Equipment Manufacturer (O.E.M.). Sell your own brand!\n* Offers great customer service with a quick response from our knowledgeable staff." + }, + ".casual_clothing.mens_clothing.hats.alien_workshop_hats" : { + "meta_keywords" : "Alien Workshop Hats,alien workshop caps,alien workshop baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Alien Workshop Hats - Zephyr carries a complete line of Alien Workshop Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Alien Workshop", + "page_title" : "Alien Workshop Hats on Sale at Zephyr", + "head_title" : "Alien Workshop Hats | Alien Workshop Caps | Alien Workshop Baseball Hats" + }, + ".casual_clothing.mens_clothing.sweatshirts.oakley_sweatshirts" : { + "meta_description" : "Oakley Sweatshirts - Buy your Oakley Hoodies At Zephyr Sports for Less Today! We carry a complete line of Oakley Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Oakley Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Oakley Sweatshirts | Oakley Hoodies | Oakley Hoody" + }, + ".markerupgrades.gog_paintball_gun_upgrades" : {}, + ".apparel.gloves.maddog_sports" : {}, + ".scenarioupgrades.tactical_vests.scenario_paintball_holsters" : {}, + ".casual_clothing.mens_clothing.shorts.hurley_shorts" : { + "meta_description" : "Hurley Board Shorts - Buy your Hurley Shorts At Zephyr Sports for Less Today! We carry a complete line of Hurley Boardshorts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Hurley Boardshorts Ship Free at Zephyr Sports", + "head_title" : "Hurley Board Shorts | Hurley Shorts | Hurley Boardshorts" + }, + ".airsoft.shop_by_brand.king_arms" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "King Arms | King Arms m4 | King arms m4a1" + }, + ".2clearance.paintball_clearance_gear.clearance_goggles" : { + "head_title" : "Sale Paintball Masks | Clearance Paintball Masks | Paintball Goggles Sale" + }, + ".category.casual_clothing.mens_clothing" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_mover_sunglasses" : { + "meta_description" : "Arnette Mover Sunglasses - Zephyr Sports carries a complete line of Mover Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Mover Sun Glasses Online Today.", + "page_title" : "Arnette Mover Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Mover Sunglasses | Mover Arnette Sunglasses | Arnette Mover Sun Glasses" + }, + ".scenarioupgrades.scenario_apparel.camo_paintball_jerseys.dye_tactical_jerseys" : {}, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_transfer_sunglasses" : { + "meta_description" : "Anarchy Transfer Sunglasses - Zephyr Sports carries a complete line of Anarchy Transfer Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Transfer Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Transfer Sunglasses | Anarchy Transfer Sun Glasses" + }, + ".casual_clothing.mens_clothing.beanies.invert_beanies" : { + "meta_keywords" : "Invert beanie,Invert hat,Invert beanies,Invert caps,Invert 686,Invert headwear,Invert cuff visor beanie,Invert beanie hat,Invert visor beanie,Invert visor beanies", + "meta_description" : "Invert Deanie - Surf style with Invert Beanies available now at Zephyr Sports. Get your Invert hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Invert Beanies on Sale at Zephyr Today", + "head_title" : "Invert Beanie | Invert Hat | Invert Beanies" + }, + ".1historical_products.paintball" : {}, + ".loaders.hopper_accesories.exalt_loader_accessories" : {}, + ".markers.jtusapaintballguns.jt_splatmaster_paintball_guns" : { + "top_description" : "JT SplatMaster is a low impact product that shoots round color filled Ammo resulting in a Splat. JT SplatMaster markers are spring loaded and shoot at a velocity of 110-140 feet per second. JT SplatMaster was engineered so kids (and adults!) ages 9+ could easily cock, load, and fire. JT SplatMaster Ammo is 100% biodegradable, non toxic, non staining, and easily washes away with water. JT SplatMaster is active play for the entire family. Safe, fun, accurate - Get in the Game!", + "zoovy:banner01" : "" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_palms_sunglasses" : { + "meta_description" : "Maui Jim Palms Sunglasses - Zephyr Sports carries a complete line of Maui Jim Palms Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Palms Online Today.", + "page_title" : "Maui Jim Palms Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Palms Sunglasses | Maui Jim Palms Sun Glasses | Sunglasses Maui Jim Palms" + }, + ".dye_i4_paintball_goggle_mask.paintball_blog.empire_e-flex_paintball_mask" : {}, + ".barrels.barrels_by_manufacturer.custom_products_paintball_barrels" : { + "meta_keywords" : "custom products barrels, cp barrels, cp paintball barrels, custom products paintball barrels, accurate paintball barrels, cp paintball", + "meta_description" : "Custom Products Barrels - Buy your CP Barrels Online at Zephyr Paintball for Less today. Free Shipping on CP Paintball Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Custom Products Barrels Online On Sale Now", + "head_title" : "Custom Products Barrels | CP Barrels | CP Paintball Barrels", + "sortby_var" : "Custom Products Barrel Type" + }, + ".markerupgrades." : {}, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases.echo_1" : {}, + ".markerupgrades.e.markerupgrades.invert_upgrades/mpire_upgrades/" : {}, + ".shop_by_brand.bravo_airsoft" : {}, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases.511_tactical_backpacks_and_gun_cases" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z_shoes_and_footwear.dc_skate_shoes" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_warm_up_womens_sunglasses" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_hijinx_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley hijinx sunglasses,polarized oakley hijinx sunglasses", + "meta_description" : "Oakley Hijinx Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Hijinx and Polarized Oakley Hijinx Sunglasses on Sale!", + "page_title" : "Oakley Hijinx Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Hijinx Sunglasses | Oakley Hijinz Polarized Sunglasses | Hijinx Oakley Sunglasses" + }, + ".harnessesbags.packs___harnesses.hk_army_paintball_harnesses" : { + "meta_keywords" : "hk army paintball harness,pod pack,hk army,paintball pod pack,hk army eject,eject harness", + "meta_description" : "HK Army Eject Paintball Harness - Get your HK Army Harness at Zephyr Paintball today. We carry a complete line of HK Army Paintball Pod packs. Get em while they last today.", + "top_description" : "Zephyr Paintball now carries the HK Army Eject Paintball Harness. Just released from HK Army, The eject harness mixes tournament level features with the HK Army style we all know and love. Get your HK Army Eject Harness today while supplies last.", + "page_title" : "HK Army Eject Paintball Harness Sale", + "head_title" : "HK Army Paintball Harness | HK Army Eject Harness | HK Army Paintball Pod Pack" + }, + ".casual_clothing.mens_clothing.shirts.metal_mulisha" : { + "meta_description" : "Metal Mulisha Flannel Shirts - Buy your Metal Mulisha Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Metal Mulisha Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Metal Mulisha Shirts & Flannels Ship Free", + "head_title" : "Metal Mulisha Flannel Shirts | Metal Mulisha Polo Shirts | Metal Mulisha Shirts" + }, + ".harnessesbags.backpacks.chocolate_backpacks" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_corporal_watches" : { + "meta_keywords" : "Nixon watches,nixon Corporal watch,nixon watch,nixon Corporal chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Corporal Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Corporal Chrono Watches", + "head_title" : "Nixon Corporal Watches | Nixon Corporal Chrono Watch | Nixon 5130" + }, + ".markers.cci_paintball_guns.cci_gravity_feed_paintball_guns" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_kensington_watches" : { + "meta_keywords" : "Nixon watches,nixon Kensington watch,nixon watch,nixon Kensington chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Kensington Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Kensington Chrono Watches", + "head_title" : "Nixon Kensington Watches | Nixon Kensington Chrono Watch | Nixon 5130" + }, + ".casual_clothing.mens_clothing.tshirts.foundation_t_shirts" : { + "meta_keywords" : "foundation skate,foundation shirts,foundation t shirt,foundation t shirts,foundation tee shirts,foundation tshirt,foundation clothing,foundation apparel\r ", + "meta_description" : "Foundation Shirts - Zephyr SPorts carries a complete line of Foundation T Shirts with free shipping over $75 and hassle free returns. Get your Foundation T Shirt today.", + "page_title" : "Foundation Shirts On Sale & Free Shipping", + "head_title" : "Foundation Shirts | Foundation T Shirt | Foundation T Shirts" + }, + ".airsoft.airsoft_guns.elite_force_airsoft_guns" : {}, + ".barrels.barrels_by_manufacturer.stiffi_paintball_barrels.stiffi_tippmann_98_threaded_barrels" : {}, + ".markers.indian_creek_paintball_guns" : { + "meta_keywords" : "Indian Creek Promaster, Promaster Paintball Guns, Promaster paintball marker, Indian creek paintball gun, icd paintball", + "banner1" : "banners/categories/guns/indian_creek_banner.jpg", + "meta_description" : "Indian Creek Promaster - Get the promaster paintball gun while supplies last at Zephyr. Save over $250 now. ", + "page_title" : "Buy Indian Creek Promaster Online On Sale Now", + "head_title" : "Indian Creek Promaster | Promaster Paintball Guns | Promaster paintball marker" + }, + ".apparel.head_bands_and_wraps.valken_head_bands_and_wraps" : { + "head_title" : "Valken Headbands | Valken Head Band | Valken Headwrap" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.blind_youth_t_shirts" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.fly_girls.fly_girls_flynoculars" : { + "meta_keywords" : "Fly Girls Sunglasses,women's sunglasses, womens sunglasses,Flynocular sunglasses", + "meta_description" : "Fly Girls Flynocular Sunglasses now available @ Zephyr! Be the next Fly Girl to rock a pair of Black Flys womens sunglasses! Select Styles of these women's sunglasses by fly girl available in multiple colors!", + "page_title" : "Fly Girls Flynoculars Sunglasses On Sale & Free Shipping", + "head_title" : "Fly Girls Flynoculars Sunglasses | Flygirls Sunglasses | FlyGirls Flynoculars Sunglasses" + }, + ".casual_clothing.mens_clothing.jackets.1_search_by_size.2-medium" : {}, + ".shop_by_brand.save_phace" : { + "top_description2" : "==Save Phace, Intimidate and conquer.==\n\nEveryone at Save Phace masks is an adrenaline junkie. It really doesn't matter what sport activity you participate in, Save Phace will have you covered and protected no matter what you do, especially paintball and air soft Save Phace masks and Save Phace paintball masks are some of the best masks offered for face protection. Save Phace has spent over 5 years researching and developing their product line and have maximized collective ability to helping you have a more comfortable, pain free game.", + "head_title" : "Save Phace mask | Save Phace paintball mask | Save Phace Masks", + "description" : "==Save Phace, Intimidate and conquer.==\n\n==Scare the living crap out of people==\n\nFirst look at these masks without wincing. These things are creepy and plain scary. Imagine it, it's a night game and you sneak up on your opponent from the dark. You breath on their shoulder and snarl. They look behind them and see a predator mask and go still, and you have the pleasure of shooting the life out of them. As far as intimidation goes, these masks are the best. \n\n==Quality over everything==\nNot only do these masks scare people, they are also pieces of art and made of the best quality materials man can buy. These masks will last you the life of your face, which should be forever as long as your wear one of these masks. \n\n==Replacement lenses==\n18.00 to 30.00 dollars on Zephyr! Not 50-70 like you will be paying with different masks. " + }, + ".scenarioupgrades.scenario_apparel.camo_paintball_jerseys" : {}, + ".casual_clothing.womens_clothing.ladies_dresses.metal_mulisha_ladies_dresses" : {}, + ".markers.psycoballistics_paintball_guns" : {}, + ".markerupgrades.tippmann.a5.tippmann_a_5_bolts" : {}, + ".casual_clothing.mens_clothing.belts.dvs_belts" : { + "meta_description" : "DVS Belts - Buy your DVS Mens Belts At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on DVS BELTS @ Zephyr Sports", + "head_title" : "DVS Belts | DVS Mens Belts | Belts DVS" + }, + ".casual_clothing.mens_clothing.wallets.empire_wallets" : { + "meta_description" : "Empire Wallets - Buy your Empire Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Empire Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Empire Wallets on Sale @ Zephyr Sports", + "head_title" : "Empire Wallets | Empire Mens Wallets | Empire Wallet" + }, + ".harnessesbags.paintball_gear_bags.valken_gear_bags___backpacks" : { + "meta_description" : "Valken Paintball Gear Bags - Buy your Valken Backpacks Online at Zephyr Paintball for Less today. Free Shipping on Valken Bags Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Valken Paintball Gear Bags Online On Sale Now", + "head_title" : "Valken Paintball Gear Bags | Valken Backpacks | Valken Bags" + }, + ".buyers_guide.airsoft.airsoft_batteries" : { + "top_html" : "", + "answer_01" : "Alkaline - Most alkaline batteries are non-rechargeable and disposable. They are the most common type used in household gadgets and are not seen too much in airsoft. Some alkaline batteries are rechargeable. They have a good capacity but limited rechargability. Rechargeable alkalines get fewer charge cycles in comparison to NiMH rechargeables. \n\n\nNiMH (Nickel-Metal Hydride) - The most common batteries used in AEGs. These batteries have great capacity and long lasting rechargability but are often more expensive than alkaline batteries. NiMH batteries come with different capacities ranging from 1050mah to 5000mah. It is always an advantage to get the higher capacity batteries. One downside is that NiMHs quickly self-discharge so they lose power when they are not being used. They will completely lose charge in about 2-3 months. It is best to recharge these batteries after completely discharging them. Charging them too long can cause damage to the battery.\n\n\nNiCad (Nickel-Cadmium) - These batteries have good capacity and long life rechargability. NiCads must be fully discharged before they can be charged again. Do not charge a warm battery. Let them cool off before charging so that they can absorb the most amperage. There is a certain theory that NiCad batteries suffer from memory effect. If the battery is recharged before it is fully spent, it will remember that capacity at which is recharged, resulting in reduced capacity of the battery.\n\n\nLithium Ion - These batteries have great capacity but are very expensive and combustible. Non-rechargeable lithium ion batteries can be used in high drain devices such as digital cameras and cd players. The rechargeable kind are often used in cell phones.\n\n\nLithium Polymer / Nano (LiPo, Li-Poly) - These rechargeable batteries have a great capacity and are less combustible but also very expensive. Overcharging a Li-poly battery can result in explosion and/or fire. Additionally, discharging the LiPo under 3 Volts can cause damage to the LiPo such that it cannot be charged again. These batteries can add a significant amount of power to an airsoft gun and will not harm an AEG as long as the right battery pack is used. Common battery packs used are 7.4V and 11.1V. 7.4V packs are usually found on stock AEGs and the 11.1Vs are used for more upgraded higher end AEGs. \n\n\nWe at Zephyr Sports only carry the highest quality NiMH batteries for your absolute satisfaction as well the chargers to go right along with them.", + "answer_03" : "What kind of battery or gun connectors do I have? Which is the best connector? Know what type of connector your AEG has can determine which is the right battery, or the only compatible battery for you. \n\n\nSmall Tamiya Connector - This is the most common battery connector for airsoft guns. It comes in a male and female variety where the male has a latch on the top of the plastic connector. These connectors are typically only slightly larger than the width of a pencil. \n\n\nLarge Tamiya Connector - These connectors are exactly the same as the small Tamiya but are bigger and allow a greater amount of voltage to pass through them. They are usually twice the width of a pencil.\n\n\nDeans Connector - This is considered to be one of the best connectors for airsoft due to their very low resistance. Deans must typically be installed, and have a 'T' shape connector. The male has extended prongs, while the female (found on batteries) has inlets.\n\n\nLipo Charger Connectors - Found on all Lipo batteries, these connectors vary in size and the number of wires based on the number of cells in the battery. This connector should only be used for testing equipment or charging the Lipo battery.\n\n\nSpecial adapters exist that will have two different connectors allowing the use of batteries with dissimilar connectors to the AEG.", + "html_01" : "

                                                                          FAQ (Frequently Asked Questions)

                                                                          \n\n\n\n\n\n\n\n\n\n
                                                                          Battery Types ExplainedBattery Chargers Explained
                                                                          Battery Connectors Explained
                                                                          ", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002", + "question_02" : "Battery Chargers Explained", + "text_01" : "There are many different types of batteries that airsoft players should know about in order to power their Airsoft Electric Guns (AEG). A number of factors come in to consideration when choosing the right airsoft battery for your AEG (Voltage, Milliamps, etc) often times confusing. In this article we will detail the different types of batteries and their uses while helping you gain knowledge so that you can make the right choice in choosing an airsoft battery.\n\n\nTypes of batteries:\n\n\nAlkaline battery- The most commonly used batteries such as Duracell or Energizer brands.\n\n\nLead-acid battery- Often used to power automobiles. These kinds of batteries are rechargeable.\n\n\nLithium-ion battery- Normally found in laptop computers and cell phones due to their good power-to-weight ratio.\n\n\nLithium-photo battery- Used to power cameras due to its ability to supply good power surges.\n\n\nMetal-chloride battery- This type of battery can be mostly found in electric vehicles.\n\n\nNickel-metal hydride battery (NiMH)- These rechargeable batteries are the most common battery found in AEGs. These are fast replacing nickel-cadmium type since they do not suffer from memory effect as nickel-cadmium does.", + "question_01" : "Battery Types Explained", + "answer_02" : "What kind of charger should I use for my airsoft battery? There are a few things to look for when deciding what charger is compatible for your airsoft gun. We will point you in the right direction.\n\n\nSmall Battery Quick Charger - This is a standard wall charger for AEGs with a small type connector. Leaving batteries plugged into these chargers too long may overheat the battery and render it dead.\n\n\nLarge Battery Quick Charger - This is a standard wall charger for AEGs with a large type connector. Leaving batteries plugged into these chargers too long may overheat the battery and render it dead.\n\n\nSmart Charger - These chargers have some great advantages. Unlike a standard battery charger, you can plug in your battery and forget about it. No need to watch it or count the time it charges for. These chargers will prevent overheating of a battery because of an automatic shutoff feature once the battery is fully charged. All smart chargers come with several adaptors to charge a variety of batteries. Some are specially designed to charge only NiMH/NiCad batteries and some for Li-Polymer batteries.\n\n\nLipo Charger - This charger is the only charger that can be used with Lipo batteries. It typically has several different ports to charge different Lipo connectors. The Tamiya plug should never be used to charge a Lipo battery, only the Lipo charging plug. These chargers monitor each individual cell of the Lipo battery so that the unit charges correctly and evenly.", + "question_03" : "Battery Connectors Explained", + "title_01" : "Airsoft Batteries Overview", + "top_description3" : "=Airsoft Batteries=\n\nThere are many different types of batteries that airsoft players should know about in order to power their Airsoft Electric Guns (AEG). A number of factors come in to consideration when choosing the right airsoft battery for your AEG (Voltage, Milliamps, Battery Layout, etc). This can confuse the experienced player as well as the newbie. In this article we will explain the different types of batteries and their uses while helping you gain knowledge so that you can make the right choice in choosing an airsoft battery.\n\n\n=Airsoft Electric Gun (AEG) Batteries Explained=\n\n\nAlkaline - Most alkaline batteries are non-rechargeable and disposable. They are the most common type used for household items but are not seen too much in airsoft. Some alkaline batteries are rechargeable. They have a good capacity but limited rechargability. Rechargeable alkalines get fewer charge cycles in comparison to NiMH rechargeables. \n\n\nNiMH (Nickel-Metal Hydride) - The most common batteries used in AEGs. These batteries have great capacity and will last through many recharge cycles but are often more expensive than alkaline batteries. NiMH batteries come with different capacities ranging from 1050mah to 5000mah. It is always an advantage to get the higher capacity batteries. One downside is that NiMHs quickly self-discharge so they lose power when they are not being used. They will completely lose charge in about 2-3 months so you will want to charge your battery the night before you are going to play. It is best to recharge these batteries after completely discharging them. Overcharging any battery will shorten it's life. We recommend always using a Smart Charger when charging your batteries as these will shut off when your battery if full preventing any damage.\n\n\nNiCad (Nickel- Cadmium) – These batteries have good capacity and long life rechargability. NiCads must be fully discharged before they can be charged again or they will suffer from memory. NiCad battery memory effect will happen if the battery is recharged before it is fully used, it will remember the capacity at which it is recharged, resulting in reduced capacity of the battery. Do not charge a warm battery. Let them cool off before charging so that they can absorb the most amperage. \n\n\n\nLithium Polymer / Nano (LiPo, Li-Poly) - These rechargeable batteries have a great capacity and are less combustible but also very expensive. Overcharging a Li-poly battery can result in explosion and/or fire. These batteries can add a significant amount of power to an airsoft gun and will not harm an AEG as long as the right battery pack is used. Common battery packs used are 7.4V and 11.1V. 7.4V packs are usually found on stock AEGs and the 11.1Vs are used for more upgraded higher end AEGs. \n\n=Airsoft Battery Voltage and current=\nWhen purchasing an airsoft battery, the package will state how much voltage and amperage it contains. Voltage for airsoft guns are typically in the 7.4V to 11.1V range. The current on batteries will range from 1000 Mah to 5000 Mah. Be sure to check your manual to see which batteries are recommended for your Airsoft AEG.\n\n\n=Airsoft Battery Layout=\n\nAirsoft batteries come in a few different standard layouts depending on the Airsoft guns you are using. Below are pictures of the main styles of airsoft batteries including Stick, Nun Chuck, Crane, Small and Large Pack. \n\n=RATBOY INSERT= \n\n\n\n\n\n=Airsoft Battery Chargers=\n\nWhat kind of charger should I use for my airsoft battery? There are a few things to look for when deciding what charger is compatible for your airsoft gun. We will point you in the right direction.\n\nStandard Airsoft Quick Charger - These are basic Airsoft battery chargers. Voltage on these chargers will range from6 to 12 Volts with an output amperage of .7 ah. Charge time is typically 6 to 8 hours. Leaving batteries plugged into these chargers too long may overheat the battery and render it dead. Airsoft Quick Chargers come in two different styles of battery plug, a large and a small. Be sure to check our picture to help deiced which co0nnector you need.\n\n\n=RATBOY INSERT= \n\n\nAirsoft Battery Smart Charger - These chargers have some great advantages. Unlike a standard battery charger, you can plug in your battery and forget about it. No need to watch it or count the time it charges for. These chargers will prevent overheating of a battery because of an automatic shutoff feature once the battery is fully charged. All smart chargers come with several adapters to charge a variety of batteries. Some are specially designed to charge only NiMH/NiCad batteries and some for Li-Polymer batteries. We highly recommend purchasing a smart charger to prolong the life of your batteries.\n", + "return_link" : "/category/buyers_guide.airsoft" + }, + ".shop_by_brand.v-force" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tV-FORCE PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n", + "top_description2" : "=V-Force, Victory vision=\n\nV-force masks are the most comfortable and technically advanced goggles in the paintball industry. VFORCE goggles gives paintball players a VISION FOR VICTORY! These paintball goggles distinguish from competition through unbeatable distortion-free optics, durable lenses with proprietary ThermoCured Anti Fog and Anti Scratch hard coatings, notorious lens' Quick-Change system and ultra-light constrictions with resilient materials. Swap in some new V-force lenses and you'll be playing with clarity in no time. Look at zephyr's large selection of V-force products, and discover a new way to see during your game.\n", + "head_title" : "V-force mask | V force mask | V force lenses", + "description" : "=V-Force, Victory vision=\n\n==V-force armor==\nThe #1 option for Stores who need a well known but cost effective mask to add it to their own gun kits. It also could be sold individually as an entry level Paintball goggle. ARMOR FIELDVISION The #1 answer for budget conscious Game Site Operators; Combining lowest cost, with good lens life and customer satisfaction.\n\n==V-force vantage==\nV-force Vantage, the \"Son of Profiler\", raises your game up to the next level. This is your 1st step-up mask! \n\n==V-force profiler==\nCreated from the fanatic intensity of top international competition, ProfilerTM is the most legendary mask system available today. The dramatic, cool-looking SE (Special Edition) version has been accomplished by simply inverting the colors.\n\n==V-force Grill==\nTight, light and with a mean sleek look, V-force Grill simply is the top of the line mask system. It includes a number of bold innovations such as the revolutionary Quick Dry Foam swap system." + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_myth_sunglasses" : { + "meta_description" : "Arnette Myth Sunglasses - Zephyr Sports carries a complete line of Myth Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Myth Sun Glasses Online Today.", + "page_title" : "Arnette Myth Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Myth Sunglasses | Myth Arnette Sunglasses | Arnette Myth Sun Glasses" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_snowboard_backpacks_and_bags" : {}, + ".airsoft.airsoft_spare_magazines.co2_pistol_magazines" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Pistol Mags | Co2 Airsoft Pistol Mags | Mags for Co2 Airsoft Pistol" + }, + ".goggles.1goggle_accesories.v_force_goggle_accesories" : { + "meta_description" : "V Force Grill Lens - Buy your V Force Profiler Thermal Lens Online at Zephyr Paintball for Less today. Free Shipping on V Force Vantage Replacement Lens Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy V Force Grill Lens Online On Sale Now", + "head_title" : "V Force Grill Lens | V Force Profiler Thermal Lens | V Force Vantage Replacement Lens" + }, + ".casual_clothing.z_shoes_and_footwear.globe_shoes" : {}, + ".apparel.shoes.1_search_by_color.yellow_mens_shoes" : {}, + ".apparel.youth_paintball_clothing" : {}, + ".apparel.head_bands_and_wraps.sandana_headbands_and_wraps" : {}, + ".apparel.jerseys.protojerseys" : { + "meta_keywords" : "Proto Paintball Jerseys, Proto Paintball Jersey, Proto Paint Ball Jerseys, Paintball Jerseys, Proto Paintball, Paint Ball Jerseys, Proto Paintball Equipment, Proto Paintball Supplies, Proto Paintball Accessories", + "meta_description" : "Proto Paintball Jerseys - Get the best prices on Proto paintball jerseys and equipment online at ZephyrPaintbal.com.", + "page_title" : "Proto Paintball Jersey with Free Shipping at Zephyr Paintball", + "head_title" : "Proto Paintball Jerseys - Proto Paintball Jersey - Proto Paint Ball Jerseys", + "page_head" : "" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_compulsive_squared_womens_sunglasses" : { + "meta_keywords" : "Oakley Compulsive Squared Womens Sunglasses,Compulsive Squared Womens oakley sunglasses,oakley Compulsive Squared Womens, Compulsive Squared Womens polarized sunglasses", + "meta_description" : "Oakley Compulsive Squared Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Compulsive Squared Womens and Polarized Oakley Compulsive Squared Womens Sunglasses on Sale! ", + "page_title" : "Oakley Compulsive Squared Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Compulsive Squared Womens Sunglasses | Compulsive Squared Womens Oakley Sunglassses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_beckon_womens_sunglasses" : { + "meta_keywords" : "Oakley Beckon Womens Sunglasses,Beckon Womens oakley sunglasses,oakley Beckon Womens, Beckon Womens polarized sunglasses", + "meta_description" : "Oakley Beckon Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Beckon Womens and Polarized Oakley Beckon Womens Sunglasses on Sale! ", + "page_title" : "Oakley Beckon Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Beckon Womens Sunglasses | Beckon Womens Oakley Sunglassses" + }, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns.tm7" : { + "meta_keywords" : "Battle Tested TM7,bt tm7, tm 7 paintball gun, TM7 Marker, BT Paintball", + "meta_description" : "BT TM7 Paintball Gun - The hottest Tactical Paintball Gun From Empire Battle Tested. Get your Battle Tested TM7 from Zephyr today with Free Shipping. TM 7 Paintball Marker on sale now at Zephyr", + "top_description" : "The BT TM-7 utilizes Mini Technology to inflict maximum force from a marker of minimal size. Don't be fooled by the size of the TM-7's exterior; it can hang with the big boys and is by no means a lightweight. Once you hold this marker and pull the trigger, you won't want to put it down. Its lightweight, yet durable construction is perfect for close quarters or long-range combat. This is the marker that just may have people rethink the way they looked at Mil-Sim paintball markers.", + "banner02_link" : "/3packagespecials.empire_paintball_packages.empire_bt.tm7/", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001", + "description" : "Mounting cool accessories is simple with the BT TM-7 paintball gun. The multiple Picatinny rails will fit optics, sights, lasers, flashlights, or anything needed to improve your experience. The lightweight construction matched with the folding Foregrip and adjustable stock allow for comfortable all-day play. Like the Mini, the TM-7 has no external hoses, giving it a clean look and the authentic feel of the real-world firearm it's based on. No paintball gun has the look and technology to match the TM-7 while in the field. Watch your opponents run when you switch to full auto using the shift-on-the-fly selector lever. Command the battlefield with the TM-7 from BT Paintball Designs.\n\n\n=Features:=\n\n* Mini Technology Inside\n* Shift-On-The-Fly, 4-Position Mode Switch\n* Multiple, Extensive Firing Modes Including Semi/Burst/Full-Auto\n* Multiple Picatinny Rails Allow For Extra Accessories\n* Adjustable, Multi-Position Stock\n* Collapsible/Adjustable Front Grip\n* Low Pressure Operation\n* No External Hoses; Internal Airline Operation\n* Additional Modes: NPPL/PSP/NXL/Millennium\n* Universal Mini-Style Barrel Threads\n", + "htmlvids" : "", + "head_title" : "BT TM7 Paintball Guns | Battle Tested TM7 | TM 7 Paintball Marker", + "page_title" : "Buy BT TM7 Paintball Guns Online On Sale Now" + }, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.etek_grip_panel" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_newton_watches" : { + "meta_keywords" : "Nixon watches,nixon newton watch,nixon watch,nixon analog watch,nixon digital watch,mens watches,mens watch,nixon,", + "meta_description" : "Nixon Watches - Brand New Nixon Newton Watch available now @ Zephyr! Nixon Newton Analog watches & Nixon Newton Digital Watches are available! Select colors are instock and ready to ship out! Pick up your Nixon watch today and never ask for the time again!", + "page_title" : "Nixon Newton Watch", + "head_title" : "Nixon Watches | Nixon Newton Watch | Nixon Watch" + }, + ".airsoft.airsoft_bbs_ammo.echo_1_airsoft_bbs" : { + "meta_description" : "ECHO1 Airsoft BBS - Zephyr stocks a complete selection of high end Echo 1 Airsoft ammo. Spend the extra few bucks for quality Echo 1 Airsoft BBs and save yourself a bunch of headaches down the rod. Zephyr Sports offrers free shipping on Airsoft Gear on orders over $75", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 Echo1 Airsoft Bio BBs | .25 Gram Echo1 Airsoft Pellets | .20 G Echo 1 Biodegradeable Ammo for Airsoft Guns" + }, + ".apparel.shoes.1_search_by_color.grey_mens_shoes" : {}, + ".airsystems.nitrogentanks.dxs_nitrogen_tanks" : {}, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_fixed_power_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Fixed power scope | Power scopes | Scopes power fixed" + }, + ".markerupgrades.grips_and_grip_panels.sly_paintball_grips" : {}, + ".airsystems.nitrogentanks.zephyr_nitrogen_tanks" : { + "meta_keywords" : "zephyr air tanks, zephyr compressed air tanks, zephyr paintball tanks, zephyr brand tanks, carbon fiber zephyr tanks, zephyr sports tanks, zephyr carbon tanks", + "meta_description" : "Zephyr Air Tanks - Buy your Zephyr Compressed Air Tanks Online at Zephyr Paintball for Less today. Free Shipping on Zephyr Paintball Tanks Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Zephyr Air Tanks Online On Sale Now", + "head_title" : "Zephyr Air Tanks | Zephyr Compressed Air Tanks | Zephyr Paintball Tanks" + }, + ".apparel.pants.v-tac_paintball_pants" : { + "page_title" : "", + "head_title" : "Valken Vtac Paintball Pants | Paintball Valken Vtac Pants | Valken Vtac Pants Paintball" + }, + ".markerupgrades.tippmann.tippmann_x7_upgrades.tippmann_x7_factory_repair_parts" : {}, + ".casual_clothing.mens_clothing.tshirts.vans_t_shirts" : { + "meta_keywords" : "Vans T Shirts,Vans shirts,free shipping,Vans TShirt", + "meta_description" : "Vans T Shirts - Zephyr carries a complete line of Vans Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Vans T Shirts at Zephyr", + "head_title" : "Vans T Shirts | Vans Shirts | Vans TShirt" + }, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels.smart_parts_linnear_barrels" : {}, + ".markerupgrades.dye_dam_upgrades_and_accessories.dye_dam_rail_accessories" : {}, + ".maddog.spyder_upgrades" : {}, + ".markers.kingmanspyder.spyder_50_cal_paintball_guns" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.35" : {}, + ".casual_clothing.mens_clothing.beanies.matix_beanies" : { + "meta_keywords" : "Matix beanie,Matix hat,Matix beanies,Matix caps,Matix 686,Matix headwear,Matix cuff visor beanie,Matix beanie hat,Matix visor beanie,Matix visor beanies", + "meta_description" : "Matix Deanie - Surf style with Matix Beanies available now at Zephyr Sports. Get your Matix hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Matix Beanies on Sale at Zephyr Today", + "head_title" : "Matix Beanie | Matix Hat | Matix Beanies" + }, + ".11_linking_give_away" : {}, + ".harnessesbags.backpacks.sly_equipment_backpacks" : { + "meta_description" : "Sly Backpacks - Buy your Sly Pro MercAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Sly Backpacks Now! On Sale & Free Shipping", + "head_title" : "Sly Backpacks | Sly Pro Merc" + }, + ".apparel.paintball_cleats.hk_army_cleats" : { + "top_description" : "The HK Army Shredder Cleats are the first paintball shoes designed for comfort, reliability, style and function. This cleat was developed to give maximum traction while playing on AstroTurf, grass, mud and dirt. There are 8 integrated traction points on the cleat. You'll never have to worry about slamming your face in the mud on your next charge again!" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.zephyr_ladies_t_shirts" : {}, + ".safetygear.slider_shorts" : {}, + ".skateboard_gear.skateboarding_videos" : { + "meta_description" : "Skate Videos - Zephyr Sports carries a complete line of Skateboard Videos At the lowest prices on the web with free shipping and easy returns. Buy your Skate Boarding Videos Online Today.", + "page_title" : "Skate Videos On Sale Free Shipping", + "head_title" : "Skate Videos | Skateboard Videos | Skate Boarding Videos" + }, + ".markerupgrades.smartparts.ion_xe_upgrades.ion_xe_triggers" : {}, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.d_xxx-large" : {}, + ".casual_clothing.mens_clothing.socks.lrg_socks" : { + "meta_description" : "LrG Socks - Buy your LrG Skate Socks At Zephyr Sports for Less Today! We carry a complete line of LrG Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "LrG Mens Socks at Zephyr Sports", + "head_title" : "LrG Socks | LrG Skate Socks | LrG Mens Socks" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.colt_airsoft_guns" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_dial_watches" : {}, + ".airsoft.airsoft_bbs_ammo.30_gram_airsoft_bb_s" : { + "meta_keywords" : ".30 gram bbs, airsoft ammo, metal bbs", + "meta_description" : ".30 Gram Airsoft BBs. Some of the most powerful BBs you will find. Do not use these without wearing proper safety gear as these BBs can pack a lot of power. Intended for use in powerful airsoft guns. These BBs are made from aluminum and it is advised that extra caution be used when firing these rounds. Perfect for use while controlling small animals and target practice.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".30 G Airsoft BB's | .30 BBs for Airsoft | .30 Gram Airsoft BB" + }, + ".markerupgrades.smartparts.shocker.shocker_nxt_feed_necks" : {}, + ".shop_by_brand.nixon" : { + "top_description2" : "=Nixon Watches, built for your lifestyle=\n\nNixon watches is based out of Encinitas, CA and specifically designed for your skate, snow and surf needs. Nixon products are made for the active and relentless lifestyle of the youth and the adventurous. Buy Nixon belts, Nixon watches, or Nixon Clothing online on our shop by brand option, you might be able to score some sweet Nixon Watches on sale! Try Nixon for any of your snowboard, surf or skateboard needs and you will not be dissapointed. Fit your lifestyle with Nixon. \n", + "head_title" : "Nixon Watches On Sale | Nixon Clothing Online | Buy Nixon Belts", + "description" : " =Nixon Watches, suit your lifestyle=\n\n==History==\nNixon was founded by Andy Laats and Chad DiNenna after DiNenna's unsuccessful attempt to find a watch that reflected his surfing lifestyle. Laats was a mechanical engineer with a bachelor's degree from Cornell University who had worked at Burton, a snowboard company in Vermont for six years, and who was getting his MBA from Stanford. DiNenna studied communications at Long Beach State and worked for publishing company Transworld for five years. The two raised nearly $1 million from venture capitalists to start Nixon and in 1997, Nixon's catalog debuted with seven models that were available at 200 retailers. Nixon opened a subsidiary in France in 2000, and by 2005 Nixon had 90 models! \n\n==The watches==\nNixon watches are Iconic. They are so variable in design that they can make sure you get out of the water on time to go to work but make sure you look stylin' when you get there. These watches are based off of quartz and mechanical working systems, and Japanese and Swiss mechanisms. You know you have a quality watch when it's form Nixon,.\n\n==The clothing==\nNixon apparel is the freshest and coolest stuff on the market. You won't ever get looked at funny when you are repping Nixon. Their vast quantities of products can, and will amaze you. Their high quality of production will keep you comforted, and their design will keep you looking cool. " + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_akoni_sunglasses" : { + "meta_description" : "Maui Jim Akoni Sunglasses - Zephyr Sports carries a complete line of Maui Jim Akoni Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Akoni Online Today.", + "page_title" : "Maui Jim Akoni Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Akoni Sunglasses | Maui Jim Akoni Sun Glasses | Sunglasses Maui Jim Akoni" + }, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns" : {}, + ".markers.d3fy" : { + "meta_keywords" : "D3FY Sports, Defy Sports, D3S Marker, DIIIS Marker, D3FY Paintball Gun, D3S Paintball Gun", + "htmlvids" : "", + "meta_description" : "The brand new D3FY D3S offers a superior shot for a lower price point. This gun will outshine all other guns in its price range.", + "top_description" : "D3FY Sports is proud to announce its groundbreaking new marker the D3S. This high performance marker is sure to improve your game and out shine the competition.\n\n\n= Features: =\n* 2 Piece barrel\n* Low profile feedneck\n* On/Off ASA\n* Adjustable firing modes\n* Unique body design\n\nMore information about the D3S will be available soon. Stay tuned here for all of the latest updates.", + "page_title" : "D3FY D3S Paintball Marker", + "head_title" : "D3FY D3S Paintball Marker" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_holbrook_sunglasses" : { + "meta_description" : "Oakley Holbrook Sunglasses - Buy your Holbrook Oakley Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Oakley Holbrook at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Holbrook Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Holbrook Sunglasses | Holbrook Oakley Sunglasses | Oakley Holbrook" + }, + ".goggles.1goggle_accesories.jt_usa_goggle_accesories.jt_lenses" : { + "meta_description" : "JT Goggle Lens - Buy your JT Goggles Online at Zephyr Paintball for Less today. Free Shipping on Lens for JT Mask Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy JT Goggle Lens Online On Sale Now", + "head_title" : "JT Goggle Lens | JT Goggles | Lens for JT Mask" + }, + ".scenarioupgrades.tactical_vests.condor_tactical_vests" : {}, + ".proto_rail_paintball_guns.proto_reflex_rail_paintball_gun" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.firepower_aeg_electric_rifles" : { + "meta_keywords" : "Firepower Airsoft Guns,spring pistols,electronic rifles,Firepower replica airsoft,Spring powered airsoft guns,airsoft guns,c02 blow back guns,airsoft shotguns,cheap airsoft guns,Firepower Spring Airsoft Guns", + "meta_description" : "Firepower Airsoft Guns. Firepower offers a wide range of airsoft guns from spring pistols to electronic rifles. Their affordable prices make them a great choice for anyone looking to get into airsoft, or the budget conscience shopper. Firepower replica airsoft products are great renditions of the real life counter-parts and provide a realist look and feel for any enthusiast. Firepower Airsoft guns range from low impact Spring powered airsoft guns, to c02 blow back guns, to multi-shot airsoft shotguns! For cheap airsoft guns, Choose Firepower!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Firepower Airsoft Guns On Sale & Free Shipping", + "head_title" : "Firepower Airsoft Guns | Firepower replica airsoft | Firepower Spring Airsoft Guns", + "description" : "" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.38" : {}, + ".markers.tippmann.tippmann_packages.tippmann_x_7_packages" : { + "banner1" : "banners/categories/guns/tippmann_package_x7_1.jpg", + "meta_description" : "Tippmann X7 Packages - Buy your Tippmann X7 Sniper Packages Online at Zephyr Paintball for Less today. Free Shipping on Tippman X7 Package Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann X7 Packages Online On Sale Now", + "head_title" : "Tippmann X7 Packages | Tippmann X7 Sniper Packages | Tippman X7 Package", + "description" : "The Tippmann X7 is one of the most durable paintball guns on the market. Throw it, step on it, dunk it in water, cover it in dirt, tie it to the back of your truck and drag it for 4 miles. Actually, don’t do the last one. If you did though, I’d bet it would stay in tact. The durability is not the only thing great about this gun. The X7 is completely customizable. Give it that realistic look and feel with modifications such as the AK47, M16, UMP and others. Zephyr offers these Tippmann X7 Paintball Guns with Packages to get you started in the wonderful world of Paintball.\n\n\n==What’s in the Bronze Package?==\n\n\nThe [[Tippmann X7 Bronze Package]:url=http://www.zephyrpaintball.com/product/3-KIT-X7BRZ/Tippmann_X7__Complete_Bronze_Package.html] offers you the standard Tippmann X7 Paintball Gun with a standard kit mask, 20 oz CO2 tank, gun oil, barrel cleaner & cover. \n\n\n==What’s in the Silver Package?==\n\n\nThe [[Tippmann X7 Silver Package]:url=http://www.zephyrpaintball.com/product/2-KIT-X7SIL/Tippmann_X7_Silver_Package__Black.html] offers you the standard Tippmann X7 Paintball Gun with a standard kit mask, 20 oz CO2 tank, gun oil, barrel cleaner & cover, 4+1 Harness + 4 Free Pods. What’s great about the harness is the luxury of being able to carry multiple pods full of paint so you don’t have to worry about running out on the field. Also, if you decide later down the road to get a [[remote line]:url=http://www.zephyrpaintball.com/category/airsystems.remote_lines/] you can put your tank on your harness and run the remote from your tank to your gun so it takes the weight off your setup. \n\n\n==What’s in the Gold Package?==\n\n\nThe [[Tippmann X7 Gold Package]:url=http://www.zephyrpaintball.com/product/1-KIT-X7GLD/Tippmann_X7_Paintball_Gun_Complete_Gold_Package.html] offers you the standard Tippmann X7 Paintball Gun with a standard kit mask, 20 oz CO2 tank, gun oil, barrel cleaner & cover, 6+1 Harness + 6 Free Pods. Just like the Silver package you get the luxury of carrying more paint well now with this package you get even more Pod Holders plus the slot for your tank and even more pods!\n\n\n==Can I upgrade the gun with my Package?==\n\n\nIn all of our packages we let the customer choose if they want to upgrade the gun with the [[E-grip]:url=http://www.zephyrpaintball.com/product/PB-TIP-X7EGRIP/Tippmann_Paintball_X7_EGrip_Upgrade_Kit.html] or [[Response Trigger]:url=http://www.zephyrpaintball.com/product/PB-TIP-X7RTKIT/Tippmann_X7_Response_Trigger_Kit.html] The X7 E-grip allows the user to shoots up to 20 Balls Per Second and features 5 firing modes including semi-automatic, turbo, 3-shot burst, auto response and full auto. It also features a selector switch that makes it easy to switch modes so there is completely no hassle. Having these options gives you the advantage over other players but also being able to participate in Speed Ball games by having a similar gun to make it fair. The X7 Response Trigger is a rapid air-assisted firing system that can shoot up to 15 BPS without batteries. An easy add-on accessory that is a perfect match for the X7 Cyclone Feed.\n\n\n==What is so great about the Cyclone Hopper?==\n\n\nThe Cyclone Feed System feeds a ball into the chamber every time you fire and does not require batteries. When you fire a Tippmann sometimes you can see excess air shoot out of the barrel or sides of the gun, well the Cyclone operates on this excess air. Air will not go to waste any longer. Since the Tippmann X7 already comes with the Cyclone Hopper it makes this gun even more of a great choice.\n\n\nThe Cyclone feed itself can also be upgraded. Check out the [[Ludicrous Cyclone Upgrade Kit]:url=http://www.zephyrpaintball.com/product/PB-TT-LUDICROUS/TechT_Paintball_Ludicrous_Speed_Cyclone_Upgrade_Kit__Black.html]. This kit turns all plastic parts into an aluminum construction for maximum durability. Not only do you get increased durability but increased air efficiency and speed as well." + }, + ".markers.dye_matrix_paintball_guns.dye_dm11_paintball_guns" : { + "meta_keywords" : "Dye Matrix,DM11 Paintball Gun,Dye Matrix paintball gun,2011 Dye Matrix,Dye DM11,paintball marker,paintball gear,paintball,", + "meta_description" : "2011 Dye Matrix Paintball Guns - The new Dye DM11 continues the tradition of being one of the lightest, smallest, fastest and accurate of paintball markers in the world. Fully loaded, high-end paintball guns, Dye paintball has only improved the DM model with this years DM11! Check out all the specs on the new Dye DM11 Paintball Gun today!", + "top_description" : "The new Dye DM11 continues the tradition of being one of the lightest, smallest, fastest and accurate of paintball markers in the world. Our one-piece Fuse bolt system operates at 145psi with a shorter flow path, resulting in a shorter overall length. The low operating pressure provides smooth operating performance with minimal recoil and sound signature. The 2011 DM Series features a low-maintenance internal patent-pending Eye Pipe anti-chop sensing system that is self cleaning, providing trouble free high rates of fire. Durable and super-flexible detents offer supreme tenderness to the most brittle of paint. The Ultralite Reach Trigger allows the trigger's reach and rake to be fully adjusted by the user for ultimate individual ergonomic comfort. Weighing in at 1.9lbs, the Dye DM11 is lighter than it's predecessor, the DM9. All of these innovations, coupled with new 3D body styling and standard features like the second generation Ultralite frame, tool-less Ultralite Sticky3 grip, two piece 14\" Ultralite barrel, cam lock feed neck, and cast aluminum inset DYE logo, it's easy to see why the 2011 DM Series is \n==\"The Choice of Champions\"==\n", + "page_title" : "Buy Dye 2011 Matrix Paintball Guns Online On Sale Now", + "head_title" : "Dye 2011 Matrix Paintball Guns | Dye Dm11 | DM 11 Paintball Marker", + "description" : "==Dye DM 11 Features:==\n\n\n=ULTRALITE BARREL=\nThe industry standard for accuracy, the 2011 DM Series comes stocked with the Ultralite 14 inch barrel. \n\n\n\n\n=FUSE BOLT WITH BOLT TIP BUMPER=\nThe removable one-piece Fuse bolt system operates at 145psi with a shorter flow path resulting in better efficiency. Large front and rear bumpers used in the Fuse bolt, offer greater reliability and smooth shooting. \n\n\n\n\n=INTERNAL LPR=\nThe miniature modular internal LPR provides more efficient shot consistency. It allows the user to optimize efficiency and reduce kick. \n\n\n\n\n=PRO-PERFORMANCE DETENTS=\nDurable and super-flexible detents offer supreme tenderness to the most brittle of paint. Flex-spring geometry ensures that balls will not double feed into the breech. \n\n\n\n\n=NO EYEPLATES=\nThe 2011 DM Series features a low-maintenance internal patented Eye Pipe anti-chop sensing system that is self cleaning, providing trouble free high rates of fire. \n\n\n\n\n=ULTRALITE=\nWeighing in at 1.9 lbs, the 2011 DM Series is lighter than it's predecessor the DM9. \n\n\n\n\n=COLOR CODED O-RINGS=\nMakes it easier to perform regular, scheduled maintenance of your Fuse Bolt system. \n\n\n\n\n=ULTRALITE REACH TRIGGER=\nTrigger roller bearing inserts give the trigger stability and a smooth swing return. The externally adjustable design allows you to limit the travel of the trigger and spring tension without removing the grip frame or Sticky3 grip. Trigger Reach Adjustment is a first in the painbtall industry, which allows the user to fully customize the trigger for ultimate shooting capability. \n\n\n\n\n=2ND GEN ULTRALITE GRIP FRAME=\nThe newest revision of the now famous UL frame offers an improved trigger adjustment system, redesigned battery mounting location, new button cover, and new control button housing system, with heads-up display light alerts you to the status of your gun, without having to take your eyes off the game. \n\n\n\n\n=LED CONTROL=\nHigh intensity LED provides identification to program functions. The 2011 DM Series features our unique heads-up display light which alerts you to the status of your gun, while still being able to focus on the game. \n\n\n\n\n=METAL POWER BUTTONS=\nOur metal/rubber button pad features large buttons that can easily be used while wearing gloves. Stainless steel buttons are guaranteed not to fail. \n\n\n\n\n=HYPER3=\nThe Hyper3 regulator sports a streamlined diameter with unmatched flow and consistency, while maintaining precise adjustments. The Hyper3 also features an ergonomic Sticky Grip Sleeve providing a more comfortable, textured foregrip. \n\n\n\n\n=CAM LOCK FEED NECK=\nLow profile locking feed port with adjustable cam lock neck allows you to use your choice of hopper and secure it firmly to the 2011 DM Series without the use of tools. \n\n\n\n\n=LOW PRESSURE=\nThe low 145 psi operating pressure provides smooth operating performance with minimal shot bounce and noise. \n\n\n\n\n=TOOL-LESS ULTRALITE STICKY3=\nThe full wrap around NT Sticky Grip allows you to easily access the battery and circuit board for programming with no tools. We have also added a front rubber contact pad and rear rubber contact grip, for maximum comfort and stability. \n\n\n\n\n=LEGAL SOFTWARE=\nComes with multiple programming modes including PSP and Millennium tournament legal software, and 40 ROF settings " + }, + ".goggles.hk_army_paintball_masks" : { + "meta_keywords" : "hk army,klr,killer,paintball,mask,goggle,pro,hkarmy,masks,goggles,thermal", + "meta_description" : "The HK Army KLR Mask has arrived at ZephyrPaintball.com. All KLR Goggles ship free . The KLR Includes a thermal lens with plenty of upgrade options available, straps, mirror and colored lenses and much more.", + "top_description2" : "", + "top_description" : "== A very limited amount of Black HK KLR masks have been released and are here, READY TO SHIP! ==\n\n= The rest of the HK Army KLR Paintball Masks and Accessories are available for Pre-Order ONLY. We expect to begin shipping in June. Payment will be processed at time of purchase and will reserve your mask for our first shipment. =", + "zoovy:banner01" : "banners/paintball/headers/hk_army_klr_goggles_header.jpg", + "description" : "== HK Army KLR Paintball Mask ==\n\nWith over 100 years in combined paintball experience, the HK design team has created a Goggle System that is both Safe and Stylish! Composed of a robust blend of thermoplastic elastomer, the design of the KLR facemask protects critical areas of the user, while still promoting supreme breathability and freedom of movement. Featuring three co-molded HDPE inserts, the KLR goggle system can be customized to fit any customer's aesthetic desires.\n\n\n= Features: =\n* Supreme Breathability\n* Pivot Lock System\n* 3D Memory Foam\n* Ear Piece Protection\n* Custom Straps\n* KLR PURE Lens System\n\n= PVT Lock System =\n\nThe HK Army KLR Goggle is the first to incorporate a lens retention system that is innovative, safe, and interchangeable. The patent-pending PVT Lock system allows the user to change lenses in mere seconds--the days of gouging your mask and lens with a screwdriver before a game is over. Featuring a large, swiveling hinge system, the PVT Lock system enables users to quickly change their lens and overall appearance of their goggle with the flick of a buckle. Offered in a variety of colors and finishes, users can collect and interchange each side of their PVT Lock to create a look that is unique to them.\n\n\n= 3D Memory Foam =\n\nBonded to the KLR frame is HK's new 3D foam--featuring tri-layer, variable density foam technology that creates unparalleled comfort. The base layer is high-density SBR memory foam that absorbs face impacts and braces against the goggle frame, followed by open-cell EVA foam that is ultra-soft and conforms to the facial profile of the wearer. These high-tech foams are then laminated in a velvet microfiber liner that both absorbs sweat from the face and insulates against heat entering the ocular cavity of the frame. \n\n\n\n= Ear Piece Protection =\n\nThe KLR Goggle offers a super high-density compressed EVA foam earpiece that is protective and low-profile. The KLR soft-ear protects the outer and inner ear from impact and abrasion, while maintaining a low profile.\n\n\n= Custom Straps =\n\nFeaturing a high-resolution microstitched jacquard strap, the KLR is an industry-first in offering microinjected TPR accent patches for users to further customize their on-field look. Coated with anti-slip silicone on the rear of the strap, the KLR strap is guaranteed against fraying and distortion.\n\n\n= Lens Options =\n\nThe KLR PURE Lens System is composed of virgin optical-grade GE polycarbonate--inherently UVA \\ UVB and IR shielded, every KLR lens shields your eyes from dangerous sunlight in every playing condition. The interior thermal lens is applied with 3M Foam Sealant, trapping a layer of cool barrier of insulating air, eliminating condensation and encouraging evaporative cooling.", + "htmlvids" : "", + "head_title" : "HK Army KLR Mask | KLR Paintball Goggles", + "page_title" : "HK Army KLR Paintball Masks" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.camelbak_agent_hydration_packs" : {}, + ".1newitems.2008_products.2008_custom_products" : {}, + ".airsoft.airsoft_batteries___chargers.airsoft_battery_chargers" : { + "meta_keywords" : "airsoft battery, airsoft batteries, rechargeable batteries, reachargeable airsoft batteries, AEG airsoft betteries", + "meta_description" : "Airsoft battery chargers for your AEG. We carry a full line of battery chargers for your Airsoft Gun. For best result, choose one of our smart chargers to prevent battery damage. Be sure to check the adapter size on your airsoft battery before purchasing", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Battery Chargers | Airsoft smart Chargers | Lipo 8.4v Battery Chargers" + }, + ".2clearance.paintball_clearance_gear.clearance_upgrades.clearance_grips" : {}, + ".scenarioupgrades.tactical_vests.genx_tactical_vests" : {}, + ".airsoft.green_gas___co2" : { + "meta_keywords" : "co2 cartridges,green gas,12 gram co2 cartridges,airsoft green gas,co2 cartridge,c02 cartridges", + "meta_description" : "12 Gram Co2 Cartridges - Green Gas - Zephyr Sports has all your Airsoft needs! 12 Gram C02 cartridges in bulk! Airsoft Green Gas by the bottle! Reload and Go with these airsoft propellants! ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "12 Gram Co2 Cartridges On Sale & Free Shipping", + "head_title" : "12 Gram Co2 Cartridges | Green Gas | Airsoft ", + "prodlist1_header" : "Airsoft Gas and Accessories", + "description" : "" + }, + ".3packagespecials.tippmann_packages.tippmann_gryphon_paintball_gun_packages" : { + "head_title" : "Tippmann Gryphon Paintball Packages | Tippmann Gryphon Paintball Gun Packages" + }, + ".buyers_guide.airsoft.airsoft_bbs" : { + "question_05" : "What if my gun is inaccurate?", + "answer_03" : "No. It is not recommended to reuse any BBs you have already fired out of your gun or that have been left out in the elements. Reusing BBs may cause them to break the second time they are shot or they might get dirt inside your gun which can cause further damage to your gun. It would be much more cost effective in the long run to buy new BBs after you have used the ones you already have. Leaving BBs out in the elements may misshape the BBs, especially biodegradable BBs.", + "html_01" : "

                                                                          FAQ (Frequently Asked Questions)

                                                                          \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                          What different kinds of BBs are there?What kind of BBs should I use for my gun?
                                                                          Can I reuse my BBs?What if my gun jams?
                                                                          Will Biodegradeable BBs degrade or shatter?What if my gun is inaccurate?
                                                                          ", + "answer_05" : "This is usually the result of using low quality BBs. Low quality BBs can have air bubbles, seams, an inconsistent finish, all leading up to turbulence as the BB flies through the air. Buying double polished or heavier BBs can usually solve this problem. If the inaccuracy persists compared with stock results, it's time to clean the barrel or consult and Airsoft Technician for assistance. In creasing the weight of the BBs used, the length of the barrel, and adjusting the cylinder to the right compression ration can all raise accuracy. ", + "question_02" : "What kind of BBs should I use for my gun?", + "answer_04" : "STOP SHOOTING! Continuing to pull the trigger will allow more BBs to enter the chamber. If the chamber and inner barrel are jammed full of BBs, they are blocking the air needed to retract the piston and propel the BB forward. With the stopped piston, the gears will continue to spin and strip the teeth on the piston as well as the gears. When a BB gets stuck in the barrel, the following BBs could have struck the first BB and shattered into small pieces. Those small broken pieces can manage to travel back into the gearbox causing catastrophic damage to your gun. Exercise caution when working on an airsoft gun. NEVER look down the barrel.", + "answer_02" : "Spring operated pistols should use .12 gram BBs only as they have less power and need a lighter BB in order to shoot correctly. Spring operated rifles should use .20 gram BBs. CO2 and gas-powered guns should use .20 gram BBs or heavier. Using .12 gram BBs in a gas or co2 powered airsoft gun may cause the BBs to break in the gun and/or damage the internals of the gun. When you purchase an airsoft gun, often times it will have 100 or so BBs included. Although they are included with the gun, they are usually very low quality and can damage your brand new airsoft gun. Use of these BBs is most likely not covered under warranty. Using properly sized BBs is an extremely important factor. Besides possibilities of jamming, it will affect velocity. When using a BB of the correct diameter, it ensures that most of the air remains behind the BB and that the BB will not bounce around the barrel. Using poorly sized BBs will cause a loss of velocity. This allows air to travel around and past the BB which will in turn cause the BB to be very inaccurate.", + "question_03" : "Can I reuse my BBs?", + "answer_06" : "When Bio BBs first came out, they were made of brittle material and could shatter in the airsoft gun such that shrapnel would be fired instead of BBs. Manufactures have since then used better materials that are both durable and eco friendly eliminating this problem. Bio BBs will degrade over time and 'out gas'. This out gassing is not harmful and produces a musty sent. So long as the BBs are kept in a dry dark place, the BBs can last for a very long time. Even leaving the Bios out in the sun, or temporarily submerging them will not cause them to immediately dissolve or harm your airsoft gun.", + "question_06" : "Will Biodegradeable BBs degrade or shatter?", + "question_04" : "What if my gun jams?", + "return_link" : "/category/buyers_guide.airsoft/", + "answer_01" : "All airsoft guns use 6mm BBs. The differences are separated by the weight of the BB: .12 gram, .20 gram, .25 gram etc. There are also biodegradable BBs which some people prefer but they still are separated by weight. There are also high quality and low quality BBs. Low quality BBs are generally the .12 gram BBs. Brightly colored BBs are a very good indicator of low weight, and often low-quality BBs. Low quality BBs are identified as being misshaped, having imperfections on them including cracks or excess plastic left over on them. Also, transparent BBs and BBs with air bubbles are low quality as well. The air bubbles cause the weight of the BB to be distributed unevenly therefore causing them to be less accurate. Use of such low-grade BBs can cause a jam, get stuck in the barrel, or break into pieces in the barrel. They can also decrease the velocity of your gun. High quality BBs will be perfectly spherical, sized correctly, weight at least .20 grams, have no imperfections and will not have air bubbles in them.", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002", + "question_01" : "What different kinds of BBs are there?", + "text_01" : "BBs are an important and inexpensive investment to your airsoft gun. Various sizes and brands of BBs will affect the performance and functionality of your airsoft gun. Keep in mind that buying low cost BBs such as ones you may find at your local discount stores may not only damage your gun, but will end up costly due to expensive repairs to your airsoft gunor causing jams. They are so cheap because they are meant to be used in low quality airsoft guns. If you happen to run into these types of bbs, notice that their size, shape and weight are not equivalent. Many have bubbles inside them and sometimes are not even be spherical.", + "title_01" : "Airsoft BBs" + }, + ".shop_by_brand.spyder" : { + "top_html" : "\n\n \n \n\n
                                                                          \n
                                                                          \n\tGuns\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tPackages\n\t\n
                                                                          \n
                                                                          \n\tOther Gear\n\t
                                                                          \n
                                                                          ", + "top_description2" : "==Spyder, Play to perform.==\n\nSpyder paintball is perhaps one of the best paintball companies to start with. With their wide selection of inexpensive but quality oriented guns, Spyder paintball has your back. Just take a look at the numerous selection of Guns Zephyr has ranging form the Spyder Mr2 to the Electra, Spyder has something for everyone. ", + "head_title" : "Spyder | Spyder Paintball | Spyder mr2", + "description" : "==Spyder, Play to perform==\n\n==Roots==\nSpyder paintball guns were the first to be mass produced that were both affordable and durable. Their initial success began in the late 1990s with the Spyder Compact series. The Spyder Compact was feature rich compared to its predecessors. As the years have passed Spyder paintball technology has advanced rapidly giving today’s paintballer a variety of exciting choices.\n\n==Kingman Spyder MR1 Silver Package==\n\nThe Spyder MR1 will take a beating and keep on firing! The slide out pull pin, field strippable bolt, and full-length stock (included) make the MR1 an easily operated and highly accurate scenario marker with military resilience and stability.\n\nThis semi-auto marker won't rust even when you're trekking through the wettest terrain, and you can play hard knowing you have a marker that will withstand anything you throw its way!\n\nFeatures:\n\n* Military Style Semi-Auto Paintball Marker\n* All Aluminum Constructed Body\n* Ergonomically Designed Aluminum Trigger Frame\n* Aluminum Magazine Style Fore-Grip\n* Standard Picatinny Rail (for Mounting Scopes or Sights)\n* Removable Composite Shoulder Stock\n* Durable Matte Anodized Finish\n* No-Slip Rubber Grip Panels\n* Quick Strip Delrin Bolt\n* 12\" Muzzle Break Barrel\n* Off-Set Feed Neck\n* Two Finger Trigger\n* Angled Bottomline with Drop Forward\n* Operates on CO2 or Compressed Air\n\n==Spyder Electra==\n\nNo one will question your gun choice with this Gun. The Spyder Electra is an all new, all powerful and all around awesome gun. Try It today and you will see why this thing is dominating all the competition. \n==\nPerformance Features==\n* All New Clamping Collar Feedneck\n* LEAP™ Circuit Board with Rear Facing Color Access Mode Display (CAMD) Developed by Tadao® Technologies\n* Aluminum Eye Covers\n* Fast Charge Inline Regulator\n* Vented Pressure Relief On/Off CA Adapter\n* 12” Two Piece Micro Ported Barrel\n* “Synergy Engineering” Low Pressure Dual Air Source System\n* 3 Modes of Operation (Semi-Auto, Ramp PSP, & Ramp Millennium)\n* Reduced Overall Profile (25% Lighter and 15% Shorter)\n* Up to 25 BPS Rate of Fire\n* Steel Braided Hose Line\n* Quick Release Delrin Bolt\n* 3-Way Adjustable Magnetic Response “Saber” Trigger\n* All Aluminum Constructed Body\n* Recessed Dual Texture Grip Panels\n* All Aluminum Trigger Frame with Integrated Dove Tail\n* Standard CA Thread Vertical Adapter\n* Compatible with a Spyder 9.6v Rechargeable Battery or a Premium 9v Alkaline Battery\n* External Velocity Adjuster\n* 300 PSI Operational Pressure\n* Operates on CO2 or Compressed Air\n" + }, + ".001a_zephyr_paintball_sports_promotions_deals_sales.proto_goggles___free_game_timer" : { + "prodlist2_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=LIST%3A%24leaveempty&ALTERNATE=0&SHOWSKU=&SHOWQUANTITY=0&", + "prodlist1_header" : "Free Proto Game Timer with Purchase of These Proto Goggles", + "zoovy:banner01" : "banners/categories/prot_axis_timer_002.jpg", + "prodlist_custom" : "&SORTBY=PRICE_DESC&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".apparel.shoes.1search_by_size.n_men_s_size_12_shoes" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_womens_backpacks_and_bags.dakine_prom_girls_backpacks" : {}, + ".casual_clothing.mens_clothing.beanies.dakine_beanies" : { + "meta_keywords" : "dakine beanie,dakine hat,dakine beanies,dakine caps,dakine 686,dakine headwear,dakine cuff visor beanie,dakine beanie hat,dakine visor beanie,dakine visor beanies", + "meta_description" : "Dakine Deanie - Surf style with Dakine Beanies available now at Zephyr Sports. Get your Dakine hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Dakine Beanies on Sale at Zephyr Today", + "head_title" : "Dakine Beanie | Dakine Hat | Dakine Beanies" + }, + ".goggles.1goggle_accesories.vents_goggle_accesories" : { + "meta_description" : "Empire Lens - Buy your Empire Thermal Lens Online at Zephyr Paintball for Less today. Free Shipping on Empire Replacement Lens Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire Lens Online On Sale Now", + "head_title" : "Empire Lens | Empire Thermal Lens | Empire Replacement Lens" + }, + ".apparel.jerseys.511_tactical" : {}, + ".airsoft.tactical_airsoft_gear.tactical_gloves.voodoo_tactical_gloves" : { + "meta_keywords" : "voodoo tactical gloves,voodoo liberator gloves,voodoo tactical crossfire gloves", + "meta_description" : "Voodoo Tactical Gloves - Zephyr carries a complete line of Gloves from Voodoo Tatcial including the crossfire and liberator shooters gloves. Fast free shipping and great customer service. Zephyr has all your airsoft needs", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Voodoo Tactical Gloves at Zephyr", + "head_title" : "Voodoo Tactical Gloves" + }, + ".skateboard_gear.skateboard_wheels.darkstar_skateboard_wheels" : { + "meta_description" : "Darkstar Wheels - Zephyr Sports carries a complete line of Darkstar Skate Wheels At the lowest prices on the web with free shipping and easy returns. Buy your Darkstar Wheels Skateboard Wheels Online Today.", + "page_title" : "Darkstar Wheels On Sale Free Shipping", + "head_title" : "Darkstar Wheels | Darkstar Skate Wheels | Darkstar Wheels Skateboard Wheels" + }, + ".markers.kingmanspyder.spyder_sonix_paintball_guns" : { + "top_description" : "The Spyder Sonix is a .68cal semi automatic paintball gun so one trigger pull will get one shot. The latest Spyder Sonix includes an aluminum clamping feedneck to keep your loader secure. The body on the sonix is all aluminum with a high impact polymer grip frame which includes a double trigger. The vertical front grip on the spyder sonix provides increased gun control in the heat of the battle. The barrel on the spyder sonix is a 9\" spyder threaded barrel. The sonix is compatible with co2 or compressed air.", + "banner02_link" : "http://www.zephyrpaintball.com/category/3packagespecials.kingman_spyder_paintball_packages.spyder_sonix_paintball_gun_packages/", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001" + }, + ".harnessesbags.backpacks" : { + "meta_keywords" : "backpacks,duffel bags,backpack bags,school backpacks,hiking backpacks,day backpack,oakley,OGIO Dakine,laptop backpack,camelbak", + "meta_description" : "Backpacks by top bags manufacturers! OGIO, Element,Dakine, Camelbak, Oakley and more backpacks and duffel bags available! Hiking backpacks, travel backpacks, day backpacks, school backpacks with Free Shipping over $50!", + "page_title" : "Bags - Backpacks - Backpacks Duffel Bags Free Shipping", + "head_title" : "Bags | Backpacks | Duffel Bags | Duffle" + }, + ".see_newsletter_online" : { + "top_description" : "\n\n\n\n\n\n\n
                                                                          \n\n\n\n
                                                                          \n\n
                                                                          If you are having trouble viewing this email or would like to view our newsletter as a webpage, click here.\n
                                                                          \n\n
                                                                          \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                          \n\"\"\n\"\"\n\"\"
                                                                          \"\"\n\"\"\n\"\"\n\"\"\n\"\"\n\"\"
                                                                          \n\"\"
                                                                          \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"
                                                                          \n\n
                                                                          \n\n
                                                                          \n\n
                                                                          \"Memorial\n
                                                                          \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                          \n \n\n\n \n\n \n \n\n \n \n
                                                                          \n\"Planet\n
                                                                          \n\n
                                                                          \n
                                                                          Zephyr Low Price: $1,394.95
                                                                          \n
                                                                          \n
                                                                          \n \n\n\n \n\n \n \n\n \n \n
                                                                          \n\"Angel\n
                                                                          \n\n
                                                                          \n
                                                                          Zephyr Low Price: $59.95
                                                                          \n
                                                                          \n
                                                                          \n \n\n\n \n\n \n \n\n \n \n
                                                                          \n\"Zephyr\n
                                                                          \n\n
                                                                          \n
                                                                          Zephyr Low Price: $29.95
                                                                          \n
                                                                          \n
                                                                          \n \n\n\n \n\n \n \n\n \n \n
                                                                          \n\"Ninja\n
                                                                          \n\n
                                                                          \n
                                                                          Zephyr Low Price: $194.95
                                                                          \n
                                                                          \n
                                                                          \n \n\n\n \n\n \n \n\n \n \n
                                                                          \n\"Condor\n
                                                                          \n\n
                                                                          \n
                                                                          Zephyr Low Price: $10.95
                                                                          \n
                                                                          \n
                                                                          \n \n\n\n \n\n \n \n\n \n \n
                                                                          \n\"Planet\n
                                                                          \n\n
                                                                          \n
                                                                          Zephyr Low Price: $1,394.95
                                                                          \n
                                                                          \n
                                                                          \n\n\"\"\n\"\"\n
                                                                          \n
                                                                          \n
                                                                          \n\n\n
                                                                          \n
                                                                          \n\n\n\n\n\n\n\n\n
                                                                          Zephyr Sports
                                                                          877-814-4297
                                                                          \n2970 Seaborg Ave.
                                                                          \nVentura, Ca 93003
                                                                          \n
                                                                          \nThis email was sent on behalf of Zephyr Sports.
                                                                          \nTo stop future mailings please Unsubscribe.
                                                                          \nYour privacy is important, please read our privacy policy.\n
                                                                          This email was sent by Zoovy.com on behalf of Zephyr Sports.\n\"\"\n\n
                                                                          \n\n
                                                                          " + }, + ".casual_clothing.womens_clothing.ladies_beanies" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.firepower_airsoft_guns" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_snowmad_30_backpacks" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_psycho_sunglasses" : { + "meta_description" : "Arnette Psycho Sunglasses - Zephyr Sports carries a complete line of Psycho Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Psycho Sun Glasses Online Today.", + "page_title" : "Arnette Psycho Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Psycho Sunglasses | Psycho Arnette Sunglasses | Arnette Psycho Sun Glasses" + }, + ".markerupgrades.proto_matrix_upgrades.proto_matrix_feed_necks" : {}, + ".casual_clothing.womens_clothing.ladies_shirts.nixon_ladies_shirts" : {}, + ".casual_clothing.youth_clothing.youth_sweatshirts.element_sweatshirts" : {}, + ".casual_clothing.mens_clothing.tshirts.almost_t_shirts" : { + "meta_description" : "Almost T Shirts - Buy your Almost Tshirts At Zephyr Sports for Less Today! We carry a complete line of Almost Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Almost T Shirts @ Zephyr Sports", + "head_title" : "Almost T Shirts | Almost Tshirts | Almost Shirts" + }, + ".casual_clothing.mens_clothing.shirts.1_search_by_size.2_medium" : {}, + ".3packagespecials.alien_paintball_gun_packages" : { + "meta_keywords" : "alien paintball, alien paintball guns, alien paintball markers, alien tournament paintball guns, alien tournament paintball markers, invasion paintball guns, alien invasion paintball guns, alien invasion paintball markers, invasion paintball guns, invasion paintball markers, paintball packages, paintball starter kit, paintball geat", + "meta_description" : "Alien Paintball - Zephyr Sports is now stocking Alien Paintball guns. These tournament paintball guns offer superior performance priced competitively against other high-level markers. With these Alien Paintball packages, you will have everything you need to start playing like a pro.", + "top_description2" : "==Alien Paintball Gun Packages==\nAlien guns are among the lightest of the full size guns, with a solid feel, comfortable grip frame, excellent balance and easy handling. Alien triggers are fast and smooth. Alien Markers have a solid feel with walls that are visibly thicker than guns of similar weight. Because the guns are modular, each piece can be minimized for a lightweight but full strength design. The low pressure regulator of Alien Paintball guns provides a quieter, calmer, and more accurate shot. Every Alien gun is exceptionally calm and very fast. They are smooth, light, and accurate, and the quality of manufacturing and use of the best parts is evident throughout each marker.", + "page_title" : "Buy Alien Paintball Gun Packages On Sale & Free Shipping", + "head_title" : "Alien Paintball | Alien Paintball Guns | Tournament Paintball Guns", + "description" : "Alien Paintball is a well respected name in tournament level play. Their guns offer some of the best performance for the price, and are notorious for wiping out the competition. In the heat of a firefight, you need a gun that can out-preform your opponents, and that is what you get with Alien Paintball guns. They are lightweight, calm, and accurate, so while your opponent is losing his cool trying to fill up his hopper, you can spray him with paint and take your team to the podium.", + "zoovy:banner02" : "banners/paintball/headers/alien_banner" + }, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories.molle_medical_pouches" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.shoes.vans_shoes" : { + "meta_description" : "Vans Shoes - Buy your Vans Mens Shoes Online At Zephyr Sports for Less Today! We carry a complete line of Vans Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Vans Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Vans Shoes | Vans Mens Shoes | Vans Skate Shoes" + }, + ".airsoft.airsoft_safety.airsoft_goggles.revision_military_goggles" : { + "head_title" : "Revision Miltary Goggles | Revision Airsoft Goggles | Revision Goggles" + }, + ".casual_clothing.mens_clothing.sweatshirts.spitfire_sweatshirts" : { + "meta_description" : "Spitfire Sweatshirts - Buy your Spitfire Hoodies At Zephyr Sports for Less Today! We carry a complete line of Spitfire Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Spitfire Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Spitfire Sweatshirts | Spitfire Hoodies | Spitfire Hoody" + }, + ".casual_clothing.mens_clothing.hats.young_and_reckless_hats" : { + "meta_keywords" : "Zero Hats,Zero caps,Zero baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Zero Hats - Zephyr carries a complete line of Zero Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Zero", + "page_title" : "Zero Hats on Sale at Zephyr" + }, + ".apparel.jerseys.dyejerseys.dye_c11_paintball_jerseys" : { + "meta_keywords" : "Paintball Gear,Dye Paintball Jersey,Dye Paintball C11 Jersey,Paintball Dye C11 Jersey,Dye Paintball,Paintball Jersey,Dye,Dye C11 Jersey,Dye Jersey,Dye Paintball gear,2011 Dye paintball jersey,", + "meta_description" : "Dye C11 Paintball Jersey - Brand New Dye Paintball Gear for the 2011 Season! New designs and colors for each C11 Dye Paintball jersey released. Check out the new specs on C11 Dye Paintball gear!", + "top_description" : "The latest and greatest from Dye Paintball is showcased in their C11 line of paintball jerseys! Each jersey is constructed with a significant amount of vented material to keep you cool under fire while reducing weight. The C11 jersey features thumb slots that prevent your sleeves from sliding up and introduces compression formed, open cell foam shoulder pads, the first of its kind. These pads conform to the body, providing a more comfortable fit and better protection. The C11 jersey also features a re-designed comfort fit v-neck collar and of course patented DyeTack. Combined features and extreme comfort makes Dye Paintball's C11 jersey their most advanced yet! Check out the new colors and designs below!", + "page_title" : "Dye C11 Paintball Jersey | Brand New 2011 Dye Paintball Gear Available Now!", + "head_title" : "Dye C11 Paintball Jersey - Dye Paintball Gear - 2011 Dye Paintball Jersey", + "description" : "==Check out the Brand New Specs on Dye Paintball's C11 Line of Paintball Jerseys!==\n\n\n=DYETACK=\nPatented DyeTack technology is a direct injection process that bonds to the material of the jersey. DyeTack is a durable polymer creating a friction point that stabilizes marker position. We invented DyeTack in 2002, since then we have perfected the level, position and density of DyeTack to ensure optimal tank stability. Everyone else has tried to imitate this patented process. If it's not DyeTack, it's not real.\n\n=3D CONTOUR PADDING=\nWe have redefined the level of protection once again. Compression formed, open cell foam shoulder pads. These molded pads are contoured to the shape of the shoulders, and extend across the chest, maximizing coverage. These new pads are always in the proper position. No matter how you move, the pads move with you.\n\n=RESPONSIVE AIR FOAM=\nThe chest panel of the new C11 jersey has been designed with our unique compression formed responsive air foam for maximum comfort and protection. This new compression formed padding offers you critical protection without hindering performance or range of motion.\n\n=EXTREME VENTING=\nFor 2011, we've introduced our new Hyper Venting. This new material is particularly special. It offers a tremendous amount of airflow over previous vented materials, while still providing complete coverage helping to prevent debris from getting inside. The venting placement also helps to channel heat away from the body. In addition, the C11 jersey has a significant amount of vented material. It's featured on the entire sleeve, lower back, outside torso, and shoulder segments. This exceptional airflow combined with light weight breathability delivers a jersey that is true performance.\n\n=GLOVE CUFFS=\nThe cuffs on the C11 Jersey have been designed to provide greater flexibility to the wrist and hand, offering freedom of rotation. The unique underside of the cuff design extends to the center of the hand, providing protection to the base of your palm. The thumb-hole in the cuff secures the sleeve in place with or without gloves.\n\n=COMFORT V-NECK COLLAR=\nThe lightweight v-neck collar features an anatomical correct fit while providing pure comfort. The C11 v-neck is designed with a light-weight stretch nylon construction. The contoured panel assembly ensures that the jersey moves with you. The collar is secured with reinforced stitching, and the neckline is double layered for added comfort.\n\n=NO FADE SUBLIMATION=\nOur graphics are sublimated for a no fade style. This process ensures that the graphics stay crisp and clean.\n\n=PADDED ELBOWS=\nThe protective material used for the elbow padding is lighter in weight, resulting in more flexibility and an overall reduced weight of the jersey. The pads begin at the wrist and extend well past the elbows, providing ultimate arm protection. Today's game is more intense than ever, requiring fast moves and aggressive slides. By reducing injuries, you can stay more focused on winning." + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_fixed_power_scopes.nikon_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".paintball.player_apparel.paintball_jerseys.empire_paintball_jerseys" : {}, + ".2clearance.paintball_clearance_gear.like_new_refurbished_guns" : {}, + ".casual_clothing.mens_clothing.socks.spitfire_socks" : { + "meta_description" : "Spitfire Socks - Buy your Spitfire Skate Socks At Zephyr Sports for Less Today! We carry a complete line of Spitfire Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Spitfire Mens Socks at Zephyr Sports", + "head_title" : "Spitfire Socks | Spitfire Skate Socks | Spitfire Mens Socks" + }, + ".markerupgrades.smartparts.shocker.shocker_nxt_triggers" : {}, + ".black_friday_paintball_and_airsoft_deals.co2_and_air_tanks" : {}, + ".harnessesbags.backpacks.girl_backpacks" : {}, + ".airsoft.airsoft_bbs_ammo.mad_bull_airsoft_bbs" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 Madbull Airsoft Bio BBs | .25 Gram Madbull Airsoft Pellets | .20 G Mad Bull Biodegradeable Ammo" + }, + ".paintballs.kingman_training_paintballs" : {}, + ".paintball.paintball_guns" : {}, + ".casual_clothing.mens_clothing.sweatshirts.eclipse_sweatshirts" : { + "meta_description" : "Planet Eclipse Sweatshirts - Buy your Eclipse Paintball Sweatshirt At Zephyr Sports for Less Today! We carry a complete line of Eclipse Sweatshirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Planet Eclipse Sweatshirts On Sale & Free Shipping", + "head_title" : "Planet Eclipse Sweatshirts | Eclipse Paintball Sweatshirt | Eclipse Sweatshirts" + }, + ".2clearance.airsoft.accessories" : {}, + ".markers.azodin" : { + "meta_keywords" : "azodin paintball guns, azodin paintball markers, azodin chaos pump, pump paintball gun, azodin zenith, zpyder azodin, azodin blitz,painball", + "meta_description" : "Azodin Paintball Guns - Zephyr is your one stop shop for Azodin Paintball Markers. We stock the complete line of gear from Azodin including the hot new Chaos Pump. We offer free shipping on orders over $99.", + "banner02_link" : "/category/3packagespecials.azodin_paintball_packages/", + "zoovy:banner01" : "banners/paintball/headers/azodin_newsletter", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001", + "description" : "=Azodin Blitz Paintball Marker=\n\nA Valve is the heart of every marker. The Board is the soul of every electronic marker. Azodin's second generation Blitz is designed with a new Heart and Soul!\n\n\nThe new High Performance (HP) Valve design offers a new level of air efficiency, accuracy and overall performance.\n\n\nThe \"Zen II\" Circuit Board has improved logistics and extends the life of most batteries you can find in the market today. Programmed with firing modes for the major circuits the \"Zen II\" Circuit Board can easily be modified with out AZ Editor to suit your likings.\n\n\nInnovative \"Twist Lock II\" has been added for increased convenience and locks you loader tighter than ever before.\n\n\nCheck out the New Features and Color Finish on the 2011 Azodin Blitz! \n\n\n\n=Azodin Kaos Paintball Marker=\n\nDeveloped with the highest standard in mind, KAOS incorporates the latest technological breakthrough, while providing standard features that are on $1000 markers. KAOS gives players the competitive edge on the field of battle.\n\n\nThe new \"Feather Striker System\" is 30% lighter than the traditional striker design. This breakthrough reduces the mechanical recoil and allows the KAOS to be smoothest handling semi-auto marker on the market.\n\n\nOverall length and the profile of the receiver body have been re-engineered to be shorter and lower. This compact design makes the KAOS one of the lightest markers at 2.1 lbs. \n\n\n\n=Azodin Zenith Paintball Marker=\n\nGoing beyond the limitations of traditional paintball marker technology, the ZENITH has brought the blow-back design into the realm of super markers. Utilizing the Zero Recoil Operation System, the blow-back marker has never shot so smooth and as result of an unprecedented level of shot on shot accuracy.\n\n\nThe new ZeRO System incorporates the \"Feather Striker System\" and a revolutionary redesign of the Valve Engine to reduce operating pressure. ZeRO system minimizes the recoil signature of the ZENITH and enables the player to focus on aiming instead of controlling the marker.\n\n\nThe new \"Feather Striker System\" is 30% lighter than the traditional striker design. This breakthrough reduces the mechanical recoil. The Valve Engine was redesigned to take full advantage of both CO2 and High Pressured Air(HPA). Through extensive research, the Azodin design team was able to engineer precise parts that will enable the Zenith to manage the rigors of CO2 and demands of HPA.\n\n\nThe Zenith is powered by the \"Zen\" Board which hosts all of the modes on the major circuits and also has the backing of a committed Azodin Team to stay current with the ever-changing landscape of tournament paintball. ", + "page_title" : "Buy Azodin Paintball Guns Online On Sale Now", + "head_title" : "Azodin Paintball Guns | Azodin Painball Markers | Azodin Chaos Pump" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_backpacks" : {}, + ".markers.azodin.azodin_paintball_packages" : { + "meta_description" : "Azodin Paintball Guns - Buy your Azodin Painball Markers Online at Zephyr Paintball for Less today. Free Shipping on Azodin Pump Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Azodin Paintball Guns Online On Sale Now", + "head_title" : "Azodin Paintball Guns | Azodin Painball Markers | Azodin Pump" + }, + ".casual_clothing.mens_clothing.hats.hostility_mma_hats" : { + "meta_description" : "Hostility MMA Hats - Buy your Hostility MMA Baseball Hats At Zephyr Sports for Less Today! We carry a complete line of Hostility MMA Caps at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Hostility MMA @ Zephyr Sports", + "head_title" : "Hostility MMA Hats | Hostility MMA Baseball Hats | Hostility MMA Caps" + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_vantage_sunglasses" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_chemist_sunglasses" : { + "meta_description" : "Smith Optics Chemist Sunglasses - Zephyr Sports carries a complete line of Chemist Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Chemist Sun Glasses Online Today.", + "page_title" : "Smith Optics Chemist Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Chemist Sunglasses | Chemist Smith Sunglasses Free Shipping | Buy Smith Chemist Sun Glasses" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_lasers" : { + "meta_description" : "Airsoft Lasers - Buy your Red Dot Lasers At Zephyr Sports for Less Today! We carry a complete line of Airsoft Dot Lasers at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Lasers On Sale & Free Shipping", + "head_title" : "Airsoft Lasers | Red Dot Lasers |Airsoft Dot Lasers" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_m4" : { + "head_title" : "KWA M4 Airsoft Guns | KWA M4 Airsoft Rifle" + }, + ".apparel.gloves.bt_paintball_gloves" : { + "meta_keywords" : "bt sniper paintball gloves,bt combat gloves,combat paintball gloves,sniper paintball gloves, battle tested paintball gloves", + "meta_description" : "BT Paintball Gloves - On Sale now at Zephyr Paintball. Get your BT Sniper Gloves and the BT Combat Gloves at Zephyr For Less. 6000+ Products in stock now with free shipping too.", + "page_title" : "", + "head_title" : "BT Sniper Gloves | BT Combat Gloves" + }, + ".shop_by_brand.anarchy_eyewear" : {}, + ".apparel.head_bands_and_wraps.bt_paintball_headbands_and_headwraps" : { + "head_title" : "BT Headbands and Headwraps | Empire BT | BT Battle Tested" + }, + ".paintball.paintball_guns.proto_paintball_guns" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.kwc_spring_airsoft_guns" : { + "head_title" : "KWC Airsoft Guns | KWC Spring Pistols | KWC Airsoft Pistols" + }, + ".airsoft.airsoft_guns.cyma_airsoft_guns" : { + "head_title" : "Cyma Airsoft Guns | Cyma Airsoft Rilfes | CYMA AEG" + }, + ".casual_clothing.mens_clothing.hats.arbor" : { + "meta_keywords" : "Blind Hats,Blind caps,Blind baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Arbor Hats - Zephyr carries a complete line of Arbor Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Arbor", + "page_title" : "Arbor Hats on Sale at Zephyr", + "head_title" : "Arbor Hats | Arbor Caps | Arbor Baseball Hats" + }, + ".shop_by_brand.rap4_paintball" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_predator_sunglasses" : { + "meta_keywords" : "ray ban predator sunglasses, ray bans , ray ban sunglasses", + "meta_description" : "Ray Ban Predator Sunglasses - Zephyr Sports carries a complete line of Predator Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Predator Sun Glasses Online Today.", + "page_title" : "Ray Ban Predator Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Predator Sunglasses | Predator Ray Ban Sunglasses | RayBan Predator Sun Glasses" + }, + ".airsoft.tactical_airsoft_gear.camoflouge_shirts.propper_tactical" : {}, + ".1newitems.2008_products.2008_hybrid_products" : {}, + ".casual_clothing.mens_clothing.sweatshirts.hurley_sweatshirts" : { + "meta_description" : "Hurley Sweatshirts - Buy your Hurley Hoodies At Zephyr Sports for Less Today! We carry a complete line of Hurley Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Hurley Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Hurley Sweatshirts | Hurley Hoodies | Hurley Hoody" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_team_heli_pro_backpacks" : {}, + ".safetygear.kneeelbowpads.smart_parts_knee___elbow_pads" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_arcolux_sunglasses" : {}, + ".airsoft.airsoft_guns.1_shop_by_gun_type.m14_airsoft_guns" : { + "meta_description" : "M14 Airsoft Guns - Buy your Airsoft M14 At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "The M14 Airsoft Rifles below are replica rifles based off the original U.S. M14 Rifle. The M14, formally known as the United States Rifle M14, was originally developed as a means of taking the place of four different weapons systems. The task seemed impossible and in the end truly was... In general, the M14 is a controversial weapon in that it had the accuracy and range of the \"old time\" military rifles, but was too long, heavy and lacked the automatic fire firepower of a true assault rifle. Truth be told, it wasn't that it 'lacked' the automatic firepower, but more-so that it was too powerful to actually control! Most service M14's were turned into solely semi-automatic weapons for this reason.. Nevertheless, the M14 was a reliable and powerful weapon, often favored by users for high lethality, long range and good penetration - features much appreciated by US soldiers during recent operations in Afghanistan and Iraq.\n\n\n\n\nThe M14 remains in limited front line service with the United States Army, Marine Corps, Navy, Air Force, and Coast Guard, and remains in use as a ceremonial weapon. It was the last so-called \"battle rifle\", a term applied to weapons firing full-power rifle ammunition, issued in quantity to U.S. troops. The M14 also provides the basis for the M21 and M25 sniper rifles.\n\n\n\n\n", + "page_title" : "Buy M14 Airsoft Guns On Sale & Free Shipping", + "head_title" : "M14 Airsoft Guns |Airsoft M14", + "description" : "" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_kriss_vector" : { + "head_title" : "KWA Kriss Vector Airsoft Gun |Kriss Vector Airsoft" + }, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases.condor_tactical" : {}, + ".casual_clothing.z-sunglasses.revo_sunglasses.revo_overhang_sunglasses" : { + "meta_description" : "Revo Overhang Sunglasses - Zephyr Sports carries a complete line of Overhang Revo Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Revo Overhang Sun Glasses Online Today.", + "page_title" : "Revo Overhang Sunglasses On Sale Free Shipping", + "head_title" : "Revo Overhang Sunglasses | Overhang Revo Sunglasses Free Shipping | Buy Revo Overhang Sun Glasses" + }, + ".safetygear.kneeelbowpads.alta_tactical_knee___elbow_pads" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns.smith_and_wesson_gas_airsoft_guns" : { + "meta_description" : "Smith and Wesson Airsoft Guns - Buy your Smith and Wesson Airsoft PistolAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Smith and Wesson Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Smith and Wesson Airsoft Guns | Smith and Wesson Airsoft Pistol" + }, + ".shop_by_brand.spy_optics" : {}, + ".goggles.1goggle_accesories.sly_paintball_goggle_accessories.sly_goggle_straps" : {}, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_catchers_mitts" : { + "head_title" : "Rawlings Catchers Mitts | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".markers.triumph_paintball_guns" : {}, + ".markers.azodin.azodin_kdii_paintball_guns" : { + "meta_keywords" : "Azodin paintball guns, paintball markers, paintball equipment, KDII, KDii, KD II,KD ii, KD2, KD 2, KD two, KD too paintball markers", + "meta_description" : "Azodin KDII Paintball Guns - Buy your Azodin KD2 Painball Markers Online at Zephyr Paintball for Less today. Free Shipping on Azodin KD 2 Guns! Trust Zephyr for all your Paintball Needs", + "top_description2" : " \t\n\nThe KD-II paintball marker is a refinement of its predecessor Kaos-D, bringing the mechanical\nmarkers to a new milestone, once again. With the already reliable Stacked tube blowback(STBB)\nplatform and utilizing the revamped Zero-D low-pressure system, KD-II is now even more air\nefficient with an operating pressure of 225psi and higher consistency in every shots.\nThe tool-less ZeRO-D system is now directly threaded onto the body for easier maintenance and reliability.\n\n\nKD-II featured with an improved trigger giving user a lighter and softer trigger pulls ever on a\nmechanical marker, now beware of the addiction rate of fire from a mechanical semi-auto marker.\n\n\nThe KD-II also comes with a clamping feedneck to lock any loaders tight in place, a refined\n2-piece 14\" barrel (.689 bore) for greater accuracy, and the air-flow friendly angled regulator collar.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/azodin_kdii_header.jpg", + "description" : "= Features: =\n* AZ Adjustable Clamping Feedneck\n* AZ Profile On/Off ASA\n* Rock Steady Regulator\n* Angled Regulator Collar\n* Dust &\" Polished Finish\n* 14\" 2 Piece Barrel - Bore .689\n* Mass Flow Valve\n* Light Mech Trigger: Softer Trigger Pull, Shorter Trigger Pull Distance, Faster Rate Of Fire\n* ZeRO-D: Improved Consistency, Lower Operating Pressure, Direct Threading", + "page_title" : "Buy Azodin KDII Paintball Guns Online On Sale Now", + "head_title" : "Azodin KDII Paintball Guns | Azodin KD2 Painball Markers | Azodin KD 2" + }, + ".apparel.pants.dyepants" : { + "meta_keywords" : "Discount Dye Paintball Pants, Dye Pants Paintball, Paintball Dye Pants, Dye Paintball Pants, Paintball Pants, Paint Ball Pants, Dye Pants, Paint Ball Dye Pants, Discount Paintball Pants,C12,C13,C14,C15,C16", + "meta_description" : "Discount Dye Paintball Pants - ZephyrPaintball is the best place to shop for paintball dye pants and other equipment. Dye C12,C13,C14,C15,C16", + "top_description" : "Looking for best paintball pants on the market? Look no further than Dye. Dye has been making top quality paintball pants for years. For 2013, Dye released the c13 and ultralite series of pants. The Dye C13 features 7 colors to choose from to fit just about any team color scheme. Looking for the lightest paintball pants on the market? Take a look at the new Dye Ultralite Pants. The ultralite pants are made with 4-way stretch fabric similar to what you find in high end Boardshorts.", + "prodlist1_header" : "Dye Paintball Pants", + "description" : "Dye Paintball Pants can take incredible abuse and still keep their structure. This is extremely important since paintball pants usually take the most beating out of all of the other gear. Taking a dive or sliding into a bunker is not like sliding over a slip and slide. Rocky dirt, grassy terrain and turf all cause wear and tear on pants. Dye secures their pants with heavy-duty nylon kneepads with Kevlar for ultimate strength. Also, a main concern of every male is our family jewels. Dye developed compression formed crotch protection for total coverage so there are no accidents. Ventilation has always been one of Dye’s main concerns. Other paintball pants keep heat in while the Dye Pants push heat out with integrated air channels in the front and rear of the pant. Another great feature is the adjustable waist that allows you to change the fitting of your pant to your personal needs. Some like them baggy some like it as tight as possible – the choice is yours. You know what really bugs? Dirt creeping up your leg as you run or slide. The adjustable cuffs make it easy to make a tight cuff to work for any type of cleat/shoe. Every year the Dye Pants get stronger and more reliable. The C9 Pants are the most advanced playing pant in the industry and they will only get better.", + "page_title" : "Dye Paintball Pants | Dye Pants | Paintball Pants", + "head_title" : "Dye Paintball Pants with Free Shipping at Zephyr", + "sortby_var" : "Dye Model Year", + "page_head" : "", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_peahi_sunglasses" : { + "meta_description" : "Maui Jim Peahi Sunglasses - Zephyr Sports carries a complete line of Maui Jim Peahi Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Peahi Online Today.", + "page_title" : "Maui Jim Peahi Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Peahi Sunglasses | Maui Jim Peahi Sun Glasses | Sunglasses Maui Jim Peahi" + }, + ".buyers_guide.paintball" : { + "title_01" : "What is Paintball?", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002.jpg", + "return_link" : "/category/buyers_guide/", + "text_01" : "Paintball is a game in which players compete, in teams or individually, to eliminate opponents by hitting them with capsules containing paint (referred to as paintballs) from a device called a paintball marker. The game is regularly played at a sporting level with organized competition involving worldwide leagues, tournaments, professional teams, and players. Paintball technology is also used by armies to supplement military training, riot response, and non lethal suppression of dangerous suspects.\n\n\nGames are played on indoor or outdoor fields of varying sizes. A game field is scattered with natural or artificial terrain, which players use for strategic play. Rules for playing paintball vary, but can include capture the flag, elimination, defending or attacking a particular point or area, or capturing objects of interest hidden in the playing area. Depending on the variant played, games can last from seconds to hours, or even days in scenario play.\n\n\nThe legality of paintball varies among countries and regions. In most areas where regulated play is offered, players are required to wear protective masks, and game rules are strictly enforced." + }, + ".airsoft.optical_and_flashlight_upgrades" : { + "meta_description" : "Airsoft Scopes - Buy your Airsoft Optics At Zephyr Sports for Less Today! We carry a complete line of Airsoft Lasers at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Scopes On Sale & Free Shipping", + "head_title" : "Airsoft Scopes |Airsoft Optics |Airsoft Lasers" + }, + ".casual_clothing.mens_clothing.beanies.metal_mulisha_beanies" : { + "meta_keywords" : "Metal Mulisha beanie,Metal Mulisha hat,Metal Mulisha beanies,Metal Mulisha caps,Metal Mulisha 686,Metal Mulisha headwear,Metal Mulisha cuff visor beanie,Metal Mulisha beanie hat,Metal Mulisha visor beanie,Metal Mulisha visor beanies", + "meta_description" : "Metal Mulisha Deanie - Surf style with Metal Mulisha Beanies available now at Zephyr Sports. Get your Metal Mulisha hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Metal Mulisha Beanies on Sale at Zephyr Today", + "head_title" : "Metal Mulisha Beanie | Metal Mulisha Hat | Metal Mulisha Beanies" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_mogul_sunglasses" : { + "meta_description" : "Smith Optics Mogul Sunglasses - Zephyr Sports carries a complete line of Mogul Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Mogul Sun Glasses Online Today.", + "page_title" : "Smith Optics Mogul Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Mogul Sunglasses | Mogul Smith Sunglasses Free Shipping | Buy Smith Mogul Sun Glasses" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.____desert_eagle_gas_airsoft_guns" : { + "meta_description" : "Desert Eagle Airsoft Guns - Buy your Desert Eagle Airsoft PistolAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Desert Eagle Airsoft Guns On Sale & Free Shipping", + "head_title" : "Desert Eagle Airsoft Guns | Desert Eagle Airsoft Pistol" + }, + ".markers.azodin.azodin_kaos_paintball_guns" : { + "meta_description" : "Azodin Kaos Paintball Guns - Buy your Azodin Kaos Painball Markers Online at Zephyr Paintball for Less today. Free Shipping on Azodin Kaos Pump Trust Zephyr for all your Paintball Needs", + "top_description2" : "Developed with the highest standard in mind, the azodin KAOS paintball gun incorporates the latest technological breakthroughs, while providing standard features that are on higher end paintball markers. The Azodin KAOS gives players the competitive edge on the field of battle. The Azodin Kaos \"Feather Striker System\" is 30% lighter than the traditional striker design, allowing reduced mechanical recoil for the smoothest handling semi-auto paintball gun on the market. In the Market for an entry level semi automatic paintball gun, the Azodin Kaos deserves a serious look.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.azodin_paintball_packages/", + "description" : "Weighing in at just over 2lbs, the azodin kaos paintball gun is lightweight and easy to maneuver during your paintball match. The kaos uses impulse / Ion feedneck threads and an autococker threaded barrel for an easy upgrade path. The Azodin Kaos will run off of co2 or compressed air although Zephyr always recommends compressed air for the best paintball experience. The standard barrel on the Kaos is a 12\" ported barrel that is fairly accurate for a stock barrel. The azodin kaos also come in a pump version for all you old school ballers. If you haven't played pump before I recommend you give it a try. You'd be amazed how much you learn when you can't just shoot a stream of paintballs and actually have to move around the field to pick your shots.\n\n\n=Azodin Kaos Features=\n*Low Rise \"Twist Lock II\" Feed Neck\n*Feather Striker System\n*Top Cocking Pull Pin\n*Quick Release Delrin Bolt\"\n*12\" Single Piece Barrel\n*Double Ball Detents\n*Gas-Thru Foregrip\n*Non-Slip Rubber Grip Panels\n*Aluminum Grip Frame w/ Dovetail and Direct Screw Mount\n*Operates on CO2 or HPA", + "page_title" : "Buy Azodin Kaos Paintball Guns Online On Sale Now", + "head_title" : "Azodin Kaos Paintball Guns | Azodin Kaos Painball Markers | Azodin Kaos Pump" + }, + ".markerupgrades.grips_and_grip_panels.hybrid_paintball_grips.hybrid_angel_paintball_grips" : {}, + ".casual_clothing.mens_clothing.accessories.audio___headphones.nixon_headphones" : { + "meta_keywords" : "nixon headphones,headphones nixon,whip,nomadic,master blaster,wire,nixon ear buds", + "meta_description" : "Nixon Headphones - Listen to your ipod in style with some new headphones from Nixon. Zephyr carries a complete line of Nixon headphones and ear buds at the lowest prices on the web", + "page_title" : "Nixon Headphones with Free Shipping at Zephyr Sports", + "head_title" : "Nixon Headphones | Nixon Head Phones" + }, + ".paintballs" : { + "subcat1_header" : "Paint Categories", + "meta_keywords" : "cheap paint balls, paint balls, high grade paintballs, high grade paint, recreational paint, tournament paint, pmi paint balls, diablo paint balls, cheap paint,paintball sale,sale paintball", + "meta_description" : "Need some paintballs? Zephyr has Sale paintballs along with bulk paintball sale packages. Whether your a beginner or a tournament player, we have the paint for you. Discount paintballs for less at zephyr. Did we mention free shipping.", + "prodlist2_title" : "Featured Paint Items", + "zoovy:banner_image_01" : "banners/09_headers/free_shipping_paint_001.png", + "banner01_link" : "", + "description" : "What do I look for with paint? Choosing your paint can depend on a lot of reasons. For recreational play using a Tippmann or Spyder we recommend using [[Diablo Heat]:url=/product/PT-DIAB-HEAT/Diablo_Heat_Paintbals_2000_Count.html] or [[PMI Stinger]:url=/product/PT-PMI-STINGER/PMI_Stinger_Paintballs__2000_Rounds.html]. With Heat and Stinger the shell is much harder than higher end paint which in the case of using a Tippmann or Spyder you would want to use a harder shell so it does not break in your chamber. Unlike [[Forumla 13]:url=/product/PT-DIAB-FORM13/Diablo_Formula_13_Paintbals_2000_Count.html] or [[Premium]:url=/product/PT-PMI-PREMIUM/PMI_Premium_Paintballs__2000_Rounds.html] the shell is brittle which is used more on higher end markers that in some cases have bolts that are softer on paint. Also, each paint has a different bore size. Most of the paint that Zephyr carries is around the common bore size of .68 caliber. The size of the paint is of importance when a player begins to recognize stray balls. If you are noticing paint flying left or right; the ball could be to small for your barrel. It's always good to look into what bore size your barrel operates with and find paint around that size. It's not the end of the world if they do not match but the consistency with your shots will be noticed.\n\n\n==Do paintballs have a warranty?==\n\nThere is no warranty on paintballs. Zephyr Sports will inspect each bag to make sure there are no breaks prior to shipping, plus we will inspect the outside of every box that is shipped for any sign of damage. All of the products we sell are securely packaged, this is to insure safe delivery. We cannot control the way a package is handled once it has left our warehouse. In some instances, small paint breaks can be contained. By taking the bag of paint with the broken ball and lightly rubbing them down with an old towel, you can easily restore the paintballs to pristine condition. Also, note that there will be a little bit of oil in each bag, this is not a break, the oil is used by the manufacturer in order to keep the balls fresh.\n\n\n==What makes one case of paint better than another?==\n\nThere are many different aspects that come into play when comparing different grades of paint. Everything from the thickness of the fill, to the shell of the ball, to the seam plays a big role in how any particular paintball is going to shoot.\n=Recreational Paintballs:=\nTypically ranges from $30-$45 per case of 2000. This is a level of paint that most people use on an average day out at the field. It may have some dimples or flat spots. The shell is a moderate thickness, the fill may be a bit runny, but it gets the job done. You may have some bounces or breaks, but a Recreational ball is just that. It is meant for recreational play, with consistent accuracy and will break upon impact the majority of the time.\n=Mid-Grade Paintballs:=\nTypically ranges from $45-$60 per case of 2000. This is a level of paint that the more experienced player will use whether it is on the field or in a tournament. It will have fewer dimples and flat spots than a recreational paintball. The shell is going to be a bit smoother than a rec. ball, and the fill will be slightly thicker. Your will see a boost in accuracy and fewer breaks.\n=Tournament/High End Paintballs:=\nTypically ranges from $60+ per case of 2000. This is a level of paint that you will see tournament players shooting. It is the cream of the crop when it comes to paintballs in every aspect. The shell is smooth and much more brittle. The fill is thicker, so there is no questioning whether you got that other player or not. It will also break on impact much more frequently than lower grades of paint. It is hard to spend that extra money per case from time to time, but when you get the opportunity to take some Tournament level paint for a spin you won't want to shoot anything else.\n\n=Paintballs damaged in transit by either weather conditions or rough handling are the customer's responsibility! Be sure to inspect the package when the product is delivered. If you need to file a claim for damaged goods please contact us at 877-814-4297 within 3 days of receiving your package. We will then file a claim with Fedex.=", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "banner1" : "banners/09_headers/main_categories/paintballs_001", + "htmllinks" : "=Popular Paintballs=\n[[Diablo Heat]:url=/category/paintballs.diablo_paintballs/] - [[PMI Marballizer]:url=/category/paintballs.pmi___rps_paintballs/] - [[PMI All Star]:url=/product/PT-PMI-ALLSTAR] - [[Tiberius First Strike]:url=/category/paintballs.tiberius_arms_paintballs/]", + "head_title" : "Cheap Paintballs | Bulk Paintball Sale | Tournament Paintballs", + "page_title" : "Buy Cheap Paintballs Online On Sale Now", + "page_head" : "" + }, + ".casual_clothing.mens_clothing.sandals.dc_sandals" : { + "meta_description" : "DC Sandals - Buy your Mens DC Sandals At Zephyr Sports for Less Today! We carry a complete line of DC Flip Flops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DC Sandals On Sale at Zephyr Sports", + "head_title" : "DC Sandals | Mens DC Sandals | DC Flip Flops" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_asian_fit_sunglasses.oakley_asian_fit_jawbone_sunglasses" : { + "meta_description" : "Oakley Asian Fit Jawbone Sunglasses - Zephyr Sports carries a complete line of Jawbone Asian Fit Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Jawbone Asian Fit Sun Glasses Online Today.", + "page_title" : "Oakley Asian Fit Jawbone Sunglasses On Sale Free Shipping", + "head_title" : "Oakley Asian Fit Jawbone Sunglasses | Jawbone Asian Fit Oakley Sunglasses | Oakley Jawbone Asian Fit Sun Glasses" + }, + ".casual_clothing.youth_clothing.youth_shoes" : {}, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_domo_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon domo sunglasses", + "meta_description" : "Dragon Domo Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Domo Sunglasses" + }, + ".airsoft.airsoft_guns.jg_jing_gong_airsoft_guns" : { + "meta_description" : "JG Airsoft Guns - Buy your JG Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of JG AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy JG Airsoft Guns On Sale & Free Shipping", + "head_title" : "JG Airsoft Guns | JG Airsoft Rifles | JG AEG" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_polarized_sunglasses" : { + "meta_description" : "Arnette Polarized Sunglasses - Zephyr Sports carries a complete line of Polarized Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Polarized Sun Glasses Online Today.", + "page_title" : "Arnette Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Polarized Sunglasses | Polarized Arnette Sunglasses | Arnette Polarized Sun Glasses" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.aps_airsoft_gas_guns" : {}, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_times_sunglasses" : { + "meta_description" : "Hoven Times Sunglasses - Zephyr Sports carries a complete line of Hoven Times Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Times Online Today.", + "page_title" : "Hoven Times Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Times Sunglasses | Hoven Times Sun Glasses | Sunglasses Hoven Times" + }, + ".3packagespecials.tippmann_packages.tippmann_ft-12_paintball_packages" : { + "head_title" : "Tippmann FT12 Paintball Packages | Tippmann FT12 Paintball Gun Packages" + }, + ".shop_by_brand.allen_paintball_products" : {}, + ".barrels.barrels_by_manufacturer.j_j_paintball_barrels.j_j_ceramic_one_piece_barrels" : { + "meta_keywords" : "j&j paintball barrels, J&J xceramic barrels, jj ceramic barrels, jj paintball barrels, ceramic paintball barrel", + "meta_description" : "J&J Ceramic Barrels are the number entry level barrel from J&J Paintball Barrels. The JJ Ceramic Barrels will increase your accuracy drasticly from a stock barrel. The other major feature of these barrels is the ceramic coating that alows for easy cleaning", + "top_description2" : "The single piece ceramic paintball barrels made by J&J are high quality upgrades to just about any paintball marker that will improve your shot and your game. The special Teflon / Ceramic coating clears breaks and reduces friction on the ball as it flies through the barrel at the other team. Get the best for your gun with a self cleaning, aluminum, high quality barrel.", + "page_title" : "Buy J&J Paintball Barrels Online On Sale Now", + "head_title" : "J&J Paintball Barrels | J&J Ceramic Barrels | JJ Ceramic Barrels", + "zoovy:banner01" : "banners/paintball/headers/jjceramic_paintball_header", + "description" : "It doesn't get any easier than this. A one piece barrel means that there is no assembly required to up the stakes and send the other team home looking like pink and yellow clowns. The JJ ceramic barrels are among one of the best first upgrades to make to your paintball marker, requiring no technical knowledge or draining the wallet.\n\n\n==Best First Upgrade:== \n\nSo you've got the new gun, you're stoked and you should be. But after a couple games you might notice the stock barrel isn't as amazing as the owners manual believes it to be. That's when you go for the number uno most recommended upgrade to paintball markers: an aftermarket barrel. These J&J ceramic barrels will fit almost any thread (Tippmann 98, A5/X7, Autococker, Impulse/Ion, Phantom and Spyder) and range in size from 12\" to 20\".\n\n\n==Slick Construction:==\nJ & J Ceramic barrels are made of T6 6061 aluminum and precision ground to specification by CNC machines. The barrels are then coated with a Teflon impregnated ceramic material that produces a frictionless surface. This Teflon coat keeps broken paint from clinging to the inside of the barrel, letting future shots actually clean out the barrel as you play. Got a break? No worries, just keep on blasting and your ceramic barrel will take care of itself. The ceramic / Teflon coating also reduces the friction generated as the ball passes through the barrel, improving accuracy and consistency of the ball's flight path.\n\n\n==Full Tilt:==\nIn addition to the one piece ceramic series, JJ performance also offers the [[Full Tilt series]:popup=/category/barrels.barrels_by_manufacturer.j_j_paintball_barrels.j_j_full_tilt_paintball_barrels/]. The Full Tilt series is made for those players that can assemble lkea furniture, with its two piece design. This barrel is more accurate, and uses the same coating on the single piece barrels." + }, + ".apparel.jerseys.sly_paintball_jerseys" : { + "meta_keywords" : "sly paintball jersey,sly pro merc paintball jersey, Sly Camo Jersey, Sly Pro Merc, Sly Neon Jersey", + "meta_description" : "Sly Pro Merc Paintball Jerseys - Complete Line of Sly Paintball Jersey available at Zephyr. The Sly Pro Merc is the newest in the line of Sly player Gear. Made by players for players.", + "page_title" : "", + "head_title" : "Sly Pro Merc Paintball Jerseys | Sly Paintball Jersey | Sly Pro Merc", + "prodlist1_header" : "" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_winter_hydration_packs" : { + "meta_description" : "Camelbak Winter Packs - Buy your Camelpack Snowboard Packs At Zephyr Sports for Less Today! We carry a complete line of Camelbak Winter Hydration Packs at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Winter Packs On Sale & Free Shipping", + "head_title" : "Camelbak Winter Packs | Camelpack Snowboard Packs | Camelbak Winter Hydration Packs" + }, + ".casual_clothing.mens_clothing.hats.famous_stars_and_straps_hats" : { + "meta_keywords" : "Famous Hats,Famous caps,Famous baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Famous Hats - Zephyr carries a complete line of Famous Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Famous", + "page_title" : "Famous Hats on Sale at Zephyr", + "head_title" : "Famous Hats | Famous Caps | Famous Baseball Hats" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.famas_spring_rifles" : { + "meta_description" : "Famas Airsoft Guns - Buy your Famas Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Famas Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Famas Airsoft Guns On Sale & Free Shipping", + "head_title" : "Famas Airsoft Guns | Famas Airsoft Rifles | Famas Spring Airsoft Guns" + }, + ".airsoft.tactical_airsoft_gear.paracord_bracelets.mil-spec_cords_paracord_bracelets" : {}, + ".casual_clothing.z_unisex_clothing_accesories.lanyards.zephyr_sports_lanyards" : {}, + ".airsoft.airsoft_guns.aps_airsoft_guns" : {}, + ".3packagespecials.extreme_rage_paintball_packages" : { + "meta_description" : "Extreme Rage Paintball Starter Kits - Buy your Extreme Rage Paintball Packages Online at Zephyr Paintball for Less today. Free Shipping on ER Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Extreme Rage Paintball Starter Kits Online On Sale Now", + "head_title" : "Extreme Rage Paintball Starter Kits | Extreme Rage Paintball Packages | ER Paintball Guns" + }, + ".casual_clothing.mens_clothing.wallets.hater_wallets" : { + "meta_description" : "Hater Wallets - Buy your Hater Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Hater Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Hater Wallets On Sale & Free Shipping", + "head_title" : "Hater Wallets | Hater Mens Wallets | Hater Wallet" + }, + ".casual_clothing.z_shoes_and_footwear.emerica_shoes" : {}, + ".scenarioupgrades.stocks.valken_sw-1" : {}, + ".casual_clothing.mens_clothing.tshirts.lrg_t_shirts" : { + "meta_keywords" : "LRG T Shirts,LRG shirts,free shipping,LRG TShirt", + "meta_description" : "LRG T Shirts - Zephyr carries a complete line of LRG Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "LRG T Shirts at Zephyr", + "head_title" : "LRG T Shirts | LRG Shirts | LRG TShirt" + }, + ".casual_clothing.mens_clothing.tshirts.hater_t_shirts" : { + "meta_keywords" : "hater tshirts,hater t shirt,hate clothing, heter paintball clothing", + "page_title" : "Hater Paintball T Shirts On Sale & Free Shipping", + "head_title" : "Hater Paintball T Shirts | Hater Apparel" + }, + "$hk_army" : {}, + ".markers.invert_paintball_guns.invert_package_specials" : { + "meta_description" : "Invert Mini Packages - Invert Mini Paintball Packages for Less at Zephyr. Complete starter packages for the Invert mini paintball gun packages ship for free at Zephyr", + "page_title" : "Buy Invert Mini Packages Online On Sale Now", + "head_title" : "Invert Mini Packages | Invert Mini Paintball Packages | Invert Mini Paintball Gun Packages", + "prodlist1_header" : "Invert Mini Paintball Gun Packages", + "prodlist_custom" : "&SORTBY=PRICE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".apparel.head_bands_and_wraps.pb_fashion_headbands_and_wraps" : {}, + ".casual_clothing.mens_clothing.accessories" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_planetary_backpacks" : { + "meta_description" : "Oakley Planetary Backpacks - Buy your Oakley Planetary Pack At Zephyr Sports for Less Today! We carry a complete line of Planetary Oakley Bag at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Planetary Backpacks On Sale & Free Shipping", + "head_title" : "Oakley Planetary Backpacks | Oakley Planetary Pack | Planetary Oakley Bag" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_kaori_sunglasses" : { + "meta_keywords" : "Spy Kaori sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Kaori Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy optic eyewear with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Kaori Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Kaori Sunglasses | Spy Optics Kaori Sunglasses" + }, + ".markerupgrades.grips_and_grip_panels.trinity_paintball_grips" : {}, + ".3packagespecials.gog_paintball_packages.gog_extcy_paintball_gun_packages" : { + "head_title" : "Gog eXTCY Paintball Packages | Gog eXTCY Paintball Gun Packages" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.m4___m16_aeg_airsoft_magazines" : {}, + ".casual_clothing.mens_clothing.watches.kr3w_watches" : {}, + ".casual_clothing.mens_clothing.hats.grenade_hats" : { + "meta_keywords" : "Blind Hats,Blind caps,Blind baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Grenade Hats - Zephyr carries a complete line of Grenade Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Grenade", + "page_title" : "Grenade Hats on Sale at Zephyr", + "head_title" : "Grenade Hats | Grenade Caps | Grenade Baseball Hats" + }, + ".2clearance.clearance_jerseys___apparel" : { + "dynimage1" : "images=banners/paintball/slideshow/weeklyspecials001\nlinks=%SESSION%/category/1weekly_specials/\npauses=2000\nblank_behavior=none\n", + "meta_keywords" : "clearance paintball jersey, discount paintball jersey, clearance paintball pants, discounted paintball apparel, clearance paintball equipment", + "page_title" : "", + "head_title" : "Clearance Paintball Jersey | Discount Paintball Jersey | Clearance Paintball Pants", + "sortby_var" : "Clothing Type" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_juice_sunglasses" : { + "meta_description" : "Arnette Juice Sunglasses - Zephyr Sports carries a complete line of Juice Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Juice Sun Glasses Online Today.", + "page_title" : "Arnette Juice Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Juice Sunglasses | Juice Arnette Sunglasses | Arnette Juice Sun Glasses" + }, + ".goggles.1goggle_accesories.tippmann" : {}, + ".shop_by_brand.midland_airsoft" : {}, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_standard_sunglasses" : { + "meta_description" : "Hoven Standard Sunglasses - Zephyr Sports carries a complete line of Hoven Standard Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Standard Online Today.", + "page_title" : "Hoven Standard Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Standard Sunglasses | Hoven Standard Sun Glasses | Sunglasses Hoven Standard" + }, + ".harnessesbags.packs___harnesses.empire_paintball_pod_packs" : { + "meta_keywords" : "empire paintball harness, empire harness, empire pod pack, liquid pack, hinge pack, paintball harness, paintball pod pack", + "meta_description" : "Empire Paintball Harness - Buy you Empire Harness at Zephyr today. We carry a complete line of Empire pod packs to get you on the field and in the game", + "page_title" : "Buy Empire Paintball Harness Online On Sale Now", + "head_title" : "Empire Paintball Harness | Empire Harness | Empire Pod Pack" + }, + ".1newitems.2008_products.2008_maddog_designz_gear" : {}, + ".casual_clothing.mens_clothing.beanies.686_beanies" : { + "meta_description" : "686 Beanies - Buy your Beanies 686At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on 686 BEANIES @ Zephyr Sports", + "head_title" : "686 Beanies | Beanies 686" + }, + ".airsoft.tactical_airsoft_gear.tactical_gloves.condor_tactical_gloves" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_optique_watches" : {}, + ".markers.tippmann.a5" : { + "meta_keywords" : "tippmann A5 paintball guns, a5 tippmann paintball guns, tippmann a5 marker, tipman, tippman, tipmann paintball gear,tippman a 5 paintball gun, tippmann a-5 gun, tippmann a5 with cyclone, tippmann a5 cyclone", + "meta_description" : "Tippmann A-5 Paintball Guns - Zephyr brings you the leader in scenraio paintball guns. A-5 paintball guns offer affordable performance from a scenario marker. The Tippmann A5 Marker features the cyclone feed system for error free feeds.", + "top_description2" : "The Tippmann A5 is the standard in woodsball. The A5 has a rock solid all aluminum body with a composite trigger frame. The tippmann A5 excepts the response trigger, Egrip and tippmann A5 flatline barrel. The patented tippmann cyclone feed gives battery free 15+ BPS feed rates. Zephyr carries a complene line of tippmann guns including the Tippmann A5 with plenty of complete Tippmann a5 packages to get you in the game.", + "prodlist1_header" : "Tippmann A-5 Paintball Guns", + "description" : "The Tippmann A5 is one of the most reliable paintball guns on the market. It's durable, light, and accurate and can be upgraded from all ends. The Tippmann A5 paintball gun is considered the most customizable gun available today. Making it look like a realistic weapon is no hassle with the A5. The Tippmann A-5 might be a bit longer and heavier than other paintball guns but has a comfortable feel with its solid design. The Tippmann Cyclone feed, which feeds paintballs without the need for batteries, uses the excess air from the gun to move at an amazing 15+ Balls Per Second. The stock tipmann A5 is semi-automatic, which means no electronics all mechanical. The Tippmann A5 is available with the A5 E-grip giving the luxury of shooting full auto, 3 round burst & semi-automatic. The A5 Egrip is also available as an upgrade for the stock Tippmann A5. This is a great feature to have since you never know what situation you will be in that allows you to up the performance of your gun with the flip of a switch.\n\n\n==How's the Performance?==\nTippmann stands by their paintball guns always promising a durable, consistent setup. Since the Tippmann A5 is equipped with the Cyclone feed, feeding paint is no problem. Other paintball guns that use standard gravity fed hoppers get jammed and you have to shake your gun to get the balls to drop in the chamber. Not the tippmann A-5, the cyclone takes care of the feeding for you by moving every time you fire the gun. This allows for rapid rates of fire without needing an electronic loader and practically guarantees that there will be no missed shots and ball will be in that chamber every time. The Tippmann A-5 will run on both Compressed Air & CO2. Since it has a durable construction CO2 will not take a toll on the internal parts but we always recommend Compressed Air. \n\n\n=Tippmann A5 Upgrades=\n\n\nThere are a full line of upgrades for the Tippmann A5. From the [[A5 Flatline barrel]:url=/product/TIP-2045-T201017], Egrip, response trigger as well as tactical upgrades including sight rails, stocks, tactical barrels, and magazine clips to give you A5 gun a realistic military look. Be sure to take a look at our fill line of [[tippmann A5 upgrades]:url=/category/markerupgrades.tippmann.a5/].\n\n\n\n\n\n\n\n\n==Tippmann A-5 CO2 Shot Count==\n*20oz - About 900 shots\n*16oz - About 700 shots\n*12oz - About 450 shots\n*9oz - About 300 shots\n\n\n==Tippmann A5 Compressed Air Shot Count==\n*48/3000 - Around 384 Shots\n*68/3000 - Around 544 Shots\n*88/3000 - Around 704 Shots\n*50/4500 - Around 600 Shots\n*68/4500 - Around 816 Shots\n*88/4500 - Around 1056 Shots\n", + "dynimage1" : "images=banners/paintball/slideshow/tippmann_a5_gunslideshow_template\nlinks=\npauses=2000\nblank_behavior=none\n", + "banner1" : "banners/a5_header", + "page_title" : "Buy Tippmann A5 Paintball Guns Online On Sale Now", + "head_title" : "Tippmann A5 Paintball Guns | A-5 Tippmann Paintball Guns | Tippmann A5 Marker", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_sandalwood_sunglasses" : { + "meta_description" : "Maui Jim Sandalwood Sunglasses - Zephyr Sports carries a complete line of Maui Jim Sandalwood Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Sandalwood Online Today.", + "page_title" : "Maui Jim Sandalwood Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Sandalwood Sunglasses | Maui Jim Sandalwood Sun Glasses | Sunglasses Maui Jim Sandalwood" + }, + ".apparel.pants.empire_paintball_pants" : { + "meta_keywords" : "Empire Paintball Pants, Paintball Empire Pants, Empire Pants Paintball, Empire Paintball Pants, Empire Pants, Paintball Pants, Paint Ball Pants, Empire Pants, Discount Empire Pants", + "meta_description" : "Empire Paintball Pants - Discount paintball Empire pants are just one of the many items available online at ZephyrPaintball.com. New for 2013, the Empire THT pants are here. Free Shipping over $100 Buy Empire Pants Today", + "page_title" : "Empire Paintball Pants on Sale Now", + "head_title" : "Empire THT Paintball Pants | 2013 Paintball Empire Pants | Empire Pants Paintball", + "page_head" : "" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_crosshair_sunglasses" : { + "meta_keywords" : "Oakley Crosshair Sunglasses,Crosshair oakley sunglasses,oakley Crosshair, Crosshair polarized sunglasses", + "meta_description" : "Oakley Crosshair Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Crosshair and Polarized Oakley Crosshair Sunglasses on Sale! ", + "page_title" : "Oakley Crosshair Sunglasses with Free Shipping", + "head_title" : "Oakley Crosshair Sunglasses | Crosshair Oakley Sunglassses" + }, + ".casual_clothing.womens_clothing.ladies_watches.nixon_ladies_watches" : {}, + ".apparel.shoes.1_search_by_color.purple_mens_shoes" : {}, + ".shop_by_brand.stiffi_carbon_fiber_paintball_barrels" : {}, + ".1newitems.2008_products.2008_smart_parts_gear" : {}, + ".barrels.tippmann98.16__tippmann_98_barrels" : { + "meta_description" : "16 inch Tippmann 98 Paintball Barrels - Buy your 16\" Custom 98 Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Tippmann 98 Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 16 inch Tippmann 98 Paintball Barrels Online On Sale Now", + "head_title" : "16 inch Tippmann 98 Paintball Barrels | 16\" Custom 98 Threaded Upgrade | Tippmann 98 Paintballs Barrels" + }, + ".casual_clothing.mens_clothing.tshirts.von_zipper_t_shirts" : { + "meta_description" : "Von Zipper T-Shirts - Buy your VZ Shirts Online At Zephyr Sports for Less Today! We carry a complete line of Von Zipper Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Von Zipper T-Shirts Now! On Sale & Free Shipping", + "head_title" : "Von Zipper T-Shirts | VZ Shirts | Von Zipper Shirts" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_parallel_d-max_sunglasses" : { + "meta_description" : "Smith Optics Parellel Sunglasses - Zephyr Sports carries a complete line of Parellel Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Parellel Sun Glasses Online Today.", + "page_title" : "Smith Optics Parellel Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Parellel Sunglasses | Parellel Smith Sunglasses Free Shipping | Buy Smith Parellel Sun Glasses" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_variable_power_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".3packagespecials.invert_paintball_packages" : { + "meta_description" : "Empire Invert Mini Paintball Guns Packages - Buy your Invert Mini Starter Kits Online at Zephyr Paintball for Less today. Free Shipping on Empire Invert Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire Invert Mini Paintball Guns Packages Online On Sale Now", + "head_title" : "Empire Invert Mini Paintball Guns Packages | Invert Mini Starter Kits | Empire Invert Paintball Markers" + }, + ".index" : { + "prodlist" : "&SORTBY=NAME&FORMAT=PLAINMSRP&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".misc_items.water_bottles.klean_kanteen_water_bottles" : {}, + ".casual_clothing.mens_clothing.tshirts.hostility_mma_t-shirts" : { + "meta_keywords" : "Hostility MMA T Shirts,Hostility MMA shirts,free shipping,Hostility MMA TShirt", + "meta_description" : "Hostility MMA T Shirts - Zephyr carries a complete line of Hostility MMA Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Hostility MMA T Shirts at Zephyr", + "head_title" : "Hostility MMA T Shirts | Hostility MMA Shirts | Hostility TShirt" + }, + ".airsystems.tankcovers.sly_paintball_bottle_covers" : { + "meta_description" : "Sly Cover - Buy your Sly Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Sly Paintball Bottle Cover Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Sly Cover Online On Sale Now", + "head_title" : "Sly Cover | Sly Tank Cover | Sly Paintball Bottle Cover" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_wrath_sunglasses" : { + "meta_description" : "Arnette Wrath Sunglasses - Zephyr Sports carries a complete line of Wrath Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Wrath Sun Glasses Online Today.", + "page_title" : "Arnette Wrath Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Wrath Sunglasses | Wrath Arnette Sunglasses | Arnette Wrath Sun Glasses" + }, + ".markerupgrades.bt_designs_upgrades.bt_paintball_trigger_upgrades" : { + "meta_description" : "BT Combat Trigger - Buy your BT Double Trigger Online at Zephyr Paintball for Less today. Free Shipping on Empire Bt Trigger Upgrades Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy BT Combat Trigger Online On Sale Now", + "head_title" : "BT Combat Trigger | BT Double Trigger | Empire Bt Trigger Upgrades" + }, + ".casual_clothing.mens_clothing.jackets.1_search_by_size.1-small" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys.proto_clearance_paintball_jerseys" : {}, + ".airsoft.airsoft_guns.1_shop_by_gun_type" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Guns | Guns Airsoft | Airsoft AEG" + }, + ".barrels.barrels_by_manufacturer.furious_paintball_barrels" : { + "meta_keywords" : "furious paintball barrels, furious lotus barrel, furious barrel, furious barrel back, lotus barrel, lotus paintball barrel, furious barrel kit", + "meta_description" : "Furious Paintball Barrels - Buy your Furious Lotus Barrel Online at Zephyr Paintball for Less today. Free Shipping on Furious Barrel Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Furious Paintball Barrels Online On Sale Now", + "head_title" : "Furious Paintball Barrels | Furious Lotus Barrel | Furious Barrel" + }, + ".harnessesbags.backpacks.young___reckless" : {}, + ".airsoft.airsoft_guns.smith___wesson_airsoft_guns" : { + "meta_keywords" : "Smith & Wesson Replica Airsoft Guns,Smith & Wesson,Smith and Wesson Airsoft Guns,Smith and Wesson Airsoft Pistol, Smith & Wesson Airsoft Revolver,cheap airsoft pistols,Airsoft,Smith and Wesson", + "meta_description" : "Smith & Wesson Replica Airsoft Guns. Smith & Wesson is one of the world's most recognizable brands. Since first opening its doors, they have focused on designing and manufacturing innovative solutions that are unparalleled in the field of personal safety and protection. Almost every major law enforcement and military agency in the world has used Smith & Wesson products, and to this day, most police departments in the United States depend on those firearms and accessories. These Smith and Wesson airsoft replicas are top of line all the way and offer something for everyone. For cheap airsoft pistols, choose Zephyr!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Smith and Wesson Airsoft Guns On Sale & Free Shipping", + "head_title" : "Smith and Wesson Airsoft Guns | Smith and Wesson Airsoft Pistols | Smith & Wesson Airsoft Revolver", + "description" : "" + }, + ".airsoft.airsoft_batteries___chargers.airsoft_rechargeable_batteries" : { + "meta_keywords" : "airsoft battery, airsoft batteries, rechargeable batteries, reachargeable airsoft batteries, AEG airsoft betteries", + "meta_description" : "Airsoft Batteries at Zephyr. We carry a full line of rechargeable batteries for your airsoft gun. Rechargeable airsoft batteries come in a large variety of sizes, shapes and output levels. Be sure to give us a call if you are unsure of the battery for your airsoft AEG rifle.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "" + }, + ".markers.dangerous_power_paintball_guns.dangerous_power_g5_paintball_guns" : { + "meta_description" : "Dangerous Power G5 - Just announce from dangerous power. The latest in the G series of paintball guns, the G5 Paintball Marker will be the first hoseless design from dangerous Power. Buy your Dp G5 from Zephyr First.", + "top_description" : "The Dangerous Power G5 paintball Gun has some pretty swee new improvements. The G5 is now hose free, so all air goes through the frame of the gun. No more macro line leaks. The G5 will start at $329 with plenty of packages available to get you on the field. Full G 5 Specs are below.\n", + "page_title" : "Dangerous Power G5 Buy it First at Zephyr", + "head_title" : "Dangerous Power G5 Paintball Guns - G5 Paintball Marker - DP G5", + "description" : "=Dangerous Power G5 Paintball Gun Features=\n\n*Changing the world. One game at a time. G5 - DP Engineering continues to strive for the exceptional design, combined with the standards of todays players. DPs years of experience in craftsmanship & intricate design brings forth a high quality marker, loaded with features such as the Stinger Frame, Wave Trigger, Subsonic Bolt Engine, & Riptide Regulator. DP is proud to proclaim the intricacy in design, simplified by Engineering, the all new G5. Staying ahead of the curve.\n\n*Low-Pressure Stinger Frame - The G5s Unibody Frame, Milled from high-grade Aluminum, houses the Inline reinforced Stinger Frame Low-Pressure system. High speed precision milling is used through the Stinger Frame to contain the Low-Pressure Inline system. The Stinger Frame includes a heavy-duty bracing structure for increased durability and is complimented with a high-performing lightweight design. Cutting edge technology, stamped with ingenuity.\n\n\n*Riptide Regulator - The Engineers of DP invigorates the Riptide Regulator. A superior design, the Riptide Regulators operation simulates the art of nature by directing the flow of pressure & combining as one controlled force. The High Pressure Regulator receives direct pressure from the Stinger Frame low-pressure system, allowing a fluid path with an extremely durable design. The components of the Riptide Regulator are very light, compact, & comprised of only a 7 stationary O-ring build.\n\n\n*Subsonic Bolt Engine - The G5 gun includes the Subsonic high performance bolt engine for increased performance and efficiency. A lower pressure operation achieves accurate & high-powered performance- Achieved by DPs Standard. The Ported vents on the G5 Bolt generates fluid motion during bolt-actuation, while creating a subsonic flow from the pressure chamber and through the vented ports to cushion paint while delivering a powerful trajectory. DPs Patent Dump-Valve Design has come a long way and continues prestigious quality with groundbreaking performance. \n\n*Innovative DP Style Clamping Feedneck - Dangerous Power Engineers continue to reinvent & improve technologies, such as our patent Clamping Feedneck & is now loaded with new features! Cushioned locking-mechanism helps decrease Lever-Wear while providing a firm hold. The improved Milled lock-nut design, ensuring a secure loader fit from the Snap to Finish.\n\n*Wave Trigger - The Dangerous Power G5 includes the Innovative Wave Trigger and is fully milled & constructed with high-precise dual bearings & critical pivoting motion to replicate fluid-motion with extreme comfort. The breakaway magnet is assisted with a compression spring, fit for high performance. The Wave Trigger allows fine tuning for increased trigger sensitivity on a 3-Axis adjustment plane. This adjustable plane also grants a, Zero side play for extreme comfort & high performance. \n" + }, + ".casual_clothing.mens_clothing.tshirts.matix_t_shirts" : { + "meta_keywords" : "Matix T Shirts,Matix shirts,free shipping,Matix TShirt", + "meta_description" : "Matix T Shirts - Zephyr carries a complete line of Matix Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Matix T shirt Today", + "page_title" : "Matix T Shirts at Zephyr", + "head_title" : "Matix T Shirts | Matix Shirts | Matix Tshirts" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_kash_sunglasses" : { + "meta_description" : "Spy Optics Kash Sunglasses - Zephyr Sports carries a complete line of Kash Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Kash Sun Glasses Online Today.", + "page_title" : "Spy Optics Kash Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Kash Sunglasses | Kash Spy Sunglasses Free Shipping | Buy Spy Kash Sun Glasses" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_touchstone_sunglasses" : { + "meta_description" : "Smith Optics Toughstone Sunglasses - Zephyr Sports carries a complete line of Toughstone Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Toughstone Sun Glasses Online Today.", + "page_title" : "Smith Optics Toughstone Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Toughstone Sunglasses | Toughstone Smith Sunglasses Free Shipping | Buy Smith Toughstone Sun Glasses" + }, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_trader_one_sunglasses" : {}, + ".2clearance.clearance_jerseys___apparel.clearance_gloves" : { + "head_title" : "Sale Paintball Gloves | Clearance Paintball Gloves | Paintball Gloves Sale" + }, + ".casual_clothing.womens_clothing.ladies_sweatshirts.dakine_ladies_sweatshirts" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.tokyo_marui_airsoft_guns" : {}, + ".apparel.head_bands_and_wraps.der_der_head_bands___wraps" : {}, + ".casual_clothing.womens_clothing.ladies_sweatshirts.eclipse_sweatshirts" : {}, + ".1historical_products.sunglasses" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_helmets" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markers.planet_eclipse_ego_paintball_guns" : { + "meta_keywords" : "Planet Eclipse Ego, Eclipse Ego Paintball Gun, planet eclipse, ego paintball guns, Eclipse Ego Paintball Marker, Eclipse Etek Gun, Eclipse Etek2 Paintball Gear, Cheap Ego Paintball Guns, eclispe Etha,etha paintball gun", + "meta_description" : "Eclipse Paintball Ego Guns - The Ego is the best tournament Paintball Gun in the world. Eclipse Etha is the perfect entry level tournamen gun. Lightweight and efficient, you need an Eclipse Ego Gun to compete at your local Paintball Tournament. In 2009 Eclipse released the Geo. The ultimate in closed bolt operation", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.planet_eclipse_package_specials/", + "description" : "Planet Eclipse brings some tough choices for it's 2014 Line of Guns. Eclipse's Entry level marker, the Etha is a rock solid marker for less $350.\n\n\n\nWant to be the TopGun on your tournament team? A Planet Eclipse EGO LV1 or thenew Geo3.1 will put that power in your hands. Zephyr Paintball.com is your source for all things Planet Eclipse Paintball!", + "banner1" : "banners/categories/guns/eclipse_banner.jpg", + "htmlvids" : "", + "head_title" : "Planet Eclipse Ego | Planet Eclipse Etha | Ego GEO Paintball Guns", + "page_title" : "Buy Planet Eclipse Ego Online On Sale Now", + "sortby_var" : "Eclipse Gun Type" + }, + ".snowboard_gear.face_and_neck" : {}, + ".1historical_products.fitness" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_jupiter_sunglasses" : { + "meta_description" : "Oakley Jupiter LX Sunglasses - Buy your Jupiter LX Oakley Sunglasses -Oakley Jupiter LXAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Jupiter LX Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Jupiter LX Sunglasses | Jupiter LX Oakley Sunglasses -Oakley Jupiter LX" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_banyans_sunglasses" : { + "meta_description" : "Maui Jim Banyans Sunglasses - Zephyr Sports carries a complete line of Maui Jim Banyans Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Banyans Online Today.", + "page_title" : "Maui Jim Banyans Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Banyans Sunglasses | Maui Jim Banyans Sun Glasses | Sunglasses Maui Jim Banyans" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_murf_watches" : {}, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_geo__paintball_guns" : { + "meta_description" : "Eclipse Geo + - Buy your Planet Eclipse Geo+ Paintball Gun Online at Zephyr Paintball for Less today. Free Shipping on Eclipse Ego Geo+ Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Eclipse Geo + Online On Sale Now", + "head_title" : "Eclipse Geo +| Planet Eclipse Geo+ Paintball Gun | Eclipse Ego Geo+" + }, + ".shop_by_brand.plan_b" : { + "top_description2" : "=Plan B, Always have a backup=\n\nPlan A doesn't always work out. Maybe you weren't able to conquer that 12 set with the finesse you wanted to, but you should always have a plan B just in case. Plan B skate has been around since 1991 and was founded by pro skaters Mike Ternasky, Jackson Kontzer, and Gabriel Torres. Today, Plan B skateboards is the birthplace of many fine products from skate decks and wheels to clothing. Try Plan B skateboards today, choose from our wide selection below and remember to always have a Plan B.\n\n", + "head_title" : "Plan B Skateboards | Plan B Skate | PlanB Skateboards", + "description" : "=Plan B, Always have a backup.=\n\n==History==\nThe Plan B Skateboarding team was founded in 1991 by Mike Ternasky, Jackson Kontzer, and Gabriel Torres. In 1994, Mike Ternasky was killed in a car accident, leaving the ownership of the company in the hands of Danny Way and Colin McKay, and Michael Ternasky's wife who temporarily shelved the company and the team in 1998. In 2005, with the financial backing of Syndrome Distribution, Way and McKay reformed Plan B Skateboards, maintaining their roles as team co-owners as well as professional skaters. On March 5, 2010 Billabong Int. Announced that Plan B skateboards will be under a 10 year contract that will force the company to work out of Irvine CA. \n\n==Plan B skateboard decks==\nPlan B offers a wide away of boards for a wide array of riders. You won't see more sleek and stylish boards on the market today. These boards are made to pop, grind, flip and shred. Check out the P2, a board reenforced with Kevlar and Maple veneer. Or maybe you want a lighter board like the Prolite series, which is lighter and thinner, but strong and offers a great pop. \n\n==Plan B Prospec wheels==\nThis formula of urethane,also known as a professional superthane formula, features many skateboard experience enhancing innovations. \n\nPro spec features include:\n* Zero Flatspot Superthane Formula\n* 100% Guarantee backed by warranty\n* Molded aerodynamic patters on side wall. \n* Unique and premium packaging\n* Plan B pro rider Brandings\n\n\n" + }, + ".casual_clothing.womens_clothing.ladies_sandals" : {}, + ".3packagespecials.tippmann_packages.tippmann_crossover_paintball_gun_packages" : { + "head_title" : "Tippmann Crossover Paintball Packages | Tippmann Crossover Paintball Gun Packages" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_manual_watches" : { + "meta_keywords" : "Nixon watches,nixon Manual watch,nixon watch,nixon Manual chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Manual Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Manual Chrono Watches", + "head_title" : "Nixon Manual Watches | Nixon Manual Chrono Watch | Nixon 5130" + }, + ".markers.empire_axe_paintball_guns.empire_axe_paintball_guns" : { + "meta_keywords" : "Empire AXE Paintball Gun,Empire AXE Marker,AXE Empire Paintball Guns,paintball guns,paint ball guns,empire,empire paintball,paintball marker,", + "meta_description" : "AXE Empire Paintball Guns - Empire Axe Paintball Guns are Empire Paintballs latest and greatest paintball gun yet! Zephyr Paintball carries the Empire Axe Paintball Guns, Empire Axe Upgrades and more! Pick up your paintball game with the Axe Paintball Gun from Empire!", + "top_description2" : "==Empire AXE Paintball Marker==\n\nWhat do you need to cut through a forest of opposition...the AXE! The new Empire AXE is a Mini on steroids; bigger, badder and willing to punish opponents. The new shape and extended grip frame give you a comfortable firing position for all day play. The Empire Relay On/Off Regulator ASA makes air bottle removal using the lever, quick and easy. The unique push-button, tool-less bolt removal system makes maintaining the AXE simple, at the end of the day. All that was great in the Mini has been carried forward into a new design. The proven Mini break-beam eye system and electronics, power this marker to ultra fast firing that is gentle on paint. Wield the AXE, the newest paintball gun from Empire and cut down everyone in your way.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/empire_axe_header", + "description" : "The Empire Axe has taken the tournament paintball scene by storm. Never before has a sub $500 gun been able to compete and win on pro tournaments. The Empire Axe is more than just a big invert mini. The features on the Empire axe include a gas through grip frae for an easy hose free grip. No more macro line to get in your way. Bolt removal on the Empire axe is insanely easy with just the push of a button and a turn. The adjustable magnetic trigger on the empire axe paintball gun allows you to adjust pre/post travel and is ultra smooth with stock ball bearings. Empire Relay Push level on/off asa with built in regulator on the empire axe makes it insanely easy taking your tank on and off. No more nightmares like the mini trying to put on your tank or remove it when gassed up. The Empire Relay On/Off is also available as an upgrade for the Invert Mini. As expected, the empire axe includes a fully functional tournament board including Semi, PSP, NPPL, NXL, and millenium Modes. Remember the axe tucks thr w board nicely into the front grip. The Empire axes comes stock with a 12\" autococker threaded barrel. If your in the market for a tournament level paintball gun and don't want to spend a fortune, take a look at the empire axe, if it's good enough for pros to win with it will be fine for you. Spend that extra money on playing more often and learning the game and you won't be dissapointed.\n\n\n=Empire AXE Features:=\n* Unique Push Button Bolt Removal System For Easy Maintenance\n* Empire Relay Regulator/ASA with ON/OFF Lever Makes Tank Removal a Breeze\n* Extended Grip Frame and New Grip for Increased Comfort\n* Magnet Returned Bearing Trigger Offers Smooth Firing Action\n* Accurate, Lightweight, Aluminum Barrel Hits Your Target\n* Integrated Break Beam Anti-Chop Eyes Eliminates Chopped Balls\n* Outstanding Velocity Consistency Offers Performance You can Depend On\n* Low Pressure Operation is Gentle on Paint\n* Multiple Adjustable Firing Modes (Semi, PSP Ramping, NXL, & Millennium Ramping)\n* Patented Proprietary Slipstream Solenoid Allows For Fast Firing\n* Through Grip Air Transfer Means No Hoses to Crimp or Break8\n* Clamping Feedneck- No Tools to Mount the Loader\n", + "page_title" : "Empire AXE Paintball Guns Ship Free at Zephyr Paintball", + "head_title" : "Empire AXE Paintball Gun | Empire AXE Marker | AXE Empire Paintball Guns" + }, + ".casual_clothing.youth_clothing.youth_beanies.neff_youth_beanies" : {}, + ".loaders.gi_sportz_paintball_loaders" : { + "htmlvids" : "", + "top_description2" : "== Pulse RDR Loader ==\nYou may have seen some leaked images of the GISportz new loader, the Pulse RDR on PBNation or other forums around the net. GISportz isn't saying much yet, but they have confirmed that it will have a built in Chrono, Shot Counter, and a BPS counter all in one, along with \"Some other goodies...\" yet to be announced. This is going to be a sweet loader with some amazing features from GISportz. Pulse RDR Loaders and Accessories are available for Pre-Order ONLY. We expect to begin shipping in Early December. Payment will be processed at time of purchase and will reserve your hopper for our first shipment.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/pulse_rdr_hopper_header.jpg", + "description" : "= Patent Pending Interactive RDR Technology =\nThe Pulse RDR (Radar) unit tracks the BPS, FPS, and Total Balls\ndriven by the force feed system displayed accurately on the bright\nOLED screen along with remaining battery life making it easy to read\nin all light conditions. The Display can be changed to fit the needs\nof the player.\n\n\n= Patented Removable Tray and Drive System =\nWith the push of a button, the patented removable tray containing\nthe high speed drive system, batteries, and Revolutionary Radar\nunit can be ejected from the outer shell allowing ease of cleaning\nand maintenance.\n\n\n= Push Button Solid State Electronics =\nThe three button interactive electronics allow the player to customize\nthe screen and settings of the motor. One touch reverse button allows\nthe player to reverse the motor with the touch of the button if a jam\noccurs. The Solid State electronics make the system more durable and\nless susceptible to malfunction due to bouncing and diving.\n\n\n= Over-molded Shell =\nThe over-molded outer shell gives the Pulse a Hot Look while providing\na bounce factor to extend the life of the player with loader deflections.\nThe over-molded shell will be available in multiple color combinations to\nfit each player’s unique style.\n\n\n= Interchangeable Duro Paddle System =\nThe Pulse Loader Systems offer interchangeable Paddles (sold separately)\nto cater to different types of paint and player needs.\n\n\n= 200 Round Capacity =\nThe Pulse has a capacity of 200 paintballs in its standard configuration\nwith the ability to step up to larger capacity with the purchase of the\naftermarket Ring Kit Patent Pending (sold separately)." + }, + ".casual_clothing.mens_clothing.shorts.dye_shorts" : { + "meta_description" : "Dye Shorts - Zephyr stocks a complete line of Dye Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Dye needs. ", + "page_title" : "Dye Shorts with Free Shipping at Zephyr", + "head_title" : "Dye Shorts | Dye Board Shorts" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.geo_3_paintball_guns" : {}, + ".airsystems.tankcovers.ninja_paintball_tank_covers" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_wit_watches" : { + "meta_keywords" : "Nixon watches,nixon Wit watch,nixon watch,nixon Wit chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Wit Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Wit Chrono Watches", + "head_title" : "Nixon Wit Watches | Nixon Wit Chrono Watch | Nixon 5130" + }, + ".airsoft.airsoft_bbs_ammo.20_gram" : { + "meta_keywords" : ".20 gram bb, airsoft bb, airsoft ammo", + "meta_description" : ".20 Gram Airsoft BBs. A high grade BB intended for use in more powerful AEG and airsoft guns. Able to withstand more power then .12 gram and travel greater distances. These BBs will keep their velocity and trajectory more accurate over reasonable distances. Still, depending on the power (velocity) for which your airsoft gun fires, you may want to consider a heavier BB. Intended for use in standard AEGs, pistols, and gas guns.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".12 G Airsoft BB's | .12 BBs for Airsoft | .12 Gram Airsoft BB" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_murena_sunglasses" : { + "meta_description" : "Spy Optics Murena Sunglasses - Zephyr Sports carries a complete line of Murena Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Murena Sun Glasses Online Today.", + "page_title" : "Spy Optics Murena Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Murena Sunglasses | Murena Spy Sunglasses Free Shipping | Buy Spy Murena Sun Glasses" + }, + ".casual_clothing.mens_clothing.tank_tops.alpinestars_tank_tops" : { + "meta_keywords" : "Alpinestars Tank Tops, alpinstars,Alpinestars Jerseys", + "meta_description" : "Alpinestars Tank Tops - Get you Alpinestars Jerseys at Zephyr Today. Low Prices, Free Shipping and easy returns We won't be beat.", + "page_title" : "Alpinestars Tank Tops & Jerseys Ship Free at Zephyr", + "head_title" : "Alpinestars Tank Tops | Alpine Stars Jerseys" + }, + ".casual_clothing.mens_clothing.sweatshirts.fox_sweatshirts" : { + "meta_description" : "Fox Sweatshirts - Buy your Fox Hoodies At Zephyr Sports for Less Today! We carry a complete line of Fox Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Fox Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Fox Sweatshirts | Fox Hoodies | Fox Hoody" + }, + ".airsystems.hosesfittings.tank_repair_" : {}, + ".airsystems.dropforwards.dangerous_power" : {}, + ".markerupgrades.proto_matrix_upgrades.proto_matrix_eye_upgrades" : {}, + ".casual_clothing.mens_clothing.belts.empire_belts" : { + "meta_keywords" : "Empire Belts,Empire Belt Buckle,Empire Belts,Empire webbed belt", + "meta_description" : "Empire Belts - We carry the complete line of Empire Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Empire Belts on Sale Now!", + "head_title" : "Empire Mens Belts | Aplinestars Belts" + }, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_john_brown_sunglasses" : {}, + ".shop_by_brand.virtue_paintball.virtue_spire" : { + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "top_description2" : "==Virtue Spire Paintball Line Coming Soon!!! We are looking at a mid-August release date, and will be taking pre-orders when we get a little closer!==\n\nThe Virtue Spire line is the culmination of all of the prior product development at Virtue Paintball. The technologies used from the Virtue upgrades and products over the past few years are reflected in this new Virtue product line, code-named \"Spire\".\n\n\nBased on the responses entered on the form linked below, Virtue will select 5 players to make up their Elite 5. As one of 5 Elite Sponsored players, you will receive one of the top secret Virtue products from the Spire line (as well as some other Virtue sponsorship items) on the day of it's launch.\n\n\nIn a sense, each of the Elite 5, will be the first players in the world to get their hands on a production model of the new product. Virtue will notify the Elite 5 in approximately 8 weeks. So if you think you have what it takes to be one of the Elite 5, click the link below, like Virtue on Facebook and apply!\n\n\n\n[[Apply Now!!]:url=http://www.facebook.com/VirtuePaintball/app_128953167177144]", + "zoovy:banner01" : "virtue/spire_banner.jpg" + }, + ".casual_clothing.mens_clothing.wallets.dgk_wallets" : { + "meta_description" : "DGK Wallets - Buy your DGK Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of DGK Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DGK Wallets on Sale @ Zephyr Sports", + "head_title" : "DGK Wallets | DGK Mens Wallets | DGK Wallet" + }, + ".harnessesbags.backpacks.alpinestars_bags_and_backpacks" : { + "meta_description" : "Alpinestars Backpacks - Buy your Alpinestars Bags At Zephyr Sports for Less Today! We carry a complete line of Alpinestars Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Alpinestars Backpacks & Bags Ship Free ", + "head_title" : "Alpinestars Backpacks | Alpinestars Bags |Alpinestars Luggage" + }, + ".casual_clothing.mens_clothing.tshirts.globe_t_shirts" : { + "meta_description" : "Globe Shirts - Buy your Globe T-shirts At Zephyr Sports for Less Today! We carry a complete line of Globe Clothing at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Globe Shirts On Sale & Free Shipping", + "head_title" : "Globe Shirts | Globe T-shirts | Globe Clothing" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_longboard_sunglasses" : { + "meta_description" : "Maui Jim Longboard Sunglasses - Zephyr Sports carries a complete line of Maui Jim Longboard Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Longboard Online Today.", + "page_title" : "Maui Jim Longboard Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Longboard Sunglasses | Maui Jim Longboard Sun Glasses | Sunglasses Maui Jim Longboard" + }, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_electra_paintball_gun_packages" : { + "meta_description" : "Spyder Electra Paintball Packages - Buy your Electra Spyder Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder Electra Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Electra Paintball Packages Online On Sale Now", + "head_title" : "Spyder Electra Paintball Packages | Electra Spyder Paintball Guns Kit | Spyder Electra Paintball Guns" + }, + ".casual_clothing.mens_clothing.beanies.brixton_beanies" : { + "meta_keywords" : "Brixton beanie,Brixton hat,Brixton beanies,Brixton caps,Brixton 686,Brixton headwear,Brixton cuff visor beanie,Brixton beanie hat,Brixton visor beanie,Brixton visor beanies", + "meta_description" : "Brixton Deanie - Surf style with Brixton Beanies available now at Zephyr Sports. Get your Brixton hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Brixton Beanies on Sale at Zephyr Today", + "head_title" : "Brixton Beanie | Brixton Hat | Brixton Beanies" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_optique_watches" : { + "meta_keywords" : "Nixon watches,nixon Optique watch,nixon watch,nixon Optique chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Optique Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Optique Chrono Watches", + "head_title" : "Nixon Optique Watches | Nixon Optique Chrono Watch | Nixon 5130" + }, + ".markers.dlx_technology" : { + "banner2" : "", + "meta_keywords" : "luxe paintball guns, dlx paintball guns, dlx luxe paintball guns, dlx technology, DLX technology Luxe", + "meta_description" : "Luxe Paintball Guns - Zephyr Paintball is your one stop shop for DLX Paintball Guns. Huge selection of DLX Luxe Paintball Guns are in stock and ready to ship for free today", + "description" : "The DLX Luxe can be classified as a high end paintball gun but really it’s in its own category– because of its stylish beauty and technological brilliance, it’s known as the luxury type. The Luxe was designed for tournament play, keeping in mind every player’s need for general maintenance, cleaning, and configuration while under little to no time. No hoses necessary, easy access to bolt and eyes with its tool-less design. Numerous innovations packed in a slim body make this gun quite something else. Let’s take a look at the inside – we find instead of a 9V Battery, the Luxe operates on a small lithium-polymer rechargeable battery that only takes about 40 minutes to charge. Once charged you can go through about 25,000 shots. The battery is much smaller than a 9V which helps reduce the size and weight of the Luxe. Programming a paintball gun has never been so easy and fun with its joystick inside the grip frame which is simple to operate for maximum control over all configuration modes. Did I mention this gun is a SHE? She talks to you. Sounds rather British to me but indeed she speaks to the user to get you through setting firing modes, rate of fire and dwell. She’s an expensive date but hey she knows paintball. The ease of maintenance is quite advanced. Pulling on a small lever at the rear of the gun is all that it takes to remove the bolt. The eye covers are magnetically enforced, making it simple to take off to clean the eyes. Inside the frame you will find well organized wiring that makes it simple to assemble/dissemble the frame from the body. The Luxe is quiet and air-efficient, with over 1400 shots from a 68ci 4500psi tank. Out of the box it comes with a freak barrel and stainless steal .693 insert for immediate use. Also included is lube, manual, barrel cover, allen keys, charger, spare screws & o-rings, spare battery pack and a mini rail (if ASA is needed). \n\n\n\n\nZephyr carries colored accent kits to replace your Eye Covers, Trigger, Feedneck Lever, Barrel Back, On/Off Knob & Power Core Quick Strip Latch. [[Click Here]:url=http://www.zephyrpaintball.com/category/markerupgrades.dlx___luxe_upgrades/] to check out all the different colors available to give your Luxe a makeover", + "banner1" : "banners/categories/dlx_luxe_header_001.jpg", + "htmlvids" : "", + "page_title" : "Buy Luxe Paintball Guns Online On Sale Now", + "head_title" : "Luxe Paintball Guns | DLX Paintball Guns | DLX Luxe Paintball Guns" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_honolulu_sunglasses" : { + "meta_description" : "Maui Jim Honolulu Sunglasses - Zephyr Sports carries a complete line of Maui Jim Honolulu Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Honolulu Online Today.", + "page_title" : "Maui Jim Honolulu Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Honolulu Sunglasses | Maui Jim Honolulu Sun Glasses | Sunglasses Maui Jim Honolulu" + }, + ".airsoft.airsoft_bbs_ammo.king_arms_airsoft_bbs" : { + "meta_description" : "King Arms Airsoft BB - Zephyr stocks a complete selection of high end King Arms Airsoft ammo. Spend the extra few bucks for quality King Arms BBs and save yourself a bunch of headaches down the road. Zephyr Sports offrers free shipping on Airsoft Gear on orders over $75", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 King Arms Airsoft Bio BBs | .25 Gram King Arms Airsoft Pellets | .20 G Biodegradeable Ammo for Airsoft Guns" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_tron_sunglasses" : { + "meta_keywords" : "Spy Tron sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Tron Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy optic eyewear with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Tron Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Tron Sunglasses | Spy Optics Tron Sunglasses | Spy Tron Sunglasses Black" + }, + ".casual_clothing.mens_clothing.sweatshirts.young___reckless_sweatshirts" : {}, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels" : { + "meta_keywords" : "smart parts freak barrel, smart parts barrels, freak barrel kit, sp freak kit, smart parts paintball barrels, freak kit, freak barrel system, smart parts progressive barrel, freak barrel back, freak barrel tip, freak inserts, stainless inserts, complete freak kit", + "meta_description" : "Smart parts are known for their extremely accurate freak barrel system. The Freak barrel backs are available in many different threads while the tips are made in different lengths. These barrels use aluminum insert sleeves that precisely match up to the users paint for a clean accurate shot!", + "page_title" : "Buy Smart Parts Freak Barrel - Smart Parts Paintball Barrels - Freak Barrel Kit Online On Sale Now", + "head_title" : "Smart Parts Freak Barrel - Smart Parts Paintball Barrels - Freak Barrel Kit" + }, + ".casual_clothing.mens_clothing.shorts.famous_stars_and_straps_shorts" : { + "meta_description" : "Famous Shorts - Zephyr stocks a complete line of Famous Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Famous needs. ", + "page_title" : "Famous Shorts with Free Shipping at Zephyr", + "head_title" : "Famous Shorts | Famous Board Shorts" + }, + ".airsoft.airsoft_guns.desert_eagle_airsoft_guns" : { + "meta_description" : "Desert Eagle Airsoft Pistol - Buy your Desert Eagle Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of Desert Eagle 44 Magnum Airsoft at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Desert Eagle Airsoft Pistol On Sale & Free Shipping", + "head_title" : "Desert Eagle Airsoft Pistol | Desert Eagle Airsoft Guns | Desert Eagle 44 Magnum Airsoft", + "description" : "" + }, + ".markerupgrades.us_army_upgrades.factory_repair_parts" : {}, + ".paintball.paintball_guns.kingman_spyder_paintball_guns" : {}, + ".001a_zephyr_paintball_sports_promotions_deals_sales" : { + "banner9" : "", + "meta_keywords" : "Zephyr, Paintball, Zephyr Paintball, Paintball Deal, Paintball Deals, Paintball Sales, Paintball Sale, Paintball Discounts Discount, Paintball Coupons, Paintball Coupon, Paintball Promos, Paintball Promotions ", + "banner8_link" : "/category/001a_zephyr_paintball_sports_promotions_deals_sales.proto_goggles___free_game_timer/", + "banner6_link" : "/category/001a_zephyr_paintball_sports_promotions_deals_sales.t9_marker___conversion_kit/", + "banner12_link" : "", + "banner11" : "", + "banner3" : "", + "banner12" : "", + "banner7" : "", + "banner4_link" : "", + "banner5_link" : "", + "banner9_link" : "", + "banner4" : "", + "banner11_link" : "", + "banner5" : "", + "banner1_link" : "/category/markers.protopaintballguns.proto_slg_paintball_guns/", + "banner2" : "banners/categories/vlocity_free_shell_header", + "banner6" : "banners/categories/t9_conversionkit_discount_header", + "banner2_link" : "/category/001a_zephyr_paintball_sports_promotions_deals_sales.viewloader_vlocity___free_shell/", + "banner7_link" : "", + "banner10" : "", + "banner1" : "banners/categories/slg_header_002", + "banner3_link" : "", + "banner8" : "banners/categories/prot_axis_timer_002", + "banner10_link" : "" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.proto_reflex_rail_paintball_guns" : {}, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_variable_power_scopes.leapers_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".loaders.extreme_rage_paintball_hoppers" : { + "meta_keywords" : "extreme rage hopper, extreme rage loader, er hopper, er loader, extreme paintball loader, overdrive hopper, overdrive loader, overdrive paintball loader, extreme rage overdrive", + "meta_description" : "Extreme Rage Hoppers - Buy your Extreme Rage Loader Online at Zephyr Paintball for Less today. Free Shipping on Overdrive Paintball Loader Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Extreme Rage Hoppers Online On Sale Now", + "head_title" : "Extreme Rage Hoppers | Extreme Rage Loader | Overdrive Paintball Loader" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.spitfire_youth_sweatshirts" : {}, + ".casual_clothing.z_shoes_and_footwear.slippers" : {}, + ".casual_clothing.mens_clothing.sweatshirts.srh_sweatshirts" : { + "meta_description" : "SRH Sweatshirts - Buy your SRH Hoodies At Zephyr Sports for Less Today! We carry a complete line of SRH Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "SRH Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "SRH Sweatshirts | SRH Hoodies | SRH Hoody" + }, + ".airsoft.shop_by_brand.tenergy" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Tenergy batteries | Tenergy | Tenergy rechargable batteries" + }, + ".paintball.paintball_guns.proto_paintball_guns.proto_reflex_rail_paintball_guns" : {}, + ".casual_clothing.youth_clothing.youth_t_shirts.enjoi_youth_t_shirts" : {}, + ".paintballs.empire_paintballs" : {}, + ".2clearance.mens_clothing.t_shirts" : { + "head_title" : "Sale T Shirts | Clearance T Shirts" + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_polarized_sunglasses" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4141_venkman_sunglasses" : { + "meta_description" : "Arnette Venkman Sunglasses - Zephyr Sports carries a complete line of Venkman Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Venkman Sun Glasses Online Today.", + "page_title" : "Arnette Venkman Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Venkman Sunglasses | Venkman Arnette Sunglasses | Arnette Venkman Sun Glasses" + }, + ".markerupgrades.proto_matrix_rail_upgrades.pmr_eye_upgrades" : {}, + ".loaders.hopper_accesories.empire_hopper_accesories.empire_back_plates" : {}, + "$cheap_kits" : {}, + ".barrels.barrels_by_manufacturer.dye_paintball_barrels.complete_barrels" : { + "meta_keywords" : "dye boomstick,complete dye barrel,carbon fiber boomstick,boom stick,dye autococker barrel", + "meta_description" : "Dye Carbon Fiber Boomstick - Complete Dye Paintball Barrels available at Zephyr Paintball. Get you Dye Boomstick from the Leader in Paintball. Dye Barrels are the ultimate tournament Upgrade and will SHIP FREE at Zephyr", + "page_title" : "Buy Dye Boomsticks Online On Sale Now", + "head_title" : "Dye Boomstick | Carbon Fiber Boomstick | Dye Barrels" + }, + ".paintballs.tiberius_arms_paintballs" : {}, + ".markerupgrades.smartparts" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts.oakley_nose_and_ear_pieces" : { + "meta_description" : "Oakley Replacement Parts - Zephyr Sports carries a complete line of Oakley Nose Pieces At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Ear Pieces Online Today.", + "page_title" : "Oakley Replacement Parts On Sale Free Shipping", + "head_title" : "Oakley Replacement Parts | Oakley Nose Pieces | Oakley Ear Pieces" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.metal_mulisha_yout_t_shirts" : {}, + ".goggles.proto.proto_el_paintball_goggles" : { + "meta_keywords" : "proto el,proto el mask,dye proto el,proto el paintball goggles, proto el paintball mask", + "meta_description" : "Proto El - Proto El Paintball Goggles are the Entry Level Paintball Mask from Proto Paintball. Starting at 29.95, the Proto EL Mask is one of the best entry level masks in the paintball goggle market. Plus you can easily upgrade your mask to thermal performance with any of the Proto Upgrade Lenses we sell", + "top_description" : "The Proto Switch EL Goggle System has the same great features as the Proto FS system, but is slightly different in its design. The Proto EL Paintball Mask system comes standard with a solid one-piece facemask and a single pane fog resistant lens. Additionally, the single pane tirodial lens is treated with an exterior hard coat for abrasion resistance. The Proto Switch EL system the perfect entry level paintball mask and is available in Black and Woodland Camo.", + "page_title" : "Buy Proto EL Online On Sale Now", + "head_title" : "Proto EL | Proto EL Paintball Goggles | Proto EL Mask" + }, + ".2clearance.paintball_clearance_gear.clearance_upgrades.clearance_drop_forwards___asa_s" : {}, + ".shop_by_brand.alien_paintball" : {}, + ".markers.protopaintballguns" : { + "meta_keywords" : "Proto Paintball Guns, Cheap Proto Paintball Markers, Proto Paintball Gear, Proto SLG, Proto Matrix Rail, PMR Paintball Gun, Proto Paintball Supplies, proto matrix guns, PM9, PM8, PM7, Matrix guns", + "meta_description" : "Proto Paintball guns - From the Proto SLG to the Proto Matrix Rail or the Proto Reflex Rail Paintball Gun, Proto has it all at a great price. Cheap Proto Paintball gear available at Zephyr", + "top_description" : "Proto Paintball is a leading designer of top quality paintball gear. Sister company to Dye Precision Paintball, Proto has really taken on its own identity in recent years! Since the early 2000's, Proto Paintball has been turning out tournament grade paintball markers at great prices. Proto Matrix Rail Paintball guns are competitive markers that won't break the bank! \nProto Rail Paintball Guns offer a host of features that won't let you down in the heat of the battle! Buy Proto Paintball Guns today and dominate tomorrow!", + "prodlist1" : "&FORMAT=DEFAULT&SRC=", + "description" : "==2011 Proto Rail==\n\nTaking over the field, the Proto Rail is your stepping stone to greatness. High-end performance in a durable and reliable setup, the Proto Rail is for the serious competitor. Featuring Boost Forward Technology, giving you a cushioned push on the ball and delayed bolt speed for increased air efficiency and high rate of fire.\n\nAll new 3-D milling, color coded seals for simplified maintenance, and a host of other features make the Rail the gun of choice. The durable Rail solenoid features consistent airflow, and with a dwell of 40 milliseconds, you get super fast cycle speeds. The small, light Hyper3 In-Line Air Regulator comes standard. The Hyper3 regulator provides high flow and smooth velocity adjustment, with non-slip grip rings. The ultimate in ergonomic comfort, the Ultralite 45 Frame with fully adjustable trigger, comes standard on the Rail. The solid construction consists of an aluminum body, bolt, Ultralite 45 Frame and trigger. We've designed the Rail with the goal of providing you with top-level performance at a reasonable price. Comes with a durable zippered gun case, parts kit, Dye Slick Lube, and 9-volt battery to keep your paintball gun of choice at its peak level. \n\n\n==2011 Proto REFLEX Rail==\n\nHigh-end performance in a durable and reliable setup. The Proto Reflex Rail is for the serious competitor, featuring Boost Forward Technology, giving you a cushioned push on the ball and delayed bolt speed for increased air efficiency and high rate of fire. REDESIGNED FOR 2011 the all-new 3-D milling, color coded seals for simplified maintenance, and a host of other features make the 2011 Reflex Rail the gun of choice.\n\nThe durable Reflex Rail solenoid features consistent airflow, and with a dwell of 18 milliseconds, you get super fast cycle speeds. The small, light Hyper3 In-Line Air Regulator comes standard. The Hyper3 regulator provides high flow and smooth velocity adjustment, with non-slip grip rings. The ultimate in ergonomic comfort, the Ultralite Frame with fully adjustable trigger, comes standard on the Rail. The solid construction consists of an aluminum body, bolt, Ultralite Frame and trigger. We've designed the Rail with the goal of providing you with top-level performance at a reasonable price.\n\nThe 2011 Proto Reflex Rail Paintball Gun comes with a durable zippered gun case, parts kit, Dye Slick Lube, and 9-volt battery to keep your paintball gun of choice at its peak level. \n\n\n\n==2010 Proto PMR Paintball Gun==\n\nThe PMR2010 Features Boost Forward Technology, giving you a cushioned push on the ball and delayed bolt speed for increased air efficiency and high rate of fire.All new 3-D milling, color coded seals for simplified maintenance, and a host of other features make the 2010 Rail the gun of choice.The durable Rail solenoid features consistent airflow and with a dwell of 18 milliseconds, you will be able to shoot faster and more consistent than ever before. The small, light Hyper3 In-Line Air Regulator (Comes Standard)provides high flow and smooth velocity adjustment, with non-slip grip rings.The ultimate in ergonomic comfort, the solid construction consists of an aluminum body, bolt, Ultralite 45 Frame with fully adjustable trigger.Comes with a durable zippered gun case, parts kit, Dye Slick Lube, and 9-volt battery. \n\n\n==Proto 09 Ultralite Rail==\n\nUnequaled quality, meticulous engineering and impeccable design are just a few of the reasons why Proto is the first name in paintball. Redesigned for 2009, the Proto Rail solenoid features increased durability and air flow. Dye Precision also lowered the dwell from 25 to 18 milliseconds resulting in faster cycle speeds. The smaller, lighter Hyper3 In-Line Air Regulator comes standard. This new regulator provides higher flow, more consistency, better ergonomic grip and smoother velocity adjustment. The new solenoid doubles the air flow through the marker and makes it more reliable on the field. The solid construction consists of an aluminum body and bolt, and Ultralite 45 frame and trigger. Dye designed the Proto Rail with the goal of providing you with tournament grade performance at a reasonable price. \n\n", + "banner1" : "banners/categories/guns/proto_banner.jpg", + "page_title" : "Buy Proto Paintball Guns Online On Sale Now", + "head_title" : "Proto Rail Paintball Guns | Cheap Proto Paintball Markers | Proto rEFLEX rAIL" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.1-search_by_size.3-large" : {}, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_variable_power_scopes.nc_star_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.grenade_beanies" : { + "meta_keywords" : "Grenade beanie,Grenade hat,Grenade beanies,Grenade caps,Grenade 686,Grenade headwear,Grenade cuff visor beanie,Grenade beanie hat,Grenade visor beanie,Grenade visor beanies", + "meta_description" : "Grenade Deanie - Surf style with Grenade Beanies available now at Zephyr Sports. Get your Grenade hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Grenade Beanies on Sale at Zephyr Today", + "head_title" : "Grenade Beanie | Grenade Hat | Grenade Beanies" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.airsoft_sport_games" : {}, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_first_base_glove" : { + "head_title" : "Rawlings First Base Glove | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".harnessesbags.packs___harnesses.genx_vests___harnesses" : { + "meta_keywords" : "genx vest,genx harness,genx paintball harness,genx pod pack, pod holder,3+4,4+1,2+1,6+1,5+4,4+3,paintball harness", + "meta_description" : "Genx Tactical Vests - Buy your Genx Paintball Harnesses Online at Zephyr Paintball for Less today. Free Shipping on Genx Harness Trust Zephyr for all your Paintball Needs", + "top_description" : "Genx makes some of the most affordable entry level paintball harnesses on the market. From your standard 4+1 and 6+1 to 3+4 and 4 and 5 pod harnesses. A Genx Harness has features of a higher end harness for alot less. When your looking for value, Genx Harnesses have you covered.", + "page_title" : "Buy Genx Tactical Vest Harness Online On Sale Now", + "head_title" : "Genx Tactical Vests | Genx Paintball Harness | Genx Harness" + }, + ".harnessesbags.backpacks.matix_backpacks_and_bags" : {}, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_profile_polarized_sunglasses" : { + "meta_description" : "Suncloud Profile Polarized Sunglasses - Zephyr Sports carries a complete line of Profile Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Profile Sun Glasses Online Today.", + "page_title" : "Suncloud Profile Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Profile Polarized Sunglasses | Profile Suncloud Sunglasses Free Shipping | Buy Suncloud Profile Sun Glasses" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_kickstand_sunglasses" : { + "meta_keywords" : "Von Zipper Kickstand sunglasses,VZ Kickstand, Von Zipper polarized sunglasses,Von Zipper Kickstand,VZ Kickstand glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Kickstand Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Kickstand sunglasses now! For Von Zipper Kickstand glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Kickstand Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Kickstand Sunglasses | Von Zipper Kickstand Polarized Sunglasses" + }, + ".casual_clothing.mens_clothing.socks.volcom_socks" : { + "meta_description" : "Volcom Socks - Buy your Volcom Skate Socks Online At Zephyr Sports for Less Today! We carry a complete line of Volcom Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Volcom Mens Socks at Zephyr Sports", + "head_title" : "Volcom Socks | Volcom Skate Socks | Volcom Mens Socks" + }, + ".markers.kingmanspyder.spyder_hammer_7_pump_paintball_gun" : { + "htmlvids" : "", + "meta_description" : "Dye DAM Paintball Gun - just released! The Dye Assault Matrix brings tournament level Dye DM performance to the scenario market. The Dye Dam is capable of being mag or hopper fed and runs eithe .68 cal or first strike paintballs. ", + "top_description2" : "", + "page_title" : "Dye Dam the ultimate Scenario Paintball Gun", + "head_title" : "Dye DAM Paintball Gun | Dye Assualt Matrix Paintball Guns", + "description" : "==2013 DYE ASSAULT MATRIX==\n\nThe Dye Assault Matrix was built from the ground up to be the ultimate product for tactical players. We wanted to provide the industry with a stunning tactical marker that gives users the performance of a high-end tournament marker, as well as the aesthetics and features that tactical players need to thrive on the battlefield.\n\n\nThe DAM has the ability to switch from a Magazine Fed system to a Loader Fed system with the fl ip of a switch, it can seamlessly change firing modes (semi, three round burst, full auto), comes standard with Picatinny rails for accessorizing, a gas-through frame, an easily maintainable bolt with a quick release system and built in hyper regulator, clamping feedneck, competition-style single trigger frame, Dye Tactical Sticky Grips, and much more.\n\n\nThe Dye Assault Matrix delivers the perfect combination of performance and versatility, catering to all styles of play and giving users that edge on the scenario field that only Dye can provide. The weight of the DAM is 4.76 lbs without the clip.\n\n\n=Features:=\n==Mag Feed==\nThe DAM comes magazine feed ready. Ambidextrous magazine release for right and left handed users makes reloading a snap and allows you to keep an extremely low profile, even when reloading. All Dye magazines are First Strike round ready and waiting to deliver each shot just like a real firearm. Leave the accuracy-by-volume to the trigger monkeys and do it like the big boys. One shot, one kill.\n\n\n==On The Fly System==\nBe the most versatile player on the field with the all new OTF system. Combined with the rotating eye pipe gearing, this system allows the operator of the DAM unprecedented options for loading capabilities. With the slide of the OTF switch, the operator can seamlessly move from traditional hopper fed, to magazine fed loading, and back again at a moments notice. Use your shaped projectile rounds when you need precise shots and go back to regular paint when volume is necessary.\n\n\n==Quick Release Bolt==\nThe quick release bolt system is a feature on the DAM that incorporates magnets within the knurled back cap. These magnets allow for the back cap to extend and give you enough surface area to grip the bolt and unscrew it by hand. This makes maintenance of your bolt easier than ever before.\n\n\n==Inline Hyper Regulator==\nThe all new In-Line regulator is based on the proven Hyper line of regulators and improves on it with the easiest access and simplest break down of any gun Dye has made. With the Quick Release Bolt any operator can toollessly access their bolt and regulator in one simplified assembly. Now all parts that require standard maintenance are accessed with 2 turns. With velocity adjustment accessible through the back cap, we’ve moved the regulator out of the way for that real military look and operation.\n\n\n==Rotating Eyepipe==\nThe Eye Pipe, patent pending, internal design houses multiple critical systems that ensure worry free performance. The polycarbonate pipe shields the self-cleaning anti-chop eye system from dirt and broken paint, ensuring the eyes are always monitoring the breech and ball drop. The seamless pipe is wiped clean by the bolt tip o-ring on every cycle. The Eye Pipe system also eliminates miss feeds and double feeding. In addition it eliminates external eye plates and the potential of stripped or corroded eye plate mounting screws.\n\n\n==Fire Selector==\nWith the push of a button the DAM can switch from Semi Auto to Three Round Burst to Fully Automatic, or if you want to get fancy you can even program specific firing modes that cater to your style of play. All changes can be done with your gun fully assembled, even mid-game. A board lockout can be implemented to get you on the tournament field or any firing mode-restricted areas. Precision or volume, just a button away.\n\n\n==Removable Lockdown Clamping Feedneck==\nThe DAM comes standard with a feedneck Cover Plate that can replace the feedneck assembly giving the operator an unbroken top Picatinny Rail compatible with all standard military optics. Reduces your profile and gives your DAM the most realistic look and feel. It also comes with an adjustable cam lock feedneck allows you to securely lock you loader onto your gun without tools. DYE’s cam lock feed neck sits low and tight on the marker making sure your loader stays low profile with the rest of your gear.\n\n\n==Competition Grade Trigger==\nBased on a custom design by Youngblood himself, the DAM’s trigger incorporates vertical ridges and an extra wide face, used by top firearms competition shooters. This design ensures steady trigger feel even in the most adverse conditions with or without gloves. Customizable forward and backward travel with spring tension adjustment create the perfect pull.\n\n\n==Modular Rail Shroud==\nThe two interchangeable shroud sections and front cap allow the operator to reconfigure the DAM for any style of play. With all shroud sections installed, the DAM has over 2 Feet of standard Picatinny rails. All side and bottom rails are removable and interchangeable. Picatinny rails are standard for fire arms and will allow attachment of any standard optics, grips, etc.\n\n\n==Tactical Sticky Grips==\nWith even easier Toolless access to the battery and extra thick ergonomic design, this all new grip improves on every aspect of these top-of-their class grips." + }, + ".casual_clothing.mens_clothing.shorts.fox_racing_shorts.fox_racing_essex_shorts" : {}, + ".casual_clothing.mens_clothing.shirts.famous_stars_and_straps_shirts" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_riverside_sunglasses" : { + "meta_description" : "Smith Optics Riverside Sunglasses - Zephyr Sports carries a complete line of Riverside Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Riverside Sun Glasses Online Today.", + "page_title" : "Smith Optics Riverside Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Riverside Sunglasses | Riverside Smith Sunglasses Free Shipping | Buy Smith Riverside Sun Glasses" + }, + ".scenarioupgrades.tactical_boots" : { + "meta_keywords" : "military boots,airsoft boots,scenario boots", + "meta_description" : "Military Tactical Boots. Standard issued military grade boots; built to last and hold even under the most extreme conditions. An unbeatable value; choose from either nylon/canvas or cordura/leather. Cushioned soles and venting make these a comfortable boot especially during extended games. Choose from standard lace or speed-lace designs. ", + "page_title" : "Military Tactical Boots On Sale at Zephyr ", + "head_title" : "Military Boots | Tactical Boots | Airsoft Boots" + }, + ".markerupgrades.dye_dam_upgrades_and_accessories.dye_dam_stocks" : {}, + ".airsoft.airsoft_batteries___chargers.96v_airsoft_battery_packs" : { + "meta_description" : "9.6 Volt Rechargeable Airsoft Batteries available at Zephyr Sports. We Stock a complete line of Airsoft Batteries from all the top manufacturers", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "9.6V Airsoft Batteries | 9.6 Battery for Airsoft | Upgrade Replacement Airsoft Battery" + }, + ".shop_by_brand.kwc_airsoft" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.sig_sauer_spring_airsoft_guns" : { + "meta_description" : "Sig Sauer Airsoft Guns - Buy your Sig Sauer Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Sig Sauer Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Sig Sauer Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Sig Sauer Airsoft Guns | Sig Sauer Airsoft Rifles | Sig Sauer Spring Airsoft Guns" + }, + ".goggles.dye" : { + "meta_keywords" : "dye I4 paintball goggles,mask,Invision,Masks,i4,i3,thermal,antifog,dye i4", + "zs11_banner_wslideshow_slide1" : "ALT=%2420+Off+While+Supplies+Last%21&IMG=&LINK=%25SESSION%25%2fproduct%2fDYE%2d2030%2d40096001%2fDye%2dI4%2dThermal%2dPaintball%2dMask%2d%2d%2dDyeTree%2dAqua%2ehtml", + "zs11_banner_wslideshow_slide3" : "ALT=&IMG=&LINK=", + "page_title" : "Buy Dye I4 Paintball Goggles Online On Sale Now", + "zs11_banner_wslideshow_slide2" : "ALT=&IMG=&LINK=", + "banner2" : "", + "meta_description" : "Dye I4 Paintball Goggles - Dye Goggles and accessories on Sale. Best Prices Dye I4 masks and lenses at Zephyr. Free Shipping Huge Selection", + "top_description" : "2014 Dye I4 colors have been released. Be sure to check out the new bomber and ultralight colors for the I4 Mask", + "ad1" : "", + "banner02_link" : "", + "banner01_link" : "/category/goggles.1goggle_accesories.dye_goggle_accesories/?sortby=!zoovy:base_price", + "prodlist1_header" : "Dye Paintball Goggles", + "zoovy:banner01" : "banners/paintball/headers/goggleaccessories_header001.jpg", + "zoovy:banner02" : "", + "description" : "Dye has come out with a new mask, one that makes players realize they don't need to shell out for a clunky machine formed hunk of plastic anymore. The Dye i4 is sleek, low profile, and anatomical. It eliminates the mask from the game, causing no obstructions or loss of vision. With a quick change lens system, this aerodynamic mask protect your face without you even noticing.\n\n\n==Dye i4 Limited Edition:==\nThere's been a few runs of some limited edition colors, masks and styles done with these dye masks. The i4 black comes in a black and gold edition that has a 'black gold' lens with sick gold highlights to show off how much of a baller you are. A snakeskin textured white was also released with the limited edition black's alter ego, the limited edition white. The [[i4 white limited edition]:popup=/product/PB-DYE-I4WHTGOLD/] is the sexy alternative, with a clean white finish and gold trim that whispers class into the ears of all who gaze upon it. \n\n\n==When Less Mask is More:==\nThe Dye i4 mask is at the apex of face protection and functionality. Dye incorporated a highly anatomical fit into the design that makes the mask easy to wear for long periods of time and keeps all those sharp edges from making you look like a raccoon. With two layers of high grade foam, this mask is comfy! The anatomical design also creates a lower profile that matches the contours of your face, and a pair or replaceable flaps cover your ears. \n\n\nUnlike some masks, the Dye i4 will let you hear your team mates screaming about the guy coming up the snake before you get nailed. Large vents in the front of the mask let you scream back about the rush on the left (hopefully he has an i4 too or you might be down a man). The lens is amazing, originally made by Dye to keep the peripheral version of a Gazell (they have eyes on the side of their head), the human adaption keeps the unparalleled field of vision. A wide strap with 'tiger teeth' secures the mask to your face with a double set of buckles, easy to adjust on the field in case you eat dirt.\n\n\n==Rapid Lens Change System:==\nTook one to the lens? The next game is in 5 minutes? No problem. The i4 uses a quick lens change system so you can swap out or clean [[dye lenses]:popup=/category/goggles.1goggle_accesories.dye_goggle_accesories/] between games and on the fly. Dye has a ton of i4 lenses including clear, HD, rose, blue, yellow, smoke, mirror and mirror gold, all thermal. The mirror i4 lenses are Dye's Dyetanium series and provide tint a shade darker than their smoke lens. The Dye mirror lenses are almost completely opaque, letting the player you're bunkering see the horror in his own face. On some models, the Dye i4 comes stock with an [[i4 HD lens]:popup=/product/PB-DYE-LENSI4HD/] (high definition) that enhances the contrast. This lens ups your game by increasing the speed of your visual recognition, let you process targets and options faster. \n\n\n==i4 Colors and Styles:==\nFor all you player that want a 'pimp' mask for your 'gangsta' jersey, the Dye i4 comes in a variety of colors so you can mix and match just like your girlfriend. Liquid, Tiger, Cloth and flat textures are available, each adding a new 'flavah' to the mix. The colors change the accents of the mask, and lens mount of the mask with only the tiger and cloth series expanding the patterning onto the ear flaps. \n\n\nThe tiger series comes in orange, lime green and a grey. The cloth run with just a red and blue. The liquid series has been discontinued, but the flat set of colors is huge. Black, white, red, green, and blue are available for those players wanting a cleaner look. Matching the masks [[Dye jerseys]:popup=/category/apparel.jerseys.dyejerseys/] are rocking it this year, especially the new Dye 2012 jersey line that has the same Cloth and Tiger styles for your i4 masks. If you're going to get the jersey, of course you want the [[Dye Pants]:popup=/category/apparel.pants.dyepants/]. Released with the jerseys, the Dye 2012 pants complete your set of new threads with the Cloth or Tiger style. Get completely decked out with high quality Dye paintball gear!\n\n\n==i4 DyeCam:==\nSome love for all you scenario players out there, Dye made a whole mask just for you. The DyeCam i4 is in DyeCam (surprise!) with the only lower face protection that isn't black or white. Dye makes you feel even more special with a matching set of ear flaps, and strap tp complete the ensemble. This special edition i4 is preferable for desert camo, or your set of MultiCam (think we just lost the speedballers). Match your set of MultiCam or DyeCam with this awesome scenario paintball mask with all the benefits the PSP field players love.", + "banner2_link" : "", + "zs11_banner_wslideshow_slide5" : "ALT=&IMG=&LINK=", + "banner1" : "", + "htmlvids" : "
                                                                          \n\n
                                                                          \n
                                                                          \n\n\n\n\n
                                                                          \n\n
                                                                          ", + "head_title" : "Dye I4 Paintball Goggles | Dye Paintball Masks | Dye I4 Paintball Goggles" + }, + ".skateboard_gear.skateboard_longboards.sector_9_longboard_skateboards.sector_9_sidewinder_series_longboards" : {}, + ".skateboard_gear.skateboard_decks.1search_by_size.80__decks" : { + "meta_description" : "8.0\" Skateboards Decks - Zephyr Sports carries a complete line of 8.0 Skate Deck At the lowest prices on the web with free shipping and easy returns. Buy your Skate Deck 8.0 Online Today.", + "page_title" : "8.0\" Skateboards Decks On Sale Free Shipping", + "head_title" : "8.0\" Skateboards Decks |8.0 Skate Deck | Skate Deck 8.0" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.40" : {}, + ".loaders.hopper_accesories.viewloader_accesories" : { + "meta_keywords" : "Viewloader Loader, Viewloader Paintball Loader Hopper, Viewloader Loaders, Viewloader, Paintball Loader, Paintball Loader Hopper, Loader Hopper, Paintball Equipment, Paintball Supplies", + "meta_description" : "Viewloader Loader - With Viewloader paintball loader hoppers on sale at ZephyrPaintall, there is no better place to shop for paintball equipment.", + "page_title" : "Buy Viewloader Loader Online On Sale Now", + "head_title" : "Viewloader Loader | Viewloader Paintball Loader Hopper | Viewloader Loaders", + "page_head" : "Viewloader Loader - Viewloader Paintball Loader Hopper - Viewloader Loaders" + }, + ".markerupgrades.proto_matrix_rail_upgrades.proto_rail_triggers" : {}, + ".casual_clothing.mens_clothing.hats.enjoi_hats" : { + "meta_keywords" : "Enjoi Hats,Enjoi caps,Enjoi baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Enjoi Hats - Zephyr carries a complete line of Enjoi Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Enjoi", + "page_title" : "Enjoi Hats on Sale at Zephyr", + "head_title" : "Enjoi Hats | Enjoi Caps | Enjoi Baseball Hats" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_rushmore_sunglasses" : { + "meta_description" : "Arnette Rushmore Sunglasses - Zephyr Sports carries a complete line of Rushmore Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Rushmore Sun Glasses Online Today.", + "page_title" : "Arnette Rushmore Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Rushmore Sunglasses | Rushmore Arnette Sunglasses | Arnette Rushmore Sun Glasses" + }, + ".skateboard_gear.skateboard_bearings.pig_skateboard_bearings" : { + "meta_description" : "Pig Skate Bearings - Buy your Pig Skateboard Bearings At Zephyr Sports for Less Today! We carry a complete line of Pig Skate Board Bearings at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Pig Skate Bearings On Sale & Free Shipping", + "head_title" : "Pig Skate Bearings | Pig Skateboard Bearings | Pig Skate Board Bearings" + }, + ".skateboard_gear.skateboard_decks.alien_workshop_skateboard_decks" : { + "meta_keywords" : "alien workshop skateboards,alien workshop decks,Alien Skate decks,cheap skate decks,skateboarding equipment,skateboarding gear", + "meta_description" : "Alien Workshop Skateboards - Zephyr Sports is your Alien Workshop Headquarters! Alien workshop Decks, Complete Alien Workshop Skateboards, and much More! Choose from a grip of Alien Skate Decks, Cheap Skate Decks, and others; throw some other Skateboarding equipment on there like some Trucks, maybe some Bones Bearings and get ready to Ride! Zephyr Sports has all your Skateboarding gear!", + "head_title" : "Alien Workshop Skateboard | Alien Workshop Decks | Skateboard Decks" + }, + ".loaders.empire.empire_prophecy_z2_paintball_hopper_loader" : { + "meta_keywords" : "Paintball Loaders,Empire Prophecy Z2 Loader,Empire Paintball,paintball loader,paintball hopper,paint ball equipment,paint ball gear,paint ball hopper,paint ball hopper,prophecy z2,empire prophecy,", + "htmlvids" : "", + "meta_description" : "Empire Paintball Prophecy Z2 Hoppers | Step up your game with new paintball equipment from Empire! The empire prophecy paintball hopper has just been released with new colors! Prophecy z2 paintball hoppers hold 200 rounds and will not let you down! Paintball loaders are essential to your success on the field - Pick up the Empire Prophecy Paintball loader today and dominate!", + "top_description2" : "=Empire Prophecy Z2 Loader=\n\nEmpire Paintball Prophecy Z2 Hoppers | Step up your game with new paintball equipment from Empire! Prophecy Z2 paintball loaders hold 200 rounds in one of the sickest body styles available! The Prophecy Z2 Loader continually monitors drive force, rate of fire, and it automatically clears a jam before you even know about it. The Prophecy Z2 will have performs more proactive measures than any other loader ever created. For just a paintball loader, it has the most advanced, easiest to use feeding system ever designed. Made of super strong-reinforced composites combined with its ultra-lightweight design and low profile, the Z2 will supercharge every player's game. \n\nEven better.. NEW COLORS COMING SOON!", + "head_title" : "Paintball Loaders | Empire Prophecy Z2 Loader | Empire Paintball", + "banner02_link" : "/category/loaders.hopper_accesories.empire_hopper_accesories/", + "zoovy:banner02" : "banners/paintball/headers/hopperaccessories_header001" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_variable_power_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.1-g36_style_aeg_airsoft_guns" : { + "meta_description" : "G36 Airsoft Guns - Buy your H&K G36 At Zephyr Sports for Less Today! We carry a complete line of G36 AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy G36 Airsoft Guns On Sale & Free Shipping", + "head_title" : "G36 Airsoft Guns |H&K G36 |G36 AEG" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_jerseys" : {}, + ".barrels" : { + "top_html" : "", + "meta_keywords" : "Cheap Paintball Barrels, Paintball Gun Barrels, Paintball Barrel, Paintball Barrels, Discount Paintball Barrels, Paintball Marker Barrels, Discount Paintball Barrel, Paintball Barrel Store, Paintball Barrel Deals, Tippmann Barrel, Flatline Barrel, Spyder Barrel,Cheap Paintball Guns", + "ad3_link" : "/category/barrels.barrels_by_manufacturer.deadly_wind_paintball_barrels/", + "add3_link" : "/results.cgis?catalog=&keywords=sly+diesel&x=0&y=0", + "prodlist2_title" : "Featured Barrel Items", + "description2" : "

                                                                          ", + "ad2" : "banners/paintball/side_banners/custom_product_barrels_sidebanner.jpg", + "banner4" : "banners/sm_promo/sly_diesel_kit.png", + "3widead_title" : "Popular Barrel Brands", + "page_title" : "Buy Cheap Paintball Barrels Online On Sale Now", + "ad2_link" : "/category/barrels.barrels_by_manufacturer.custom_products_paintball_barrels/", + "add1_link" : "/category/barrels.barrels_by_manufacturer.dye_paintball_barrels/", + "banner2" : "banners/sm_promo/dye_ultralite_barrel.png", + "subcat1_header" : "Barrel Categories", + "meta_description" : "Need something different than that stock paintball barrel? Choose from our wide selection of Cheap paintball Gun barrels from titanium to carbon fiber. You are bound to find what you need in our barrels section.", + "top_description" : "", + "ad1" : "banners/paintball/side_banners/dye_ultralite_barrels_sidebanner.jpg", + "prodlist1_header" : "", + "description" : "\nZephyr Paintball has a complete line of Paintball barrels to satisfy your needs. Whether it's a cheap paintball barrel your looking for, or Tournament quality, we have what you need. Current Paintball Barrels include Tippmann, Proto, Dye, Smart Parts, Redz, J&J Performance, CMI, and more. An example of a great starter barrel would be the [[J&J Ceramic Barrel]:url=http://www.zephyrpaintball.com/category/barrels.barrels_by_manufacturer.j_j_paintball_barrels.j_j_ceramic_one_piece_barrels/]. This barrel has a ceramic coat inside that acts as a self cleaning mechanism if a ball is chopped. The Ceramic coat prevents paint from sticking inside the barrel. Just shoot a couple more and it will clean itself out. This starter barrel is available for multiple types of threads, like most of the barrels we carry give those thread options. We continue to add new products every week. If you don't see what you need, let us know and we'll get it. Be sure to check out our live chat for instant answers to your questions.", + "btn_title" : "Barrels By Thread", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "ad3" : "banners/paintball/side_banners/deadlywind_barrels_sidebanner.jpg", + "banner1" : "banners/09_headers/main_categories/barrels_001", + "htmlvids" : "

                                                                          ", + "ad1_link" : "/category/barrels.barrels_by_manufacturer.dye_paintball_barrels/", + "head_title" : "Cheap Paintball Barrels | Paintball Gun Barrels | Paintball Barrel", + "sortby_var" : "Barrel Thread", + "page_head" : "" + }, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_ruido_sunglasses" : {}, + ".barrels.barrels_by_manufacturer.j_j_paintball_barrels" : { + "meta_keywords" : "J&J paintball barrels, JJ ceramic Paintball barrels, ceramic paintball barrels, ceramic barrels, jj ceramic barrels, jj barrels,ceramic barrel", + "meta_description" : "J&J Ceramic Paintball Barrels - JJ Paintball Barrels are the ultimate entry level upgrade barrel. Ceramic Paintball Barrels are the easiest to clean during a game while still being affordable. Zephyr Carries the complete line of J&J Ceramic Barrels.", + "top_description2" : "There are few upgrades as easy and as fast as getting a J&J Ceramic barrel. Often the best and first upgrade to paintball guns, adding a ceramic barrel can do wonders to improve your accuracy and game. With a ceramic impregnated teflon coating these barrels can self clean on the field while eliminating friction between the ball and the barrel. Grab one of the most recommended first upgrades on the field today at Zephyr!", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/jjceramic_paintball_header.jpg", + "description" : "Upgrade your current paintball setup with J & J Ceramic Barrels!\nFrom an entry level 'rookie' to the most experienced player out there, everyone knows your barrel makes or breaks your day of paintball. Whether your paintball set-up lacks accuracy, style, or just sheer ability, J&J has you covered with their high performance, machine-precision, aluminum paintball barrels...\n\n\n==For The New Players:==\n\nFrom in the store to on the field one of the best first upgrades you can make without tinkering or breaking the bank is to upgrade from your stock barrel. Why use a ceramic? Because it is crazy light and aside from poking your team mates, you'll never know it was there (but check because playing paintball without a barrel is embarrassing). Improving the length and quality of your barrel will drastically improve your game and training by improving the accuracy and the consistency of the ball's flight path. Since hitting opposing players is kind of important in paintball. Between $30 and $40 these barrels are a steal, and the perfect first step toward pumping up your game.\n\n\n==Made To Outperform:==\n\nThe lightweight and accurate J&J Ceramic barrel is made from 6061 T6 aluminum then CNC machined to the highest quality standards in the industry. The ceramic coating and teflon impregnation reduces the friction rate to a minimum and actually self-cleans as you fire. With this special teflon coating, the broken paint cannot cling to the surface texture of the barrel, allowing you to clear your barrel with the next shot. The lack of friction in the barrel keeps your ball stable and reduces the drag that occurs as the ball leaves the barrel. With the ease and simplicity of a one piece JJ [[Ceramic barrel]:popup=/category/barrels.barrels_by_manufacturer.j_j_paintball_barrels.j_j_ceramic_one_piece_barrels/], it's a wonder why other players still run around with swabs sticking out of their gear. Leave the cleaning till after the game chump! Shoot straight through all your breaks with J&J!\n\n\nJ&J also produces a stellar 2-piece paintball barrel that offers the best of both worlds in paintball! In an even more accurate design, the [[J&J Full Tilt]:popup=/category/barrels.barrels_by_manufacturer.j_j_paintball_barrels.j_j_full_tilt_paintball_barrels/] Series offers improved ergonomics with its 2-piece application alongside that same friction-reduced, self-cleaning ceramic interior. \n\n\nThe J & J Ceramic Barrel upgrade is one of the most popular upgrades in the game. These barrels are available in sizes 12\",14\",16\" and 20\". The increase in length will give you an even more accurate and consistent shot. Available in most thread types (Tippmann 98, A5/X7, Autococker, Impulse/Ion, Phantom and Spyder) you can be assured these barrels will be compatible with your marker.", + "page_title" : "Buy J&J Paintball Cermaic Barrels On Sale Now", + "head_title" : "J&J Paintball Barrels | JJ ceramic Paintball Barrels | Ceramic Paintball Barrels", + "sortby_var" : "J&J Barrel Type" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_variable_power_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_variable_power_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Centerpoint scopes | Centerpoint rifle scopes | Centerpoint scopes review" + }, + ".airsoft.tactical_airsoft_gear.airsoft_iron_sights" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.sly_equipment_beanies" : { + "meta_keywords" : "Sly beanie,Sly hat,Sly beanies,Sly caps,Sly 686,Sly headwear,Sly cuff visor beanie,Sly beanie hat,Sly visor beanie,Sly visor beanies", + "meta_description" : "Sly Deanie - Surf style with Sly Beanies available now at Zephyr Sports. Get your Sly hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Sly Beanies on Sale at Zephyr Today", + "head_title" : "Sly Beanie | Sly Hat | Sly Beanies" + }, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns.omega" : { + "meta_description" : "BT Omega Paintball Guns - Buy your Empire BT Omega Online at Zephyr Paintball for Less today. Free Shipping on Omega Tactical Paintball Markers Trust Zephyr for all your Paintball Needs", + "top_description" : "==The new BT Omega Paintball Marker will take you into battle without breaking the bank!==\n\nThe rugged aluminum body will withstand heavy duty combat situations and provides increased performance and durability. The Omega will require little in terms of regular maintenance. Fully upgradeable, the Omega easily accepts numerous BT upgrades, such as the HALO powered Rip Clip,the BT1913 Barrel, the BT Clamp Elbow Kit and the Tactical Folding Stock. Carrying your marker out to battle has never been easier thanks to its secure carry handle. The Omega's permanent, fixed sight rail provides you a continuous lock on your opponents, thereby giving you the confidence needed to take them out of the game. Grab your gear, lock and load and hit the field running with the Omega today!", + "banner02_link" : "/category/3packagespecials.empire_paintball_packages.empire_bt.omega/", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001", + "description" : "=BT Omega Features=\n\n\n* Rugged Aluminum Body\n* Multi-Position Adjustable Stock\n* BT Rip Clip Compatible\n* Accepts CO2 or High Pressure Air Sources\n* Adjustable Velocity\n* Stainless Steel Braided Air Hose\n* Secure Carry Handle\n* Fixed Sight Rail\n* Removable Magazine with Tool Storage\n* Built-In Sling Attachments\n* Comes with O-rings and allen wrenches to help maintain your gun.\n", + "htmlvids" : "", + "page_title" : "Buy BT Omega Paintball Guns Online On Sale Now", + "head_title" : "BT Omega Paintball Guns | Empire BT Omega | Omega Tactical Paintball Markers" + }, + ".markers.dye_matrix_paintball_guns.dye_dm10_paintball_guns" : { + "meta_description" : "Dye 2010 Matrix Paintball Guns - Buy your Dye Dm10 Online at Zephyr Paintball for Less today. Free Shipping on DM 10 Paintball Marker Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye 2010 Matrix Paintball Guns Online On Sale Now", + "head_title" : "Dye 2010 Matrix Paintball Guns | Dye Dm10 | DM 10 Paintball Marker", + "description" : "The new Dye DM10 continues the tradition of being one of the lightest, smallest, fastest and certainly the most accurate of paintball markers in the world. Our one-piece Fuse bolt system operates at 145psi with a shorter flow path, resulting in a shorter overall length. The low operating pressure provides smooth operating performance with minimal shot bounce and noise. \n\nThe 2010 DM Series features a low-maintenance internal patent-pending Eye Pipe anti-chop sensing system that is self cleaning, providing trouble free high rates of fire. Durable and super-flexible detents offer supreme tenderness to the most brittle of paint. The Reach Trigger allows the triggers reach and rake to be fully adjusted by the user for ultimate individual ergonomic comfort. \n\nWeighing in at 1.9lbs, the Dye DM10 Series is lighter than it's predecessor the DM9. All of these innovations, coupled with new 3D body styling and standard features like the patent pending Ultralite frame, Ultralite Sticky3 grip, two piece 14\" Ultralite barrel, cam lock feed neck, and cast aluminum inset DYE logo, it's easy to see why the 2010 DM Series is The Choice of Champions.\n\n\n=Dye DM10 Paintball Gun Features=\n*Dye DM10 Ultralite Barrel - The industry standard for accuracy, the 2010 DM Series comes stock with the Ultralite 14 inch barrel.\n*Dye DM10 Fuse Bolt - The removable one-piece Fuse bolt system operates at 145psi with a shorter flow path resulting in better efficiency. Large front and rear bumpers used in the Fuse bolt, offer greater reliability and smooth shooting.\n*Dye DM10 Internal LPR - The miniature modular internal LPR provides more efficient shot consistency. It allows the user to optimize efficiency and reduce kick.\n*Dye DM10 Pro-Performance Detents - Durable and super-flexible detents offer supreme tenderness to the most brittle of paint. Flex-spring geometry ensures that balls will not double feed into the breech.\n*Dye DM10 No Eyeplates - The 2010 DM Series features a low-maintenance internal patent-pending Eye Pipe anti-chop sensing system that is self cleaning, providing trouble free high rates of fire.\n*Dye DM10 Ultralite - Weighing in at 1.9 lbs, the 2010 DM Series is lighter than any previous DM.\n*Dye DM10 Color Coded O-Rings - Makes it easier to perform regular, scheduled maintenance of your Fuse Bolt system.\n*08 Dye DM10 Ultralite Reach Trigger - Trigger roller bearing inserts give the trigger stability and a smooth swing return. The externally adjustable design allows you to limit the travel of the trigger and spring tension without removing the grip frame or Sticky3 grip. Trigger Reach Adjustment is a first in the painbtall industry, which allows the user to fully customize the trigger for ultimate shooting capability.\n*Dye DM10 UL Grip Frame - The 2010 DM Series is the proud owner of the worlds lightest, most compact and comfortable 45 grip frame available. The patent-pending hour-glass design allows for a sleeker profile, while heads-up display light alert you to the status of your gun, without having to take your eyes off the game.\n*Dye DM10 LED Control - High intensity LED provides identification to program functions. The 2010 DM Series features our unique heads-up display light which alerts you to the status of your gun, while still being able to focus on the game.\n*Dye DM10 Metal Power Buttons - Our metal/rubber button pad features large buttons that can easily be used while wearing gloves. Stainless steel buttons are guaranteed not to fail." + }, + ".shop_by_brand.energy_paintball_batteries" : {}, + ".markerupgrades.tippmann.tippmann_x7_upgrades.tippmann_x_7_bolts" : { + "meta_description" : "X7 Bolt - Buy your Tippmann X7 Bolts Online at Zephyr Paintball for Less today. Free Shipping on X-7 Mods Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy X7 Bolt Online On Sale Now", + "head_title" : "X7 Bolt | Tippmann X7 Bolts | X-7 Mods" + }, + ".shop_by_brand.dye" : { + "meta_keywords" : "Dye Paintball,dye rotor,Dye Paintball guns,dye dm, dye paintball pants,paintball jersey", + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tDYE PLAYER'S APPAREL\n\t\n
                                                                          \n
                                                                          \n \n \n
                                                                          \n\tDYE CASUAL APPAREL\n\t\n
                                                                          \n
                                                                          ", + "meta_description" : "Dye Paintball - Zephyr Sports carries the complete line of dye paintball gear including Dye Paintball Guns like the DM11, Dye NT Rotor and much more", + "top_description2" : "=Dye Precision Paintball, Play to Win=\nDye is one of the largest innovators in the world of Paintball. They've been around long enough to know what products their customers want and what quality they are expected to perform at. Dye has the leading technology in the business, and they have come a long way to get there. It started in a kids garage, and now it's one of the largest paintball manufacturers around. Their high quality material exceeds every expectation, so if you want to win go for Dye today. ", + "zoovy:banner01" : "banners/paintball/headers/dye_paintball_header.jpg", + "description" : "=Dye Precision Paintball, Play to Win=\n\n==History of Dye==\nIn 1994, world renown professional paintball player, Dave Youngblood, began making barrels in a garage with Earon Carter of Carter Machine. In the short span of time from '94 to '09, Dave transformed DYE, or \"Dave Youngblood Enterprises\", into the pinnacle of performance paintball products. It all started with a single barrel, the Boomstick. It's name is relative to the effect it had on the industry as a whole. Now Dye offers anything and everything for the sport, from socks and squeegees to high end markers, electronic loaders, and goggle systems. Today, Dye continues to innovate within the sport of paintball; constantly raising the bar and releasing revolutionary products. \n\n==Carbon Fiber Boomstick Barrel==\nDye Precision Paintball has done it again, revoulutionizing the sport in which they rain supreme. With the Dye Boomstick Carbon Fiber barrel you will have greater speed, accuracy and agility. Virtually indestructible, this Barrel will last you through the toughest games and the hardest falls. \n\n\n==DM Series Paintball Gun==\nThe 2011 DM Series features a low-maintenance internal patented Eye Pipe anti-chop sensing system that is self cleaning, providing trouble free high rates of fire. Durable and super-flexible detents offer supreme tenderness to the most brittle of paint. The Ultralite Reach Trigger allows the trigger's reach and rake to be fully adjusted by the user for ultimate individual ergonomic comfort. Weighing in at 1.9lbs, the Dye DM11 is lighter than it's predecessor, the DM9. All of these innovations, coupled with new 3D body styling and standard features like the second generation Ultralite frame, tool-less Ultralite Sticky3 grip, two piece 14\" Ultralite barrel, cam lock feed neck, and cast aluminum inset DYE logo, it's easy to see why the 2011 DM Series is \"The Choice of Champions.\"\n\n==NT Series Paintball Gun==\nThe 2011 NT series offers a revolutionary technology break through in air usage efficiency, accuracy performance and stylish design. The NT is not only the most air efficient and accurate paintball gun Dye has ever produced, it is also the lightest and most compact in its category. Continuing with Dye's famous patented spool valve design, the new NT Boost Bolt design is the ultimate refinement of next generation spool valve technology. After several years in development, the NT sets a new performance standard for all high-end paintball markers to aspire. Simply put, the best just got better.\n\nThe Boost Bolt system is supported by a redesigned circuit board with faster processing and providing more accurate ROF control. Comfort and stability is assured with the second generation Patented Ultralight grip frame design, providing improved trigger adjustment, new retained push button system, and a redesigned battery mounting system. This grip frame combination is easily accessed through a new first for the industry, full wrap-around, tool-less sticky grip design. Mounted to the bottom of the UL frame is the new UL airport that operates with a simple easy turn, low profile knob that allows forward placement for maximum comfort.\n", + "page_title" : "Dye Paintball Guns & Gear @ Zephyr Sports", + "head_title" : "Dye Paintball | Dye Paintball Guns" + }, + ".casual_clothing.z-sunglasses.z_sunglass_cleaning_kits" : { + "meta_description" : "Sunglass Lens Cleaning Kit - Zephyr Sports carries a complete line of Buy Sunglasses Cleanit Kit At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Sunglass Lens Cleaning Kit On Sale Free Shipping", + "head_title" : "Sunglass Lens Cleaning Kit | Buy Sunglasses Cleanit Kit" + }, + ".2clearance.clearance_bottle_covers" : { + "meta_keywords" : "clearance tank covers, cheap bottle covers, cheap bottle gloves, paintball tank covers, cheap tank protection, cheap compressed air tank covers", + "page_title" : "", + "head_title" : "Clearance Tank Covers | Cheap Bottle Covers | Cheap Bottle Gloves" + }, + ".apparel.pants.511_tactical_pants" : {}, + ".apparel.pants.sly_paintball_pants" : { + "page_title" : "", + "head_title" : "Sly Paintball Pants | Sly Pants", + "prodlist1_header" : "" + }, + ".markers.kingmanspyder.spyder_electronic_packages" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines.aeg_bulk_buy_mags" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "AEG Magazines | Bulk Airsoft Mags | Airsoft Rifle Mags" + }, + ".casual_clothing.mens_clothing.shirts.dickies_shirts_and_flannels" : { + "meta_description" : "Dickies Flannel Shirts - Buy your Dickies Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Dickies Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dickies Shirts & Flannels Ship Free", + "head_title" : "Dickies Flannel Shirts | Dickies Polo Shirts | Dickies Shirts" + }, + ".casual_clothing.mens_clothing.hats.bones_hats" : { + "meta_keywords" : "Bones Hats,Bones caps,Bones baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Bones Hats - Zephyr carries a complete line of Bones Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Bones", + "page_title" : "Bones Hats on Sale at Zephyr", + "head_title" : "Bones Hats | Bones Caps | Bones Baseball Hats" + }, + ".shop_by_brand.young___reckless" : {}, + ".markerupgrades.smartparts.ion.triggers.custom_products_ion_triggers" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.molle_holsters" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".apparel.pants.valken_paintball_pants" : { + "meta_description" : "Valken Paintball Pants - The new standard in quality affordable paintball gear. Valken Pants offer the same great features of expensive pants for less. Get rid of your jeans and get in the game", + "top_description" : "Valken may be a new name, but behind the name there is experience and history that has created Valken's unique character and corporate philosophy that places the strength and profitability of our customers above all else. \n\n\nWhether your playing woodsball, speedball, or just thinking about joining the military, Valken Paintball has the style and the gear you want! \n\n\nValken Paintball is taking things in the paintball industry to the next level! Their ever-expanding product line features high-quality and functional designs! Valken Paintball has been designing tournament paintball gear for years and this season's line showcases all the right stuff! Just enough padding and protection where you need it and quality materials to keep your comfortable in the game! \n\n\nValken has a little something for everyone! Check out the specs on Valken Paintball's full 2011 Line of Tournament Paintball Pants below.. \n", + "page_title" : "Valken Paintball Pants on Sale Now", + "head_title" : "Valken Pants | Valken Paintball Pants", + "prodlist1_header" : "Valken Paintball Pants", + "description" : "=Redemption Pants=\n\nA new material design allows the Redemption pants to be comfortable and flexible while holding your harness snugly in place. And if you need to keep personals on you, the zip-up pockets are the perfect size to carry most items while making sure they won't fall out during intense play! Just as any other player clothing in the Valken line, the pants have integrated meshing to help keep you cool and allow for better movement. \n\n\n=Crusade Pants=\n\nThe new Crusade pants are ready to take a beating out on the field! Padded knees keep you safe and comfortable when kneeling or crawling on the ground. Grippy silicone printing along the waist line helps keep your harness from bouncing around, but is also flexible enough to keep you moving. They have adjustable ankle cuffs, allowing you to shrink them down creating a better fit and making your self a smaller target! \n\n\n=Fate Pants=\n\nValken Paintball's 'Fast Pants'. Ultra Durable, breathable polyester material. Velcro closure bottom to adjust length. Stretch panels in crotch allows flexibility. Built in adjustable velcro waistbelt. And heavy duty nylon knees. \n" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_forsake_womens_sunglasses" : {}, + ".airsoft.shop_by_brand" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Brand shopping | Shop by brand | Brands shop" + }, + ".markers.kingmanspyder.kingmansemiautospyders" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_radarlock_edge_sunglasses" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns.g_g_gas_airsoft_guns" : { + "meta_description" : "G&G Airsoft Guns - Buy your G&G Airsoft Pistols At Zephyr Sports for Less Today! We carry a complete line of G&G Gas Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy G&G Airsoft Guns On Sale & Free Shipping", + "head_title" : "G&G Airsoft Guns | G&G Airsoft Pistols |G&G Gas Pistols" + }, + ".markerupgrades.tippmann.tippmann_x7_upgrades.tippmann_x_7_complete_mod_kits" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.thompson_m1a1_aeg_airsoft_gun_mags" : {}, + ".apparel.shoes.1search_by_size.j_men_s_size_10_shoes" : {}, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_the_jam_sunglasses" : {}, + ".barrels.tippmann98.18___tippmann_98_barrels" : { + "meta_description" : "Tippmann 98 2 piece Barrels - Buy your Custom 98 Sniper Barrels Online at Zephyr Paintball for Less today. Free Shipping on Tippmann 98 Tactical Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann 98 2 piece Barrels Online On Sale Now", + "head_title" : "Tippmann 98 2 piece Barrels | Custom 98 Sniper Barrels | Tippmann 98 Tactical Barrels" + }, + ".casual_clothing.mens_clothing.hats.yums" : { + "top_description2" : "==YUMS History:==\n\nYUMS is not your typical action sports brand. Rooted in today's street culture, the YUMS movement appeals to today's connected generation.\n\n\nSeveral years ago, their involvement in the BMX scene ignited organically from the competitive BMX rider and their interest in the YUMS brand. As a result, YUMS collaborated with a broad base of Pro/Am riders to develop a performance-based shoe geared to meet the demands of various styles displayed by BMX athletes. Whether it be park, vert dirt, or street, the YUMS ReUp mid's versatility conquers any BMX venue." + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_module_sunglasses" : { + "meta_description" : "Electric Module Sunglasses - Zephyr Sports carries a complete line of Electric Module Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Module Online Today.", + "page_title" : "Electric Module Sunglasses On Sale Free Shipping", + "head_title" : "Electric Module Sunglasses | Electric Module Sun Glasses | Sunglasses Electric Module" + }, + ".casual_clothing.mens_clothing.hats.von_zipper_hats" : { + "meta_keywords" : "Von Zipper Hats,Von Zipper caps,Von Zipper baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Von Zipper Hats - Zephyr carries a complete line of Von Zipper Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Von Zipper", + "page_title" : "Von Zipper Hats on Sale at Zephyr", + "head_title" : "Von Zipper Hats | Von Zipper Caps | Von Zipper Baseball Hats" + }, + ".airsystems.tankcovers.blackstar_butt_bottle_covers" : { + "meta_description" : "Blackstar Butt - Buy your Blackstar Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Black Star Butt Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Blackstar Butt Online On Sale Now", + "head_title" : "Blackstar Butt | Blackstar Tank Cover | Black Star Butt" + }, + ".barrels.barrels_by_manufacturer.lapco_paintball_barrels.lapco_snapshot_barrels.complete_snapshot_barrels" : {}, + ".2clearance.mens_clothing.hats___beanies" : { + "head_title" : "Sale Hats and Beanies | Clearance Hats and Beanies" + }, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel" : {}, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_sushi_sunglasses" : {}, + ".markers.tiberius_arms_paintball_guns" : { + "meta_keywords" : "Tiberius Arms, Tiberius Paintball Guns, Tiberius Paintball, Tiberius t9 paintball gun, tiberius paintball pistol, ", + "banner1" : "banners/categories/t9_conversionkit_discount_header", + "meta_description" : "Tiberius Arms Paintball Guns - Tiberius Arms is the leader in magazine fed Paintball pistols and paintball rifles. Get your tiberius t8 pistol or t9 rifle at Zephyr Today", + "page_title" : "Buy Tiberius Arms Online On Sale Now", + "head_title" : "Tiberius Arms | Tiberius Paintball Guns | Tiberius t9 paintball gun", + "banner1_link" : "/category/001a_zephyr_paintball_sports_promotions_deals_sales.t9_marker___conversion_kit/", + "description" : "Tiberius Arms is the leader in Magazine fed paintball pistols and Rifles. All Tiberius guns run off of [[12 gram]:search=12 gram cartridge] Co2 cartridges that provide about 16 shots per cartridge. Both the [[Pistol]:search=tiberius 8 pistol] and the [[rifles]:search=tiberius t9] use an 8 shot quick change [[magazine]:product=PB-TA-TIB8MAG] that also holds your co2 cartridge. Additional magazines are available along with [[magazine holsters]:search='tiberius magazine holster] to to keep you in the game. Accuracy and velocity is similar to a standard paintball gun. The Tiberius T9 Rifles include a conversion kit to add a standard paintball hopper and a remote coil to run off a co2 or compressed air tank. For the Tiberius T8 pistols you can purchase remote air adapter [[remote air adapter]:product=PB-TA-REMOTE] to run off of a remote coil and a standard paintball tank." + }, + ".paintballs.valken_paintballs" : { + "head_title" : "Valken Paintballs | Valken Redemption | Valken Infinity" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.leapers_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_agent_4119_sunglasses" : { + "meta_description" : "Arnette Agent Sunglasses - Buy your Arnette 4119 Agent At Zephyr Sports for Less Today! We carry a complete line of Agent Arnette Sunglasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Arnette Agent Sunglasses On Sale & Free Shipping", + "head_title" : "Arnette Agent Sunglasses | Arnette 4119 Agent | Agent Arnette Sunglasses" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.desert_eagle_spring_airsoft_guns" : { + "meta_description" : "Desert Eagle Airsoft Guns - Buy your Desert Eagle Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Desert Eagle Spring Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Desert Eagle Airsoft Guns On Sale & Free Shipping", + "head_title" : "Desert Eagle Airsoft Guns | Desert Eagle Airsoft Rifles | Desert Eagle Spring Airsoft Gun" + }, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests" : { + "meta_keywords" : "airsoft vest, tactical vest, military vest", + "meta_description" : "Tactical Airsoft Vests. Standard vests with all the pockets you could use as well as velcro vests that allow you to expand and change your vest design to fit your needs. Vests come in multiple sizes and shapes. They also will include a variety of different accessories. Some of the vests listed are will allow you to purchase attachments separately so you can outfit yourself with exactly what you need with having to spend extra money items you may not need.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Tactical Airsoft Vests" + }, + ".markerupgrades.tippmann.a5" : { + "meta_keywords" : "tippmann A-5 upgrades,A 5 upgrades,upgrades for tippmann A-5 ,Tippmann A5 trigger,grip", + "btn2_link" : "/category/scenarioupgrades.slings/", + "prodlist2_title" : "Featured Tippmann A-5 Upgrades", + "banner3" : "zephyr_buttons/stocks_btn001", + "buttonname_03" : "Stocks", + "btn1_link" : "/category/barrels.tippmanna5/", + "page_title" : "Buy Tippmann A5 A-5 A 5 Upgrades Online Now", + "btn3_link" : "/category/scenarioupgrades.stocks.tippmann_a_5_paintball_stocks/", + "buttonname_04" : "", + "btn2" : "zephyr_buttons/slings_btn001", + "add1_link" : "/category/barrels.tippmanna5/", + "subcat1_header" : "Tippmann A-5 Upgrades Categories", + "banner2" : "zephyr_buttons/barrel_btn001", + "meta_description" : "Tippmann A5 Upgrades - Everything you need to upgrade your Tippmann A-5. From Triggers to bolts and more we have upgrades for tippmann A 5. Free Shipping Knowledgeable customer service", + "btn1" : "zephyr_buttons/barrel_btn001", + "buttonname_01" : "A5 Barrels", + "btn3" : "zephyr_buttons/stocks_btn001", + "btn_title" : "Common Tippmann A-5 Upgrades", + "add2_link" : "/category/scenarioupgrades.stocks.tippmann_a_5_paintball_stocks/", + "buttonname_02" : "Slings", + "head_title" : "Tippmann A5 Upgrades | A-5 Tippmann Upgrades | Upgrades for Tippmann A 5", + "btn4" : "zephyr_buttons/empty_btn001.png" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_hardknox_sunglasses" : { + "meta_description" : "Electric Hardknox Sunglasses - Zephyr Sports carries a complete line of Electric Hardknox Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Hardknox Online Today.", + "page_title" : "Electric Hardknox Sunglasses On Sale Free Shipping", + "head_title" : "Electric Hardknox Sunglasses | Electric Hardknox Sun Glasses | Sunglasses Electric Hardknox" + }, + ".barrels.zsquegee" : { + "meta_description" : "Paintball Barrel Swab - Buy your Squeegees Paintball Online at Zephyr Paintball for Less today. Free Shipping on Paintball Barrel Squeegees Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Barrel Swab Online On Sale Now", + "head_title" : "Paintball Barrel Swab | Squeegees Paintball | Paintball Barrel Squeegees" + }, + ".markerupgrades.dangerous_power_upgrades.dangerous_power_board_upgrades" : { + "meta_description" : "Dangerous Power Upgrade Boards - Buy your Dp G4 Virtue Boards Online at Zephyr Paintball for Less today. Free Shipping on Dangerous Power Ramping Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dangerous Power Upgrade Boards Online On Sale Now", + "head_title" : "Dangerous Power Upgrade Boards | Dp G4 Virtue Boards | Dangerous Power Ramping Boards" + }, + ".apparel.pants.jt_usa_paintball_pants" : { + "page_title" : "", + "head_title" : "JT USA Paintball Pants | Paintball JT USA Pants | JT USA Pants Paintball" + }, + ".maddog.ht_bolt_ad" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_fringe_womens_sunglasses" : { + "meta_keywords" : "Oakley Fringe Womens Sunglasses,Fringe Womens oakley sunglasses,oakley Fringe Womens, Fringe Womens polarized sunglasses", + "meta_description" : "Oakley Fringe Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Fringe Womens and Polarized Oakley Fringe Womens Sunglasses on Sale! ", + "page_title" : "Oakley Fringe Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Fringe Womens Sunglasses | Fringe Womens Oakley Sunglassses" + }, + ".markerupgrades.smartparts.ion.snatch_grips" : {}, + ".markerupgrades.matrix.matrix_triggers" : {}, + ".casual_clothing.mens_clothing.beanies.dgk_beanies" : { + "meta_keywords" : "DGK beanie,DGK hat,DGK beanies,DGK caps,DGK 686,DGK headwear,DGK cuff visor beanie,DGK beanie hat,DGK visor beanie,DGK visor beanies", + "meta_description" : "DGK Deanie - Surf style with DGK Beanies available now at Zephyr Sports. Get your DGK hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "DGK Beanies on Sale at Zephyr Today", + "head_title" : "DGK Beanie | DGK Hat | DGK Beanies" + }, + ".markers.macdev_paintball_guns.macdev_cyborg_rx_paintball_guns" : {}, + ".markerupgrades.proto_matrix_rail_upgrades.proto_rail_body_kits" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.team_sd_sport_aeg_airsoft_guns" : { + "meta_description" : "TSD Airsoft Guns - Buy your Team SD Sport Airsoft Guns Online At Zephyr Sports for Less Today! We carry a complete line of Team SD Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy TSD Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "TSD Airsoft Guns | Team SD Sport Airsoft Guns | Team SD Airsoft Guns" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.aeg_fast_magazines" : {}, + ".casual_clothing.mens_clothing.sweatshirts.hk_army_sweatshirts" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_big_taco_sunglasses" : {}, + ".markerupgrades.proto_matrix_upgrades.proto_matrix_grips" : {}, + ".misc_items.dvd_s" : { + "meta_keywords" : "paintball dvds, paintball movies, der der movies, der der productions", + "page_title" : "", + "head_title" : "Paintball DVDS | Paintball Movies | Der Der Movies" + }, + ".casual_clothing.z_unisex_clothing_accesories.lanyards.hk_army_lanyards" : {}, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_akamai_sunglasses" : { + "meta_description" : "Maui Jim Akamai Sunglasses - Zephyr Sports carries a complete line of Maui Jim Akamai Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Akamai Online Today.", + "page_title" : "Maui Jim Akamai Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Akamai Sunglasses | Maui Jim Akamai Sun Glasses | Sunglasses Maui Jim Akamai" + }, + ".airsystems" : { + "meta_keywords" : "Paintball tanks, co2 tanks, paintball air tanks, hpa tanks, carbon fiber tank, paintball co2 tanks, paintball asa, paintball fill station, air systems, paintball air systems, paintball co2, paintball tank", + "ad3_link" : "/results.cgis?catalog=HOMEPAGE&keywords=maddog+usa+remote&x=22&y=6", + "ad2" : "banners/paintball/side_banners/ninja_pro_tanks_sidebanner.jpg", + "page_title" : "Buy Paintball Tanks Online On Sale Now", + "3widead_title" : "", + "ad2_link" : "/category/airsystems.nitrogentanks.ninja_paintball_tanks.ninja_pro_paintball_tanks/", + "subcat1_header" : "Air System Categories", + "meta_description" : "Need Paintball Tanks? How are you expecting to get those little paintballs to fly out of your brand new paintball gun? With either a compressed air tank or Co2 tank of course! We got you covered from practically every size and shape to fit your needs and wants.", + "ad1" : "banners/paintball/side_banners/c02_tank_sale_sidebanner.jpg", + "prodlist1_header" : "Featured Air System Items", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/airsystems_header.jpg\"", + "banner1" : "banners/09_headers/main_categories/air_systems_001", + "ad3" : "banners/paintball/side_banners/usa_made_maddog_remote_lines_sidebanner.jpg", + "htmlvids" : "", + "ad1_link" : "/category/airsystems.co2tanks/", + "htmllinks" : "Popular Links\n\nNinja Tank | Crossfire Tank", + "header1" : "Featured Products", + "head_title" : "Paintball Tanks | CO2 Tank | Paintball Air Tanks", + "page_head" : "" + }, + ".markerupgrades.smartparts.shocker.shocker_nxt_bolts_and_accesories" : {}, + ".barrels.barrels_by_manufacturer.proto_paintball_barrels.proto_barrel_backs" : {}, + ".dye_i4_paintball_goggle_mask.paintball_blog.empire_event_paintball_mask" : {}, + ".markers.planet_eclipse_ego_paintball_guns.eclipse_ego_11_paintball_guns" : { + "meta_keywords" : "Ego11,planet eclipse ego 11 paintball gun, ego paintball gun, eclipse ego 11,eclipse ego,planet eclipse ego", + "meta_description" : "Planet Eclipse Ego 11 Paintball Guns - Zephyr has the widest variety of Ego 11 Paintball Guns. Free shipping for your ego 11 ", + "top_description2" : "=Planet Eclipse Ego 11=\n\nThe Ego 11 has been developed and created with the sole intention of giving the modern player the things that they most desire in a modern paintball marker: a smoother shot; a quieter sound signature; outstanding efficiency; unparalleled reliability; simplicity; ergonomics; built-in user adjustability and choice; industry-leading customer service. ", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.planet_eclipse_package_specials.ego_package_specials/", + "zoovy:banner02" : "banners/paintball/slideshow/planet_eclipse_ego_11_price_drop.jpg", + "description" : "Planet Eclipse takes pride in being able to react quickly to changing trends; to give customers what they want; and to give them the flexibility to have their marker set up just the way they like it. This philosophy has never been more evident than in the new Ego11. \n\n\n\n\nThe Ego11 comes equipped with an industry first, a bespoke solenoid - manufactured by MAC Valves USA - that incorporates twin flow control devices. These Solenoid Flow Controls each comprise of a quarter-turn adjuster which has a pointer to indicate position on an incremental scale etched into the body of the solenoid. The Solenoid Flow Controls are used to independently control both the forward and rearward speed of the rammer and bolt so that, for the first time ever in a poppet marker, the user can tune the feel of the marker with a simple twist of a screwdriver. In the time it takes to turn off the tourney-lock, the Ego11 can be switched from a high speed, uncapped, free-for-all machine to the softest, gentlest, smoothest shooting poppet you have ever felt - or anything in-between. The analogue adjustment allows an infinite level of control over the speed of the rammer and bolt in either direction, providing unprecedented influence over the dynamic characteristics of the marker. With the Ego11 it looks like you really can have your cake and eat it too! \n\n\n\n\nThe Push-On-Purge-System \"POPS\" is a completely new concept in On/Off/Purging ASAs. The idea is simple, push back on the front 'Bonnet' section of the POPS and this depresses the air system valve pin - gassing up the marker - before latching itself into place; the operation takes just a fraction of a second. Once gassed up, the bonnet stays in position until the push button on the side of the POPS bonnet is depressed, at which point the bonnet POPS forward and the marker purges itself of air; again, de-gassing takes a fraction of a second and very little effort. \n\n\n\n\nInside the protective cocoon of the frame lies the Eclipse circuit board. Designed to negate the need for an expensive after-market 'upgrade', this board has all of the features that the discerning player needs. The large screen LCD module provides excellent contrast in even the brightest sunlight, using significantly less power than its OLED counterparts; indoors, a tru-color backlight can be customized to taste; furthermore, in the event of damage, the LCD module can be quickly and easily replaced. Twin trigger sensing circuitry - micro-switch or optoelectronic sensor - can be selected and tuned to individual requirements using multi-parameter trigger de-bounce algorithms. Prioritized solenoid drive circuitry produces superb shot-to-shot consistency and rate of fire accuracy. An expansion port allows the Ego11 to be connected to a PC using the optional Eclipse E-Portal kit which provides firmware re-programming, splash screen design and control parameter editing functionality. A low power, 16-bit microprocessor provides the brawn, and stable firmware, refined over years of tournament play provides the intelligence. With all the adjustability and functionality you could ever need, the range of features on the Ego11 is simply breathtaking: a refill counter; ROF indicators; timers; audible indicators; RF transmitter compatible; you name it, the Ego11 board will do it or support it! \n\n\n", + "head_title" : "Eclipse Ego | Planet Eclipse Ego 11 Paintball Gun | Eclipse 2011 Ego", + "page_title" : "Buy Eclipse Ego Paintball Gun Online On Sale Now" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.asg_scopes" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.empire_marballizer_paintballs" : {}, + ".casual_clothing.mens_clothing.wallets.nixon_wallets" : { + "meta_description" : "Nixon Wallets - Buy your Nixon Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Nixon Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Wallets on Sale @ Zephyr Sports", + "head_title" : "Nixon Wallets | Nixon Mens Wallets | Nixon Wallet" + }, + ".airsoft.shop_by_brand.revision_eyewear" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Revision eyewear | Revision eyewear sawfly | Revision ballistic eyewear" + }, + ".casual_clothing.mens_clothing.tshirts.plan_b_t-shirts" : { + "meta_description" : "Plan B Tshirts - Buy your Plan B Shirts At Zephyr Sports for Less Today! We carry a complete line of Plan B Clothing at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Plan B Tshirts On Sale & Free Shipping", + "head_title" : "Plan B Tshirts | Plan B Shirts | Plan B Clothing" + }, + ".barrels.barrels_by_manufacturer.proto_paintball_barrels.proto_barrel_tips" : {}, + ".apparel.shoes" : {}, + ".casual_clothing.z_unisex_clothing_accesories.lanyards.dye_lanyards" : { + "meta_description" : "Dye Lanyards - Buy your Dye Paintball LanyardsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Dye Lanyards @ Zephyr Sports", + "head_title" : "Dye Lanyards | Dye Paintball Lanyards | Lanyard Dye" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_temper_sunglasses" : { + "meta_description" : "Arnette Temper Sunglasses - Zephyr Sports carries a complete line of Temper Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Temper Sun Glasses Online Today.", + "page_title" : "Arnette Temper Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Temper Sunglasses | Temper Arnette Sunglasses | Arnette Temper Sun Glasses" + }, + ".maddog.spyder_upgrades.spyder_triggers" : {}, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_polarized_sunglasses" : { + "meta_description" : "Gatorz Polarized Sunglasses - Zephyr Sports carries a complete line of Gatorz Polarized Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Gatorz Polarized Online Today.", + "page_title" : "Gatorz Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Gatorz Polarized Sunglasses | Gatorz Polarized Sun Glasses | Sunglasses Gatorz Polarized" + }, + ".markers.ariakon" : { + "meta_keywords" : "Ariakon Paintball, Ariakon paintball guns, Ariakon Overlord, Ariakon acp, ariakon sim 4, ariakon sim 5, ariakon paintball rifle, paintball marker ariakon", + "banner1" : "banners/categories/guns/ariakon_banner.jpg", + "meta_description" : "Ariakon Paintball Guns - The leader in scenario paintball pistols and rifles. Don't settle for a lower end paintball gun, get the realism of an ariakon paintball marker", + "page_title" : "Buy Ariakon Paintball Online On Sale Now", + "head_title" : "Ariakon Paintball | Ariakon Paintball Guns | Ariakon Paintball Pistol" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_ec_dc_xl_sunglasses" : { + "meta_description" : "Electric EC/DC XL Sunglasses - Zephyr Sports carries a complete line of Electric EC/DC XL Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric EC/DC XL Online Today.", + "page_title" : "Electric EC/DC XL Sunglasses On Sale Free Shipping", + "head_title" : "Electric EC/DC XL Sunglasses | Electric EC/DC XL Sun Glasses | Sunglasses Electric EC/DC XL" + }, + ".casual_clothing.mens_clothing.beanies.neff_beanies" : { + "meta_keywords" : "Neff beanie,Neff hat,Neff beanies,Neff caps,Neff 686,Neff headwear,Neff cuff visor beanie,Neff beanie hat,Neff visor beanie,Neff visor beanies", + "meta_description" : "Neff Deanie - Surf style with Neff Beanies available now at Zephyr Sports. Get your Neff hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Neff Beanies on Sale at Zephyr Today", + "head_title" : "Neff Beanie | Neff Hat | Neff Beanies" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_radar_pitch_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley radar pitch sunglasses,polarized oakley radar pitch sunglasses", + "meta_description" : "Oakley Radar Pitch Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Radar Pitch Sunglasses and Polarized Oakley Radar Pitch Sunglasses on Sale! ", + "page_title" : "Oakley Radar Pitch Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Radar Pitch Sunglasses | Radar Pitch Oakley Sunglasses" + }, + ".casual_clothing.mens_clothing.belts.anti_hero_belts" : { + "meta_keywords" : "Anti Hero Belts,Anti Hero Belt Buckle,Anti Hero Belts,Anti Hero webbed belt", + "meta_description" : "Anti Hero Belts - We carry the complete line of Anti Hero Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Anti Hero Belts on Sale Now!", + "head_title" : "Anti Hero Mens Belts | Antihero Belts | Anti Hero Skate Belts" + }, + ".casual_clothing.womens_clothing.ladies_socks.neff_ladies_socks" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.oakley_pants_and_jeans" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_kids_hydration_packs" : { + "meta_description" : "Camelbak Kids Packs - Buy your Kids CamelbaksAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Kids Packs On Sale & Free Shipping", + "head_title" : "Camelbak Kids Packs | Kids Camelbaks" + }, + ".airsoft.tactical_airsoft_gear.head_gear.full_clip_head_gear" : { + "meta_keywords" : "full clip headband,head band, full clip headwrap,headwrap", + "meta_description" : "Full Clip Headbands - Zephyr Carries a complete line of Full Clip Headwraps and headbands for all your paintball and airsoft needs. Largest Selection, Free Shipping and Customer Service Trust Zephyr", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Full Clip Headbands and Headwraps" + }, + ".airsoft.airsoft_gun_magazines.co2_pistol_magazines" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_tightrope_sunglasses" : { + "meta_keywords" : "Oakley Tightrope Sunglasses,Tightrope oakley sunglasses,oakley Tightrope, Tightrope polarized sunglasses", + "meta_description" : "Oakley Tightrope Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Tightrope and Polarized Oakley Tightrope Sunglasses on Sale! ", + "page_title" : "Oakley Tightrope Sunglasses with Free Shipping", + "head_title" : "Oakley Tightrope Sunglasses | Tightrope Oakley Sunglassses" + }, + ".casual_clothing.womens_clothing.ladies_watches" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_terminal_backpacks" : {}, + ".markers.smartparts.smart_parts_vibe_paintball_guns" : { + "meta_keywords" : "Smart Parts Vibe, vibe paintball gun, cheap smart parts vibe, vibe paintball starter package", + "meta_description" : "Smart Parts Vibe - professional paintball gun performance at an entry level price. Get your Vibe starter package at Zephyr today", + "page_title" : "", + "head_title" : "Smart Parts Vibe | Vibe Paintball Gun | The smart parts vibe " + }, + ".casual_clothing.mens_clothing.hats.alpine_stars_hats" : { + "meta_keywords" : "Alpinestars Hats,Alpinestars caps,Alpinestars baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Alpinestars Hats - Zephyr carries a complete line of Alpinestars Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Alpinestars", + "page_title" : "Alpinestars Hats on Sale at Zephyr", + "head_title" : "Alpinestars Hats | Alpinestars Caps | Alpinestars Baseball Hats" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_4075_havana_sunglasses" : { + "meta_description" : "Ray Ban Havana Sunglasses - Zephyr Sports carries a complete line of Havana Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Havana Sun Glasses Online Today.", + "page_title" : "Ray Ban Havana Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Havana Sunglasses | Havana Ray Ban Sunglasses | RayBan Havana Sun Glasses" + }, + ".harnessesbags.backpacks.ogio_backpacks" : { + "meta_keywords" : "ogio bags,ogio backpack,ogio pack,ogio travel,ogio laptop,ogio duffel,ogio street,ogio backpacks,ogio ozone,ogio messenger bag,ogio laptop backpack,ogio laptop bag,ogio duffel bag,ogio gear bag,ogio duffle,ogio duffle bag,ogio laptop backpacks,ogio laptop bags,ogio sports bag,ogio packs,ogio duffel bags,ogio duffle bags\r ", + "meta_description" : "OGIO Bags - Complete Line of OGIO Backpacks at the lowest prices on the web. Backpack OGIO with Free Shipping on orders over $75 and on all OGIO bags and backpacks", + "page_title" : "OGIO Bags & Backpacks FREE SHIPPING ", + "head_title" : "OGIO Bags | OGIO Backpacks | Backpack OGIO" + }, + ".loaders.hopper_accesories.virtue_crowns" : { + "meta_description" : "Virtue Crowns - Buy your Virtue Crown Speed Loaders Online at Zephyr Paintball for Less today. Free Shipping on Crown Speed Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Virtue Crowns Online On Sale Now", + "head_title" : "Virtue Crowns | Virtue Crown Speed Loaders | Crown Speed Feed" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.echo_1_airsoft_guns.ak47_echo_1_airsoft_guns" : {}, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_hook_polarized_sunglasses" : { + "meta_description" : "Suncloud Hook Polarized Sunglasses - Zephyr Sports carries a complete line of Hook Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Hook Sun Glasses Online Today.", + "page_title" : "Suncloud Hook Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Hook Polarized Sunglasses | Hook Suncloud Sunglasses Free Shipping | Buy Suncloud Hook Sun Glasses" + }, + ".shop_by_brand.sanuk" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.king_arms_airsoft_guns" : {}, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_playmaker_series_baseball_gloves" : { + "head_title" : "Rawlings Playmaker Series Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones.nixon_headphones.nixon_tps_speakers" : {}, + ".sponsorship.sponsor_only_specials.team_sponsorship_packages.invert_team_packages" : {}, + ".paintballs.tippmann_us_army_paintballs" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4058_sunglasses" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines.aeg_high_capacity_mags" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "High Cap Airsoft Mags | High Capacity Airsoft Magazines | Airsoft High Cap" + }, + ".scenarioupgrades.tactical_vests.jt_tactical_vests" : {}, + ".1historical_products" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb3341_sunglasses" : { + "meta_keywords" : "Ray Ban RB3341 Sunglasses ,Ray Bans,Ray Ban Sunglasses", + "meta_description" : "Ray Ban RB3341 Sunglasses are now available @ Zephyr Sports! Made in Italy, these Ray Ban Sunglasses have style and quality above all else! Backed with a manufacturers warranty, the Rayban Sunglasses are a classic look that never fades! These Ray Bans are available in various colors, check em out @ Zephyr Sports!", + "page_title" : "Buy Ray-Ban RB3341 Sunglasses On Sale & Free Shipping", + "head_title" : "Ray-Ban RB3341 Sunglasses | Ray Ban RB3341 Sunglasses | Ray Ban RB 3341 Sunglasses" + }, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_atlas_polarized_sunglasses" : { + "meta_description" : "Suncloud Atlas Polarized Sunglasses - Zephyr Sports carries a complete line of Atlas Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Atlas Sun Glasses Online Today.", + "page_title" : "Suncloud Atlas Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Atlas Polarized Sunglasses | Atlas Suncloud Sunglasses Free Shipping | Buy Suncloud Atlas Sun Glasses" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_flak_pack_xl_backpacks" : {}, + ".shop_by_brand.jox_sox" : { + "top_description2" : "=Jox Sox, all the performance, half the price=\n\nAt Jox Sox they don't make just any socks, but sports socks that will last you a lifetime. These socks are the best, lightest and most comfortable in the business. Use Jox Sox at work, play or even around the house. You may be surprised at the diverse clientele that Jocks Socks entails like fire fighters, military, nurses, runners, hikers, cyclists, golfers and tennis players! Use Jox Sox and you'll never wear another pair of Socks again! ", + "head_title" : "Jox Sox | Sport Socks | Jocks Socks", + "description" : "=Jox Sox, all the performance, half the price=\n\n==Mission==\nThe Jox Sox mission is to improve quality of life. They do so by bringing you the comfort, stability and durability to bounce back no matter what life throws your way. Jox Sox is the foundation to put your best foot forward.\n\n==Airflow Technology==\nAirflow Technology keeps your feet cooler, while advanced fibers keep them drier. Padded bottoms help reduce fatigue. The snug fit adds support and promotes perfusion. Also includes a Y shaped heel that will not slide around, a smooth toe seam to eliminate irratation and a no slip top that stays put. Cooler. Drier. More comfortable. \n\n\n" + }, + ".markers.bob_long_paintball_guns.bob_long_rapper_paintball_guns" : {}, + ".airsoft.airsoft_guns.1_shop_by_gun_type.m9_airsoft_guns" : { + "meta_description" : "M9 Airsoft Guns - Buy your Airsoft M9 At Zephyr Sports for Less Today! We carry a complete line of M9 AEG Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "Below are replica M9 Pistols. The original M9 9mm is a short recoil, semi-automatic, single-action / double-action pistol which uses a 15-round staggered box magazine. The M9 is the standard pistol of the United States Army and the United States Air Force and has been since 1990. \n\n\nOver the years, the M9 has serviced the U.S. in multiple conflicts; The Persian Gulf War, Operation Enduring Freedom (Afganistan) and Operation Iraqi Freedom (Iraq). Most importantly, in the Iraq War, which featured frequent urban and room-to-room combat, American soldiers relied most heavily on their pistols.", + "page_title" : "Buy M9 Airsoft Guns On Sale & Free Shipping", + "head_title" : "M9 Airsoft Guns |Airsoft M9 |M9 AEG Airsoft Gun", + "description" : "" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_murf_watches" : { + "meta_keywords" : "Nixon watches,nixon Murf watch,nixon watch,nixon Murf chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Murf Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Murf Chrono Watches", + "head_title" : "Nixon Murf Watches | Nixon Murf Chrono Watch | Nixon 5130" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_conman_sunglasses" : { + "meta_description" : "Von Zipper Conman Sunglasses - Zephyr Sports carries a complete line of Buy Conman Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Conman Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Conman Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Conman Sunglasses | Buy Conman Von Zipper Sunglasses | Von Zipper Conman Sunglasses Free Shipping" + }, + ".harnessesbags.paintball_gear_bags.eclips_gear_bags___backpacks" : { + "meta_keywords" : "eclipse gear bags, planet eclipse bags, paintball gear bags, lowland bags, ftac, backpack", + "meta_description" : "Eclipse Gear Bags - Zephyr your one stop paintball shop carries the complete line of planet eclipse bags. Be sure to check out our other paintball gear bags", + "page_title" : "Buy Eclipse Gear Bags Online On Sale Now", + "head_title" : "Eclipse Gear Bags | Planet Eclipse Bags | Paintball gear Bags" + }, + ".markerupgrades.bt_designs_upgrades" : { + "btn2_link" : "", + "banner3" : "zephyr_buttons/stocks_btn001", + "btn1_link" : "", + "page_title" : "Buy BT Combat Upgrades Online On Sale Now", + "add1_link" : "/category/barrels.tippmanna5/", + "btn2" : "", + "banner2" : "zephyr_buttons/barrel_btn001", + "btn1" : "", + "meta_description" : "BT Combat Upgrades - Buy your BT Paintball Gun Upgrades Online at Zephyr Paintball for Less today. Free Shipping on Delta Erc Parts Trust Zephyr for all your Paintball Needs", + "ad1" : "", + "buttonname_01" : "", + "description" : "=Notice=\nBT paintball markers are compatible with Tippmann A5/X7 Threaded Barrels as well as Tippmann 98 Stocks.", + "add2_link" : "/category/scenarioupgrades.stocks.tippmann_98_scenario_stocks/", + "buttonname_02" : "", + "ad1_link" : "%SESSION%/category/barrels.tippmanna5/", + "head_title" : "BT Combat Upgrades | BT Paintball Gun Upgrades | Delta Erc Parts" + }, + ".casual_clothing.mens_clothing.shorts.fox_racing_shorts" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_tastemaker" : {}, + ".markerupgrades.valken_v-tac" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_tenet_sunglasses" : { + "meta_description" : "Smith Optics Tenet Sunglasses - Zephyr Sports carries a complete line of Tenet Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Tenet Sun Glasses Online Today.", + "page_title" : "Smith Optics Tenet Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Tenet Sunglasses | Tenet Smith Sunglasses Free Shipping | Buy Smith Tenet Sun Glasses" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.classic_army_airsoft_guns" : { + "meta_keywords" : "Classic Army,Classic Army Airsoft Guns,airsoft equipment,full metal,AEG 's,spring powered,gas powered,co2 powered airsoft guns,classic army airsoft", + "meta_description" : "Classic Army Airsoft is one of the most respected manufactures of high-end airsoft products in the world. Their dedication to using only the best materials and quality machining have given them the reputation as a leading innovator in airsoft equipment. Their rifles are made with full metal bodies and are designed to a 1:1 scale. Classic Army is the first company in the airsoft industry to achieve the international safety certificate (CE) for airsoft products. Zephyr Sports carries a grip of Classic army airsoft pistols including AEG 's, spring powered, gas powered, and co2 powered airsoft guns! ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Classic Army Airsoft Guns On Sale & Free Shipping", + "head_title" : "Classic Army Airsoft Guns | Classic Army M15A4 Airsoft | Classic Army Sportline", + "description" : "" + }, + ".casual_clothing.mens_clothing.beanies.enjoi_beanies" : { + "meta_keywords" : "Enjoi beanie,Enjoi hat,Enjoi beanies,Enjoi caps,Enjoi 686,Enjoi headwear,Enjoi cuff visor beanie,Enjoi beanie hat,Enjoi visor beanie,Enjoi visor beanies", + "meta_description" : "Enjoi Deanie - Surf style with Enjoi Beanies available now at Zephyr Sports. Get your Enjoi hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Enjoi Beanies on Sale at Zephyr Today", + "head_title" : "Enjoi Beanie | Enjoi Hat | Enjoi Beanies" + }, + ".casual_clothing.z-sunglasses.filtrate_sunglasses" : {}, + ".casual_clothing.womens_clothing.ladies_rash_guards.oakley_ladies_rash_guards" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_variable_power_scopes.nc_star_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.obey_beanies" : { + "meta_description" : "Obey Beanies - Buy your Beanies ObeyAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on OBEY BEANIES @ Zephyr Sports", + "head_title" : "Obey Beanies | Beanies Obey" + }, + ".goggles.proto.proto_axis_paintball_goggles" : { + "meta_description" : "Proto Axis Paintball Goggles - Buy your Proto Axis Paintball Goggles Online at Zephyr Paintball for Less today. Free Shipping on Proto Axis Pro Thermal Goggles Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Proto Axis Paintball Goggles Online On Sale Now", + "head_title" : "Proto Axis Paintball Goggles | Proto Axis Paintball Goggles | Proto Axis Pro Thermal Goggles" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.1-search_by_size.2-medium" : {}, + ".casual_clothing.z_shoes_and_footwear.converse_skate_shoes" : {}, + ".markers.empire_axe_paintball_guns.empire_invert_mini_paintball_guns" : { + "meta_description" : "Empire Mini Paintball Gun - The hottest entry level tournament paintball gun from Empire. The Empire Mini was rebranded from the Invert Mini in 2012. Still the best paintball gun for the dollar.", + "top_description2" : "The all new Empire Mini Paintball Gun from Empire Paintball. The Empire Mini was rebranded from Invert in 2011. So an Invert Mini and a Empire Mini are the same guns with a new brand name. Weighing in at less than 2lbs, the Empire Mini is one of the best tournament level paintball paintball guns on the market. The Empire Mini features an autococker threaded paintball barrel for an easy upgrade. The hose-less design of the Empire Mini gun allows for a tighter grip on the marker so you can reduce your profile during the game. The Empire Mini will only run off of an HPA tank, co2 tanks are not compatible with the Empire mini. Multi-point adjustable trigger allows for fine trigger adjustment. The front grip of the Empire mini paintball gun houses the battery and the board. The stock Empire mini board has multiple firing modes including psp and nppl tournament modes.\n", + "top_description" : "", + "zoovy:banner01" : "", + "description" : "=Invert Mini Features:=\n* Weighing in under 2 lbs (including barrel, ASA, 9volt battery and regulator) the Invert Mini might be THE Lightest & Tightest electronic marker available\n* NEW patented proprietary P.C.P. (Pressure Controlled Poppet) operating system\n* NEW patented proprietary MINI Regulator/ASA\n* NEW patented proprietary Slipstream solenoid\n* Break Beam Anti-Chop Eyes Standard\n* Multi-mode (NXL, PSP, NPPL & Millennium) firing capability with easy tournament lockout\n* Clamping feed-neck with Ion (Smart Parts)/ICD threads\n* 11.5\" Autococker Threaded Barrel\n* No hoses to crimp or break!", + "htmlvids" : "", + "page_title" : "Empire Mini Paintball Gun on Sale", + "head_title" : "Empire Mini Paintball Gun | Invert Mini | Empire Mini" + }, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests.firepower_tactical_vests" : { + "meta_description" : "Firepower Tactical Vests - Buy your Firepower Military Vests At Zephyr Sports for Less Today! We carry a complete line of Firepower Molle Vests at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Firepower Tactical Vests On Sale at Zephyr ", + "head_title" : "Firepower Tactical Vests | Firepower Military Vests | Firepower Molle Vests" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.ics_airsoft_guns" : {}, + ".casual_clothing.mens_clothing.shorts.globe_shorts" : {}, + ".2clearance.clearance_goggles" : { + "meta_keywords" : "discount paintball mask, discount paintball masks, clearance paintball mask, clearance paintball goggles", + "page_title" : "", + "head_title" : "Discount Paintball Mask | Discount Paintball Masks | Clerance Paintball Masks" + }, + ".markerupgrades.jt_usa_marker_upgrades" : { + "head_title" : "JT USA Paintball Gun Upgrades | JT Marker Upgrades" + }, + ".paintballs.evil_paintballs" : { + "meta_description" : "Evil Paint - Buy your Evil Paintballs Online at Zephyr Paintball for Less today. Free Shipping on Empire PMI Evil Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Evil Paint Online On Sale Now", + "head_title" : "Evil Paint | Evil Paintballs | Empire PMI Evil" + }, + ".markers.bob_long_paintball_guns.bob_long_vice_paintball_guns" : {}, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_airsoft_bipods" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Bipods | Bipod for Airsoft | Airsoft Sniper Bipod" + }, + ".harnessesbags.backpacks.blind_backpacks" : { + "meta_description" : "Blind Backpacks - Buy your Blind Bags At Zephyr Sports for Less Today! We carry a complete line of Blind Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Blind Backpacks & Bags Ship Free ", + "head_title" : "Blind Backpacks | Blind Bags |Blind Luggage" + }, + ".harnessesbags.tubes.empire_paintball_pods" : {}, + ".harnessesbags.backpacks.1_shop_by_bag_style.messenger_bags" : {}, + ".casual_clothing.mens_clothing.sweatshirts.neff_sweatshirts" : { + "meta_description" : "Neff Sweatshirts - Buy your Neff Hoodies At Zephyr Sports for Less Today! We carry a complete line of Neff Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Neff Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Neff Sweatshirts | Neff Hoodies | Neff Hoody" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.ics_aeg_airsoft_rifles" : { + "meta_keywords" : "ICS Airsoft Guns,AEG rifles,AK47,MP5,high-end rifles,airsoft rifles,ICS MP5,airsoft AEG,", + "meta_description" : "ICS Airsoft Guns. ICS has been dedicated to the development of AEG rifles for a decade and continues to build and offer outstanding products. ICS offers high-end electronic versions of popular airsoft AEG 's including the AK47, MP5, and more. Dedicated to creating the most realistic product, ICS works to bring you high-end rifles that feel and operate at the highest standards. These are 1:1 scale, high capacity airsoft rifles for avid airsoft players. ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "ICS Airsoft Rifles On Sale & Free Shipping", + "head_title" : "ICS Airsoft Rifles | ICS MP5 | ICS MP5A4", + "description" : "" + }, + ".markerupgrades.feednecks.spyder_holes" : { + "meta_description" : "Spyder Holes Feed Necks - Buy your Feednecks for Spyder Holes Online at Zephyr Paintball for Less today. Free Shipping on Spyder Holes Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Holes Feed Necks Online On Sale Now", + "head_title" : "Spyder Holes Feed Necks | Feednecks for Spyder Holes | Spyder Holes Feed" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.smith___wesson_airsoft_guns" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses" : { + "meta_keywords" : "spy sunglasses,optics spy,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy sunglass with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your sunglass needs", + "page_title" : "Buy Spy Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Sunglasses | Spy Optics Sunglasses | Spy Sunglass" + }, + ".airsoft.airsoft_guns.airsoft_bb_launchers___shells.action_sport_games" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft AEG Mags | Airsoft Gun Magazines |Airsoft Rifle Mags" + }, + ".casual_clothing.z_unisex_clothing_accesories.phone_cases" : { + "head_title" : "Phone Cases | Iphone Cases | Case for Cell Phones" + }, + ".airsoft.airsoft_guns.echo_1_airsoft_guns" : { + "meta_description" : "Echo1 AEG - Buy your Echo 1 Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Echo1 Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "Echo1 U.S.A. is the leading brand of Airsoft guns located in the heart of Los Angeles in the United States of America. Echo1's products are made of high quality materials and crafted with precision to give you an edge above your competition. \n\n\n\n\nEcho 1 strives to provide their customers with a comprehensive support experience. They are airsoft enthusiasts and know what it takes to make great products. At Echo1 U.S.A., they are committed to providing unparalleled support for their customers. That's why all Echo1 Automatic Electric Guns (AEG) will come with a 30-day limited warranty. Extensive support channels have been set up and are designed to make the support experience as simple as possible for customers.", + "page_title" : "Buy Echo1 AEG On Sale & Free Shipping", + "head_title" : "Echo1 AEG | Echo 1 Airsoft Rifles | Echo1 Airsoft Guns", + "description" : "" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.e90_airsoft_gun_magazines" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.thompson_m1a1_aeg_airsoft_magazines" : {}, + ".markerupgrades.smartparts.ion.bodykits" : {}, + ".casual_clothing.mens_clothing.beanies.electric_beanies" : { + "meta_keywords" : "Electric beanie,Electric hat,Electric beanies,Electric caps,Electric 686,Electric headwear,Electric cuff visor beanie,Electric beanie hat,Electric visor beanie,Electric visor beanies", + "meta_description" : "Electric Deanie - Surf style with Electric Beanies available now at Zephyr Sports. Get your Electric hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Electric Beanies on Sale at Zephyr Today", + "head_title" : "Electric Beanie | Electric Hat | Electric Beanies" + }, + ".apparel.jerseys.invert_paintball_jerseys.invert_2009-10_paintball_jerseys" : {}, + ".barrels.barrels_by_manufacturer.tippmann_paintball_barrels" : { + "meta_keywords" : "Tippmann barrels, tippmann sniper barrels, tippmann paintball barrels, tippmann scenario barrels, tippmann flatline, flatline barrel, tippmann barrel kit, a-5 barrel, 98 custom barrel", + "meta_description" : "Increase your accuracy and distance by replacing your shorty stock barrel with a sniper barrel or go big with the Tippmann Flatline barrel that puts a back spin on the ball for maximum distance", + "page_title" : "Buy Tippmann Barrels Online On Sale Now", + "head_title" : "Tippmann Barrels | Tippmann Sniper Barrels | Tippmann Paintball Barrels" + }, + ".1newitems" : { + "meta_keywords" : "new products, new items, brand new items, brand new products", + "top_html" : "", + "ad3_link" : "%SESSION%/search.cgis/is_newarrival+sunglass/", + "zoovy:banner_image_01" : "banners/categories/2009products_001.jpg", + "top_html_focus" : "", + "ad2" : "", + "page_title" : "New Products - New Items", + "ad2_link" : "%SESSION%/search.cgis/is_newarrival+airsoft/", + "btn2" : "", + "btn1" : "", + "meta_description" : "Come check out this section for brand new items that have just arrived into the Zephyr catalog. Here you will find new items that you may have missed in your everyday normal browsing. You just might find what you are looking for in this new items section.", + "ad1" : "", + "btn3" : "", + "prodlist1" : "&SORTBY=NONE&FORMAT=THUMBMSRP&SRC=&ALTERNATE=0&COLS=4&SIZE=&SHOWSKU=&", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/newitems_header.jpg\"\n", + "ad3" : "", + "banner1" : "banners/09_headers/main_categories/new_items_001", + "ad1_link" : "%SESSION%/search.cgis/is_newarrival+paintball/", + "header1" : "Featured Products" + }, + ".airsoft.tactical_airsoft_gear.airsoft_communications" : { + "meta_keywords" : "Airsoft Communications,Cheap Airsoft Tactical Gear,Walkie Talkies,airsoft headsets,airsoft walky talkys,walkie talkie,", + "meta_description" : "Zephyr Sports is your Cheap Airsoft Tactical Gear Outlet! Everything Airsoft here at Zephyr! Sometimes it takes a little strategy! Airsoft communication headsets work just like walkie talkies!", + "head_title" : "Airsoft Communications | Cheap Airsoft Tactical Gear | Walkie Talkies" + }, + ".casual_clothing.z_unisex_clothing_accesories.stickers.alpinestars_stickers" : {}, + ".casual_clothing.youth_clothing.youth_sweatshirts.1_search_by_size.2_medium" : {}, + ".markerupgrades.proto_matrix_rail_upgrades.proto_rail_back_caps" : {}, + ".shop_by_brand.empire" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tGuns\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tPackages\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tOther Gear\n\t\n
                                                                          \n
                                                                          " + }, + ".markers.protopaintballguns.proto_reflex_rail_paintball_guns" : { + "meta_description" : "Proto Matrix Reflex Rail - Buy your Proto Reflex Rail Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Proto Reflex Paintball Guns Trust Zephyr for all your Paintball Needs", + "top_description" : "", + "description" : "== Proto Reflex Rail Features: ==\n* Fuse Bolt Technology\n* Color Coded O-rings for Easy Maintenance\n* Hyper3 In-Line Regulator\n* Ultralite Frame\n* Adjustable Reach Trigger\n* Aluminum Body\n* 14 Inch Barrel\n\n= Ultralite Frame =\nThe UL 45 frame is the culmination of top pro player influence and progressive engineering. The hour-glass UL frame was ergonomically designed to give the player complete control of the marker. It also allows players to quickly and effortlessly pull the trigger. An integrated heads up display LED light alerts you to the status of your marker without taking your eyes off the game.\n\n\n= Reach Trigger =\nThe Reach Trigger is the next evolutionary step in individually customized ergonomic comfort as well as optimal trigger speed. With the Reach Trigger it is possible to adjust the angle and reach of your trigger externally. The new angle adjustment combined with the travel and spring tension allows you to create a personalized fit to reach you ultimate shooting capabilities.\n\n\n= Eye Pipe =\nThe Eye Pipe, patent pending, internal design houses multiple critical systems that ensure worry free performance. The poly carbonate pipe shields the self-cleaning anti-chop eye system from dirt and broken paint ensuring the eyes are always monitoring the breech and ball drop. The seamless pipe is wiped clean by the bolt tip o-ring on every cycle. The Eye Pipe system eliminates miss feeds and double feeding.\n\n\n= Hyper3 Regulator =\nThe proven Hyper regulator design has been greatly improved. This design is sleeker, smaller, consistent and offers precise increments of air pressure adjustment. Proto's new shim stack is more responsive and reacts quicker to pressure changes allowing better flow and a faster response. The side has been dramatically reduced allowing the incorporation of Proto's proven soft rubber Sticky Grips.\n\n\n= Lockdown Clamping Feedneck =\nThe adjustable cam lock lever allows you to securely lock your Rotor onto your gun without tools. Dye's cam lock feedneck sits low and tight on the marker making sure your Rotor stays low profile with the rest of your gear. ", + "top_html_focus" : "", + "htmlvids" : "", + "page_title" : "Buy Proto Matrix Reflex Rail Online On Sale Now", + "top_description3" : "== Proto's Latest & Greatest ==\nHigh-end performance in a durable and reliable setup. The Proto Reflex Rail is for the serious competitor, featuring Fuse Bolt Technology, operating at 145psi. Color coded o-rings for simplified maintenance, and a host of other features to make the Reflex Rail the gun of choice. The durable Reflex Rail solenoid features consistent airflow with a dwell of 18 milliseconds. The small, light Hyper3 In-Line air regulator provides high flow and smooth velocity adjustment, with non-slips grips. The ultimate in ergonomic comfort, The Ultralite Frame is equipped with an adjustable Reach trigger. The solid construction consists of an aluminum body, bolt, Ultralite Frame and trigger. The Reflex comes with a precision honed two piece 14 inch barrel, durable zippered gun case, parts kit, Dye Slick Lube, barrel sock, allen key set and 9-volt battery.", + "head_title" : "Proto Matrix Reflex Rail | Proto Reflex Rail Paintball Guns | Proto Reflex Paintball Guns" + }, + ".markers.tippmann.tippmann_ft-12_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_joyride_polarized_sunglasses" : { + "meta_description" : "Suncloud Joyride Polarized Sunglasses - Zephyr Sports carries a complete line of Joyride Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Joyride Sun Glasses Online Today.", + "page_title" : "Suncloud Joyride Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Joyride Polarized Sunglasses | Joyride Suncloud Sunglasses Free Shipping | Buy Suncloud Joyride Sun Glasses" + }, + ".casual_clothing.mens_clothing.boots.oakley_boots" : { + "meta_keywords" : "oakley si boots,oakley boots,oakley tactical boots,oakley si assault boot,oakley sabot boot", + "meta_description" : "Oakley SI Boots - Get you Oakley Boots at Zephyr today. Free Shipping on all Oakley Tactical Boots. We support Active Duty Military and Police", + "page_title" : "Oakley SI Boots with Free Shipping at Zephyr", + "head_title" : "Oakley Boots | Oakley SI Boots | Oakley Tactical Boot" + }, + ".safetygear.tippmann" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_burnout_sunglasses" : { + "meta_keywords" : "Von Zipper Burnout sunglasses,VZ Burnout, Von Zipper polarized sunglasses,Von Zipper Burnout,VZ Burnout glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Burnout Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Burnout sunglasses now! For Von Zipper Burnout glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Burnout Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Burnout Sunglasses | Burnout Von Zipper Sunglasses | VZ Burnout Sunglasses" + }, + ".scenarioupgrades.stocks.tippmann_a_5_paintball_stocks" : {}, + ".apparel.jerseys.valken_paintball_jerseys.valken_crusade_paintball_jerseys" : {}, + ".airsystems.nitrogentanks.crossfirenitrogentanks" : { + "meta_keywords" : "Crossfire Tanks, Crossfire Paintball Tanks, Crossfire Nitrogen Tanks, Paintball Tanks, Nitrogen Tanks, Paintball Nitrogen Tanks, Crossfire Paintball Equipment, Crossfire Paintball Supplies, Crossfire Paintball", + "meta_description" : "Crossfire Tanks - Crossfire paintball tanks are just some of the supplies and equipment available online at ZephyrPaintball.com.", + "top_description" : "Zephyr carries a complete line of Crossfire Paintball Tanks. Crossfire has been the standard in quality Paintball HPA Tanks for years. All Crossfire tanks are made in the USA to the highest quality standards. With over 15 years of experience, Crossfire has you covered. All crossfire tanks come with a 5 year hydro stamp.", + "description" : "The Crossfire SS tank is the latest in high performance HPA tanks. Available in multiple sizes and their lightest carbon fiber air system to date. The bottle on the new Crossfire tanks are lighter than ever and have a very durable clear coat finish. The regulator on the new SS Crossfire tank is fully rebuildable and almost half the weight of the previous Crossfire tank regs. The New version of the tank comes with a ton of great safety features and is more reliable than ever. You can't go wrong with Crossfire.", + "page_title" : "Buy Crossfire Tanks Online On Sale Now", + "head_title" : "Crossfire Tanks | Crossfire Paintball Tanks | Crossfire Nitrogen Tanks", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&", + "page_head" : "Crossfire Tanks - Crossfire Paintball Tanks - Crossfire Nitrogen Tanks" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_clutch_sunglasses" : { + "meta_keywords" : "Von Zipper Clutch sunglasses,VZ Clutch, Von Zipper polarized sunglasses,Von Zipper Clutch,VZ Clutch glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Clutch Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Clutch sunglasses now! For Von Zipper Clutch glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Clutch Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Clutch Sunglasses | Von Zipper Clutch | VZ Clutch Sunglasses" + }, + ".barrels.barrels_by_manufacturer.custom_products_paintball_barrels.2_piece_barrels" : {}, + ".shop_by_brand.socom_gear_airsoft" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_chronicle_watches" : {}, + ".harnessesbags.paintball_gear_bags.tippmann_paintball_gear_bags" : { + "meta_description" : "Tippmann Gear Bag - Buy your Tippmann Duffle Bag Online at Zephyr Paintball for Less today. Free Shipping on Tippmann Backpack Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann Gear Bag Online On Sale Now", + "head_title" : "Tippmann Gear Bag | Tippmann Duffle Bag | Tippmann Backpack" + }, + ".apparel.gloves.voodoo_tactical_gloves" : { + "page_title" : "", + "head_title" : "Voodoo Tactical Paintball Gloves | Gloves Voodoo Tactical |Voodoo Tactical Paintballing Gloves" + }, + ".loaders.proto_paintball_loaders" : { + "meta_keywords" : "proto primo loader,primo paintball loader,proto paintball hopper, proto primo,proto gravity feed hopper, dye proto primo", + "meta_description" : "Proto Paintball Hopper - The Proto Primo Loader bring affordable gravity fed paintball loaders to the market. Improving on the basic plastic feeder we all started playing paintball with. The Proto Primo can compete with some entry level electronic loaders without the need for batteries. Get yours at Zephyr paintball Today.", + "page_title" : "Buy Proto Primo Loader Online On Sale Now", + "head_title" : "Proto Primo Loader | Proto Paintball Hopper | Proto Primo" + }, + ".casual_clothing.z_unisex_clothing_accesories.lanyards.c1rca_lanyards" : { + "meta_description" : "Circa Lanyards - Buy your Lanyards CircaAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Circa Lanyards @ Zephyr Sports", + "head_title" : "Circa Lanyards | Lanyards Circa | Lanyard Circa" + }, + ".casual_clothing.mens_clothing.beanies.alpinestars_beanies" : { + "meta_keywords" : "Alpinestars beanie,Alpinestars hat,Alpinestars beanies,Alpinestars caps,Alpinestars 686,Alpinestars headwear,Alpinestars cuff visor beanie,Alpinestars beanie hat,Alpinestars visor beanie,Alpinestars visor beanies", + "meta_description" : "Alpinestars Deanie - Surf style with Alpinestars Beanies available now at Zephyr Sports. Get your Alpinestars hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Alpinestars Beanies on Sale at Zephyr Today", + "head_title" : "Alpinestars Beanie | Alpinestars Hat | Alpinestars Beanies" + }, + ".harnessesbags.packs___harnesses.pcs_pod_packs" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.aug_airsoft_gun_magazines" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_cooper_xl_sunglasses" : { + "meta_description" : "Spy Cooper XL Sunglasses - Buy your Cooper Xl Spy Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Spy Cooper Xl at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Spy Cooper XL Sunglasses Now! On Sale & Free Shipping", + "head_title" : "Spy Cooper XL Sunglasses | Cooper Xl Spy Sunglasses | Spy Cooper Xl" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_loaders.empire_halo_too_loader" : {}, + ".apparel.head_bands_and_wraps.sly_headbands_and_wraps" : {}, + ".casual_clothing.mens_clothing.accessories.audio___headphones.skullcandy_headphones" : { + "meta_keywords" : "Skullcandy Headphones,Skullcandy Head Phones, Skullcandy Audio", + "meta_description" : "Skullcandy Headphones - Zephyr stock a complete line of Skullcandy Head Phones. For the ultimate Audio experience buy your Skullcandy at Zephyr Today", + "page_title" : "Skullcandy Headphones with Free Shipping at Zephyr", + "head_title" : "Skullcandy Headphones | Skullcandy Head Phones" + }, + ".2clearance.clearance_harnesses" : { + "meta_keywords" : "cheap paintball harnesses, clearance harness, cheap pod pack, clearance pod pack, cheap paintball pod pack, clearance pod packs", + "page_title" : "", + "head_title" : "Cheap Paintball Harnesses | Clearance Harness | Cheap Pod Pack" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_miss_conduct_sunglasses" : { + "meta_keywords" : "Oakley Miss Conduct Womens Sunglasses,Miss Conduct Womens oakley sunglasses,oakley Miss Conduct Womens, Miss Conduct Womens polarized sunglasses", + "meta_description" : "Oakley Miss Conduct Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Miss Conduct Womens and Polarized Oakley Miss Conduct Womens Sunglasses on Sale! ", + "page_title" : "Oakley Miss Conduct Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Miss Conduct Womens Sunglasses | Miss Conduct Womens Oakley Sunglassses" + }, + ".2clearance" : { + "meta_keywords" : "paintball sale,paintball sale gear,sale paintball,sale paintball gun,sale paintball gear,paintball discount,discount paintball", + "zs11_banner_wslideshow_slide1" : "ALT=Proto+Reflex+Rail+%2b+Dye+Rotor+%3d+FREE+Dye+I4+Goggle%21&IMG=&LINK=%25SESSION%25%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3dREFLEXI4PROMO%26x%3d39%26y%3d0", + "prodlist2_title" : "Featured Clearance Items", + "zs11_banner_wslideshow_slide3" : "ALT=PRICE+DROP%21%21%21+Dye+DM+13+Tournament+Paintball+Guns+On+SALE%21&IMG=banners%2fpaintball%2fslideshow%2fdye_dm13_paintball_makers_slideshow_template%2ejpg&LINK=%25SESSION%25%2fcategory%2f2clearance%2eclearance_paintball_guns%2f%3fsortby%3d%21zoovy%253Abase_price%26size%3d15", + "page_title" : "Paintball Sale Gear at Zephyr Paintball", + "zs11_banner_wslideshow_slide2" : "ALT=Empire+Hopper+Sale%21+Save+NOW%21&IMG=banners%2fpaintball%2fslideshow%2fempire_hopper_pricedrop_slideshow%2ejpg&LINK=%25SESSION%25%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3dPRICEDROP%26x%3d15%26y%3d1", + "subcat1_header" : "Clearance Categories", + "meta_description" : "Paintball Sale Gear - Discount paintball and clearance gear. Save 50% or more with Sale paintball gear from Zephyr Paintball", + "top_description" : "== HUGE Savings Across the Board! ==", + "banner01_link" : "", + "prodlist1_header" : "Featured Clearance Items", + "zoovy:banner01" : "", + "description" : "Save 50% or more with sale paintball gear. Last years gear for less, Our loss is your gain. Sizes and color choices may be limited and when it's gone, it's gone for good. Buy your paintball sale gear while supplies last.", + "prodlist1" : "&FORMAT=THUMBMSRP&SRC=&", + "zs11_banner_wslideshow_slide4" : "ALT=Save+Over+20%25+Off+Empire+BT+Etacs+Gear%21&IMG=banners%2fpaintball%2fslideshow%2f2empire_bt_tht_slideshow_template%2ejpg&LINK=%25SESSION%25%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3de%2dtacs%26x%3d29%26y%3d14", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "zs11_banner_wslideshow_slide5" : "ALT=%2425+Dye+I4+Goggle+w%2f+Dye+UL+Pant+%26+Jersey+Purchase%21&IMG=&LINK=%25SESSION%25%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3d25ULI4%26x%3d12%26y%3d9", + "banner1" : "banners/09_headers/main_categories/clearance_items_001", + "head_title" : "Paintball Sale Gear | Discount Painmtball | Sale Paintball Gear", + "header1" : "Featured Products" + }, + ".markerupgrades.invert_upgrades.feed_necks" : { + "meta_description" : "Invert Mini Feednecks - Buy your Feed Neck for Invert Mini Online at Zephyr Paintball for Less today. Free Shipping on Mini Feedneck Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert Mini Feednecks Online On Sale Now", + "head_title" : "Invert Mini Feednecks | Feed Neck for Invert Mini | Mini Feedneck" + }, + ".airsoft.tactical_airsoft_gear.tactical_thigh_rigs.full_clip_thigh_rigs" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.famas_airsoft_gun_magazines" : {}, + ".airsoft.tactical_airsoft_gear.head_gear" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.hoven_sunglasses" : { + "meta_keywords" : "Hoven Vision,Hoven Optics,Hoven Sunglasses,Hoven eyewear,Hoven Sunglass,Hoven,Hoven shades", + "meta_description" : "Hoven Eyewear - Hoven Optics has all the style and function you need. High quality designs of polarized sunglasses with hand crafted frames. Hoven Vision features an array of styles and colors. Pick up a pair of Hoven sunglasses today!", + "page_title" : "Hoven Sunglasses", + "head_title" : "Hoven | Hoven Sunglasses | Polarized Sunglasses" + }, + ".shop_by_brand.condor_tactical" : {}, + ".harnessesbags.backpacks.dvs_backpacks_and_bags" : {}, + ".airsoft.tactical_airsoft_gear.tactical_gloves.maddog_sports" : {}, + ".scenarioupgrades.barrels.spyder_tactical_barrels" : {}, + ".airsoft.airsoft_spare_magazines" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Mags | Airsoft Gun Magazines |Airsoft Pistol Mags" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_tach_watches" : {}, + ".shop_by_brand.test" : {}, + ".buyers_guide.paintball.paintballs" : {}, + ".apparel.jerseys.empire_paintball_jerseys.empire_ze_paintball_jerseys" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_headwear.tanked_clearance_hats" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.ares_electric_airsoft_guns" : { + "meta_description" : "Ares Airsoft Guns - Buy your Ares Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Ares AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Ares Airsoft Guns On Sale & Free Shipping", + "head_title" : "Ares Airsoft Guns | Ares Airsoft Rifles | Ares AEG" + }, + ".markers.dye_matrix_paintball_guns.dye_dm14_paintball_guns" : { + "zs_banner_right5" : "ALT=&IMG=&LINK=", + "htmlvids" : "", + "top_description2" : "Dye has revamped the DM series paintball markers for 2014. The DM-14 represents over ten years of paintball marker evolution. Dye athletes demanded perfection, so that's what Dye strived for in all of their design decisions. Revamped and rebooted, the DM-14 is smaller and more air efficient that previous incarnations of the DM, with a streamlined design, nearly half and inch shorter than the DM-13. It is also easier to clean and maintain than ever before. When you take the field you an be sure DYE has spared no expense in putting pure performance in you hands, as the DM Series has been born again.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/slideshow/dye_dm14_slideshow_template.jpg", + "description" : "== Dye DM14 Features: ==\n\n= Gas-Thru =\nThe DM14 is the first gas-thru tournament marker from Dye. The macro line has been removed to improve ergonomics and durability. Switching hands in tight situations has never been quicker or easier.\n\n\n= Low Profile Design =\nThe DM14 has the lowest profile of any marker in the DM series. At nearly ½ an inch shorter, the DM14 is streamlined for the most competitive profile possible. To accomplish this the LPR ha s been moved to the front and redesigned into a self contained cartridge for easy maintenance.\n\n\n= Reach Airport =\nMove your tank forward or backward to get the best fit for any tank and any player. The floating ASA holds the balanced cam lever system on/off toggle. When the knob is in the locked on position, air is delivered to the marker through the frame for maximum comfort and streamlined design. When released, trapped air is vented, allowing easy removal of tanks, reducing wear on regulator threads and o-rings.\n\n\n= Hyper 4 Regulator =\nThe Hyper 4, the latest generation of Dye's trusted line of regulators, is the most reliable and consistent regulator Dye has ever made with the fastest disassembly available. Standard maintenance can be complete in under a minute, ensuring the best performance for your DM, day in and day out.\n\n\n= Quick Release Magnetic Bolt =\nThe all new Quick Release Bolt Assembly is the fastest, easiest and most reliable bolt removal system on the market. A simple, one-touch spring loaded button allows the user to remove and re-install the bolt kit in seconds. Standard maintenance has never been easier or more accessible.\n\n\n= Eye Pipe Plateless Enclosure =\nThe polycarbonate Eye-Pipe shields the anti-chip eye system from dirt and broken paint, creating a self-cleaning system that ensures the eyes are always monitoring the breech and ball drop. The seamless pipe is wiped clean by the bolt tip-O-ring on every singe firing cycle.\"" + }, + ".harnessesbags.paintballpodloaders.valken_pod_loaders" : {}, + ".markers.us_army_paintball_guns.us_army_packages" : { + "meta_description" : "Tippmann Alpha Black Package - Buy your Tippmann Army Package Online at Zephyr Paintball for Less today. Free Shipping on US Army Alpha Black Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann Alpha Black Package Online On Sale Now", + "head_title" : "Tippmann Alpha Black Package | Tippmann Army Package | US Army Alpha Black" + }, + ".markers.empire_axe_paintball_guns.empire_resurrection_paintball_guns" : { + "meta_keywords" : "Empire Resurrection,Empire Paintball Markers,Empire 2013 Paintball Guns,pump paintball,ressurection paintball gun,ressurection,resurrection,ressurrection", + "meta_description" : "The Empire Ressurection is the Autococker reborn! All New for 2013, the Empire Resurrection Paintball Marker is loaded with all the bells and whistles! Pump Paintball is back with the 2013 Empire Resurrection Paintball Gun.", + "top_description" : "= Empire Ressurection Paintball Markers =\nNew school style with old school accuracy! The Empire Ressurection is The Autocker reborn! Taking the best of proven designs, Empire has created a super smooth and accurate 'cocker that players of all skill levels will love! With plenty of bells and whistles already installed, the Ressurection paintball gun just might live up to the beloved Autococker legacy... Pick one up and see for yourself...", + "page_title" : "Empire Resurrection Paintball Markers Online On Sale Now", + "head_title" : "Empire Resurrection | Empire Paintball Markers | Empire 2013 Paintball Guns", + "description" : "= Features: =\n\n* Closed Bolt System for Extreme Accuracy\n* Low Pressure Operation\n* Incredibly stable firing platform\n* 45 Frame molded wrap around grips with finger grooves\n* Slide Trigger Frame with Trigger Shoe\n* Aluminum 2-piece 14\" barrel\n* Dual Soft Rubber Detents\n* Quick Strip Delrin Bolt\n* 6 pc Sniper Barrel Kit: Aluminum Tip + 5 sized backs (.675, .680, .685, .690, .695)\n* Adjustable LPR (Low Pressure Regulator)\n* Quick Lever On/off Bottom line ASA\n* Clamping Feedneck with Thumb Adjustment\n* Built on the all new Sniper Pump Platform\n\n\n\n\n\n" + }, + ".casual_clothing.z_unisex_clothing_accesories.cell_phone_cases.nixon_cell_phone_cases" : { + "meta_description" : "Nixon Phone Cases - Buy your Nixon Iphone CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Iphone Cases On Sale", + "head_title" : "Nixon Phone Cases | Nixon Iphone Cases" + }, + ".casual_clothing.z_shoes_and_footwear.rothco_boots_and_shoes" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs.women_s_camelbak_charm_hydration_packs" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_fixed_power_scopes.bushnell_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_capt_ahab_sunglasses" : {}, + ".skateboard_gear.skateboard_longboards.sector_9_longboard_skateboards.sector_9_sea_shephard_series_longboards" : {}, + ".2clearance.clearance_jerseys___apparel.under__5__/" : {}, + ".airsoft.airsoft_accessories.airsoft_bbs_speedloaders" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_harnesses" : {}, + ".airsoft.airsoft_bbs_ammo.flying_colors_airsoft_bbs" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_rotolog_watches" : {}, + ".casual_clothing.mens_clothing.accessories.audio___headphones.nixon_headphones.nixon_rpm_headphones" : {}, + ".markerupgrades.smartparts.epiphany.epiphany_trigger_upgrades" : {}, + ".airsoft.airsoft_guns.1_shop_by_gun_type.e90_airsoft_guns" : { + "meta_description" : "E90 Airsoft Guns - Buy your Airsoft E90 At Zephyr Sports for Less Today! We carry a complete line of E90 AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "The E90 weapon system is considered a Personal Defense Weapon (PDW), and is designed as a compact but powerful firearm for vehicle drivers, operators of crew-served weapons, support personnel, special operations and anti-terrorist units operating in Close Quarters Battle (CQB). ", + "page_title" : "Buy E90 Airsoft Guns On Sale & Free Shipping", + "head_title" : "E90 Airsoft Guns |Airsoft E90 |E90 AEG", + "description" : "" + }, + ".casual_clothing.youth_clothing.youth_pants" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.desert_eagle_airsoft_guns" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_running_hydration_packs.camelbak_octane_24_hydration_packs" : {}, + ".markerupgrades.planet_eclipse_ego_upgrades.ego_grips" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.nixon_headphones" : { + "meta_keywords" : "nixon headphones,headphones nixon,whip,nomadic,master blaster,wire,nixon ear buds", + "meta_description" : "Nixon Headphones - Listen to your ipod in style with some new headphones from Nixon. Zephyr carries a complete line of Nixon headphones and ear buds at the lowest prices on the web", + "page_title" : "Nixon Headphones with Free Shipping at Zephyr Sports", + "head_title" : "Nixon Headphones | Nixon Head Phones | Headphones Nixon" + }, + ".goggles.proto.proto_axis_pro_paintball_goggles" : { + "meta_keywords" : "proto axis goggles,proto axis thermal paintball goggles,proto axis pro thermal paintball goggles,proto axis pro mask,proto axis goggle,proto axis paintball goggle\r ", + "meta_description" : "Proto Axis Goggles - Proto Axis Pro Thermal Paintball Goggles are the ultimate tournament goggle from Proto Paintball. Starting at $49.95, we have the Proto Axis Pro Mask your looking for for less with Free shipping over $100", + "page_title" : "Buy Proto Axis Goggles Online On Sale Now", + "head_title" : "Proto Axis Goggles | Proto Axis Pro Thermal Paintball Goggles | Proto Axis Pro Mask" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.matix_pants_and_jeans" : { + "meta_keywords" : "Matix pants,Matix denim,Matix pant,Matix jean,stretch Matix pants,Matix cargo pants,Matix mens jeans,Matix denim jeans,Matix mens pants,stretch Matix pant,Matix feeble pant", + "meta_description" : "Matix Pants - Huge selection of Matix Denim Pants available online at Zephyr Sports. Always the best price, Always free shipping over $75. Buy your Matix Jeans online Now!", + "page_title" : "Matixs Pants & Jeans with Free Shipping", + "head_title" : "Matix Pants | Matix Denim Pants | Matix Jeans" + }, + ".markerupgrades.grips_and_grip_panels.smart_parts_paintball_grips" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches" : { + "meta_keywords" : "nixon watches,nixon watch,time teller,player,51-30,watches Nixon,Nixon Player,lodown,banks,rotolog,scout", + "meta_description" : "Nixon Watches - Zephyr Carries a complete of watches from Nixon. Get your Nixon watch today with free shipping at Zephyr Sports. From the Player to the Time Teller we have you covered", + "page_title" : "Nixon Watches Free Shipping at Zephyr Sports", + "head_title" : "Nixon Watches | Nixon Watch | Watches Nixon" + }, + ".casual_clothing.mens_clothing.watches" : {}, + ".markerupgrades.tippmann.model98customandpro.custom_98_feed_upgrades" : {}, + ".loaders.hopper_accesories.odyssey_halo_accesories.halo_shells" : { + "meta_description" : "Halo B Replacement Shells - Buy your Halo Paintball Shells Online at Zephyr Paintball for Less today. Free Shipping on Halo Shell Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Halo B Replacement Shells Online On Sale Now", + "head_title" : "Halo B Replacement Shells | Halo Paintball Shells | Halo Shell" + }, + ".casual_clothing.mens_clothing.beanies.spitfire_beanies" : { + "meta_keywords" : "Spitfire beanie,Spitfire hat,Spitfire beanies,Spitfire caps,Spitfire 686,Spitfire headwear,Spitfire cuff visor beanie,Spitfire beanie hat,Spitfire visor beanie,Spitfire visor beanies", + "meta_description" : "Spitfire Deanie - Surf style with Spitfire Beanies available now at Zephyr Sports. Get your Spitfire hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Spitfire Beanies on Sale at Zephyr Today", + "head_title" : "Spitfire Beanie | Spitfire Hat | Spitfire Beanies" + }, + ".apparel.gloves.sly_paintball_gloves" : { + "meta_keywords" : "sly paintball gloves,pro merc paintball gloves,gloves paintball sly,promerc sly gloves", + "page_title" : "", + "head_title" : "Sly Pro Merc Paintball Gloves | Sly Paintball Gloves", + "prodlist1_header" : "Sly Pro Merc Paintball Gloves" + }, + ".tech" : { + "top_html_focus" : "\n
                                                                          \n\n", + "top_description" : "Need some help getting your gear setup? Something not quite working how you want it? We're here to help. We have Gun Techs for paintball and airsoft on hand to help you get your gear working right the first time. Click the link below for Tech Support" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_tanks.tippmann_paintball_tanks" : {}, + ".category/apparel.jerseys.planet_eclipse_paintball_jerseys/" : {}, + ".videos_page" : {}, + ".apparel.head_bands_and_wraps.infamous_paintball" : {}, + ".casual_clothing.youth_clothing.youth_sweatshirts.1-search_by_size.4-x-large" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.king_arms_aeg_electric_airsoft_rifles" : { + "meta_description" : "King Arms Airsoft Guns - Buy your King Arms Airsoft At Zephyr Sports for Less Today! We carry a complete line of King Arms Airsoft Rifles at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy King Arms Airsoft Guns On Sale & Free Shipping", + "head_title" : "King Arms Airsoft Guns | King Arms Airsoft | King Arms Airsoft Rifles" + }, + ".testing_help_desk.warranty" : { + "hd_answer_four" : "==30 Day Money Back Guarantee==\nGo ahead and try that new pair of shades out for 30 days. NO RISK! When you buy any pair of sunglasses from ZephyrSunglasses.com you get a 30 day money back guarantee! If for some reason you do not like your item you can return them for a full refund of your purchased price provided that you file a money back return request within 30 days of delivery.\n\n\n==Terms and Conditions:==\nA refund will be issued for full purchase amount minus shipping. Shipping is not included if you change your mind.\n\n\nYou will have 30 days from the date that you receive your item for your trial period. You must file before your 30 days are up to qualify for the money back guarantee.\n\n\nYour item must be unused and in brand new condition, so that we can resell the item as a brand new product. This includes the packaging and accessories, all items must be in brand new unused condition with original tags attached.\n\n\nYou must contact us for a RMA # before sending the item back to us.\n\n\nYou will then ship back the item to us and upon receiving the product and inspecting it, we will contact you.\n\n\nPlease allow 8-12 business days for processing.\n\n\nZephyr Sunglasses Returns\n\n2970 Seaborg Ave\n\nVentura, CA., 93003", + "hd_question_three" : "Do Paintballs Have a Warranty?", + "hd_question_four" : "Money Back Guarantee on Sunglasses.", + "hd_answer_three" : "There is no warranty on paintballs. Zephyr Sports will inspect each bag to make sure there are no breaks prior to shipping, plus we will inspect the outside of every box that is shipped for any sign of damage. All of the products we sell have air pillows surrounding the product when we package them, this is to insure safe delivery. We cannot control the way a package is handled once it has left our warehouse. In some instances, small paint breaks can be contained. By taking the bag of paint with the broken ball and lightly rubbing them down with an old towel, you can easily restore the paintballs to pristine condition. Also, note that there will be a little bit of oil in each bag, this is not a break, the oil is used by the manufacturer in order to keep the balls fresh. \n\n\nPaintballs damaged in transit by either weather conditions or rough handling are the customer's responsibility! Be sure to inspect the package when the product is delivered. If you need to file a claim for damaged goods please contact us at 877-814-4297 within 3 days of receiving your package. We will then file a claim with Fedex. ", + "hd_question_two" : "Who Should I Contact for Warranty Repairs?", + "hd_answer_two" : "*Ariakon - 877-427-4256\n*Brass Eagle/View Loader - 800-861-6095\n*CCI - 503-554-8095\n*Crossfire - 269-344-7600\n*Crosman - 800-724-7486\n*Custom Products - 480-539-4820\n*DOP - 765-286-9725\n*Dye/Proto - 858-536-5183\n*Dangerous Power - 909-869-7800\n*DXS/VForce - 866.688.8880\n*Echo1 USA - 626-448-9879\n*Guerilla Air - 847-640-9080\n*Indian Creek - 208-468-0446\n*J & J - 330-567-2455\n*JT USA - 800-587-2246\n*Kingman/Spyder - 888-546-4626\n*Lapco - 800-640-8085\n*Maddog Designz - 805-275-0927\n*Ninja Paintball - 877-646-5287\n*New Designz - 860-384-1810\n*Palco Sports - 866-2604908\n*Planet Eclipse - 401-247-9061\n*Redz - 877-873-3432\n*Shocktech - 708-862-4776\n*Smart Parts - 800-992-2147\n*TechT - 901-258-1976\n*Tiberius - 888-982-2842\n*Tippmann - 800-533-4831\n*Virtue - 631-617-5346\n*WDP - 617-830-1891\n*Worr Games - 800-755-5061\n*Paintball Solutions — BT, Diablo, Empire/Invert, PMI, Psycho Ballistics, 32 Degrees and Halo - 800-220-3222", + "hd_question_six" : "General Airsoft Warranty", + "hd_question_five" : "Breakage Protection Plan on Sunglasses.", + "hd_topic_listing" : "» My Product is broken or doesn't work.
                                                                          \n» Who should I contact for warranty repairs?
                                                                          \n» Do paintballs have a warranty?
                                                                          \n» Money Back Guarantee on sunglasses.
                                                                          \n» Breakage Protection Plan on sunglasses.
                                                                          \n» General Airsoft Warranty.
                                                                          ", + "hd_question_one" : "My Product is Broken or Doesn't Work.", + "hd_topic" : "Warranty", + "hd_answer_five" : "All sunglasses purchased from Zephyr come with Breakage Protection for ONE YEAR!\n\n\n==How it works==\nFirst, shop Zephyr and get yourself a pair of sunglasses.\n\n\nIf you so happen to damage them in the first year, just contact us and explain what happened. We can then replace your sunglasses with an identical pair AT COST plus replacement shipping.\n\n\nThe Breakage Protection Plan will cover your purchase for one year from the original purchase date. Any and all replacement sunglasses fall within the same time line as the ORIGINAL purchase.\n\n\nThis plan does not cover lost or stolen items.\n\n\n==How to redeem==\nYou will need to return your damaged glasses to receive this coverage plan. Please contact us via phone call to get your RMA number; otherwise your package will be refused.\n\n\nWe will need your original order number as well. You received an email and a printed copy in your order with this information. Please include a copy with your damaged sunglasses. You will also be instructed to write clearly, your RMA number on the outside of the package.\n\n\nYou will then send back the damaged item for approval.\n\n\nOnce received, we will contact you for payment for the replacements sunglasses. We will then ship your new pair to you.", + "hd_btn" : "images/site_specific/backto_helpdesk", + "hd_answer_six" : "All products come with a manufacturers warranty of 30 days unless otherwise stated. If an item breaks or malfunctions under normal use you may request a RMA# within 30 days of delivery and return the item with the given RMA# for repair or replacement. Once a gun has been fired it is considered used and is NOT eligible for a refund. If due to lack of availability the item can not be replaced with the same model, a store credit will be issued instead of replacement.\n\n\nWe do not issue prepaid shipping labels for warranty service. The customer is responsible for shipping the product to Zephyr Sports. However we will cover the shipping of the serviced product back to you.\n\n\nThe warranty is void if the item is altered or abused (Examples: altering or removing the orange tip, disassembling, reusing BBs or shooting wrong type, weight or grade of BB, using paintballs or low quality BBs, dropping or mishandling the product).\n\n\nUse of BBs found at local sporting goods stores (Wal-Mart, Dick’s, Sports Authority) will void all warranty on your airsoft gun. Those BBs are exceptionally low quality and will cause major issues with your airsoft gun. Please only get your BBs from dedicated airsoft shops or websites.\n\n\nSome airsoft guns such as AEGs and Gas Guns require a specific grade of BBs known as High Polished. These are manufactured by such brands as KSC, Excel, Airsoft Elite, ECHO 1, TSD, Mad Bull, Tokyo Marui, Systema, Toy-tec, SIIS, Maruzen and Digicon. Use of any other brand in your AEG or Gas Gun will void its warranty.\n\n\nIf you take your gun apart the warranty is void! DO NOT take the gun apart or try to fix your gun unless under instruction from our service department.\n\n\nDamage sustained during use in \"war games\" is not covered under warranty. In other words if you bought a car that was under warranty and ran it into a pole, the dealership isn't going to fix your car due to your negligence; so if a gun is hit against a tree or damaged from opposing gunfire the manufacturer will not pay to repair or replace the gun.\n\n\nThe warranty on some items is covered by the manufacturer or importer and does not fall under the Zephyr Sports warranty. These items will need to be returned to the importer or manufacturer for repair or replacement. We do not issue prepaid shipping labels. The customer is responsible for shipping the product.\n\n\n===“The item I purchased did not work when I got it. Why do I have to pay to ship it back when it came to me broken?”===\n\nAll returns need to be evaluated by a Certified Airsoft Gun Technician to eliminate possible user error. If, after the evaluation, it is determined that the item in question has a manufacturers defect causing it to be unoperable out of the box, in most cases you will be compensated for the return shipping in the form of a store credit or a gift certificate. Under no condition will a refund be issued for return shipping costs. Compensation will cover base ground shipping and excludes expedited delivery, additional packing, insurance fees or other non essential services.\n\n\nZephyr Sports makes every effort to be as reasonable as possible. For example if you have done something to your gun so that it is no longer covered under warranty please just tell us the truth and we will do our best to help you. We understand accidents do and will happen so please be as accurate as possible when explaining how your gun broke.", + "hd_answer_one" : "If you receive a broken or damaged item or if the item seems to be defective right out of the box, please give us a call at 877-814-4297. We then can further instruct you whether to contact the manufacturer for assistance or provide you with an RMA number, all depending on the circumstance.", + "hd_link" : "/category/testing_help_desk" + }, + ".goggles.1goggle_accesories.hk_army_goggle_accessories" : { + "top_description" : "== HK Army KLR Paintball Masks and Accessories are available for Pre-Order ONLY. We expect to begin shipping in June. Payment will be processed at time of purchase and will reserve your mask for our first shipment. ==", + "zoovy:banner01" : "banners/paintball/headers/hk_army_klr_goggles_header.jpg" + }, + ".1newitems.2008_products.2008_virtue_paintball_gear" : {}, + ".airsystems.nitrogentanks.custom_products_nitrogen_tanks" : { + "meta_description" : "CP Air - Buy your Custom Products HPA Tank Online at Zephyr Paintball for Less today. Free Shipping on CP Air Paintball Tanks Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy CP Air Online On Sale Now", + "head_title" : "CP Air | Custom Products HPA Tank | CP Air Paintball Tanks" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns" : { + "meta_keywords" : "electric airsoft guns, electric airsoft rifles, aeg, aegs, airsoft aeg, aeg airsoft,airsoft rifle", + "meta_description" : "", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "", + "description" : "" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.alpinestars_youth_t_shirts" : {}, + ".casual_clothing.mens_clothing.accessories.cell_phone_cases.alpinestars_cell_phone_cases" : { + "meta_description" : "Alpinestars Phone Cases - Buy your Alpinestars Iphone CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Alpinestars Iphone Cases", + "head_title" : "Alpinestars Phone Cases | Alpinestars Iphone Cases" + }, + ".casual_clothing.mens_clothing.accessories.lanyards.oakley_lanyards" : { + "meta_description" : "Oakley Lanyards - Buy your Oakley Stretch LanyardsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Oakley Lanyards @ Zephyr Sports", + "head_title" : "Oakley Lanyards | Oakley Stretch Lanyards" + }, + ".shop_by_brand.leapers_utg" : {}, + ".casual_clothing.mens_clothing.wallets.sandana_wallets" : { + "meta_description" : "Sandana Wallets - Buy your Sandana Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Sandana Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Sandana Wallets on Sale @ Zephyr Sports", + "head_title" : "Sandana Wallets | Sandana Mens Wallets | Sandana Wallet" + }, + ".loaders.empire" : { + "meta_keywords" : "Empire Loaders, halo too,Empire Prophecy,Empire Magna,Paintball Loaders Empire, Paintball Empire Loader, Paintball Loaders, Loaders Empire, Empire Loader, Empire Paintball Supplies, Empire Paintball, Empire Paintball Equipment, prophecy z2,z2 prophecy", + "meta_description" : "Empire Prophecy Z2- Full Line of Empire paintball Loaders available now. Empire halo too, Prophecy Z2 Empire BT Rip Clip and More. Lowest Prices guaranteed. Free SHipping on orders over $100. Check out paintball Empire loaders online at ZephyrPaintball.com.", + "top_description" : "Empire Paintball Loaders are built for tournament paintball. Starting with the Empire Halo too at 20+BPS you get insanely fast feed rates and sound operated feed operation so your loader will feed on every shot. The Empire Prophecy Z2 is the latest in high end tournamnet level paintball loaders. The Z2 holds 180 paintballs and features tool free disassembly along with the Rip drive and RF upgradeability to link your gun and your hopper together. Empire didn't want the scenario guys to miss out, so they ame out with with BT Rip clip that is compatible with all BT combat based guns as well as the BT Delta, Delta Elite, TM7 and TM15. The BT Rip clip provides sound activated operation as well as a rip drive.", + "banner02_link" : "/category/loaders.hopper_accesories.empire_hopper_accesories/", + "zoovy:banner01" : "banners/paintball/slideshow/empire_hopper_pricedrop_slideshow.jpg", + "zoovy:banner02" : "banners/paintball/headers/hopperaccessories_header001.jpg", + "description" : "The latest paintball loaders from empire paintball include the Empire Prophecy Z2 Loader as well as the Halo Too and Rip Clip Loaders. The Prophecy Z2 loader is the ultimate in tournament loaders. Insane feed rates, no tools disassembly, sound activated and rf chip ready. The Empire Prophecy Z2 holds 200 paintballs and includes the rip drive system. If your looking for a high end tournament loader, you can't beat the Prophecy Z2 loader.\n\nNot ready to spend $150+ on your next hopper? Take a look at the Empire Halo TOO. Feeding 20+BPS and costing about $75, the Halo too gives you alot of bang for your buck. Built on time tested Halo belt drive technology, the Halo too is sound activated and can be upgraded with the rip drive to manually get through those occasional jams. The Empire Halo Too was rebranded in 2012 from Invert to Empire, no change in the loader, just a new logo on the side. The Halo Too holds 180 paintballs and includes the freeway anti jam for top performance.\n\nHave a BT Paintball Gun? The BT Rip Clip now works with all BT guns including the BT 4 Combat, Delta, TM7, TM15, Slice and Omega. The BT Rip clip gives you sound activated 15+ BPS performance and is RF compatible if your ready to link your gun with your hopper for ultimate performance. The Rip Clip has 3 adjustable speed and sound settings to get just the performance you need.\n\nEmpire paintball makes some of the best tournament Paintball Hoppers in the world. With the insane rate of fire of todays paintball guns, you need a high performance hopper to keep the paint flying. Built on the years of experience learned through the Halo hoppers, Empire released the Empire Magna Loader in 2008. This took many of the features of the popular Halo Loaders and improved upon them. The Empire Magna also added the Magna Clutch system. This was a group of adjustable magnets that controlled the amount of force incurred on a paintball. You could could now set your hopper to insane speeds and loosen up the clutch and you would never have broken paint in the hopper again.\n\n\nIn 2009, Empire released the Empire Prophecy Loader. This built on the lessons learned from the Magna Loader. The Prophecy includes the Magna Clutch system, RF technology, magnetic lid, rip drive and many other of the Magna features. Empire decided to return to the Halo style shell that paintball players were accustomed too. Empire was able to re-engineer the hopper to shave weight, lower the hopper profile, and increase the speed. The Prophecy also allows you to change the size of the hopper by installing different size nose cones. Players have the option of using the standard 240 round nose or switching to a 195 round or 260 round nose cone in a matter of seconds. The prophecy allows you to change your battery in seconds without any tools. The Empire Freeway Anti-jam which was released in 2008 as an upgrade for all current Empire and Halo Loaders is now included on the Prophecy Hopper. Be sure to check out our entire library of Prophecy loader Videos.", + "htmlvids" : "", + "head_title" : "Empire Prophecy Z2 Loaders | Empire Halo Too | Empire BT Rip Clip", + "page_title" : "Buy Empire Prophecy Paintball Loaders Online On Sale Now", + "prodlist_custom" : "&SORTBY=PRICE_DESC&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&", + "page_head" : "" + }, + ".casual_clothing.mens_clothing.tshirts.lucky_skateboard_t-shirts" : { + "meta_keywords" : "Lucky T Shirts,Lucky shirts,free shipping,Lucky TShirt", + "meta_description" : "Lucky T Shirts - Zephyr carries a complete line of Lucky Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Lucky T Shirts at Zephyr", + "head_title" : "Lucky T Shirts | Lucky Shirts | Lucky TShirt" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_running_hydration_packs.camelbak_annadel_hydration_packs" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_tool_pouch_backpacks" : { + "meta_description" : "Oakley Tool Pouch Backpacks - Buy your Oakley Tool Pouch Bag At Zephyr Sports for Less Today! We carry a complete line of Tool Pouch Oakley Packs at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Tool Pouch Backpacks On Sale & Free Shipping", + "head_title" : "Oakley Tool Pouch Backpacks | Oakley Tool Pouch Bag | Tool Pouch Oakley Packs" + }, + ".markerupgrades" : { + "meta_keywords" : "Paintball Marker Accessories, Cheap Paintball Markers,Paintball Marker, Paintball Guns, Paintball Equipment, Paintball Accessories, upgrades, paintball upgrades, marker upgrades, tippmann upgrades", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels/", + "btn2_link" : "", + "banner3" : "zephyr_buttons/boards_btn001", + "buttonname_03" : "", + "btn1_link" : "", + "top_html_focus" : "
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          ", + "banner4" : "zephyr_buttons/grips_btn001", + "page_title" : "Buy Paintball Gun Upgrades Online On Sale Now", + "btn3_link" : "", + "btn4_link" : "", + "banner5" : "zephyr_buttons/feedneck_btn001", + "buttonname_04" : "", + "add1_link" : "/category/barrels/", + "btn2" : "", + "banner2" : "zephyr_buttons/barrel_btn001", + "subcat1_header" : "", + "add4_link" : "/category/markerupgrades.feednecks", + "btn1" : "", + "meta_description" : "Time for something better, but do not have enough cash to get a new gun? No problem. Getting a new board for your gun will let it breath a new life. Or maybe it is time to get all those mods for your Tippmann you have always wanted.", + "buttonname_01" : "", + "btn3" : "", + "description" : "", + "btn_title" : "", + "banner1" : "banners/09_headers/main_categories/marker_upgrades_001", + "add2_link" : "/category/markerupgrades.rampingchipsboards/", + "htmlvids" : "", + "buttonname_02" : "", + "head_title" : "Paintball Gun Upgrades | Paintball Marker Upgrades | Upgrades for Paintball", + "sortby_var" : "Gun Type", + "page_head" : "", + "btn4" : "" + }, + ".markers.protopaintballguns.proto_m8_paintball_guns" : { + "banner1" : "banners/proto_m8_header", + "sortby_var" : "Proto Gun Type", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/proto_m8_header.jpg\"" + }, + ".3packagespecials" : { + "meta_keywords" : "Paintball marker package, paintball packages, paintball gun package,paint ball package, paintball starter packages, starter kit, beginner paintball package,Cheap packages,paintball marker", + "ad3_link" : "%SESSION%/category/3packagespecials.kingman_spyder_paintball_packages.spyder_victor_paintball_gun_packages/", + "add3_link" : "/results.cgis?catalog=&keywords=emx+1000&x=0&y=0", + "description2" : "We reserve the right to to replace items in kits for items of equal or greater value", + "banner4" : "banners/sm_promo/emx1000_package_specials_002.jpg", + "page_title" : "Buy Paintball Marker Packages Cheap Online On Sale Now", + "zs11_banner_wslideshow_slide2" : "ALT=Cheap+Dye+I4+w%2f+Dye+UL+Pant+%26+Jersey+Combo%21&IMG=&LINK=%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3d25ULI4%26x%3d12%26y%3d9", + "ad2_link" : "%SESSION%/category/3packagespecials.kingman_spyder_paintball_packages.spyder_fenix_paintball_gun_packages/", + "add1_link" : "/results.cgis?catalog=&keywords=Kingman+09+Spyder+RT&x=0&y=0", + "subcat1_header" : "Package Categories", + "meta_description" : "Paintball Marker Packages - Zephyr Paintball has your paintball packages. We carry a complete line of paintball gun packages from tippmann, spyder, US Army, Azodin, GOG and more. Be sure to contact one of our specialists at 805-275-2040 to answer any questions you have on paintball starter packages.", + "ad1" : "banners/paintball/side_banners/bt_omegatactical_sidebanner001", + "zoovy:banner01" : "", + "description" : "\n=Have questions? Not sure which package is right for you or your child? Give us a call at 805-275-2040 and let the pro's at Zephyr answer your questions=", + "header1" : "Featured Products", + "sortby_var" : "Brand", + "page_head" : "", + "zs11_banner_wslideshow_slide1" : "ALT=FREE+Dye+I4+w%2f+Proto+Reflex+Rail+%26+Rotor+Combo%21&IMG=&LINK=%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3dREFLEXI4PROMO%26x%3d39%26y%3d0", + "prodlist2_title" : "Featured Packages", + "banner3" : "banners/categories/small_header/tippa5_bronzepack_ad_001.jpg", + "ad2" : "banners/paintball/side_banners/1kingman_spyder_fenix.jpg", + "3widead_title" : "Popular Package Buys", + "banner2" : "banners/sm_promo/spyder_rt_packages_small_header_001.jpg", + "banner01_link" : "", + "prodlist1_header" : "Featured Paintball Packages", + "prodlist1" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=1&SHOWSKU=&SHOWQUANTITY=0&", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "banner1" : "banners/09_headers/main_categories/package_specials_001", + "ad3" : "banners/paintball/side_banners/spyder_victor_sidebanner001.jpg", + "add2_link" : "/product/3-KIT-A5BRZ/Tippmann_A5_Paintball_Gun_Black_Bronze_Starter_Package.html", + "htmlvids" : "\n", + "ad1_link" : "%SESSION%/results.cgis?catalog=&keywords=BT+Omega+Paintball&x=0&y=0", + "htmllinks" : "Tippmann Package | Spyder Paintball Package | US Army Package ", + "head_title" : "Paintball Marker Packages | Paintball Packages | Cheap Paintball Gun Packages" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_runaway_sunglasses" : { + "meta_description" : "Von Zipper Runaway Sunglasses - Zephyr Sports carries a complete line of Buy Runaway Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Runaway Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Runaway Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Runaway Sunglasses | Buy Runaway Von Zipper Sunglasses | Von Zipper Runaway Sunglasses Free Shipping" + }, + ".markers.kingmanspyder.spyder_mr5_paintball_guns" : { + "htmlvids" : "\n\n\n\n\n\n\n\n\n", + "meta_description" : "Proto SLG - The revolutionary new Proto Paintball SLG redefines affordable tournament paintball gun performance. The SLG Paintball Gun comes in two versions for 2009. the Ultralight SLG with a Dye Ultralight frame and standard SLG.", + "page_title" : "Buy Proto SLG Online On Sale Now", + "head_title" : "Proto SLG | Proto Paintball SLG | SLG Paintball Gun", + "description" : "The Proto SLG is the clear choice if you are looking for serious performance at an entry level price. Built on the patented Self-Closing Valve (SCV) Spool Platform, the Proto SLG paintball gun is constructed using a hybrid of aluminum and composite materials providing extreme durability and lightweight function. The streamlined two-piece bolt system operates at a low 145 psi. This low operating pressure results in superior accuracy, less paint breakage, and an impressive 1500 shots from a 68ci/4500psi tank. \n\nThe Proto SLG will work with compressed air, nitrogen, and CO2.\n\nImproved for 2010, the Proto SLG Paintball Marker now comes with color-coded o-rings for easy maintenance. Featuring a new smaller and lighter poppet solenoid, and a 320˚ degree Hyper3 swivel.\n\nUnmatched manufacturer support, continuous evolution of design, and meticulous engineering are just a few of the reasons that make Proto the first name in paintball.\n\nComes with a parts kit, Dye Slick Lube, and 9-volt battery to keep your paintball gun of choice at its peak level. The Proto SLG is available in Clear, Blue, Olive, and Red. Also be sure to check out our Proto SLG Packages." + }, + ".markers.invert_paintball_guns" : { + "meta_keywords" : "Invert Mini Paintball Guns, Invert Mini, Invert Mini Packages, Mini Invert,Invert Mini Gear,Invert Mini Supplies, Discount Invert Mini,paintball guns invert mini,invert mini gun,invert mini paintball,Invert mini marker,invert mini markers,invert mini semi,\r ", + "meta_description" : "Invert Mini Paintball Guns - Invert makes the best Tournament Paintball Guns. If your a beninner or a seasoned tournament player Grab an Invert Mini marker and get on the field", + "top_description2" : "The all new Invert Mini Paintball Gun from Invert Paintball. Weighing in at less than 2lbs, the Invert Mini is one of the best tournament level paintball paintball guns on the market. The Invert Mini features an autococker threaded paintball barrel for an easy upgrade. The hose-less design of the Invert Mini gun allows for a tighter grip on the marker so you can reduce your profile during the game. The Invert Mini will only run off of an HPA tank, co2 tanks are not compatible with the invert mini. Multi-point adjustable trigger allows for fine trigger adjustment. The front grip of the invert mini paintball gun houses the battery and the board. The stock invert mini board has multiple firing modes including psp and nppl tournament modes.", + "top_description" : "", + "description2" : "\n\n\n\n\n ", + "zoovy:banner01" : "", + "prodlist1_header" : "Invert Mini Paintball Guns", + "banner01_link" : "", + "zoovy:banner02" : "", + "description" : "Take a look at a completely different design. Experience no hoses, easy maintenance and a light setup. Inside the Mini you will find that all parts are organized for effortless servicing/cleaning. The board is located in the front grip giving quick access to change the battery or even for replacement of the board. The board is the \"brain\" of the mini - powered by a 9 Volt battery - it allows each player to configure their mini to their own personal needs, whether that be firing in semi-automatic or tricking it up to full auto. Changing the firing mode is only 1 out of the 5 functions the mini is capable of, but if you are just starting out and getting into paintball, the modes might be all that you want to tap into for now. Moving to the grips you will find a comfortable design that allows an easy grip for complete control while firing. Inside the grip is where your air transfer tube is located. What? Transfer what? Don't worry it's quite simple - Once you screw in the compressed air tank, the air begins to flow up the grips through the transfer tube - leading the air to the bolt making your gun ready to fire. DO NOT USE CO2 - this gun only operates on compressed air (any [[compressed air tank]:url= http://www.zephyrpaintball.com/category/airsystems.nitrogentanks/] will work fine). Overall the gun is great for both starters and experienced players due to its simplicity in design. \n\n\n\n=What can I do to upgrade my Invert Mini?=\n\nWhat's great about the Mini is how customizable it can be. The barrel is Autococker threaded allowing for a more accurate design. The board, as mentioned earlier, has multiple configurations to play around with but once you start getting into the sport more you may want to be able to shoot faster, have more modes and get the newest technology with much more features - well it's 100% upgradeable, check out Virtue to learn about all the fun stuff your Mini is capable of doing. Bolts, Feednecks, Triggers and many other parts can all be replaced so don't ever worry about not being able to upgrade with the Invert Mini\n\n\n=What Maintenance?=\n\nKeeping the barrel clean will insure consistency in accuracy. Unscrew the barrel from the gun and give it a good rinse with hot water. You may also want to grab a Squeegee when you are on the go. It's recommended to take out the bolt before game time and give it a good wipe down to make sure no paint settles. Use some gun lube all around the o-rings to prevent cracks causing air leaks. That's it! The Mini only requires a minimal amount of maintenance\n\n\n==Invert Mini Frequently asked questions==\n\n\n=Q - Can I use co2 with the invert mini?=\n A - No the invert mini is designed to only run off of compressed air. Use of co2 will damage the internals of the gun and will void your warranty.\n\n\n=Q - What kind of barrel comes on the invert mini?=\n A - The mini uses an autococker threaded barrel. The stock barrel is 11.5\" long.\n\n\n=Q - Can I replace the feedneck on the invert mini?=\n A - Yes, the mini has in ion/impulse threaded feedneck that can be replaced. The stock feedneck is one of the best on the market so replacement is typically not neccesary.\n\n\n=Q - What is the difference between an empire mini and and invert mini?=\n A - In 2012, the company that owns empire and invert decided to rebrand the mini as empire. No changes were made to the gun beyond logo changes on the gun.\n\n\n=Q - What does the Empire mini weigh?=\n A - The Invert Mini weighs less than 2 lbs. The mini is insanely light and manueverable.\n\n\n\n==Invert Mini pros and cons==\n=Pros=\n*Lightweight - Less than 2 lbs\n*Tournament ready board - Most popular tournament modes are already included with your mini\n*No external hoses - No more issues with macro line leaks and hoses in the way\n*Clamping feedneck to keep your hopper secure\n\n=Cons=\n*No on off asa - this can be upgraded down the road with the Empire relay on/off asa\n*Small size - If you have big hands the gun may be a little too small.\n", + "top_html_focus" : "", + "banner1" : "banners/categories/new_minis_header001", + "htmlvids" : "", + "head_title" : "Invert Mini Paintball Gun | Cheap Invert Mini Paintball Packages | Mini Invert Paintball Marker", + "page_title" : "Buy Invert Mini Paintball Gun Online On Sale Now" + }, + ".casual_clothing.mens_clothing.beanies.toy_machine_beanies" : { + "meta_keywords" : "Toy Machine beanie,Toy Machine hat,Toy Machine beanies,Toy Machine caps,Toy Machine 686,Toy Machine headwear,Toy Machine cuff visor beanie,Toy Machine beanie hat,Toy Machine visor beanie,Toy Machine visor beanies", + "meta_description" : "Toy Machine Deanie - Surf style with Toy Machine Beanies available now at Zephyr Sports. Get your Toy Machine hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Toy Machine Beanies on Sale at Zephyr Today", + "head_title" : "Toy Machine Beanie | Toy Machine Hat | Toy Machine Beanies" + }, + ".markerupgrades.rampingchipsboards.scenario_dreams" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.aftermath_airsoft_guns" : { + "meta_description" : "Aftermath Airsoft Guns - Buy your Aftermath Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Aftermath AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Aftermath Airsoft Guns On Sale & Free Shipping", + "head_title" : "Aftermath Airsoft Guns | Aftermath Airsoft Rifles | Aftermath AEG" + }, + ".casual_clothing.mens_clothing.tshirts.proto_t_shirts" : { + "meta_description" : "Proto T-shirts - Buy your Proto Apparel At Zephyr Sports for Less Today! We carry a complete line of Proto Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Proto T-shirts On Sale & Free Shipping", + "head_title" : "Proto T-shirts | Proto Apparel | Proto Shirts" + }, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.spyder_grip_panel" : {}, + "$threadprotectors" : {}, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_mr4_paintball_packages" : { + "meta_description" : "Spyder MR4 Tactical Paintball Packages - Buy your MR4 Spyder Scenario Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder MR4 Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder MR4 Tactical Paintball Packages Online On Sale Now", + "head_title" : "Spyder MR4 Tactical Paintball Packages | MR4 Spyder Scenario Paintball Guns Kit | Spyder MR4 Paintball Guns" + }, + ".goggles.save_phace_paintball_goggles.dope_series" : { + "meta_keywords" : "Save Phace Dope Series, Dope Series paintball goggles, save face dope series, dope paintball goggles, thermal paintball goggles, painted paintball mask, custom paintball mask", + "meta_description" : "Save Phace Dope Series Goggles. The Dope Series paintball goggle comes with a military grade anti fog and anti scratch single pane lens and Dope graphics. The graphics on these goggles are detailed and look incredible. Save Face Dope Series goggles do not include a Save Phace stuff sack or an extra lense. Dope Series Designs - Invader, Point-man, Voodoo Magic, Solar Fusion, and Dog Phace.", + "page_title" : "Buy Save Phace Dope Series Online On Sale Now", + "head_title" : "Save Phace Dope Series | Dope Series Paintball Goggles | Save Face Dope Series" + }, + ".3packagespecials.empire_paintball_packages.empire_bt.tm7" : { + "meta_keywords" : "Battle Tested TM7,bt tm7, tm 7 paintball gun, TM7 Marker, BT Paintball\r ", + "htmlvids" : "
                                                                          \n\n
                                                                          ", + "meta_description" : "BT TM7 Paintball Gun - The hottest Tactical Paintball Gun From Empire Battle Tested. Get your Battle Tested TM7 from Zephyr today with Free Shipping. TM 7 Paintball Marker on sale now at Zephyr", + "top_description" : "The BT TM-7 utilizes Mini Technology to inflict maximum force from a marker of minimal size. Don't be fooled by the size of the TM-7's exterior; it can hang with the big boys and is by no means a lightweight. Once you hold this marker and pull the trigger, you won't want to put it down. Its lightweight, yet durable construction is perfect for close quarters or long-range combat. This is the marker that just may have people rethink the way they looked at Mil-Sim paintball markers.", + "page_title" : "Buy BT TM7 Paintball Packages Online On Sale Now", + "head_title" : "BT TM7 Paintball Guns | Battle Tested TM7 | TM 7 Paintball Marker", + "description" : "Mounting cool accessories is simple with the BT TM-7 paintball gun. The multiple Picatinny rails will fit optics, sights, lasers, flashlights, or anything needed to improve your experience. The lightweight construction matched with the folding Foregrip and adjustable stock allow for comfortable all-day play. Like the Mini, the TM-7 has no external hoses, giving it a clean look and the authentic feel of the real-world firearm it's based on. No paintball gun has the look and technology to match the TM-7 while in the field. Watch your opponents run when you switch to full auto using the shift-on-the-fly selector lever. Command the battlefield with the TM-7 from BT Paintball Designs.\n\n\n=Features:=\n\n* Mini Technology Inside\n* Shift-On-The-Fly, 4-Position Mode Switch\n* Multiple, Extensive Firing Modes Including Semi/Burst/Full-Auto\n* Multiple Picatinny Rails Allow For Extra Accessories\n* Adjustable, Multi-Position Stock\n* Collapsible/Adjustable Front Grip\n* Low Pressure Operation\n* No External Hoses; Internal Airline Operation\n* Additional Modes: NPPL/PSP/NXL/Millennium\n* Universal Mini-Style Barrel Threads\n" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_limited_edition_sunglasses" : { + "meta_keywords" : "Oakley Limited Edition Sunglasses,Limited Edition oakley sunglasses,oakley Limited Edition, Limited Edition polarized sunglasses", + "meta_description" : "Oakley Limited Edition Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Limited Edition and Polarized Oakley Limited Edition Sunglasses on Sale! ", + "page_title" : "Oakley Limited Edition Sunglasses with Free Shipping", + "head_title" : "Oakley Limited Edition Sunglasses | Limited Edition Oakley Sunglassses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_livestrong_sunglasses" : { + "meta_description" : "Oakley Livestrong Sunglasses - Buy your Oakley Live Strong At Zephyr Sports for Less Today! We carry a complete line of Livestrong Oakley Sunglasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Livestrong Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Livestrong Sunglasses | Oakley Live Strong | Livestrong Oakley Sunglasses" + }, + ".2clearance.under__25_paintball_clearance" : { + "head_title" : "Under $20 Paintball Gear | Cheap Paintball Gear" + }, + ".markers.tippmann.tippmann_packages.tippmann_custom_98_pro_packages" : { + "meta_keywords" : "tippmann 98 pro packages, tippmann 98 custom pro packages, tippmann 98 pro paintball package, 98 pro kits, 98 custom pro paintball package", + "banner1" : "banners/categories/guns/tippmann_package_98.jpg", + "meta_description" : "Tippmann 98 Pro Packages - Buy your Tippmann 98 Custom Pro Package Online at Zephyr Paintball for Less today. Free Shipping on Tippmann 98 Pro Paintball Package Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann 98 Pro Packages Online On Sale Now", + "head_title" : "Tippmann 98 Pro Packages | Tippmann 98 Custom Pro Package | Tippmann 98 Pro Paintball Package" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.m4___m16_aeg_airosft_gun_mags" : {}, + ".snowboard_gear.snowboard_goggles.electric_snowboard_goggles.electric_goggle_cases" : {}, + ".paintball.paintball_hopper_loaders.virtue_paintball_hoppers" : {}, + ".casual_clothing.womens_clothing.ladies_sunglasses.fly_girls_sunglasses" : {}, + ".casual_clothing.mens_clothing.belts.arbor" : { + "meta_keywords" : "Anti Hero Belts,Anti Hero Belt Buckle,Anti Hero Belts,Anti Hero webbed belt", + "meta_description" : "Anti Hero Belts - We carry the complete line of Anti Hero Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Anti Hero Belts on Sale Now!", + "head_title" : "Arbor Mens Belts | Arbor Belts | Arbor Skate Belts" + }, + ".misc_items.accessories" : {}, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_standby_polarized_sunglasses" : { + "meta_description" : "Suncloud Standby Polarized Sunglasses - Zephyr Sports carries a complete line of Standby Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Standby Sun Glasses Online Today.", + "page_title" : "Suncloud Standby Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Standby Polarized Sunglasses | Standby Suncloud Sunglasses Free Shipping | Buy Suncloud Standby Sun Glasses" + }, + ".harnessesbags.packs___harnesses.full_clip_harnesses_and_vests" : { + "meta_description" : "Full Clip Tactical Vests - Buy your Full Clip Paintball Harnesses Online at Zephyr Paintball for Less today. Free Shipping on FullClip Paintball Vests Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Full Clip Tactical Vests Online On Sale Now", + "head_title" : "Full Clip Tactical Vests | Full Clip Paintball Harnesses | FullClip Paintball Vests" + }, + ".casual_clothing.womens_clothing.ladies_shirts.1-search_by_size.4-large" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_berko_sunglasses" : {}, + ".casual_clothing.mens_clothing.tshirts.fmf_t_shirts" : { + "meta_keywords" : "FMF T Shirts,FMF shirts,free shipping,FMF TShirt", + "meta_description" : "FMF T Shirts - Zephyr carries a complete line of FMF Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "FMF T Shirts at Zephyr", + "head_title" : "FMF T Shirts | FMF Shirts |FMF TShirt" + }, + ".goggles.jt_usa_goggles.jt_qls_paintball_goggles" : { + "meta_description" : "JT QLS Paintball Goggles - Buy your JT QLS Paintball Masks Online at Zephyr Paintball for Less today. Free Shipping on JT QLS Paintball Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy JT QLS Paintball Goggles Online On Sale Now", + "head_title" : "JT QLS Paintball Goggles | JT QLS Paintball Masks | JT QLS Paintball" + }, + ".casual_clothing.mens_clothing.shirts.anti_hero_shirts_and_flannels" : { + "meta_description" : "Anti Hero Flannel Shirts - Buy your Anti Hero Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Anti Hero Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Anti Hero Shirts & Flannels Ship Free", + "head_title" : "Anti Hero Flannel Shirts | Anti Hero Polo Shirts | Anti Hero Shirts" + }, + ".airsystems.tankcovers.bottle_covers_by_tank_size.70_ci_nitro_bottle_covers" : { + "meta_description" : "70ci Tank Cover - Buy your 70 Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Paintball Bottle Covers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 70ci Tank Cover Online On Sale Now", + "head_title" : "70ci Tank Cover | 70 Tank Cover | Paintball Bottle Covers" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.1_search_by_size.1_small" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_kubric_sunglasses" : { + "meta_keywords" : "Spy Kubric sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Kubric Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy optic eyewear with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Kubric Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Kubric Sunglasses | Spy Optics Kubric Sunglasses" + }, + ".airsystems.nitrogentanks.ninja_paintball_tanks" : { + "meta_keywords" : "ninja paintball tanks, ninja compressed air tanks, ninja paintball, compressed air tank, paintball nitro tank, carbon fiber paintball bottle, HPA Bottle", + "meta_description" : "Ninja Paintball Tanks - Ninja compressed air tanks from Zephyr are proudly made in the USA. We stock a complete line of Ninja Paintball gear including compressed air bottles, remote coils and fill stations", + "page_title" : "Buy Ninja Paintball HPA Tanks Online On Sale Now", + "head_title" : "Ninja Paintball HPA Tanks | Ninja Compressed Air Tanks | Ninja Paintball Bottles", + "description" : "The Ninja Tanks continue to be consistent and reliable each time a new size is offered. The regulator is completely re-buildable by the consumer making it effortless to meet anyone’s specific needs. Changing the output pressure can be costly and time consuming but not with the Ninja Tank. It can be easily done by removing a couple shims inside the regulator. In our opinion the Ninja HPA Tank is the most user-friendly tank on the market by dissembling with ease and 100% modifiable.\n\n\nCheck out the [[Ninja Remote Line]:url=http://www.zephyrpaintball.com/product/PB-NINJ-REMOTE/Ninja_Paintball_Heavy_Duty_Remote_Coil.html] that we carry. Remote lines are great for multiple reasons. If you are using CO2 with your gun the remote line prevents the liquid CO2 going directly into your gun which can ware down your gun very quickly. By having the line mainly gas is running through your gun which overall is going to make your shots consistent and more efficient. Remote coils are also great to keep the weight off your gun for easy maneuvering." + }, + ".airsoft.tactical_airsoft_gear.airsoft_tactical_belts.511_tactical_belts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".barrels.barrels_by_manufacturer.lapco_paintball_barrels.lapco_snapshot_barrels.snapshot_barrel_backs" : {}, + ".markerupgrades.grips_and_grip_panels.hybrid_paintball_grips.hybrid_dye_ultralight_frame_grips" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.mossberg_spring_airsoft_shotguns" : { + "meta_description" : "Mossberg Airsoft Guns - Buy your Mossberg Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Mossberg Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Mossberg Airsoft Guns On Sale & Free Shipping", + "head_title" : "Mossberg Airsoft Guns | Mossberg Airsoft Rifles | Mossberg Spring Airsoft Guns" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_helm_sunglasses" : {}, + ".skateboard_gear.skateboard_decks.zoo_york_skateboard_decks" : { + "meta_keywords" : "Zoo York skateboards,Zoo York decks,Zoo York Skate decks,cheap skate decks,Zoo York skate boards,skateboarding equipment,skateboarding gear,Zoo York Deck,Zoo York skateboard deck,Trucks,wheel,bearings,Zoo York skateboarding", + "meta_description" : "Zoo York Skateboards - Zephyr Sports is your Zoo York Skateboarding Headquarters! Zoo York skateboard Decks, Complete Zoo York Skateboards, and much More! Choose from a grip of Zoo York skate boards, Cheap Skate Decks, and others! Zephyr has all your Skateboarding equipment! Customize your Zoo York Skateboard with the latest trucks, wheels and bearings all @ Zephyr! Grab your Zoo York Deck Today!", + "page_title" : "Buy Zoo York Skateboards On Sale & Free Shipping", + "head_title" : "Zoo York Skateboards | Zoo York | Zoo York Skateboard Decks" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_hielo_sunglasses" : { + "meta_keywords" : "Spy Hielo sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear,Spy polarized sunglasses", + "meta_description" : "Spy Hielo Sunglasses - Zephyr carries a complete line of Spy Optic Hielo Sunglassess including the Spy Hielo Polarized line of sunglasses. With Free shipping, a 30 day satisfaction guarantee and 1 year breakage protection, Zephyr Sports is your one stop shop for Spy Optic Sunwear! ", + "page_title" : "Buy Spy Hielo Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Hielo Sunglasses | Spy Hielo Polarized Sunglasses | Spy Optic Hielo Sunglasses" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_private_ss_watches" : { + "meta_keywords" : "Nixon Watches,Nixon Private SS,Nixon SS Private Watch,Nixon,mens watch,Private SS Nixon Watch,SS Private Watch", + "meta_description" : "Nixon Watches - Brand New Nixon Private SS Watch Available Now @ Zephyr! Nixon Private SS Watches feature a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Private SS Watch", + "head_title" : "Nixon Private Watches | Nixon Private Watch | Nixon Private" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_fly_straight" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys Fly Straight Sunglasses", + "meta_description" : "Black Flys Fly Straight Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Flys Fly Straight Sunglasses.", + "head_title" : "Black Flys Fly Straight Sunglasses | Black Flys Sunglasses" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys.jt_clearance_paintball_jerseys" : {}, + ".categorybarrels.tippmanna5" : {}, + ".casual_clothing.mens_clothing.shorts.billabong_shorts" : { + "meta_description" : "Billabong Board Shorts - Buy your Billabong Shorts At Zephyr Sports for Less Today! We carry a complete line of Billabong Boardshorts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Billabong Boardshorts Ship Free at Zephyr Sports", + "head_title" : "Billabong Board Shorts | Billabong Shorts | Billabong Boardshorts" + }, + ".airsoft.airsoft_bbs_ammo.ksc_airsoft_bbs" : { + "meta_description" : "KSC Airsoft BBs - Zephyr stocks a complete selection of high end KSC Airsoft ammo. Spend the extra few bucks for quality KSC Airsoft Ammo and save yourself a bunch of headaches down the road. Zephyr Sports offrers free shipping on Airsoft Gear on orders over $75", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 KSC Airsoft Bio BBs | .25 Gram KSC Airsoft Pellets | .20 G Biodegradeable Ammo for Airsoft Guns" + }, + ".2clearance.paintball_clearance_gear.clearance_knee___elbow_pads" : {}, + ".markerupgrades.smartparts.impulse.feednecks" : {}, + ".harnessesbags.paintball_gear_bags.voodoo_tactical_gear_bags" : { + "meta_description" : "Voodoo Tactical Paintball Gear Bags - Buy your Voodoo Tactical Backpacks Online at Zephyr Paintball for Less today. Free Shipping on Voodoo Tactical Bags Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Voodoo Tactical Paintball Gear Bags Online On Sale Now", + "head_title" : "Voodoo Tactical Paintball Gear Bags | Voodoo Tactical Backpacks | Voodoo Tactical Bags" + }, + ".casual_clothing.womens_clothing.ladies_swim_wear" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.1m16_style_aeg_airsoft_guns" : { + "meta_description" : "M16 Airsoft Guns - Buy your Airsoft M16 At Zephyr Sports for Less Today! We carry a complete line of M16 AEG Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy M16 Airsoft Guns On Sale & Free Shipping", + "head_title" : "M16 Airsoft Guns |Airsoft M16 |M16 AEG Airsoft Gun" + }, + ".skateboard_gear.skateboard_decks" : { + "meta_keywords" : "skateboarding decks,skateboards decks,skateboard deck,skateboard decks,Skateboarding equipment,skateboard grip tape,skateboard accessories,grip tape,Alien workshop decks,Element Skateboard Decks,Foundation Skateboard Decks,Toy Machine Skateboard decks,Speed Demon Decks,World Industries skateboard decks,ATM skateboard Decks,Baker Skateboard Decks,Black Label Decks,Chocolate Skateboard Decks,Element Skateboard Decks,Flip Skateboard Decks,Girl Skateboard Decks,Habitat Skateboards,Hollywood Skateboard Decks,Hook Ups Skate Decks,Krooked Skateboard Decks,REAL Skateboard Decks,Santa Cruz Skateboard Decks,", + "meta_description" : "Skateboard Decks - Brand new Skateboarding Decks from top Skate Companies like Alien workshop decks, Element , Foundation, Toy Machine, Speed Demon Decks, World Industries, ATM, Baker, Black Label, Chocolate , Element, Flip, Girl, Habitat, Hollywood, Hook Ups Skate Decks, Krooked, REAL, and Santa Cruz, to name a few! Get all of your Skateboarding Equipment from Zephyr! ", + "page_title" : "Skateboard Decks on Sale Free Shipping ", + "head_title" : "Skateboard Decks | Decks Skateboard | Skateboarding Equipment" + }, + ".casual_clothing.z_shoes_and_footwear.fox_racing_shoes_and_sandals" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_polarized_sunglasses" : { + "meta_description" : "Ray Ban Polarized Sunglasses - Zephyr Sports carries a complete line of Polarized Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Polarized Sun Glasses Online Today.", + "page_title" : "Ray Ban Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Polarized Sunglasses | Polarized Ray Ban Sunglasses | RayBan Polarized Sun Glasses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_wind_jacket_sunglasses" : { + "meta_keywords" : "Oakley Wind Jacket Sunglasses,Wind Jacket oakley sunglasses,oakley Wind Jacket, Wind Jacket polarized sunglasses", + "meta_description" : "Oakley Wind Jacket Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Wind Jacket and Polarized Oakley Wind Jacket Sunglasses on Sale! ", + "page_title" : "Oakley Wind Jacket Sunglasses with Free Shipping", + "head_title" : "Oakley Wind Jacket Sunglasses | Wind Jacket Oakley Sunglassses" + }, + ".3packagespecials.tippmann_packages" : { + "meta_keywords" : "tippmann paintball package,tippmann kit,tippmann a5 package,paintball starter package,cheap tippmann package", + "meta_description" : "Tippmann Paintball Packages - Complete line of Tippmann Starter Kits for less at Zephyr Paintball. Tippmann Paintball kits ship free. 50+ Packages in stock now", + "page_title" : "Buy Tippmann Packages Kits Online Now", + "head_title" : "Tippmann Paintball Package | Tippmann A5 Package | Tippmann Paintball Kits", + "sortby_var" : "Tippmann Gun Type" + }, + ".casual_clothing.z-sunglasses.suncloud_sunglasses" : { + "meta_keywords" : "sun cloud,suncloud sunglasses,suncloud polarized sunglasses,cheap sunglasses", + "meta_description" : "Suncloud Sunglasses - Suncloud Polarized Sunglasses now available at Zephyr Sports. Free Shipping now on Sun Cloud Sunglasses.", + "page_title" : "Suncloud Sunglasses with Free Shipping @ Zephyr", + "head_title" : "Suncloud Polarized Sunglasse | Sunglasses Suncloud | Sun Cloud" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_helena_hydration_packs" : {}, + ".2clearance.clearance_jerseys___apparel.clearance_jerseys" : { + "head_title" : "Sale Paintball Jerseys | Clearance Paintball Jerseys | Paintball Jerseys Sale" + }, + ".casual_clothing.mens_clothing.sweatshirts.dakine_sweatshirts" : { + "meta_description" : "Dakine Sweatshirts - Buy your Dakine Hoodies At Zephyr Sports for Less Today! We carry a complete line of Dakine Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Dakine Sweatshirts | Dakine Hoodies | Dakine Hoody" + }, + ".casual_clothing.mens_clothing.tshirts.dvs" : { + "meta_keywords" : "DVS T Shirts,DVS shirts,free shipping,DVS TShirt", + "meta_description" : "DVS T Shirts - Zephyr carries a complete line of DVS Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "DVS T Shirts at Zephyr", + "head_title" : "DVS T Shirts | DVS Shirts |DVS TShirt" + }, + ".apparel.jerseys.dyejerseys.dye_tactical_paintball_jerseys" : { + "meta_description" : "Dye Tactical Jerseys - Tactical Jerseys for Airsoft or Scenario Paintball. Dye has out done itself with the new tactical jersey and mod top. Dye quality you trust for the woods available now at Zephyr Paintball.", + "top_description" : "", + "page_title" : "Dye Tactical Jersey available at Zephyr", + "head_title" : "Dye Tactical Jerseys | Dye Mod Top" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_hideout_sunglasses" : { + "meta_description" : "Smith Optics Hideout Sunglasses - Zephyr Sports carries a complete line of Hideout Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Hideout Sun Glasses Online Today.", + "page_title" : "Smith Optics Hideout Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Hideout Sunglasses | Hideout Smith Sunglasses Free Shipping | Buy Smith Hideout Sun Glasses" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.swiss_arms_scopes" : {}, + ".barrels.barrels_by_manufacturer" : { + "banner1" : "banners/barrels_header", + "meta_description" : "Paintball Barrels - Buy your Paintball Sniper Barrel Online at Zephyr Paintball for Less today. Free Shipping on Barrels for Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Barrels Online On Sale Now", + "head_title" : "Paintball Barrels | Paintball Sniper Barrel |Barrels for Paintball Guns ", + "description" : "Zephyr has Paintball Barrels from all of the top manufacturers at the lowest prices around. Whether you are looking for a J&J Ceramic barrel for your spyder or a new Dye Ultralight Barrel for your Ego We have it all. " + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_havoc_sunglasses" : { + "meta_description" : "Arnette Havoc Sunglasses - Zephyr Sports carries a complete line of Havoc Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Havoc Sun Glasses Online Today.", + "page_title" : "Arnette Havoc Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Havoc Sunglasses | Havoc Arnette Sunglasses | Arnette Havoc Sun Glasses" + }, + ".casual_clothing.mens_clothing.shoes.globe_shoes" : { + "meta_keywords" : "globe shoes,globe skate,globe shoe,globe skate shoe,globe skate shoes,globe shoes castro,globe skateboard shoes,globe shoes sale,cheap globe shoes,globe skating,buy globe shoes,globe shoes on sale,globe shoes store,cheap globe skate shoes,globe skater shoes,globe skating shoes\r ", + "meta_description" : "Globe Skate Shoes - Huge selection of Globe Skateboard Shoes available online at Zephyr Sports. Always the best price, Always free shipping over $25. Buy your Globe Shoe online Now!", + "page_title" : "Globe Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Globe Skate Shoes | Globe Shoe | Globe Skateboard Shoes" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.bt_delta_paintball_guns" : {}, + ".casual_clothing.z_unisex_clothing_accesories.lanyards.srh_lanyards" : { + "meta_description" : "SRH Lanyards - Buy your Lanyards SRHAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on SRH Lanyards @ Zephyr Sports", + "head_title" : "SRH Lanyards | Lanyards SRH | Lanyard SRH" + }, + ".harnessesbags.backpacks.ogio_backpacks.ogio_rolling_gear_bags" : { + "meta_description" : "OGIO Gear Bags - Buy your OGIO Rolling Gear Bags At Zephyr Sports for Less Today! We carry a complete line of OGIO Luggage Bags at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy OGIO Gear Bags On Sale & Free Shipping", + "head_title" : "OGIO Gear Bags | OGIO Rolling Gear Bags | OGIO Luggage Bags" + }, + ".casual_clothing.mens_clothing.tshirts.spy_optic_t_shirts" : { + "meta_keywords" : "spy optics t shirts,spy shirts,spy t-shirts,spy clothing", + "meta_description" : "Spy Optics Shirts - Zephyr carries a complete line of Spy Optics T Shirts. Low Prices, Free Shipping, we won;t be beat.", + "page_title" : "Spy Optic T Shirts at Zephyr", + "head_title" : "Spy Optic Shirts | Spy T-Shirts | Clothing" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs.camelbak_aurora_hydration_packs" : {}, + ".harnessesbags.packs___harnesses.gi_sportz_paintball_harnesses" : { + "meta_keywords" : "G.I. Sportz Paintball,Paintball Harness,GI Sports Paintball Harness,paintball equipment,paintball harnesses,GI Sportz,G.I. Sports,paintball gear", + "meta_description" : "GI Sports is all about utility for the modern day paintballer. GI Sports Paintball Harnesses get you that extra shot when you're in need on the field! Reload and own the field! GI Sports produces paintball equipment across the board with years and years of trusted experience! Get in the game today with GI Sports Paintball Harnesses. ", + "top_description" : "= G.I. Sportz =\nG.I. Sportz gets the job done! Years and years of trusted experience in the paintball industry; G.I. Sportz give you the edge on the field to own the competition! Run out of paint?! Relax and RELOAD! Great for those times you need just a little something extra to get the job done! G.I. Sportz Paintball Harnesses!", + "page_title" : "Buy G.I. Sportz Paintball Harness Online On Sale Now", + "head_title" : "G.I. Sportz Paintball | Paintball Harness | GI Sports Paintball Harness" + }, + ".harnessesbags.backpacks.ogio_backpacks.ogio_messenger_bags" : { + "meta_description" : "OGIo Messenger Bags - Buy your OGIO BagsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "OGIO Messenger Bags Ship Free @ Zephyr Sports ", + "head_title" : "OGIo Messenger Bags | OGIO Bags" + }, + ".harnessesbags.backpacks.ogio_backpacks.ogio_women_s_packs" : { + "page_title" : "", + "head_title" : "Ogio Women's Packs Ship Free @ Zephyr Sports " + }, + ".1newitems.2008_products.2008_invert_paintball_gear" : {}, + ".casual_clothing.mens_clothing.belts.neff_belts" : { + "meta_keywords" : "Neff Belts,Neff Belt Buckle,Neff Belts,Neff webbed belt", + "meta_description" : "Neff Belts - We carry the complete line of Neff Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Neff Belts on Sale Now!", + "head_title" : "Neff Mens Belts | Aplinestars Belts" + }, + ".loaders.hopper_accesories.odyssey_halo_accesories" : { + "meta_description" : "Halo Loader Parts - Buy your Halo B Parts Online at Zephyr Paintball for Less today. Free Shipping on Halo Upgrade Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Halo Loader Parts Online On Sale Now", + "head_title" : "Halo Loader Parts | Halo B Parts | Halo Upgrade Boards" + }, + ".casual_clothing.mens_clothing.sweatshirts.virtue_sweatshirts" : { + "meta_description" : "Virtue Sweatshirts - Buy your Virtue Hoodies Online At Zephyr Sports for Less Today! We carry a complete line of Virtue Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Virtue Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Virtue Sweatshirts | Virtue Hoodies | Virtue Hoody" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.tsd_airsoft_guns" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_bodega_sunglasses" : { + "meta_keywords" : "Spy Bodega sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Bodega Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy sunglass with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Bodega Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Bodega Sunglasses | Spy Optics Bodega Sunglasses " + }, + ".markerupgrades.proto_matrix_rail_upgrades.proto_matrix_rail_upgrade_boards" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_dharma_sunglasses" : { + "meta_description" : "Von Zipper Dharma Sunglasses - Buy your Dharma Von Zipper Sunglasses Online At Zephyr Sports for Less Today! We carry a complete line of Von Zipper Dharma at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Von Zipper Dharma Sunglasses Now! On Sale & Free Shipping", + "head_title" : "Von Zipper Dharma Sunglasses | Dharma Von Zipper Sunglasses | Von Zipper Dharma" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.v-force_grill_paintball_masks" : {}, + ".markers.walther_paintball_guns" : { + "meta_description" : "Walther Paintball Pistols - Buy your Walther 68 Cal Online at Zephyr Paintball for Less today. Free Shipping on Walther Tactical Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Walther Paintball Pistols Online On Sale Now", + "head_title" : "Walther Paintball Pistols | Walther 68 Cal | Walther Tactical Paintball Guns" + }, + ".shop_by_brand.echo_1" : { + "meta_keywords" : "echo 1 airsoft guns,echo1 airsoft aeg,echo 1 airsoft rifles,echo 1 aeg,m14,m16,scar,e90,usa,asr", + "meta_description" : "Echo 1 Airsoft Guns - Get your Echo1 AEG at Zephyr Today. We stock a complete line of Echo 1 Airsoft Rifles to get you on the field today with Free Shipping and Tech Support", + "top_description2" : "Echo1 U.S.A. is the leading brand of Airsoft guns located in the heart of Los Angeles in the United States of America. Their products are made of high quality materials and crafted with precision to give you an edge above your competition. Echo 1 USA strives to provide their customers with a comprehensive support experience. They are airsoft enthusiasts and they know what it takes to make great products. They have committed themselves to providing unparalleled support for their customers. That's why all Echo1 Automatic Electric Guns (AEG) will come with a 30-day limited warranty. The extensive support channels they have set up are designed to make the support experience as simple as possible for all of their customers.", + "page_title" : "Echo 1 Airsoft Guns and Gear", + "head_title" : "Echo 1 Airsoft Guns | Echo1 Airsoft AEG | Echo 1 Airsoft Rifles", + "description" : "Since its inception the Echo1USA brand has strived to provide their clients with uncompromising quality of products and customer service. As avid Airsoft players themselves, they are able to understand the needs of the sport and the frustration with inferior products. Echo1USA's commitment to yielding the finest most affordable Airsoft Guns and Accessories on the market today is steadfast, and remains the foundation of their continued success.\n\nIn fact, because of their progress, Echo1USA is the first non Japanese company to be approved for sale in Japan by Air Soft Gun Kai (ASGK) which is the regulatory commission for Airsoft in Japan. Echo1 USA has made Airsoft one of the fastest growing sports in the world! and it's now more accessible and affordable then ever before. They are passionate about the sport, and the excitement of watching it grow keeps them eager to find new ways to reinvent themselves daily.\n\nAs Echo1USA grows with the game, a vital component to our objectives is keeping the sport safe. Much like their commitment to quality and durability, if their product is not safe they won't put the Echo1 USA name on it.\n\nWhen Echo1USA announced/released its line of Automatic Electric Guns (AEG) it instantly created a whole new level of airsoft products; Working Class Airsoft; the Echo1USA brand is referred to as The Working Class for two simple reasons; It Works and its affordable enough for the average working class enthusiast/hobbyist/player. Before Echo1USA brand enthusiast/hobbyist/player were forced to choose high-end expensive products of average performance or low-end low performance junk. Now one can have high-performance at a price nearly everyone can enjoy!" + }, + ".3packagespecials.valken_paintball_packages" : { + "meta_description" : "Valken Paintball Packages - Buy your Valken Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Valken Starter Kits Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Valken Paintball Packages Online On Sale Now", + "head_title" : "Valken Paintball Packages | Valken Paintball Guns | Valken Starter Kits" + }, + ".paintballs.umarex_t4e_43_cal_paintballs" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_surf_backpacks" : {}, + ".skateboard_gear.skateboard_trucks.globe_skateboard_trucks" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.tactical_force_airsoft_guns" : { + "meta_description" : "Tactical Force Airsoft Guns - Buy your Tactical Force Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Tactical Force AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Tactical Force Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Tactical Force Airsoft Guns | Tactical Force Airsoft Rifles | Tactical Force AEG" + }, + ".casual_clothing.mens_clothing.jackets.spitfire_jackets" : { + "meta_description" : "Spitfire Jackets - Buy your Spitfire Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Spitfire Jackets with Free Shipping", + "head_title" : "Spitfire Jackets | Spitfire Mens Jackets" + }, + ".loaders.hopper_accesories.inception_designs_loader_accessories" : {}, + ".harnessesbags.backpacks.ncstar_backpacks___bags" : {}, + ".harnessesbags.backpacks.volcom_bags___backpacks" : { + "meta_description" : "Volcom Backpacks - Buy your Volcom Bags Online At Zephyr Sports for Less Today! We carry a complete line of Volcom Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Volcom Backpacks & Bags Ship Free ", + "head_title" : "Volcom Backpacks | Volcom Bags |Volcom Luggage" + }, + ".airsoft.airsoft_guns.team_sd_sports_airsoft_guns" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "TSD Sports | TSD Tactical | Team SD Airsoft Guns" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_trudie_sunglasses" : { + "meta_description" : "Von Zipper Trudie Sunglasses - Zephyr Sports carries a complete line of Buy Trudie Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Trudie Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Trudie Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Trudie Sunglasses | Buy Trudie Von Zipper Sunglasses | Von Zipper Trudie Sunglasses Free Shipping" + }, + ".scenarioupgrades.flashlights___laser_sights.kingman_spyder" : {}, + ".shop_by_brand.guard_dogs" : {}, + ".apparel.gloves.hk_army_paintball_gloves" : {}, + ".harnessesbags.backpacks.krooked_bags" : { + "meta_description" : "Krooked Bags - Buy your Krooked BackpacksAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Krooked Bags & Backpacks Available at Zephyr", + "head_title" : "Krooked Bags | Krooked Backpacks" + }, + ".snowboard_gear.snowboard_goggles.smith_optics_ski_and_snowboard_goggles.smith_womens_ski_and_snowboard_goggles" : {}, + ".barrels.barrels_by_manufacturer.maddog_designz_paintball_barrels" : { + "meta_keywords" : "maddog paintball barrels, maddog scenario barrels, maddog designs barrels, maddog m-16 barrels, maddog barrel shrouds, maddog tippmann barrels", + "meta_description" : "Maddog Paintball Barrels - Buy your Maddog scenario barrels Online at Zephyr Paintball for Less today. Free Shipping on Maddog designs barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Maddog Paintball Barrels Online On Sale Now", + "head_title" : "Maddog Paintball Barrels | Maddog scenario barrels | Maddog designs barrels" + }, + ".harnessesbags.backpacks.1_shop_by_bag_style.backpacks" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_spazz_sunglasses" : { + "meta_description" : "Von Zipper Spazz Sunglasses - Zephyr Sports carries a complete line of Buy Spazz Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Spazz Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Spazz Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Spazz Sunglasses | Buy Spazz Von Zipper Sunglasses | Von Zipper Spazz Sunglasses Free Shipping" + }, + ".loaders.hopper_accesories.empire_hopper_accesories.empire_rip_wheels" : { + "meta_description" : "Empire Rip Wheels - Buy your Halo B Rip Wheel Online at Zephyr Paintball for Less today. Free Shipping on Reloader B Rip Wheel Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire Rip Wheels Online On Sale Now", + "head_title" : "Empire Rip Wheels | Halo B Rip Wheel | Reloader B Rip Wheel" + }, + ".casual_clothing.mens_clothing.belts.rvca_belts" : { + "meta_description" : "RVCA Belts - Buy your RVCA Mens BeltsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on RVCA BELTS @ Zephyr Sports", + "head_title" : "RVCA Belts | RVCA Mens Belts" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.dickies_pants" : { + "meta_description" : "Dickies Pants - Buy your Dickies Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dickies Pants & Jeans Ship Free", + "head_title" : "Dickies Pants | Dickies Jeans" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_gatti_sunglasses" : { + "meta_description" : "Von Zipper Gatti Sunglasses - Zephyr Sports carries a complete line of Buy Gatti Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Gatti Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Gatti Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Gatti Sunglasses | Buy Gatti Von Zipper Sunglasses | Von Zipper Gatti Sunglasses Free Shipping" + }, + ".apparel.shoes.1search_by_size.k_men_s_size_105_shoes" : {}, + ".casual_clothing.z_shoes_and_footwear.srh_shoes" : {}, + ".markerupgrades.tippmann.model98customandpro.custom_98_stocks" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_axis_watches" : { + "meta_keywords" : "Nixon watches,nixon Axis watch,nixon watch,nixon Axis chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Axis Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Axis Chrono Watches", + "head_title" : "Nixon Axis Watches | Nixon Axis Chrono Watch | Nixon 5130" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_stoaway_hydration_packs_" : {}, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_1911" : { + "head_title" : "KWA 1911 Airsoft Pistols | KWA 1911 | 1911 Airsoft Pistol" + }, + "$mixed_kits" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_slings_and_holsters" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markers.tippmann.tippmann_gryphon" : {}, + ".harnessesbags.backpacks.condor_tactical" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.smith_and_wesson_spring_airsoft_guns" : { + "meta_description" : "Smith & Wesson Airsoft Guns - Buy your Smith & Wesson Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Smith & Wesson Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Smith & Wesson Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Smith & Wesson Airsoft Guns | Smith & Wesson Airsoft Rifles | Smith & Wesson Spring Airsoft Guns" + }, + ".casual_clothing.mens_clothing.tshirts.sandana_t_shirts" : {}, + ".markerupgrades.grips_and_grip_panels.virtue_paintball_grips" : { + "banner1" : "banners/categories/virtue_grips_header001" + }, + ".goggles.save_phace_paintball_goggles.ou812_series" : {}, + ".casual_clothing.mens_clothing.shirts.enjoi_shirts" : { + "meta_description" : "Enjoi Shirts - Buy your Enjoi Flannels At Zephyr Sports for Less Today! We carry a complete line of Enjoi Polo Shirt at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Enjoi Shirts On Sale & Free Shipping", + "head_title" : "Enjoi Shirts | Enjoi Flannels | Enjoi Polo Shirt" + }, + ".markers.btdesignspaintballguns.bt_sa_17_paintball_guns" : { + "meta_keywords" : "BT SA Paintball Gun,BT SA Paintball Pistol,BT Paintball Guns,BT Paintball,Paintball,BT Paintball Gear,Paintball Pistol,BT Paintball Markers,BT SA Pistol", + "meta_description" : "BT SA Paintball Gun - Always be prepared with the BT SA Paintball Pistol. You never know when you're gonna need a side arm! BT Paintball has you covered with the BT SA Pistol. Plenty of BT Paintball Gear to go along with it! No ammo?! Reload your paintball pistol with pre-loaded extra mags!", + "top_description" : "BT SA 17 Paintball Gun - The new SA-17 paintball pistol from BT has a bold profile and big performance. Built on the successful US-P platform, this new paintball pistol has a precision milled aluminum body for durability and a new spring feed system that can feed forwards or backwards. Utilizing full-size internals means this gun will perform like the big boy it is and dominate your opponents on the field. Plenty of BT Paintball Gear to help customize your paintball pistol! Featuring multiple Picatinny rails, the SA-17 is designed with a military-inspired look and can accept cool aftermarket accessories. The quick change CO2 system and easy feed tube loading means you won't get caught short when the enemy counterattacks. Grab a SA-17 paintball pistol and remember that size matters when the game is on the line. ", + "page_title" : "Buy BT SA Paintball Gun Online On Sale Now", + "head_title" : "BT SA Paintball Gun | BT SA Paintball Pistol | BT Paintball Guns", + "description" : "\n=SA-17 Features=\n\n* Precision Milled Aluminum Body\n* Threaded Barrel Tip for Barrel Accessories\n* Quick Change 12g System for Fast CO2 Changes\n* Reversible Ball Feed Tube will Fit any Holster\n* Top and Bottom Picatinny Rails Accept Many Accessories\n* Quick Strip Bolt and Hammer System for Easy Maintenance\n* Sniper Round Compatible Breech\n* Picatinny Rail Mounted Feed System Offers Clear Sight Line\n* Fires .68 caliber paintballs\n* 10 round magazine\n* 20+ shots per 12-gram cartridge\n" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.dye_i3_paintball_masks" : {}, + ".casual_clothing.mens_clothing.tshirts.fox_t_shirts" : { + "meta_keywords" : "Fox T Shirts,Fox shirts,free shipping,Fox TShirt", + "meta_description" : "Fox T Shirts - Zephyr carries a complete line of Fox Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Fox T Shirts at Zephyr", + "head_title" : "Fox T Shirts | Fox Shirts | Fox TShirt" + }, + ".scenarioupgrades.scenario_paintball_mags" : {}, + ".markerupgrades.smartparts.eos_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "add2_link" : "/category/markerupgrades.feednecks.nxt_feednecks/", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".harnessesbags.backpacks.1_shop_by_bag_style.luggage" : {}, + ".airsoft.airsoft_spare_magazines.kwa" : {}, + ".barrels.barrels_by_manufacturer.hammerhead_paintball_barrels" : { + "meta_keywords" : "hammerhead barrels, hammerhead barrel kits, hammerhead barrel fins, hammer head paintball barrels, hammerhead paintball barrels, hammerhead stikxx barrel kit, hammerhead shark tooth, hammerhead battle stikxx", + "meta_description" : "Hammerhead Barrels - Buy your Hammerhead Barrel Kits Online at Zephyr Paintball for Less today. Free Shipping on Hammerhead barrel fin Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Hammerhead Barrels Online On Sale Now", + "head_title" : "Hammerhead Barrels | Hammerhead Barrel Kits | Hammerhead barrel fin" + }, + ".shop_by_brand.elite_force_airsoft" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_pampered_women_s_sunglasses" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_micro_fly_2_sunglasses" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys micro,Black Fly Micro", + "meta_description" : "Black Flys Micro Fly 2 Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Fly Micro fly Sunglasses.", + "head_title" : "Black Flys Micro Fly 2 Sunglasses | Black Flys Eyewear | Black Flys Sunglasses" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.empire_e-flex_paintball_masks" : {}, + ".apparel.shoes.converse_skate_shoes" : {}, + ".paintball.paintball_goggles.valken_paintball_goggles" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_inflyt_2" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys Inflyt Sunglasses", + "meta_description" : "Black Flys Inflyt Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Flys Inflight Sunglasses.", + "head_title" : "Black Flys Inflyt 2 Sunglasses | Black Flys Inflyt Sunglasses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_remedy_womens_sunglasses" : { + "meta_keywords" : "Oakley Remedy Womens Sunglasses,Remedy Womens oakley sunglasses,oakley Remedy Womens, Remedy Womens polarized sunglasses", + "meta_description" : "Oakley Remedy Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Remedy Womens and Polarized Oakley Remedy Womens Sunglasses on Sale! ", + "page_title" : "Oakley Remedy Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Remedy Womens Sunglasses | Remedy Womens Oakley Sunglassses" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.etha_paintball_guns" : {}, + ".casual_clothing.mens_clothing.tshirts.element_t-shirts" : { + "meta_keywords" : "element clothing,element shirt,element shirts,t shirt element,element t shirt,element tee,element clothes,element apparel,element t shirts,element tshirt,element tshirts,element tee shirts,element wear,element clothing brand,element tee shirt,element skateboard shirts,element skate shirts\r ", + "meta_description" : "Element Shirts - Zephyr Sports carries a complete line of Element T Shirts with Free Shipping over $75 and hassle free returns. Buy your T Shirt Element today.", + "page_title" : "Element Shirts On Sale & Free Shipping", + "head_title" : "Element Shirts | T Shirt Element | Element T Shirts" + }, + ".markerupgrades.bt_designs_upgrades.bt_paintball_stocks" : {}, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests.voodoo_tactical_vests" : { + "meta_description" : "Voodoo Tactical Vests - Buy your Voodoo Tactical Military Vests Online At Zephyr Sports for Less Today! We carry a complete line of Voodoo Tactical Molle Vests at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Voodoo Tactical Vests On Sale at Zephyr ", + "head_title" : "Voodoo Tactical Vests | Voodoo Tactical Military Vests | Voodoo Tactical Molle Vests" + }, + ".affiliate.coupon_cabin" : { + "top_description" : "\n", + "prodlist1_header" : "Featured Products", + "zoovy:banner01" : "banners/storewide/headers/couponcabin_header001.jpg", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=LIST%3A%24affiliate&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".airsoft.tactical_airsoft_gear.tactical_thigh_rigs.asg_thigh_rigs" : {}, + ".casual_clothing.mens_clothing.beanies.dc_beanies" : { + "meta_keywords" : "DC beanie,DC hat,DC beanies,DC caps,DC 686,DC headwear,DC cuff visor beanie,DC beanie hat,DC visor beanie,DC visor beanies", + "meta_description" : "DC Deanie - Surf style with DC Beanies available now at Zephyr Sports. Get your DC hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "DC Beanies on Sale at Zephyr Today", + "head_title" : "DC Beanie | DC Hat | DC Beanies" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.d_xx-large" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_network_bags" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_tycoon_hydration_packs_" : {}, + ".apparel.head_bands_and_wraps.eclipse_paintball_head_bands___wraps" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns.kwc_gas_airsoft_guns" : {}, + ".2clearance.fourth_of_july_sale" : { + "top_description" : "== Memorial Day Savings!!! ==\n\nSave BIG Money ALL WEEKEND LONG @ Zephyr! Huge selection of discount paintball gear to get you on the field for less! " + }, + ".paintballs.proball_paintballs" : {}, + ".harnessesbags.packs___harnesses.eclipse_paintball_harnesses" : { + "meta_description" : "Eclipse Paintball Harnesses - Buy your Eclipse Pod Packs Online at Zephyr Paintball for Less today. Free Shipping on Eclipse Pod Belts Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Eclipse Paintball Harnesses Online On Sale Now", + "head_title" : "Eclipse Paintball Harnesses | Eclipse Pod Packs | Eclipse Pod Belts" + }, + ".casual_clothing.mens_clothing.shirts.1_search_by_size.1_small" : {}, + ".markerupgrades.autococker" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "btn2_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "btn1" : "", + "buttonname_01" : "", + "btn3" : "", + "zoovy:banner01" : "", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "", + "description" : "=Notice=\nNot all WGP/Autococker frames accept 45 degree Style grips. Please ensure that your frame indeed will accept the particular grips before ordering.", + "btn1_link" : " /category/markerupgrades.feednecks.autococker_feednecks/ ", + "add2_link" : "/category/markerupgrades.feednecks.autococker_feednecks/", + "buttonname_02" : "", + "banner4" : "zephyr_buttons/grips_btn001", + "btn3_link" : "/category/barrels.autococker/", + "add1_link" : "/category/barrels.autococker/", + "btn2" : "" + }, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Upgrades | Airsoft Parts | Airsoft Gun Upgrades" + }, + ".misc_items.gun_lube" : { + "meta_keywords" : "paintball lube, gun lube, gun oil, paintball gun lube, paint ball oil, techt lube, smart parts lube, hater sauce, marker oil, marker lube, dow 33 lube", + "page_title" : "", + "head_title" : "Paintball Lube | Gun Lube | Gun Oil" + }, + ".barrels.barrels_by_manufacturer.stiffi_paintball_barrels.stiffi_impulse_threaded_barrels" : {}, + ".casual_clothing.z-sunglasses.shop_by_brand" : {}, + ".barrels.freakbarrels.freakbarrelinsert" : {}, + ".apparel.shoes.1search_by_size.i_men_s_size_95_shoes" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_mellor_watches" : { + "meta_description" : "Nixon Mellor Watches - Buy your Nixon Mellor Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Mellor at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Mellor Watches", + "head_title" : "Nixon Mellor Watches | Nixon Mellor Watch | Nixon Mellor" + }, + ".shop_by_brand.viewloader" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tVIEWLOADER PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n\n", + "top_description2" : "=Viewloader, Innovation made for winning=\n\nViewloader, is the world's leading manufacturer of paintball loaders and accessories. However, the company is not content to continue business as usual. Coming off a very successful launch of the VLocity, the world's fastest loader, Viewloader continues to push the envelope at all levels to see how much better they can get. Facing the ever increasing desire for faster performance, they are revamping our successful line and pushing the limits to design, engineer, and launch a line of products that is unparalleled in the paintball industry. At each price point, Viewloader continues to integrate new technology to feed the desires of the consumer and provide better value in the process. \n\n\n\n", + "head_title" : "Viewloader | Viewloader paintball | Viewloader triton 2", + "description" : "=Viewloader, Innovation made for winning=\n\n==Products==\nThe product offering ranges from the economical and best selling gravity feed VL-200 for the beginner with a feed rate of 8 balls per second to the XSV VLocity Select Force which was developed with the help of one of the top professional teams in the world and can perform up to 27 balls per second. But while the range of products is impressive, the depth is equally amazing. New products abound at viewloader! Viewloader is upgrading the popular eVLution line by incorporating the legendary Z-Board technology as a standard feature to go along with the iconic egg design and spill-proof lockable spring-loaded lid in the new eVLution 3. \n\n==eVLution 4==\nThe eVLution 4 was built from the successful platform of the eVLution paintball loaders. This eye activated force feed loader is made of flexible impact resistant REVY material for the toughest of conditions. The new toolless quick release pins make this loader quick to access and easy to clean. Instant auto and quick-jam features dislodge the balls that get stuck and provide for a more consistent feed. Dual LED battery monitoring system gives you advance notice so you don't get in a jam. At an average of 18 BPS (Balls Per Second), this advanced loader from ViewLoader won't starve your marker, no matter how fast you shoot. Available in Black.\n\n==XSV Vlocity Select Force==\n\t\nThe XSV VLocity Select Force, a product that represents the \"best of the best.\" We have collaborated with the professional paintball team XSV in the development of a loader and rechargeable lithium-ion battery pack system for the players who compete at the top levels of our sport. Includes:\n* VLocity Select Force loader\n* Charging base\n* Two lithium-ion 9vt. rechargeable batteries" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_rosewood_sunglasses" : { + "meta_description" : "Smith Optics Rosewood Sunglasses - Zephyr Sports carries a complete line of Rosewood Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Rosewood Sun Glasses Online Today.", + "page_title" : "Smith Optics Rosewood Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Rosewood Sunglasses | Rosewood Smith Sunglasses Free Shipping | Buy Smith Rosewood Sun Glasses" + }, + ".barrels.angel" : {}, + ".casual_clothing.z_unisex_clothing_accesories.hacky_sack_foot_bags" : { + "meta_description" : "Foot Bags - Buy your Hackey SackAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Foot Bags On Sale & Free Shipping", + "head_title" : "Foot Bags | Hackey Sack" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.combat_zone_airsoft_guns" : { + "meta_description" : "Combat Zone Airsoft Guns - Buy your Combat Zone Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Combat Zone Spring Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Combat Zone Airsoft Guns On Sale & Free Shipping", + "head_title" : "Combat Zone Airsoft Guns | Combat Zone Airsoft Rifles | Combat Zone Spring Airsoft Gun" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_so_easy_sunglasses" : {}, + ".markerupgrades.kingmanspyder.feednecks" : {}, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_knucklehead_sunglasses" : {}, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_skinny_legs_sunglasses" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_42-20_tide_watches" : { + "meta_keywords" : "Nixon Watches,Nixon Tide Watch,Nixon Watch,Nixon 42-20 Watch,Nixon,mens watches,", + "meta_description" : "Nixon Watches - Brand new Nixon Tide Watch Available now @ Zephyr! Nixon 42-20 Tide Watches feature a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon 42-20 Tide Watch", + "head_title" : "Nixon Tide Watches | Nixon Tide Watch | Nixon 42-20" + }, + ".casual_clothing.mens_clothing.belts.hater_belts" : { + "meta_keywords" : "Hater Belts,Hater Belt Buckle,Hater Belts,Hater webbed belt", + "meta_description" : "Hater Belts - We carry the complete line of Hater Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Hater Belts on Sale Now!", + "head_title" : "Hater Mens Belts | Aplinestars Belts" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts.oakley_replacement_lenses.oakley_m_frame_replacement_lenses" : { + "meta_description" : "Oakley M Frame Lenses - Zephyr Sports carries a complete line of M Frame Oakley Replacement Lenses At the lowest prices on the web with free shipping and easy returns. Buy your M Frame Oakley Lenses Online Today.", + "page_title" : "Oakley M Frame Lenses On Sale Free Shipping", + "head_title" : "Oakley M Frame Lenses | M Frame Oakley Replacement Lenses | M Frame Oakley Lenses" + }, + ".markers.tippmann.tippmann_tcr_tactical_paintball_markers" : { + "meta_keywords" : "tippmann TCR paintball guns, TCR tippmann paintball guns, tippmann TCR marker, tipman, tippman, tipmann paintball gear, tippman TCR paintball gun, tippmann TCR gun, tippmann TCR with cyclone, tippmann TCR cyclone, tcr tactical", + "htmlvids" : "", + "meta_description" : "Tippmann TCR Tactical Paintball Guns - Zephyr brings you the leader in scenario paintball guns. TCR Tactical paintball guns offer affordable performance from a scenario marker. The Tippmann TCR Marker features a compact rugged body sure to own the opposition!", + "top_description" : "== Tippmann TCR Magfed Tactical Paintball Marker ==\nThe Tactical Compact Rifle (TCR) Magfed Marker provides a new level of realism to your paintball play. It comes with two magazines: a 12 Ball Extended Mag and a 7 Ball Mag. Based on Tippmann's TiPX platform of using CO2 cartridges or HPA with a remote line along with its dual feed capability gives you a marker with a ton of flexibility in how you want to play. You can switch from magfed to hopper fed depending on how much paint you want to shoot and the conditions of play. And let's not forget it's First Strike Compatible!", + "page_title" : "Buy Tippmann TCR Paintball Guns Online On Sale Now", + "head_title" : "Tippmann TCR Paintball Guns | TCR Tippmann Paintball Guns | Tippmann TCR Marker", + "description" : "= Features: =\n* .68 Caliber Semi-Automatic\n* Modular Design For Shrouds or Stocks to Create Different Looks\n* Adjustable Flip Top Sights \n* Vertical Folding Handle with Tool-Less Slide Adjustment\n* Collapsible Stock w/ Adjustable Cheek Rest and Spare Magazine Holder\n* 11\" Tactical Barrel\n* First Strike Compatible" + }, + ".2clearance.clearance_upgrades.clearance_drop_forwards___asa_s" : { + "head_title" : "Sale Paintball Drop Forwards" + }, + ".markerupgrades.angel.angel_maintenance__kits" : {}, + ".markerupgrades.smartparts.ion.triggers.new_designz_ion_triggers" : {}, + ".casual_clothing.mens_clothing.hats.fox_hats" : { + "meta_keywords" : "Fox Hats,Fox caps,Fox baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Fox Hats - Zephyr carries a complete line of Fox Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Fox", + "page_title" : "Fox Hats on Sale at Zephyr", + "head_title" : "Fox Hats | Fox Caps | Fox Baseball Hats" + }, + ".test.skateboard_deck_test.testlayout" : { + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=banners%2fairsoft_banner_new&LINK=", + "top_description" : "", + "zs11_banner_wslideshow_slide2" : "ALT=&IMG=banners%2fsnow%2fnewsletters%2fspring_12_snow_gear_sale&LINK=" + }, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories.spetzgear" : {}, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.leapers_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".scenarioupgrades.tactical_vests.nxe_extraktion_vests___accessories" : {}, + ".apparel.jerseys.dyejerseys.dye_c10_paintball_jerseys" : { + "meta_keywords" : "Dye Paintball Jersey,Dye Paintball C10 Jersey,Paintball Dye C10 Jersey,Dye Paintball,Paintball Jersey,Dye,Dye C10 Jersey,Dye Jersey\r ", + "meta_description" : "Dye Paintball C10 Jersey - 2010 Dye Paintball jerseys are still available. Get your Dye C10 Paintball Jersey while you still can! Limited sizes and colors are available. \r ", + "top_description" : "Dye Paintball C10 Jersey - 2010 Dye Paintball jerseys are still available. Limited sizes and colors are available! Each year, Dye releases new designs and colors for the new season! Pick up your C10 Jerseys while you still can!", + "page_title" : "Dye C10 Paintball Jersey | Limited Stock Available", + "head_title" : "Dye C10 Paintball Jersey - Dye Paintball C10 Jersey - Paintball Dye C10 Jersey" + }, + ".harnessesbags.packs___harnesses.xsv_paintball_harnesses" : {}, + ".airsoft.shop_by_brand.modefy_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".barrels.tippmanna5" : { + "meta_keywords" : "tippman a 5 paintball guns,tippman a 5 barrels,barrels for tippmann a5,barrel for tippmann a 5,best barrel for tippmann a5,tippmann a 5 price,tippman a5 barrels,best barrel for a5,a5 paintball barrels\r tippmann a 5 paintball guns\r tippman a 5 barrel\r tippmann a 5 barrels\r tippmann bt4\r tippman a5 barrel\r tippmann a5 barrels\r tippmann a5 paintball barrel\r a5 paintball barrel\r a5 barrels\r a5 upgrades\r tippmann a 5 barrel\r tippmann a5 a 5\r tippman a 5\r tippmann a5 barrel\r a5 tippmann barrel\r a5 barrel\r paintball a5\r ", + "meta_description" : "Tippmann A5 Barrels - Zephyr Paintball carries a complete line of Tippmann A5 A 5 paintball upgrade barrels for less. We offer free shipping on Tippman A 5 Barrels on orders over $100. Become another satisfied Zephyr Customer", + "page_title" : "Buy Tippmann A5 Barrels Online On Sale Now", + "head_title" : "Tippmann A5 Barrels | Tippmann A5 A 5 | Tippman A 5 Barrel", + "sortby_var" : "Barrel Length / Type", + "description" : "Full line of Tippmann A-5, X7, and BT-4 paintball barrels by top paintball manufacturers! DYE, Proto, Invert, Tippmann, J&J Ceramics, Invert, Sly Equipment, and many more! Standard barrel lengths include: 12\", 14\", and 16\". Some paintball barrels extend up to 21\" for improved accuracy and distance. \n\n\n\n\nThe most important part of any paintball barrel is the \"threading\" that physically screws into the paintball gun. If these threads do not match the threads of your marker, the barrel will be inoperable to your paintball gun. All of the barrels above use the Tippmann A-5 threads which are the same for the X7 as well as all of the BT-4 guns. This means that unless you have a Tippmann A-5, X7, or BT-4 Paintball marker, these barrels will not work for your gun. \n\n\n\n\nSome Tippmann A-5, X7, or BT-4 Paintball barrels employ a 2-piece design. 2-piece paintball barrels require both; a Front barrel tip as well as a barrel back. Barrel backs contain the actual threads of the barrel so depending on your marker, it is important to select one with the same thread type. All barrel backs above are Tippmann A-5, X7, or BT-4 threaded! As far as the front barrel tips are concerned... these screw right into the barrel back and with various lengths, the user is able to customize length, color, etc. 2-piece paintball barrels allow a little more variability with your overall set-up and also make maintaining your equipment rather easy. \n\n\n\n\nSpecialty barrels like the Apex, Flatline, or boremaster kit give the user a little more control and ability over the competition. The Tippmann Flateline creates backspin with every shot giving your paintball longer range and accuracy. The Apex barrel allows the user to adjust the spin of the paintball as it is shot out the barrel enabling the user to take-out targets that were unhittable before. The adjustable ramp switch now comes with 9 levels of control to customize your level of curve and spin, from no spin to unbelievable. Lastly, the boremaster kit comes complete with an array of different bores for your barrel. The use of various bore sizes in a barrel allow the user to use the best fit possible when shooting different caliber paint. See which size fits your needs best! " + }, + ".markers.bob_long_paintball_guns.bob_long_closer_paintball_guns" : { + "meta_keywords" : "Bob Long Closer EXP, Bob long paintball guns, bob long marq closer exp, marq paintball gun, intimidator, ", + "meta_description" : "Bob long Closer Paintball Guns - Zephyr is the largest west coast distributor of Bob Long paintball guns. From the Marq to the closer exp, Zephyr has the guns you need in stock today", + "page_title" : "Buy Bob Long Closer Online On Sale Now", + "head_title" : "Bob Long Closer | Bob Long Paintball Guns | Marq Closer EXP" + }, + ".scenarioupgrades.flashlights___laser_sights" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.mp5___sub_gun_aeg_airsoft_magazines" : {}, + ".maddog.ion_upgrades.ion_aluminum_bodies" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.watch_cases" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_fixed_power_scopes.nc_star_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_player_watches" : { + "meta_keywords" : "Nixon Watches,nixon player watch,nixon watch,nixon player,player nixon watch,player watch,nixon,mens watch", + "meta_description" : "Nixon Watches - Brand New Nixon Player watch available now @ Zephyr! Nixon Player watches feature a host of high-end qualities. Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Player Watch", + "head_title" : "Nixon Player Watches | Nixon Player Watch | Nixon Player" + }, + ".casual_clothing.mens_clothing.hats.eclipse_hats" : { + "meta_keywords" : "Eclipse Hats,Eclipse caps,Eclipse baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Eclipse Hats - Zephyr carries a complete line of Eclipse Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Eclipse", + "page_title" : "Eclipse Hats on Sale at Zephyr", + "head_title" : "Eclipse Hats | Eclipse Caps | Eclipse Baseball Hats" + }, + ".casual_clothing.womens_clothing.ladies_shirts.1-search_by_size" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_dime_sunglasses" : { + "meta_description" : "Arnette Dime Sunglasses - Zephyr Sports carries a complete line of Dime Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Dime Sun Glasses Online Today.", + "page_title" : "Arnette Dime Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Dime Sunglasses | Dime Arnette Sunglasses | Arnette Dime Sun Glasses" + }, + ".casual_clothing.z_shoes_and_footwear.vox_shoes" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray-ban_rb3426_active_lifestyle_sunglasses" : { + "meta_description" : "Ray Ban Active Lifestyle Sunglasses - Zephyr Sports carries a complete line of Active Lifestyle Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Active Lifestyle Sun Glasses Online Today.", + "page_title" : "Ray Ban Active Lifestyle Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Active Lifestyle Sunglasses | Active Lifestyle Ray Ban Sunglasses | RayBan Active Lifestyle Sun Glasses" + }, + ".casual_clothing.womens_clothing.ladies_beanies.element_beanies" : {}, + ".apparel.jerseys.dyejerseys.a_dye_c8_paintball_jerseys" : { + "meta_keywords" : "Dye Paintball Jersey,Dye Paintball C8 Jersey,Paintball Dye C8 Jersey,Dye Paintball,Paintball Jersey,Dye,Dye C8 Jersey,Dye Jersey", + "meta_description" : "Dye Paintball C8 Jersey - 2008 Dye Paintball jerseys are still available. Get your Dye C8 Paintball Jersey while you still can! Limited sizes and colors are available. ", + "top_description" : "Dye Paintball C8 Jersey - 2008 Dye Paintball jerseys are still available. Sizes and colors are limited! Each year, Dye releases new designs and colors for the new season! Pick up your C8 Jerseys while you still can!", + "page_title" : "Dye C8 Paintball Jersey | Limited Stock Available", + "head_title" : "Dye C8 Paintball Jersey - Dye Paintball C8 Jersey - Paintball Dye C8 Jersey" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_straight_jacket_sunglasses" : { + "meta_keywords" : "oakley straight jacket sunglasses,oakley polarized straight jacket sunglasses", + "meta_description" : "Oakley Straight Jacket Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Straight Jacket Sunglasses and Polarized Oakley Straight Jacket Sunglasses on Sale! ", + "page_title" : "Oakley Straight Jacket Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Straight Jacket Sunglasses | Oakley Straight Jacket Polarized Sunglasses" + }, + ".markerupgrades.smartparts.ion_xe_upgrades.ion_xe_body_kits" : {}, + ".airsystems.tankcovers.dye_paintball_bottle_covers" : { + "meta_keywords" : "dye rhino cover, dye rhino tank cover, dye bottle cover, paintball tank cover, 47 ci tank cover, hpa tank cover, ", + "meta_description" : "Dye Rhino Cover - The Dye Rhino Tank Cover is the premiere protective cover for your expensive paintball tank. The Dye Bottle Cover works with all current sizes of paintball tanks including 47ci aluminum tanks", + "page_title" : "Buy Dye Rhino Cover Online On Sale Now", + "head_title" : "Dye Rhino Cover | Dye Rhino Tank Cover | Dye Bottle Cover" + }, + ".harnessesbags.packs___harnesses.valken_paintball_harnesses" : { + "meta_description" : "Valken Paintball Harness - Buy your Valken Pod Belts Online at Zephyr Paintball for Less today. Free Shipping on Valken Paintball Pod Packs Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Valken Paintball Harness Online On Sale Now", + "head_title" : "Valken Paintball Harness | Valken Pod Belts | Valken Paintball Pod Packs" + }, + ".casual_clothing.mens_clothing.tshirts.quicksilver_t_shirts" : { + "meta_keywords" : "Quicksilver T Shirts,Quicksilver shirts,free shipping,Quicksilver TShirt", + "meta_description" : "Quicksilver T Shirts - Zephyr carries a complete line of Quicksilver Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Quicksilver T Shirts at Zephyr", + "head_title" : "Quicksilver T Shirts | Quicksilver Shirts | Quicksilver TShirt" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_gloves" : {}, + ".markerupgrades.dangerous_power_upgrades.dangerous_power_trigger_upgrades" : { + "meta_description" : "Dangerous Power Trigger Upgrades - Buy your G3 G4 Trigger Upgrades Online at Zephyr Paintball for Less today. Free Shipping on Trigger Upgrades for DP Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dangerous Power Trigger Upgrades Online On Sale Now", + "head_title" : "Dangerous Power Trigger Upgrades | G3 G4 Trigger Upgrades | Trigger Upgrades for DP" + }, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns.combat" : { + "meta_keywords" : "bt4 paintball markers,bt4 paintball guns,bt4 combat sniper,bt4 custom,bt 4 combat paintball marker,bt4 combat marker,bt4 combat paintball gun,bt4 barrel,bt 4 combat paintball gun,bt4 paintball marker,tippmann bt4,bt combat marker,bt combat paintball gun,bt4 marker,bt4 combat paintball,bt4 gun,bt4 paintball gun,bt combat paintball,bt4 paintball,bt4 combat,bt4\r ", + "meta_description" : "BT4 Combat Paintball Guns - BT4 Paintball Markers are one of the most affordable entry level paintball guns on the market today. The BT4 Combat Paintball Marker is fully upgradeable and as reliable as you could ask for. Free Shipping on BT Combat from Zephyr Today", + "top_description" : "The BT-4 Combat is the marker that started the BT-4 Series. It's the perfect scenario or woodsball marker which allows you to build the perfect one-of-a-kind beast. Fully upgradeable, the Combat is the scenario marker by which others are judged. This reliable and accurate marker is the obvious choice for use in your scenario or woodsball event. The front grip is removable and the military standard dual Picatinny rails accept many tactical upgrades like optics and other accessories like the BT Flashsight. The trigger system can be enhanced with by installing the Double Trigger and Electronic Grip Frame to increase your rate of fire. With available upgrades like the HALO powered Rip Clip and Apex Barrel system, the BT4 Combat is the core of our successful BT4 line of markers. If you are looking to customize your paintball gun, start with the BT4 Combat and open a world of realistically styled marker configurations. Step into Combat with BT Paintball. ", + "banner02_link" : "/category/3packagespecials.empire_paintball_packages.empire_bt.combat/", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001", + "description" : "=Features:=\n\n* Tournament legal external velocity adjuster.\n* Removable grip frame for quick and easy upgrades.\n* Easily accepts expansion chambers, vertical and horizontal bottle adapters.\n* Works with CO2 or Compressed air.\n* Stainless steel bottomline.\n* Impact resistant baked on coating.\n* Dual Picatinny mounting rails meet Military Standard 1913.\n* Modular trigger system.\n* 1 year full parts and labor warranty.\n* Slide-Away TM Feedport for easy cleaning, maintenance\n* Light weight balanced construction.\n* Adjustable vertical front grip.\n* Selecta-Barrel TM adapter allows use of multiple barrel threads.\n\n\n=Specifications:=\n\n* Caliber: .68\n* Action: Semi-Automatic\n* Powered: CO2 or Compressed Air(HP Output)\n* Cycle Rate: 13BPS\n* Main Body Material: Aluminium\n* Accuracy Range: 150+ft\n\n\nThe BT-4 comes with a removable barrel system. This feature allows the user to select a barrel that is suitable for the playing conditions. Standard barrels are mirror honed with a step-bore and porting and stock length is 8 inches. ", + "top_html_focus" : "", + "head_title" : "BT4 Combat Paintball Guns | BT4 Paintball | BT4 Combat Paintball", + "page_title" : "Buy BT4 Combat Paintball Guns Online On Sale Now" + }, + ".airsoft.airsoft_bbs_ammo.25_airsoft_bb_s" : { + "meta_keywords" : ".25 gram bb, airsoft bb, airsoft ammo", + "meta_description" : ".25 Gram Airsoft BBs. These high grade BBs are the premier size for use in high power AEG guns, co2, and green gas pistols and rifles. Able to withstand even the highest velocities, .25 gram BBs will travel long distances and keep their trajectory accurate. They also pack a lot of power so your covenants will absolutely know when they are hit. These are the perfect BBs to buy for your 300-400+ fps rifle or pistol.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".12 G Airsoft BB's | .12 BBs for Airsoft | .12 Gram Airsoft BB" + }, + ".airsoft.airsoft_guns.echo_1_airsoft_guns.m4___m16_echo_1_airsoft_guns.echo1_stag_m4" : { + "head_title" : "Echo1 Stag M4 | Echo 1 M4 Airsoft Gun | Echo1 Stag" + }, + ".markerupgrades.tippmann.a5.scenarioupgrades.tippmann_a_5_scenario_barrels" : {}, + ".apparel.knee___elbow_pads.sly_knee___elbow_pads" : { + "page_title" : "", + "head_title" : "Sly Elbow Pads | Sly Knee Pads | Sly Paintball Protection", + "prodlist1_header" : "" + }, + ".3packagespecials.tippmann_packages.tippmann_x7_paintball_packages" : { + "meta_description" : "Tippmann X7 Package - Buy your X7 Package Online at Zephyr Paintball for Less today. Free Shipping on X7 Packages Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann X7 Package Online On Sale Now", + "head_title" : "Tippmann X7 Package | X7 Package | X7 Packages" + }, + ".shop_by_brand.g_g" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.1_aug_style_aeg_airsoft_guns" : { + "meta_description" : "Aug Airsoft Guns - Buy your Airsoft AUG GunsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Aug Airsoft Guns On Sale & Free Shipping", + "head_title" : "Aug Airsoft Guns | Airsoft AUG Guns" + }, + ".0001a_christmas_sale.0025" : { + "banner1" : "banners/holiday/holiday_specials_btn_25_001", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=21&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".1_wip.sortorder_list" : { + "subcat1_header" : "", + "top_html" : "", + "top_description2" : "", + "top_description" : "", + "ad1" : "", + "prodlist1_header" : "", + "zoovy:banner01" : "", + "description" : "", + "zoovy:banner02" : "", + "btn_title" : "", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "ad3" : "", + "ad2" : "", + "htmlvids" : "", + "htmllinks" : "", + "top_description3" : "", + "3widead_title" : "", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.echo_1_airsoft_guns.mp5_echo_1_airsoft_guns" : {}, + ".markerupgrades.planet_eclipse_ego_upgrades.ego_eye_upgrades" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines.ak47_style_aeg_airsoft_magazines" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.anti_hero_beanies" : { + "meta_keywords" : "Anti Hero beanie,Anti Hero hat,Anti Hero beanies,Anti Hero caps,Anti Hero 686,Anti Hero headwear,Anti Hero cuff visor beanie,Anti Hero beanie hat,Anti Hero visor beanie,Anti Hero visor beanies", + "meta_description" : "Anti Hero Deanie - Surf style with Anti Hero Beanies available now at Zephyr Sports. Get your Anti Hero hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Anti Hero Beanies on Sale at Zephyr Today", + "head_title" : "Anti Hero Beanie | Anti Hero Hat | Anti Hero Beanies" + }, + ".shop_by_brand.metal_mulisha" : { + "top_description2" : "=Metal Mulisha clothing, Hardcore and Free=\n\nKnown for winning gold medals, breaking world records, and turning industry tradition upside down through the sport of freestyle motocross, pro riders Brian Deegan and Larry Linkogle launched Metal Mulisha Apparel in 1999. Metal Mulisha has grown into the biggest, best and most awesome Freestyle Motocross team in the world. Metal Mulisha's winning form in freestyle competitions like the X Games has helped spread the brand's message to a growing audience around the world. Metal Mulisha gear speaks the language of nonconformity with distinctive apparel that includes graphic tees, jerseys, boardshorts, fleece, tanks, denim and accessories; and encourages guys and girls to \"join the domination\" and express their rebellious spirit and daring attitude.", + "head_title" : "Metal Mulisha Clothing | Metal Mulisha Apparel | Metal Mulisha Gear", + "description" : "=Metal Mulisha, Hardcore and free=\n\n==History==\nStarted sometime around 1998 or 1999 by Brian Deegan and Larry Linkogle, the Metal Mulisha has grown into the biggest, best and most awesome Freestyle Motocross team in the world. They sell clothes, too. Known for winning gold medals, breaking world records, and turning industry tradition upside down through the sport of freestyle motocross, pro riders Brian Deegan and Larry Linkogle launched Metal Mulisha Clothing in 1999. It's popularity won over hundreds of teens and adults all seeking a new pair of threads for their next ride. \n\n==Clothing==\nMetal Mulisha is first and foremost a team, but they're popularity and success inspired them to branch out and create some rad styles for all to wear. From Women's and Men's clothing to Boy's and Girl's accessories, Metal Mulisha has something for everyone. They also make purses, jewelry, stickers and Fight shorts. Their brand is high quality and ready to be rocked by anyone, at anytime. \n\n==Lifestyle==\nMetal Mulisha is only for the die hard and free. At Metal Mulisha, they only create high quality product for people who are going to put it to use, so grab your purse, fight shorts, Motocross jersey or whatever you need and get on the road! This product is for the hardcore only!" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_lomax" : {}, + ".dye_i4_paintball_goggle_mask.o_-_airsoft_product_review.dye_tactical_airsoft_goggles" : {}, + ".markerupgrades.gog_paintball_gun_upgrades.gog_g-1" : {}, + ".dye_i4_paintball_goggle_mask" : { + "html01" : "
                                                                          \n\n
                                                                          ", + "meta_description" : "", + "page_title" : "", + "head_title" : "" + }, + ".shop_by_brand.tiberius_arms" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tTIBERIUS ARMS PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n", + "top_description2" : "=Tiberius arms, Military simulation in a whole new way=\n\nTiberius arms offers some of the hottest and most realistic selection of Paintball product today. They believe in making product that will make you a better player, and a better marksman. These guns are created to hold an 12 gram Co2 cartridge, so every shot you make counts. TA makes the highest quality Mil-Sim paintball gun today, get yours and know why. Look below through Zephyr's wide range of TA guns, pistols, paint and more. With Tiberius arms, you'll lead the way. ", + "head_title" : "Tiberius arms t9 | Tiberius Arms | Tiberius paintball", + "description" : "=Tiberius arms, Military simulation in a whole new way=\n\n==Tiberious Technology==\nTiberius offers many things to the paintball enthusiast including incredibly realistic design, unreal performance, and even scopes! Tiberious believes in a compact and self suffiecient paintball system. These guns only use 12 gram Co2 containers, and you can only get 8 shots out of them. These rounds drive faster than anything you have ever shot before. Their sleek and sexy design incorporated with their realistic design and functionality add up to be one of the coolest designs ever created. \n\n==Tiberious T4==\nThe Tiberious T4 is Tiberius's compact assault rifle. It includes features like:\n* First strike equipped\n* Billet machined upper and lower receivers\n* Monolithic rail platform\n* Functional charging handle\n* 4x32 dual illuminated scope\n* Tri-rail riser mount with 4 side rails\n* Low-profile bipod\n* AR 15/M4 collapsible stock\n* Shroud rail guards\n* Two 14 round magazines\n* Remote air adapter\n* Hopper adapter\n\n==Tiberious T9.1==\nThe larger and more accurate rifle from tiberious.\n* 4x32 dual illuminated scope with range estimator\n* Tri-rail riser\n* Multi-position\n* 5-position compact folding foregrip\n* Adjustable laser\n* tactical flashlight\n* Low profile bipod\n\n==First strike paintball bullets==\n* 25x more accurate!\n* 2x more range!\n* 68 caliper\n* Fin stabilized \n* Brittle shell for easy breakage on contact" + }, + ".markerupgrades.tippmann.tippmann_crossover" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_roll_top_backpacks" : { + "meta_description" : "Dakine Roll Top Backpacks - Buy your Roll Top Dakine Bags At Zephyr Sports for Less Today! We carry a complete line of Dakine Roll Top Packs at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Roll Top Backpacks & Bags Ship Free ", + "head_title" : "Dakine Roll Top Backpacks | Roll Top Dakine Bags |Dakine Roll Top Packs" + }, + ".shop_by_brand.prowin_airsoft" : {}, + ".skateboard_gear.skateboard_bearings" : { + "meta_keywords" : "Skateboarding Bearings,Skateboard Wheel Bearings,Skateboard Bearing,ABEC bearings,Bones Bearings,Bearings,Skateboard equipment,skateboard accessories", + "meta_description" : "skateboard Bearings - Zephyrhas all of your Skateboarding Equipment! Need new Abec Skateboard Bearings?? Zephyr Carries the latest in Bones Bearings, Reds Bearings, and a grip of standard ABEC Bearings! Pick up some new Skateboard Wheel Bearings today", + "page_title" : "ABEC Skateboard Bearings at Zephyr", + "head_title" : "Skateboard Bearings | Abec Skateboard Bearings | Bones Skateboard Bearings" + }, + ".sponsorship.team_sponsorship_packages.bt_team_packages" : {}, + ".casual_clothing.mens_clothing.sandals.vans_sandals" : { + "meta_description" : "Vans Sandals - Buy your Mens Vans Sandals Online At Zephyr Sports for Less Today! We carry a complete line of Vans Flip Flops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Vans Sandals On Sale at Zephyr Sports", + "head_title" : "Vans Sandals | Mens Vans Sandals | Vans Flip Flops" + }, + ".markerupgrades.dangerous_power_upgrades" : { + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.dangerous_power_grip_panel/", + "btn2_link" : "/category/markerupgrades.feednecks.matrix_feeds/", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "btn1_link" : "/category/barrels.autococker/ ", + "banner4" : "zephyr_buttons/grips_btn001", + "page_title" : "Buy Dangerous Power Paintball Gun Upgrades Online On Sale Now", + "btn3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.dangerous_power_grip_panel/ ", + "btn2" : "zephyr_buttons/paintball_pop/products_pop/feednecks_popbtn001", + "add1_link" : "/category/barrels.autococker/", + "banner2" : "zephyr_buttons/barrel_btn001", + "meta_description" : "Dangerous Power Paintball Gun Upgrades - Buy your G4 Upgrades Online at Zephyr Paintball for Less today. Free Shipping on Dangerous Power Parts Trust Zephyr for all your Paintball Needs", + "btn1" : "zephyr_buttons/paintball_pop/products_pop/barrels_popbtn001", + "btn3" : "zephyr_buttons/paintball_pop/products_pop/grips_popbtn001", + "buttonname_01" : "Barrels", + "add2_link" : "/category/markerupgrades.feednecks.matrix_feeds/", + "buttonname_02" : "Feednecks", + "head_title" : "Dangerous Power Paintball Gun Upgrades | G4 Upgrades | Dangerous Power Parts" + }, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_hoffman_sunglasses" : {}, + ".casual_clothing.z-sunglasses.revo_sunglasses" : { + "meta_keywords" : "revo sunglasses,cheap revo,sunglass revo,thrive,abyss,discern titanium,overhead,mooring", + "meta_description" : "Revo Sunglasses - Cheap Revo Sunglasses now available at Zephyr Sports. We offer a complete line of Revo Shades with Free Shipping.", + "page_title" : "Revo Sunglasses with Free Shipping @ Zephyr", + "head_title" : "Revo Sunglasses | Cheap Revo Sunglasses | Sunglass Revo" + }, + ".airsystems.tankcovers.empire_paintball_bottle_covers" : { + "meta_keywords" : "empire bottle glove, empire bottle cover, paintball bottle cover, pro bottle glove", + "meta_description" : "Empire Bottle Glove - The ultimate protection for your compressed air tank. The Empire Bottle Cover is the paintball bottle cover to protect your expensive Carbon fiber tank. Zephyr carries a complete line of Empire bottle covers", + "page_title" : "Buy Empire Bottle Glove Online On Sale Now", + "head_title" : "Empire Bottle Glove | Empire Bottle Cover | Paintball Bottle Cover" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.fly_girls" : { + "meta_keywords" : "Fly Girls Sunglasses,women's sunglasses, womens sunglasses,", + "meta_description" : "Fly Girls Sunglasses now available @ Zephyr! Be the next Fly Girl to rock a pair of Black Flys womens sunglasses! Select Styles of these women's sunglasses by fly girl include Beverly Fly, Flynoculars, and the Snow Fly all available @ Zephyr!", + "page_title" : "Fly Girls Sunglasses On Sale & Free Shipping", + "head_title" : "Fly Girls Sunglasses | FlyGirls Sunglasses | Fly Girl Sunglasses" + }, + ".paintballs.spyder_paintballs" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.m14_aeg_airsoft_magazines" : {}, + ".scenarioupgrades.scenario_apparel.camo_t_shirts" : {}, + ".airsystems.remote_lines.remote_line_covers" : { + "meta_description" : "Paintball Remote Line Covers - Buy your Remote Coil Camo Cover Online at Zephyr Paintball for Less today. Free Shipping on Air Line for Tippmann Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Remote Line Covers Online On Sale Now", + "head_title" : "Paintball Remote Line Covers | Remote Coil Camo Cover | Air Line for Tippmann" + }, + ".safetygear.valken_paintball_protective_gear" : {}, + ".casual_clothing.mens_clothing.tshirts.obey_t_shirts" : { + "meta_keywords" : "Obey T Shirts,Obey shirts,free shipping,Obey TShirt", + "meta_description" : "Obey T Shirts - Zephyr carries a complete line of Obey Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Obey T Shirts at Zephyr", + "head_title" : "Obey T Shirts | Obey Shirts | Obey Skate TShirt" + }, + ".goggles.1goggle_accesories.gi_sportz" : {}, + ".casual_clothing.mens_clothing.tank_tops.hurley_tank_tops" : { + "meta_description" : "Hurley Tank Tops - Buy your Hurley Jersey Tank Tops At Zephyr Sports for Less Today! We carry a complete line of Hurley Mens Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Hurley Mens Jersey Tank Tops at Zephyr Sports", + "head_title" : "Hurley Tank Tops | Hurley Jersey Tank Tops | Hurley Mens Tank Tops" + }, + ".casual_clothing.mens_clothing.tshirts.enjoi_t_shirts" : { + "meta_keywords" : "enjoi shirt,enjoi shirts,enjoi t shirts,enjoi tee shirts,enjoi panda t shirts,enjoi skate shirts\r ", + "meta_description" : "Enjoi Shirts - Huge selection of Enjoi T Shirts available online at Zephyr Sports. Always the best price, Always free shipping over $75. Buy your Enjoi Panda T Shirts online Now!", + "page_title" : "Enjoi Shirts On Sale & Free Shipping", + "head_title" : "Enjoi Shirts | Enjoi T Shirts | Enjoi Panda T Shirts" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_tanks.paintball_co2_tanks" : {}, + ".casual_clothing.mens_clothing.beanies.sector_9_beanies" : { + "meta_description" : "Sector 9 Beanies - Buy your Beanies Sector 9At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on SECTOR 9 BEANIES @ Zephyr Sports", + "head_title" : "Sector 9 Beanies | Beanies Sector 9" + }, + ".airsystems.tankcovers" : { + "meta_description" : "Paintball Tank Covers - Buy your Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Air Tank Cover Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Tank Covers Online On Sale Now", + "head_title" : "Paintball Tank Covers | Tank Cover | Air Tank Cover", + "description" : "Cover that bottle! Not only for protection but for comfort. It's good to get a nice grip with your setup so the bottle doesn't slide around on you. Zephyr carries covers for compressed air tanks; sizes 45ci,48ci,68ci,70ci, 88ci and 92ci. " + }, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_regent_sunglasses" : { + "meta_description" : "Anarchy Regent Sunglasses - Zephyr Sports carries a complete line of Anarchy Regent Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Regent Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Regent Sunglasses | Anarchy Regent Sun Glasses" + }, + ".maddog.spyder_upgrades.spyder_feed_necks" : {}, + ".airsystems.dropforwards.custom_products_drops___cradles.custom_products_asa_s" : { + "meta_description" : "Custom Products Drop Forward - Buy your Cp Drop Online at Zephyr Paintball for Less today. Free Shipping on CP ASA Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Custom Products Drop Forward Online On Sale Now", + "head_title" : "Custom Products Drop Forward | Cp Drop | CP ASA" + }, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.ego7_8_geo_grip_panel" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb4108_sunglasses" : { + "meta_keywords" : "Ray Ban RB4108 Sunglasses ,Ray Bans,Ray Ban Sunglasses", + "meta_description" : "Ray Ban RB4108 Sunglasses are now available @ Zephyr Sports! Made in Italy, these Ray Ban Sunglasses have style and quality above all else! Backed with a manufacturers warranty, these Rayban Sunglasses are a classic look that never fades! These Ray Bans are available in various colors, check em out @ Zephyr Sports!", + "page_title" : "Buy Ray-Ban RB4108 Sunglasses On Sale & Free Shipping", + "head_title" : "Ray-Ban RB4108 Sunglasses | Ray Ban RB4108 Sunglasses | Ray Ban RB 4108 Sunglasses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_dart_womens_sunglasses" : { + "meta_keywords" : "Oakley Dart Womens Sunglasses,Dart Womens oakley sunglasses,oakley Dart Womens, Dart Womens polarized sunglasses", + "meta_description" : "Oakley Dart Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Dart Womens and Polarized Oakley Dart Womens Sunglasses on Sale! ", + "page_title" : "Oakley Dart Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Dart Womens Sunglasses | Dart Womens Oakley Sunglassses" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_pants.dye_clearance_paintball_pants" : {}, + ".category/loaders.hopper_accesories/" : {}, + ".barrels.barrelcovers" : { + "meta_description" : "Paintball Barrel Covers - Buy your Barrel Cover Paintball Online at Zephyr Paintball for Less today. Free Shipping on Paintball Barrel Cover Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Barrel Covers Online On Sale Now", + "head_title" : "Paintball Barrel Covers | Barrel Cover Paintball | Paintball Barrel Cover" + }, + ".casual_clothing.womens_clothing.ladies_beanies.nixon_ladies_beanies" : {}, + ".safetygear.barrelcovers" : { + "prodlist1" : "&SORTBY=NAME&FORMAT=&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".barrels.barrels_by_manufacturer.j_j_paintball_barrels.j_j_full_tilt_paintball_barrels" : { + "meta_description" : "J&J Full Tilt Barrels - Buy your J&J Paintball Barrels Online at Zephyr Paintball for Less today. Free Shipping on JJ Paintball Barrels Trust Zephyr for all your Paintball Needs", + "top_description2" : "What's the number one thing you can do to up your game and improve your paintball marker? Grab an aftermarket barrel, and J & J performance have some of the best ceramic coated aluminum two piece barrels on the market. Check out the low friction coating that will clean your barrel as you shoot and make your shots more consistent. Go with one of the most recommended upgrades on the field, and get the most out of your game.", + "page_title" : "Buy J&J Full Tilt Barrels Online On Sale Now", + "head_title" : "J&J Full Tilt Barrels | J&J Paintball Barrels | JJ Paintball Barrels", + "zoovy:banner01" : "banners/paintball/headers/jjceramic_paintball_header", + "description" : "When you combine the two awesome pieces of the J&J ceramic barrel you get: one sick precision barrel. Using a Teflon impregnated ceramic coat, this barrel reduces friction and is so advanced it will clean itself. Coming in Tippmann 98, A5/X7, Autococker, Impulse/Ion, Phantom and Spyder threads, there's no gun that can't use these barrels. Want more reach? The Full Tilt series comes in lengths 12\" to 20\" to hit that guy way back behind that snake.\n\n\n==Top First Upgrade:==\n\nIf there is one thing that you can do to your marker that doesn't require a second mortgage or technical know how, that will improve your game, its using an upgrade barrel. The Full Tilt paintball barrels combine the accuracy gained from using a two piece barrel with different bore sizes, with the Teflon coat of JJ's ceramic paintball barrel series. A stock barrel simply cannot compare with a dedicated precision machined barrel's accuracy and performance.\n\n\n==High Grade Barrel:==\n\nMade of T6 6061 aluminum this barrel is both light and versatile. The Ceramic coating is impregnated with Teflon to provide an ultra slick surface that broken paint cannot cling to. If you do get a break the paint will be blown out by the next ball, self cleaning the barrel and keeping you in the game for those crucial moments. the Teflon coating also reduces the friction on the ball as it passes through the barrel giving you a more consistent, more accurate shot.\n\n\n==A Simpler Solution:==\nIf two pieces are two much, J & J also has a ceramic barrel with a [[one piece]:popup=/category/barrels.barrels_by_manufacturer.j_j_paintball_barrels.j_j_ceramic_one_piece_barrels/] design that uses the same technology found in the Full Tilt series, without the extra barrel piece headache. " + }, + ".sponsorship.sponsor_only_specials.guns_and_gear.scenario_deals" : {}, + ".casual_clothing.mens_clothing.shorts.kr3w_shorts" : { + "meta_description" : "KR3W Shorts - Zephyr stocks a complete line of KR3W Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your KR3W needs. ", + "page_title" : "KR3W Shorts with Free Shipping at Zephyr", + "head_title" : "KR3W Shorts | KR3W Board Shorts" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.hater_ladies_t_shirts" : {}, + ".shop_by_brand.unity_paintball" : { + "top_description2" : "=Unity=\nUnity Paintball is a new name in the world of paintball, but the foundation of the company has been in the business for over 20 years. Backed by the knowledge and expertise of one of Paintball's best brains, they are proud to release the Unity Prime. ", + "zoovy:banner01" : "banners/paintball/slideshow/1_unity_prime_paintball_guns_slideshow", + "description" : "The goal of Unity Paintball is to provide a reliable gun that will not break the bank, and they have done just that with the Unity Prime. The Unity Prime is perfect for anybody starting out in the game of paintball." + }, + ".casual_clothing.z_shoes_and_footwear.1shoe_laces" : {}, + ".markerupgrades.tippmann.a5.tippmann_a5_gun_tags" : {}, + ".casual_clothing.womens_clothing.ladies_purses_and_bags.dakine_purses_and_bags" : {}, + ".apparel.pants.angel_paintball_sports_paintball_pants" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.dye_assault_matrix_dam_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_fiona_sunglasses" : { + "meta_description" : "Spy Optics Fiona Sunglasses - Zephyr Sports carries a complete line of Fiona Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Fiona Sun Glasses Online Today.", + "page_title" : "Spy Optics Fiona Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Fiona Sunglasses | Fiona Spy Sunglasses Free Shipping | Buy Spy Fiona Sun Glasses" + }, + ".promotions.free_items" : {}, + ".snowboard_gear.ski_and_snowboard_helmets.smith_ski_and_snowboard_helmets" : { + "meta_description" : "Smith Ski Helmets - Zephyr Sports carries a complete line of Smith Snowboard Helmets At the lowest prices on the web with free shipping and easy returns. Buy your Ski Helmets Smith Online Today.", + "page_title" : "Smith Ski Helmets On Sale Free Shipping", + "head_title" : "Smith Ski Helmets | Smith Snowboard Helmets | Ski Helmets Smith" + }, + ".casual_clothing.mens_clothing.beanies.emerica_beanies" : { + "meta_keywords" : "Emerica beanie,Emerica hat,Emerica beanies,Emerica caps,Emerica 686,Emerica headwear,Emerica cuff visor beanie,Emerica beanie hat,Emerica visor beanie,Emerica visor beanies", + "meta_description" : "Emerica Deanie - Surf style with Emerica Beanies available now at Zephyr Sports. Get your Emerica hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Emerica Beanies on Sale at Zephyr Today", + "head_title" : "Emerica Beanie | Emerica Hat | Emerica Beanies" + }, + ".2clearance.clearance_jerseys_apparel.v-under_20" : { + "head_title" : "Sale Paintball Clothes | Clearance Paintball Clothes | Paintball Clothes Sale" + }, + ".airsoft.tactical_airsoft_gear.tactical_gloves.oakley_tactical_gloves" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_raider_watches" : { + "meta_keywords" : "Nixon watches,nixon Raider watch,nixon watch,nixon Raider chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Raider Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Raider Chrono Watches", + "head_title" : "Nixon Raider Watches | Nixon Raider Chrono Watch | Nixon 5130" + }, + ".casual_clothing.mens_clothing.wallets.matix_wallets" : {}, + ".markerupgrades.tippmann.a5.shrouds___foregrips" : { + "prodlist_custom" : "&SORTBY=PRICE_DESC&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&" + }, + ".skateboard_gear.skateboard_decks.habitat_skateboard_decks" : { + "meta_keywords" : "Habitat skateboards,Habitat decks,Habitat Skate decks,cheap skate decks,Habitat skate boards,skateboarding equipment,skateboarding gear,Habitat skateboard deck,Trucks,wheel,bearings,Habitat skateboarding", + "meta_description" : "Habitat Skateboards - Zephyr Sports is your Habitat Skateboarding Headquarters! Habitat skateboard Decks, Complete Habitat Skateboards, and much More! Choose from a grip of Habitat skate boards, Cheap Skate Decks, and others! Zephyr has all your Skateboarding equipment! Customize your Habitat Skateboard with the latest trucks, wheels and bearings all @ Zephyr!", + "page_title" : "Habitat Skateboard On Sale & Free Shipping", + "head_title" : "Habitat Skateboard | Skateboard Equipment | Habitat Skateboard Decks" + }, + ".airsystems.dropforwards" : { + "meta_description" : "Drop Forward - Buy your Paintball Drop Forward Online at Zephyr Paintball for Less today. Free Shipping on Tippmann Drop Forwards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Drop Forward Online On Sale Now", + "head_title" : "Drop Forward | Paintball Drop Forward | Tippmann Drop Forwards" + }, + ".2clearance.paintball_clearance_gear.clearance_upgrades" : {}, + ".scenarioupgrades.barrels" : {}, + ".loaders.squeegees" : { + "meta_description" : "Paintball Squeegees - Buy your Jerk Squeegees Online at Zephyr Paintball for Less today. Free Shipping on Paintball Barrel Swab Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Squeegees Online On Sale Now", + "head_title" : "Paintball Squeegees | Jerk Squeegees | Paintball Barrel Swab" + }, + ".scenarioupgrades" : { + "meta_keywords" : "scenario paintball, scenario paintball gear, camo paintball apparel, woodsball gear, scenario paintball guns, camo paintball jersey, camo paintball gear, camouflage, camo, scenario", + "ad3_link" : "%SESSION%/product/PB-BT-DELITE/", + "add3_link" : "/category/markers.bob_long_paintball_guns.bob_long_m_tac_paintball_gun/", + "zs11_banner_wslideshow_slide1" : "ALT=Dye+Tactical+Jerseys+On+SALE+NOW%21&IMG=banners%2fpaintball%2fslideshow%2fdye_tactical_jerseys_slideshow%2ejpg&LINK=%2fcategory%2fapparel%2ejerseys%2edyejerseys%2edye_tactical_paintball_jerseys%2f%3fsortby%3dzoovy%253Abase_price%26size%3d15", + "prodlist2_title" : "Featured Scenario Items", + "banner3" : "", + "buttonname_03" : "", + "ad2" : "banners/paintball/side_banners/tippmann_x7phenom_sidebanner001", + "banner4" : "banners/sm_promo/scenario_boblong_mtac_001.png", + "3widead_title" : "Featured Scenario Paintball Guns", + "page_title" : "Buy Scenario Paintball Online On Sale Now", + "banner5" : "zephyr_buttons/guns_scenario_page_btn001.png", + "buttonname_04" : "", + "ad2_link" : "%SESSION%/product/PB-TIP-X7PHENOM/", + "add1_link" : "/category/markers.ariakon/", + "banner2" : "banners/sm_promo/scenario_ariakon_sim4_001.png", + "subcat1_header" : "Scenario Categories", + "meta_description" : "Time to get serious. All the gear and mods for your gun to make you go stealth and get that kill.", + "ad1" : "banners/paintball/side_banners/valken_vtac_sw_1_sidebanner001", + "buttonname_01" : "", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/scenario_header.jpg\"", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "add2_link" : "", + "ad3" : "banners/paintball/side_banners/bt_deltaelite_sidebanner001", + "banner1" : "banners/09_headers/main_categories/scenario_header_001.png", + "buttonname_02" : "", + "ad1_link" : "%SESSION%/product/PB-VTAC-SW1BLK/", + "head_title" : "Scenario Paintball | Scenario Paintball Gear | Camo Paintball Apparel", + "sortby_var" : "Category", + "page_head" : "" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_original_wayfarer_sunglasses" : { + "meta_keywords" : "Sunglasses wayfarer,ray ban polarized,ray ban men's sunglasses,wayfarer glasses,", + "meta_description" : "One of the leading sellers of the Ray Ban Men's sunglasses collection, the Original Wayfarer glasses are here @ Zephyr Sports! A classic for years, and now Ray Ban polarized sunglasses are not limited to the Wayfarer! Various Color Combos IN STOCK! Check the new styles of these Ray Bans out now @ Zephyr Sports!", + "head_title" : "Ray Ban 2140 Wayfarer Sunglasses | Ray-Ban Wayfarer Sunglasses | Ray Ban Polarized Wayfarer Sunglasses" + }, + ".casual_clothing.youth_clothing.youth_rash_guards" : {}, + ".shop_by_brand.custom_products" : { + "" : "", + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tAir Accessories\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tBarrels & Accessories\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\n
                                                                          \n
                                                                          ", + "top_description2" : "=Custom Products, refine and win=\n\nCustom products paintball makes EVERYTHING you have ever needed or wanted for paintball. Try Custom Products regulators,triggers, trigger guards, tanks, hoppers, feed-necks, batteries, barrels, muzzle guards, muzzles, dust caps or fittings. They're are literally hundreds more to choose from! Look at Zephyr's wide selection of cutom products items and you are sure to find at least 50+ things that will fit your marker. Choose Custom products and it's impossible to go wrong!\n", + "head_title" : "Custom Products | Custom products regulators | Custom Products paintball", + "description" : "=Custom Products, refine and win=\n\n==Huge selection!==\nCustom Products is the largest manufacturer of all paintball products. They make accessories for all your weapons no matter the make or model. Custom products has guaranteed that their products will out last and perform the competition. Try them today!\n\n" + }, + ".casual_clothing.mens_clothing.watches.suunto_watches" : { + "meta_description" : "Suunto Watches - Buy your Suunto Watch At Zephyr Sports for Less Today! We carry a complete line of Sunto Watches at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Suunto Watches Free Shipping at Zephyr", + "head_title" : "Suunto Watches | Suunto Watch | Sunto Watches" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_dart_womens_sunglasses" : {}, + ".markerupgrades.smartparts.impulse.visioneyecovers" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_stratos_sunglasses" : { + "meta_keywords" : "Spy Stratos sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Stratos Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy optic eyewear with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Stratos Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Stratos Sunglasses | Spy Optics Stratos Sunglasses" + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones.krooked_headphones" : { + "meta_keywords" : "Krooked Headphones,Krooked Head Phones, Krooked Audio", + "meta_description" : "Krooked Headphones - Zephyr stock a complete line of Krooked Head Phones. For the ultimate Audio experience buy your Krooked at Zephyr Today", + "page_title" : "Krooked Headphones with Free Shipping at Zephyr", + "head_title" : "Krooked Headphones | Krooked Head Phones" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.echo_1_electric_airsoft_rifles.ak47_echo_1_airsoft_guns" : { + "meta_description" : "Echo 1 AK47 Airsoft Guns - Buy your Echo1 AK47At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Echo 1 AK47 Airsoft Guns On Sale & Free Shipping", + "head_title" : "Echo 1 AK47 Airsoft Guns | Echo1 AK47" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_barrels.j_j_ceramic_paintball_barrels" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.tokyo_marui_aeg_airsoft_rifles" : { + "meta_keywords" : "Tokyo Marui Airsoft Guns,Tokyo Marui Airsoft AEG 's,airsoft gun,Airsoft AEG rifles,airsoft submachine guns,AEG", + "meta_description" : "Tokyo Marui Airsoft Guns. Tokyo Marui is truly a leader in innovation, being the first company to produce airsoft guns powered solely by electric-powered, motor driven air compressors (AEG). As its products are notable for their detail and accuracy, they have appeared in numerous movies. Tokyo Marui is widely known as Japan's largest and most renowned airsoft gun manufacturer. Zephyr Sports is a leading distributor of Tokyo Marui Airsoft Gun Products! We carry everything from Airsoft AEG rifles to Airsoft submachine guns! ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Tokyo Marui Airsoft Guns On Sale & Free Shipping", + "head_title" : "Tokyo Marui Airsoft Guns | Tokyo Marui Airsoft AEG ", + "description" : "" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.1_search_by_size" : {}, + ".markerupgrades.bt_designs_upgrades.bt_paintball_sights___rails" : {}, + ".affiliate" : { + "top_description" : "=Affiliate Program=\nZephyrPaintball.com Affiliate Program provides paintball or extreme sports websites with the opportunity to earn money by turning their site visitors into ZephyrPaintball.com customers.\n\n\nWhen a visitor to your site clicks on a link that points to ZephyrPaintball.com a cookie with your unique tracking information is placed on their computer. Commission Junction is a respected industry leader that has a state of the art tracking system. 100% of your results are monitored. This information is accessible to you 24 hours a day through this trusted third party's web-site.\n\n\nThere is no fee to join our program or Commission Junction. Affiliate commission rates start at 5% and you can earn up to 10% depending on your monthly sales.\n\n\nClick Here To [[Sign Up]:popup=https://signup.cj.com/member/brandedPublisherSignUp.do?air_refmerchantid=2395586]" + }, + ".airsoft.airsoft_spare_magazines.kwa.pistol_mags" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_housing_watches" : { + "meta_keywords" : "Nixon watches,nixon tide watch,nixon watch,nixon Outsider watch,Outsider watch,nixon,mens watches,", + "meta_description" : "Nixon Watches - Brand New Nixon Outsider Watches on sale now @ Zephyr! The new Nixon Outsider watch showcases a host of features with all kinds of Tide information and other Specs! Pick up your Nixon Watch today and never as for the time again! ", + "page_title" : "Nixon Outsider Watch", + "head_title" : "Nixon Outsider Watches | Nixon Outsider Watch | Nixon Outsider" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.valken_infinity_paintballs" : {}, + ".barrels.barrels_by_manufacturer.kingman_spyder_paintball_barrels" : {}, + ".casual_clothing.mens_clothing.accessories.bandanas" : {}, + ".harnessesbags.backpacks.girl_backpacks_and_bags" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_aviator_sunglasses" : { + "meta_keywords" : "Ray ban aviators sunglasses,ray ban aviators,ray ban aviator sunglasses, ray-ban aviatar sunglasses,ray ban sunglasses aviator,ray bans", + "meta_description" : "Ray Ban Aviator Sunglasses now on Sale @ Zephyr Sports! Get your authentic Ray Ban Aviators in various styles! Colored Lens available in the Ray-Ban Aviator Sunglasses! These Ray Ban Aviators are made in Italy and backed with a manufacturers warranty! Get your ray bans while supplies last!!", + "page_title" : "Buy Ray-Ban Aviator Sunglasses On Sale & Free Shipping", + "head_title" : "Ray-Ban Aviator Sunglasses | Ray Ban Aviator Sunglasses | Ray Ban Aviators" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_bsg_sunglasses" : { + "meta_description" : "Electric BSG Sunglasses - Zephyr Sports carries a complete line of Electric BSG Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric BSG Online Today.", + "page_title" : "Electric BSG Sunglasses On Sale Free Shipping", + "head_title" : "Electric BSG Sunglasses | Electric BSG Sun Glasses | Sunglasses Electric BSG" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.nixon_ladies_tank_tops" : {}, + ".apparel.jerseys.valken_paintball_jerseys" : { + "meta_keywords" : "valken paintball jerseys,crusade paintball jersey,valken fate jersey,valken crusade jersey", + "meta_description" : "Valken Paintball Jerseys - A New Brand from the orginator of paintball gear. Get your Vlaken Crusade Jersey at Zephyr Today. 6000+ Products in stock with free shipping too 805-275-2040", + "page_title" : "", + "head_title" : "Valken Paintball Jerseys | Crusade Paintball Jersey | Valken Fate Jersey", + "prodlist1_header" : "Valken Paintball Jerseys" + }, + ".airsoft.airsoft_batteries___chargers.accessory_batteries" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Accessory Batteries | Lithium Airsoft Flashlight Batteries | CR123A Dot Laser Battery" + }, + ".markers.rap4_paintball_guns" : { + "meta_description" : "Rap4 Paintball Guns - Buy your Rap 4 Paintball Markers Online at Zephyr Paintball for Less today. Free Shipping on Rap 4 Tactical Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Rap4 Paintball Guns Online On Sale Now", + "head_title" : "Rap4 Paintball Guns | Rap 4 Paintball Markers | Rap 4 Tactical " + }, + ".casual_clothing.womens_clothing.ladies_beanies.dakine_womens_beanies" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns.kjw_airsoft_guns" : { + "meta_description" : "KJW Airsoft Guns - Buy your KJW Airsoft Pistols At Zephyr Sports for Less Today! We carry a complete line of KJW Gas Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy KJW Airsoft Guns On Sale & Free Shipping", + "head_title" : "KJW Airsoft Guns | KJW Airsoft Pistols |KJW Gas Pistols" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_re-run_watches" : { + "meta_keywords" : "Nixon watches,Nixon re-run watch,nixon watch,nixon re-run,nixon re run watch,re-run watches,re run watch,mens watches,mens watch,nixon,", + "meta_description" : "Nixon Watches - Brand new Nixon Re-Run Watch Available now @ Zephyr! Nixon Re-Run Watches are full of a host of cool features. Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Re-Run Watches", + "head_title" : "Nixon Re-Run Watches | Nixon Re-Run Watch | Nixon Re-Run" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.c1rca_circa_youth_t_shirts" : {}, + ".casual_clothing.mens_clothing.tshirts.zephyr_t_shirts" : { + "meta_keywords" : "Zephyr T Shirts,Zephyr shirts,free shipping,Zephyr TShirt", + "meta_description" : "Zephyr T Shirts - Zephyr carries a complete line of Zephyr Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Zephyr T Shirts at Zephyr", + "head_title" : "Zephyr T Shirts | Zephyr Shirts |Zephyr TShirt" + }, + ".markerupgrades.autococker.feednecks" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.cybergun_airsoft_electric_guns" : { + "meta_description" : "Cybergun Airsoft Gunhs - Buy your Cybergun Electric Airsoft Gun At Zephyr Sports for Less Today! We carry a complete line of Cybergun AEG Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Cybergun Airsoft Gunhs On Sale & Free Shipping", + "head_title" : "Cybergun Airsoft Gunhs | Cybergun Electric Airsoft Gun | Cybergun AEG Airsoft Guns" + }, + ".markerupgrades.dangerous_power_upgrades.dangerous_power_maintenance_kits" : { + "meta_description" : "Dangerous Power G3 G4 Maintenance Kits - Buy your Dp Repair Kits Online at Zephyr Paintball for Less today. Free Shipping on Dangerous Power Replacement Parts Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dangerous Power G3 G4 Maintenance Kits Online On Sale Now", + "head_title" : "Dangerous Power G3 G4 Maintenance Kits | Dp Repair Kits | Dangerous Power Replacement Parts" + }, + ".casual_clothing.mens_clothing.tshirts.dye_t_shirts" : { + "meta_keywords" : "Dye T Shirts,Dye shirts,free shipping,Dye TShirt", + "meta_description" : "Dye T Shirts - Zephyr carries a complete line of Dye Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Dye T Shirts at Zephyr", + "head_title" : "Dye T Shirts | Dye Shirts | Dye TShirt" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.aps_aeg_airsoft_guns" : {}, + ".apparel.head_bands_and_wraps.zephyr_paintball_head_bands___wraps" : {}, + ".casual_clothing.mens_clothing.shorts.o_neil_shorts" : { + "head_title" : "O'Neill Board Shorts | O'Neill Shorts | O'Neill Boardshorts" + }, + ".3packagespecials.bt_paintball_packages" : { + "meta_keywords" : "bt paintball package,bt combat kit,starter kit,sniper kit, empire bt paintball packages, bt erc, bt delta elite, bt tm7,tm15,tm-7,tm-15 ", + "meta_description" : "BT Paintball Packages - Buy your BT Battle Tested Starter Kits Online at Zephyr Paintball for Less today. Free Shipping on Empire BT Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy BT Paintball Packages Online On Sale Now", + "head_title" : "BT Paintball Packages | BT Battle Tested Starter Kits | Empire BT Paintball Guns" + }, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns.sa-17" : { + "meta_keywords" : "BT SA Paintball Gun,BT SA Paintball Pistol,BT Paintball Guns,BT Paintball,Paintball,BT Paintball Gear,Paintball Pistol,BT Paintball Markers,BT SA Pistol", + "meta_description" : "BT SA Paintball Gun - Always be prepared with the BT SA Paintball Pistol. You never know when you're gonna need a side arm! BT Paintball has you covered with the BT SA Pistol. Plenty of BT Paintball Gear to go along with it! No ammo?! Reload your paintball pistol with pre-loaded extra mags!", + "top_description" : "BT SA 17 Paintball Gun - The new SA-17 paintball pistol from BT has a bold profile and big performance. Built on the successful US-P platform, this new paintball pistol has a precision milled aluminum body for durability and a new spring feed system that can feed forwards or backwards. Utilizing full-size internals means this gun will perform like the big boy it is and dominate your opponents on the field. Plenty of BT Paintball Gear to help customize your paintball pistol! Featuring multiple Picatinny rails, the SA-17 is designed with a military-inspired look and can accept cool aftermarket accessories. The quick change CO2 system and easy feed tube loading means you won't get caught short when the enemy counterattacks. Grab a SA-17 paintball pistol and remember that size matters when the game is on the line. ", + "page_title" : "Buy BT SA Paintball Gun Online On Sale Now", + "head_title" : "BT SA Paintball Gun | BT SA Paintball Pistol | BT Paintball Guns", + "description" : "=SA-17 Features=\n\n* Precision Milled Aluminum Body\n* Threaded Barrel Tip for Barrel Accessories\n* Quick Change 12g System for Fast CO2 Changes\n* Reversible Ball Feed Tube will Fit any Holster\n* Top and Bottom Picatinny Rails Accept Many Accessories\n* Quick Strip Bolt and Hammer System for Easy Maintenance\n* Sniper Round Compatible Breech\n* Picatinny Rail Mounted Feed System Offers Clear Sight Line\n* Fires .68 caliber paintballs\n* 10 round magazine\n* 20+ shots per 12-gram cartridge\n" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts.oakley_replacement_lenses.oakley_oil_rig_replacement_lenses" : { + "meta_description" : "Oakley Oil Rig Lenses - Zephyr Sports carries a complete line of Oil Rig Oakley Replacement Lenses At the lowest prices on the web with free shipping and easy returns. Buy your Oil Rig Oakley Lenses Online Today.", + "page_title" : "Oakley Oil Rig Lenses On Sale Free Shipping", + "head_title" : "Oakley Oil Rig Lenses | Oil Rig Oakley Replacement Lenses | Oil Rig Oakley Lenses" + }, + ".markers.btdesignspaintballguns" : { + "meta_keywords" : "BT paintball Guns, BT Tm7 gun, BT paintball gear, BT combat paintball gun, BT4 Paintball, Ben Tippmann, BT ERC Paintball Gun, BT Delta Gun, BT Delta Elite Gun, BT Rental gun", + "meta_description" : "BT Paintball Guns - Bt paintball markers are a great scenario marker. From the basic BT4 Combat to the Delta Elite, BT can handle all your scenario and woodsball needs. Perfermance and reliability", + "zs11_banner_wslideshow_slide1" : "ALT=FREE+Halo+Too+Hopper%2a&IMG=&LINK=%25SESSION%25%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3dKEEHOLIDAY%26x%3d32%26y%3d11", + "top_description" : "==BT Battle Tested Paintball is a leading manufacturer of paintball equipment across the board!==\nWide range of BT Paintball Gear; paintball harnesses, hoppers, masks, pants, jerseys, various scenario gear, and even more. \nBT Paintball has a full line of high performance paintball guns. BT Paintball Markers are epic set-ups for any scenario or woodsball player! These accurate, reliable, mil-sim paintball guns feature a host of marker upgrades already installed stock. \nBT has something for everyone! BT Paintball Guns range from High-end to mid-level markers; each gun showcasing a little something different! Fully upgradeable designs with extreme durability and performance!", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "prodlist1_header" : "Battle Tested Paintball Guns", + "banner01_link" : "/category/3packagespecials.bt_paintball_packages/", + "description" : "==BT Combat ERC Paintball Gun==\n\nWhat happens when you take the standard BT-4 Combat and load it full of technology, you get the BT4 ERC paintball gun. The BT-4 ERC comes standard with both the BT Electronic Grip Frame and BT Rip-Clip, allowing you to experience the fastest possible rate-of-fire. The Rip-Clip force-feed loader system utilizes HALO technology, including the built-in Rip Drive, to throw a wall of paint towards the enemy. The Apex barrel system allows you to customize your shot trajectory to hit hidden opponents. Does a tree or bunker stand between you and a kill? Dial up the Apex to curve your shot right on target. The BT 4 ERC offers technology on the battlefield that few markers can match. If you have a need for speed and precision, this is the marker that delivers.\n\n\n==BT-4 Combat Paintball Gun==\n\nThe BT-4 Combat is the marker that started the BT-4 Series. It's the perfect scenario or woodsball marker which allows you to build the perfect one-of-a-kind beast. Fully upgradeable, the Combat is the scenario marker by which others are judged. This reliable and accurate marker is the obvious choice for use in your scenario or woodsball event. The front grip is removable and the military standard dual Picatinny rails accept many tactical upgrades like optics and other accessories like the BT Flashsight. The trigger system can be enhanced with by installing the Double Trigger and Electronic Grip Frame to increase your rate of fire. With available upgrades like the HALO powered Rip Clip and Apex Barrel system, the BT4 Combat is the core of our successful BT4 line of markers. If you are looking to customize your paintball gun, start with the BT4 Combat and open a world of realistically styled marker configurations. Step into Combat with BT Paintball. \n\n\n==BT Delta Elite Paintball Gun==\n\nBT Paintball strives to create markers with a real-world look and feel. The BT Delta Elite paintball gun design is based on the world's pre-eminent submachine gun and is the choice of many players who desire authenticity. While it looks like it's straight off the battlefield, it has some advanced features that make it an awesome paintball marker. Manage the number of paintballs you can shoot with the Electronic Grip Frame, offering multiple firing modes, such as semi-auto, adjustable ramping and full auto. The Rip Clip force feeds paintballs using sound-activated HALO technology and when paired with the E-Grip and Double Trigger, puts more paint in the air than your opponent can duck. The Apex Barrel can create custom shot trajectories, specifying left or right hooks, drop shots and even extended range. There's no place to hide from the player using the Elite. The Delta Elite paintball gun has an adjustable stock for a comfortable fit and adjustable range rear sight for accurate shooting. The small, compact size is perfect for Close Quarters combat and the rate of fire will ensure you emerge victorious. The Delta Elite is tough, its baked on coating can withstand impacts and the quality construction assures it will continue to fire. Whether using CO2 or compressed Air, the Delta Elite paintball gun give you the edge over the opposition and guarantee your day will be fun. \n\n\n==BT Delta Paintball Gun==\n\nFor the scenario or woodsball player who wants realism, BT Paintball offers the BT4 Delta paintball gun. Based on the MP5, most recognizable submachine gun in the world, BT has created a compact, accurate paintball marker that looks like it should be carried by SEALs. The Delta paintball gun has a lightweight, balanced construction for all day play and an adjustable stock for a comfortable firing position. The clamping feedneck will accept loaders without the need for tools, or upgrade to a BT Rip Clip for HALO powered force feed loading. The Delta gun has a modular trigger, so taking it apart for cleaning is simple, and easily upgrades to the Double Trigger or the Electronic Grip Frame for increased firepower. The compact BT4 Delta is an accurate, reliable paintball gun with an authentic look that will help you and your team reign supreme on the battlefield. \n\n\n==BT Omega Tactical Paintball Gun==\n\nThe new BT Omega Paintball Marker will take you into battle without breaking the bank! The rugged aluminum body will withstand heavy duty combat situations and provides increased performance and durability. The Omega will require little in terms of regular maintenance. Fully upgradeable, the Omega easily accepts numerous BT upgrades, such as the HALO powered Rip Clip,the BT1913 Barrel, the BT Clamp Elbow Kit and the Tactical Folding Stock. Carrying your marker out to battle has never been easier thanks to its secure carry handle. The Omega's permanent, fixed sight rail provides you a continuous lock on your opponents, thereby giving you the confidence needed to take them out of the game. Grab your gear, lock and load and hit the field running with the Omega today! \n\n\n==BT Paintball SA-17 Paintball Pistol==\n\nThe new SA-17 paintball pistol from BT has a bold profile and big performance. Built on the successful US-P platform, this new paintball pistol has a precision milled aluminum body for durability and a new spring feed system that can feed forwards or backwards. Utilizing full-size internals means this gun will perform like the big boy it is and dominate your opponents on the field. Featuring multiple Picatinny rails, the SA-17 is designed with a military-inspired look and can accept cool aftermarket accessories. The quick change CO2 system and easy feed tube loading means you won't get caught short when the enemy counterattacks. Grab a SA-17 and remember that size matters when the game is on the line. \n\n\n==BT TM-7 Tactical Paintball Gun==\n\nThe BT TM-7 utilizes Mini Technology to inflict maximum force from a marker of minimal size. Don't be fooled by the size of the TM-7's exterior; it can hang with the big boys and is by no means a lightweight. Once you hold this marker and pull the trigger, you won't want to put it down. Its lightweight, yet durable construction is perfect for close quarters or long-range combat. This is the marker that just may have people rethink the way they looked at Mil-Sim paintball markers. Mounting cool accessories is simple with the BT TM-7 paintball gun. The multiple Picatinny rails will fit optics, sights, lasers, flashlights, or anything needed to improve your experience. The lightweight construction matched with the folding Foregrip and adjustable stock allow for comfortable all-day play. Like the Mini, the TM-7 has no external hoses, giving it a clean look and the authentic feel of the real-world firearm it's based on. No paintball gun has the look and technology to match the TM-7 while in the field. Watch your opponents run when you switch to full auto using the shift-on-the-fly selector lever. Command the battlefield with the TM-7 from BT Paintball Designs. \n\n\n==BT TM-15 Paintball Gun==\n\nThe BT TM-15 is the ultimate choice for any woodsball or mil-sim paintball enthusiast. Its high performance magnesium body is ultra strong, yet light enough for all-day action. Equipped with features usually found on much more expensive markers, the BT TM-15 features a true electropneumatic operating system as well as reduced sound signature for stealth firing in any of the multiple firing modes. With the standard multiple Picatinny rails, accessory options are nearly endless. Internal airline operation eliminates external hoses. Plus, front and rear sights ensure you get your shot. \n\n\n==Empire Bt Tracer Pump Gun==\n\nThe internals of the new Empire Tracer paintball gun are compatible with the original PMI Trracer which have been proven for the past 15+ years.\nWhen you take hold of the pump handle on the new Empire Tracer paintball gun you will feel the most comfortable and ergonomic handle. Those old days of struggling to pump your gun are gone for good.\nPicatinny rails are mounted on the top of the Empire Tracer so you can mount all of your favorite accessories.\nThe Empire Tracer is compatible with either CO2 or HPA and will accept any Autococker threaded barrel or barrel kit. The Empire Tracer pump paintball gun is affordable to any new player, pump player or anyone looking to bring back some old memories.", + "banner1" : "banners/categories/guns/bt1_banner.jpg", + "head_title" : "Cheap BT Paintball Guns | BT Paintball Gear | BT Paintball Markers", + "page_title" : "Buy Cheap BT Paintball Guns Online On Sale Now" + }, + ".airsoft" : { + "meta_keywords" : "cheap airsoft guns,airsoft guns cheap,electric airsoft guns,airsoft gear,cheap airsoft rifles,airsoft machine guns,airsoft shotguns,electric airsoft pistol,co2 airsoft guns,airsoft green gas,airsoft tommy gun,beretta airsoft guns,crosman,airsoft batteries,chargers,holsters", + "zs11_banner_wslideshow_slide1" : "ALT=Elite+Force+Airsoft+BB%27s&IMG=banners%2fairsoft%2fslideshow%2f2_elite_force_bbs_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2fairsoft%2eairsoft_bbs_ammo%2eumarex_elite_force_airsoft_bb_s%2f", + "prodlist2_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&", + "description2" : "", + "zs11_banner_wslideshow_slide3" : "ALT=ASG+Licensed+Ares+Armalite+M15A4+Sportline+AEG+Airsoft+Gun&IMG=banners%2fairsoft%2fslideshow%2fasg_m15a4_sportline_aeg_slideshow%2ejpg&LINK=%25SESSION%25%2fproduct%2fASG%2d2410%2d50040%2fASG%2dLicensed%2dAres%2dArmalite%2dM15A4%2dSportline%2dAEG%2dAirsoft%2dGun%2dw%2dLMT%2dStock%2d%2d%2dBlack%2ehtml", + "page_title" : "", + "zs11_banner_wslideshow_slide2" : "ALT=Condor+Tactical+Gear%21&IMG=banners%2fairsoft%2fslideshow%2fcondor2_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2fshop_by_brand%2econdor_tactical%2f", + "subcat1_header" : "Airsoft Categories", + "bot_description" : "\n=All Airsoft replica BB guns include a safety orange muzzle tip in accordance with Federal law. Any attempt to remove the orange tip is a violation of Federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/Country and local jurisdiction. We are not responsible for items confiscated in customs. You Must be 18 to Purchase Airsoft items.=", + "meta_description" : "Zephyr Sports is your Cheap Airsoft Guns Outlet! Everything Airsoft here at Zephyr! Airsoft guns and airsoft gear for less. Complete line of AEG Electric Airsoft Guns with Free Shipping", + "zoovy:banner01" : "", + "prodlist1_header" : "Featured Airsoft Items", + "banner01_link" : "", + "prodlist1" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=LIST%3A%24as_homepage&ALTERNATE=0&SHOWSKU=&", + "description" : "Zephyr Sports, one shot, one kill, one stop shopping for all your airsoft needs! Whether you are just getting into the sport with a few springers and a couple of friends or you are a hardcore airsoft veteran looking for the best parts for your piece Zephyr has your back. Look at all of Zephyr's products and you are sure to find something perfect for your next battle. We offer Airsoft Grenades, AEG's, Gas blowback pistols and rifles, spring sniper rifles, bb's, vests, Protective goggles and every possible type of gear you could ever want or need on the field. And when you have everything you need you know you'll have all the tools to DESTROY the competition. Those communist fools won't have a chance. If you want precision gear for realistic game play at unbeatable prices, look no further. You've found Zephyr Sports. Check out some of our sweet deals below for prices and products you won't find anywhere else!", + "zs11_banner_wslideshow_slide4" : "ALT=Airsoft+Grenades+and+Launchers+Available+Now%21&IMG=banners%2fairsoft%2fslideshow%2fgrenades_launchers_5_1_web_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2fairsoft%2eairsoft_bbs_ammo%2eairsoft_grenades_and_mines%2f", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "banner1" : "banners/09_headers/main_categories/airsoft_001.png", + "zs11_banner_wslideshow_slide5" : "ALT=ASG+AUG+Airsoft+Guns+Available+Now%21&IMG=banners%2fairsoft%2fslideshow%2fasg_aug_airsoft_guns_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2fairsoft%2eairsoft_guns%2e1_shop_by_gun_type%2eaug_airsoft_guns%2f", + "htmlvids" : "", + "htmllinks" : "", + "head_title" : "Airsoft Guns | Cheap Airsoft Tactical Gear |Airsoft Supplies", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&SHOWQUANTITY=0&", + "page_head" : "" + }, + ".casual_clothing.mens_clothing.tank_tops.srh_tank_tops" : { + "meta_description" : "HK Army Tank Tops - Buy your HK Army Jersey Tank Tops At Zephyr Sports for Less Today! We carry a complete line of HK Army Mens Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "HK Army Mens Jersey Tank Tops at Zephyr Sports", + "head_title" : "HK Army Tank Tops | HK Army Jersey Tank Tops | HK Army Mens Tank Tops" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_vertical_messenger_bags" : {}, + ".apparel.jerseys.hybrid_paintball_jerseys" : {}, + ".2clearance.clearance_upgrades" : { + "head_title" : "Sale Paintball Upgrades | Clearance Paintball Upgrades | Paintball Upgrades Sale" + }, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_mr1_paintball_gun_packages" : { + "meta_description" : "Spyder MR1 Tactical Paintball Packages - Buy your MR1 Spyder Scenario Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder MR1 Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder MR1 Tactical Paintball Packages Online On Sale Now", + "head_title" : "Spyder MR1 Tactical Paintball Packages | MR1 Spyder Scenario Paintball Guns Kit | Spyder MR1 Paintball Guns" + }, + ".airsoft.shop_by_brand.echo_1_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Echo 1 | Echo 1 guns | Echo 1 m28" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_sweatshirts" : {}, + ".apparel.shoes.1search_by_size.g_men_s_size_85_shoes" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_confront_womens_sunglasses" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.ego_11_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_sink_sunglasses" : {}, + ".buyers_guide.paintball.paintball_goggles" : { + "top_description3" : "Paintball Goggles are the most important part of your Paintball Gear. Paintball Masks keep your eyes safe to play another day. We will discuss all kinds of different masks here. From an entry level goggle to a high end tournament level goggle. While they may look similar, the features in these goggles will help make your day at the paintball field much more enjoyable.\n\n\n=Thermal vs Single Paintball goggle lenses=\nSo you will probably see most of the goggles we sell will say they are either a single lens or thermal lens. What does this mean and which do I want?\n\n\n=Single Paintball Lens=\n\n\nA Single lens is basically a piece of plastic which has passed the needed safety tests to be used on a paintball mask. The single lens paintball mask is typically the cheapest version available and while it will protect your eyes, this is one area that you will definitely want to upgrade when possible. Masks with a single lens will tend to fog up if it is hot humid or you are running around sweating a lot like you typically would in a normal game of paintball. Many of the single lens Goggles we sell will have a anti fog coating that will help reduce the amount of fogging in your goggles. While this helps, this is not as nice as having a good thermal lens in your paintball mask. If you cannot upgrade your mask to a thermal lens and cannot afford a new mask, you can try some anti fog spray. This will need to be re applied to the inside of your goggles every day that you play to maintain the anti fog protection.\n\n=Thermal Paintball Lens=\n\n\nThermal lenses are what will come on most high end paintball goggles. Thermal Paintball Goggles will have a dual layer lens. One layer is the outside layer just like a single Lens. The second layer will be attached on the inside of the lens with a semi air tight foam to seal the lens. This will drastically reduce fogging and allow you to see the competition during your game. \n\n\n=Entry Level Paintball Goggles=\nEntry level paintball masks are similar to what you would get if you were to rent equipment at your local field. Entry level goggles will have a single lens and tend to be a little large and heavy. The foam around the eyes will also be less comfortable than a higher end goggle. Entry level Paintball Masks have a price range from $15 to $35. Our basic kit masks, either the Genx Stealth Mask or PMI Xray Goggles cost about $20 but will not allow you to upgrade your lens. Some of the better entry level Paintball goggles like the Proto El or JT Carnivore will allow you to upgrade to a thermal lens down the road.\n\n\n\n\n\n\nYou might think finding the perfect paintball mask is the least of your worries but actually its one of the main priorities in finding the perfect setup for your paintball experience. Not just for the looks or comfort, but for the safety of yourself. Now you may be browsing through and notice that the price somewhat varies between the different types of masks. Well, when you are looking at the design of a paintball mask that is more expensive it becomes lighter, provides more padding, better fog resistance and more ventilation. Let's start with a basic mask.\n\nThe Proto EL is a basic starter mask that may not be the most comfortable but will do the job by protecting your noggin. It provides a woven goggles strap that you can adjust for the perfect fit. There is foam padding for the ears. Throughout the mask there are tiny holes for ventilation to help with fogging. The Proto EL has a single lens that is Anti-fog, but not thermal. Depending on where you live could decide if a single lens will work or not. If you live in a very humid area a THERMAL LENS, which is a duel pane lens (makes it anti-fog) would be the more accurate choice so you don't have to worry about fogging while in game.\n\nA higher end thermal mask is the Empire Events The Events would fall in the category of a high end mask. What makes this mask worth more than the Proto EL? The Empire Events are lighter, have SOFT EARS for more padding, greater ventilation and a Thermal lens. The lens itself is very easy to remove. An active player might find that changing the lens is a big deal for them. Being active and playing once or twice a week you may run into more wear on your lenses. Also, the Events are a very low profile mask which is preferable especially for tournament play. You want a light thin design to keep yourself away from being a big target and also for easy maneuvering which makes the Events the better choice.\nThe Dye I4 is the hottest mask in paintball currently. Ultra lightweight with an insanely small profile, it's perfect for tournament players. Players with large faces and or chins may have some issue though as your chin may extend beyond that mask which could lead to some painful shots.\n\nCan I wear my glasses while I play? What's great about some of the paintball masks that we carry is that they provide enough room for your eye glasses. A good choice for eye glasses is the V-force Profiler mask. With the bug eyed lens on the Profiler you have enough room to wear your eye glasses while being comfortable. JT and V-force are usually a good choice if you wear glasses. " + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.nc_star_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.shorts.contract_killer_shorts" : { + "meta_description" : "AlpineStars Shorts - Zephyr stocks a complete line of Alpinestars Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Alpinestars needs. ", + "page_title" : "Alpinestars Shorts with Free Shipping at Zephyr", + "head_title" : "Contract Killer Shorts | Contract Killer Board Shorts" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.dye_i4_paintball_masks" : {}, + ".casual_clothing.mens_clothing.beanies.neff_beanies.neff_wildstyle_beanies" : { + "meta_description" : "Analog Beanies - Buy your Beanies Analog At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Neff Wildstyle Beanies @ Zephyr Sports", + "head_title" : "Neff Wildstyle Beanies | Beanies Neff Wildstyle" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses" : { + "meta_keywords" : "smith sunglasses,smith optics,smith polarized,smith glasses,smith polarized sunglasses,smith sport optics,smith eyewear,smith sunglass,smith anthem,smiths sunglasses,smith toaster sunglasses,smith shades,smith action optics,smith method polarized,smith optic\r ", + "meta_description" : "Smith Sunglasses - Smith Optics Sunglasses on Sale at Zephyr Sports with Free Shipping. Get your Smith Polarized Sunglasses from the leader in online sunglass sale. 30 day Money back guarantee and one year breakage warranty.", + "page_title" : "Smith Sunglasses with Free Shipping", + "head_title" : "Smith Sunglasses | Smith Optics Sunglasses | Smith Polarized Sunglasses" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_atlas_backpacks" : {}, + ".airsoft.airsoft_guns.airsoft_bb_launchers___shells.hakkotsu_thunder_grenades" : { + "head_title" : "Hakkotsu Thunder Grenades | Airsoft Grenades" + }, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_easy_sunglasses" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs" : { + "meta_description" : "Camelbak Womens Packs - Buy your Womens CamelbaksAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Womens Packs On Sale & Free Shipping", + "head_title" : "Camelbak Womens Packs | Womens Camelbaks" + }, + ".markerupgrades.smartparts.ion.ion_front_grips" : {}, + ".casual_clothing.mens_clothing.sweatshirts.proto_sweatshirts" : { + "meta_description" : "Proto Sweatshirts - Buy your Proto Hoodies At Zephyr Sports for Less Today! We carry a complete line of Proto Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Proto Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Proto Sweatshirts | Proto Hoodies | Proto Hoody" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.v-force_profiler_paintball_masks" : {}, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_kanaha_sunglasses" : { + "meta_description" : "Maui Jim Kahana Sunglasses - Zephyr Sports carries a complete line of Maui Jim Kahana Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Kahana Online Today.", + "page_title" : "Maui Jim Kahana Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Kahana Sunglasses | Maui Jim Kahana Sun Glasses | Sunglasses Maui Jim Kahana" + }, + ".shop_by_brand.gog_paintball" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tGuns\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tPackages\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tOther Gear\n\t
                                                                          \n
                                                                          ", + "zoovy:banner02" : "banners/paintball/headers/gog_banner.jpg" + }, + ".shop_by_brand.pure_energy" : { + "top_description2" : "==Pure energy, performance you can trust==\n\nPure energy tanks are the best for the money out there. If you don't want to blow a month's worth of work on your co2 tank or Compressed air tank, then get a Pure energy system today!!!! These tanks don't just cost less, they perform more than equivalent tanks because of their superior features and construction. Try pure energy, and you won't want anything that isn't pure again.", + "head_title" : "Pure energy | Pure energy systems | Pure energy tank", + "description" : "==Pure energy, performance you can trust==\n\n==About==\nPure energy represents paintball in a new way by offering affordable and high quality tanks. Normally, you would have to pick between the two, but these guys have the formula figured out. Try any of their products ranging form 9 oz co2 to carbon fiber compressed air tanks! No matter how you play, you should try Pure Energy and see how it changes your game. \n\n\n\n" + }, + ".goggles.vforce.v_force_profiler_paintball_goggles" : { + "meta_description" : "Profiler Paintball Goggles - Buy your Vforce Profiler Goggles Online at Zephyr Paintball for Less today. Free Shipping on V-Force Profiler Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Profiler Paintball Goggles Online On Sale Now", + "head_title" : "Profiler Paintball Goggles | Vforce Profiler Goggles | V-Force Profiler" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.us_army_project_salvo_paintball_guns" : {}, + ".skateboard_gear.complete_skateboards.real_complete_skateboards" : { + "meta_keywords" : "real skate boards,real skateboards,real complete skate boards,real skateboarding,street skateboarding, complete skateboard real,real completes", + "meta_description" : "Real Skateboards - Full line of Real Complete Skate Boards on Sale and Free Shipping at Zephyr Sports. Looking for a new board? Real Skateboarding keeps it real with high quality decks and components to keep you in the game. Real Live Customer Service Available 805-275-2040", + "page_title" : "Buy Real Skateboards On Sale & Free Shipping", + "head_title" : "Real Skateboards | Real Complete Skate Boards | Real Skateboarding" + }, + "airsoft.airsoft_guns.airsoft_electric_guns" : {}, + ".casual_clothing.z-sunglasses.revo_sunglasses.revo_mooring_sunglasses" : { + "meta_description" : "Revo Mooring Sunglasses - Zephyr Sports carries a complete line of Mooring Revo Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Revo Mooring Sun Glasses Online Today.", + "page_title" : "Revo Mooring Sunglasses On Sale Free Shipping", + "head_title" : "Revo Mooring Sunglasses | Mooring Revo Sunglasses Free Shipping | Buy Revo Mooring Sun Glasses" + }, + ".casual_clothing.z_unisex_clothing_accesories.lanyards.metal_mulisha_lanyards" : { + "meta_description" : "Metal Mulisha Lanyards - Buy your Lanyards Metal MulishaAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Metal Mulisha Lanyards @ Zephyr Sports", + "head_title" : "Metal Mulisha Lanyards | Lanyards Metal Mulisha | Lanyard Metal Mulisha" + }, + ".airsoft.airsoft_guns.team_sd_tactical_airsoft_guns" : { + "head_title" : "TSD Airsoft Guns | Team SD Airsoft Rifles" + }, + ".apparel.head_bands_and_wraps.zan_headbands_and_wraps" : {}, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.mini_grip_panel" : {}, + ".airsoft.airsoft_upgrades" : { + "meta_description" : "Airsoft Upgrades - Buy your Upgrades Airsoft At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Upgrades On Sale & Free Shipping", + "head_title" : "Airsoft Upgrades | Upgrades Airsoft", + "sortby_var" : "Upgrade Type" + }, + ".markerupgrades.matrix" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.ultralite_grip_panel/", + "meta_description" : "Dye DM Upgrades - Buy your Dye NT Upgrades Online at Zephyr Paintball for Less today. Free Shipping on NT DM Parts Trust Zephyr for all your Paintball Needs", + "buttonname_01" : "", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "", + "add2_link" : "/category/markerupgrades.feednecks.matrix_feeds/", + "buttonname_02" : "", + "banner4" : "zephyr_buttons/grips_btn001", + "head_title" : "Dye DM Upgrades | Dye NT Upgrades | NT DM Parts", + "page_title" : "Buy Dye DM Upgrades Online On Sale Now", + "add1_link" : "/category/barrels.autococker/" + }, + ".safetygear.kneeelbowpads.dye" : { + "head_title" : "Dye Knee & Elbow Pads | Dye Paintball Pads" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_advocate_sunglasses" : { + "meta_description" : "Smith Optics Advocate Sunglasses - Zephyr Sports carries a complete line of Advocate Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Advocate Sun Glasses Online Today.", + "page_title" : "Smith Optics Advocate Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Advocate Sunglasses | Advocate Smith Sunglasses Free Shipping | Buy Smith Advocate Sun Glasses" + }, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_cookie_polarized_sunglasses" : { + "meta_description" : "Suncloud Cookie Polarized Sunglasses - Zephyr Sports carries a complete line of Cookie Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Cookie Sun Glasses Online Today.", + "page_title" : "Suncloud Cookie Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Cookie Polarized Sunglasses | Cookie Suncloud Sunglasses Free Shipping | Buy Suncloud Cookie Sun Glasses" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_desmond_sunglasses" : { + "meta_description" : "Von Zipper Desmond Sunglasses - Zephyr Sports carries a complete line of Buy Desmond Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Desmond Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Desmond Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Desmond Sunglasses | Buy Desmond Von Zipper Sunglasses | Von Zipper Desmond Sunglasses Free Shipping" + }, + ".harnessesbags.backpacks.proto_backpacks" : { + "meta_keywords" : "proto backpacks,sport backpacks,school backpacks,travel bags,gear bags", + "meta_description" : "Proto Sport Backpacks - Tote all you gear around easily with Proto Backpacks! Cool enough for school and big enough for travel; Proto Gear bags work as school backpacks and travel bags! Durable and able to withstand a lot of weight comfortably! Padded straps! And a load of organized compartments! ", + "page_title" : "Buy Proto Backpacks On Sale & Free Shipping", + "head_title" : "Proto Backpacks | Sport Backpacks | Gear Bags" + }, + ".3packagespecials.wgp_paintball_packages" : { + "meta_description" : "Valken Paintball Packages - Buy your Valken Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Valken Starter Kits Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Valken Paintball Packages Online On Sale Now", + "head_title" : "Valken Paintball Packages | Valken Paintball Guns | Valken Starter Kits" + }, + ".casual_clothing.mens_clothing.jackets.enjoi_jackets" : { + "meta_description" : "Enjoi Jackets - Buy your Enjoi Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Enjoi Jackets with Free Shipping", + "head_title" : "Enjoi Jackets | Enjoi Mens Jackets" + }, + ".apparel.knee___elbow_pads.zephyr_sports_knee___elbow_pads" : { + "page_title" : "", + "head_title" : "Zephyr Elbow Pads | Zephyr Knee Pads | Zephyr Paintball Protection" + }, + ".casual_clothing.mens_clothing.shorts.electric_shorts" : { + "meta_description" : "Electric Shorts - Zephyr stocks a complete line of Electric Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Electric needs. ", + "page_title" : "Electric Shorts with Free Shipping at Zephyr", + "head_title" : "Electric Shorts | Electric Board Shorts" + }, + ".casual_clothing.womens_clothing.ladies_shirts.1-search_by_size.3-medium" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns.sig_sauer_gas_airsoft_guns" : { + "meta_description" : "Sig Sauer Airsoft Guns - Buy your Sig Sauer Airsoft PistolAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Sig Sauer Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Sig Sauer Airsoft Guns | Sig Sauer Airsoft Pistol" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.1_search_by_size.3_large" : {}, + ".markers.dangerous_power_paintball_guns.dangerous_power_fusion_fx_paintball_guns" : { + "meta_keywords" : "dangerous power fusion,fusion paintball gun,fusion fx,fusion fx paintball gun,dangerous power", + "meta_description" : "Dangerous Power Fusion - The hot new Fusion FX Paintball Gun from Dangerous Power is here. Zephyr has the lowest prices on Fusion Paintball Guns with free shipping to boot. Buy Online Now!", + "top_description2" : "The Dangerous Power Fusion FX is lighter, smaller, more efficient and even more user friendly than ever before. What else has dangerous power improved from the last version of the fusion? The Fusion FX includes a new OLED board that has more programming options than most people will ever use, but it's nice when you need them. The milling on the fusion fx keeps the gun insanely light weighing in at 1.89lb with battery. As with all dangerous power paintball guns, the feedneck is dm threaded and the barrel is autococker threads. The clamping feed is second to none and will keep your loader secure no matter how rough you play. The included two piece 14\" .689 autococker barrel will throw consistent shots down field. The fusion fx uses the same time tested on/off asa that we all love from the g4. You will need a compressed air tank with the fusion fx as it is not compatible with co2. \n\n", + "top_description" : "", + "zoovy:banner01" : "", + "prodlist1_header" : "Dangerous Power Fusion FX Paintball Guns", + "banner01_link" : "/category/3packagespecials.dangerous_power_paintball_packages/?sortby=zoovy:prod_name ", + "description" : "=Dangerous Power Fusion FX Features:=\n\n* Grip frame OLED.\n* Innovative stocked fully programmable micro-switch OLED board for your viewing pleasure.\n* Ultra sharp OLED display. The sharpest OLED display in its class, providing a high contrast (2000:1), high resolution (192 x 32), and extremely power efficient display screen.\n* Configurable modes. Rule change \"immune\" Tournament Modes that are fully user configurable. Flexible for all levels and modes of play.\n* Comprehensive Breakout Mode Controls. Provides the most flexible and creative recreational play and training operations available.\n* Ultra low-profile Clamping Feedneck. That's right - the clamping feedneck that is widely used throughout the paintball industry was originally designed by the folks at DP Engineering.\n* RAPS (Rapid Air Pressurizing System) Flip Lever Style ASA. This revolutionary ASA makes standard twist-knob ASAs a thing of the past. Another DP Engineering original.\n* SwitchBlade Trigger. Customize your game plan by flipping the trigger to the desired side, no tools necessary and Adjustable magnetic ball bearing trigger. Two amazing triggers in one - priceless.\n* Extremely light weight body (1.94 lbs with barrel, patented RAPS ASA, clamping feedneck and battery).\n* High precision light weight 3-D milled aluminum alloy body and accents.\n* Light weight interlocking ported two piece 14\" barrel.\n* Technology surface TiN treatment for Ram/Hammer, lower friction with marker body.\n", + "htmlvids" : "\t\t
                                                                          \n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
                                                                          \n\t", + "head_title" : "Dangerous Power Fusion | Fusion FX Paintball Gun | Fusion Paintball Gun", + "page_title" : "Buy Dangerous Power Fusion Online On Sale Now" + }, + ".2clearance.clearance_upgrades.clearance_stocks" : { + "head_title" : "Sale Paintball Stocks | Clearance Paintball Stocks | Paintball Stocks Sale" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.echo1_sprint_airsoft_rifles" : { + "meta_description" : "Echo1 Airsoft Guns - Buy your Echo1 Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Echo1 Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Echo1 Airsoft Guns On Sale & Free Shipping", + "head_title" : "Echo1 Airsoft Guns | Echo1 Airsoft Rifles | Echo1 Spring Airsoft Guns" + }, + ".casual_clothing.mens_clothing.tshirts.sullen_t-shirts" : { + "meta_keywords" : "Sullen T Shirts,Sullen shirts,free shipping,Sullen TShirt", + "meta_description" : "Sullen T Shirts - Zephyr carries a complete line of Sullen Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Sullen T Shirts at Zephyr", + "head_title" : "Sullen T Shirts | Sullen Shirts | Sullen TShirt" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_m-frame_sunglasses" : { + "meta_description" : "Oakley M Frame Sunglasses - Buy your M Frame Oakley At Zephyr Sports for Less Today! We carry a complete line of Oakley M-Frame at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley M Frame Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley M Frame Sunglasses | M Frame Oakley | Oakley M-Frame" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_hoss_sunglasses" : { + "meta_keywords" : "Von Zipper Hoss sunglasses,VZ Hoss, Von Zipper polarized sunglasses,Von Zipper Hoss,VZ Hoss glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Hoss Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Hoss sunglasses now! For Von Zipper Hoss glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Hoss Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Hoss Sunglasses | VonZipper Hoss Sunglasses | VZ Hoss Sunglasses" + }, + ".casual_clothing.mens_clothing.sweatshirts.sullen_mma_sweatshirts" : { + "meta_description" : "Sullen Sweatshirts - Buy your Sullen Hoodies At Zephyr Sports for Less Today! We carry a complete line of Sullen Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Sullen Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Sullen Sweatshirts | Sullen Hoodies | Sullen Hoody" + }, + ".markerupgrades.planet_eclipse_lv1.planet_eclipse_lv1_grips" : {}, + ".skateboard_gear.skateboard_accessories.skateboard_grip_tape.jessup_grip_tape" : { + "meta_description" : "Jessup Grip Tape - Zephyr Sports carries a complete line of Jessup Skateboard Grip Tape At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Jessup Grip Tape On Sale Free Shipping", + "head_title" : "Jessup Grip Tape | Jessup Skateboard Grip Tape" + }, + ".skateboard_gear.complete_skateboards.birdhouse_complete_skateboards" : { + "meta_keywords" : "birdhouse complete skateboards,birdhouse boards,bird house skate boards,skate board,bird house skateboards", + "meta_description" : "Birdhouse Complete Skateboards - Complete line of Tony Hawk Birdhouse Boards in stock and shipping free now. Bird House Skateboards are made with the highest pro quality components. Don't be disappointed, go with Bird House. Phone orders welcome 805-275-2040", + "head_title" : "Birdhouse Complete Skateboards | Birdhouse Boards | Bird House Skateboards" + }, + ".zephyr_sports_coupons" : {}, + ".airsoft.airsoft_guns.colt_airsoft_guns" : { + "meta_description" : "Colt Airsoft Pistol - Buy your Colt Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of Colt Airsoft Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Colt Airsoft Pistol On Sale & Free Shipping", + "head_title" : "Colt Airsoft Pistol | Colt Airsoft Guns | Colt Airsoft Pistols", + "description" : "" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.100_oz_mountain_bike_hydration_packs" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_chronicle_watches" : { + "meta_keywords" : "Nixon watches,nixon Chronicle watch,nixon watch,nixon Chronicle chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Chronicle Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Chronicle Chrono Watches", + "head_title" : "Nixon Chronicle Watches | Nixon Chronicle Chrono Watch | Nixon 5130" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_jawbone_sunglasses" : { + "meta_keywords" : "Oakley Jawbone Sunglasses,Jawbone oakley sunglasses,oakley Jawbone, Jawbone polarized sunglasses", + "meta_description" : "Oakley Jawbone Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Jawbone and Polarized Oakley Jawbone Sunglasses on Sale! ", + "page_title" : "Oakley Jawbone Sunglasses with Free Shipping", + "head_title" : "Oakley Jawbone Sunglasses | Jawbone Oakley Sunglassses" + }, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.matrix_grip_panel" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.mp_40_airsoft_gun_magazines" : {}, + ".buyers_guide.paintball.paintball_guns" : { + "top_description3" : "=Choosing the right Paintball Gun=\n\n\nWe know when your new to paintball the choices can be overwhelming. We try to explain and break down some of these options to help make your buying decision a little easier. Your best bet will be to give us a call or use our live chat to help you make your decision.\n\n\n=Where do you plan to play?=\n\n\nAre you looking to play out in the back woods with a few of your friends? Or are you looking to play at your local field? Do you want to play speedball? or the scenario style games?\n\n\n=Entry Level Paintball Guns for Scenario Play=\n\n\nThere are a broad range of guns in this category with various different features and ability for upgrades. We will go over this by brand to give you a little overview.\n\n\n=Tippmann Paintball Guns=\nThe most popular entry level guns are tippmanns. They offer a good quality gun that will give you very few issues at the field. They are perfect for the beginner that does not want to tinker with there gun. Most Tippmann guns offer an upgrade path for you also. Tippmann Paintball Guns are Proudly Made in the USA so you get great quality, but they are slightly more expensive than some of the competition. You can start with the basic model and than upgrade to either the response trigger or the egrip for more firepower. More information on these upgrade is available on the product pages.\n\n\nTippmann Custom 98 - The Custom 98 is the standard for field rental guns. The 98 Custom will run off of Co2 or Compressed Air. The standard barrel is an 8\" barrel which has decent accuracy. The Platinum series of the 98 comes with ACT Anti Chop Technology which will help reduce breaking paintballs in your gun.\n\n\nTippmann A5 - \n\n=Entry Level Speedball Guns=\n\n\n" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_contact_backpacks" : { + "meta_description" : "Oakley Contact Backpacks - Buy your Contact Oakley PacksAt Zephyr Sports for Less Today! We carry a complete line of Oakley Contact Bags at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Oakley Contact Backpacks Ship Free @ Zephyr Sports ", + "head_title" : "Oakley Contact Backpacks | Contact Oakley Packs| Oakley Contact Bags" + }, + ".harnessesbags.tubes.virtue_pf_pods" : { + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=banners%2fpaintball%2fslideshow%2f1virtue_pf_pods_slideshow%2ejpg&LINK=Virtue+%22Press+Flick%22+Pods%21", + "zs11_banner_wslideshow_slide3" : "ALT=&IMG=banners%2fpaintball%2fslideshow%2fvirtue_pf165_pods_slideshow%2ejpg&LINK=Virtue+%22Press+Flick%22+165+Pods+%2d+20%25+MORE+PAINT%21", + "zs11_banner_wslideshow_slide2" : "ALT=&IMG=banners%2fpaintball%2fslideshow%2fvirtue_pf135_pods_slideshow%2ejpg&LINK=Virtue+%22Press+Flick%22+135+Pods+%2d+20%25+Smaller%21" + }, + ".markerupgrades.planet_eclipse_ego_upgrades.ego_triggers" : {}, + ".casual_clothing.mens_clothing.shorts.fallen_shorts" : { + "meta_description" : "Fallen Shorts - Zephyr stocks a complete line of Fallen Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Fallen needs. ", + "page_title" : "Fallen Shorts with Free Shipping at Zephyr", + "head_title" : "Fallen Shorts | Fallen Board Shorts" + }, + ".empire_prophecy_paintball_loader.empire_prophecy_z2_upgrades" : {}, + ".markerupgrades.matrix.matrix_bolts" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_polarized_sunglasses" : { + "meta_description" : "Von Zipper Polarized Sunglasses - Zephyr Sports carries a complete line of Buy Polarized Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Polarized Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Polarized Sunglasses | Buy Polarized Von Zipper Sunglasses | Von Zipper Polarized Sunglasses Free Shipping" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_pit_bull_sunglasses" : { + "meta_keywords" : "Oakley Pit Bull Sunglasses,Pit Bull oakley sunglasses,oakley Pit Bull, Pit Bull polarized sunglasses", + "meta_description" : "Oakley Pit Bull Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Pit Bull and Polarized Oakley Pit Bull Sunglasses on Sale! ", + "page_title" : "Oakley Pit Bull Sunglasses with Free Shipping", + "head_title" : "Oakley Pit Bull Sunglasses | Pit Bull Oakley Sunglassses" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.g_shock_watches" : {}, + ".markers.jtusapaintballguns.jt_impulse_paintball_guns" : { + "meta_keywords" : "JT Paintball Markers,JT Impulse Paintball Markers,JT Paintball,impulse paintball,paintball guns,paintball gear,JT USA,Impulse paintball markers,", + "meta_description" : "Check Out the Specs on the New JT Impulse Paintball Marker! This Paintball Gun features a 4 Way Adjustable Magnetic Trigger, Balanced Valve Technology and Much, More! Mow Down the Competition with the JT Impulse!", + "top_description" : "== JT Impulse ==\nCheck Out the Specs on the New JT Impulse Paintball Marker! This Paintball Gun features a 4 Way Adjustable Magnetic Trigger, Balanced Valve Technology and Much, More! Mow Down the Competition with the JT Impulse!", + "zoovy:banner02" : "", + "description" : "= Features: =\n* LPR Balanced Valve Technology\n* Air Cushioned Piston\n* Blue OLED Screen\n* Contoured Slim Grip\n* Tool-Less Clamping Feed Neck\n* Wired Break Beam Eyes\n* 4 Way Adjustable Magnetic Trigger\n* Dual bearing suspended trigger\n* Dovetail Mounted ASA System (With optional standard 10-32 mounts)\n* On/Off ASA with Bleed\n* Two Piece 14\" Micro Honed Barrel\n* Adjustable LPR\n* Software upgradable via mini USB (cable not supplied)\n* Spring driven detents for maximum life", + "htmlvids" : "\n", + "page_title" : "Buy JT Impulse Paintball Guns Online On Sale Now", + "head_title" : "JT Paintball Markers | JT Impulse Paintball Markers | JT Paintball" + }, + ".1newsletter" : { + "fheader_01" : "banners/categories/forum_winner_page_header_002", + "winner_01" : "Winner:", + "fdate_02" : "March 2009", + "banner_04" : "banners/newsletter/december_newsletter_g3", + "winner_04" : "Winner:", + "date_05" : "May 2009", + "banner_01" : "banners/newsletter/march_09_newsletter_pinokio", + "description" : "
                                                                          \n\n\n
                                                                          \n
                                                                          \nLATEST WINNERS: * Andrew Rowles was hooked up with a Brand New GoG eNMEy Paintball Marker * Conor Mead Signed up and Earned himself a Brand New Empire BT-4 Combat Slice Paintball Marker! * Ian Dugan Won an awesome pair of Ray-Ban 58mm Aviator Sunglasses! * Houston Lindquist Won a Brand New 2011 Empire AXE Paintball Marker! * D. Ellis, J. Bowen, M. Furr, A. Train, & T. Pietrolungo each won a Zephyr $50 Gift Card! \n
                                                                          \n
                                                                          \n
                                                                          \n\n\n
                                                                          \n\n
                                                                          \n\n\n\n
                                                                          \n\n\n \n \n \n \n \n \n \n \n \n \n \n\n
                                                                          \n
                                                                          \nSign me up for the Zephyr Newsletter:\n
                                                                          \n
                                                                          \n
                                                                          \n Paintball
                                                                          \n
                                                                          \n Airsoft
                                                                          \n
                                                                          \n Baseball & Softball
                                                                          \n
                                                                          \n Surf, Skate, Clothing
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n\n
                                                                          \n
                                                                          \n\n Enter Your Email:
                                                                          \nFull Name:
                                                                          \n\n \n
                                                                          \n

                                                                          \n The protection of your privacy is very important to us. We will never share your personal information with anyone.\n
                                                                          \n
                                                                          \n
                                                                          \n\n
                                                                          \n\n\n
                                                                          \n
                                                                          \nNOTE: Signing up for the newsletter will automatically create an account with Zephyr Sports. A confirmation email will be sent to your email address with your password. Once you retrieve your password, you can log in and make any changes to your account including adding and removing newsletter subscriptions.\n
                                                                          \n
                                                                          \n
                                                                          \nALREADY HAVE AN ACCOUNT: If you already have an account with Zephyr Sports and would like to sign up for the newsletter, please log in using your email and password by Choosing \"My Account\" on the top right of our site. In the control panel click on \"email settings\" (located under account management). From here you can choose which newsletters you would like to receive.\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \nTo enter the Monthly Giveaway please register your email and name above. This will enter you for a chance to win this Month's Giveaway of Your Very Own Empire E-vent Paintball Goggles!!

                                                                          \nYour eligibility will only be for the raffle taken place within the month you initially sign up for the newsletter. Each email address will only be allowed to enter the earliest monthly giveaway upon sign up.

                                                                          \nPlease do not email our staff asking about your status in the monthly raffle as they will not be able to answer your questions about raffle status. Also DO NOT email zephyrsports asking for free or discounted items through our monthly giveaway program.

                                                                          \nUpon the end of each monthly giveaway, we will contact the winner via email at which point the winner will have ONE week to respond. The email will be from sales@zephyrpaintball.com , so please be sure that this address is not directed to your spam mail. If we are not contacted within the given week, then we will consider the email void and choose another participant as that given month's winner. Again, the secondary winner has one week to contact our office either by phone or via email to claim their prize. If you wish to unsubscribe, you can either adjust the newsletter options in your account or click the unsubscribe button on any of our newsletters.

                                                                          \nTHANKS AGAIN AND GOOD LUCK!\n
                                                                          \n
                                                                          \n\n\n\n\n", + "location_01" : "of Abingdon, MD", + "fname_01" : "PB4LVince", + "header1" : "", + "banner_03" : "banners/newsletter/january_09_newsletter_rotor", + "page_head" : "\n\n\n\n", + "banner_05" : "banners/newsletter/may_09_newsletter_tnkd", + "header_01" : "banners/categories/newsletter_winner_page_header_001", + "location_04" : "of the United States", + "winner_02" : "Winner", + "location_03" : "of Christopher, IL", + "date_04" : "December 2008", + "name_06" : "Marcus Black", + "banner_06" : "banners/newsletter/april_09_newsletter_tnkd", + "winner_06" : "Winner:", + "date_06" : "April 2009", + "date_02" : "February 2009", + "location_02" : "of Shreveport, LA", + "date_01" : "March 2009", + "name_04" : "Timothy Kim", + "banner_02" : "banners/newsletter/february_09_newsletter_invert", + "name_03" : "Jeremy Cobin", + "fdate_01" : "January/February 2009", + "name_02" : "Kimberly Roberts", + "fwinner_02" : "TechT Ludicrous Kit, Zephyr Apparel & Headband Winners: ", + "date_03" : "January 2009", + "location_06" : "Awaiting Response.", + "name_05" : "Awaiting Response", + "fwinner_01" : "$100.00 Zephyr Sports Gift Certificate Winner: ", + "winner_05" : "Winner:", + "name_01" : "Craig Miller", + "fname_02" : "Daniel Collins, William Green, David Kellogg, Hep Hepburn, Alex Pino and Arnold Kao", + "winner_03" : "Winner" + }, + ".airsoft.airsoft_spare_magazines.gas_pistol_magazines" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Pistol Mags | Gas Airsoft Pistol Mags | Mags for Gas Airsoft Pistol" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_fixed_power_scopes.nikon_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".shop_by_brand.nxe" : { + "top_html" : "\n\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tNXE PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tNXE CASUAL APPAREL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          " + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_water_bottles.camelbak_bottle_accessories" : {}, + ".casual_clothing.mens_clothing.tshirts.grenade_t_shirts" : { + "meta_keywords" : "Grenade T Shirts,Grenade shirts,free shipping,Grenade TShirt", + "meta_description" : "Grenade T Shirts - Zephyr carries a complete line of Grenade Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Grenade T Shirts at Zephyr", + "head_title" : "Grenade T Shirts | Grenade Shirts |Grenade TShirt" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.srh_ladies_tank_tops" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs" : { + "meta_description" : "Camelbak Mountain Bike Packs - Buy your At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Mountain Bike PacksOn Sale & Free Shipping", + "head_title" : "Camelbak Mountain Bike Packs" + }, + ".2clearance.paintball_clearance_gear.clearance_hoppers" : { + "head_title" : "Sale Paintball Loaders | Clearance Paintball Hoppers | Paintball Loaders Sale" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.utg_spring_airsoft_guns" : { + "meta_description" : "UTG Airsoft Guns - Buy your UTG Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of UTG Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy UTG Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "UTG Airsoft Guns | UTG Airsoft Rifles | UTG Spring Airsoft Guns" + }, + ".apparel.jerseys.tippmannjerseys" : { + "page_title" : "", + "head_title" : "Tippmann Jersey | Tippmann Paintball Jersey | Camo Tippmann Jersey" + }, + ".goggles.us_army_paintball_goggles" : { + "meta_description" : "US Army Paintball Goggles - Buy your USArmy Ranger Paintball Masks Online at Zephyr Paintball for Less today. Free Shipping on US Army Paintball Goggle Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy US Army Paintball Goggles Online On Sale Now", + "head_title" : "US Army Paintball Goggles | USArmy Ranger Paintball Masks | US Army Paintball Goggle" + }, + ".airsoft.shop_by_brand.wg_airsoft" : {}, + ".markerupgrades.smartparts.ion.bodykits.maddog_designz_ion_body_kits" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.camelbak_charge_hydration_packs" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.real-sword-airsoft-guns" : { + "meta_description" : "Real Sword Airsoft Guns - Buy your Real Sword Airsoft -Real Sword Airsoft RifleAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Real Sword Airsoft Guns On Sale & Free Shipping", + "head_title" : "Real Sword Airsoft Guns | Real Sword Airsoft -Real Sword Airsoft Rifle" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.mp5_sub_gun_aeg_airosft_gun_mags" : {}, + ".casual_clothing.mens_clothing.hats.volcom_hats" : { + "meta_description" : "Volcom Hats - Buy your Volcom Baseball Hats Online At Zephyr Sports for Less Today! We carry a complete line of Volcom Caps at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on VOLCOM HATS @ Zephyr Sports", + "head_title" : "Volcom Hats | Volcom Baseball Hats | Volcom Caps" + }, + ".3packagespecials.d3fy_paintball_packages" : {}, + ".casual_clothing.mens_clothing.accessories.audio___headphones.nixon_headphones.nixon_loop_headphones" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.element_pants_and_jeans" : { + "meta_keywords" : "element pants,element denim,element pant,element jean,stretch element pants,element cargo pants,element mens jeans,element denim jeans,element mens pants,stretch element pant,element feeble pant", + "meta_description" : "Element Pants - Huge selection of Element Denim Pants available online at Zephyr Sports. Always the best price, Always free shipping over $75. Buy your Element Jeans online Now!", + "page_title" : "Elements Pants & Jeans with Free Shipping", + "head_title" : "Element Pants | Element Denim Pants | Element Jeans" + }, + ".snowboard_gear.snowboard_goggles.dye.dye_t1_dts_snow_goggles" : {}, + ".markerupgrades.smartparts.ion.ion_maintenance_kits" : {}, + ".markerupgrades.grips_and_grip_panels.tanked_paintball_grips" : {}, + ".safetygear.kneeelbowpads.zephyr_sports_knee___elbow_pads" : {}, + ".casual_clothing.womens_clothing.ladies_tank_tops.eclipse_ladies_tank_tops" : {}, + ".airsystems.tankcovers.guerilla_air_tank_covers" : { + "meta_description" : "Guerrilla Air Cover - Buy your Guerrilla Air Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Guerilla Paintball Bottle Cover Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Guerrilla Air Cover Online On Sale Now", + "head_title" : "Guerrilla Air Cover | Guerrilla Air Tank Cover | Guerilla Paintball Bottle Cover" + }, + ".3packagespecials.empire_paintball_packages.empire_axe" : { + "meta_keywords" : "Empire AXE Paintball Gun,Empire AXE Marker,AXE Empire Paintball Guns,paintball guns,paint ball guns,empire,empire paintball,paintball marker,axe kit, axe package", + "meta_description" : "AXE Empire Paintball Guns - Empire Axe Paintball Guns are Empire Paintballs latest and greatest paintball gun yet! Zephyr Paintball carries the Empire Axe Paintball Guns, Empire Axe Upgrades and more! Pick up your paintball game with the Axe Paintball Gun from Empire! Be completely prepared with the Empire Axe Paintball Packages.", + "top_description2" : "==Empire AXE Paintball Marker==\n\nWhat do you need to cut through a forest of opposition...the AXE! The new Empire AXE is a Mini on steroids; bigger, badder and willing to punish opponents. The new shape and extended grip frame give you a comfortable firing position for all day play. The Empire Relay On/Off Regulator ASA makes air bottle removal using the lever, quick and easy. The unique push-button, tool-less bolt removal system makes maintaining the AXE simple, at the end of the day. All that was great in the Mini has been carried forward into a new design. The proven Mini break-beam eye system and electronics, power this marker to ultra fast firing that is gentle on paint. Wield the AXE, the newest paintball gun from Empire and cut down everyone in your way.", + "page_title" : "Empire AXE Paintball Packages Ship Free at Zephyr Paintball", + "head_title" : "Empire AXE Paintball Gun | Empire AXE Marker | AXE Empire Paintball Guns", + "description" : "=Empire AXE Features:=\n* Unique Push Button Bolt Removal System For Easy Maintenance\n* Empire Relay Regulator/ASA with ON/OFF Lever Makes Tank Removal a Breeze\n* Extended Grip Frame and New Grip for Increased Comfort\n* Magnet Returned Bearing Trigger Offers Smooth Firing Action\n* Accurate, Lightweight, Aluminum Barrel Hits Your Target\n* Integrated Break Beam Anti-Chop Eyes Eliminates Chopped Balls\n* Outstanding Velocity Consistency Offers Performance You can Depend On\n* Low Pressure Operation is Gentle on Paint\n* Multiple Adjustable Firing Modes (Semi, PSP Ramping, NXL, & Millennium Ramping)\n* Patented Proprietary Slipstream Solenoid Allows For Fast Firing\n* Through Grip Air Transfer Means No Hoses to Crimp or Break8\n* Clamping Feedneck- No Tools to Mount the Loader\n" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_peak_load_backpacks" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs.women_s_camelbak_magic_hydration_packs" : {}, + ".shop_by_brand.voodoo_tactical" : {}, + ".casual_clothing.womens_clothing.ladies_watches.vestal_ladies_watches" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".shop_by_brand.bt_battle_tested" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tBT PAINTBALL APPAREL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tBT PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n\n", + "top_description2" : "=Empire Battle Tested Paintball - Take On The World=\n\nBT Paintball guns are the worldwide leader in the manufacturing and distribution of paintball sporting goods. Dedicated to quality, craftsmanship, and customer service, BT Battle Tested Paintball embodies the sport of Paintball - Life, Function, Style. \"It's what we do.\" Buy your BT paintball marker today and see how your game changes. You'll feel like you can take on the world. Choose from our selection below.", + "head_title" : "BT Paintball guns | BT paintball gun | BT paintball marker", + "zoovy:banner01" : "banners/paintball/headers/battle_tested_header.jpg", + "description" : "=Empire Battle Tested Paintball, take on the world=\n\n==Designed for the outdoors==\nThese guns are made for the rough and tumble of the outdoors, and designed for the tactical usage that speed ball lacks. These guns come with battery and light mounts, tactical sights and everything else you need to out strategize the enemy.\n\n\n==BT Combat Tested ERC Paintball Gun==\nWhat happens when you take the standard BT-4 Combat and load it full of technology, you get the BT4 ERC paintball gun. The BT-4 ERC comes standard with both the BT Electronic Grip Frame and BT Rip-Clip, allowing you to experience the fastest possible rate-of-fire. The Rip-Clip force-feed loader system utilizes HALO technology, including the built-in Rip Drive, to throw a wall of paint towards the enemy. The Apex barrel system allows you to customize your shot trajectory to hit hidden opponents. Does a tree or bunker stand between you and a kill? Dial up the Apex to curve your shot right on target. The BT 4 ERC offers technology on the battlefield that few markers can match. If you have a need for speed and precision, this is the marker that delivers.\n\n\n==BT-4 Combat Paintball Gun==\nThe BT-4 Combat is the marker that started the BT-4 Series. It's the perfect scenario or woodsball marker which allows you to build the perfect one-of-a-kind beast. Fully upgradeable, the Combat is the scenario marker by which others are judged. This reliable and accurate marker is the obvious choice for use in your scenario or woodsball event. The front grip is removable and the military standard dual Picatinny rails accept many tactical upgrades like optics and other accessories like the BT Flashsight. The trigger system can be enhanced with by installing the Double Trigger and Electronic Grip Frame to increase your rate of fire. With available upgrades like the HALO powered Rip Clip and Apex Barrel system, the BT4 Combat is the core of our successful BT4 line of markers. If you are looking to customize your paintball gun, start with the BT4 Combat and open a world of realistically styled marker configurations. Step into Combat with BT Paintball.\n\n\n==BT Delta Elite Paintball Gun==\nBT Paintball strives to create markers with a real-world look and feel. The BT Delta Elite paintball gun design is based on the world's pre-eminent submachine gun and is the choice of many players who desire authenticity. While it looks like it's straight off the battlefield, it has some advanced features that make it an awesome paintball marker. Manage the number of paintballs you can shoot with the Electronic Grip Frame, offering multiple firing modes, such as semi-auto, adjustable ramping and full auto. The Rip Clip force feeds paintballs using sound-activated HALO technology and when paired with the E-Grip and Double Trigger, puts more paint in the air than your opponent can duck. The Apex Barrel can create custom shot trajectories, specifying left or right hooks, drop shots and even extended range. There's no place to hide from the player using the Elite. The Delta Elite paintball gun has an adjustable stock for a comfortable fit and adjustable range rear sight for accurate shooting. The small, compact size is perfect for Close Quarters combat and the rate of fire will ensure you emerge victorious. The Delta Elite is tough, its baked on coating can withstand impacts and the quality construction assures it will continue to fire. Whether using CO2 or compressed Air, the Delta Elite paintball gun give you the edge over the opposition and guarantee your day will be fun.\n\n\n==BT Delta Paintball Gun==\nFor the scenario or woodsball player who wants realism, BT Paintball offers the BT4 Delta paintball gun. Based on the MP5, most recognizable submachine gun in the world, BT has created a compact, accurate paintball marker that looks like it should be carried by SEALs. The Delta paintball gun has a lightweight, balanced construction for all day play and an adjustable stock for a comfortable firing position. The clamping feedneck will accept loaders without the need for tools, or upgrade to a BT Rip Clip for HALO powered force feed loading. The Delta gun has a modular trigger, so taking it apart for cleaning is simple, and easily upgrades to the Double Trigger or the Electronic Grip Frame for increased firepower. The compact BT4 Delta is an accurate, reliable paintball gun with an authentic look that will help you and your team reign supreme on the battlefield.\n\n\n==BT Omega Tactical Paintball Gun==\nThe new BT Omega Paintball Marker will take you into battle without breaking the bank! The rugged aluminum body will withstand heavy duty combat situations and provides increased performance and durability. The Omega will require little in terms of regular maintenance. Fully upgradeable, the Omega easily accepts numerous BT upgrades, such as the HALO powered Rip Clip,the BT1913 Barrel, the BT Clamp Elbow Kit and the Tactical Folding Stock. Carrying your marker out to battle has never been easier thanks to its secure carry handle. The Omega's permanent, fixed sight rail provides you a continuous lock on your opponents, thereby giving you the confidence needed to take them out of the game. Grab your gear, lock and load and hit the field running with the Omega today!\n\n\n==BT Paintball SA-17 Paintball Pistol==\nThe new SA-17 paintball pistol from BT has a bold profile and big performance. Built on the successful US-P platform, this new paintball pistol has a precision milled aluminum body for durability and a new spring feed system that can feed forwards or backwards. Utilizing full-size internals means this gun will perform like the big boy it is and dominate your opponents on the field. Featuring multiple Picatinny rails, the SA-17 is designed with a military-inspired look and can accept cool aftermarket accessories. The quick change CO2 system and easy feed tube loading means you won't get caught short when the enemy counterattacks. Grab a SA-17 and remember that size matters when the game is on the line.\n\n\n==BT TM-7 Tactical Paintball Gun==\nThe BT TM-7 utilizes Mini Technology to inflict maximum force from a marker of minimal size. Don't be fooled by the size of the TM-7's exterior; it can hang with the big boys and is by no means a lightweight. Once you hold this marker and pull the trigger, you won't want to put it down. Its lightweight, yet durable construction is perfect for close quarters or long-range combat. This is the marker that just may have people rethink the way they looked at Mil-Sim paintball markers. Mounting cool accessories is simple with the BT TM-7 paintball gun. The multiple Picatinny rails will fit optics, sights, lasers, flashlights, or anything needed to improve your experience. The lightweight construction matched with the folding Foregrip and adjustable stock allow for comfortable all-day play. Like the Mini, the TM-7 has no external hoses, giving it a clean look and the authentic feel of the real-world firearm it's based on. No paintball gun has the look and technology to match the TM-7 while in the field. Watch your opponents run when you switch to full auto using the shift-on-the-fly selector lever. Command the battlefield with the TM-7 from BT Paintball Designs.\n\n\n==BT TM-15 Paintball Gun==\nThe BT TM-15 is the ultimate choice for any woodsball or mil-sim paintball enthusiast. Its high performance magnesium body is ultra strong, yet light enough for all-day action. Equipped with features usually found on much more expensive markers, the BT TM-15 features a true electropneumatic operating system as well as reduced sound signature for stealth firing in any of the multiple firing modes. With the standard multiple Picatinny rails, accessory options are nearly endless. Internal airline operation eliminates external hoses. Plus, front and rear sights ensure you get your shot.\n\n\n==Empire Bt Tracer Pump Gun==\nThe internals of the new Empire Tracer paintball gun are compatible with the original PMI Trracer which have been proven for the past 15+ years. When you take hold of the pump handle on the new Empire Tracer paintball gun you will feel the most comfortable and ergonomic handle. Those old days of struggling to pump your gun are gone for good. Picatinny rails are mounted on the top of the Empire Tracer so you can mount all of your favorite accessories. The Empire Tracer is compatible with either CO2 or HPA and will accept any Autococker threaded barrel or barrel kit. The Empire Tracer pump paintball gun is affordable to any new player, pump player or anyone looking to bring back some old memories." + }, + ".barrels.tippmann98" : { + "meta_keywords" : "tippmann 98 barrels,US Army Barrels, 98 custom tippmann,tippmann 98 barrels,tippmann 98 custom barrel,barrels for tippmann,98 paintball,98 tippmann,tippmann paintballs,tippmann 98 paintball guns", + "meta_description" : "Tippmann 98 Barrels - Your first upgrade for your Tippmann 98 Custom or US Army Gun has to be a barrel. The stock 98 Custom Tippmann Barrel is the weakest link in the best entry level paintball marker ever made. Get your tippmann 98 Barrel at Zephyr Today", + "top_description" : "One of the first upgrades for your tippmann 98 should be a high performance barrel. The Model 98 is a bulletproof entry level paintball gun, but we all know the stock barrel leaves a bit to be desired. There are lots of choices when your ready to upgrade. Are you looking for more distance? better accuracy? Read through our barrel choice guideline below.", + "page_title" : "Buy Tippmann 98 Barrels Online On Sale Now", + "head_title" : "Tippmann 98 Barrels | US Army Barrels | 98 Custom Tippmann", + "sortby_var" : "Barrel Size / Type", + "description" : "=Spin is good for distance, or a little curveball=\n\nIf distance is your thing, you need to take a look at either the Tippmann 98 Flatline barrel or the BT Apex barrel. Both of these put spin on the paintball to increase distance. The flatline barrel puts a fixed backspin on the ball adding 100-150 feet to your shot. Backspin also flattens out your shot so your not looping paint onto the field. The BT Apex takes a little different look at the backspin method. The BT apex allows you to adjust the amount of spin as well as the angle. You can put backspin, side spin, or top spin on the ball. Have someone hiding in a bunker and blind firing at you? Give it a little top spin and you can rain paint down on them. someone keeps leaning out from behind a bunker and shooting at you, give it a little sidespin and hit them with the curveball. The BT apex takes a little getting used to, but once you get used to it, it's a great tool. And if you want to turn off the spin, you have that option too.\n\n\n=Standard Tippmann Model 98 Barrels=\n\nModel 98 upgrade barrels atart at about $35. The J&J ceramic barrels are the standard upgrade barrel. The ceramic coating is amazing if you break paint in the barrel. Typically your able to fire a few shots and the barrels clean and good to go. Worse case run a swab through the barrel and your set. Accuracy on the J&J barrels are a vast improvement over stock. The next step in 98 barrels is the tippmann sniper barrel or lapco bigshot. The tippmann Sniper barrel is a pretty decent upgrade over stock at about $40. The lapco bigshot is a bit more pricey at about $65, but lapco barrels are known for there dead-on accuracy. The lapco barrels also allow you to attach various different tips to change the look of your gun.\n\n\n\n=Guns that use Model 98 threads=\n*Tippmann Model 98, custom 98, and Pro\n*US Army Alpha\n*US Army Alpha Tactical\n*US Army Project Salvo\n*US Army Carver One\n" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns" : { + "meta_keywords" : "KWA Airsoft Guns,M9 series,KWA pistols,full metal,KWA Airsoft Pistols,high-capacity magazines,gas powered airsoft guns,Blow back airsoft guns", + "top_html" : "
                                                                          \n
                                                                          \n
                                                                          ", + "meta_description" : "KWA Airsoft Guns. KWA is a U.S. company dedicated to making airsoft replicas of popular handguns and rifles. Most notable are their handguns and their popular M9 series. KWA delivers incredible realism to the handgun market. With full metal bodies, high-capacity magazines, and an all new gas system, KWA pistols are second to none. Zephyr Sports carries a wide variety of KWA pistols including gas powered airsoft guns, Blow back airsoft guns, and more!", + "top_description2" : "KWA USA is renown for their high quality parts, airsoft pistols, and airsoft guns. Using advanced engineering, KWA develops each of its airsoft guns to the utmost realism mimicking the real steel firearms firing action and field stripping. With the development of the NS2 and FV systems, KWA has made their gas pistols a step ahead of the competition producing increased efficiency and consistent shots. For the full electric AEG rifles, the 2GX gearbox was pioneered. The 2GX is a CNC machined highly reinforced gearbox that is lipo ready out of the box and has incredible upgrade potential. If you are looking for some of the best airsoft guns, go no further than the battle proven replicas by KWA. Details below!", + "zoovy:banner01" : "banners/airsoft/headers/kwa_ns2_header001", + "prodlist1_header" : "KWA Airsoft Guns", + "description" : "", + "htmllinks" : "==Bio:==\nKWA started out as an airsoft pistol manufacture from their sister company KSC, providing decent quality pistols for their M9, 1911, G36C, and old USP series. Since then, they have expanded to include SMGs, AEGs, and even gas blow-back rifles and have incorporated such trades as CCCP, [[H&K airsoft guns]:url=/category/airsoft.airsoft_guns.heckler___koch_airsoft_guns/] and even Magpul PTS into their products for authentic trademarks. Their new Mark series of airsoft pistols, the new KWA M4 line, and the H&K USP series have proven to be extremely popular amongst airsofters. \n\n\n==Continuing to innovate:==\nA few years ago KWA announced their new NS2 system. A brand new patented design found exclusively on KWA products, the NS2 system uses an advanced, lightweight composite gas piston with a two stage internal expansion chamber that delivers the gasses more efficiently, and consistently than previous systems.\n\n\nMore recently, the 2GX gearbox was released for KWA's M4/M16 series of AEGs. The 2GX is a robust gearbox shell engineered with structural reinforcement in areas prone to cold temperature failures typical in high powered gearboxes. Rather than Zinc metals (pot metal), these gearboxes are forged from high grade alloy steel, tempered with KWA's hardening process. The extremely precise machining a six 9mm bearings in this gearbox ensure maximum performance in a Lipo ready AEG.\n\n\nJust announced is the new FV (Force velocity system) engineered by KWA to be incorporated in their new KRISS VECTOR, AK-74 and M4 series Gas Blow-Back Rifles. The FV system uses a unique simplified design of the internal cylinder return spring that improves operational reliability while maintaining a consistent cyclic rate. The Force Velocity reinforced piston is made of a high strength polymer that delivers superb gas efficiency and reliability to the rifle in a wide range of temperatures and climates.\n\n\nA new design coming out is the 3GX gearbox and the KFS (Kinetic Feedback System). This new gearbox design is going to be used in KWA's upcoming AK-74 series of AEGs. Based on the Version 3 gearbox, the 3GX will set a new standard for performance and reliability, utilizing many of the innovations found in the 2GX gearbox. The new platform allows for the integration of the KFS system that utilizes a synchronized counter weight to deliver the sharp recoil seen on most GBBRs. Later the KFS is going to be integrated into the 2GX gearboxes, giving M4 users an enhanced experience.\n\n\n==Tried and True Models:==\nTwo of the most popular series KWA has made are the USP airsoft pistols, and the KM4 airsoft AEGs. The USPs have been made with a host of variations from the Tactical, to the Compact and even a few special models have been shown the USP MATCH, and the USSOCOM MK23. The KM4 series have seen similar diversity, incorporating CQB, and M16 lengths, as well as providing RIS and tradition foregrips for all your accessory needs.\n\n\nBridging the gap between gas blow-back pistols and full AEG rifles are KWA's SMGs including the KMP9, M11A1 (Mac11), KMP9R, the FPG and the H&K MP7A1. These high quality sub machine guns utilize KWA's NS2 system and are capable of hosing rounds at ridiculous rates of fire to clear rooms, buildings, or where ever the enemy is hiding.\n\n\n==New Releases:==\nSoon to be released are the new gas blow-back pistols, the 945, 1911A1 US ARMY, and the GBBR LM4 series. The KWA LM4 series of rifles utilizes the new FV system and come in a variety of different configurations. These GBBRs will be green gas powered with a 40 round M4 mag or 38 round Magpul PMag style magazine both powering the rifle to fire between 390 and 410 fps. Additionally, a special edition Magpul PTS KWA LM4 will be released will be released with Magpul furniture and a stamped lower reciever. These full metal rifles are extremely realistic, down to the firing function and the take down all components have been engineered to be as close as possible to real AR-15 operation.\n\n\nFor the Red or Russian themed players, KWA is releasing the MKV Makarov, TT-33 Tokarev, and their line of AK-74 AEGs and GBBRs. The AK-74's will come in two varieties, the gas powered and the electric powered rifles. The gas powered AK-74's use the new FV system firing between 390 and 410 fps and will hold 40 rounds in their magazines. Two variations will come out for the gas AK-74 line the AK-74M (a full sized AK with sight mount and side folding stock) and the AK-74SU (a carbine sized rifle with a skeletonized side folding stock and sight rail). These GBBR AK-74's function and field strip exactly like their real steel counterparts. The AEG AK's will be using the 3GX gearbox and the new KFS system giving these electric airsoft guns a sharp, crisp recoil every round that is fired. \n\n\nAlso to come out is the hotly anticipated ATP AUTO variant and KRISS Vector. The AUTO will utilize the same NS2 system as the ATP but swap out some of the firing mechanism allowing the gas pistol to fire in fully automatic. It will keep the same functionality and also be compatible with the same mags and the 50 round ATP/FPG magazines. The KRISS Vector is scheduled to release this summer. It uses the new FV system and has its own dedicated 50 round magazine operating off of green gas. Though the project was started several years ago, KWA has finally finished replicating the highly unusual delayed bolt recoil system found in the real steel weapon. It will be fully functional just like the real steel KRISS right out of the boxes replicating every feature down to the smallest component.\n\n\nComing soon is KWA's CQR series AEGs. These two M4s are meant to provide a cheaper alternative to many of the high end models while still retaining the amazing quality KWA produces. The CQR MOD 1 and 2 are the standard M4 and CQB AEGs, with all teh same high performance internals seen on expensive high end guns for less than 200 dollars. The only difference KWA made to these two models is that replaced the machined steel lower receiver with a high strength polymer lower receiver. This means you get a Lipo ready airsoft gun for under 200 dollars, with the only change being the lower receiver. If you've been waiting to get a KWA KM4 but have been hesitant about the cost, then the MOD 1 and 2 are right for you!\n\n\n=DISCLAIMER:=\nAll Airsoft replica bb guns include a safety orange muzzle tip (at least 1/4 of an inch) in accordance with Federal law. Any attempt to remove the orange tip is a violation of Federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state and local jurisdiction. You must be 18 to purchase airsoft equipment", + "page_title" : "KWA Airsoft Pistols On Sale & Free Shipping", + "head_title" : "KWA Airsoft Pistols | KWA Airsoft Guns | KWA M9 Airsoft" + }, + ".maddog.dealerinquiries" : { + "description" : "

                                                                          For dealer pricing, fax your business license or resale certificate to \n805-293-8717 or email to maddogdesignz@yahoo.com.

                                                                          " + }, + ".markerupgrades.tippmann.a5.tippmann_a_5_sight_rails" : { + "prodlist1_header" : "Tippmann A5 Sights & Sight Rails" + }, + ".1_wip.newsletter_winners" : { + "header_01" : "banners/categories/newsletter_winner_page_header_001.jpg", + "winner_02" : "Winner: Awaiting Response!", + "date_04" : "December 2008", + "winner_01" : "Giveaway Ends Feb. 28", + "location_02" : "", + "banner_04" : "banners/newsletter/december_newsletter_g3", + "date_02" : "January 2009", + "name_04" : "Timothy Kim", + "date_01" : "February 2009", + "banner_02" : "banners/newsletter/january_09_newsletter_rotor", + "name_03" : "David Giunta", + "name_02" : "Adriana Villa", + "winner_04" : "Winner:", + "banner_01" : "banners/newsletter/february_09_newsletter_invert", + "date_03" : "January 2009", + "location_01" : "", + "name_01" : "", + "banner_03" : "banners/newsletter/january_09_newsletter_rotor", + "winner_03" : "Winner: Awaiting Response!" + }, + ".maddog.tippmann_upgrades.tippmann_a_5_upgrades" : {}, + ".shop_by_brand.sector_9" : {}, + ".shop_by_brand.ares" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_pit_boss_hydration_packs_" : {}, + ".casual_clothing.mens_clothing.hats.hk_army" : {}, + ".scenarioupgrades.flashlights___laser_sights.ncstar" : {}, + ".casual_clothing.mens_clothing.wallets.hurley_wallets" : { + "meta_description" : "Hurley Wallets - Buy your Hurley Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Hurley Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Hurley Wallets on Sale @ Zephyr Sports", + "head_title" : "Hurley Wallets | Hurley Mens Wallets | Hurley Wallet" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_cooper_sunglasses" : { + "meta_keywords" : "spy cooper sunglasses,spy cooper,spy cooper polarized sunglasses,spy optic cooper,spy cooper glasses", + "meta_description" : "Spy Cooper Sunglasses - Zephyr carries a complete line of Spy Optic Cooper Sunglassess including the Spy Cooper Polarized line of sunglasses. With Free shipping, a 30 day satisfaction guarantee and 1 year breakage protection, Zephyr Sports is your last Sunglass Shop ", + "page_title" : "Buy Spy Cooper Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Cooper Sunglasses | Spy Cooper Polarized Sunglasses | Spy Optic Cooper" + }, + ".casual_clothing.mens_clothing.shirts.1_search_by_size.3_large" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_cloverdale_sunglasses" : { + "meta_description" : "Spy Optics Cloverdale Sunglasses - Zephyr Sports carries a complete line of Cloverdale Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Cloverdale Sun Glasses Online Today.", + "page_title" : "Spy Optics Cloverdale Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Cloverdale Sunglasses | Cloverdale Spy Sunglasses Free Shipping | Buy Spy Cloverdale Sun Glasses" + }, + ".casual_clothing.z-sunglasses.polarized_sunglasses" : { + "meta_description" : "Discount Polarized Sunglasses - Zephyr Sports carries a complete line of Free Shipping Sunglasses Polarized At the lowest prices on the web with free shipping and easy returns. Buy your Buy Polarized Sun Glasses Online Today.", + "page_title" : "Discount Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Discount Polarized Sunglasses | Free Shipping Sunglasses Polarized |Buy Polarized Sun Glasses" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.es_pants_and_jeans" : { + "meta_description" : "Es Pants - Buy your Es Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Es Pants & Jeans Ship Free", + "head_title" : "Es Pants | Es Jeans" + }, + ".shop_by_brand.contract_killer_clothing" : { + "meta_description" : "Contract Killer Clothing - Buy your Contract Killer ApparelAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=The Smell of Victory; Contract Killer Clothing=\n\nContract Killer Clothing has been a source for UFC apparel and paintball harnesses for over a decade. Their line of T-shirts, Fight shorts, hats, gear bags, backpacks, and paintball harnesses are the best in the market. Contract Killer has their roots set in fighting and paintball, and they've been doing both for awhile so they know what you need for all your UFC and paintball clothing needs. Contract Killer MMA Clothing incorporates the needs of all fighting styles into their clothing while capturing the fighting spirit of those who wear it. For those who require innovation, function, and style and for those that push their limits when they smell the blood, they can taste victory Contact Killer Clothing is for you. ", + "page_title" : "Buy Contract Killer Clothing On Sale & Free Shipping", + "head_title" : "Contract Killer Clothing | Contract Killer Apparel", + "description" : "=The Smell of Victory=\n\n==Where the Fight Started==\n\nLike all companies that have been around the block, Contract Killer knows the ins and outs of making a good product that can be used in any situation for fighting, practice, or even paintball. Contract Killer started when UFC was first getting a name, and now they have evolved. They have kicked out the old, and brought in the new and versatile just like the UFC. Not everything works forever, and one needs to be versatile when creating product for ever changing clientele. Contract Killer does this with the ease and finesse of a skilled fighter. \n\n\n==Why Contract Killer?==\nContract Killer offers some of the coolest and most creative high quality product in the UFC/MMA market today. Their wide range of styles and fits tailor to all customers needs. The products are made to last,and they are made to perform. Contract Killer's products are nothing to scoff at, and if you do, you might end up with a bloody nose. Contract Killer. Fight. Hunt. Compete. \n\n\n\n\n\n" + }, + ".casual_clothing.mens_clothing.tank_tops.globe_tank_tops" : {}, + ".airsoft.shop_by_brand.kwa_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "KWA | KWA Airsoft | KWA m4" + }, + ".loaders.hopper_batteries____chargers" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_super_method_sunglasses" : { + "meta_description" : "Smith Optics Super Method Sunglasses - Zephyr Sports carries a complete line of Super Method Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Super Method Sun Glasses Online Today.", + "page_title" : "Smith Optics Super Method Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Super Method Sunglasses | Super Method Smith Sunglasses Free Shipping | Buy Smith Super Method Sun Glasses" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.enjoi_ladies_t_shirts" : {}, + ".casual_clothing.mens_clothing.jackets.hurley_jackets" : { + "meta_description" : "Hurley Jackets - Buy your Hurley Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Hurley Jackets with Free Shipping", + "head_title" : "Hurley Jackets | Hurley Mens Jackets | Jackets Hurley" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_asian_fit_sunglasses" : { + "meta_keywords" : "Oakley Asian Fit Sunglasses,Asian Fit oakley sunglasses,oakley Asian Fit, Asian Fit polarized sunglasses", + "meta_description" : "Oakley Asian Fit Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Asian Fit and Polarized Oakley Asian Fit Sunglasses on Sale! ", + "page_title" : "Oakley Asian Fit Sunglasses with Free Shipping", + "head_title" : "Oakley Asian Fit Sunglasses | Asian Fit Oakley Sunglassses" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.we_gas_airsoft_guns" : { + "meta_description" : "WE Airsoft Guns - Buy your WE Airsoft Pistols Online At Zephyr Sports for Less Today! We carry a complete line of WE Gas Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy WE Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "WE Airsoft Guns | WE Airsoft Pistols |WE Gas Pistols" + }, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_indie_sunglasses" : { + "meta_description" : "Anarchy Indie Sunglasses - Zephyr Sports carries a complete line of Anarchy Indie Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Indie Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Indie Sunglasses | Anarchy Indie Sun Glasses" + }, + ".markerupgrades.kingmanspyder.feednecks.spyder_feed_necks___no_holes" : {}, + ".casual_clothing.womens_clothing.ladies_wallets.nixon_ladies_wallets" : {}, + ".shop_by_brand.zephyr_sports" : {}, + ".casual_clothing.womens_clothing.ladies_shorts" : {}, + ".casual_clothing.mens_clothing.accessories.cell_phone_cases.incase_cell_phone_cases" : { + "meta_description" : "InCase Phone Cases - Buy your InCase Iphone CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "InCase Phone Cases", + "head_title" : "InCase Phone Cases | InCase Iphone Cases" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs.women_s_camelbak_aventura_hydration_packs" : {}, + ".skateboard_gear.skateboard_wheels.sector_9_skateboard_wheels" : { + "meta_keywords" : "skateboard wheels,skate wheels,skateboard wheel,skate wheel,skateboarding wheels,Sector 9 Longboard wheels,skateboard equipment,bearings,sector 9 longboard complete,longboarding", + "meta_description" : "Sector 9 Skateboard Wheels - Zephyr Sports now carries Skateboard Wheels by top skate companies! Sector 9 Skate wheels are some of the best in the buisness for longboarding! Zephyr Sports is your skateboarding stop to shop! All kinds of skateboard equipment! Get everything from the standard skateboard wheel and bearings to the decked out Sector 9 Longboard Complete @ Zephyr!", + "page_title" : "Buy Sector 9 Longboard Wheels On Sale & Free Shipping", + "head_title" : "Sector 9 Longboard Wheels | Skate Wheels | Skateboarding Wheel" + }, + ".shop_by_brand.crossfire" : { + "top_description2" : "=Crossfire tanks, the best tanks around!=\n\nCrossfire tanks likes to do things differently. Their manufacturing plant is 100% DOT approved and regulated with constant 3rd party supervision. Crossfire is also one of the largest and best makers of tanks in the business. Try The Crossfire Carbon Fiber Tanks for decreased weight and increased durability. With crossfire you can use your tank for Co2 or compressed air. Try Crossfire today and you will know why these are considered the best tanks in the industry!\n\n", + "head_title" : "Crossfire CO2 | Crossfire carbon fiber | Crossfire tanks", + "description" : "=Crossfire tanks, the best tanks around=\n\n==About Crossfire==\nCrossfire tanks are 100% Authentic and genuinely American. Their plant is even located Missouri! These guys have been in the business for over 18 years, so they know their stuff when it comes to paintball. \n\n==Nitrogen, Co2, and compressed air==\nNo matter what you are running, Crossfire tanks will meet all of your needs. They have product for nitrogen compressed air, and co2. These tanks are lightweight and extremely durable and reliable. They also look awesome!" + }, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_sandlot_series_baseball_gloves" : { + "head_title" : "Rawlings Sandlot Series Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".casual_clothing.mens_clothing.hats.dc_hats" : { + "meta_description" : "DC Hats - Buy your DC Baseball Hats At Zephyr Sports for Less Today! We carry a complete line of DC Caps at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on DC HATS @ Zephyr Sports", + "head_title" : "DC Hats | DC Baseball Hats | DC Caps" + }, + ".markerupgrades.bob_long_upgrades.bob_long_upgrade_bolts" : { + "meta_description" : "Bob Long Bolt Upgrades - Buy your Marq Victory Bolts Online at Zephyr Paintball for Less today. Free Shipping on BobLong Intimidator Upgrade Bolt Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Bob Long Bolt Upgrades Online On Sale Now", + "head_title" : "Bob Long Bolt Upgrades | Marq Victory Bolts | BobLong Intimidator Upgrade Bolt" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.camelbak_asset_hydration_packs" : {}, + ".maddog.z" : { + "description" : "=Maddog Shipping Policy=\r\n\r\n\r\nAll orders (except Guns)will be shipped within 24 hours Mon through Friday. Please allow up to 2 days on guns since we typically build and test these for each order. Orders will be shipped via fedex and will require a signature upon delivery. You will be e-mailed a tracking number as soon as your order ships. \r\n\r\n\r\n=International Orders=\r\n\r\n\r\nWe are not responsible for any customs fee or taxes. Please research the legality of importing any of our products before purchasing, We are not responsible for items confiscated by customs. " + }, + ".empire_prophecy_paintball_loader.empire_prophecy_z2_quick_feeds" : {}, + ".casual_clothing.mens_clothing.beanies.lrg_beanies" : { + "meta_description" : "LrG Beanies - Buy your Beanies LrGAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on LRG BEANIES @ Zephyr Sports", + "head_title" : "LrG Beanies | Beanies LrG" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.1_search_by_size.2_small_ladies_tank_tops" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_heavenly_sunglasses" : { + "meta_description" : "Arnette Heavenly Sunglasses - Zephyr Sports carries a complete line of Heavenly Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Heavenly Sun Glasses Online Today.", + "page_title" : "Arnette Heavenly Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Heavenly Sunglasses | Heavenly Arnette Sunglasses | Arnette Heavenly Sun Glasses" + }, + ".casual_clothing.mens_clothing.tank_tops.1-search_by_size.1-small" : {}, + ".casual_clothing.mens_clothing.wallets.quicksilver_wallets" : { + "meta_description" : "Quicksilver Wallets - Buy your Quicksilver Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Quicksilver Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Quicksilver Wallets on Sale @ Zephyr Sports", + "head_title" : "Quicksilver Wallets | Quicksilver Mens Wallets | Quicksilver Wallet" + }, + ".airsoft.airsoft_guns.uhc_airsoft_guns" : { + "meta_description" : "UHC Airsoft Guns - Buy your UHC Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of UHC AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy UHC Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "UHC Airsoft Guns | UHC Airsoft Rifles | UHC AEG", + "description" : "" + }, + ".markerupgrades.planet_eclipse_etek_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add2_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.etek_grip_panel/", + "buttonname_02" : "", + "banner3" : "zephyr_buttons/grips_btn001", + "buttonname_01" : "", + "add1_link" : "/category/barrels.autococker/" + }, + ".casual_clothing.mens_clothing.socks.north_face_socks" : { + "meta_keywords" : "North Face socks,North Face mens socks,North Face men socks", + "meta_description" : "North Face Socks - Zephyr stocks a complete line of North Face Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your North Face needs. ", + "page_title" : "North Face Socks on Sale at Zephyr", + "head_title" : "North Face Socks | North Face Mens Socks" + }, + ".shop_by_brand.km" : { + "" : "", + "top_html" : "\n\n \n \n \n\n
                                                                          \n \n \n \n \n \n
                                                                          ", + "meta_description" : "KM Paintball Straps - Buy your KM Straps At Zephyr Sports for Less Today! We carry a complete line of KM Spines at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=KM, Strap in=\n\nKM straps are all about being the highest quality goggle straps. KM Paintball straps are some of the most diverse and unique straps on the field, or anywhere. KM is a maker of many Paintball accessories and products, including the line of KM spines that come with lifetime warranties. With so many different accessories to choose from you can personalize your gun and your outfit to the specifications you want to meet. Go KM today!", + "zoovy:banner01" : "banners/paintball/headers/km_straps_header.jpg", + "description" : "=KM, Strap in=\n\n==KM, a new way to show your stuff==\nKM Paintball is a tailored manufacturer of Buckles, Spines, Headbands, Straps, Apparel, and Columns. They make some ridiculously cool and unique products that cater to individuals needs. With designs like Rasta Stripper and Ghetto Monkey, Zephyr is sure that you will find some product that will appeal to you. \n\n\n==KM Headbands==\nDesigned for comfort and style, the KM Headband line will have your forehead free of sweat and keep you looking cool on the field, even if you are getting shot down. \n\n==KM Buckles==\nKeep you mask in check with a stylish and indestructible buckle for the back of your head. \n\n==KM Spines==\nThe Dye Rotor Spine speed feed is a great investment and upgrade for your paintball loader. The Spine speed feed is very easy to install on your loader and is one of the most effective speed feeds on the market. The 8 long arms around the Rotor Spine speed feed are weighted in order to make it very easy for the weight of the paintballs to push down the paddles and enter the loader. The small flaps on the outside of the Dye Rotor Spine speed feed keep all of your paint securely in the loader. One of the most exciting features of the Rotor Spine speed feed is the LIFETIME WARRANTY! The Spine speed feed guaranteed to last backed by a Lifetime Warranty! \n\n==KM Straps==\nEasily the largest selection of Straps on the Strap market today. So strap on, and get ready to have that maks on your face for a while, because this thing isn't falling off. ", + "page_title" : "Buy KM Paintball Straps On Sale & Free Shipping", + "head_title" : "KM Paintball Straps | KM Straps | KM Spines" + }, + ".harnessesbags.paintball_gear_bags.defcon_tactical_gear" : {}, + ".casual_clothing.mens_clothing.wallets" : { + "meta_description" : "Mens Walets - Buy your Skate Wallets At Zephyr Sports for Less Today! We carry a complete line of Element Wallets at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Mens Walets On Sale & Free Shipping", + "head_title" : "Mens Walets | Skate Wallets | Element Wallets" + }, + ".apparel.shoes.es_shoes" : {}, + ".markerupgrades.feednecks" : {}, + ".casual_clothing.mens_clothing.tshirts.billabong_t_shirts" : { + "meta_keywords" : "Billabong T Shirts,Billabong shirts,free shipping,Billabong TShirt", + "meta_description" : "Billabong T Shirts - Zephyr carries a complete line of Billabong Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Billabong T Shirts at Zephyr", + "head_title" : "Billabong T Shirts | Billabong Shirts | Billabong TShirt" + }, + ".barrels.spyder" : { + "meta_keywords" : "spyder barrel,spyder paintball barrels,spyder threaded barrel", + "meta_description" : "Spyder Paintball Barrels - Zephyr Paintball carries the largest selection of Spyder Upgrade Barrels. Get the accuracy you need with a Spyder barrel.", + "page_title" : "Buy Spyder Paintball Barrels Online On Sale Now", + "head_title" : "Spyder Paintball Barrels | Spyder Barrel | Spyder Upgrade Barrels", + "prodlist1_header" : "Featured Spyder Paintball Barrels", + "description" : "Full line of Spyder paintball barrels by top paintball manufacturers! DYE, Proto, Invert, J&J Ceramics, Invert, Sly Equipment, and many more! Standard barrel lengths include: 12\", 14\", and 16\". Some Spyder barrels extend up to 21\" for improved accuracy and distance. \n\n\n\n\nThe most important part of any paintball barrel is the \"threading\" that physically screws into the paintball gun. If these threads do not match the threads of your marker, the barrel will be inoperable to your paintball gun. All of the barrels above have SPYDER threads, meaning that unless you have a Kingman Spyder Paintball gun, the Pirahna GTI or GTI+, or any other SPYDER threaded marker, these barrels will not work for your gun. \n\n\n\n\nSome Spyder Paintball barrels employ a 2-piece design. 2-piece paintball barrels require both; a Front barrel tip as well as a barrel back. Barrel backs contain the actual threads of the barrel so depending on your marker, it is important to select one with the same thread type. All barrel backs above are SPYDER threaded! As far as the front barrel tips are concerned... these screw right into the barrel back and with various lengths, the user is able to customize length, color, etc. 2-piece paintball barrels allow a little more variability with your overall set-up and also make maintaining your equipment rather easy. " + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_bpm_sunglasses" : { + "meta_description" : "Electric BPM Sunglasses - Zephyr Sports carries a complete line of Electric BPM Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric BPM Online Today.", + "page_title" : "Electric BPM Sunglasses On Sale Free Shipping", + "head_title" : "Electric BPM Sunglasses | Electric BPM Sun Glasses | Sunglasses Electric BPM" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_aloha_friday_sunglasses" : { + "meta_description" : "Maui Jim Aloha Friday Sunglasses - Zephyr Sports carries a complete line of Maui Jim Aloha Friday Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Aloha Friday Online Today.", + "page_title" : "Maui Jim Aloha Friday Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Aloha Friday Sunglasses | Maui Jim Aloha Friday Sun Glasses | Sunglasses Maui Jim Aloha Friday" + }, + ".airsoft.tactical_airsoft_gear.camoflouge_shirts.rothco_bdu_shirts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".loaders.hopper_accesories.dye_loader_accesories.dye_rotor_quick_feeds" : { + "meta_description" : "Dye Rotor Speed Feeds - Buy your Speed Feed Dye Rotor Online at Zephyr Paintball for Less today. Free Shipping on Rotor Quick Feeds Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Rotor Speed Feeds Online On Sale Now", + "head_title" : "Dye Rotor Speed Feeds | Speed Feed Dye Rotor | Rotor Quick Feeds", + "prodlist_custom" : "&SORTBY=NAME&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".casual_clothing.mens_clothing.accessories.cell_phone_cases" : { + "meta_description" : "Cell Phone Cases - Buy your Iphone Cases At Zephyr Sports for Less Today! We carry a complete line of Phone Cases at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Iphone & Cell Phone Cases on Sale", + "head_title" : "Cell Phone Cases | Iphone Cases | Phone Cases" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_tanks.crossfire_paintball_tanks" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_time_teller_p_watches" : { + "meta_keywords" : "nixon watches,nixon time teller,nixon time teller p,nixon time-teller p,nixon,nixon watch,mens watch,mens watches,nixon time-teller,nixon", + "meta_description" : "Nixon Watches - Brand New Nixon Time Teller P Watch @ Zephyr. Nixon Time-Teller P Watches keep life simple. Basic analog features! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Time Teller P Watch", + "head_title" : "Nixon Time Teller Watches | Nixon Time Teller Watch | Nixon Time Teller" + }, + ".markers.gog_paintball_guns.gog_envy_paintball_guns" : { + "meta_description" : "GOG Paintball Guns Envy - Buy your Gog Envy Paintball Markers Online at Zephyr Paintball for Less today. Free Shipping on Gog Envy Paintball Gun Trust Zephyr for all your Paintball Needs", + "top_description2" : "3 Words that come to mind when checking out the brand new GoG Envy Paintball Gun...\n \nReliable, Affordable, and Effective!\n\n\nDesigned for entry level and field rental players, the GoG Envy will hold up against some of the best guns in paintball! Straight out of the box, the GoG Envy shoots a solid 11 Balls Per Second and can easily be upgraded to shoot up to 25BPS with the addition of the blackheart board and a QEV. The stock board on the GOG envy paintball gun is fully capable of various firing modes including: semi auto, fully auto, 3 shot burst, PSP and BillBall! Easily maintain your gog g1 with its Bolt Out Back design allows for full gun cleaning (inside and out) in minutes rather than hours after a full day at the field. Guaranteed to perform with either C02 or HPA, the GoG Envy is also equipped with the Max-Flow R vertical regulator for consistent shooting all day!\nNot only consistent shooting, but also the GoG Envy comes with a 2 point adjustable trigger which gives the user the ability to adjust the length and feel of each trigger pull. Couple that with the option to use any Smart Parts threaded paintball barrel (Ion, Impulse, NXT Shocker) and you are set to dominate the competition on the field regardless of your playing level! Only $199.95!\n", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.gog_paintball_packages/?sortby=zoovy:prod_name", + "description" : "Zephyr carries a complete line of gog envy paintball guns. Perfect for entry entry level paintball player, the gog envy is upgradeable as your skills improve so you don't need to buy a complete new gun.\n\n==GoG Envy Paintball Gun Features:==\n\n* 11 bps (upgradable to 25+ with QEV and board )\n* Hammer free GoG Envy Electro-pneumatic Design\n* Modes Include semi auto, fully auto and 3 shot burst also PSP & BillyBall\n* Simple 9-Volt Operation\n* GoG Envy Mulit-Gas Operation\n* Light Microswitch Trigger\n* 2 Point Adjustable Trigger\n* Simple Maintenance with bolt out back design\n* Low Bolt Pressure Anti-Chop technology\n* GoG Envy paintball Gun is Field Legal\n* Seal Forward Technology\n* Max-Flo R Vertical Regulator\n* Vertical Feed Breech & Clamping Feedneck\n* GoG Envy Paintball Gun Uses Standard Smart Parts Ion/Impulse Barrel Thread ", + "page_title" : "Buy GOG Paintball Guns Envy Online On Sale Now", + "head_title" : "GOG Paintball Guns Envy | Gog Envy Paintball Markers | Gog Envy Paintball Gun" + }, + ".markers.extreme_rage_paintball_guns" : { + "banner01_link" : "/category/3packagespecials.extreme_rage_paintball_packages/", + "prodlist1_header" : "Extreme Rage Paintball Guns", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001" + }, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_kegger_sunglasses" : {}, + ".casual_clothing.z_shoes_and_footwear.511_tactical_footwear" : {}, + ".barrels.barrels_by_manufacturer.maddog_designz_paintball_barrels.bones_series_pro_2_piece_barrels" : {}, + ".skateboard_gear.skateboard_trucks" : { + "meta_keywords" : "Venture Skateboard Trucks,Destructo skateboard trucks,element skateboard trucks,grind king skateboard trucks,independent skateboard trucks,krux skateboard trucks,skateboarding trucks,skateboard trucks,skateboard truck,skate trucks,cheap skateboarding trucks,skateboard trucks and wheels,skateboarding accessories,skateboard equipment,", + "meta_description" : "Skateboard Trucks - Zephyr Sports now carries Skateboarding trucks by top skate companies; Venture Skateboard Trucks, Destructo Skateboard trucks, Element Skateboard trucks, Grind King Skateboard trucks, Independent Skateboard trucks, Krux Skateboard trucks, and more! For Cheap skateboarding trucks and other skateboard accessories choose Zephyr! Everything from Skateboard trucks and wheels to Skate tools and grip tape! Zephyr for all your Skateboard Equipment!", + "page_title" : "Buy Skateboard Trucks On Sale & Free Shipping", + "head_title" : "Skateboard Trucks | Skate Trucks | Skateboarding Trucks" + }, + ".apparel.knee___elbow_pads.proto_knee___elbow_pads" : { + "page_title" : "", + "head_title" : "Proto Elbow Pads | Proto Knee Pads | Proto Paintball Protection" + }, + ".goggles.save_phace_paintball_goggles.diss_series" : { + "meta_keywords" : "Save Phave Diss Series, Diss Series Paintball Goggles, camo paintball goggles, save face Dis", + "meta_description" : "Save Phace Diss Series Goggles. The Diss Series comes with a military grade anti fog and anti scratch single pane lens and graphics that are to kill for!!! This is the entry level Save Phace goggle system that is made affordable for all players. Diss Series goggles do not include a Save Phace stuff sack or an extra lense. Diss Series Designs - 20MDI, Intimidator, OSC Camo, and Phantom.", + "page_title" : "Buy Save Phave Diss Series Online On Sale Now", + "head_title" : "Save Phave Diss Series | Diss Series Paintball Goggles | Save Phave Dis" + }, + ".goggles.sly_profit_paintball_goggles.sly_annex_paintball_goggles" : { + "meta_keywords" : "sly annex paintball masks,sly annex,sly annex mi7,annex sly,sly annex paintball goggles,sly thermal,buy sly mask,sly annex mi-7", + "meta_description" : "Sly Annex paintball mask for Less at Zephyr Sports. Largest selection, Lowest Prices Guaranteed. Free Shipping on orders over $100. Paintball masks, safety glasses, everyone needs them to play- so why not get them here. We carry all the latest styles and accessories that you could ever need including Thermal Paintball Goggles.", + "top_description2" : "Sly Annex goggles provides a high quality, high-performance mask for entry players. Equipped with anti-fog, scratch resistant lenses so you'll be able to clearly see the field. This paintball mask incorporates many professional eye protection features at an affordable price. Choose from the popular MI-5 or MI-7 series models which come in a variety of colors!", + "zoovy:banner02" : "", + "description" : "Just released for 2012, the Sly Annex paintball goggle brings high end features without the high end price tag. The Sly Annex includes a thermal lens and dual foam padding to keep the mask comfortable. The Sly Annex has plenty of ventilation to keep you cool and fog free as well as angled slots to keep paint out of your mouth on those face shots. The Annex Strap has silicone strips to keep the mask secure on your head. A full 160 degree vertical and 260 degree horizontal view makes sure you can see every part of the game. The Sly annex has a quick change lens system similar to the sly profit allowing you to have multiple lenses to suite weather conditions with the ability to change in under a minute. The Sly annex comes in standard black as well as four different custom camo colors. Theses colors use an advanced hydrographic finish process that makes every mask unique and is resistant to paint etching and gouges.For a complete [[Sly Annex Review]:popup=http://blog.zephyrsports.com/new-sly-mi-7-annex-paintball-mask/] be sure to check out our blog.", + "htmlvids" : "", + "page_title" : "Buy Online Sly Annex Paintball Masks Now On Sale", + "head_title" : "Sly Annex Paintball Mask | Sly Annex Goggles | Sly Annex MI7" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs" : {}, + ".loaders.virtue_spire_paintball_loaders" : { + "meta_keywords" : "virtue spire,spire paintball loader,spire drive,virtue spire flex drive,paintball hopper,spire loader", + "meta_description" : "Virtue Spire Paintball Loader - Just released from Virtue. Get your Virtue Spire Loader from Zephyr First. The Spire Paintball hopper is a game changer for tournament paintball.", + "top_description" : "== Virtue Spire Paintball Loader ==\nVirtue just released the identity of the new Virtue Spire. Featuring the new Spire Drive. The Spire drive flex cone allows you to use the most brittle paint possible and has spring loaded arms to stop jams before they even happen. The Virtue Spire holds 200+ rounds and retails for $184.95. The Spire is available NOW in black and white. Buy yours first at Zephyr Paintball!\n12+ Spire color options available with either a black or white base. Limited edition team loaders include Edmonton Impact, Russian Legion and CP Raiders. Tactical Spires include Dark Earth and Olive Drab. Need to hold some more paint? Check out the new Virtue 260 Spire. All Virtue Spire Loaders ship free at Zephyr Paintball.", + "zoovy:banner01" : "", + "description" : "=Virtue Spire Features:=\n\n* Shot Activated G-Force Sensor Technology\n* Simple Two-Step, Tool-less Disassembly\n* Feeds Super Fragile Paint\n* Ultra Fast, Never Jams\n* True 200 Capacity\n* Lowest Profile in Paintball\n* Long Battery Life\n* Hassle Free Operation\n", + "top_html_focus" : "", + "htmlvids" : "", + "head_title" : "Virtue Spire Paintball Loader | Virtue Spire | Spire Paintball Hopper", + "page_title" : "Virtue Spire Paintball Loader - Buy it First" + }, + ".3packagespecials.us_army_paintball_packages.us_army_alpha_basic_paintball_gun_packages" : { + "meta_description" : "US Army Packages - Buy your US Army Package Online at Zephyr Paintball for Less today. Free Shipping on US Army Alpha Package Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy US Army Packages Online On Sale Now", + "head_title" : "US Army Packages | US Army Package | US Army Alpha Package" + }, + ".skateboard_gear.skateboard_accessories" : { + "meta_keywords" : "Skateboard Equipment,Skateboard Bushings,Skateboard Grip Tape,Skateboard Hardware,Skateboard Riser Pads,Skateboard Tools,Skateboard Curb Wax,Skateboard Bearings,Skateboard Decks,Skateboard stuff,custom complete skateboard", + "meta_description" : "Skateboarding Accessories - Skateboard Equipment - Zephyr Sports is your Skateboarding headquarters! Pick up some new Grip Tape or other Skateboard Stuff here at @ Zephyr! We have everything you need to custom build your own complete skateboard! We have various Skateboard bushings,Skateboard Hardware,Skateboard Riser Pads,Skateboard Tools,Skateboard Wax,Skateboard ABEC Bearings,Skateboard Decks,Skateboard Trucks, and More! ", + "page_title" : "Buy Skateboard Accessories On Sale & Free Shipping", + "head_title" : "Skateboard Accessories | Skateboard Equipment | Skateboard Tools" + }, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_fifth_ave_sunglasses" : { + "meta_description" : "Hoven Fifth Ave Sunglasses - Zephyr Sports carries a complete line of Hoven Fifth Ave Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Fifth Ave Online Today.", + "page_title" : "Hoven Fifth Ave Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Fifth Ave Sunglasses | Hoven Fifth Ave Sun Glasses | Sunglasses Hoven Fifth Ave" + }, + ".markerupgrades.matrix.matrix_body_kits" : {}, + ".skateboard_gear.skateboard_decks.flip_skateboard_decks" : { + "meta_keywords" : "Flip skateboards,Flip decks,Flip Skate decks,cheap skate decks,Flip skate boards,skateboarding equipment,skateboarding gear,Flip skateboard deck,Trucks,wheel,bearings", + "meta_description" : "Flip Skateboards - Zephyr Sports is your Flip Skateboard Headquarters! Flip skateboard Decks, Complete Flip Skateboards, and much More! Choose from a grip of Flip skate boards, Cheap Skate Decks, and others! Zephyr has all your Skateboarding equipment! Customize your Flip Skateboard with the latest trucks, wheels and bearings all @ Zephyr!", + "page_title" : "Flip Skateboard On Sale & Free Shipping", + "head_title" : "Flip Skateboard | Skateboard Equipment | Flip Decks" + }, + ".goggles.valken_paintball_goggles" : {}, + ".airsoft.shop_by_brand.zan_headgear" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".apparel.gloves.paintball_gloves_by_size.3.medium_paintball_gloves" : { + "page_title" : "", + "head_title" : "Medium Paintball Gloves | Medium Gloves for Paintball | Medium Paintballing Gloves" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_lodown_watches" : { + "meta_description" : "Nixon Lodown Watches - Buy your Nixon Lodown Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Lodown at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Lodown Watches", + "head_title" : "Nixon Lodown Watches | Nixon Lodown Watch | Nixon Lodown" + }, + ".paintball.player_apparel.paintball_jerseys" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_eliza_sunglasses" : { + "meta_keywords" : "Spy eliza sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Eliza Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy sunglass with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Eliza Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Eliza Sunglasses | Spy Optics Eliza Sunglasses | Eliza Spy Optics Sunglasses" + }, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_atlas_sunglasses" : {}, + ".1newitems.2008_products.2008_proto_paintball_gear" : {}, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_rail_accessories" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Rails | Rails Airsoft | Airsoft Scope Mounts" + }, + ".airsoft.slingshots.1slingshots.daisy_slingshots" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.pants_and_jeans.anti_hero_pants_and_jeans" : { + "meta_description" : "Anti Hero Pants - Buy your Anti Hero Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Anti Hero Pants & Jeans Ship Free", + "head_title" : "Anti Hero Pants | Anti Hero Jeans" + }, + ".3packagespecials.tippmann_packages.tippmann_a5_paintball_packages" : { + "meta_keywords" : "tippmann a5 a-5 a 5 packages,tippmann a5 starter kits,tippmann a-5 tactical package,sniper kit,flatline kit,tippmanna 5 kits", + "meta_description" : "Tippmann a5 packages - Tippmann a-5 starter kits for all levels. From entry level tippmann a 5 packages to Sniper packages, we have you covered for all things tipmann. Tippman", + "top_description" : "Tippmann A5 Packages from Zephyr Paintball are perfect for getting you in the game. The Tippmann A5 paintball gun is one of the most reliable guns on the market today. With the Cyclone feed that feeds 15+BPS with no batteries as well as future upgrades including the egrip, response trigger and flatline barrel, The Tippmann A5 is a great entry level gun that you can customize without breaking the bank. \nZephyr Paintball has a complete range of Tippmann A5 starter packages that include everything you need for your first day of play. Tank, mask, harness, squeegee, Remote coil, Tactical vest. Be sure to take a look at all of our options as each kit comes with different gear included. ", + "page_title" : "Buy Tippmanna 5 Kits Online Now", + "head_title" : "Tippmann A5 Packages | Tippmann A-5 Starter Kits | Tippmann A 5 Package", + "description" : "=Tippmann A5 Package Details=\n\n\nBronze Package - Our entry level Tippmann a-5 package includes a basic 20 oz tank to get you 1000+ shots per fill as well as an entry level paintball mask, rubber pull squeegee, gun oil and Zephyr Paintball american flag barrel cover (while supplies last)\n\n\nSilver and Titanium Packages - Our next level Tippmann a5 package includes a basic everything from our bronze package, but add in a harness and pods. Basically you get to choose between a 4+1 (silver) or 6+1 (titanium) harness with pods.\n\n\n1 Star HPA Package - This Tippmann A5 package is our entry level compressed air package. Xompressed air will give you a much more consistent shot during the game and is highly reccomended. Compressed air tanks are significantly higher than co2 tanks, but have come down significantly over the past few years. We include a high quality 48/3000 tank in this package. The brand will vary betweeen Zephyr, Empire / PMI, Ninja, and guerrilla air depending on availablity. The 1 Star Tippmann a5 kit also includes the Zephyr paintball flag barrel cover as well as a bottle of gun oil and a rubber jerk squeegee." + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_foley_sunglasses" : { + "meta_description" : "Smith Optics Foley Sunglasses - Zephyr Sports carries a complete line of Foley Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Foley Sun Glasses Online Today.", + "page_title" : "Smith Optics Foley Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Foley Sunglasses | Foley Smith Sunglasses Free Shipping | Buy Smith Foley Sun Glasses" + }, + ".markers.tippmann.tippmann_packages.tippmann_custom_98_packages" : { + "meta_keywords" : "Tippmann 98 packages, tippmann 98 custom packages, tippmann paintball kits, tippmann 98 custom packages, tippmann 98 kit, tippmann 98 platinum package, 98 platinum package", + "banner1" : "banners/98_packs_header", + "meta_description" : "Tippmann 98 Package - Buy your Tippmann 98 Custom Packages Online at Zephyr Paintball for Less today. Free Shipping on Tippmann 98 Paintball Kits Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann 98 Package Online On Sale Now", + "head_title" : "Tippmann 98 Package | Tippmann 98 Custom Packages | Tippmann 98 Paintball Kits" + }, + ".barrels.barrels_by_manufacturer.lapco_paintball_barrels" : { + "meta_keywords" : "lapco paintball barrels, apex barrel, apex paintball barrel, lapco big shot, lapco snapshot, lapco barrels, lapco apex ready, apex ready barrel, snapshot barrel kit", + "meta_description" : "Lapco Paintball Barrels - Buy your Lapco Apex Ready Barrel Online at Zephyr Paintball for Less today. Free Shipping on Lapco Tactical Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Lapco Paintball Barrels Online On Sale Now", + "head_title" : "Lapco Paintball Barrels | Lapco Apex Ready Barrel | Lapco Tactical Barrels", + "zoovy:banner01" : "banners/paintball/headers/2_lapco_barrels_header.jpg" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_high_life_4134_sunglasses" : { + "meta_description" : "Arnette High Ligh Sunglasses - Buy your Arnette 4134 High Life At Zephyr Sports for Less Today! We carry a complete line of Hiigh Life Arnette Sunglasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Arnette High Ligh Sunglasses On Sale & Free Shipping", + "head_title" : "Arnette High Ligh Sunglasses | Arnette 4134 High Life | Hiigh Life Arnette Sunglasses" + }, + ".barrels.barrels_by_manufacturer.lapco_paintball_barrels.lapco_snapshot_barrels" : {}, + ".shop_by_brand.arbor_longboards" : {}, + ".casual_clothing.mens_clothing.jackets.matix_jackets" : { + "meta_description" : "Matix Jackets - Buy your Matix Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Matix with Free Shipping", + "head_title" : "Matix Jackets | Matix Mens Jackets" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.quicksilver_pants_and_jeans" : { + "meta_description" : "Quicksilver Pants - Buy your Quicksilver Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Quicksilver Pants & Jeans Ship Free", + "head_title" : "Quicksilver Pants | Quicksilver Jeans" + }, + ".casual_clothing.womens_clothing.ladies_sandals.sanuk_sandals" : {}, + ".casual_clothing.mens_clothing.socks" : { + "meta_description" : "Mens Socks - Buy your Athletic Socks At Zephyr Sports for Less Today! We carry a complete line of Skate Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Mens Socks on Sale at Zephyr Sports", + "head_title" : "Mens Socks | Athletic Socks | Skate Socks" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_cloud_walker_hydration_packs" : {}, + ".1newitems.2008_products.2008_nxe_paintball_gear" : {}, + ".apparel.pants.protopants" : { + "meta_keywords" : "Proto Paintball Pants, Paintball Proto Pants, Paintball Pants Proto, Proto Paintball, Paintball Pants, Paintball Equipment, Paintball Accessories, Paintball Supplies, Paintball Gear", + "meta_description" : "Proto Paintball Pants - At ZephyrPaintball, you can get the lowest prices on paintball Proto pants and other equipment.", + "page_title" : "", + "head_title" : "Proto Paintball Pants | Paintball Proto Pants | Paintball Pants Proto", + "page_head" : "Proto Paintball Pants - Paintball Proto Pants - Paintball Pants Proto" + }, + ".markerupgrades.planet_eclipse_etha_upgrades.eclipse_etha_body_kits" : {}, + ".skateboard_gear.complete_skateboards.zoo_york_complete_skateboards" : { + "meta_description" : "Zoo York Skateboards - Buy your Zoo York Complet Skateboards Online At Zephyr Sports for Less Today! We carry a complete line of Complet Zoo York Skateboards at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Zoo York Skateboards Now! On Sale & Free Shipping", + "head_title" : "Zoo York Skateboards | Zoo York Complet Skateboards | Complet Zoo York Skateboards" + }, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_oxford_sunglasses" : {}, + ".markerupgrades.feednecks.ego_feednecks" : { + "meta_description" : "Ego Feed Necks - Buy your Feednecks for Ego Online at Zephyr Paintball for Less today. Free Shipping on Ego Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Ego Feed Necks Online On Sale Now", + "head_title" : "Ego Feed Necks | Feednecks for Ego | Ego Feed" + }, + ".airsoft.airsoft_safety.airsoft_goggles.asg_airsoft_goggles" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.aerial_7_headphones" : { + "meta_keywords" : "Aerial 7 Headphones,Aerial 7 Head Phones, aerial 7 Audio", + "meta_description" : "Aerial 7 Headphones - Zephyr stock a complete line of Aerial 7 Head Phones. For the ultimate Audio experience buy your Aerial 7 at Zephyr Today", + "page_title" : "Aerial 7 Headphones with Free Shipping at Zephyr", + "head_title" : "Aerial 7 Headphones | Aerial 7 Head Phones" + }, + ".apparel.jerseys.xsv_paintball_jerseys" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.utg_electric_airsoft_guns" : { + "meta_description" : "UTG Airsoft Guns - Buy your Airsoft UTG Online At Zephyr Sports for Less Today! We carry a complete line of Under The Gun Airsoft at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy UTG Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "UTG Airsoft Guns | Airsoft UTG | Under The Gun Airsoft" + }, + ".casual_clothing.mens_clothing.shirts.oakley_shirts" : { + "meta_description" : "Oakley Shirts - Buy your Oakley Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Oakley Flannel Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Shirts On Sale & Free Shipping", + "head_title" : "Oakley Shirts | Oakley Polo Shirts | Oakley Flannel Shirts" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_mccoy_sunglasses" : {}, + ".paintball.paintball_goggles.sly_profit_paintball_goggles.sly_annex_mi-7_paintball_goggles" : {}, + ".airsystems.nitrogentanks.gi_sportz_nitrogen_tanks" : { + "top_description" : "== G.I. Sportz Paintball Tanks ==\nG.I. Sportz makes superior quality nickel plated Compressed Air Tanks! G.I. Sportz has you covered across the board! Regulators are individually hand assembled and tested on state of the art machines for outstanding quality and assurance! Tanks are manufactured from high grade aluminum for increased strength and reduced weight. Various sizes and custom designs are available!\n", + "description" : "= Features: =\n* 2 Year Limited Warranty\n* Manufactured from high grade aluminum for increased strength and reduced weight\n* High quality finishing process\n* All testing and finishing are done in-house for superior quality control\n* Nickel plated and PVD coated parts for exceptional appearance and durability\n* Regulators are individually hand assembled and tested on state of the art machines for outstanding quality and assurance\n* Regulators are fully rebuildable and adjustable\n* 5 year Hydro Available in DOT / TC and PI certifications" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts.oakley_replacement_lenses.oakley_flak_jacket_replacement_lenses" : {}, + ".casual_clothing.z_shoes_and_footwear.dekline_mens_shoes" : {}, + ".airsoft.airsoft_guns.king_arms_airsoft_rifles" : { + "meta_description" : "King Arms Airsoft - Buy your King Arms Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of King Arms Airsoft Rifles at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy King Arms Airsoft On Sale & Free Shipping", + "head_title" : "King Arms Airsoft | King Arms Airsoft Guns | King Arms Airsoft Rifles" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_bathroom_sink_backpacks" : { + "meta_description" : "Oakley Bathroom Sink Backpacks - Buy your Bathroom Sink Oakley PacksAt Zephyr Sports for Less Today! We carry a complete line of Oakley Bathroom Sink Bags at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Oakley Bathroom Sink Backpacks Ship Free @ Zephyr Sports ", + "head_title" : "Oakley Bathroom Sink Backpacks | Bathroom Sink Oakley Packs| Oakley Bathroom Sink Bags" + }, + ".paintballs.diablo_paintballs" : { + "meta_description" : "Diablo Paintballs - Buy your Diablo Heat Online at Zephyr Paintball for Less today. Free Shipping on Diablo Heat Paintballs Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Diablo Paintballs Online On Sale Now", + "head_title" : "Diablo Paintballs | Diablo Heat | Diablo Heat Paintballs" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.bt_omega_paintball_guns" : {}, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.28" : {}, + ".airsoft.airsoft_guns.combat_zone_airsoft_guns" : { + "meta_description" : "Combat Zone Airsoft Guns - Buy your Combat Zone Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Combat Zone AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Combat Zone Airsoft Guns On Sale & Free Shipping", + "head_title" : "Combat Zone Airsoft Guns | Combat Zone Airsoft Rifles | Combat Zone AEG" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.1_search_by_size.5_x-large_ladies_tank_tops" : {}, + ".casual_clothing.mens_clothing.tank_tops.1-search_by_size" : {}, + ".casual_clothing.mens_clothing.belts.quicksilver_belts" : { + "meta_description" : "Quicksilver Belts - Buy your Quicksilver Mens BeltsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on QUICKSILVER BELTS @ Zephyr Sports", + "head_title" : "Quicksilver Belts | Quicksilver Mens Belts" + }, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels.freak_barrel_system.freak_jr_paintball_barrels" : {}, + ".markers.dangerous_power_paintball_guns.dangerous_power_g4_paintball_guns" : { + "meta_keywords" : "dangerous power g4, g4 paintball gun, paintball guns,dp g4 marker,dangerou power g4 paintball marker", + "meta_description" : "Dangerous Power G4 - Zephyr Paintball has your G4 Paintball Guns in stock and shipping today. At $299, you cannot beat the features of the DP G4. Buys yours online today with free Shipping at Zephyr Paintball", + "top_description2" : "The Dangerous Power G4 gives you the performance of $1000 gun for a lot less. Weighing in at 1.85 lbs with battery, the dangerous power g4 is insanely light. The G4 improved on the G3 with an O-ring less bolt, the o-rings are actually in the body of the marker, not the bolt. The G4 trigger has a 4 way adjustment so you always have the perfect trigger pull, no need to upgrade later. The dangerous power g4 comes standard with break beam anti chop eyes as well as an improved micro switch programmable circuit board, huge improvement over the g3. A 14\" Autococker threaded barrel and DM threaded Feedneck are standard on the Dangerous Power g4 paintball gun.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.dangerous_power_paintball_packages/?sortby=!zoovy:prod_name", + "description" : "=Dangerous Power G4 Paintball Gun Features:=\n\n*Dangerous Power G4 Light Weight - You will notice as soon as you pick up your Dangerous Power G4 that this baby is light. Weighing in at less than 2 pounds, the Dangerous Power G4 is one of the lightest paintball guns on the market. \n*Dangerous Power G4 O-ring Free Bolt - The bolt on the Dangerous Power G4 incorporates the O-ring-less bolt of the Spec R series guns. This translates to the same accuracy and efficiency as the Spec R series guns for $100 less.\n*Dangerous Power G4 Ramping Board - Adjusting modes on your paintball gun has never been easier than on the Dangerous Power G4. The DP G4 has a fully programmable micro-switch board that will suite the preferences of any paintball player.\n*Dangerous Power G4 Adjustable Trigger - Dangerous power listened to their customers and have added the Rev-I four way trigger adjustment which includes the breakaway magnet. The Dangerous Power G4 Paintball Gun trigger ranks up with the highest tournament level paintball guns on the market for about a third of the price\n\nThe dangerous power g4 is also highly upgrade-able. While the g4 is a great gun stock out of the box, it's nice to know we can tinker down the road. For increased efficiency and accuracy, check out the [[TechT L7 Bolt]:url=/product/TT-2040-DDP011]. The most common upgrades for the g4 are an autococker barrel, upgraded bolt, as well as a virtue board.\n", + "top_html_focus" : "", + "htmlvids" : "\t\t
                                                                          \n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
                                                                          \n\t", + "head_title" : "Dangerous Power G4 | G4 Paintball Gun | DP G4", + "page_title" : "Buy Dangerous Power G4 Online On Sale Now" + }, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.nc_star_tactical_holsters_and_slings" : { + "meta_description" : "NC Star Tactical Holsters - Buy your NC Star Slings At Zephyr Sports for Less Today! We carry a complete line of NC Star Holsters at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy NC Star Tactical Holsters On Sale & Free Shipping", + "head_title" : "NC Star Tactical Holsters | NC Star Slings | NC Star Holsters" + }, + ".casual_clothing.z-sunglasses.vestal_sunglasses" : { + "meta_keywords" : "Vestal Sunglasses,Vestal eyewear,Vestal,Vestal designer Glasses,Vestal polarized sunglasses,sunglasses,", + "meta_description" : "Vestal Eyewear - Zephyr Sports carries an array of Vestal Sunglass styles. Vestal is a leading designer of mens sunglasses. Polarized sunglasses are available! These designer sunglasses are showcased all over the world.", + "page_title" : "Vestal Sunglasses", + "head_title" : "Vestal | Vestal Sunglasses | Vestal Eyewear" + }, + ".casual_clothing.mens_clothing.tshirts.habitat_t_shirts" : { + "meta_keywords" : "Habitat T Shirts,Habitat shirts,free shipping,Habitat TShirt", + "meta_description" : "Habitat T Shirts - Zephyr carries a complete line of Habitat Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Habitat T Shirts at Zephyr", + "head_title" : "Habitat T Shirts | Habitat Shirts | Habitat Skate TShirt" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.36" : {}, + ".barrels.barrels_by_manufacturer.trinity_paintball_barrels" : {}, + ".casual_clothing.womens_clothing.ladies_sweatshirts.metal_mulisha_ladies_sweatshirts" : {}, + ".casual_clothing.mens_clothing.accessories.lanyards.dye_lanyards" : { + "meta_description" : "Dye Lanyards - Buy your Dye Paintball LanyardsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Dye Lanyards @ Zephyr Sports", + "head_title" : "Dye Lanyards | Dye Paintball Lanyards" + }, + ".testing_help_desk.testing_help_desk_answers" : { + "hd_answer_four" : "The best way to cancel your order or a particular item is to give us a call at 877-814-4297. We will be glad to help you out.", + "hd_question_three" : "I Never Received My Order?", + "hd_question_four" : "How Do I Cancel My Order/Item?", + "hd_question_eight" : "Can I Make Changes To My Order?", + "hd_answer_three" : "First, be sure you have logged in to your [[account]:url=https://ssl.zoovy.com/zephyrsports/login.cgis] and checked your order status. If your tracking information indicates that your order has been delivered, please check with everyone in your household and with any neighbors to ensure that they did not accept the package for you. Please also check all areas around your home to ensure that the package was not delivered to you and left in a hidden spot (on the back porch, in the garage, or behind a flower pot, for example). You should also check with your neighbors just in case they are holding on to it for you.\n\n\n\n\nIf we are not notified within 2 weeks of the ship date that you did not receive your package we will be unable to help you. There is only a certain amount of time that we have to deal with lost packages with the carrier and if we do not contact the carrier within that amount of time we will not be able to help you unfortunately.\n\n\n\n\nFedEx can be reached at (800)-GO-FEDEX and USPS can be reached at 1-800-ASK-USPS. You can also check the tracking page for the number to your local USPS location. If UPS or USPS was there and couldn't obtain an adult signature, they may have left a post-it note with re-delivery or pickup information. If you cannot track your order or find your order status via these methods, please call our customer service department at 877-814-4297.\n\n\n\n\nIf your order shipped via FedEx and is showing that it was delivered but you have not received your order, we will file a tracer on your behalf. FedEx will attempt to locate the package and deliver it. If they cannot locate and deliver the package, they will issue a refund for the items contained in the package. Tracers typically are completed within 5-8 business days, but can take up to 4 weeks.\n\n\n\n\nIf your order shipped via Economy (USPS), it can take up to 12 days, not including Sundays or Federal Holidays, to be delivered. If it has been over 12 shipping days and your package still has not arrived, please call us at 877-814-4297. We will initiate an investigation with our USPS representative who should be able to locate and deliver the package. If the package has not been located and delivered after 8 business days, we will reship your package via FedEx Home at no cost to you.\n\n\n\n\nWe will continue to track your original order and if it is delivered to you, we will issue a call tag and FedEx will pick up the second package from you and return it to us.", + "hd_answer_nine" : "At this time you can not combine two or more orders together. If you think that you have made two orders by mistake, please call us at 877-814-4297 and we will be glad to help you out.", + "hd_question_two" : "How Do I Track My Order?", + "hd_answer_two" : "As long as you entered a valid e-mail address during checkout, you will receive an e-mail with tracking information. Please be sure to check your spam filter as these e-mails tend to get caught in these filters. You can also login to your [[account]:url=https://ssl.zoovy.com/zephyrsports/login.cgis] to track your package. Your login is your e-mail address and a password that you received when you placed your order. If you have forgotten your password, you will be able to retrieve your password from this screen also.", + "hd_question_six" : "An Item Is Missing From My Shipment.", + "hd_question_seven" : "My Product is Missing Parts.", + "hd_question_five" : "What Is Your Out Of Stock Policy?", + "hd_topic_listing" : "» Has my order shipped?
                                                                          \n» How do I track my order?
                                                                          \n» I never received my order?
                                                                          \n» How do I cancel my order/item?
                                                                          \n» What is your out of stock policy?
                                                                          \n» An item is missing from my shipment.
                                                                          \n» My product is missing parts.
                                                                          \n» Can I make changes to my order?
                                                                          \n» Can I combine two orders?
                                                                          ", + "hd_topic" : "Order Status", + "hd_question_one" : "Has My Order Shipped?", + "hd_answer_five" : "Currently we do not have a \"Live Inventory\", but as soon as there is an item out of stock we will try our very hardest to take that item off of the site. There may be a case when an out of stock item slips by in the system in between when we are taking items off the site. For this we apologize. For most items that are out of stock we will be getting them back in. ", + "hd_btn" : "images/site_specific/backto_helpdesk", + "hd_answer_eight" : "Yes, the easiest way to make changes to your order is by calling our customer service at 877-814-4297. As long as your order has not be shipped yet, you may be able to make changes to your order.", + "hd_link" : "/category/testing_help_desk", + "hd_answer_one" : "Once you have placed your order and if you have given us a working email address, as soon as your package gets a shipping label, you will be automatically emailed with the tracking number.", + "hd_answer_six" : "If you are missing an item from your order, please call us immediately at 877-814-4297. We will initiate an internal investigation on your behalf. We will check the weight of a properly packed package against the weight of the package missing the item and compare the two to ensure that the package was missing when it left our warehouse. We will also check our inventory of the item to confirm that we do have an extra one that was not sent.\n\n\n\n\nIf the item was not shipped in your original package, we will ship a replacement immediately using the shipping method from the original order. We will gladly upgrade the shipping if you are willing to pay the difference between the original shipping and expedited shipping.\n\n\n\n\nIf we determine that the item was shipped and was lost in transit, we will file a FedEx or USPS claim on your behalf, depending upon the shipping method. Claims typically take 2-8 business days to complete, but can take up to 3-4 weeks in rare circumstances.", + "hd_question_nine" : "Can I Combine Two Orders?", + "hd_answer_seven" : "If your item is missing any parts that are listed on our website's description, the first step you should take is to contact the manufacturer. This is because many times they will change the features on an item when new ones are shipped before we have a chance to update the website. If this is not the case, the manufacturer can ship you any missing elements much faster than we can because we do not always stock the parts that make up some items. In most cases we will need you to send back the item for an exchange if it is missing something or defective." + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_barrels.dye_ultralite_barrels" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.empire_stinger_paintballs" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_shotglass_sunglasses" : { + "meta_description" : "Electric Shotglass Sunglasses - Zephyr Sports carries a complete line of Electric Shotglass Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Shotglass Online Today.", + "page_title" : "Electric Shotglass Sunglasses On Sale Free Shipping", + "head_title" : "Electric Shotglass Sunglasses | Electric Shotglass Sun Glasses | Sunglasses Electric Shotglass" + }, + ".markers.kingmanspyder.spyder_pilot_paintball_guns" : {}, + ".casual_clothing.mens_clothing.sweatshirts.dc_sweatshirts" : { + "meta_description" : "DC Sweatshirts - Buy your DC Hoodies At Zephyr Sports for Less Today! We carry a complete line of DC Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DC Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "DC Sweatshirts | DC Hoodies | DC Hoody" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.1_search_by_size.3_large" : {}, + ".harnessesbags.backpacks.circa_backpacks" : {}, + ".zephyr_paintball_coupons_and_discounts" : { + "meta_keywords" : "zephyr paintball discounts, zephyr paintball coupons, zephyr coupon codes", + "meta_description" : "Zephyr Paintball Coupon Codes - Get you Zephyr Paintball Discounts. Free shipping % Discounts and our current promos now available directly from Zephyr Paintball", + "top_description2" : "", + "top_description" : "We Know everyone is looking to save a few bucks when they shop online. We're here to help. This page will have our current promotions and discounts that will apply on top of our Free Shipping.\n", + "ad1" : "", + "zoovy:banner01" : "", + "banner01_link" : "http://www.zephyrpaintball.com/results.cgis?catalog=MFG&wrapper=~zephyrsports_zephyrsportscom_20100727&root=.&keywords=c11promo&x=16&y=3", + "description" : "=Coupons can not be combined with any other coupon or discount besides free shipping. I.e. you cannot get a free headband and use a discount coupon=\n\n\n\n==Please note that many companies will not allow us to provide any kind of discount or coupon on there products and no coupons or discounts will be able to be applied to your order. These companies may include Dye, Tippmann, Proto, Empire (Including Empire BT, Empire Invert) Note this list is not all inclusive and additional manufacturer exclusions may apply. Sorry, we would allow you to use this companies if we could==", + "ad1_link" : "/category/001a_zephyr_paintball_sports_promotions_deals_sales.free_headband_with_order/", + "head_title" : "Zephyr Paintball Coupons, Coupon Codes and Discounts", + "page_title" : "Zephyr Paintball Coupons and Discounts" + }, + ".shop_by_brand.toy_machine" : {}, + ".giftcertificates" : {}, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_calaca_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon calaca sunglasses", + "meta_description" : "Dragon Calaca Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Calaca Sunglasses" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_barrels.techt_ifit_paintball_barrels" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_shorts" : {}, + ".1newitems.2008_products.2008_eclipse_paintball_gear" : { + "prodlist_custom" : "&SORTBY=NAME&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".paintball.player_apparel" : {}, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Upgrade | Airsoft Parts | Airsoft Springs" + }, + ".casual_clothing.mens_clothing.jackets.neff_jackets" : { + "meta_description" : "Neff Jackets - Buy your Neff Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Neff Jackets with Free Shipping", + "head_title" : "Neff Jackets | Neff Mens Jackets" + }, + ".casual_clothing.mens_clothing.shirts.eclipse_shirts" : { + "meta_description" : "Eclipse Flannel Shirts - Buy your Eclipse Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Eclipse Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Eclipse Shirts & Flannels Ship Free", + "head_title" : "Eclipse Flannel Shirts | Eclipse Polo Shirts | Eclipse Shirts" + }, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_ego_paintball_guns" : { + "meta_keywords" : "Eclipse Ego Paintball Guns, Planet Eclipse Ego, Ego Paintball Guns, Ego Paintball, Ego SL8r, Origin Ego, 08 Ego, SL Ego gun, UK flage Ego, US Flag ego 08, 08 confederate ego paintball gun", + "meta_description" : "Planet Eclipse Ego Paintball Guns - The ultimate tournament Eclipse Ego Paintball Gun. Ultra fast, lightweight and efficient. What else could you want. Get your Eclipse Ego Marker at Zephyr today", + "description2" : "\n\n\n\n\n ", + "description" : "The Planet Eclipse Ego 08 paintball gun is the lightest and most widely used tournament paintball gun available today. Directly out of the box, the eclipse ego 08 will compete on any tournament circuit from your local field to the PSP.\nFire-power, accuracy and lightening-fast speed is what you come to expect from a Planet Eclipse Gun. Eclipse practically invented paintball upgrades – now they’ve put all that attitude into their own line of hyper-light, paintball markers. \n\n\nWant to light up all your friends next weekend with your 08 Ego. Zephyr has the largest selection of egos on the west coast.\n\n\n", + "banner1" : "", + "page_title" : "Buy Eclipse Ego Paintball Guns Online On Sale Now", + "head_title" : "Eclipse Ego Paintball Guns | Planet Eclipse Ego | Ego Paintball Gun", + "prodlist_custom" : "&SORTBY=PRICE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".casual_clothing.mens_clothing.shirts.krooked_shirts_and_flannels" : { + "meta_description" : "Krooked Flannel Shirts - Buy your Krooked Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Krooked Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Krooked Shirts & Flannels Ship Free", + "head_title" : "Krooked Flannel Shirts | Krooked Polo Shirts | Krooked Shirts" + }, + ".barrels.tippmanna5.16__tippmann_a_5_barrels" : { + "meta_description" : "16 inch Tippmann A5 Paintball Barrels - Buy your 16\" Tippmann A-5 Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Tippmann A5 Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 16 inch Tippmann A5 Paintball Barrels Online On Sale Now", + "head_title" : "16 inch Tippmann A5 Paintball Barrels | 16\" Tippmann A-5 Threaded Upgrade | Tippmann A5 Paintballs Barrels" + }, + ".casual_clothing.mens_clothing.tank_tops.matix_tank_tops" : { + "meta_description" : "Matix Tank Tops - Buy your Matix Jersey Tank Tops At Zephyr Sports for Less Today! We carry a complete line of Matix Mens Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Matix Mens Jersey Tank Tops at Zephyr Sports", + "head_title" : "Matix Tank Tops | Matix Jersey Tank Tops | Matix Mens Tank Tops" + }, + ".markerupgrades.invert_upgrades.empire_mini_factory_parts" : {}, + ".shop_by_brand.intellect_airsoft_batteries" : {}, + ".markerupgrades.tippmann.a5.scenarioupgrades.a_5_stocks" : {}, + ".1newitems.2009_exalt_gear" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_rotolog_watches" : { + "meta_keywords" : "Nixon watches,nixon Rotologr watch,nixon watch,nixon Rotologr chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Rotologr Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Rotologr Chrono Watches", + "head_title" : "Nixon Rotologr Watches | Nixon Rotologr Chrono Watch | Nixon 5130" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_telly_sunglasses" : { + "meta_description" : "Von Zipper Telly Sunglasses - Zephyr Sports carries a complete line of Buy Telly Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Telly Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Telly Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Telly Sunglasses | Buy Telly Von Zipper Sunglasses | Von Zipper Telly Sunglasses Free Shipping" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.e90_aeg_airsoft_magazines" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_fixed_power_scopes.barska_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".harnessesbags.packs___harnesses.redz_pod_packs" : {}, + ".paintballs.jt_paintballs" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_arsenal_backpacks" : {}, + ".barrels.barrels_by_manufacturer.stiffi_paintball_barrels.stiffi_spyder_threaded_barrels" : {}, + ".casual_clothing.mens_clothing.sweatshirts.anti_hero_sweatshirts" : { + "meta_description" : "Anti Hero Sweatshirts - Buy your Anti Hero Hoodies At Zephyr Sports for Less Today! We carry a complete line of Anti Hero Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Anti Hero Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Anti Hero Sweatshirts | Anti Hero Hoodies | Anti Hero Hoody" + }, + ".casual_clothing.mens_clothing.wallets.electric_wallets" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_crankcase_sunglasses" : {}, + ".barrels.smartparts.16__impulse___ion_paintball_barrels" : { + "meta_description" : "16 inch Impulse Paintball Barrels - Buy your 16\" Impulse Threaded Barrels Online at Zephyr Paintball for Less today. Free Shipping on Ion Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 16 inch Impulse Paintball Barrels Online On Sale Now", + "head_title" : "16 inch Impulse Paintball Barrels | 16\" Impulse Threaded Barrels | Ion Paintballs Barrels" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.29" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_golf_bags" : {}, + ".airsoft.2clearance" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_drydock_sunglasses" : { + "meta_description" : "Von Zipper Drydock Sunglasses - Zephyr Sports carries a complete line of Buy Drydock Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Drydock Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Drydock Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Drydock Sunglasses | Buy Drydock Von Zipper Sunglasses | Von Zipper Drydock Sunglasses Free Shipping" + }, + ".shop_by_brand.blackstar_paintball" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_chainlink_sunglasses" : {}, + ".loaders.pinokio_paintball_loaders" : { + "meta_keywords" : "pinokio hoppers, pinokio loaders, pinokio paintball hoppers, pinokio paintball loaders, pinokio loader", + "meta_description" : "Pinokio Hoppers - Pinokio Loaders are the hot new loader for scenario and tournament play. Pinokio Paintball hoppers have the detachable nose cone to increase the number of balls you can carry. Perfect for those long scenario games", + "page_title" : "Buy Pinokio Hoppers Online On Sale Now", + "head_title" : "Pinokio Hoppers | Pinokio Loaders | Pinokio Paintball Hoppers", + "description" : "Don't let the big nose scare you away. This hopper is great for players who want to kick back and let go 400 rounds in one full hopper. What's great about this hopper is that it gives you options. If one day you feel like jumping around with as little weight as possible the standard 140 round shell is all for you, but what's great about Paintball you never know what field opportunity comes at you. So why not have an easy interchangeable nose to allow those options. Ok, so we know it can hold plenty of paint for our experience. How about speed? Well, with a 30+ ball per second rate of fire your speed is well covered. With all this speed how often am I going to change batteries? No need to worry. The Pinokio has the ability to go through 37+ cases of paint on just 2 nine volt batteries! Lets be honest, only 2 nine volt batteries for that much paint - definitely economy-friendly. On another note - Mike Paxson, a true professional on the field, plays with the Pinokio Hopper. If a Dye Ironman player like Mike has no problems using it then surely it can be trusted. \n\n\n\nOverall the Pinokio hopper is light, fast, durable and used by many. If you are looking for a reliable hopper for speedball or scenario/woodsball the Pinokio is your nose" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.classic_army_airsoft_guns.classic_army_sportline_aeg_airsoft_guns" : { + "meta_description" : "Classic Army Airsoft Guns - Buy your Classic Army M15A4 Airsoft At Zephyr Sports for Less Today! We carry a complete line of Classic Army Sportline at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Classic Army Airsoft Guns On Sale & Free Shipping", + "head_title" : "Classic Army Airsoft Guns | Classic Army M15A4 Airsoft | Classic Army Sportline" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.zoo_york_pants_and_jeans" : { + "meta_description" : "Zoo York Pants - Buy your Zoo York JeansOnline At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Zoo York Pants & Jeans Ship Free", + "head_title" : "Zoo York Pants | Zoo York Jeans" + }, + ".safetygear.empire" : {}, + ".casual_clothing.mens_clothing.hats.billabong_hats" : { + "meta_description" : "Billabong Hats - Buy your Billabong Baseball Hats At Zephyr Sports for Less Today! We carry a complete line of Billabong Caps at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on BILLABONG HATS @ Zephyr Sports", + "head_title" : "Billabong Hats | Billabong Baseball Hats | Billabong Caps" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.m249_saw_airsoft_gun_magazines" : {}, + ".apparel.jerseys.smart_parts_paintball_jerseys" : {}, + ".airsoft.airsoft_apparel.tactical_gloves" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray-ban_rb4151_sunglasses" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_comsat_sunglasses" : { + "meta_description" : "Von Zipper Comsat Sunglasses - Zephyr Sports carries a complete line of Buy Comsat Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Comsat Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Comsat Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Comsat Sunglasses | Buy Comsat Von Zipper Sunglasses | Von Zipper Comsat Sunglasses Free Shipping" + }, + ".2clearance.clearance_upgrades.upgrade_boards" : { + "head_title" : "Sale Paintball Upgrade Boards | Clearance Paintball Upgrade Boards | Paintball Upgrade Boards Sale" + }, + ".barrels.smartparts.12__impulse___ion_paintball_barrels" : { + "meta_description" : "12 inch Impulse Paintball Barrels - Buy your 12\" Impulse Threaded Barrels Online at Zephyr Paintball for Less today. Free Shipping on Ion Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 12 inch Impulse Paintball Barrels Online On Sale Now", + "head_title" : "12 inch Impulse Paintball Barrels | 12\" Impulse Threaded Barrels | Ion Paintballs Barrels" + }, + ".paintball.player_apparel.paintball_jerseys.planet_eclipse_paintball_jerseys" : {}, + ".casual_clothing.youth_clothing.youth_socks" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_infamous_sunglasses" : { + "meta_keywords" : "Arnette Sunglasses, arnette polarized, arnette sunglass, Arnette Eyewear, Arnette Lens", + "meta_description" : "Arnette Infamous Sunglasses - Arnette Lens, Polarized Sunglasses are the way to go! Whether it be fame or infamy, the Infamous Arnette Sunglasses will have you struttin your stuff whereever you go! ", + "head_title" : "Arnette Infamous Sunglasses | Arnette 4076 Infamous Sunglasses | Arnette Infamous" + }, + ".harnessesbags.paintball_gear_bags" : { + "subcat1_header" : "", + "meta_keywords" : "Paintball Gear Bag, Paintball Bag, Paintball Equipment Bag, Paintball Gear, Gear Bag, Paintball Equipment, Paintball Supplies, Paintball Accessories, Paint Ball Supplies", + "meta_description" : "Paintball Gear Bag - Shop for paintball equipment bags and accessories online at ZephyrPaintball.com.", + "prodlist2_title" : "Featured Paintball Gear Bags", + "prodlist1_header" : "", + "description" : "Zephyr carries multiple options when it comes to equipment bags. Gun cases, backpacks and large gear bags. Pretty much anything to make sure your equipment is well taken care of. When traveling with paintball equipment it's important to have enough compartments for your gun and all its accessories. Luckily manufacturers such as Dye, Empire, Eclipse, NXE have created the ultimate gear bags for all your toys :-). Weather it's a small backpack for your gun and a few other items or a large gear bag for all your paintball equipment and clothing. Paintball backpacks are built well enough to carry your gun, hopper, tank, barrels and more. The Dye Backpacker has multiple compartments for tools and small accessories that you definitely do not want to lose on the field. Maybe you need to carry your equipment to get to a nice paintball spot. Well the Backpacker has you covered with padded shoulder straps for comfort and new back padding. This is one example of the many backpacks that are available. Now, the big boys such as Eclipse and Dye large gear bags have two main compartments that are big enough to cram in all your gear with multiple smaller pouches for all your accessories. Guns, tanks, hoppers, clothes - doesn’t matter it will all fit. It doesn’t stop there. Wheel it around! Pull out that handle for easy traveling. Now these bags are great but you might be looking for something in the middle. Not to small not to large.", + "page_title" : "Buy Paintball Gear Bag Online On Sale Now", + "head_title" : "Paintball Gear Bag | Paintball Bag | Paintball Equipment Bag", + "page_head" : "" + }, + ".goggles.save_phace_paintball_goggles.tagged_series" : { + "meta_description" : "Tagged Series Save Phace Goggles. Tagged Series are custom airbrushed individually, meaning each mask is uniquely hand painted. That’s right, we said it! We have had a small number of Masks airbrushed by our A+ artist and are offering these at a reduced cost to you. This Series comes with our patent pending R.W.I foam, military grade anti fog and anti scratch Clear Lens and includes a stuff sack.", + "page_title" : "Buy Save Phace Tagged Series Masks Online On Sale Now", + "head_title" : "Save Phace Tagged Series Masks | Tagged Series Paintball Goggles | Save Face Hand Painted Tagged Series" + }, + ".airsoft.airsoft_guns.ics_airsoft_guns" : { + "meta_description" : "ICS Airsoft Rifles - Buy your ICS MP5 At Zephyr Sports for Less Today! We carry a complete line of ICS MP5A4 at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy ICS Airsoft Rifles On Sale & Free Shipping", + "head_title" : "ICS Airsoft Rifles | ICS MP5 | ICS MP5A4", + "description" : "" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_boardwalk_sunglasses" : { + "meta_description" : "Smith Optics Boardwalk Sunglasses - Zephyr Sports carries a complete line of Boardwalk Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Boardwalk Sun Glasses Online Today.", + "page_title" : "Smith Optics Boardwalk Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Boardwalk Sunglasses | Boardwalk Smith Sunglasses Free Shipping | Buy Smith Boardwalk Sun Glasses" + }, + ".casual_clothing.mens_clothing.tshirts.zoo_york_t-shirts" : { + "meta_keywords" : "Zoo York T Shirts,Zoo York shirts,free shipping,Zoo York TShirt", + "meta_description" : "Zoo York T Shirts - Zephyr carries a complete line of Zoo York Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Zoo York T Shirts at Zephyr", + "head_title" : "Zoo York T Shirts | Zoo York Shirts | Zoo York TShirt" + }, + ".markerupgrades.grips_and_grip_panels.planet_eclipse_paintball_grips" : {}, + ".scenarioupgrades.tactical_scarves" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.50_oz_mountain_bike_hydration_packs" : {}, + ".markerupgrades.smartparts.ion.triggers.maddog_designz_ion_triggers" : {}, + ".casual_clothing.mens_clothing.accessories.lanyards" : {}, + ".casual_clothing.mens_clothing.belts.globe_belts" : { + "meta_description" : "Globe Belts - Buy your Globe Mens BeltsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Globe BELTS @ Zephyr Sports", + "head_title" : "Globe Belts | Globe Mens Belts | Mens Belt Globe" + }, + ".markerupgrades.planet_eclipse_ego_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.ego7_8_geo_grip_panel/", + "buttonname_01" : "", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "", + "add2_link" : "/category/markerupgrades.feednecks.ego_feednecks/", + "buttonname_02" : "", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.autococker/" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_compulsive_squared_sunglasses" : {}, + ".markerupgrades.us_army_upgrades.bolts_and_internal_upgrades" : {}, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.bushnell_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".1weekly_specials" : { + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "top_description" : "", + "head_title" : "Weekly Paintball Specials | Paintball Sale Gear", + "zoovy:banner01" : "", + "description" : "" + }, + ".airsystems.nitrogentanks.valken_nitrogen_tanks" : { + "meta_description" : "Valken paintball tanks feature time tested crossfire bottles and regulators with a little Valken style. Valken compressed air tanks hold 4500Psi and are the hottest new HPA bottles on the market. Buy yours at Zephyr today and get the best price and free shipping.", + "top_description" : "==Custom Designed Valken Carbon Fiber Paintball Tanks==\n\nSupe your current paintball marker set up with one of Valken's brand new custom designed carbon fiber paintball tanks! Really nice collab here with Valken Paintball and Crossfire Paintball Compressed Air Tanks! These are some of the lightest carbon fiber Crossfire Tanks/Regs on the market with bitchin' custom designed graphics!", + "page_title" : "Valken Paintball Tanks Ship Free at Zephyr", + "head_title" : "Valken Paintball Tanks | Valken Compressed Air Tanks | HPA Bottle", + "description" : "=Features:=\n* Crossfire Bottle/Reg w/ Custom Valken Designs\n* Reliable\n* Carbon Fiber Tank\n* Mini gauge\n* Flats on both regulator body and bonet for easy non-damaging service and hydro\n* Two sets of screws for added safety and security\n* Dual burst discs\n* Overall length of 10.2 inches\n* Weighs 2lbs 5.6oz" + }, + ".sponsorship.sponsorship_headquarters" : {}, + ".casual_clothing.z_shoes_and_footwear.world_industries_shoes" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.vestal_watches" : { + "meta_keywords" : "Vestal,Vestal Watches,Vestal Apparel,vestal watch,mens watches,watches for men,", + "meta_description" : "Vestal Watches - Zephyr Sports carries an array of watches for men. Vestal is a leading designer of mens watches showcased all over the world. Whether its style, or class, Vestal is the watch to wear. ", + "page_title" : "Vestal Watches", + "head_title" : "Vestal | Vestal Watches | Mens Watches" + }, + ".apparel.shoes.1search_by_size.h_men_s_size_9_shoes" : {}, + ".airsystems.expansion_chambers" : { + "meta_description" : "Expansion Chamber - Buy your Tippmann 98 Expansion Chamber Online at Zephyr Paintball for Less today. Free Shipping on Tippmann A5 Expansion Chamber Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Expansion Chamber Online On Sale Now", + "head_title" : "Expansion Chamber | Tippmann 98 Expansion Chamber | Tippmann A5 Expansion Chamber" + }, + ".airsoft.tactical_airsoft_gear.camoflouge_shirts.511_tactical_bdu_shirts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_winter_hydration_packs.women_s_camelbak_scorpion_hydration_packs" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_gibson_sunglasses_" : { + "meta_description" : "Smith Optics Gibson Sunglasses - Zephyr Sports carries a complete line of Gibson Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Gibson Sun Glasses Online Today.", + "page_title" : "Smith Optics Gibson Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Gibson Sunglasses | Gibson Smith Sunglasses Free Shipping | Buy Smith Gibson Sun Glasses" + }, + ".markerupgrades.matrix.matrix_feed_necks" : {}, + ".airsoft.airsoft_guns.refurbished_airsoft_guns" : { + "meta_description" : "Refurbished Airsoft Guns - Buy your Refurbished Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Refurbished AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Refurbished Airsoft Guns On Sale & Free Shipping", + "head_title" : "Refurbished Airsoft Guns | Refurbished Airsoft Rifles | Refurbished AEG" + }, + ".markers.btdesignspaintballguns.bt_combat_erc_paintball_guns" : { + "meta_keywords" : "bt combat erc paintball gun,bt combat marker,bt combat paintball gun,bt combat paintball,bt combat,bt erc\r ", + "meta_description" : "BT Combat ERC Paintball Guns - The Fully Upgraded Version of the BT4 Combat has arrived. Free Fast Shipping from Zephyr Paintball Today.", + "top_description" : "What happens when you take the standard BT-4 Combat and load it full of technology, you get the BT4 ERC paintball gun. The BT-4 ERC comes standard with both the BT Electronic Grip Frame and BT Rip-Clip, allowing you to experience the fastest possible rate-of-fire. The Rip-Clip force-feed loader system utilizes HALO technology, including the built-in Rip Drive, to throw a wall of paint towards the enemy. The Apex barrel system allows you to customize your shot trajectory to hit hidden opponents. Does a tree or bunker stand between you and a kill? Dial up the Apex to curve your shot right on target. The BT 4 ERC offers technology on the battlefield that few markers can match. If you have a need for speed and precision, this is the marker that delivers. ", + "page_title" : "Buy BT Combat ERC Paintball Guns Online On Sale Now", + "head_title" : "BT Combat ERC Paintball Guns | Combat ERC Paintball Markers", + "description" : "\n=Features:=\n\n* Slide-Away feedport for easy cleaning and maintenance.\n* Lightweight, balanced construction\n* Impact-resistant, backed-on coating\n* Works with CO2 or compressed air\n* BT Electronic Grip Frame\n* Custom two-finger trigger\n* Semi-auto\n* 2 ramp modes\n* 2 full-auto modes\n* Powered BT Rip-Clip\n* Sound activated\n* Force-feed\n* Holds over 200 paintballs\n" + }, + ".skateboard_gear.complete_skateboards.1_complete_skateboards_by_size_.775__complete_skateboards" : {}, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels.freak_barrel_system.freak_barrel_fronts" : { + "page_title" : "", + "head_title" : "Freak Barrel Tips | Freak Paintball Barrel Fronts | Freak Barrel Kits" + }, + ".markerupgrades.matrix.matrix_internals" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses" : { + "meta_keywords" : "electric sunglasses,sunglasses electric,electric eyewear,electric glasses,electric polarized sunglasses,electric ecdc sunglasses,electric ec dc sunglasses,electric mens sunglasses,electric bsg sunglasses,electric sunglass", + "meta_description" : "Electric Sunglasses - Free shipping on Sunglasses Electric. Get your Electric Eyewear from Zephyr today.", + "page_title" : "Electric Sunglasses with Free Shipping", + "head_title" : "Electric Sunglasses | Sunglasses Electric | Electric Eyewear" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.nc_star_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews" : { + "htmlvids" : "" + }, + ".skateboard_gear.skateboard_wheels.bones_skateboard_wheels" : { + "meta_description" : "Bones Wheels - Zephyr Sports carries a complete line of Bones Skate Wheels At the lowest prices on the web with free shipping and easy returns. Buy your Bones Wheels Skateboard Wheels Online Today.", + "page_title" : "Bones Wheels On Sale Free Shipping", + "head_title" : "Bones Wheels | Bones Skate Wheels | Bones Wheels Skateboard Wheels" + }, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels.freak_barrel_system.freak_inserts" : { + "page_title" : "", + "head_title" : "Freak barrel Insert | Freak Inserts | Freak Barrel System" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.tiberius_arms_first_strike_rounds" : {}, + ".skateboard_gear.complete_skateboards.darkstar_complete_skateboards" : { + "meta_description" : "Darkstar Complete Skateboards - Buy your Darkstar Skateboards At Zephyr Sports for Less Today! We carry a complete line of Dark Star Skateboards at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Darkstar Complete Skateboards On Sale & Free Shipping", + "head_title" : "Darkstar Complete Skateboards | Darkstar Skateboards | Dark Star Skateboards" + }, + ".barrels.tippmann98.12__tippmann_98_barrels" : { + "meta_description" : "12 inch Tippmann 98 Paintball Barrels - Buy your 12\" Custom 98 Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Tippmann 98 Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 12 inch Tippmann 98 Paintball Barrels Online On Sale Now", + "head_title" : "12 inch Tippmann 98 Paintball Barrels | 12\" Custom 98 Threaded Upgrade | Tippmann 98 Paintballs Barrels" + }, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings." : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_conduct_sunglasses" : { + "meta_keywords" : "Oakley Conduct Sunglasses,Conduct oakley sunglasses,oakley Conduct, Conduct polarized sunglasses", + "meta_description" : "Oakley Conduct Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Conduct and Polarized Oakley Conduct Sunglasses on Sale! ", + "page_title" : "Oakley Conduct Sunglasses with Free Shipping", + "head_title" : "Oakley Conduct Sunglasses | Conduct Oakley Sunglassses" + }, + ".markers.pump_paintball_guns" : { + "meta_keywords" : "pump paintball gun,paintball pump gun,cci phantom,azodin chaos pump", + "top_html" : "", + "meta_description" : "Pump Paintball guns. Get back to the roots of Paintball with a paintball pump gun. ", + "top_description" : "=Legends are never forgotten, Classics never Die..!=\n\n\n\n\nPump Paintball has seen a resurgence that is here to stay! Whether you are a veteran returning to your roots, or just a rookie looking to get in, Pump Paintball is a the whole new game within itself! Pump Paintball is all about the challenge! Limited firepower ensures that in order to be successful, you have got to make your shots count! In short, One-Pump-One-Paintball... It's not about the ol' accuracy by volume tactic anymore! Earn the respect you deserve by playing pump!\n\n\n\n\n==Perks of Pump Paintball...==\n\n\n\n\n* Chance to Prove Yourself\n* Changes the Game\n* Improves Overall PB Skill\n* Saves $$ on Paint", + "banner02_link" : "/category/markerupgrades.pump_gun_upgrades/", + "prodlist1_header" : "Pump Paintball Guns", + "zoovy:banner02" : "banners/paintball/headers/pumpgunacc_header001.jpg", + "description" : "==CCI Phantom Pump==\nThe Phantom is a .68 caliber, pump action CO2 powered gun designed to fire paintballs at 200 to 300 fps as accurately as possible to mark the aiming point with the splat of a paintball. \nThe Phantom cocks and loads a paintball when the pump is pulled fully back and returned to its full forward position. Squeezing the trigger releases the hammer striking the power tube allowing a blast of CO2 to fire a paintball. The design of the trigger firing mechanism allows a rapid fire capability. With constant pull on the trigger, the gun fires with each pump action. \n\n\n\n\n==Tippmann SL-68 II==\nRedesigned and improved, making it a perfect addition to your pump arsenal. Aside from all of the standard features of a Tippmann gun (solid cast aluminum, non corrosive internals, metal trigger etc.), the SL-68II is equiped with a redesigned feedneck that fits most standard hoppers as well as a redesigned ergonomic grip for comfort and control. \n\n\n\n\n==Azodin Kaos Pump==\nBrings all the innovations from the AZODIN team to the pump market. Built on the KAOS chassis, the KP provides closed-bolt performance in an entry-level package. The optimized valve and main springs of the KP give you the efficiency you need when you are out at the field. The pump action is smooth out of the box so you don't have to worry about breaking in the pump action.\n\n\n\n\n==Azodin KP+ Electronic Pump==\nUtilizing the \"ZEN\" circuit board, KP+ is not only capable of a Standard Pump Mode but also hosts Auto Trigger and a new Enhanced Trigger Mode. Now with the Zen board, it only needs seconds to change the mode setting instead of switching the whole grip frame just to play the auto trigger pump style. \nThe new \"TRIAD Ball Retention System\" minimizes roll-out, the Low Pressure Inline Regulator gives the KP+ 300 PSI working pressure and On/Off Bottom ASA for easy removal of your tank. KP+ gives the unparalleled edge on the day of your pump play. \n\n\n\n\n==2011 Azodin Kaos Pump II==\nFor 2011, the Azodin design team has added not only new looks, but also introduces the \"Twist Lock II\" design. Now with the new \"Twist Lock II\", you can secure your loader tighter than ever before. The Muffle Percussion System incorporates a Low Pressure Inline Regulator, High Performance Valve, Muffle Striker and Silence Bolt to minimize the sound signature and increase the accuracy and performance. A new Stainless steel pump rod reaffirms long term durability and outright customer confidence and satisfaction. \n\n\n\n\n==Empire BT Tracer==\nThe Empire Tracer pump paintball gun is affordable to any new player, pump player or anyone looking to bring back some old memories. Proven design of 15+ years from the original PMI Tracer. Brand new feel with a more comfortable and ergonomic handle. Those old days of struggling to pump your gun are gone for good. Picatinny rails are mounted on the top of the Empire Tracer so you can mount all of your favorite accessories.", + "htmllinks" : "Pump Gun Upgrades and Accessories", + "head_title" : "Pump Paintball Guns | Paintball Pump Guns", + "page_title" : "Buy Pump Paintball Guns Online On Sale Now" + }, + ".backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_roulette_hydration_packs_" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.spitfire_pants" : { + "meta_keywords" : "Spitfire pants,Spitfire denim,Spitfire pant,Spitfire jean,stretch Spitfire pants,Spitfire cargo pants,Spitfire mens jeans,Spitfire denim jeans,Spitfire mens pants,stretch Spitfire pant,Spitfire feeble pant", + "meta_description" : "Spitfire Pants - Huge selection of Spitfire Denim Pants available online at Zephyr Sports. Always the best price, Always free shipping over $75. Buy your Spitfire Jeans online Now!", + "page_title" : "Spitfires Pants & Jeans with Free Shipping", + "head_title" : "Spitfire Pants | Spitfire Denim Pants | Spitfire Jeans" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_ap_30_backpacks" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.dpms_airsoft_rifles" : {}, + ".apparel.head_bands_and_wraps.maddog_paintball_head_bands___sandanas" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.vans_watches" : {}, + ".markers.kingmanspyder.spyder_electra_paintball_guns" : {}, + ".casual_clothing.mens_clothing.tshirts.eclipse_t_shirts" : { + "meta_keywords" : "eclipse tee shirt,eclipse paintball shirt,eclipse tshirts,planet eclipse t shirts\r ", + "meta_description" : "Eclipse paintball shirts on sale at Zephyr Sports now. Lowest Prices Free Shipping, Pain free returns. Get your Planet Eclipse shirt today", + "page_title" : "Eclipse Paintball Shirts On Sale & Free Shipping", + "head_title" : "Eclipse Paintball Shirts | Plant Eclipse Shirt | Eclipse Tee Shirt" + }, + ".casual_clothing.mens_clothing.sweatshirts.nixon_sweatshirts" : { + "meta_description" : "Nixon Sweatshirts - Buy your Nixon Hoodies At Zephyr Sports for Less Today! We carry a complete line of Nixon Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Nixon Sweatshirts | Nixon Hoodies | Nixon Hoody" + }, + ".airsystems.co2tanks" : { + "meta_description" : "CO2 Tank - Buy your Paintball CO2 Online at Zephyr Paintball for Less today. Free Shipping on CO2 Paintball Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy CO2 Tank Online On Sale Now", + "head_title" : "CO2 Tank | Paintball CO2 | CO2 Paintball", + "description" : "=All co2 tanks are shipped empty to comply with DOT regulations. Sorry but we are unable to ship full tanks=" + }, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_sl8r_paintball_guns" : {}, + ".1newitems.2009_proto_gear" : {}, + ".airsoft.airsoft_gun_magazines.gas_pistol_magazines" : {}, + ".airsoft.airsoft_safety.airsoft_goggles.guard_dogs_goggles" : {}, + ".airsystems.regulators.custom_products_regulators" : { + "meta_keywords" : "CP regulator, custom products regular, cp regulator, Custom products reg, cp inline regulator", + "meta_description" : "CP Regulator - The Custom Products Regulator is the #1 Regulator in tournament paintball. CP regulators have a fast recharge rate, are extremely lightweight and are hand built in the USA.Zephyr carries a complete line of CP regulators in numerous colors with free shipping on order overs $100", + "page_title" : "Buy CP Regulator Online On Sale Now", + "head_title" : "CP Regulator | Custom Products Regulator | CP Regulators", + "description" : "Custom Products new high flow regulator is the perfect solution for any paintball gun in need of a regulator upgrade. High quality construction (Made in the USA) and careful engineering makes for an awesome reg with some excellent features. - Lightweight construction keeps your paintball marker as light as possible, allowing better handling of your gun. Bottom exiting hose fittings stays out of the way of your hand. Screws easily into any gun with an ASA port. Durable space age regulator seat makes for consistent velocities and reduced regulator shootdown. The guys at Zephyr shoot CP regulators, and we are impressed with the degree of comfort and performance it provides. Excellent upgrade for any gun. This reg comes in two different versions. The short reg comes with a threade bottom to attach a macroline fitting to. The short reg comes with a straight macro line fitting pre-installed." + }, + ".shop_by_brand.techt_paintball" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n \n \n \n \n
                                                                          \n Other Upgrades\n \n
                                                                          \n
                                                                          ", + "meta_description" : "Techt Paintball - Buy your Tech T Paintball At Zephyr Sports for Less Today! We carry a complete line of TechT Bolts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "==Tech T Paintbal. . . SUPERIOR DESIGN EQUALS SUPERIOR PARTS==\n\n=MADE IN THE USA=\n\nTechT Paintball Products is driven to make every paintball gun shoot at its best. Their focus is to make paintball guns (markers) cycle faster, smoother and more consistent, all while saving on compressed air or CO2. They manufacture bolt upgrades, triggers, Tippmann upgrades, loader upgrades, paintball gun maintenance videos, t-shirts, paintball gun o-ring kits, marker accessories, stickers, screws, and various other paintball related products that are all made in the USA. ", + "page_title" : "Buy Techt Paintball Now! On Sale & Free Shipping", + "head_title" : "Techt Paintball | Tech T Paintball | TechT Bolts", + "zoovy:banner01" : "banners/paintball/headers/tech_t_header", + "description" : "When producing every product, Tech T's goal is to make it hands-down the best product in its class. They strive for perfection in every aspect of our products. All of Tech T's products are the result of a love for paintball.\n\n\nThey are very proud of the fact that all of their products are made in the USA. Tech T has it's top machinists manufacture their products to the tightest tolerances possible. Because of that attention to detail and strict quality guidelines,TechT has become synonymous with quality and performance. All Tech T parts also carry a WARRANTY for manufacturers defects.\n\n\n=At TechT, performance parts are their business, and they take their business very seriously.=\n\n\n==Innovative Parts by Tech T==\n* Enertia Bolt System\n* Hush Bolt System ( For EGO Marker )\n* L7 Bolt Series\n* Vortex Mod\n* I Fit\n* Squishy Paddles\n* Zero Kick Hammer\n* MRT " + }, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_front_end_conversion_kits" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Front End Conversion Kits | AEG Front End Kits" + }, + ".return_request" : { + "description4" : "This is the form submit/print confirmation. You can edit this through the website builder to say whatever you need. The contents only show up when printing.", + "description" : "

                                                                          Returns & Exchanges

                                                                          \nReturn Policy & Procedure
                                                                          \nWe offer a 30-Day Money Back Guarantee on all new and unused merchandise in its original packaging, (paintballs excluded). Extended Holiday Return Policy: Orders placed between November 1st to December 31st, 2008 can be returned or exchanged until January 31st, 2009. If you plan to return or exchange an item(s), then please follow the prompt bellow.
                                                                          \n

                                                                          Is the item you're returning defective?

                                                                          \n

                                                                          Hint: Did the item NOT work when you opened the box?

                                                                          \n\n
                                                                          \n
                                                                          \n
                                                                          \nPlease Note:
                                                                          \n
                                                                            \n
                                                                          • All returns are subject to a 15% restocking fee
                                                                          • \n
                                                                          • Restocking fee may be waived if Store Credit is preferred
                                                                          • \n
                                                                          • Used products may not be returned. Use is defined as any attempt to open packaging, fire, install, wear or wash.
                                                                          • \n
                                                                          • If you were shipped the incorrect item or an item that differed from the invoice, please note this under the \"Reason for Return\" section of the RMA request form. This is so you receive the appropriate RMA number.
                                                                          • \n
                                                                          • All Manufactures provide at least a 90-day (some offer 1 year) full parts and labor warranty on guns.
                                                                          • \n
                                                                          • All purchasers of paintball markers must be 18 years of age. Purchasers agree to abide to all local laws and regulations in their area.
                                                                          • \n
                                                                          • Purchasers are responsible for all importation taxes and duties imposed.
                                                                          • \n
                                                                          • We will not accept exchanges / returns on defective merchandise, please contact the manufacturer.
                                                                          • \n
                                                                          • Shipping costs for returns are the responsibility of the purchaser. Shipping will be charged on returns that received free shipping. Shipping costs will not be refunded on returns or refused packages
                                                                          • \n
                                                                          • No returns accepted without RMA (Return Merchandise Authorization) number.
                                                                          • \n

                                                                          \nFeel free to contact our office at 877.814.4297 with any questions or concerns. Zephyr Sports will not be held responsible for any typographical errors made when filling out the RMA request Form. Paintball Guns are not toys and should be handled as such. Airsoft guns are required to have the tip (1/4 inch) of the barrel permanently colored in blaze orange or red.

                                                                          \nAll pricing is listed in U.S. Dollars (USD$)." + }, + ".casual_clothing.z_unisex_clothing_accesories.cell_phone_cases.incipio_cell_phone_cases" : {}, + ".casual_clothing.mens_clothing.socks.globe_socks" : { + "meta_description" : "Globe Socks - Buy your Globe Skate Socks At Zephyr Sports for Less Today! We carry a complete line of Globe Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Globe Mens Socks at Zephyr Sports", + "head_title" : "Globe Socks | Globe Skate Socks | Globe Mens Socks" + }, + ".3packagespecials.stryker_paintball_packages" : { + "meta_description" : "Stryker Paintball Packages - Buy your Stryker Rail Paintball Guns Kits Online at Zephyr Paintball for Less today. Free Shipping on Stryker Rail Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Stryker Paintball Packages Online On Sale Now", + "head_title" : "Stryker Paintball Packages | Stryker Rail Paintball Guns Kits | Stryker Rail Paintball Markers" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_royal_sunglasses" : { + "meta_description" : "Arnette Royal Sunglasses - Zephyr Sports carries a complete line of Royal Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Royal Sun Glasses Online Today.", + "page_title" : "Arnette Royal Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Royal Sunglasses | Royal Arnette Sunglasses | Arnette Royal Sun Glasses" + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_dusk_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,Dragon Dusk Sunglasses", + "meta_description" : "Dragon Dusk Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Dusk Sunglasses" + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_calavera_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon calavera sunglasses", + "meta_description" : "Dragon Calavera Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Calavera Sunglasses" + }, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_darth_sunglasses" : {}, + ".casual_clothing.mens_clothing.tank_tops.metal_mulisha_tank_tops" : { + "meta_description" : "Metal Mulisha Tank Tops - Buy your Metal Mulisha Jersey Tank Tops At Zephyr Sports for Less Today! We carry a complete line of Metal Mulisha Mens Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Metal Mulisha Mens Jersey Tank Tops at Zephyr Sports", + "head_title" : "Metal Mulisha Tank Tops | Metal Mulisha Jersey Tank Tops | Metal Mulisha Mens Tank Tops" + }, + ".casual_clothing.z_shoes_and_footwear.sanuk_shoes" : {}, + ".airsystems.dropforwards.dye" : { + "meta_description" : "Dye Drop Forward - Buy your Dye on off Airport Online at Zephyr Paintball for Less today. Free Shipping on Dye Air Port Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Drop Forward Online On Sale Now", + "head_title" : "Dye Drop Forward | Dye on off Airport | Dye Air Port" + }, + ".markers.pmi_paintball_guns" : { + "banner1" : "banners/categories/guns/pmi_banner.jpg", + "banner01_link" : "/category/3packagespecials.pihrana_paintball_packages/", + "prodlist1_header" : "PMI Pirahna Paintball Guns", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001" + }, + ".markers.kingmanspyder.spyder_mrx_paintball_guns.kingman_spyder_mrx_elite" : { + "meta_keywords" : "Spyder paintball gun, woodsball gun, woodsball marker, Spyder MRX, Spyder MRX Elite, Spyder woodsball, spyder markers, spyder elite marker, spyder elite paintball gun, woodsball markers, woodsball paintball gun, woodsball, military simulation paintball guns, DLS, Dual Loading System, Mag Fed paintball gun, paintball magazine", + "meta_description" : "The Spyder MRX Elite Paintball gun is an excellent woodsball marker for the player looking for the most realist military simulation. the DLS (Dual Loading System) allows you to use both a hopper and the guns 10 round magazine to spray paint. ", + "top_description2" : "==Spyder MRX Elite==\nThe Spyder MRX Elite is a tactical powerhouse featuring the brand new \"DLS\" Dual Loading System. This unique patent pending system enables you to interchange your loading system with a quick turn of the barrel; allowing the user to switch between a traditional upper load feed system and all new 10-round lower magazine feed system during play. The extensive list of included MRX Accessories delivers a realistic military look allowing the player to experience a true Mil-Sim feel making it a must-have marker for scenario paintball players.", + "banner02_link" : "http://www.zephyrpaintball.com/category/3packagespecials.kingman_spyder_paintball_packages.kingman_spyder_mrx_elite_paintball_packages/", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "zoovy:banner02" : "banners/paintball/newsletters/spyder_mrx_elite_banner", + "htmlvids" : "", + "head_title" : "Spyder Paintball Gun | Woodsball Marker | Spyder MRX", + "page_title" : "Spyder MRX Elite Paintball Guns" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs.camelbak_fairfax_hydration_packs" : {}, + ".casual_clothing.mens_clothing.tshirts.pb_fashion_t_shirts" : { + "meta_keywords" : "pb fashion t shirts,hk army shirts,hk army t shirts,paintball fashion", + "meta_description" : "PB Fashion T Shirts - Zephyr carries a complete line of PB Fashion shirts including HK Army Shirts. Low prices, Free Shipping, Zephyr has you covered.", + "page_title" : "PB Fashion T Shirts On Sale & Free Shipping", + "head_title" : "PB Fashion T Shirts | HK Army Shirts " + }, + ".markers.kingmanspyder.spyder_mr4_paintball_guns" : { + "meta_description" : "Spyder MR4 Paintball Guns - Buy your MR4 Spyder Paintball Marker Online at Zephyr Paintball for Less today. Free Shipping on MR4 Paintball Gun Trust Zephyr for all your Paintball Needs", + "top_description2" : "The Spyder MR4 uses the patent pending Eko Valve System to squeeze up to 1800 shots out of a 20oz co2 tank. The MR4 comes plenty of picattinny rail mounts for what ever you want to add to your marker. The side feed port allows you to use all of the top mounts on the spyder mr4 with no obstructions. The spyder mr4 paintball gun also includes a removeable shoulder stock, 12\" micro port barrel and a magazine style foregrip. Full Spyder MR4 features below.", + "banner02_link" : "http://www.zephyrpaintball.com/category/3packagespecials.kingman_spyder_paintball_packages.spyder_mr4_paintball_packages/", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001", + "description" : "The spyder mr4 is a great entry level scenario paintball gun. Upgradeable with the egrip, the mr4 can shoot 15bps. Plenty of firepower to control the woods. The stock mr4 is a semi auto gun that is great for beginners. Very durable with plenty of features like the picatinny rails and included raised sight rail / carry handle. Zephyr Paintball has a complete line of spyder mr4 guns and packages with everything you need to get on the field. More questions on the Spyder MR4? use our live chat for instant answers.\n\n\n=Spyder MR4 Feature List=\n*Mil-Sim Style Semi-Auto Paintball Marker\n*EKO™ Valve System (Patent Pending)\n*Removeable Shoulder Stock\n*12\" Micro Ported Barrel w/ Muzzle Break - Spyder Thread\n*Barrel Shroud w/ Ring Sight\n*Raised Sight Rail\n*Multiple Picatinny Rail Mounting System\n*Magazine Style Foregrip\n*High Impact Polymer Off-Set Clamping Feed Neck\n*Side Cocking Aluminum Bolt\n*Quick Release Striker Plug Pull Pin\n*Short Pull Single Trigger\n*Steel Braided Hose\n*External Velocity Adjuster\n*Operates on CO2 or Compressed Air\n*Effective Range: Approximately 200 feet\n*Accuracy Range: Up to 150 feet\n*Air Efficiency: Shoot up to 1,800 paintballs per 20oz CO2 Tank\n*2-Way Adjustable Two Finger Trigger\n ", + "top_html_focus" : "", + "page_title" : "Buy Spyder MR4 Paintball Guns Online On Sale Now", + "head_title" : "Spyder MR4 Paintball Guns | MR4 Spyder Paintball Marker | MR4 Paintball Gun" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.c1rca_circa_youth_sweatshirts" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_juliet_sunglasses" : { + "meta_keywords" : "Oakley Juliet Sunglasses,Juliet oakley sunglasses,oakley Juliet, Juliet polarized sunglasses", + "meta_description" : "Oakley Juliet Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Juliet and Polarized Oakley Juliet Sunglasses on Sale! ", + "page_title" : "Oakley Juliet Sunglasses with Free Shipping", + "head_title" : "Oakley Juliet Sunglasses | Juliet Oakley Sunglassses" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_pants" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_asian_fit_sunglasses.oakley_asian_fit_flak_jacket_xlj_sunglasses" : { + "meta_description" : "Oakley Asian Fit Flak Jacket Sunglasses - Zephyr Sports carries a complete line of Flak Jacket Asian Fit Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Flak Jacket Asian Fit Sun Glasses Online Today.", + "page_title" : "Oakley Asian Fit Flak Jacket Sunglasses On Sale Free Shipping", + "head_title" : "Oakley Asian Fit Flak Jacket Sunglasses | Flak Jacket Asian Fit Oakley Sunglasses | Oakley Flak Jacket Asian Fit Sun Glasses" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns" : { + "meta_keywords" : "Green Gas,Gas Blowback Revolver,Gas Blowback 1911,Green Gas Airsoft Guns,blow back,non blow back,Gas powered airsoft gun,Firepower,Classic Army,Sig Sauer,green gas gun,airsoft green gas gun", + "meta_description" : "Green Gas is the propellant used to drive these airsoft guns, consisting of the gas propane with silicone oil added. Typically green gas guns are pistols in which the magazine accepts small amounts of green gas. These pistols tend to allow for both real action blow back or non blow back and very in weight and size. Depending on the gun, a single magazine full of green gas can allow for multiple reloads. Zephyr Sports carries a wide variety of big airsoft brands to choose from..! Firepower, Classic Army, Sig Sauer, and more!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Gas Blowback Revolver On Sale & Free Shipping", + "head_title" : "Gas Blowback Revolver | Gas Blowback 1911 | Green Gas Airsoft Guns", + "description" : "" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_goggle_cases" : { + "meta_description" : "Dakine Goggle Cases - - Buy your Dakine Snow Goggle CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Goggles Cases on Sale Now", + "head_title" : "Dakine Goggle Cases -| Dakine Snow Goggle Cases" + }, + ".casual_clothing.z_shoes_and_footwear.dvs_shoes" : {}, + ".casual_clothing.mens_clothing.shoes.world_industries_shoes" : {}, + ".casual_clothing.mens_clothing.beanies.vans_beanies" : { + "meta_keywords" : "Vans beanie,Vans hat,Vans beanies,Vans caps,Vans 686,Vans headwear,Vans cuff visor beanie,Vans beanie hat,Vans visor beanie,Vans visor beanies", + "meta_description" : "Vans Deanie - Surf style with Vans Beanies available now at Zephyr Sports. Get your Vans hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Vans Beanies on Sale at Zephyr Today", + "head_title" : "Vans Beanie | Vans Hat | Vans Beanies" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_headwear.eclipse_clearance_headwear" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_honeyrider_sunglasses" : { + "meta_description" : "Electric Honeyrider Sunglasses - Zephyr Sports carries a complete line of Electric Honeyrider Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Honeyrider Online Today.", + "page_title" : "Electric Honeyrider Sunglasses On Sale Free Shipping", + "head_title" : "Electric Honeyrider Sunglasses | Electric Honeyrider Sun Glasses | Sunglasses Electric Honeyrider" + }, + ".goggles.1goggle_accesories.sly_paintball_goggle_accessories.sly_goggle_lenses" : {}, + ".harnessesbags.backpacks.oakley_backpacks" : { + "meta_keywords" : "oakley backpacks,oakley bags,oakley backpack 2.0,oakley packs,oakley back pack,oakley bags,hiking backpack,snowboarding backpack,hydration pack,oakley daypacks,backpacking backpack,oakley bag,oakley pack", + "meta_description" : "Oakley Backpacks - Oakley Bags are filled with useful organizational compartments! Dual Zippers for convenience! Tons of storage for food, files, and everything else! Take em everywhere! Backpacking backpack,Hiking backpack, snowboarding backpack, school backpack, ETC! Some are even hydration packs complete with built in water storage! Oakley packs are the way to go!", + "page_title" : "Oakley Backpacks with Free Shipping at Zephyr", + "head_title" : "Oakley Backpacks | Oakley Bags | Oakley Packs" + }, + ".goggles.virtue" : { + "meta_keywords" : "Virtue Vio,vio paintball mask,goggles,masks,thermal,custom,vio mask,anti,fog,tournament,best", + "meta_description" : "The Virtue Vio is the hottest Paintball Mask in 2014. The Vio is fully customizeable. You can change the lens, strap, frame and mask bottom to be exactly what you want. No longer do you have a clear lens you'll never use. Spend the extra $10 up front and get the Goggles you what you want to start. ZephyrPaintball ships the Virtue Vio for Free", + "top_description" : "== They're HERE! ==\n\nTOTALLY CUSTOMIZABLE!!! The Virtue VIO is the best looking goggle in paintball, and now you can make it truly your own. Customize your VIO below with your choice of lens, frame, mask, and more. With thousands of different possible combinations, your VIO will be truly custom.", + "zoovy:banner01" : "", + "banner01_link" : "", + "zoovy:banner02" : "", + "description" : "The Virtue VIO is the most comfortable paintball mask ever designed, featuring a quick change, fog resistant thermal lens, and an innovative versatile design that allows the player to easily change out every aspect of the goggle from the face mask to the foam, ear pads, goggle strap, and lens.\n\n\n= Features: =\n* Hinge Lock quick change lens.\n* Low profile without sacrificing coverage.\n* Dual material facemask\n* Combines soft and hard materials for protection and comfort\n* High density soft foam ear pads.\n* Ventilates and breathes easier.\n* Transmits voice better.\n* Light weight and comfortable.\n* Removable multi-layer eye foam.\n* Large lens with increased field of view.\n* Distortion Free Optical Clarity\n* Snap On removable goggle strap & ear pads.\n* Easily interchangeable face mask.\n* Available in 12 stock colorways\n* Available with 30 facemask colorways\n* Scratch-Resistant lens coatings\n* Anti-fog Dual Pane thermal lens\n* Advanced Chromatic lenses available", + "dynimage1" : "images=banners/paintball/slideshow/virtue_vio_paintball_mask_slideshow_template.jpg,banners/paintball/slideshow/virtue_vio_mask_catslideshow1.jpg,banners/paintball/slideshow/virtue_vio_mask_catslideshow2.jpg,banners/paintball/slideshow/vio_customize.jpg\nlinks=http://www.zephyrpaintball.com/product/APB-2030-VIO-PRT/Virtue-VIO-Thermal-Paintball-Mask.html,http://www.zephyrpaintball.com/product/APB-2030-FMSK-PRT/Virtue-VIO-Face-Mask.html,http://www.zephyrpaintball.com/product/APB-2030-VIOLNS-PRT/Virtue-VIO-Thermal-Replacement-Lens.html,http://www.zephyrpaintball.com/product/APB-2030-VIOBUILD/Virtue-Vio-Paintball-Mask-Builder.html\npauses=5000,5000,5000,10000\nblank_behavior=none\n", + "top_html_focus" : "", + "htmlvids" : "", + "head_title" : "Virtue Vio Paintball Mask | Custom Vio Goggles | Sale", + "page_title" : "Virtue Vio Paintball Mask Shipping Now!" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_x_squared_sunglasses" : { + "meta_keywords" : "Oakley X Squared Sunglasses,X Squared oakley sunglasses,oakley X Squared, X Squared polarized sunglasses", + "meta_description" : "Oakley X Squared Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley X Squared and Polarized Oakley X Squared Sunglasses on Sale! ", + "page_title" : "Oakley X Squared Sunglasses with Free Shipping", + "head_title" : "Oakley X Squared Sunglasses | X Squared Oakley Sunglassses" + }, + ".scenarioupgrades.flashlights___laser_sights.bt_battle_tested" : {}, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_classic_stingray_sunglasses" : { + "meta_description" : "Maui Jim Classic Stingray Sunglasses - Zephyr Sports carries a complete line of Maui Jim Classic Stingray Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Classic Stingray Online Today.", + "page_title" : "Maui Jim Classic Stingray Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Classic Stingray Sunglasses | Maui Jim Classic Stingray Sun Glasses | Sunglasses Maui Jim Classic Stingray" + }, + ".markers.us_army_paintball_guns" : { + "meta_keywords" : "us army paintball guns, tippmann alpha tactical, tippmann us army, us army salvo paintball gun, tipmann, tippman, tipman, tippmann army,tippmann alpha black,army alpha black", + "meta_description" : "Tippmann Alpha Black Guns made by Tippmann - The Tippmann Alpha Tactical paintball gun is an M4 based paintball gun. The Army Alpha Black Paintball gun is the first officially licensed paintball gun. Based on the popular tipmann 98, the us Army markers have the performance and upgradability of the custom 98 while allowing you to save about 35%", + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=&LINK=", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.us_army_paintball_packages/", + "description" : "Manufactured by Tippmann Sports, U.S. Army Paintball markers and accessories are designed to help you take your game to the highest level of realistic play possible at a great value. And since it's made by Tippmann, you can be assured of the Tippmann quality that your accustomed to. At home and abroad, the U.S. Army has utilized Tippmann paintball markers in its training to emphasize the importance of fire-control measures and cover and concealment procedures. No other training device can replicate this sense of combat realism in a totally safe environment. With these markers, you will be able to play smart…and play strong. Army Strong\n\n\nUS Army Paintball Guns use a Tippmann Model 98 Threaded barrel so you can use any of your current Model 98 Barrels. The US Army guns come in two different styles, the Army Alpha Basic and The Army Alpha tactical Paintball Gun. The US Army Tactical version of the marker includes and adjustable stock and M16 style Paintball Barrel.\n\n\nFirepower upgrades for the US Army brand of guns includes the US army Electronic E-grip Upgrade. This will upgrade your US Army gun to 15+ BPS in minutes.", + "banner1" : "banners/categories/guns/usarmy_banner.jpg", + "page_title" : "Buy Tippmann Alpha Black Online On Sale Now", + "head_title" : "Tippmann Alpha Black | Tippmann Alpha Tactical | Army Alpha Black", + "sortby_var" : "US Army Gun Type" + }, + ".apparel.jerseys.jt_usa_paintball_jerseys" : {}, + ".casual_clothing.womens_clothing.accessories.cell_phone_cases" : {}, + ".markerupgrades.tippmann.tippmann_tpx_pistol" : { + "meta_description" : "Tippmann TPX Upgrades - Buy your Tipx Upgrades Online at Zephyr Paintball for Less today. Free Shipping on Upgrades for Tippmann TPX Pistol Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann TPX Upgrades Online On Sale Now", + "head_title" : "Tippmann TPX Upgrades | Tipx Upgrades | Upgrades for Tippmann TPX Pistol" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel" : { + "head_title" : "Sale Paintball Clothing | Clearance Paintball Clothing | Paintball Clothes Sale" + }, + ".proto_rail_paintball_guns" : {}, + ".goggles.c2_eyon_paintball_goggles" : { + "meta_keywords" : "c2 eyon paintball goggles, c2 eyon masks, c2 eyon paintball masks, angel eyes, tiberius arms paintball masks, safety gear, Paintball Goggles, Paintball Masks, Paintball Equipment, paintball lens, paintball mask,", + "meta_description" : "C2 Eyon Paintball Goggles - Visit ZephyrPaintball for the lowest prices on Paintball masks and other equipment! The Eyon paintball mask is almost all lens! The C2 Eyon mask offers the largest lens in paintball to provide the player with the clearest, undistorted vision and widest field of view possible.", + "top_description" : "== C2 Eyon Paintball Masks ==\nThe new C2 Eyon Paintball Mask is the most anticipated paintball product for 2014! Below is a preview of features and sample images of what is to be expected once they are released (mid-May).\n\n\nThe brand new C2 Eyon goggle is a killer new design in both looks and performance! Features, unlike any other mask in the industry! The Eyon incorporates the largest lens in paintball to provide the player with the clearest, undistorted vision and widest field of view possible. \n\n\nThe C2 Eyon mask is designed for the utmost in comfort. The thick plush foam is positioned to wear comfortably on the face. The bridge of the nose is open to prevent uncomfortable pressure or restricted breathing. Baffles redirect your breath away from the lens and promote air circulation for fog prevention. The soft ear pieces of the Eyon protect the ear while still allowing full hearing.", + "page_title" : "Buy Goggles C2 Eyon Paintball Goggles Online On Sale Now!", + "head_title" : "C2 Eyon Paintball Goggles | Paintball Mask C2 Eyon | C2 Eyon Paintball Masks", + "zoovy:banner01" : "tiberius_arms/c2_goggles_sample_pic.jpg", + "description" : "= Features: =\n* Enhanced Optics: Orbital lens technology creates unparalleled levels of lateral and longitudinal ocular perfection.\n* EYE Quick release lens mechanism: Unbelievably simple, speedy and secure. The patented design is unique to paintball and allows super fast lens replacement.\n* Comms Ready: The removable, soft touch, ear protection shields incorporate pre-moulded comms channels allowing quick and easy comms attachment. Built-in, strategic, sound wave ergonomics help audible range at all frequencies.\n* Pitch Perfect: The unique design of the EYE lover face-plate reduces reverb and voice echo whilst generating optimum vocal clarity" + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.1911_airsoft_guns" : { + "meta_description" : "1911 Airsoft Guns - Buy your 1911 Pistols At Zephyr Sports for Less Today! We carry a complete line of Colt 1911 Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "The 1911 Airsoft guns below are replicas of the original Colt Model 1911 Firearm. Originally designed by John Moses Browning and initially produced by Colt, this pistol has served as the official military sidearm, in the armies of several nations. It has gone through several conflicts (WW1, WW2, Korea, Vietnam and others), but it also has served as the pistol of choice for thousands of civilians and Law Enforcement agents. \n\n\n\n\nThe Colt Model 1911 is probably one of the most copied firearm designs of all times. Almost all contemporary pistols are based (more or less) to the principles of the John Moses Browning pistol.\n", + "page_title" : "Buy 1911 Airsoft Guns On Sale & Free Shipping", + "head_title" : "1911 Airsoft Guns | 1911 Pistols | Colt 1911 Pistols", + "description" : "" + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.sniper_airsoft_guns" : { + "meta_keywords" : "airsoft sniper,airsoft rifle,airsoft sniper rifle,sniper airsoft, airsoft marksman", + "meta_description" : "Airsoft Sniper - Zephyr carries a complete line of Airsoft Sniper Rifles. For that longe range shot, get the latest and greatest Sniper Airsoft Gun at Zephyr todat with Free Shipping and Customer Service", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "Below are replica Airsoft Sniper Rifles. The actual military role of a sniper (a term derived from the snipe, a bird which was difficult to hunt and shoot) dates back to the turn of the 18th century, but the true sniper rifle is a much more recent development. Advances in technology, specifically that of telescopic sights and more accurate manufacturing, allowed armies to equip specially-trained soldiers with rifles that enable them to deliver precise shots over greater distances than regular infantry weapons. The rifle itself could be based on a standard rifle (at first, a bolt-action rifle); however, when fitted with a telescopic sight, it becomes a sniper rifle. ", + "page_title" : "Airsoft Sniper Rifles at Zephyr", + "head_title" : "Airsoft Sniper | Airsoft Sniper Rifles | Sniper Airsoft", + "description" : "" + }, + ".airsoft.airsoft_guns.thompson_airsoft_guns" : { + "meta_keywords" : "airsoft m1a1 thompson,thompson air soft,airsoft thompson guns,thompson airsoft guns,m1a1 thompson airsoft guns,airsoft m1 thompson,airsoft thompson smg,thompson m1 airsoft,electric airsoft thompson,thompson airsoft rifles,airsoft thompson,airsoft thompson m1a1,m1a1 airsoft thompson,spring airsoft thompson,electric thompson airsoft guns,cheap thompson airsoft guns,cheap airsoft thompson,thompson m1a1 airsoft guns,thompson airsoft machine gun,airsoft thompson tommy gun,thompson machine gun airsoft,thompson airsoft cybergun,airsoft thompson submachine gun,airsoft thompson sub machine gun\n", + "meta_description" : "Airsoft Thompson M1A1 Airsoft Guns - Thompson Airsoft Guns on sale at Zephyr Sports with Free Shipping. Get your Airsoft Thompson M1A1 Airsoft Guns from your Airsoft Headquarters", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Thompson Airsoft Guns | Airsoft Tommy Guns | Airsoft Thompson M1A1", + "description" : "" + }, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_magnum_sunglasses" : { + "meta_description" : "Gatorz Magnum Sunglasses - Zephyr Sports carries a complete line of Gatorz Magnum Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Gatorz Magnum Online Today.", + "page_title" : "Gatorz Magnum Sunglasses On Sale Free Shipping", + "head_title" : "Gatorz Magnum Sunglasses | Gatorz Magnum Sun Glasses | Sunglasses Gatorz Magnum" + }, + ".3packagespecials.dye_paintball_package_specials" : { + "meta_description" : "Dye Paintball Packages - Buy your Dye Paintball Gun Package Online at Zephyr Paintball for Less today. Free Shipping on Dye NT Package Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Paintball Packages Online On Sale Now", + "head_title" : "Dye Paintball Packages | Dye Paintball Gun Package | Dye NT Package" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_m93rii" : { + "head_title" : "KWA M93R Airsoft Pistols | KWA M93R | M93R Airsoft Pistol" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.tiberius_arms_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.sweatshirts.matix_sweatshirts" : { + "meta_description" : "Matix Sweatshirts - Buy your Matix Hoodies At Zephyr Sports for Less Today! We carry a complete line of Matix Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Matix Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Matix Sweatshirts | Matix Hoodies | Matix Hoody" + }, + ".markers.smartparts.smart_parts_impulse_paintball_guns" : { + "page_title" : "", + "head_title" : "Smart Parts 09 Impulse | Impulse Paintball Gun | Impulse Smart Parts", + "description" : "=09 Smart Parts Impulse Frequently Asked Questions=\n\n=What barrel thread pattern does the 09 Impulse use?=\n*The same thread pattern that was introduced with the Classic Impulse/Ion. Because this is now the thread pattern used on all Smart Parts markers, it is now simply referred to as Smart Parts threading.\n\n=How much does the 09 Impulse weigh?=\n*Weight of the Impulse is approximately 2.1 pounds. \n\n=Are mods from the original Impulse Compatible with the 09 Impulse?=\n*The 09 version of the Impulse is a completely different marker. At this time we know of no upgrades that are compatible.\n\n=If spool valves are so great, why make a poppet valve marker?=\n*Some players like the feel of a spool valve marker, while some prefer a poppet. Regardless of their preference, all players are looking for performance – that's where the 09 Impulse delivers. \n\n=Does the release of the new Impulse mark the end of the Shocker product line?=\n*No. In fact, this new product release proves that the Shocker SFT and Shocker NXT were not the end of the Impulse.\n\n=Why is the Impulse pressure balanced poppet valve a big deal?=\n*Most poppet valves are pushed closed by the gas used to fire the marker. At the pressure ranges needed to obtain efficient operation (in terms of shots per tank fill) these valves must be struck fairly hard in order to knock them open and fire a paintball. The balanced valve in the Impulse also uses air-pressure to counter-act the pressure pushing it closed. It opens with little force, regardless of the pressure it is holding back. The balanced valve requires so little force to open that on prototype marker one of our engineers was actually able to fire the marker by pushing the valve open with his little finger. Since the valve takes less force to open, the Impulse is not shaken by the recoil of a hard hitting heavy hammer or ram. \n\n=Is the small part sticking out under the Impulse barrel a volume chamber?=\n*No. The fire valve housing is an integral part of the pressure balanced poppet valve. The tail end of the valve is exposed to outside air through a passage in the center of the housing. The difference in pressure between the gas inside the valve, and the outside atmosphere is what provides the balancing force for the valve.\n\n=What is the advantage of dual-stage regulation?=\n*The best pressure for firing a paintball and getting maximum air efficiency is not necessarily the best pressure to drive the firing piston which closes the bolt and opens the poppet valve. By regulating these gas supplies separately, each can be optimized for its own function. The Impulse uses approximately 50 psi to drive its firing piston. Compared to competing brand markers that drive pneumatic rams or hammers at 120 psi or more, this pressure reduction means that the Impulse bolt does not strike paint as hard, nor does it cause appreciable recoil or kick. This ultra-low force piston is only possible with the combination of the pressure balanced valve and dual-stage regulation. \n\n=Where are the Impulse's regulators and how are they adjusted?=\n*Both the primary and second-stage regulators for the Impulse are built into small rectangular cartridges housed inside the grip frame. They are adjusted using allen-wrenches through the Impulse control panel - a rubber panel on the back of the grip frame. The modular design of the regulators also makes them quite simple to remove, inspect and clean or repair.\n\n=If the regulators are in the grip frame, what is in the foregrip?=\n*The Impulse foregrip is an over-sized expanded volume chamber for the pressure balanced poppet valve. It provides a buffering reservoir of gas immediately adjacent to the valve, to prevent velocity drop-off under rapid fire. The bottom of the foregrip also contains an integrated relief valve to protect the Impulse from over-pressurization in case of a compressed air system regulator failure.\n\n=Can an aftermarket regulator be screwed in place of the foregrip, bypassing the primary Impulse regulator?=\n*No, the Impulse foregrip does not use an ASA connection to attach to the marker body. A customized adapter and additional modifications would be required to use a different regulator.\n\n=The Impulse has no hoses on the outside, but what about the inside?=\n*The Impulse has no hoses on the inside either. Compressed air is routed through the regulators, grip frame and body via channels machined within the aluminum walls of those parts. A pair of stainless steel transfer linkages route gas from the grip frame into the body.\n\n=Why is the Impulse firing piston air buffered?=\n*By restricting gas flow vented from the firing piston, an air pressure buffer is created, slowing the piston and bolt as they near the end of their stroke. By slowing these parts, rather than letting them slam to an abrupt halt on impact with the valve, recoil is further eliminated from the Impulse's firing cycle.\n\n=What kind of HPA system should be used with the Impulse?=\n*The Impulse will perform optimally with a compressed air system delivering between 600 and 900 psi. “Low-Output” compressed air systems outputting 400 psi, are not recommended, as they may not react fast enough to maintain consistent pressure under high rates of fire.\n\n=Will the Impulse run on CO2?=\n*The Impulse was designed from day one to run on compressed air only. The integrated relief valve that protects the Impulse from HPA regulator failure also protects it from the pressure spikes related to CO2, so although the marker is not designed for CO2 use, it is protected from CO2 related pressure damage.\n\n=Why is an integrated relief valve important?=\n*Increasingly, compressed air system some manufacturers (not Smart Parts) save money by neglecting to include output-pressure burst disks or relief valves in their products. If such an unprotected air system should develop an internal leak, it could deliver full tank pressure to a marker. The Impulse's built-in relief valve protects the marker's solenoid valve seals and other components that could otherwise be damaged by over-pressurization.\n\n=Does the Impulse use a spoopet valve?=\n*No. The Impulse has a pressure balanced poppet valve. Internet rumors have suggested that Smart Parts was soon to release a marker with a valve that was a hybrid of spool and poppet valve designs. These rumors were not true. The Impulse is a poppet valve marker. Although it is not a spool valve, the new Impulse valve core does share a feature in common with the some Smart Parts spool valves designs – a tail. The tail end of the valve core is exposed to the outside air, the same as the pin end. This allows the gas pressure in the Impulse valve to press equally in both directions, resulting in a balanced valve that requires very little force to open.\n\n=Is the Impulse compatible with integrated air accessories for the Luxe from DLX Technology Group?=\n*No. Although the Impulse bottom-line ASA and optional drop spacer rail work similar to those components on a Luxe, placement of their air ports is different, due to the requirements of the regulators placed within the grip. \n\n=Is the Impulse battery strong enough to get through a full weekend of paintball?=\n*That really depends how much you shoot in a weekend. A fully charged Impulse battery will power the marker for approximately 100,000 shots under optimal conditions.\n\n=How long does it take the Impulse battery to charge?=\n*Approximately 20 to 30 minutes. Charging time is affected by temperature, and battery discharge level.\n\n=What if there isn't time to charge the battery?=\n*A second Lithium Polymer battery is included with the Impulse, and the battery side of the grip frame features Smart Parts quick grip snaps. The grip can be opened almost instantly without tools, and the low battery exchanged for a full battery in a matter of seconds.\n\n=What countries will the Impulse charger work in?=\n*The Impulse charger is designed for universal operation with 110 or 220 volt AC wall outlets in most countries of the world. Prong adapters may be required outside of the US, Canada or Mexico.\n\n=Does the Impulse have a “Cricket” board?=\n*No, the Impulse uses trigger-based programming with multi-colored LED feedback through the power button on the rear of its grip frame.\n\n=Is the Impulse circuit board tournament legal?=\n*Yes, the Impulse features firing modes specifically designed to comply with the rules of all the current leading tournament series, and can be upgraded by Smart Parts techs, in case of a rules change. Additional scenario and recreational modes such as multi-shot burst, and Billy Ball are also included. The Impulse features a tournament lock button on the circuit board, that prevents mode changes from being made on the field.\n\n=If the grip opens without tools for a battery change, can't a player open it to access the tournament lock during a game?=\n*No. The left side of the grip opens with quick-snap connectors for fast battery changes. The right side is secured with button-head screws that require an allen-wrench for removal. The field-lock button is on the right side of the Impulse circuit board, and can not be accessed without tools.\n\n=What type of ball detents does the Impulse use?=\n*Rubber nubbin style detents. The detents are located behind the Vision eye covers.\n\n=Why does the Impulse have a two-piece body?=\n*The two piece body allows the electronics of the Vision anti-chop system to remain completely internal without bolt-on wire/eye covers, and provides machining access for the internal gas passages used by the Impulse's hose-free design. It also allows for some interesting parts color combination possibilities and unusual feature upgrades.\n\n=How difficult is it to access the Vision sensors for cleaning?=\n*No tools are required. Each eye cover has a knurled latch. Pressing down on the latch releases the eye cover to swing open.\n\n=What prevents the eye covers from getting lost in a staging area?=\n*The Impulse Vision eye covers are hinged to the marker frame. They are not removed during normal maintenance, instead they are opened.\n\n=Do the eye covers pop open from a paintball hit, or gas pressure when shooting?=\n*No. Inside each eye cover, a small o-ring acts as a spring, securely holding the eye cover latch in the locked position.\n\n=How difficult is it to re-seat the Vision sensors in the body after cleaning?=\n*It is not difficult at all, because it is automatic. Both the Vision emitter and detector sit in pockets within the eye cover, held in place by a pair of brackets. As the eye cover is opened, they swing out with it, exposing the optical surface for cleaning, and the Vision beam path in the body. When the Vision eye cover is closed, they are perfectly re-aligned to the body.\n\n=How complex is removal of the pressure balanced valve core?=\n*No tools are required, the valve housing can be unscrewed by hand for removal of the vale spring and valve core. If the housing has been over-tightened, it may be removed with an allen-wrench.\n\n=How complex is removal of the body from the grip frame?=\n*The rubber grip must be removed, the Vision system and solenoid valve unplugged from the circuit board, two grip frame screws removed, and the grip may be removed from the body. The gas transfer linkages unplug from the Impulse body, and plug back in automatically as the two parts are rejoined.\n\n=How complex is separation of the upper body from the lower body?=\n*With the body off the grip frame, and the bolt lifted out, three screws are removed, and the two pieces separate easily.\n\n=How complex is removal of the bolt?=\n*It is very simple, just lift up on the bolt pin and slide the bolt out the back of the body.\n\n=How complex is removal of the firing piston?=\n*One allen wrench is needed to unscrew the rear cap from the Impulse. After the bolt has been removed, the firing piston is free to slide out the back.\n\n=Does the Impulse include a Q-Lock feedneck?=\n*Yes, that is a standard feature.\n\n=How complex is removal of the Q-Lock?=\n*One screw clamps the Q-Lock securely in place.\n\n=What is different between the Impulse barrel back and The Freak barrel back?=\n*Functionally, the parts are the same. The Impulse barrel back features a different external design. Some of the first photographed and released Impulse markers were shown with The Freak barrel back.\n\n=Can parts of the Impulse be mixed-and matched with different color combinations like they were with the Classic Impulse?=\n*Yes, the Impulse has a very modular design. Even the body is built with an upper and lower section." + }, + ".harnessesbags.packs___harnesses" : { + "subcat1_header" : "Shop Paintball Harnesses by Brand", + "meta_keywords" : "paintball harness, paintball pod pack, paintball pod harness, 3 2 paintball harness, dye paintball harness", + "ad3_link" : "/category/harnessesbags.packs___harnesses.maddog_designz_paintball_pod_packs/", + "meta_description" : "Paintball Harness - Get the best price on paintball pod pack at Zephyr today. Paintball pod harness sale with free shipping over $100", + "ad1" : "banners/paintball/side_banners/maddog_tactical_vestsidebanner_template.jpg", + "prodlist1_header" : "Featured Paintball Harnesses", + "description" : "Zephyr carries a wide variety of harnesses for your comfort. A Paintball Harness is much more than a Pod holder. The right harness will help with your maneuvering and comfort while on the field. Also, you might want to consider what position do you like to play when you're on the field? If you are a back player who unloads paint like crazy you might want to consider a harness that holds up to 7-9 pods. Let's start with a good starter harness that you don't have to carry around so much paint. Just getting into Paintball and looking for the basic setup that will provide you the comfort and extra paint needed on the field. The [[Kingman Spyder 4+1]:url=http://www.zephyrpaintball.com/product/PB-KING-41/Spyder_41_Ammo_Pack_Paintball_Harness__Black.html] Harness. This harness holds up to 4 pods. Each pod carries around 140 rounds of paint. It's nice to have that extra paint on the field especially for those who are trigger happy and your hopper is gone in a minute or so :-). Also this harness has a built in belt that clips on/off very easily. Most harnesses are either belt operated like the Spyder or Velcro. When you are looking at harness the (+) indicates how much more pods the harness can actually carry. In the case of the Spyder 4+1; the (1) indicates a holder for the Tank. If later down the road you decide to hold a tank attached to a [[Remote Line]:url=http://www.zephyrpaintball.com/category/airsystems.remote_lines/], this option is available. Some Harnesses may say 3+4. 4+3, 4+7, ect. Example - 3+4. There are 3 main pod holders and 4 extra pod sleeves if more paint is desired to be carried. It does get heavy so start with the minimal amount of pods to get yourself started and if you feel like you need more paint on you, you can always add another pod to your setup.", + "ad3" : "banners/paintball/side_banners/2maddog_freepods_sidebanner_template.jpg", + "ad2" : "banners/paintball/side_banners/1empire_2014_harnesses_sidebanner.jpg", + "ad1_link" : "/category/harnessesbags.packs___harnesses.maddog_designz_paintball_pod_packs/?sortby=!zoovy%3Abase_price&size=15 ", + "head_title" : "Paintball Harness | Paintball Pod Pack | Paintball Pod Harness", + "page_title" : "Buy Paintball Harness Online On Sale Now", + "ad2_link" : "/category/harnessesbags.packs___harnesses.empire_paintball_pod_packs/?sortby=zoovy%3Aprod_mfg&size=15" + }, + ".markerupgrades.feednecks.feed_elbows" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.heavyweight_spring_airsoft_pistols" : { + "meta_keywords" : "Airsoft Spring Pistols,Airsoft Spring Revolver,Airsoft Spring Colt,Smith and Wesson, Firepower,classic army,Desert Eagle,Sig Sauer,Colt,Beretta,cheap airsoft guns,Spring Powered airsoft guns,Full Metal Airsoft Pistol", + "meta_description" : "Full Metal Airsoft Pistol - Zephyr Sports carries a wide variety of heavy duty Airsoft Spring Pistols! These spring powered Airsoft replicas include: guns by Smith and Wesson, Firepower, Classic Army, Desert Eagle, Sig Sauer, Colt, Beretta and more! For cheap airsoft guns, choose Zephyr! These heavy weight Spring Powered airsoft guns are Full Metal Airsoft pistols similar to the looks and feel of the real deals! ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : " Full Metal Airsoft Pistol | Airsoft Spring Pistols | Semi Auto Airsoft Pistols", + "description" : "" + }, + ".airsoft.tactical_airsoft_gear.head_gear.valken_v-tac_head_gear" : {}, + ".airsoft.airsoft_accessories.airsoft_factory_replacement_parts" : {}, + ".loaders.hopper_accesories.empire_hopper_accesories.quick_feed_systems" : { + "meta_description" : "Prophecy Quick Feeds - Buy your Propechy Speed Feeds Online at Zephyr Paintball for Less today. Free Shipping on Empire Prophecy Crown Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Prophecy Quick Feeds Online On Sale Now", + "head_title" : "Prophecy Quick Feeds | Propechy Speed Feeds | Empire Prophecy Crown" + }, + ".casual_clothing.mens_clothing.socks.fox_socks" : { + "meta_description" : "Fox Socks - Buy your Fox Skate Socks At Zephyr Sports for Less Today! We carry a complete line of Fox Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Fox Mens Socks at Zephyr Sports", + "head_title" : "Fox Socks | Fox Skate Socks | Fox Mens Socks" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.hostility_mma_t_shirts" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_diablo_sunglasses" : { + "meta_description" : "Spy Optics Diablo Sunglasses - Zephyr Sports carries a complete line of Diablo Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Diablo Sun Glasses Online Today.", + "page_title" : "Spy Optics Diablo Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Diablo Sunglasses | Diablo Spy Sunglasses Free Shipping | Buy Spy Diablo Sun Glasses" + }, + ".markerupgrades.grips_and_grip_panels.hybrid_paintball_grips.hybrid_matrix_paintball_grips" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_valve_sunglasses" : {}, + ".casual_clothing.mens_clothing.shoes.rothco_boots_and_shoes" : {}, + ".airsoft.airsoft_batteries___chargers" : { + "meta_keywords" : "airsoft battery charger,airsoft battery,rechargeable airsoft batteries,nimh battery chargers,small airsoft battery chargers,large airsoft battery chargers,universal chargers,", + "meta_description" : "Airsoft Battery Chargers - Zephyr Sports has all your Airsoft power needs! Airsoft battery chargers, Airsoft rechargeable batteries, large and small airsoft battery chargers, etc! Universal smart chargers that prevent battery damage are available along with nimh batteries and chargers! Get it all @ Zephyr Sports", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Batteries | NIMH Lipo Battery for Airsoft | Airsoft Smart Chargers", + "sortby_var" : "Battery Type", + "description" : "" + }, + ".casual_clothing.mens_clothing.wallets.oakley_wallets" : { + "meta_description" : "Oakley Wallets - Buy your Oakley Leather Wallets At Zephyr Sports for Less Today! We carry a complete line of Wallet Oakley at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Wallets On Sale & Free Shipping", + "head_title" : "Oakley Wallets | Oakley Leather Wallets | Wallet Oakley" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_fixed_power_scopes.nikon_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".harnessesbags.backpacks.chocolate_backpacks_and_bags" : {}, + ".casual_clothing.mens_clothing.tshirts.nixon_t_shirts" : { + "meta_keywords" : "Nixon T Shirts,Nixon shirts,free shipping,Nixon TShirt", + "meta_description" : "Nixon T Shirts - Zephyr carries a complete line of Nixon Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Nixon T Shirts at Zephyr", + "head_title" : "Nixon T Shirts | Nixon Shirts | Nixon TShirt" + }, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_pilot_paintball_gun_packages" : { + "meta_description" : "Spyder Pilot Paintball Packages - Buy your Pilot Spyder Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder Pilot Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Pilot Paintball Packages Online On Sale Now", + "head_title" : "Spyder Pilot Paintball Packages | Pilot Spyder Paintball Guns Kit | Spyder Pilot Paintball Guns" + }, + ".airsoft.airsoft_bbs_ammo.crosman_airsoft_bb_s" : { + "meta_description" : "Crosman Airsoft BB Sale at Zephyr Sports. We Carry a full ine of Crosman Airsoft Ammo including Bio BBs, glow in the dark, camo and more. Get your 6mm Crosman Airsoft bb today.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 Crosman Airsoft BBs | .25 Gram Crosman Airsoft Pellets | .20 G Ammo for Airsoft Guns" + }, + ".harnessesbags.paintball_gear_bags.sly_paintball_gear_bags___backpacks" : { + "meta_description" : "Sly Paintball Gear Bags - Buy your Sly Backpacks Online at Zephyr Paintball for Less today. Free Shipping on Sly Bags Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Sly Paintball Gear Bags Online On Sale Now", + "head_title" : "Sly Paintball Gear Bags | Sly Backpacks | Sly Bags" + }, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.neff_headphones" : { + "meta_description" : "Neff Headphones - Buy your Neff Head PhonesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Neff Headphones Low Prices Free Shipping", + "head_title" : "Neff Headphones | Neff Head Phones | Headphones Nixon" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.tsd_spring_airsoft_guns" : { + "meta_description" : "TSD Airsoft Pistol - Buy your TSD Spring Airsoft PistolsOnline At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy TSD Airsoft Pistol Now! On Sale & Free Shipping", + "head_title" : "TSD Airsoft Pistol | TSD Spring Airsoft Pistols" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_fixed_power_scopes.bushnell_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones.aerial_7_headphones" : { + "meta_keywords" : "Aerial 7 Headphones,Aerial 7 Head Phones, aerial 7 Audio", + "meta_description" : "Aerial 7 Headphones - Zephyr stock a complete line of Aerial 7 Head Phones. For the ultimate Audio experience buy your Aerial 7 at Zephyr Today", + "page_title" : "Aerial 7 Headphones with Free Shipping at Zephyr", + "head_title" : "Aerial 7 Headphones | Aerial 7 Head Phones" + }, + ".scenarioupgrades.tactical_vests.voodoo_tactical_vests" : {}, + ".markerupgrades.invert_upgrades.invert_mini_grips" : { + "meta_description" : "Invert Grips - Buy your Grips for Invert Mini Online at Zephyr Paintball for Less today. Free Shipping on Mini Grips Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert Grips Online On Sale Now", + "head_title" : "Invert Grips | Grips for Invert Mini | Mini Grips" + }, + ".markerupgrades.cci_paintball_upgrades" : { + "meta_description" : "CCI Phantom Upgrades - Buy your CCI Pump Upgrades Online at Zephyr Paintball for Less today. Free Shipping on Phantom Pump Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy CCI Phantom Upgrades Online On Sale Now", + "head_title" : "CCI Phantom Upgrades | CCI Pump Upgrades | Phantom Pump Guns" + }, + ".casual_clothing.mens_clothing.socks.circa_socks" : { + "meta_description" : "Fox Socks - Buy your Fox Skate Socks At Zephyr Sports for Less Today! We carry a complete line of Fox Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Circa Mens Socks at Zephyr Sports", + "head_title" : "Circa Socks | Circa Skate Socks | Circa Mens Socks" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_day_hydration_packs" : {}, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_geo_gsl_paintball_gun" : { + "htmlvids" : "", + "top_description2" : "", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/gsl_eclipse_header.jpg", + "description" : "= The GSL has been a long time coming. =\n\nWork on the very first SL Geo started way back in February 2008. Known as the SL91 that still born project has achieved cult status within the paintball community with only the ten sample units ever seeing the light of day; exchanging hands for staggering sums of money amongst collectors its place in paintball history is secure as one of the rarest markers ever made.\nFast forward to late 2013 and we have the first fully-fledged Limited Edition SL Geo; The GSL\nJust like every other SL before it, the GSL brings something a little bit special to the table. In this case it's a stunning fusion of technology and features from the Geo3, the Ego LV1, the Ego CSL together with all new ideas developed specifically for the GSL.\n\n\nThe SL range has always been made that extra bit special by its exclusivity and its use of bespoke parts that are not used on or in any other model in the range. The GSL is no exception with virtually every external metal part being designed and manufactured in limited numbers for use exclusively on the GSL. From the body, to the frame, the POPS and trigger. Every part manufactured for sole use on the GSL. \n\n\nMechanically the GSL also varies dramatically from the Geo3 on which it is loosely based. Replacing the standard threaded internals comes a new quick release system. Pull up the bonnet and slide out the IV Core and you have access to a completely new firing assembly. The IV Core is made up of all new components with new ST3 bolt, super soft ST3 bolt tip, can, propshaft, propshaft tip, back cap, locking mechanism and bonnet. Besides the obvious quick release mechanism the IV Core was developed to further increase the already impressive efficiency of the Geo3 platform. The internals incorporate a new pressure sensing path that allows the sprung propshaft to react more quickly and earlier in the cycle to trap more of the \"tail end\" air in the firing chamber. This tail end air does not have a significant effect on the velocity of the paintball, but does contribute to inefficiency if it is wasted. The IV Core traps more of this wasted air each shot therefore increasing overall efficiency without any negative impact on the sound or feel of the marker.\n\n\nExternally the GSL incorporates the SL4 regulator and foregrip together with the grips and console from the Ego LV1. The soft, textured and shaped rubber at both contact points on the marker offer exceptional stability and ergonomic comfort. With the inclusion of the AT Pipe system from the Ego LV1 the macroline is removed from the marker and the air passes through the frame and the AT Pipe into the new SL4 inline regulator. It makes for a sleek finish.\n\n\nOf course the body, bonnet and frame blend seamlessly into each other helping to emphasise the aggressive 3D milling of the billet machined and hand finished body. A deep lustrous anodizing over a satin blasted finish in 3 select colourways adorn each marker. The colour matched anodizing extends to each of the additional accessories that are included with the GSL, such as the optional triggers and the full 5-piece SL3 barrel kit.\n\n\nPackaged in the zipper case with the barrel kit and additional trigger there is also a completely new GSL manual, a second GSL-specific ST bolt (all metal construction), a GSL Parts Kit that includes an AT POPS extender rail, ePortal Kit, tools, barrel sock and GSL Key Chain.\n\n\nThe GSL comes fully loaded in every conceivable way.\n\n= Unique GSL Features: =\n* Bespoke GSL 3D Milled Body\n* Bespoke GSL 3D Milled Quick Release Bonnet\n* Bespoke GSL 3D Milled Grip Frame\n* Bespoke GSL 3D Milled AT POPS\n* Bespoke GSL 3D Milled Contoured Eye Covers\n* Bespoke GSL IV Core Internals\n* Bespoke GSL Propshaft with Spring-Loaded Drive Core\n* Bespoke GSL ST1Bolt and ST2 Bolt\n* Bespoke GSL Circuit Board With USB Interface – Cable and Software Included\n* Bespoke GSL Dual Triggers - “Blade” and “S” Style Triggers Included\n* Bespoke GSL AT Pipe Assembly\n* Bespoke GSL 5-Piece SL3 Shaft Barrel Kit\n* Lazer-Eyes Red BBSS System\n* Exclusive PBNation GSL Badge\n\n\n= Geo 3 Features: =\n* Gen 2 ISCIS (Innovative Solenoid Controlled Isolation System) Solenoid Valve\n* LV1-Style Grip Frame and Grips\n* LV1-Style Rear Console\n* LV1-Style SL4 Inline Reg and Sleeve \n* Integrated Body Filter\n* Bolt Speed Control System (BSC)\n* 92% Larger Multicoloured Transflective LCD Module\n* Extended Grip Pitch - Increased Comfortable and Stability\n* Spool Valve Design\n* Low Reciprocating Mass - Bolt 19g\n* Tool-less Bolt removal - all internal bolt components removed without tools\n* Def-Tek Offset Feed\n* C-Lever Clamping Feedneck with Sprocket Wheel\n* Dual Selectable Trigger Switching - Opto and Micro Switches\n* Dual Trigger Return Mechanisms - Spring and Magnetic Return\n* Integrated Audible Beeper for Alarms and Actuations\n* Capped and Uncapped Ramp Modes\n* All Major Tournament Presets\n* 9 Preset Debounce Modes\n* 5-Point Adjustable Trigger\n\n\n= GSL Specifications =\n* Weight\t885g/1.95lb (including 14.5\" Barrel,Battery,Feed,POPS)\n* Length\t540mm (includes 14\" Barrel)\n* Height\t202mm\n* Width\t31mm\n\n\n= Materials =\n* Body\t6061-T6 Aluminium\n* Barrel\t6061-T6 Aluminium\n* Frame\t6061-T6 Aluminium\n* Feed\t6061-T6 Aluminium\n* Eye Covers\t6061-T6 Aluminium\n\n\n= Electronics =\n* Interface\t3 Push buttons on frame with tourney lock on PCB\n* Display\tTransflective LCD w/ Tru-Color adjustable backlite\n* Solenoid Voltage\t5v\n* Processor Voltage\t3v\n* Processor\t16-Bit 16 MIPS\n* Power Supply\t1 x 9v (PP3) Battery\n* Eportal\tCompatible (included) \n\n\n= Hardware =\n* ASA Mount\tGSL AT POPS (Push On Purge System)\n* Trigger Methods\tMicro-switch and Break Beam Opto-switch\n* Trigger Mechanism\tLeaf spring and magnetic return\n* Trigger Pivot\tDual instrument ball race units mounted in bearing carrier\n\n\n= Barrel Kit\tSL3 Shaft Barrel Kit includes: =\n* 1 x 14.5\" Aluminium SL Front 0.700\" Bore\n* 1 x 16\" Aluminium SL Front 0.700\" Bore\n* 1 x Rear Section - 0.681\" Bore\n* 1 x Rear Section - 0.685\" Bore\n* 1 x Rear Section - 0.689\" Bore\n\n" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_piston_piston_head" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Piston | Piston Head Airsoft | Airsoft Piston Heads" + }, + ".apparel.gloves.invert_paintball_gloves" : { + "meta_keywords" : "invert paintball gloves,invert ltd paintball gloves,invert limited gloves,invert prevail Gloves", + "meta_description" : "Invert Paintball Gloves - Professional quality at an entry level price. Check out the Invert LTD and Prevail Paintball Gloves at Zephyr Todat. Zephyr Paintball is the leader in online Paintball Gear. With 6000+ Product in stock, Free shipping and top notch customer service, we won't be beat.", + "page_title" : "", + "head_title" : "Invert Paintball Gloves | Invert LTD Paintball Gloves | Invert Prevail Gloves" + }, + ".barrels.barrels_by_manufacturer.lapco_paintball_barrels.lapco_big_shot_barrels" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs.camelbak_blowfish_hydration_packs" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.aeg_standard_capacity_mags" : {}, + ".shop_by_brand.full_clip" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_zoid_hydration_packs" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_cb4_sunglasses" : { + "meta_description" : "Electric CB4 Sunglasses - Zephyr Sports carries a complete line of Electric CB4 Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric CB4 Online Today.", + "page_title" : "Electric CB4 Sunglasses On Sale Free Shipping", + "head_title" : "Electric CB4 Sunglasses | Electric CB4 Sun Glasses | Sunglasses Electric CB4" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_given_womens_sunglasses" : {}, + ".barrels.freakbarrels.allamericanfreakfronts" : {}, + ".markers.jtusapaintballguns.jt_us-50_paintball_pistol" : {}, + ".shop_by_brand.kwa" : { + "top_html" : "
                                                                          \n\t\n
                                                                          \n
                                                                          \n\n\n \n \n \n \n
                                                                          \n
                                                                          \n Rifles\n \n
                                                                          \n
                                                                          \n
                                                                          \n Pistols\n
                                                                          \n
                                                                          \n SMG's\n\t\t\n
                                                                          \n
                                                                          \n
                                                                          \n", + "meta_description" : "KWA Airsoft - Buy your KWA Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of KWA M4 at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=KWA. . . Engineered to Outperform=\n\nKWA leads the industry with innovative and high performing airsoft products by combining precision engineering and a passion to outperform. Their products can be found in federal and local law enforcement training facilities nationwide. KWA offers quality products with unparalleled service and is the preferred airsoft brand for Force on Force training. Through an industry leading warranty and customer service, KWA strives to produce the highest quality airsoft products and to ensure complete customer satisfaction. The 2GX gearbox and NS2 GBB systems has set the standard in airsoft technology.", + "page_title" : "Buy KWA Airsoft On Sale & Free Shipping", + "head_title" : "KWA Airsoft | KWA Airsoft Guns | KWA M4", + "description" : "For over a decade KWA has been the industry leader of airsoft weapons. Their products can be found in federal and local law enforcement training facilities nationwide. KWA offers quality products with unparalleled service and is the preferred airsoft brand for Force on Force training.\n\n\nAirsoft technology in tactical training applications has gained momentum and acceptance over recent years. Law enforcement agencies and military units have integrated airsoft training weapons into their force-on-force training programs because of their realism and relatively low cost of operation.\n\n\nKWA Professional Training Products were developed in consultation with top tactical trainers from around the world. Every model in the series is designed to be 1:1 in scale with their real firearm counterparts, allowing full compatibility with gear and accessories. Recoil action, fire controls, and safety features are also recreated for a more dynamic training experience.\n\n\nIn a time when diminishing budgets are a reality, KWA products offer a low cost solution to your training needs. Every 6mm BB costs but a fraction of other training rounds available on the market, making KWA the logical choice.", + "zoovy:banner02" : "banners/airsoft/headers/kwa_rifles_header" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_womens_backpacks_and_bags.dakine_academy_girls_backpacks" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_swinger_sunglasses" : { + "meta_keywords" : "Arnette Swinger, Swinger Arnette, Arnette Sunglasses swinger, Arnette Swinger Sunglasses, Arnette Swinger Polarized,", + "meta_description" : "Arnette Swinger Sunglasses - High quality polarized Lens on the Arnette Swinger Polarized Sunglasses! Check out the Arnette Swinger shades @ Zephyr Sports!", + "head_title" : "Arnette Swinger Sunglasses | Arnette Sunglasses Swinger | Arnetter Swinger" + }, + ".casual_clothing.mens_clothing.sweatshirts.dragon_sweatshirts" : { + "meta_description" : "Dragon Sweatshirts - Buy your Dragon Hoodies At Zephyr Sports for Less Today! We carry a complete line of Dragon Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dragon Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Dragon Sweatshirts | Dragon Hoodies | Dragon Hoody" + }, + ".promotion_codes.free_items" : { + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_tanks.guerrilla_air_paintball_tanks" : {}, + ".harnessesbags.backpacks.1_shop_by_bag_style.laptop_bags" : {}, + ".3packagespecials.proto_paintball_gun_packages" : { + "meta_description" : "Proto Paintball Packages - Buy your Proto Rail Paintball Guns Kits Online at Zephyr Paintball for Less today. Free Shipping on Proto Rail Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Proto Paintball Packages Online On Sale Now", + "head_title" : "Proto Paintball Packages | Proto Rail Paintball Guns Kits | Proto Rail Paintball Markers" + }, + ".buyers_guide.paintball.paintball_gear_bags" : {}, + ".maddog.hopper_upgrades" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses", + "meta_description" : "Black Flys Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Fly Detector Sunglasses, Fly Jacker Sunglasses, Black Fly No 5 Sunglasses, Flyblocker sunglasses, Fly Swatter Sunglasses, Black Flys InFlyt Sunglasses, Black Flys Micro Fly 2 Sunglasses, Black Fly Micro Fly Sunglasses, Black Flys Scifly 2 Sunglasses, Black Flys Sonic Fly Sunglasses, and Black Fly Sonic Fly 2 sunglasses.", + "head_title" : "Black Flys Sunglasses | Black Flys Sunglass | Black Flys Eyewear" + }, + ".casual_clothing.mens_clothing.sweatshirts.shorty_s_sweatshirts" : { + "meta_description" : "Shortys Sweatshirts - Buy your Shortys Hoodies At Zephyr Sports for Less Today! We carry a complete line of Shortys Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Shortys Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Shortys Sweatshirts | Shortys Hoodies | Shortys Hoody" + }, + ".apparel.jerseys.dyejerseys" : { + "meta_keywords" : "Dye Paintball Jerseys,Dye Jersey Paintball, Dye Paintball, Paintball Jersey, Dye Jersey, Paintball Equipment, Dye Paintball Equipment, Dye Paintball Supplies,dye c10 paintball jersey,dye c11 Jersey,C13,C14,C15,C16", + "meta_description" : "Dye C13 Paintball Jersey - Dye paintball jerseys and equipment are available online for less at ZephyrPaintball.com. Get your Dye C13 Jersey Today or take a look at the new four way stretch Dye Ultralite Jerseys.", + "top_description" : "Dye Paintball is the leader in professional tournament-grade paintball playing gear! Since paintball's inception, Dye has set the standard in paintball wear! High performance functional paintball jerseys have been their bread and butter since the start and they have only gotten better! New designs and ventilated padding are just a couple of the features showcased in Dye Paintball's C13 and Ultralite line of jerseys! Check out all the specs, colors, and designs on Dye Paintball's latest and greatest paintball jerseys for the 2013 season!", + "prodlist1_header" : "Dye Paintball Jerseys", + "banner1" : "", + "page_title" : "Dye Paintball Jerseys Free Shipping", + "head_title" : "Dye Paintball Jersey - Dye C13 Paintball Jerseys - Dye Ultralite Jersey Paintball", + "sortby_var" : "Dye Jersey Model Year", + "page_head" : "" + }, + ".3packagespecials.1_halo" : { + "meta_description" : "Halo B Starter Kits - Buy your Compressed Air Packages Online at Zephyr Paintball for Less today. Free Shipping on Paintball Packages Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Halo B Starter Kits Online On Sale Now", + "head_title" : "Halo B Starter Kits | Compressed Air Packages | Paintball Packages " + }, + ".markerupgrades.proto_slg_upgrades.proto_slg_upgrade_boards___electronics" : {}, + ".markerupgrades.feednecks.matrix_feeds" : { + "meta_description" : "Dye Matrix DM Feed Necks - Buy your Feednecks for DM Online at Zephyr Paintball for Less today. Free Shipping on DM Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Matrix DM Feed Necks Online On Sale Now", + "head_title" : "Dye Matrix DM Feed Necks | Feednecks for DM | DM Feed" + }, + ".safetygear.alta_tactical" : {}, + ".paintball.paintball_guns.battle_tested_paintball_guns.empire_bt_d_fender_paintball_marker" : {}, + ".safetygear.kneeelbowpads.condor_tactical" : {}, + ".loaders.invert_paintball_hoppers.invert_halo_too" : {}, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests.nc_star_tactical_vests" : { + "meta_description" : "NC Star Tactical Vests - Buy your NC Star Military Vests At Zephyr Sports for Less Today! We carry a complete line of NC Star Molle Vests at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "NC Star Tactical Vests On Sale at Zephyr ", + "head_title" : "NC Star Tactical Vests | NC Star Military Vests | NC Star Molle Vests" + }, + ".markerupgrades.proto_slg_upgrades.proto_slg_grip_frames" : {}, + ".markers.smartparts.shockerpaintballguns" : {}, + ".shop_by_brand.critical_paintball" : {}, + ".casual_clothing.z_shoes_and_footwear.element_skate_shoes" : {}, + ".harnessesbags.backpacks.dye_backpacks" : { + "meta_keywords" : "Dye Backpacks,Dye Back Packs,Gear Bag,travel bags,day backpack,headphone slots,bookbags,storage,", + "meta_description" : "Not just Paintball Gear Bags! Dye Backpacks double as travel bags, day backpacks, bookbags and more! Plenty of organized compartments! MP3 / CD player headphone slots! Tons of storage and durability!", + "page_title" : "Dye Backpack - Backpack Dye - Dye Bags Free Shipping", + "head_title" : "Dye Backpacks | Dye Back Packs" + }, + ".markers.kingmanspyder.kingmanelectronicspyder" : { + "htmlvids" : "
                                                                          \n\n
                                                                          ", + "description2" : "\n\n\n\n", + "description" : "" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_mason_sunglasses" : { + "meta_description" : "Spy Optics Mayson Sunglasses - Zephyr Sports carries a complete line of Mayson Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Mayson Sun Glasses Online Today.", + "page_title" : "Spy Optics Mayson Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Mayson Sunglasses | Mayson Spy Sunglasses Free Shipping | Buy Spy Mayson Sun Glasses" + }, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_aviator_polarized_sunglasses" : { + "meta_description" : "Suncloud Aviator Polarized Sunglasses - Zephyr Sports carries a complete line of Aviator Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Aviator Sun Glasses Online Today.", + "page_title" : "Suncloud Aviator Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Aviator Polarized Sunglasses | Aviator Suncloud Sunglasses Free Shipping | Buy Suncloud Aviator Sun Glasses" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_tanks.ninja_paintball_tanks" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_polarized_sunglasses" : { + "meta_description" : "Smith Optics Polarized Sunglasses - Zephyr Sports carries a complete line of Polarized Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Polarized Sun Glasses Online Today.", + "page_title" : "Smith Optics Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Polarized Sunglasses | Polarized Smith Sunglasses Free Shipping | Buy Smith Polarized Sun Glasses" + }, + ".shop_by_brand.team_sd" : { + "top_description2" : "=Team SD, specialized in performance=\n\nTeam SD is an incredibly diverse and influential in the current airsoft market. They offer everything to the young beginner or the seasoned veteran. SD airsoft makes some of the best in quality guns and have some of the lowest prices around. You won't find full metal gearbox AEG's cheaper anywhere else than with SD, especially when they are combined with the low prices Zephyr offers. Check below for any quality guns SD produces. With SD, you won't be disappointed. ", + "head_title" : "SD airsoft | Team SD | TSD sports", + "description" : "=Team SD, specialized in performance=\n\n==SD Performance==\nTeam SD is and continues to be one of the highest quality for the lowest price airsoft dealers on the market today. When you buy team SD you know you are getting a product that is quality made and cost effective. TSD sports has it's roots in airsoft, and they are sure not to disappoint. \n\n==SD, something for everyone=\nSD realizes that people have bills to pay and things to do other than airsoft, which is why they devised a way to create extremely inexpensive product compared to everyone else with comparable performance. Even for those who are just getting into the sport a few bucks will get you a long way with Team SD. " + }, + ".shop_by_brand.exalt" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tEXALT PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n", + "meta_description" : "Exalt Paintball - Buy your Exalt CleatsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=Exalt... Raise Your Game=\n\nExalt is the up and coming paintball accessories brand. With killer gear styles, accessories, and the world renowned Exalt Cleats...Everyone's eyes are now on this awesome brand. Exalt is bringing in new technology to advance the game. Technology like the Exalt TRX Cleats and the Exalt OTB Cleats, also the revolutionary Exalt Tank Grip...Basically a unique design and material that allows you to put grip onto ANY size carbon tank. Exalt IS the cutting edge for Speedball gear.", + "page_title" : "Buy Exalt Paintball On Sale & Free Shipping", + "head_title" : "Exalt Paintball | Exalt Cleats", + "description" : "Exalt is steadily becoming a big player in the paintball accessories marker. They put everything from gun lube to Exalt paintball Feed Gate's out on the table. Exalt also has their own line of speedball pants and jersey's on top of the Exalt Cleats. The new Exalt cleats that will perfect your game by giving you the footing you need when running, crouching or leaning around a corner. Made of flexible material they can bend and allow better traction when kneeling or crawling. What more could you ask for? Well I'll tell you....The unique design & material of the Exalt tank cover allows the one size to be used on any tank size from 45ci to 68ci. Made from a high quality elastomer the tank cover contains features to provide superior shoulder grip even in the wettest playing conditions, while the inner side provides a secure grip with any tank to eliminate any movement or slop found in other tank covers. The centers can be cut out so that they can be used on the front half of the tank, allowing the possibility of using 2 covers to protect the whole tank. The user can simply use 1 cover mounted on the rear half of the tank or even cut down the covers to suit the users preference. Exalt really has thought of everything with their gear. So why don't you take a closer look at what we offer for this awesome brand. " + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.action_sport_games" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.bravo" : {}, + ".safetygear.planet_eclipse" : { + "zoovy:banner01" : "banners/paintball/headers/eclipse_protective_gear_header.jpg" + }, + ".apparel.gloves.paintball_gloves_by_size.1.x.small_paintball_gloves" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.fly_girls.fly_girls_snow_fly" : { + "meta_keywords" : "Fly Girls Sunglasses,women's sunglasses, womens sunglasses,snow fly sunglasses", + "meta_description" : "Fly Girls Snow Fly Sunglasses now available @ Zephyr! Be the next Fly Girl to rock a pair of Black Flys womens sunglasses! Select Styles of these women's sunglasses by fly girl available in multiple colors!", + "page_title" : "Fly Girls Snow Fly Sunglasses On Sale & Free Shipping", + "head_title" : "Fly Girls Snow Fly Sunglasses | Flygirls Eyewear | FlyGirls Snow Fly Sunglasses" + }, + ".markerupgrades.proto_matrix_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.matrix_grip_panel/", + "buttonname_01" : "", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "", + "add2_link" : "/category/markerupgrades.feednecks.matrix_feeds/", + "buttonname_02" : "", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.autococker/" + }, + ".airsoft.shop_by_brand.full_clip" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Full clip vest | Full clip headband | Full clip holster" + }, + ".black_friday_paintball_and_airsoft_deals" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_sham_sunglasses" : { + "meta_keywords" : "Von Zipper Sham sunglasses,VZ Sham,Von Zipper polarized sunglasses,Von Zipper Sham,VZ Sham glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Sham Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Sham sunglasses now! For Von Zipper Sham glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Sham Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Sham Sunglasses | VonZipper Sham Sunglasses | VZ Sham Sunglasses" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_platform_watches" : { + "meta_keywords" : "Nixon Watches,nixon platform watch,nixon watch,nixon platform,nixon,mens watches,", + "meta_description" : "Nixon Watches - Brand new Nixon Platform Watch Available now @ Zephyr! Nixon Platform Watches feature slick styling and top quality functions. Search the shop, select a Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Platform Watch", + "head_title" : "Nixon Platform Watches | Nixon Platform Watch | Nixon Platform" + }, + ".markerupgrades.tippmann.a5.scenarioupgrades" : {}, + ".sponsorship.sponsor_only_specials.team_sponsorship_packages.empire_team_packages" : {}, + ".apparel.jerseys.hk_army_paintball_jerseys" : {}, + ".apparel.jerseys.invert_paintball_jerseys" : { + "meta_keywords" : "Invert Paintball Jerseys, Empire Invert Paintball Jersey, Discount Invert Paintball Jersey, Invert Paintball, Paintball Jerseys, Empire Invert, Empire Paintball Jerseys, Discount Paintball Jerseys, Discount Paintball Supplies", + "meta_description" : "Invert Paintball Jerseys - Shop for discount Invert paintball jerseys online at ZephyrPaintball.com.", + "page_title" : "Invert Paintball Jerseys Free Shipping at Zephyr", + "head_title" : "Invert Paintball Jerseys - Empire Invert Paintball Jersey - Discount Invert Paintball Jersey", + "page_head" : "" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_loaders.empire_prophecy_paintball_loader" : {}, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.b_medium" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_capitol_sunglasses" : { + "meta_description" : "Smith Optics Advocate Sunglasses - Zephyr Sports carries a complete line of Advocate Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Advocate Sun Glasses Online Today.", + "page_title" : "Smith Optics Advocate Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Advocate Sunglasses | Advocate Smith Sunglasses Free Shipping | Buy Smith Advocate Sun Glasses" + }, + ".1newitems.2008_products" : { + "description" : "" + }, + ".markerupgrades.proto_matrix_rail_upgrades.proto_rail_feed_necks" : {}, + ".casual_clothing.mens_clothing.beanies.famous_stars_and_straps_beanies" : {}, + ".casual_clothing.z_unisex_clothing_accesories.cell_phone_cases.oakley_cell_phone_cases" : { + "meta_description" : "Oakley Phone Cases - Buy your Oakley Iphone CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Oakley Iphone Cases", + "head_title" : "Oakley Phone Cases | Oakley Iphone Cases" + }, + ".airsoft.airsoft_safety.airsoft_face_and_neck_protection" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_bounty_sunglasses" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_dispatch_sunglasses" : { + "meta_description" : "Oakley Dispatch Sunglasses - Buy your Dispatch Oakley Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Oakley Dispatch at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Dispatch Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Dispatch Sunglasses | Dispatch Oakley Sunglasses | Oakley Dispatch" + }, + ".sponsorship.team_sponsorship_packages.empire_team_packages" : {}, + ".airsoft.tactical_airsoft_gear.patches_" : { + "meta_description" : "Airsoft Patches - Buy your Military PatchesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Patches On Sale & Free Shipping", + "head_title" : "Airsoft Patches | Military Patches" + }, + ".harnessesbags.backpacks.voodoo_tactical_backpack_and_bags" : {}, + ".markerupgrades.matrix.dye_matrix_boards___electronics" : {}, + ".loaders.kingman_paintball_loaders" : { + "meta_keywords" : "fasta loader,kingman hoppers, kingman spyder loader, kingman fasta loader, fasta hopper, spyder fasta, spyder fasta hopper, kingman paintball hopper, spyder paintball loader", + "meta_description" : "Fasta Loader - The newest high performance loader from Kingman. The Spyder Fasta Hopper give high end performance at an affordable price. Get your Kingman Paintball Hopper at Zephyr Today.", + "top_description" : "The Speed is yours. Spyder is proud to announce the new Fasta Electronic Loader. The Fasta provides both a sleek aerodynamic design and lightning fast game play with an impressive 30+ BPS (18V. These Loaders pick up the slack on the others promising to be the fastest. The Fasta is ultra light weighing in at one pound with the batteries installed! The loader has an impressive 230 ball capacity and is easy to reload in the heat of the action. The fasta is available in 18V LED and LCD as well a a more affordable 9V version. Get in the game with a Spyder Fast Loader.", + "page_title" : "Buy Fasta Loader Online On Sale Now", + "head_title" : "Fasta Loader | Spyder Fasta Hopper | Kingman Paintball Hoppers", + "description" : "" + }, + ".black_friday_paintball_and_airsoft_deals.upgrades" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_outsider_watches" : { + "meta_description" : "Nixon Outsider Watches - Buy your Nixon Outsider Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Outsider at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Outsider Watches", + "head_title" : "Nixon Outsider Watches | Nixon Outsider Watch | Nixon Outsider" + }, + ".001a_zephyr_paintball_sports_promotions_deals_sales.viewloader_vlocity___free_shell" : { + "prodlist2_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=LIST%3A%24leaveempty&ALTERNATE=0&SHOWSKU=&", + "prodlist1_header" : "Free Vlocity Shell with any Vlocity or Vlocity Jr. Purchase", + "zoovy:banner01" : "banners/categories/vlocity_free_shell_header.jpg", + "prodlist_custom" : "&SORTBY=PRICE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_fixed_power_scopes.bushnell_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_headwear.dye_clearance_headwear" : {}, + ".casual_clothing.z_unisex_clothing_accesories.lanyards.fmf_lanyards" : {}, + ".zephyr_ltd" : { + "meta_keywords" : "zephyr paintball, zephyr ltd, zephyr limited edition,paintball gear,paintball,paintball gun, vitamin c,zephyr paintball ltd", + "meta_description" : "Zephyr LTD - The new gold standard in limited edition Paintball gear. Guns, loaders, harnesses, pants and jerseys. It's all coming to Zephyr.", + "top_description" : "Limited edition gear, only available at Zephyr. Zephyr LTD is something a little different than the rest. Some of the Zephyr LTD will just be custom colors, some will be fully upgraded. Check back for more new Zephyr LTD Paintball gear.", + "page_title" : "Zephyr Paintball LTD Exclusive Paintball Gear", + "head_title" : "Zephyr Paintball LTD Limited Edition Paintball Gear", + "description" : "" + }, + ".casual_clothing.mens_clothing.socks.stance_socks" : { + "meta_description" : "Stance Socks - Buy your Stance Skate Socks At Zephyr Sports for Less Today! We carry a complete line of Stance Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Stance Mens Socks at Zephyr Sports", + "head_title" : "Stance Socks | Stance Skate Socks | Stance Mens Socks" + }, + ".casual_clothing.z_shoes_and_footwear.adio_shoes" : {}, + ".skateboard_gear.skateboard_longboards.arbor_longboard_skateboards" : { + "meta_keywords" : "Arbor Longboard ,Longboard Complete,Longboarding Skateboarding,longboarding skateboard,complete longboards,skateboards longboard,longboard skateboard complete,longboarding skateboards,longboard decks,Arbor complete,arbor bamboo,arbor koa,arbor skateboards", + "meta_description" : "Arbor Longboards - Zephyr Sports is your longboading skateboarding outlet!We carry a complete line of Arbor Skateboards including the Arbo Bamboo line of boards. Whether you're building your own longboard skateboard or already have a longboard complete in mind, Zephyr is the place to be! Zephyr Carries a grip of longboarding skateboards accessories! Skateboards longboard, Complete longboards, longboard decks, carving trucks, skateboard bearings and more all @ Zephyr Sports! ", + "head_title" : "Arbor Longboards | Arbor Bamboo | Arbor Skateboards" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_spring_guides" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft spring guide | Spring guide AEG | Airsoft spring guide G&G" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_outdoorsman_ii" : { + "meta_keywords" : "ray ban outdoorsman sunglasses, ray ban outdoorsman,ray ban outdoorsman ii, ray ban sunglasses", + "meta_description" : "Ray Ban Outdoorsman Sunglasses - Zephyr Sports carries a complete line of Outdoorsman Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Outdoorsman Sun Glasses Online Today.", + "page_title" : "Ray Ban Outdoorsman Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Outdoorsman Sunglasses | Outdoorsman Ray Ban Sunglasses | RayBan Outdoorsman Sun Glasses" + }, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_airsoft_outer_barrels" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Barrels | Airsoft Barrel Upgrades | Airsoft Tightbore Barrels" + }, + ".markers.dye_matrix_paintball_guns.dye_dm9_paintball_guns" : { + "meta_keywords" : "Dye DM9 paintball gun, cheap dye dm9, dye dm9 paintball marker, tournament paintball gun, dye matrix gun", + "banner1" : "banners/categories/guns/dm9_banner_header_002.png", + "htmlvids" : "\n\n\n\n
                                                                          \n\n
                                                                          ", + "meta_description" : "Dye DM9 Paintball Gun - The paintball gun for the dye ironmen. Check out the improvement Dye has made in the DM9 version of the dye matrix paintball marker", + "page_title" : "Buy Dye Dm9 Paintball Gun Online On Sale Now", + "head_title" : "Dye Dm9 Paintball Gun | Cheap Dye DM9 Paintball Marker | Dye Matrix", + "description" : "For 2009, Dye has released the new Dye DM9 Paintball marker, the latest in Dye’s DM series of tournament paintball guns.\n\n\nThe DM9 is the lightest paintball gun ever in the DM series. Dye has reduced the body size and gotten rid of the LPR on the front of the body for a much smoother sleeker look. Initial results have shown the DM9 is more accurate and efficient than prior models.\n\n\nThe DM9’s Hyper 3 regulator gives consistent air flow. The low operating pressure reduces kick and chopping. The gun has an internal eye sensor, which means no eye plates are needed. The DM9 also has the new one-piece eyepipe performance detents.\nThe DM9’s UL reach trigger allows for optimal trigger angle and activation." + }, + ".airsoft.airsoft_guns.utg_airsoft_guns" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "UTG Airsoft Guns | UTG Airsoft Rifles | Airsoft UTG Pistols", + "description" : "" + }, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_rt_paintball_packages" : { + "meta_description" : "Spyder Sonix RT Paintball Packages - Buy your Sonix RT Spyder Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder Sonix RT Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Sonix RT Paintball Packages Online On Sale Now", + "head_title" : "Spyder Sonix RT Paintball Packages | Sonix RT Spyder Paintball Guns Kit | Spyder Sonix RT Paintball Guns" + }, + ".apparel.shoes.vans_shoes" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_3061_one_time_sunglasses" : { + "meta_description" : "Arnette One Time Sunglasses - Zephyr Sports carries a complete line of One Time Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette One Time Sun Glasses Online Today.", + "page_title" : "Arnette One Time Sunglasses On Sale Free Shipping", + "head_title" : "Arnette One Time Sunglasses | One Time Arnette Sunglasses | Arnette One Time Sun Glasses" + }, + ".paintball.player_apparel.paintball_gloves" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_pants.tanked_clearance_paintball_pants" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb8306_tech_sunglasses" : { + "meta_description" : "Ray Ban RB8306 Tech Sunglasses - Zephyr Sports carries a complete line of RB8306 Tech Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan RB8306 Tech Sun Glasses Online Today.", + "page_title" : "Ray Ban RB8306 Tech Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban RB8306 Tech Sunglasses | RB8306 Tech Ray Ban Sunglasses | RayBan RB8306 Tech Sun Glasses" + }, + ".2clearance.paintball_clearance_gear.clearance_upgrades.clearance_bolts" : {}, + ".casual_clothing.mens_clothing.wallets.metal_mulisha_wallets" : { + "meta_description" : "Metal Mulisha Wallets - Buy your Metal Mulisha Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Metal Mulisha Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Metal Mulisha Wallets on Sale @ Zephyr Sports", + "head_title" : "Metal Mulisha Wallets | Metal Mulisha Mens Wallets | Metal Mulisha Wallet" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_m16" : {}, + ".category.misc_items.water_bottles.sigg_water_bottles" : {}, + ".scenarioupgrades.flashlights___laser_sights.maddog_scopes_and_lasers" : {}, + ".paintball.3_paintball_gun_packages.starter_packages" : {}, + ".casual_clothing.womens_clothing.ladies_sunglasses.spy_ladies_sunglasses" : {}, + ".1-employment_opportunites" : { + "top_description" : "Zephyr Sports is looking for Active Sports minded individuals to work in our fast paced high energy environment. If you think you fit the bill, email your resume to HR@zephyrsports.com for consideration. Be sure to use the job title as the subject of your email. Current open positions are listed below. Serious inquiries only!", + "top_description3" : "=Airsoft Tech Support Specialist=\n\n\n==Summary:==\n\nTo perform tech duties associated with repairs department by performing the following duties. \n\n\n==Duties and Responsibilities include the following:==\n\n\n*Hands on tech/mechanically oriented background.\n*Provide technical assistance and repairs/refurbishment for products that include, but not limited to: Airsoft Markers, and Accessories.\n*Ability to assess and appraise repairs in a timely manner.\n*Maintains an updated log of all past and current repairs.\n*Maintains and organizes the tech department.\n*Responsible for overall operation within the tech department.\n*Possess strong work ethic and positive attitude.\n\n==Skills:==\n\n*Detail Oriented\n*Quick Learner in a Fast Paced Environment\n*Oral and Written Communication Skills\n*Computer Literacy\n*Customer Relations\n*Telephone etiquette\n*Organizational Skills\n*Time Management\n\n\n==Education/Experience:==\n*1-2 Years Minimum Airsoft tech experience.\n*Must be over 18 years of age.\n\n\n\n\n=Paintball Tech Support Specialist=\n\n\n==Summary:==\n\nTo perform tech duties associated with repairs department by performing the following duties. \n\n\n==Duties and Responsibilities include the following:==\n\n\n*Hands on tech/mechanically oriented background.\n*Provide technical assistance and repairs/refurbishment for products that include, but not limited to: Paintball Markers, Loaders, Air Systems and other Paintball Accessories.\n*Ability to assess and appraise repairs in a timely manner.\n*Maintains an updated log of all past and current repairs.\n*Maintains and organizes the tech department.\n*Responsible for overall operation within the tech department.\n*Possess strong work ethic and positive attitude.\n\n==Skills:==\n\n*Detail Oriented\n*Quick Learner in a Fast Paced Environment\n*Oral and Written Communication Skills\n*Computer Literacy\n*Customer Relations\n*Telephone etiquette\n*Organizational Skills\n*Time Management\n\n\n==Education/Experience:==\n*1-2 Years Minimum Paintball tech experience.\n*Must be over 18 years of age." + }, + ".3packagespecials.azodin_paintball_packages.azodin_ats_packates" : { + "head_title" : "Azodin ATS Paintball Packages | Azodin ATS Package" + }, + ".casual_clothing.mens_clothing.shorts" : { + "meta_keywords" : "Oakley shorts,element shorts,oakley board shorts,oakley boardshorts,surf shorts,mens board shorts, mens shorts,mens boardshorts,men shorts\r billabong shorts,mens cargo shorts,board shorts swimwear,quiksilver shorts,billabong board shorts,board shorts men,mens clothing shorts,board shorts for men,hurley board shorts,volcom board shorts,mens plaid shorts,quiksilver board shorts,mens denim shorts,element shorts,quicksilver board shorts,surf board shorts,board shorts sale,board surf shorts,oneill board shorts,o neill board shorts,volcom mens shorts,plaid board shorts,mens cargo short,reef board shorts,rip curl board shorts\r ", + "meta_description" : "Mens Board Shorts - Huge selection of Mens Shorts available online at Zephyr Sports from Oakley, Billabong, DC, Element, Oneil, Hurley, Volcom and More. Always the lowest price, Always free shipping over $75. Buy your Mens Boardshorts online Now! ", + "page_title" : "Mens Board Shorts On Sale & Free Shipping", + "head_title" : "Mens Board Shorts | Mens Shorts | Mens Boardshorts" + }, + ".barrels.barrels_by_manufacturer.dye_paintball_barrels.dye_barrel_backs" : { + "meta_description" : "Dye Ultralite Backs - Buy your Dye UL Paintball Barrels Online at Zephyr Paintball for Less today. Free Shipping on Dye Ultralite Barrel Back Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Ultralite Backs Online On Sale Now", + "head_title" : "Dye Ultralite Backs| Dye UL Paintball Barrels | Dye Ultralite Barrel Back" + }, + ".casual_clothing.mens_clothing.accessories.cell_phone_cases.nixon_cell_phone_cases" : { + "meta_description" : "Nixon Phone Cases - Buy your Nixon Iphone CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Iphone Cases On Sale", + "head_title" : "Nixon Phone Cases | Nixon Iphone Cases" + }, + ".airsoft.airsoft_batteries___chargers.84v_airsoft_battery_packs" : { + "meta_description" : "8.4 Volt Rechargeable Airsoft Batteries available at Zephyr Sports. We Stock a complete line of Airsoft Batteries from all the top manufacturers", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "8.4V Airsoft Batteries | 8.4 Battery for Airsoft | Upgrade Replacement Airsoft Battery" + }, + ".markerupgrades.gog_paintball_gun_upgrades.gog_enmey" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_skitch_sunglasses" : { + "meta_keywords" : "Von Zipper Skitch sunglasses,VZ Skitch,Von Zipper polarized sunglasses,Von Zipper Skitch,VZ Skitch glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Skitch Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Skitch sunglasses now! For Von Zipper Skitch glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Skitch Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Skitch Sunglasses | VonZipper Skitch Sunglasses | VZ Skitch Sunglasses" + }, + ".markers.protopaintballguns.proto_pm7_paintball_guns" : { + "description2" : "\n\n\n\n\n ", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/proto_m7_header.jpg\"" + }, + ".wholesale" : { + "banner1" : "banners/categories/zephyr_wholesale.jpg", + "htmlvids" : "= Wholesale =\nWe handle shops & fields both small and big from all around the world. Wholesale pricing is available for most products we carry. International Wholesale is available, but some vendors limit what can be shipped internationally. \n\n\nPlease fill out and print the wholesale application found [[Here]:popup=http://static---zephyrsports.app-hosted.com/media/merchant/zephyrsports/Zephyr_Wholesale_App_2013.pdf] Be sure to sign in and then email your completed application to wholesale@zephyrsports.com.\n\n= Please note wholesale orders do not qualify for any free shipping promotions. =\n\n= Bulk Order Discounts=\nLooking for large quantities (5 to 10 qty minimum) of products we carry? Fill out [[This Form]:popup=http://static---zephyrsports.app-hosted.com/media/merchant/zephyrsports/Zephyr_Sorts_Bulk_Order_Request_Form.pdf] and email it to wholesale@zephyrsports.com and we will provide you with a quote.", + "zoovy:banner01" : "banners/paintball/headers/5wholesale_header.jpg", + "description" : "" + }, + ".casual_clothing.z_shoes_and_footwear" : {}, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases.swiss_arms" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_pants.proto_clearance_paintball_pants" : {}, + ".harnessesbags.packs___harnesses.zephyr_sports_pod_packs" : { + "prodlist1" : "&FORMAT=DEFAULT&SRC=" + }, + ".casual_clothing.mens_clothing.tshirts.virtue_t_shirts" : { + "meta_keywords" : "Virtue T Shirts,Virtue shirts,free shipping,Virtue TShirt", + "meta_description" : "Virtue T Shirts - Zephyr carries a complete line of Virtue Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Virtue T Shirts at Zephyr", + "head_title" : "Virtue T Shirts | Virtue Shirts | Virtue TShirt" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_banks_watches" : { + "meta_keywords" : "Nixon Watches,Nixon Banks,Nixon watch,Nixon Banks watch,Nixon,mens watches,Nixon mens watch", + "meta_description" : "Nixon Watches - Brand new Nixon Banks Watch available now @ Zephyr! Nixon Banks Watches features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Banks Watch", + "head_title" : "Nixon Banks Watches | Nixon Banks Watch | Nixon Banks" + }, + ".apparel.shoes.1_search_by_color.gum_mens_shoes" : {}, + ".airsoft.airsoft_bbs_ammo.g_g_airsoft_bb_s" : { + "meta_keywords" : "GG airsoft bb,G&G airsoft BB's,G&G airsoft ammo, bio bb's,biodegradeable, precision GG", + "meta_description" : "G&G Airsoft BBs - Now Available at Zephyr, the complet line of G&G Airsoft Ammo. From Bio to Sniper BBs we have you covered. With fast free shipping, low prices and customer service, Zephyr is your one stop shop for GG Airsoft BB", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 G&G Airsoft Bio BBs | .25 Gram G&G Airsoft Pellets | .20 G Biodegradeable Ammo for Airsoft Guns" + }, + ".markerupgrades.tippmann.model98customandpro.triggersgrips" : { + "meta_description" : "Tippmann 98 Triggers - Buy your Custom 98 Triggers Online at Zephyr Paintball for Less today. Free Shipping on 98 Custom Response Trigger Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann 98 Triggers Online On Sale Now", + "head_title" : "Tippmann 98 Triggers |Custom 98 Triggers | 98 Custom Response Trigger" + }, + ".casual_clothing.mens_clothing.shoes.oakley_shoes" : { + "meta_description" : "Oakley Shoes - Buy your Oakley Mens Shoes At Zephyr Sports for Less Today! We carry a complete line of Oakley Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Oakley Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Oakley Shoes | Oakley Mens Shoes | Oakley Skate Shoes" + }, + ".casual_clothing.mens_clothing.socks.alpinestars_socks" : {}, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_pistols" : { + "head_title" : "KWA Airsoft Pistols | Kwa Gas Pistols | KWA Airsoft Guns" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_serpico_sunglasses" : { + "meta_description" : "Smith Optics Serpico Sunglasses - Zephyr Sports carries a complete line of Serpico Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Serpico Sun Glasses Online Today.", + "page_title" : "Smith Optics Serpico Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Serpico Sunglasses | Serpico Smith Sunglasses Free Shipping | Buy Smith Serpico Sun Glasses" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_bermuda_sunglasses" : { + "meta_description" : "Arnette Bermuda Sunglasses - Zephyr Sports carries a complete line of Bermuda Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Bermuda Sun Glasses Online Today.", + "page_title" : "Arnette Bermuda Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Bermuda Sunglasses | Bermuda Arnette Sunglasses | Arnette Bermuda Sun Glasses" + }, + ".2clearance.under__10_paintball_clearance" : { + "head_title" : "Under $10 Paintball Gear | Cheap Paintball Gear" + }, + ".airsoft.airsoft_guns.real-sword-airsoft-guns" : { + "meta_description" : "Real Sword Airsoft Guns - Buy your Real Sword Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Real Sword AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Real Sword Airsoft Guns On Sale & Free Shipping", + "head_title" : "Real Sword Airsoft Guns | Real Sword Airsoft Rifles | Real Sword AEG" + }, + ".shop_by_brand.invert" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tINVERT PLAYER's APPAREL\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tINVERT PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tINVERT CASUAL APPAREL\n\t\n
                                                                          \n
                                                                          ", + "meta_description" : "Invert Paintball - Buy your Invert Mini At Zephyr Sports for Less Today! We carry a complete line of Invert Paintball Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=Invert Paintball. . . Rock the Invert Lifestyle=\n\nInvert Paintball became one of the leading manufacturers of low cost high quality paintball markers, gear and equipment. They took a new approach in paintball, which brought tournament style gear, and tournament grade markers to the \"Average Joe\". By making their guns and gear affordable, they gained the loyalty and respect of their customers from the quality and craftsmanship in all of their products. Invert paintball produces items such as tank covers, paintball guns, paintball masks, paintball clothes ect. Invert gear has some of the most popular styles of gear out on the market right now.", + "page_title" : "Buy Invert Paintball On Sale & Free Shipping", + "head_title" : "Invert Paintball | Invert Mini | Invert Paintball Guns" + }, + ".casual_clothing.mens_clothing.shirts.1_search_by_size.5_xx-large" : {}, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels.freak_barrel_system.complete_freak_barrels" : {}, + ".airsoft.airsoft_guns.umarex_airsoft_guns" : { + "meta_description" : "Umarex Airsoft Guns - Buy your Umarex Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of Umarex AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Umarex Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Umarex Airsoft Guns | Umarex Airsoft Rifles | Umarex AEG", + "description" : "" + }, + ".airsoft.airsoft_gun_safey_and_precautions" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Safety | Safety Airsoft Rules | Rules for Airsoft Safety" + }, + ".casual_clothing.mens_clothing.beanies.dye_beanies" : { + "meta_keywords" : "Dye beanie,Dye hat,Dye beanies,Dye caps,Dye 686,Dye headwear,Dye cuff visor beanie,Dye beanie hat,Dye visor beanie,Dye visor beanies", + "meta_description" : "Dye Deanie - Surf style with Dye Beanies available now at Zephyr Sports. Get your Dye hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Dye Beanies on Sale at Zephyr Today", + "head_title" : "Dye Beanie | Dye Hat | Dye Beanies" + }, + ".casual_clothing.mens_clothing.beanies" : { + "meta_description" : "Mens Beanie Hats - Buy your Visor Beanie At Zephyr Sports for Less Today! We carry a complete line of Knit Beanie Visor at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Mens Beanie Hats On Sale & Free Shipping", + "head_title" : "Mens Beanie Hats | Visor Beanie | Knit Beanie Visor" + }, + ".harnessesbags.backpacks.ogio_backpacks.ogio_duffel_bags" : { + "meta_keywords" : "Ogio duffel bags,duffel bags,ogio duffel,ogio pack,Ogio duffle bags,duffle bags,ogio duffle", + "meta_description" : "Zephyr Sports is a leading distributor of Ogio Duffel Bags. Travel the world with Ogio duffels! Ogio bags are made from top quality materials! Small and large, Ogio duffle bags have plenty of space for all your stuff! Super durable and stylish, Ogio bags can haul your stuff everywhere!", + "page_title" : "Ogio Duffel Bags On Sale & Free Shipping", + "head_title" : "Ogio Duffel Bags | Ogio Duffle Bags | Duffle Ogio Bags" + }, + ".markers.smartparts.smart_parts_eos_paintball_guns" : { + "meta_keywords" : "eos paintball guns, eos paintball markers, smart parts eos, eos paintball, paintball gun, paintball marker, eos paintball guns", + "meta_description" : "Eos Paintball guns - Smart Parts Eos, The best mid range tournament paintball gun today. Get your Eos paintball markers at Zephyr Today. With Bolt out back technology, you cannot beat", + "page_title" : "", + "head_title" : "EOS Paintball Guns | EOS Paintball Markers | Smart Parts EOS" + }, + ".casual_clothing.mens_clothing.jackets" : { + "meta_description" : "Mens Jackets - Buy your Windbreakers At Zephyr Sports for Less Today! We carry a complete line of Winter Jackets at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Mens Jackets @ Zephyr Sports", + "head_title" : "Mens Jackets | Windbreakers | Winter Jackets" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.29" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.tippmann_spring_airsoft_guns" : { + "meta_description" : "Tippmann Airsoft Guns - Buy your Tippmann Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of Tippmann Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Tippmann Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Tippmann Airsoft Guns | Tippmann Airsoft Rifles | Tippmann Spring Airsoft Guns" + }, + ".casual_clothing.womens_clothing.ladies_belts.nixon_ladies_belts" : {}, + ".casual_clothing.mens_clothing.accessories.hacky_sack_foot_bags" : { + "meta_description" : "Foot Bags - Buy your Hackey SackAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Foot Bags On Sale & Free Shipping", + "head_title" : "Foot Bags | Hackey Sack" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_pants.empire_clearance_paintball_pants" : {}, + ".barrels.barrels_by_manufacturer.unity_paintball_barrels" : {}, + ".skateboard_gear.skateboard_wheels.arbor_longboard_wheels" : { + "meta_description" : "Arbor Wheels - Zephyr Sports carries a complete line of Arbor Longboard Wheels At the lowest prices on the web with free shipping and easy returns. Buy your Arbor Skateboard Wheels Online Today.", + "page_title" : "Arbor Wheels On Sale Free Shipping", + "head_title" : "Arbor Wheels | Arbor Longboard Wheels | Arbor Skateboard Wheels" + }, + ".markerupgrades.feednecks.spyder_no_holes" : { + "meta_description" : "Spyder No Holes Feed Necks - Buy your Feednecks for Spyder No Holes Online at Zephyr Paintball for Less today. Free Shipping on Spyder No Holes Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder No Holes Feed Necks Online On Sale Now", + "head_title" : "Spyder No Holes Feed Necks | Feednecks for Spyder No Holes | Spyder No Holes Feed" + }, + ".airsoft.airsoft_guns.team_sd_sports_airsoft_guns.team_sd_tactical" : { + "meta_description" : "TSD Airsoft Guns - Buy your Team SD Tactical Airsoft Guns Online At Zephyr Sports for Less Today! We carry a complete line of Team SD Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy TSD Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "TSD Airsoft Guns | Team SD Tactical Airsoft Guns | Team SD Airsoft Guns", + "description" : "" + }, + ".shop_by_brand.azodin" : { + "top_html" : "
                                                                          \n\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tGuns\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\t\tPackages\n\t
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          ", + "top_description2" : "=Azodin, a fresh way to paint=\n\nAzodin Paintball is a newer paintball company that produces great starter paintball guns at a fraction of the cost of other paintball companies. Their great quality low cost paintball guns make it possible for anyone to get into the sport of paintball. Azodin Paintball guns are similar to the quality of Spyder paintball guns with a little more competitive pricing. Azodin Paintball guns all come with a full manufacturer warranty and are built to withstand the test of time. If you are serious about getting into paintball, Azodin Paintball guns are a great place to start. Look below at Zephyr's array of Azodin products. Try Azodin 2011 products like the Azodin 2011 Blitz! We are sure you won't be disappointed. ", + "head_title" : "Azodin 2011 | Paintball Azodin | Azodoin 2011 Blitz", + "banner01_link" : "/category/3packagespecials.azodin_paintball_packages/", + "zoovy:banner01" : "banners/paintball/headers/azodin_newsletter01", + "description" : "=Azodin=\nThe Azodin Paintball Gun line is designed by and distributed by previous Kingman employees that have been in the paintball industry for over 50 combined years. The Azodin Paintball Gun line ranges from great performing pump guns to the most advanced blowback guns on the market. Get your Azodin gun today and compete today!\n\n\n==Zero recoil operating system==\nZero recoil operating system is a technological breakthrough that allows for low operating pressure out of the box and gives an unparalleled shooting profile for a stacked tube blow back. The Zero system combines several unique and proprietary features that allow the Zentith to operate at 250 PSI out of the box and reduces the recoil from blow back down to the level of a spool valve marker. It features:\n\n* Feather striker system\n* Low tension Main Spring\n* Low tension Valve spring\n* Zero housing to adjust Valve timing for HPA and CO2 use. \n\nTraditionally, when seeking to lower the operating pressure of the STBB, players first look to reduce the weight of the striker. The Feather Striker System (FSS) eliminates the need to drill, grind and generally making a mess of your strikers y incorporating Delrin with a hardened Steel core to produce a striker that is both light and durable.\n\n\nNext, players also seek to balance between the Main Spring and Valve Spring to the right combination for low pressure operations, as the stock configuration was for operating pressure in excess of 600 PSI. This often involves investing in a spring kit that is limited in its choices and often produces mixed results. The AZODIN design team has taken care of this by preparing Main Spring and Valve Spring that are matched to the FSS. These matched springs have reduced the recoil signature of the ZENITH while maintaining proper air efficiency.\n\n\nLastly, to accommodate for CO2 usage, the ZeRO housing below the barrel is an adjustor to compensate for the irregularities of CO2 pressure. Technically speaking when using CO2, there will be times where liquid CO2 will seep past regulator and cause spike in pressure. The ZeRO housing acts on the Valve Spring to compensate for these occasional spikes by increasing the tension of the Valve Spring so that it will close faster in reaction to these pressure spikes. This allows for comparable performance with CO2 usage with no bench time to set the marker. All the player will need to do is to turn the ZeRO adjustor two full revolutions clockwise to achieve optimal CO2 operating profile. \n\n\n==Feather Striker System==\n\nThe Feather Striker System (FSS) utilizes Delrin and hardened Steel for a combination of durability and a reduction in weight that is over 30% lighter than the traditional striker. The AZODIN design team has coupled the FSS with lighter main and valve springs which gives all AZODIN markers unparalleled performance signature.\n\n\nThe Self Lubricating Delrin enables the FSS to be lighter and minimizes drag while the FSS moves within the receiver. The Delrin face is cupped to maximize the blow back efficiency to minimize the mechanical recoil further. The hardened Steel core provides the dependability you came to expect from the Stack Tube Blow Back system.\n\n\nThe entire assembly is locked together and rigorously tested with High Pressure Air and CO2 to ensure the durability of the construction." + }, + ".casual_clothing.womens_clothing.ladies_swim_wear.oakley_ladies_swim_wear" : {}, + ".casual_clothing.mens_clothing.watches.watch_cases" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_freezer_sunglasses" : { + "meta_description" : "Arnette Freezer Sunglasses - Zephyr Sports carries a complete line of Freezer Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Freezer Sun Glasses Online Today.", + "page_title" : "Arnette Freezer Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Freezer Sunglasses | Freezer Arnette Sunglasses | Arnette Freezer Sun Glasses" + }, + ".casual_clothing.mens_clothing.tshirts.krooked_t_shirts" : { + "meta_keywords" : "Krooked T Shirts,Krooked shirts,free shipping,Krooked TShirt", + "meta_description" : "Krooked T Shirts - Zephyr carries a complete line of Krooked Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Krooked T Shirts at Zephyr", + "head_title" : "Krooked T Shirts | Krooked Shirts | Krooked Skate TShirt" + }, + ".safetygear.chest___back_protectors" : { + "meta_keywords" : "paintball chest protector, proto chest protector, eclipse chest protector, paintball padding", + "meta_description" : "A few too many welts last time you played paintball? Paintball Protective gear is for you. A Paintball Chest Protectector will also get you many bounces to keep you in the game. Paintball padding is not just for wimps any more.", + "top_description" : "Love playing paintball, but tired of getting the welts? Or are you just looking for a few more bounces? A paintball chest protector is not just for new players any more. The newest chest protectors will fit under your jersey without the opposition even knowing. Your paintball chest protector will provide an additional layer of padding getting you the extra bounces you need.", + "page_title" : "Buy Paintball Chest Protector Online On Sale Now", + "head_title" : "Paintball Chest Protector | Paintball Protective Gear | Paintball Padding" + }, + ".skateboard_gear.skateboard_wheels" : { + "meta_keywords" : "skateboard wheels,skate wheels,skateboard wheel,skate wheel,skateboarding wheels,Alien workshop wheels,autobahn skate board wheels,baker skateboard wheels,chocolate skateboard wheels,element skateboard wheels,flip skateboard wheels,flip skateboard wheels,girl skateboard wheels,hubba skateboard wheels,pig skateboard wheels,Ricta skateboard wheels,sector 9 wheels,spitfire wheels,toy machine wheels,zoo york wheels,skateboard equipment,", + "meta_description" : "Skateboard Wheels - Zephyr Sports now carries Skateboard Wheels by top skate companies; Alien Workshop Wheels, Autobahn Skate board Wheels, Baker Skateboard Wheels, Chocolate Skateboard Wheels, Element Skateboard Wheels, Flip Skateboard Wheels, Flip Skateboard Wheels, Girl Skateboard Wheels, Hubba Skateboard Wheels, Pig Skateboard Wheels, Ricta Skateboard Wheels, Sector 9 Wheels, Spitfire Wheels, Toy Machine Wheels, Zoo york Wheels, and more! For Cheap skateboarding wheels and other skateboard accessories choose Zephyr! Everything from Skateboard trucks and skate wheels to Skate tools and grip tape! Zephyr for all your Skateboard Equipment!", + "page_title" : "Buy Skateboard Wheels On Sale & Free Shipping", + "head_title" : "Skateboard Wheels | Skate Wheels | Skateboarding Wheel" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_central_backpacks" : {}, + ".markers.tippmann.tippmann_98_packages" : { + "banner1" : "banners/98_packs_header", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/98_packs_header.jpg\"" + }, + ".testing_help_desk.international_orders" : { + "hd_answer_two" : "Yes, Zephyr Sports will ship to any country. ", + "hd_answer_four" : "To receive a shipping quote, you will need to add all of your items to the shopping cart and enter your full shipping information in the shopping cart. Sorry, but we are not able to provide shipping estimates over live chat or the phone. All orders will be shipped vis USPS Priority or Express International Mail with Insurance. A Signature will be required upon delivery.", + "hd_question_three" : "What are My Payment Options?", + "hd_question_four" : "How Much is Shipping?", + "hd_topic_listing" : "» Do you ship to APO or FPO addresses?
                                                                          \n» Do you ship to my country?
                                                                          \n» What are my payment options?
                                                                          ", + "hd_topic" : "International Orders", + "hd_question_one" : "Do You Ship to APO or FPO Addresses?", + "hd_btn" : "images/site_specific/backto_helpdesk", + "hd_answer_three" : "===For International orders you may use any of the following payment methods.===\n\n\nGoogle Checkout, Amazon Payment (purchasing through Amazon),Paypal(Must be verified) or Credit Card. All orders are subject to verification and may be delayed a few days while our Credit department reviews your order.\n\n\n\nGoogle Checkout - To use Google Checkout you will need to have an account with [[Google]:popup=https://checkout.google.com/buyerSignup?service=sierra&signupAgent=sierraAgent&gclid=homepage&hsk=1&dsh=-4315676325323532485]. If you do not have one you can set one up when checking out with Google.\n\n\nPayPal - To pay by PayPal you will need to have setup an account with [[PayPal]:popup=https://www.paypal.com/us/cgi-bin/webscr?cmd%3d_registration-run] or you may use a credit card through PayPal. ", + "hd_question_two" : "Do You Ship to My Country?", + "hd_answer_one" : "We know our Military people love to play paintball. We ship using USPS to APO/FPO addresses. Delivery times range from 1-3 weeks.", + "hd_link" : "/category/testing_help_desk" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.m4_and_m16_style_aeg_magazines" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.28" : {}, + ".1newitems.2009_planet_eclipse_gear" : { + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=21&SHOWSKU=&" + }, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_zeen_sunglasses" : { + "meta_description" : "Hoven Big Risky Sunglasses - Zephyr Sports carries a complete line of Hoven Big Risky Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Big Risky Online Today.", + "page_title" : "Hoven Big Risky Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Big Risky Sunglasses | Hoven Big Risky Sun Glasses | Sunglasses Hoven Big Risky" + }, + ".airsystems.tankcovers.bt_battle_tested_tank_covers" : { + "meta_description" : "BT Paintball Tank Covers - Buy your Empire BT Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on BT Bottle Covers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy BT Paintball Tank Covers Online On Sale Now", + "head_title" : "BT Paintball Tank Covers | Empire BT Tank Cover | BT Bottle Covers" + }, + ".markers.us_army_paintball_guns.us_army_alpha_paintball_guns" : { + "meta_description" : "Tippmann Alpha Black - Buy your Tippmann Army Alpha Online at Zephyr Paintball for Less today. Free Shipping on US Army Alpha Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann Alpha Black Online On Sale Now", + "head_title" : "Tippmann Alpha Black | Tippmann Army Alpha | US Army Alpha", + "banner01_link" : "/category/3packagespecials.us_army_paintball_packages.us_army_alpha_basic_paintball_gun_packages/", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_closeout__hydration_packs" : { + "meta_description" : "Camelbak Closeout Packs - Buy your Clearance Camelbak At Zephyr Sports for Less Today! We carry a complete line of Cheap Camelbak at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Closeout Packs On Sale & Free Shipping", + "head_title" : "Camelbak Closeout Packs | Clearance Camelbak |Cheap Camelbak" + }, + ".markerupgrades.tippmann.tippmann_x7_upgrades.front_grips___magazines" : {}, + ".shop_by_brand.arnette" : {}, + ".2clearance.clearance_paintball_guns" : { + "head_title" : "Sale Paintball Guns | Clearance Paintball Guns | Paintball Guns Sale" + }, + ".casual_clothing.mens_clothing.shirts.rothco_shirts" : { + "meta_description" : "Rothco Flannel Shirts - Buy your Rothco Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Rothco Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Rothco Shirts & Flannels Ship Free", + "head_title" : "Rothco Flannel Shirts | Rothco Polo Shirts | Rothco Shirts" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.kalishnakov_ak_47_airsoft_guns" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_stickup_sunglasses" : { + "meta_description" : "Arnette Stickup Sunglasses - Zephyr Sports carries a complete line of Stickup Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Stickup Sun Glasses Online Today.", + "page_title" : "Arnette Stickup Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Stickup Sunglasses | Stickup Arnette Sunglasses | Arnette Stickup Sun Glasses" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_skate_backpacks" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_cypher_sunglasses" : { + "meta_description" : "Arnette Cypher Sunglasses - Zephyr Sports carries a complete line of Cypher Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Cypher Sun Glasses Online Today.", + "page_title" : "Arnette Cypher Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Cypher Sunglasses | Cypher Arnette Sunglasses | Arnette Cypher Sun Glasses" + }, + ".markerupgrades.tiberius_arms" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_jury_sunglasses" : { + "meta_keywords" : "Oakley Jury Sunglasses,Jury oakley sunglasses,oakley Jury, Jury polarized sunglasses", + "meta_description" : "Oakley Jury Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Jury and Polarized Oakley Jury Sunglasses on Sale! ", + "page_title" : "Oakley Jury Sunglasses with Free Shipping", + "head_title" : "Oakley Jury Sunglasses | Jury Oakley Sunglassses" + }, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases.valken_gun_cases" : {}, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels.freak_barrel_system" : { + "meta_description" : "Freak Paintball Barrels - Buy your Freak Barrel Systems Online at Zephyr Paintball for Less today. Free Shipping on The Freak Barrel Kits Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Freak Paintball Barrels Online On Sale Now", + "head_title" : "Freak Paintball Barrels | Freak Barrel Systems | The Freak Barrel Kits" + }, + ".casual_clothing.mens_clothing.jackets.1_search_by_size" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.tippmann_98_paintball_guns" : {}, + ".barrels.barrels_by_manufacturer.stiffi_paintball_barrels.stiffi_barreltips" : {}, + ".casual_clothing.mens_clothing.boots.voodoo_tactical_boots" : { + "meta_keywords" : "", + "meta_description" : "", + "page_title" : "" + }, + ".casual_clothing.womens_clothing" : {}, + ".apparel.jerseys.valken_paintball_jerseys.valken_redemption_paintball_jerseys" : {}, + ".harnessesbags.backpacks.ogio_backpacks.ogio_motorcycle_bags" : { + "page_title" : "", + "head_title" : "!Ogio Motorcycle Bags Ship Free @ Zephyr Sports " + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.galil_airsoft_guns" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_lock_down_sunglasses" : { + "meta_description" : "Arnette Lock Down Sunglasses - Zephyr Sports carries a complete line of Lock Down Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Lock Down Sun Glasses Online Today.", + "page_title" : "Arnette Lock Down Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Lock Down Sunglasses | Lock Down Arnette Sunglasses | Arnette Lock Down Sun Glasses" + }, + ".casual_clothing.mens_clothing.jackets.dickies_jackets" : { + "meta_description" : "Dickies Jackets - Buy your Dickies Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Dickies Jackets with Free Shipping", + "head_title" : "Dickies Jackets | Dickies Mens Jackets" + }, + ".shop_by_brand" : { + "top_description2" : "", + "zoovy:banner01" : "" + }, + ".apparel.pants.sandana_venomwear_paintball_pants" : {}, + ".goggles.vforce.v_force_pro_vantage_paintball_goggles" : { + "meta_description" : "Pro Vantage Paintball Goggles - Buy your Vforce Vantage Goggles Online at Zephyr Paintball for Less today. Free Shipping on V-Force Vantage Masks Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Pro Vantage Paintball Goggles Online On Sale Now", + "head_title" : "Pro Vantage Paintball Goggles | Vforce Vantage Goggles | V-Force Vantage Masks" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_inmate_sunglasses" : { + "meta_keywords" : "Oakley Inmate Sunglasses,inmate oakley sunglasses,oakley inmate, inmate polarized sunglasses", + "meta_description" : "Oakley Inmate Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Inmate and Polarized Oakley Inmate Sunglasses on Sale! ", + "page_title" : "Oakley Inmate Sunglasses with Free Shipping", + "head_title" : "Oakley Inmate Sunglasses | Inmate Oakley Sunglassses" + }, + ".dye_i4_paintball_goggle_mask.paintball_blog" : { + "btn_title1" : "", + "btn1_name" : "Dye DM13 Paintball Gun", + "btn2_link" : "/category/dye_i4_paintball_goggle_mask.paintball_blog.dye_assault_matrix_dam_paintball_gun", + "btn2_name" : "Dye DAM Paintball Gun", + "btn1_link" : "/category/dye_i4_paintball_goggle_mask.paintball_blog.dye_dm13_paintball_gun/" + }, + ".snowboard_gear" : { + "meta_keywords" : "snowboard helmets,snowboards,snowboard gear,snowboard goggles,bindings,gloves,beanies,snowboard boots,snowboard gear bags,snowboard goggles,snowboard jackets,snowboard pants,snowboard protective gear,sweatshirts,Snowboard Gear,Von Zipper,snowboard equipment,snowboarding,snowboarding gear,snowboard helmets", + "meta_description" : "All kinds of Snowboard Gear @ Zephyr! Everything you need to kill the slopes this winter! Snowboard and Ski Helmets, Snowboard and Ski Goggles, gloves, beanies, snowboard boots, snowboard jackets, snowboard pants, protective gear, and more! Gear bags to tote all your snowboard equipment! Snowboard Goggles from Top Brands like Von Zipper! Zephyr Sports is your Snowboarding outlet this winter!", + "page_title" : "Buy Snowboard Helmets On Sale & Free Shipping", + "head_title" : "Snowboard Helmets | Snowboard Gear | Snowboard Goggles" + }, + ".airsoft.airsoft_guns.dpms_airsoft_guns" : { + "meta_description" : "DPMS Carbine Airsoft Rifles - Buy your DPMS Airsfot Guns At Zephyr Sports for Less Today! We carry a complete line of DPMS M16 Airsoft at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy DPMS Carbine Airsoft Rifles On Sale & Free Shipping", + "head_title" : "DPMS Carbine Airsoft Rifles | DPMS Airsfot Guns | DPMS M16 Airsoft" + }, + ".safetygear.kneeelbowpads" : {}, + ".airsoft.airsoft_accessories.targets" : { + "meta_keywords" : "airsoft targets,airsoft gun targets,airsoft sticky targets,", + "meta_description" : "Airsoft targets for both indoor and outdoor use. Practice your aim without making a mess. Airsoft gun targets allow you to shoot your gun at home when there is no one to play with. Sticky targets are a great alternative that make clean up easy and provide game for indoor use.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Targets | Target for Airsoft | Airsoft Practice Targets" + }, + ".casual_clothing.mens_clothing.jackets.metal_mulisha_jackets" : { + "meta_description" : "Hurley Jackets - Buy your Hurley Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Hurley Jackets with Free Shipping", + "head_title" : "Hurley Jackets | Hurley Mens Jackets | Jackets Hurley" + }, + ".skateboard_gear.skateboard_accessories.skateboard_tools" : { + "meta_keywords" : "Skateboard Tools,Skateboard hardware,Skateboard Equipment,Skateboard Trucks,Skateboard Decks,Skateboard Riser Pads,Skateboards,", + "meta_description" : "Skateboard Tools - Zephyr Sports has all of your necessary Skateboard Tools for you to set up your own Custom Complete Skateboard! Swap out your old Skate's trucks and throw on some brand new Skateboard Trucks w/ Riser Pads! Change your old rusted skate hardward for brand new custom color skateboard hardware! They're just nuts and bolts, but their YOUR nuts and bolts! It's your Skateboard!Build it to how you want it to ride! It's easy w/ Skateboard Tools @ Zephyr!", + "page_title" : "Buy Skateboard Tools On Sale & Free Shipping", + "head_title" : "Skateboard Tools | Skateboard Hardware | Skateboard Equipment" + }, + ".2clearance.paintball_clearance_gear.clearance_upgrades.clearance_stocks" : {}, + ".scenarioupgrades.flashlights___laser_sights.leapers" : {}, + ".paintballs.pmi___rps_paintballs" : {}, + ".scenarioupgrades.stocks" : {}, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_the_one_sunglasses" : { + "meta_description" : "Hoven The One Sunglasses - Zephyr Sports carries a complete line of Hoven The One Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven The One Online Today.", + "page_title" : "Hoven The One Sunglasses On Sale Free Shipping", + "head_title" : "Hoven The One Sunglasses | Hoven The One Sun Glasses | Sunglasses Hoven The One" + }, + ".apparel.shoes.circa_shoes" : {}, + ".skateboard_gear.skateboard_longboards.surf_one_longboards" : { + "meta_description" : "Surf One Longboards - Buy your Surf One Complete Longboards At Zephyr Sports for Less Today! We carry a complete line of Surf One Skateboards at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Surf One Longboards with Free Shipping at Zephyr", + "head_title" : "Surf One Longboards | Surf One Complete Longboards | Surf One Skateboards" + }, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_etha_paintball_guns" : { + "meta_keywords" : "planet eclipse etha,etha paintball gun,eclipse etha,review,colors,etha paintball marker", + "meta_description" : "Eclipse Etha - On sale now The Planet Eclipse Etha. The hottest new Marker for 2012. The Planet Eclipse Etha is a tournament level gun for $395. Free Shipping at ZephyrPaintball.com", + "top_description2" : "", + "zoovy:banner01" : "", + "banner01_link" : "", + "zoovy:banner02" : "", + "description" : "==Planet Eclipse Etha Paintball Gun==\n\nPlanet Eclipse has long been known as a market leader in high-end paintball markers and accessories. Their aim has always been set high; to produce the very best paintball equipment possible. Unashamedly, their products to date have always been aimed at the higher-end of the paintball market. They are feature- laden, finished to the very highest standard and immaculately prepared and presented. Entry Level they are not.\n\n\nWe understand that not every player has the budget for markers at that level. New or recreational players within the sport may not see the benefit in such fully featured products, but why should those players be precluded from receiving exceptional value and quality? We believe that they shouldn't be.\n\n\nThat was their philosophy when they set out to design their latest paintball marker. One that retains the core elements of all Planet Eclipse markers but comes wrapped in a more affordable package, allowing more players to enjoy the \"Eclipse Ownership Experience\"\nThe challenge was on and we are proud to share with you, the... Planet Eclipse Etha Paintball Gun!!!\n\n\n==Inside Eclipse Etha:==\n\nBut what of the Eclipse Etha itself? Well, internally the Etha is a radical departure from anything seen before in an Eclipse marker. For the first time we utilize a spring return bolt system in the firing mechanism, allowing us to simplify the pneumatic side of the marker and use a Pull Poppet spool to release air from the firing chamber.\n\n\nThe Etha bolt features dual-stage acceleration so that it picks up the paintball at a lower speed before accelerating further to push the ball fully into the barrel. The front of the bolt has a ramped rubber section. This extended rubber piece is both removable and replaceable and designed to flex freely in order to prevent clipping of the second ball in the stack as well as to be flexible on the face to cushion the paintball as its pushed toward the barrel. Both of these features work hand-in-hand with the Deftek Feed System and Break Beam Sensor System to keep any occurrences of barrel breaks to an absolute minimum.\n\n\nThe Pull Poppet that releases the air from the firing chamber is driven by a new, super-robust high pressure solenoid that is controlled by the fully adjustable PCB. The PCB controls the firing mode (semi-automatic and ramping), rate of fire, dwell and de-bounce through the multi-colour LED mounted in the rear of the frame. It is pre-programmed with modes compatible with all major tournament series meaning no upgrade needed wherever you play.\n\n\nThe frame, together with the lever operated clamping feed-tube, eye covers and the new OOPS knob are all manufactured from extremely resilient glass reinforced nylon. The Etek3 LT has proven to us just what this amazing composite is capable of: it is extremely strong, very tough, and more than capable of handling the abuse that even the roughest and toughest paintballer can throw at it. When it came time to specify the materials for Etha there was no question that this material would be at the top of our list for these parts.\n\n\nInside the frame there are sintered brass bushings for the trigger pin to pivot on and a captured, fully adjustable leaf spring similar to that found in the Ego11. These components combine with the externally adjustable trigger to produce a crisp, smooth trigger action with which to operate the micro switch. And for the first time in an Eclipse marker the trigger can be fully removed for maintenance or cleaning without having to separate the frame from the body - it makes cleaning up after a hit to the frame a breeze. To help keep paint and debris out of the inside of the frame, the grip panels are sunk into the frame around their perimeter, they also use a clever upper locating tab that means that each grip panel only requires one screw to fix it in place making access to the board and battery quick and easy. \n\n\nOn the bottom of the frame there is a brand new OOPS (On/Off Purge System) ASA with front exit porting and the same internals that are found in the POPS ASA. It actuates with the twist of a knob and fully vents the entire marker when turned off. It mounts to the frame via the robust T-Slot system.\n\n\nThe OOPS feeds through a macro-line and up to an SL3 regulator. The SL3 reg was first seen on the SLS and has since made its way onto the Geo2 and the Ego11 as well as the CSL where it has been very well received. With the ability to run HP, MP or LP compressed air tanks without adjustment it makes it a truly versatile regulator. And with its replaceable and reversible main seal it is robust, reliable and easy to service too. Like all other Eclipse markers, the Etha is designed to run solely on compressed air and not CO2.\n\n\nThe barrel also shares some similarities with those found on its bigger brothers. The Etha barrel is a 14.5 inch, two-piece, precision honed, 0.693 bore barrel that has a 'Cocker' thread into the gun body and uses the same threading as the Shaft4 barrel to join the front section to rear section. This means it has the longer control bore as well as being compatible with all other Shaft4 barrel accessories such as the Boost Kit and 16\" tip. With such a good standard barrel there should be no reason to run out and spend money on an aftermarket system.\n\n\nAnd like all other Eclipse markers, the Etha comes delivered in a hard case, lined with shock absorbing foam and packed with everything you need to look after and maintain it: a full colour manual; a full set of hex keys; a tube of Eclipse Grease; a comprehensive marker and regulator spares kit; and a barrel safety device.\n", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "top_html_focus" : "", + "head_title" : "Planet Eclipse Etha | Etha Paintball Guns | Planet Eclipse Etha", + "page_title" : "Planet Eclipse Etha On Sale Free Shipping" + }, + ".barrels.spyder.14__spyder_paintball_barrels" : { + "meta_description" : "14 inch Spyder Paintball Barrels - Buy your 14\" Spyder Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Spyder Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 14 inch Spyder Paintball Barrels Online On Sale Now", + "head_title" : "14 inch Spyder Paintball Barrels | 14\" Spyder Threaded Upgrade | Spyder Paintballs Barrels" + }, + ".casual_clothing.mens_clothing.sweatshirts.dickies_sweatshirts" : { + "meta_description" : "Dickies Sweatshirts - Buy your Dickies Hoodies At Zephyr Sports for Less Today! We carry a complete line of Dickies Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dickies Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Dickies Sweatshirts | Dickies Hoodies | Dickies Hoody" + }, + ".backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_tycoon_hydration_packs_" : {}, + "$facebook_-_pb" : {}, + ".markerupgrades.tippmann.tippmann_x7_upgrades.tippmann_x_7_stocks" : { + "meta_description" : "X7 Stocks - Buy your X7 Tactical Stock Online at Zephyr Paintball for Less today. Free Shipping on X7 Car Stock Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy X7 Stocks Online On Sale Now", + "head_title" : "X7 Stocks | X7 Tactical Stock | X7 Car Stock" + }, + ".buyers_guide.paintball.paintball_harnesses" : { + "answer_01" : "It depends on how many pods your harness can carry. Each pod can hold about 140 paintballs. Harnesses range from carrying 2 pods up to 6. A 4+1 harness can hold 4 pods. The +1 refers to the tank it can carry if you are using a remote line. Other harnesses can be 4+3 or 3+2. The +3 and +2 refer to extra pods that it can carry. The harness may only have 4 main pod holders but can have 3 small loops in between those that are able to carry extra pods. Some harnesses may even be able to hold 15 pods!", + "html_01" : "

                                                                          FAQ (Frequently Asked Questions)

                                                                          \n\n\n\n\n\n\n
                                                                          How much paint can I hold with a harness?What harness is good for me?
                                                                          ", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002", + "question_02" : "What harness is good for me?", + "text_01" : "Harnesses, also known as a pod packs, allow a player to carry extra paint and in some cases a tank. It either has a belt clip or velcro that goes around the waist or may also sometimes be a vest.", + "question_01" : "How much paint can I hold with a harness?", + "answer_02" : "It depends on the style of paintball you play. Speedball players tend to use a lot more paint than woodsball or scenario players do. Most speedball players have a harness that can hold at least 4 pods of paint.\n\n\nRemote coils are very popular among woodsball players. One end connects to the gun and one to the tank, which is carried on the harness. For example, a player who uses a remote coil would need a 4+1 harness. It's got 4 pod holders and one tank pouch.\n\n\nSpeedball harnesses do not feature tank pouches for a remote line as players constantly switch hands to fire and fill their tanks often. Some basic harnesses feature the pod holders that face forward on the side of the body instead of the back. This allows a player to easily put an empty pod back into its pocket. This is necessary because discarding and retrieving a spent pod in a woodsball game is infeasible.\n\n\nYou may also consider the position you play when looking for a harness. Back players in speedball tend to spray a lot of paint so consider more pod holders if you are a back position player.", + "title_01" : "Paintball Harness", + "return_link" : "/category/buyers_guide.paintball/" + }, + ".casual_clothing.z-sunglasses.dgk_sunglasses" : { + "meta_description" : "DGK Sunglasses - Zephyr Sports carries a complete line of DGK Eyewear At the lowest prices on the web with free shipping and easy returns. Buy your DGk Sun Glasses Online Today.", + "page_title" : "DGK Sunglasses On Sale Free Shipping", + "head_title" : "DGK Sunglasses |DGK Eyewear |DGk Sun Glasses" + }, + ".casual_clothing.mens_clothing.shirts.dvs_shirts" : { + "meta_description" : "DVS Flannel Shirts - Buy your DVS Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of DVS Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DVS Shirts & Flannels Ship Free", + "head_title" : "DVS Flannel Shirts | DVS Polo Shirts | DVS Shirts" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs" : { + "meta_description" : "Camelbak Cycling Packs - Buy your Camelbak Road Bike Packs At Zephyr Sports for Less Today! We carry a complete line of Camelbak Cycling at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Cycling Packs On Sale & Free Shipping", + "head_title" : "Camelbak Cycling Packs | Camelbak Road Bike Packs | Camelbak Cycling" + }, + ".markerupgrades.planet_eclipse_ego_upgrades.ego_body_kits" : {}, + ".markers.bob_long_paintball_guns.bob_long_victory_intimidator_paintball_guns" : { + "meta_keywords" : "Bob long,bob long paintball,paintball guns,Bob Long Victory Intimidator Paintball Gun,victory intimidator,bob long victory,cheap bob long,paintball gun,paintball marker,paintball equipment,marq victory 2", + "meta_description" : "Bob Long Victory Intimidator Paintball Guns @ Zephyr! Full line of bob long paintball guns. Bob Long Marq Victory V2 Paintball guns now in stock! Bob Long paintball gun accessories available! Pick up your Bob Long Victory Intimidator today! Choose Zephyr for all your Paintball Equipment!", + "page_title" : "Buy Bob Long Paintball Online On Sale Now", + "head_title" : "Bob Long Paintball | Bob Long | Bob Long Victory Intimidator" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.echo_1_electric_airsoft_rifles" : { + "meta_description" : "Echo 1 Airsoft Guns - Buy your Echo1 Airsoft Electric Guns At Zephyr Sports for Less Today! We carry a complete line of Echo 1 AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Echo 1 Airsoft Guns On Sale & Free Shipping", + "head_title" : "Echo 1 Airsoft Guns | Echo1 Airsoft Electric Guns | Echo 1 AEG" + }, + ".casual_clothing.mens_clothing.tshirts.birdhouse_t_shirts" : { + "meta_keywords" : "Birdhouse T Shirts,Birdhouse shirts,free shipping,Birdhouse TShirt", + "meta_description" : "Birdhouse T Shirts - Zephyr carries a complete line of Birdhouse Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Birdhouse T Shirts at Zephyr", + "head_title" : "Birdhouse T Shirts | Birdhouse Shirts | Birdhouse Tshirt" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4142_blowout_sunglasses" : { + "meta_description" : "Arnette Blowout Sunglasses - Zephyr Sports carries a complete line of Blowout Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Blowout Sun Glasses Online Today.", + "page_title" : "Arnette Blowout Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Blowout Sunglasses | Blowout Arnette Sunglasses | Arnette Blowout Sun Glasses" + }, + ".goggles.proto" : { + "meta_keywords" : "proto paintball goggles, proto axis paintball goggles, proto thermal goggles, thermal paintball goggles, proto axis pro, dye proto goggles", + "meta_description" : "Proto Paintball Goggles - Zephyr has Proto Axis paintball goggles in stock and ready to ship today. Free shipping on orders over $100. Zephyr is the largest west coast distributor for Proto thermal goggles.", + "zoovy:banner01" : "banners/paintball/headers/goggleaccessories_header001", + "banner01_link" : "/category/goggles.1goggle_accesories.proto_goggle_accesories/?sortby=!zoovy:prod_name", + "description" : "", + "banner1" : "banners/categories/prot_axis_timer_002", + "htmlvids" : "", + "head_title" : "Proto Paintball Goggles | Proto Axis Paintball Goggles | Proto Thermal Goggles", + "page_title" : "Buy Proto Paintball Goggles Online On Sale Now", + "sortby_var" : "Proto Goggle Type", + "prodlist_custom" : "&SORTBY=PRICE_DESC&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&", + "banner1_link" : "/category/001a_zephyr_paintball_sports_promotions_deals_sales.proto_goggles___free_game_timer/" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs.women_s_camelbak_trinity_hydration_packs" : {}, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_pro_preffered_baseball_gloves" : { + "head_title" : "Rawlings Pro Preferred Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".markers.kingmanspyder.semi_auto_spyder_packages" : {}, + ".apparel.jerseys.valken_paintball_jerseys.valken_fate_paintball_jerseys" : {}, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_phase_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon phase sunglasses", + "meta_description" : "Dragon Phase Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Phase Sunglasses" + }, + ".dye_i4_paintball_goggle_mask.o_-_airsoft_product_review.valken_tactical_slings" : {}, + ".casual_clothing.mens_clothing.beanies.es_beanies" : { + "meta_keywords" : "Es beanie,Es hat,Es beanies,Es caps,Es 686,Es headwear,Es cuff visor beanie,Es beanie hat,Es visor beanie,Es visor beanies", + "meta_description" : "Es Deanie - Surf style with Es Beanies available now at Zephyr Sports. Get your Es hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Es Beanies on Sale at Zephyr Today", + "head_title" : "Es Beanie | Es Hat | Es Beanies" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_blender_sunglasses" : {}, + ".shop_by_brand.raptors_airsoft" : {}, + ".barrels.freakbarrels.freakjrbarrels" : {}, + ".casual_clothing.mens_clothing.beanies.hurley_beanies" : { + "meta_keywords" : "Hurley beanie,Hurley hat,Hurley beanies,Hurley caps,Hurley 686,Hurley headwear,Hurley cuff visor beanie,Hurley beanie hat,Hurley visor beanie,Hurley visor beanies", + "meta_description" : "Hurley Deanie - Surf style with Hurley Beanies available now at Zephyr Sports. Get your Hurley hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Hurley Beanies on Sale at Zephyr Today", + "head_title" : "Hurley Beanie | Hurley Hat | Hurley Beanies" + }, + ".markerupgrades.macdev_upgrades" : {}, + ".harnessesbags.paintball_gear_bags.jt_usa_gear_bags___backpacks" : { + "meta_description" : "JT USA Paintball Gear Bags - Buy your JT USA Backpacks Online at Zephyr Paintball for Less today. Free Shipping on JT USA Bags Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy JT USA Paintball Gear Bags Online On Sale Now", + "head_title" : "JT USA Paintball Gear Bags | JT USA Backpacks | JT USA Bags" + }, + ".airsystems.regulators.empire_paintball_regulators" : { + "meta_description" : "Empire Regulator - Buy your Empire Paintball Regulator Online at Zephyr Paintball for Less today. Free Shipping on Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire Regulator Online On Sale Now", + "head_title" : "Empire Regulator | Empire Paintball Regulator" + }, + ".markers.pcspaintballguns" : {}, + ".casual_clothing.mens_clothing.shorts.fox_racing_shorts.fox_racing_slambozo_cargo_shorts" : {}, + ".casual_clothing.mens_clothing.hats.sullen_mma_hats" : { + "meta_keywords" : "Sullen Hats,Sullen caps,Sullen baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Sullen Hats - Zephyr carries a complete line of Sullen Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Sullen", + "page_title" : "Sullen Hats on Sale at Zephyr", + "head_title" : "Sullen Hats | Sullen Caps | Sullen Baseball Hats" + }, + "$all_packages" : {}, + ".casual_clothing.mens_clothing.beanies.empire_beanies" : { + "meta_keywords" : "Empire beanie,Empire hat,Empire beanies,Empire caps,Empire 686,Empire headwear,Empire cuff visor beanie,Empire beanie hat,Empire visor beanie,Empire visor beanies", + "meta_description" : "Empire Deanie - Surf style with Empire Beanies available now at Zephyr Sports. Get your Empire hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Empire Beanies on Sale at Zephyr Today", + "head_title" : "Empire Beanie | Empire Hat | Empire Beanies" + }, + ".1historical_products.paintball.paintball_gun_packages" : {}, + ".shop_by_brand.converse" : {}, + ".casual_clothing.mens_clothing.hats.element_hats" : { + "meta_keywords" : "Element Hats,Element caps,Element baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Element Hats - Zephyr carries a complete line of Element Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Element", + "page_title" : "Element Hats on Sale at Zephyr", + "head_title" : "Element Hats | Element Caps | Element Baseball Hats" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_laptop_bags" : { + "meta_keywords" : "Oakley laptop case, bag,oakley laptop case", + "meta_description" : "Oakley Laptop Bags - Need to carry your laptop in Style? Get your Oakley Computer bag today. Plenty of protection and that Oakley Style we all know an love", + "page_title" : "Oakley Computer & Laptop Bags FREE SHIPPING", + "head_title" : "Oakley Laptop Bags | Oakley Computer Bags" + }, + ".apparel.pants.dyepants.dye_tactical_paintball_pants" : {}, + ".barrels.autococker.12__autococker_paintball_barrels" : { + "meta_description" : "12 inch Autococker Paintball Barrels - Buy your 12\" Autococker Threaded Barrels Online at Zephyr Paintball for Less today. Free Shipping on Cocker Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 12 inch Autococker Paintball Barrels Online On Sale Now", + "head_title" : "12 inch Autococker Paintball Barrels | 12\" Autococker Threaded Barrels | Cocker Paintballs Barrels" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_2-1_blade_backpacks" : {}, + ".casual_clothing.mens_clothing.accessories.lanyards.c1rca_circa_lanyards" : {}, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.34" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.rayban_sidestreet_sunglasses" : { + "meta_keywords" : "Ray Ban Sidestreet Sunglasses ,Ray Bans,Ray Ban Sunglasses", + "meta_description" : "Ray Ban Sidestreet Sunglasses - Zephyr Sports carries a complete line of Sidestreet Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Sidestreet Sun Glasses Online Today.", + "page_title" : "Ray Ban Sidestreet Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Sidestreet Sunglasses | Sidestreet Ray Ban Sunglasses | RayBan Sidestreet Sun Glasses" + }, + ".black_friday_paintball_and_airsoft_deals.goggles___accessories" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_bsg_ii_sunglasses" : { + "meta_description" : "Electric BSG 2 Sunglasses - Zephyr Sports carries a complete line of Electric BSG 2 Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric BSG 2 Online Today.", + "page_title" : "Electric BSG 2 Sunglasses On Sale Free Shipping", + "head_title" : "Electric BSG 2 Sunglasses | Electric BSG 2 Sun Glasses | Sunglasses Electric BSG 2" + }, + ".airsoft.airsoft_guns.hfc_airsoft_guns" : { + "meta_description" : "HFC Airsoft Guns - Buy your HFC Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of HFC AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy HFC Airsoft Guns On Sale & Free Shipping", + "head_title" : "HFC Airsoft Guns | HFC Airsoft Rifles | HFC AEG" + }, + ".harnessesbags.backpacks.1_shop_by_bag_style.duffel_bags" : {}, + ".2clearance.clearance_upgrades.air_accessories" : { + "head_title" : "Sale Paintball Air Accessories | Clearance Paintball Air Accessories | Paintball Air Accessories Sale" + }, + ".apparel.gloves.v-tac_paintball_gloves" : { + "page_title" : "", + "head_title" : "Vlken Vtac Paintball Gloves | Gloves Vlken Vtac |Vlken Vtac Paintballing Gloves" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_alpine_explorer_hydration_packs" : {}, + ".casual_clothing.mens_clothing.wallets.neff_wallets" : { + "meta_description" : "Neff Wallets - Buy your Neff Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Neff Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Neff Wallets on Sale @ Zephyr Sports", + "head_title" : "Neff Wallets | Neff Mens Wallets | Neff Wallet" + }, + ".casual_clothing.z-sunglasses.revo_sunglasses.revo_thrive_sunglasses" : { + "meta_description" : "Revo Thrive Sunglasses - Zephyr Sports carries a complete line of Thrive Revo Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Revo Thrive Sun Glasses Online Today.", + "page_title" : "Revo Thrive Sunglasses On Sale Free Shipping", + "head_title" : "Revo Thrive Sunglasses | Thrive Revo Sunglasses Free Shipping | Buy Revo Thrive Sun Glasses" + }, + ".airsoft.tactical_airsoft_gear.camoflouge_pants" : { + "meta_keywords" : "camouflage pants,airsoft pants,military pants", + "meta_description" : "Camouflage Pants. These are high grade military style pants that will last through any scenario. Available in multiple camouflage patterns; wear the same uniform as the US army. These pants provide great cover from enemies and allow you to blend in to your environment. They are also extremely durable and include drawstrings for a comfortable feel. Outfitted with multiple pockets to allow you to carry all the items you need for lengthy games. Military grade BDUs.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markerupgrades.tippmann.tippmann_x7_upgrades.tippmann_x_7_sight_rails" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_m-frame_sunglasses.oakley_m_frame_hybrid_sunglasses" : { + "meta_description" : "Oakley M Frame Hybrid Sunglasses - Zephyr Sports carries a complete line of M Frame Hybrid Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley M Frame Hybrid Sun Glasses Online Today.", + "page_title" : "Oakley M Frame Hybrid Sunglasses On Sale Free Shipping", + "head_title" : "Oakley M Frame Hybrid Sunglasses | M Frame Hybrid Oakley Sunglasses | Oakley M Frame Hybrid Sun Glasses" + }, + ".markerupgrades.proto_slg_upgrades.proto_slg_feed_necks" : {}, + ".goggles.1goggle_accesories.valken" : {}, + ".safetygear.kneeelbowpads.sly_knee___elbow_pads" : { + "prodlist1_header" : "Sly Knee & Elbow Pads" + }, + ".barrels.tippmann98.14__tippmann_98_barrels" : { + "meta_description" : "14 inch Tippmann 98 Paintball Barrels - Buy your 14\" Custom 98 Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Tippmann 98 Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 14 inch Tippmann 98 Paintball Barrels Online On Sale Now", + "head_title" : "14 inch Tippmann 98 Paintball Barrels | 14\" Custom 98 Threaded Upgrade | Tippmann 98 Paintballs Barrels" + }, + ".casual_clothing.mens_clothing.sandals.reef_sandals" : { + "meta_description" : "Reef Sandals - Buy your Mens Reef Sandals At Zephyr Sports for Less Today! We carry a complete line of Reef Flip Flops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Reef Sandals On Sale at Zephyr Sports", + "head_title" : "Reef Sandals | Mens Reef Sandals | Reef Flip Flops" + }, + ".markerupgrades.proto_slg_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "meta_keywords" : "proto slg upgrade,proto slg,proto slg barrel,proto barrel,proto slg bolt,09 proto slg,proto upgrades,proto slg barrels", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.slg_grip_panel/", + "meta_description" : "Proto SLG Upgrades - Zephyr Stocks a complete line of Proto SLG parts to upgrade your marker including Proto SLG Barrels. Free shipping over $100 from the leading online paintball store", + "buttonname_01" : "", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "", + "add2_link" : "/category/markerupgrades.feednecks.matrix_feeds/", + "buttonname_02" : "", + "banner4" : "zephyr_buttons/grips_btn001", + "head_title" : "Proto SLG Upgrades | Proto SLG | Proto SLG Barrel", + "page_title" : "Buy Proto SLG Upgrades Online On Sale Now", + "add1_link" : "/category/barrels.autococker/" + }, + ".markerupgrades.tippmann.a5.tippmann_a5_expansion_chambers_and_grips" : { + "prodlist1_header" : "Tippmann A-5 Expansion Chambers & Grips" + }, + ".harnessesbags.paintballpodloaders" : { + "meta_keywords" : "Paintball Pod Loader, Paintball Pod Loaders, Paintball Loaders, Pod Loader, Paintball Pod, Paint Ball Pods, Paint Ball Loaders, Paintball Equipment, Paint Ball Equipment", + "meta_description" : "Paintball Pod Loader - Shop online for paintball pod loaders and other accessories online at ZephyrPaintball.com.", + "page_title" : "Buy Paintball Pod Loader Online On Sale Now", + "head_title" : "Paintball Pod Loader | Paintball Pod Loaders | Paintball Loaders", + "page_head" : "", + "description" : "It's ok to admit that you have spilled paint in the past. It's kind of hard to get the balls roll from the bag perfectly into a pod or hopper. Well, paint is way to expensive to have them spill all over the ground! The Paintball Caddy is the ultimate invention. It holds around 1,000 paintballs and is made out of a light medical grade plastic. It's fast, easy and well worth it" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches" : { + "page_title" : "Watches Ship Free On Sale @ Zephyr Sports", + "head_title" : "Watches | Mens Watches | Free Shipping Watches" + }, + ".apparel.gloves.paintball_gloves_by_size.5.x.large_paintball_gloves" : { + "page_title" : "", + "head_title" : "X|Large Paintball Gloves | X|Large Gloves for Paintball | X|Large Paintballing Gloves" + }, + ".airsoft.shop_by_brand.madbull_airsoft" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.thompson_aeg_electric_airsoft_guns" : { + "meta_keywords" : "airsoft thompson,airsoft thompson m1a1,m1a1 airsoft thompson,airsoft m1a1 thompson,thompson air soft,airsoft thompson guns,thompson airsoft guns,m1a1 thompson airsoft guns,airsoft m1 thompson,airsoft thompson smg,thompson m1 airsoft,electric airsoft thompson,thompson airsoft rifles,spring airsoft thompson,electric thompson airsoft guns,cheap thompson airsoft guns,cheap airsoft thompson,thompson m1a1 airsoft guns,thompson airsoft machine gun,airsoft thompson tommy gun,thompson machine gun airsoft,thompson airsoft cybergun,airsoft thompson submachine gun,airsoft thompson sub machine gun\n", + "meta_description" : "Airsoft Thompson M1A1 Airsoft Guns - Thompson Airsoft Guns on sale at Zephyr Sports with Free Shipping. Get your Airsoft Tommy Guns from your Airsoft Headquarters", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Thompson M1A1 | Thompson Airsoft Guns | Airsoft Tommy Guns" + }, + ".casual_clothing.mens_clothing.socks.hurley_socks" : { + "meta_description" : "Hurley Socks - Buy your Hurley Skate Socks At Zephyr Sports for Less Today! We carry a complete line of Hurley Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Hurley Mens Socks at Zephyr Sports", + "head_title" : "Hurley Socks | Hurley Skate Socks | Hurley Mens Socks" + }, + ".barrels.tippmann98.tippmann_98_sniper_barrels" : { + "meta_description" : "Tippmann 98 Flatline Barrels - Buy your Tippmann Custom 98 Tactical Barrels Online at Zephyr Paintball for Less today. Free Shipping on Sniper 98 Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann 98 Flatline Barrels Online On Sale Now", + "head_title" : "Tippmann 98 Flatline Barrels | Tippmann Custom 98 Tactical Barrels | Sniper 98 Barrels" + }, + ".shop_by_brand.camelbak" : { + "meta_keywords" : "camlelbak packs,camelback,camelbak hydration backpack,camelback bag,podium water bottle,podium chill,podium ice,elixir,mountain bike packs", + "top_html" : "", + "meta_description" : "Camelbak Hydration at Zephyr Sports - Your one stop shop for Camelbak Paks and camelbak bags. We carry camelbak posium bottles as well as as the accessories you will ever need", + "top_description2" : "=Rehydrate with Camelbak=\n\nWhat started as a thirsty EMT Bike racing innovator became the worlds largest portable hydration company. CamelBak Hydration, Camelbak Bags and Camelbak Bags offer a new way to keep your body hydrated and fueled to perform. Look at Zephyr's wide selection of Camelback hydration systems and you're sure to find a versatile and comfortable pack that will suit all your needs. ", + "page_title" : "Camelbak Hydration On Sale & Free Shipping", + "head_title" : "Camelbak Hydration | Camelbak Bags | Camelbak Packs", + "description" : "=Rehydrate with CamelBak=\n\n==Why CamelBak has your Back==\n\nCamelBak started with an EMT, a bike, and really hot weather. Michael Eidson, founder and CEO, decided one day he would do a century race in the summer heat of Wichita Falls, Texas. But he had one problem, he didn't want to carry four hundred water bottles on his back. So, being the resourceful person he was, he took an IV bag, an IV line, a tube sock and a clothing pin, stuck it all together, and BAM! the first CamelBak was born. After that he decided to start traveling from bike race to bike race and word got out about his new CamelBak system. The company was made, the product was sold and improved, and people were finally getting effectively hydrated. CamelBak now has hundreds of products ranging from jerseys with integrated hydration systems to BPA free water bottles. CamelBak has come a long way since that fateful day in Texas, but the concept has stayed the same. Keep the active lifestyle going by keeping people hydrated. CamelBak has a multitude of ways to do this with different lines of product with the highest quality, and cleanest materials known.\n\n\n==Water Beast Reservoir==\nCamelBak leveraged years of extensive research to develop the NEW products they have on the line today. Standard on all CamelBak military and industrial hydration systems, the newest polyurethane reservoir is 33% stronger and can handle almost anything you throw at it! \n\n==Low Infrared Reflective Materials==\nBlending in with the environment is critical to mission success! Several of CamelBak's systems will come with low infrared reflective (IRR) webbing, fabric and buckle technology. These materials are specifically designed to reduce infrared reflectivity in the near-IR light range (0.7 to 1.3 microns). CamelBak's unique fabric and hardware solution will provide soldiers with the best chance for evading detection on the high-tech battlefields of today and the future.\n\n==Hydroguard Anti-Microbial Technology==\nHydroGuard technology inhibits the growth of bacteria on reservoir and tube surfaces. Does not protect user from bacteria or other disease-causing organisms. Please wash reservoir after each use.\n\n==Leakproof System==\nCamelBak's patented HydroLock Valve provides secure, positive lever action flow shut-off when you're not drinking. Their NEW Water Beast Reservoir and CBR 4.0 materials are tough and reliable!\n\n==Hydrolink 2.0==\nHydorlink's modularity allows for a quick and easy transition of components as your mission or environment changes. Switch from the Water Beast Reservoir to Chem Bio Reservoir 4.0 quickly. Snap into most maks systems using the HydroLink Protective Mask Adapters. Add an In-Line MicroFilter when necessary. " + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_newton_watches" : { + "meta_keywords" : "Nixon watches,nixon newton watch,nixon watch,nixon analog watch,nixon digital watch,mens watches,mens watch,nixon,", + "meta_description" : "Nixon Watches - Brand New Nixon Newton Watch available now @ Zephyr! Nixon Newton Analog watches & Nixon Newton Digital Watches are available! Select colors are instock and ready to ship out! Pick up your Nixon watch today and never ask for the time again!", + "page_title" : "Nixon Newton Watch", + "head_title" : "Nixon Watches | Nixon Newton Watch | Nixon Watch" + }, + ".airsoft.airsoft_apparel.head_gear" : {}, + ".markerupgrades.us_army_upgrades.cyclone_feed_upgrades" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_discreet_women_s_sunglasses" : {}, + ".loaders.hopper_accesories" : {}, + ".markerupgrades.smartparts.ion_xe_upgrades.ion_xe_feednecks" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_g_seven_sunglasses" : { + "meta_description" : "Electric G Seven Sunglasses - Zephyr Sports carries a complete line of Electric G Seven Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric G Seven Online Today.", + "page_title" : "Electric G Seven Sunglasses On Sale Free Shipping", + "head_title" : "Electric G Seven Sunglasses | Electric G Seven Sun Glasses | Sunglasses Electric G Seven" + }, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns.tm15" : { + "meta_keywords" : "BT TM-15 Paintball Gun,BT TM 15 Paintball Marker,BT TM-15,BT paintball gear,paintball guns,BT Paintball Markers,BT Paintball Guns", + "meta_description" : "BT TM-15 Paintball Gun - Free Shipping on all BT TM 15 Paintball Markers. The BT TM-15 is ultimate choice for any woodsball or mil-sim paintball player. Loads of BT paintball gear to upgrade and customize your BT Paintball Marker. Get in the game today with BT Paintball Guns!", + "page_title" : "Buy BT TM-15 Paintball Guns Online On Sale Now", + "head_title" : "BT TM-15 Paintball Gun | BT TM 15 Paintball Marker | BT Paintball Guns", + "description" : "=Features:=\n\n* High Performance, Ultra Strong, Lightweight Magnesium Body.\n* Bolt Out Back Design for Easy Cleaning and Maintenance.\n* Modern Styling.\n* True Electropneumatic Operating System.\n* Shift-On-The-Fly, 4-Position Recreational Firing Mode Switch.\n* Multiple Firing Modes: Semi/PSP/NXL/Millennium.\n* Stealth Body Design Works in Conjunction with the Barrel to Reduce Sound Signature.\n* 14 Barrel with Sound Signature Reduction Porting.\n* Flip-Up Front and Rear Sights.\n* Clamping Feed Elbow.\n* Universal, Mini Style Barrel Threads.\n* Single-Finger Trigger (Double Trigger Kit Available).\n* Multiple Picatinny Rails Allow for Extra Accessories.\n* Quick-Change Battery in the Removable Magazine.\n* Collapsible/Adjustable Rear Stock.\n* Low Pressure Operation (200psi).\n* No External Hoses; Internal Airline Operation.\n" + }, + ".skateboard_gear.skateboard_decks.foundation_skateboard_decks" : { + "meta_keywords" : "Foundation skateboards,Foundation decks,Foundation Skate decks,cheap skate decks,Foundation skate boards,skateboarding equipment,skateboarding gear,Foundation skateboard deck,Trucks,wheel,bearings", + "meta_description" : "Foundation Skateboards - Zephyr Sports is your Foundation Skateboard Headquarters! Foundation skateboard Decks, Complete Foundation Skateboards, and much More! Choose from a grip of Foundation skate boards, Cheap Skate Decks, and others! Zephyr has all your Skateboarding equipment! Customize your Foundation Skateboard with the latest trucks, wheels and bearings all @ Zephyr!", + "page_title" : "Foundation Skateboard On Sale & Free Shipping", + "head_title" : "Foundation Skateboard | Skateboard Equipment | Foundation Decks" + }, + ".skateboard_gear.skateboard_decks.1search_by_size.8125__decks" : { + "meta_description" : "8.1100\" Skateboards Decks - Zephyr Sports carries a complete line of 8.1100 Skate Deck At the lowest prices on the web with free shipping and easy returns. Buy your Skate Deck 8.1100 Online Today.", + "page_title" : "8.1100\" Skateboards Decks On Sale Free Shipping", + "head_title" : "8.125\" Skateboards Decks |8.125 Skate Deck | Skate Deck 8.125" + }, + ".airsoft.airsoft_gun_magazines" : {}, + ".loaders.32degrees" : { + "description" : "" + }, + ".casual_clothing.womens_clothing.ladies_shorts.oakley_ladies_shorts" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_running_hydration_packs.camelbak_octane_18x_hydration_packs" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_private_ss_watches" : { + "meta_keywords" : "Nixon Watches,Nixon Private SS,Nixon SS Private Watch,Nixon,mens watch,Private SS Nixon Watch,SS Private Watch", + "meta_description" : "Nixon Watches - Brand New Nixon Private SS Watch Available Now @ Zephyr! Nixon Private SS Watches feature a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Private SS Watch", + "head_title" : "Nixon Private Watches | Nixon Private Watch | Nixon Private" + }, + ".airsystems.dropforwards.custom_products_drops___cradles" : { + "meta_description" : "Custom Products Drop Forward - Buy your Cp ASA Online at Zephyr Paintball for Less today. Free Shipping on CP Drops Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Custom Products Drop Forward Online On Sale Now", + "head_title" : "Custom Products Drop Forward | Cp ASA | CP Drops" + }, + ".goggles.1goggle_accesories.km_straps" : { + "meta_description" : "KM Goggle Straps - Buy your Paintball Masks Straps Online at Zephyr Paintball for Less today. Free Shipping on MK Paintball Strap Trust Zephyr for all your Paintball Needs", + "top_description" : "KM goggle straps may not fit nor be used in conjunction with all the goggles in the paintball industry. KM's 9\" and 7\" goggle straps are assembled with butterfly ends. You must insert butterfly ends of the straps into the slot where the existing straps are installed. Butterfly ends must be completely inserted through the slots for proper use. Physical abuse to or misuse of the product may cause malfunction and/or injury. Knowledge of the proper use of this product is a pre-requisite to purchase and resale. Paintball is an active sport and goggles must be worn at all times during play.", + "page_title" : "Buy KM Goggle Straps Online On Sale Now", + "head_title" : "KM Goggle Straps | Paintball Masks Straps | MK Paintball Strap" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_highball_watches" : { + "meta_keywords" : "Nixon watches,nixon Highball watch,nixon watch,nixon Highball chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Highball Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Highball Chrono Watches", + "head_title" : "Nixon Highball Watches | Nixon Highball Chrono Watch | Nixon 5130" + }, + ".airsoft.airsoft_spare_magazines." : {}, + ".casual_clothing.mens_clothing.tshirts.shorty_s_t-shirts" : { + "meta_description" : "Shortys Shirts - Buy your Shortys T-Shirts At Zephyr Sports for Less Today! We carry a complete line of Shorty's Skate Clothing at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Shortys Shirts Now! On Sale & Free Shipping", + "head_title" : "Shortys Shirts | Shortys T-Shirts | Shorty's Skate Clothing" + }, + ".paintball.3_paintball_gun_packages.starter_packs" : {}, + ".proto_rail_paintball_guns.proto_rail_paintball_gun" : {}, + ".casual_clothing.mens_clothing.shoes.i_path_shoes" : { + "meta_keywords" : "ipath skate,ipath shoe,ipath hemp,ipath hemp shoes,ipath skate shoe,rasta ipath,mens ipath,ipath cat,ipath cats shoes,ipath reed shoes,cheap ipath,ipaths,ipath footwear,ipath skateboarding,cheap ipath shoes,ipath cats hemp,ipath cats suede,ipath cat shoes,ipath skateboard,ipath sneakers,ipath reed shoe,i path shoes,i path shoe,i path skate,i path skate shoes,i path footwear,i path rasta shoes", + "meta_description" : "Ipath Skate Shoes - Huge selection of Ipath Help Shoe available online at Zephyr Sports. Always the best price, Always free shipping on Shoes. Buy your I Path Shoes online Now!", + "page_title" : "I Path Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Ipath Skate Shoes | Ipath Hemp Shoe | I Path Cats Shoes" + }, + ".casual_clothing.mens_clothing.beanies.fallen_beanies" : { + "meta_keywords" : "Fallen beanie,Fallen hat,Fallen beanies,Fallen caps,Fallen 686,Fallen headwear,Fallen cuff visor beanie,Fallen beanie hat,Fallen visor beanie,Fallen visor beanies", + "meta_description" : "Fallen Deanie - Surf style with Fallen Beanies available now at Zephyr Sports. Get your Fallen hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Fallen Beanies on Sale at Zephyr Today", + "head_title" : "Fallen Beanie | Fallen Hat | Fallen Beanies" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.famas_aeg_airsoft_magazines" : {}, + ".shop_by_brand.j_j_performance" : { + "top_description2" : "=J and J Barrels, shoot it straight!=\n\nTired of curve and balls dropping out of your barrel? Tired of ugly colors and poor design? Do you want a barrel that is fully functional, 100% American and built to perform and last? If yes, J and J barrels are for you. With J and J ceramic barrels, these guys have made a name for themselves. J and J Ceramic make sthe best Ceramic barrels period. Go ahead and get you J and J barrel today and you'll see what all the buzz is about. ", + "head_title" : "J and J barrel | J and J Ceramic | J and J ceramic barrels", + "description" : "=J and J barrels, shoot it straight!=\n\n==Ceramic series==\nThese barrels are made form 6061 T6 aluminum then CNC machined to the highest quality standards in the industry. The ceramic coating and teflon impregnation reduces the friction rate to a minimum, while inducing a self cleaning method!!!\n\n==S2 Barrel==\nJ&J Performance has redesigned the lock and bore size of the s2 for 2011. The new s2 has a lower sound level and a performance unmatched by any other barrel manufacturer.\n\n\n" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.camelbak_luxe_hydration_packs" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.vegas_force_airsoft_guns" : { + "meta_description" : "Vega Force Airsoft Guns - Buy your Vega Force AEG Online At Zephyr Sports for Less Today! We carry a complete line of Vega Force Rifle at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Vega Force Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Vega Force Airsoft Guns | Vega Force AEG | Vega Force Rifle" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_g_six_sunglasses" : { + "meta_description" : "Electric G Six Sunglasses - Zephyr Sports carries a complete line of Electric G Six Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric G Six Online Today.", + "page_title" : "Electric G Six Sunglasses On Sale Free Shipping", + "head_title" : "Electric G Six Sunglasses | Electric G Six Sun Glasses | Sunglasses Electric G Six" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses" : { + "meta_keywords" : "maui sunglasses,jim maui sunglasses,sunglasses maui jim,maui jim sunglasses,jim maui sunglass,maui sun glasses,designer sunglasses,polarized sunglasses,\r ", + "meta_description" : "Maui Jim Sunglasses - All the top style of Jim Maui Sunglasses with free Shipping from Zephyr Get your Maui Sunglasses today!", + "page_title" : "Maui Jim Sunglasses with Free Shipping", + "head_title" : "Maui Jim Sunglasses | Jim Maui Sunglasses | Maui Sunglasses" + }, + ".casual_clothing.mens_clothing.jackets.1_search_by_size.3-large" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_laptop_bags_and_sleeves" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_variable_power_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".goggles.1goggle_accesories.sly_paintball_goggle_accessories" : { + "meta_description" : "Sly Profit Lens - Buy your Sly Profit Thermal Lens Online at Zephyr Paintball for Less today. Free Shipping on Sly Profit Replacement Lens Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Sly Profit Lens Online On Sale Now", + "head_title" : "Sly Profit Lens | Sly Profit Thermal Lens | Sly Profit Replacement Lens" + }, + ".casual_clothing.mens_clothing.tshirts.alpinestars_t_shirts" : { + "meta_keywords" : "Alpinestars T Shirts,Alpinestars shirts,free shipping,Alpinestars TShirt", + "meta_description" : "Alpinestars T Shirts - Zephyr carries a complete line of Alpinestars Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Alpinestars T Shirts at Zephyr", + "head_title" : "Alpinestars T Shirts | AlpineStars Shirts | Alpine Stars TShirt" + }, + ".airsystems.nipplefillcovers" : { + "meta_description" : "Paintball Fill Nipple Cover - Buy your Nipple Fill Cover Online at Zephyr Paintball for Less today. Free Shipping on Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Fill Nipple Cover Online On Sale Now", + "head_title" : "Paintball Fill Nipple Cover | Nipple Fill Cover" + }, + ".maddog.harnesses" : {}, + ".markerupgrades.proto_slg_upgrades.proto_slg_bolts___internals" : {}, + ".paintball.paintball_goggles.hk_army_klr_paintball_goggles" : { + "htmlvids" : "", + "top_description2" : "== HK Army KLR Paintball Mask ==\n\nWith over 100 years in combined paintball experience, the HK design team has created a Goggle System that is both Safe and Stylish! Composed of a robust blend of thermoplastic elastomer, the design of the KLR facemask protects critical areas of the user, while still promoting supreme breathability and freedom of movement. Featuring three co-molded HDPE inserts, the KLR goggle system can be customized to fit any customer's aesthetic desires.\n\n\n= Features: =\n* Supreme Breathability\n* Pivot Lock System\n* 3D Memory Foam\n* Ear Piece Protection\n* Custom Straps\n* KLR PURE Lens System", + "zoovy:banner01" : "banners/paintball/headers/hk_army_klr_goggles_header.jpg", + "description" : "= PVT Lock System =\n\nThe HK Army KLR Goggle is the first to incorporate a lens retention system that is innovative, safe, and interchangeable. The patent-pending PVT Lock system allows the user to change lenses in mere seconds--the days of gouging your mask and lens with a screwdriver before a game is over. Featuring a large, swiveling hinge system, the PVT Lock system enables users to quickly change their lens and overall appearance of their goggle with the flick of a buckle. Offered in a variety of colors and finishes, users can collect and interchange each side of their PVT Lock to create a look that is unique to them.\n\n\n= 3D Memory Foam =\n\nBonded to the KLR frame is HK's new 3D foam--featuring tri-layer, variable density foam technology that creates unparalleled comfort. The base layer is high-density SBR memory foam that absorbs face impacts and braces against the goggle frame, followed by open-cell EVA foam that is ultra-soft and conforms to the facial profile of the wearer. These high-tech foams are then laminated in a velvet microfiber liner that both absorbs sweat from the face and insulates against heat entering the ocular cavity of the frame. \n\n\n\n= Ear Piece Protection =\n\nThe KLR Goggle offers a super high-density compressed EVA foam earpiece that is protective and low-profile. The KLR soft-ear protects the outer and inner ear from impact and abrasion, while maintaining a low profile.\n\n\n= Custom Straps =\n\nFeaturing a high-resolution microstitched jacquard strap, the KLR is an industry-first in offering microinjected TPR accent patches for users to further customize their on-field look. Coated with anti-slip silicone on the rear of the strap, the KLR strap is guaranteed against fraying and distortion.\n\n\n= Lens Options =\n\nThe KLR PURE Lens System is composed of virgin optical-grade GE polycarbonate--inherently UVA \\ UVB and IR shielded, every KLR lens shields your eyes from dangerous sunlight in every playing condition. The interior thermal lens is applied with 3M Foam Sealant, trapping a layer of cool barrier of insulating air, eliminating condensation and encouraging evaporative cooling." + }, + ".casual_clothing.mens_clothing.tshirts.c1rca_circa_t_shirts" : { + "meta_keywords" : "Circa T Shirts,Circa shirts,free shipping,Circa TShirt", + "meta_description" : "Circa T Shirts - Zephyr carries a complete line of Circa Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Circa T Shirts at Zephyr", + "head_title" : "Circa T Shirts | Circa Shirts |Circa TShirt" + }, + ".barrels.smartparts.14__impulse___ion_paintball_barrels" : { + "meta_description" : "14 inch Impulse Paintball Barrels - Buy your 14\" Impulse Threaded Barrels Online at Zephyr Paintball for Less today. Free Shipping on Ion Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 14 inch Impulse Paintball Barrels Online On Sale Now", + "head_title" : "14 inch Impulse Paintball Barrels | 14\" Impulse Threaded Barrels | Ion Paintballs Barrels" + }, + ".casual_clothing.womens_clothing.ladies_hats.oakley_ladies_hats" : {}, + ".loaders.nxe_paintball_loaders" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.spyder_fenix_paintball_guns" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_ripcord_backpacks" : { + "meta_description" : "Oakley Ripcord Backpacks - Oakley Ripcord Bags are perfect for school, With a media pocket, headphone port and Sunglass pocket.", + "page_title" : "Oakley Ripcord Backpacks Free Shipping", + "head_title" : "Oakley Ripcord Backpacks | Oakley Ripcord Bag | Ripcord Oakley Backpack" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.echo_1_gas_airsoft_guns" : {}, + ".casual_clothing.womens_clothing.ladies_shirts.1-search_by_size.1-x-small" : {}, + ".markerupgrades.bob_long_upgrades.bob_long_upgrade_boards" : { + "meta_description" : "Bob Long Upgrade Boards - Buy your Marq Victory Virtue Boards Online at Zephyr Paintball for Less today. Free Shipping on Intimidator Ramping Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Bob Long Upgrade Boards Online On Sale Now", + "head_title" : "Bob Long Upgrade Boards | Marq Victory Virtue Boards | Intimidator Ramping Boards" + }, + ".casual_clothing.mens_clothing.sweatshirts.infamous_paintball" : {}, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_big_risky_sunglasses" : { + "meta_description" : "Hoven Big Risky Sunglasses - Zephyr Sports carries a complete line of Hoven Big Risky Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Big Risky Online Today.", + "page_title" : "Hoven Big Risky Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Big Risky Sunglasses | Hoven Big Risky Sun Glasses | Sunglasses Hoven Big Risky" + }, + ".airsoft.airsoft_spare_magazines.kwa.rifle_mags" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_duffel_bags" : { + "meta_description" : "Oakley Duffel Bags - Buy your Duffle BagsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Duffel Bags On Sale & Free Shipping", + "head_title" : "Oakley Duffel Bags | Duffle Bags" + }, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases.defcon_tactical_gear" : {}, + ".harnessesbags.backpacks.ogio_backpacks.ogio_skateboard_backpacks" : { + "meta_description" : "OGIO Skate Packs - Buy your OGIO Skateboard Backpacks At Zephyr Sports for Less Today! We carry a complete line of OGIO Skate Bags at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "OGIO Skateboard Backpacks Ship Free @ Zephyr Sports ", + "head_title" : "OGIO Skate Packs | OGIO Skateboard Backpacks | OGIO Skate Bags" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.matix_youth_t_shirts" : {}, + ".3packagespecials.planet_eclipse_package_specials.eclipse_etha_package_specials" : { + "top_html_focus" : "", + "head_title" : "Eclipse Etha Paintball Packages | Eclipse Etha Paintball Gun Packages" + }, + ".casual_clothing.youth_clothing.youth_beanies" : {}, + ".paintball" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.airsoft_spring_pistols" : { + "meta_keywords" : "Airsoft Spring Pistols,Airsoft Spring Revolver,Airsoft Spring Colt,Smith and Wesson, Firepower,classic army,Desert Eagle,Sig Sauer,Colt,Beretta,cheap airsoft guns,Spring Powered airsoft guns,", + "meta_description" : "Zephyr Sports carries a wide variety of Airsoft Spring Pistols! These spring powered Airsoft replicas include: guns by Smith and Wesson, Firepower, Classic Army, Desert Eagle, Sig Sauer, Colt, Beretta and more! For cheap airsoft guns, choose Zephyr! Spring Powered airsoft guns are low impact toy guns that are sure to entertain you and your friends!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Spring Pistols | Airsoft Spring Revolver | Airsoft Spring Colt", + "description" : "" + }, + "$maddog_new_items" : {}, + ".apparel.shoes.vox_shoes" : {}, + ".markers.dye_matrix_paintball_guns.dye_dm12_paintball_guns" : { + "meta_keywords" : "dye dm12,dm 12, dm12 paintball gun, dm 12 paintball guns, dm12 paintball marker, dye matrix", + "meta_description" : "Dye Dm12 Paintball Guns - Dm12 paintball markers are the leader in pro grade tournament paintball guns. Get your Dye Dm 12 at Zephyr Paintball today with free shipping.", + "top_description" : "The Dye DM12 is here. The Dye DM12 paintball gun is the current version of Dye DM line of paintball guns. The Dye DM12 is used by the top professional paintball teams including the Ironmen and Tampa Bay Damage. If your looking for tournament level performance trusted by pros to shoot the most fragile paint without breaks quietly and with insane accuracy, the Dye Dm12 is for you. ", + "zoovy:banner01" : "banners/paintball/newsletters/3_dm_12_price_drop_newsletter.jpg", + "description" : "The Dye DM12 now has an easy bolt out the back design as well as a cool viewing window to keep you and your friends entertained as you fire. The orings in the DM12 o-rings are color coded for easy maintenance and replacement. Oh yeah the Dye DM12 is more than just gimmicks, you get rock solid performance and the ability to shoot insanely brittle paintballs without breaks. The Dye DM12 includes a 14\" Dye Ultralight barrel for the best accuracy money can buy. Once again Dye uses the Ultralight 45 frame on the DM12 for a great feel to your gun. The Dm12 uses an autococker threaded barrel and a DM threaded feedneck, but I'm not sure how you could upgrade from the high quality parts included by Dye. Other features of the Dm12 include the Hyper 3 regulator, reach triigger system and quick release bolt. Basically the DM12 is fully upgraded out of the box as you'd expect for the price you pay.", + "htmlvids" : "", + "page_title" : "Dye Dm12 Paintball Guns Shipp Free at Zephyr", + "head_title" : "Dye DM12 Paintball Guns | DM12 Paintball Markers | Dye DM 12" + }, + ".1newitems.2009_products" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.nixon_headphones.nixon_rpm_headphones" : { + "head_title" : "Nixon RPM Headphones | RPM Nixon Head Phones | Nixon RPM Headphone" + }, + ".harnessesbags.packs___harnesses.invert_paintball_pod_packs" : { + "meta_description" : "Invert Paintball Harnesses - Buy your Invert Pod Packs Online at Zephyr Paintball for Less today. Free Shipping on Invert Pod Belts Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert Paintball Harnesses Online On Sale Now", + "head_title" : "Invert Paintball Harnesses | Invert Pod Packs | Invert Pod Belts" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.x36_aeg_airsoft_magazines" : {}, + ".casual_clothing.womens_clothing.ladies_belts" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.c1rca_pants_and_jeans" : { + "meta_description" : "Circa Pants - Buy your Circa Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Circa Pants & Jeans Ship Free", + "head_title" : "Circa Pants | Circa Jeans" + }, + ".goggles.invert_paintball_goggles" : { + "meta_keywords" : "invert paintball goggles, invert avatar paintball mask, invert thermal goggles", + "meta_description" : "Invert Paintball Goggles - Zephyr Carries a complete line of Invert Masks including the Invert Avatar Paintball Mask. ", + "page_title" : "Buy Invert Paintball Goggles Online On Sale Now", + "head_title" : "Invert Paintball Goggles | Invert Avatar Paintball Mask | Invert Thermal Goggles", + "banner01_link" : "/category/goggles.1goggle_accesories.vents_goggle_accesories/?sortby=!zoovy:base_price", + "zoovy:banner01" : "banners/paintball/headers/goggleaccessories_header001" + }, + ".casual_clothing.mens_clothing.rash_guards.oakley_rash_guards" : { + "meta_description" : "Oakley Rash Guards - Buy your Oakley Surf ShirtsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Oakley Rash Guards at Zephyr Sports", + "head_title" : "Oakley Rash Guards | Oakley Surf Shirts" + }, + ".barrels.barrels_by_manufacturer.azodin_paintball_barrels" : {}, + ".paintballs.wgp_paintballs" : {}, + ".skateboard_gear.skateboard_decks.enjoi_skateboard_decks" : { + "meta_description" : "Enjoi Skateboard Decks - Buy your Enjoi Decks At Zephyr Sports for Less Today! We carry a complete line of Enjoi Skate Board Decks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Enjoi Skateboard Decks On Sale & Free Shipping", + "head_title" : "Enjoi Skateboard Decks | Enjoi Decks | Enjoi Skate Board Decks" + }, + ".harnessesbags.packs___harnesses.paintball_mafia_harnesses" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_highball_watches" : {}, + ".markerupgrades.rampingchipsboards.advantage_pb.virtue_laser_eye_upgrades" : { + "meta_description" : "Virtue Eyes - Buy your Virtue Laser Eyes Online at Zephyr Paintball for Less today. Free Shipping on Laser Eye Upgrades Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Virtue Eyes Online On Sale Now", + "head_title" : "Virtue Eyes | Virtue Laser Eyes | Laser Eye Upgrades" + }, + ".skateboard_gear.skateboard_decks.birdhouse_skateboard_decks" : { + "meta_description" : "Birdhouse Skate Decks - Buy your Birdhouse Skateboards At Zephyr Sports for Less Today! We carry a complete line of Birdhouse Decks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Birdhouse Skate Decks On Sale & Free Shipping", + "head_title" : "Birdhouse Skate Decks | Birdhouse Skateboards | Birdhouse Decks" + }, + ".2clearance.1-black_friday.paintball" : { + "head_title" : "Black Friday Paintball Sale | Paintball Black Friday" + }, + ".goggles.jt_usa_goggles.jt_spectra_series_goggles" : { + "meta_description" : "JT Spectra Paintball Goggles - Buy your JT Spectra Paintball Masks Online at Zephyr Paintball for Less today. Free Shipping on JT Spectra Paintball Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy JT Spectra Paintball Goggles Online On Sale Now", + "head_title" : "JT Spectra Paintball Goggles | JT Spectra Paintball Masks | JT Spectra Paintball" + }, + ".dye_i4_paintball_goggle_mask.o_-_airsoft_product_review.dye_tactical_vests" : {}, + ".harnessesbags.backpacks.empire_backpacks" : { + "meta_keywords" : "Empire Backpacks,sport backpacks,school backpacks,back packs", + "meta_description" : "Empire Backpack - Put the whole world on your Back with these Empire Backpacks! Sport Backpacks ready to lug around all your stuff! Designed to withstand the toughest of travels! Empire Back packs aren't just for Paintball! Backpacks for School, work, and play! Zephyr Sports", + "page_title" : "Empire Backpacks On Sale & Free Shipping", + "head_title" : "Empire Backpacks | Sports Backpacks" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_radar_path_sunglasses" : { + "meta_description" : "Oakley Radar Path Sunglasses - Buy your Radar Path Oakley Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Oakley Radar Path at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Radar Path Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Radar Path Sunglasses | Radar Path Oakley Sunglasses | Oakley Radar Path" + }, + ".loaders.viewloader" : { + "banner2" : "banners/categories/vlocity_free_shell_header", + "meta_keywords" : "viewloader loaders, viewloader force loaders, viewloader vlocity paintball loader, vlocity jr, eye force loader, evolution 3 loader, velocity paintball hoppers, velocity loaders, vl hoppers, vl paintball loaders", + "meta_description" : "Viewloader Loaders - Viewloader makes a variety of paintball loaders from the entry level Viewloader Force loaders to the tournament quality Viewloader Vlocity Paintball Loader. Starting at less than 430 Zephyr has the complete line of loaders to get you in the game.", + "description" : "", + "banner2_link" : "/category/001a_zephyr_paintball_sports_promotions_deals_sales.viewloader_vlocity___free_shell/", + "banner1" : "images/site_specific/click_here/clickhere_vlocity_accessories_btn001.png", + "page_title" : "Buy Viewloader Loaders Online On Sale Now", + "head_title" : "Viewloader Loaders | Viewloader Force Loaders | Viewloader Vlocity Paintball Loader", + "banner1_link" : "/category/loaders.hopper_accesories.viewloader_accesories/" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_supertide_watches" : {}, + ".markerupgrades.tippmann.tippmann_cronus_paintball_gun_upgrades" : {}, + ".markers.azodin.azodin_zenith_paintball_guns" : { + "meta_description" : "Azodin Zenith Paintball Guns - Buy your Azodin Zenith Painball Markers Online at Zephyr Paintball for Less today. Free Shipping on Azodin Zenith Pump Trust Zephyr for all your Paintball Needs", + "top_description2" : "== Azodin Zenith Paintball Marker ==\n\nThe ZII is the pinnacle of design and performance for the stack tube blow-back platform.\n\n\nWhen the ZII was developed, we focused our efforts on improving its operation and performance.\nThe result was the creation of the Zen OLED board and the ZeRO-D system.\n\n\nThe Zen OLED board is the conscious of the ZII and is the first user programmable board on an\nAzodin marker. The board features new logic which helps to prolong battery life and decrease\nvoltage requirements.\n\n\nThe ZeRO-D system is the soul of the ZII and threads directly onto the body. The new design\nimproves the durability of the ZeRO Housing and it allows for quicker maintenance of the ZeRO-D\nSystem. When paired with the Mass Flow Valve, the ZerRO-D lowers the operating pressure of the ZII.\n\n\nThe ZII showcases Azodins next generation of markers and establishes new performance\nbenchmarks for the STBB Platform.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.azodin_paintball_packages/", + "zoovy:banner02" : "banners/paintball/slideshow/azodin_zii_paintball_markers_slideshow_template.jpg", + "page_title" : "Buy Azodin Zenith Paintball Guns Online On Sale Now", + "head_title" : "Azodin Zenith Paintball Guns | Azodin Zenith Painball Markers | Azodin Zenith Pump" + }, + ".scenarioupgrades.tactical_vests.ncstar_tactical_vests___plate_carriers" : {}, + ".dye_i4_paintball_goggle_mask.dye_i4_paintball_masks" : {}, + ".casual_clothing.mens_clothing.shorts.es_shorts" : { + "meta_description" : "ES Shorts - Zephyr stocks a complete line of ES Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your ES needs. ", + "page_title" : "ES Shorts with Free Shipping at Zephyr", + "head_title" : "ES Shorts | ES Board Shorts" + }, + ".casual_clothing.mens_clothing.wallets.dakine_wallets" : { + "meta_description" : "Dakine Wallets - Buy your Dakine Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Dakine Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Wallets on Sale @ Zephyr Sports", + "head_title" : "Dakine Wallets | Dakine Mens Wallets | Dakine Wallet" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_inner_barrels.classic_army_upgradbarrels" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Classic Army Upgrade | Classic Army Barrel | Classic Army inner barrel" + }, + ".skateboard_gear.skateboard_decks.1search_by_size.775__decks" : { + "meta_description" : "7.75\" Skateboards Decks - Zephyr Sports carries a complete line of 7.75 Skate Deck At the lowest prices on the web with free shipping and easy returns. Buy your Skate Deck 7.75 Online Today.", + "page_title" : "7.75\" Skateboards Decks On Sale Free Shipping", + "head_title" : "7.75\" Skateboards Decks |7.75 Skate Deck | Skate Deck 7.75" + }, + ".casual_clothing.mens_clothing.sandals.oakley_sandals" : { + "meta_keywords" : "Oakley sandals,oakley flip flops,oakley mens sandals,oakley super coil", + "meta_description" : "Oakley Sandals - Get your Oakley Flip Flop from Zephyr Today. Free Shipping, Easy returns why shop anywhere else for your Oakley Mens Sandals", + "page_title" : "Oakley Sandals Ship Free ", + "head_title" : "Oakley Sandals | Oakley Flip Flops | Oakley Mens Sandals" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_mutiny_sunglasses" : { + "meta_description" : "Electric Mutiny Sunglasses - Zephyr Sports carries a complete line of Electric Mutiny Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Mutiny Online Today.", + "page_title" : "Electric Mutiny Sunglasses On Sale Free Shipping", + "head_title" : "Electric Mutiny Sunglasses | Electric Mutiny Sun Glasses | Sunglasses Electric Mutiny" + }, + ".scenarioupgrades.tactical_vests" : { + "meta_keywords" : "tactical paintball vest,paintball vests,scenario,woodsball,camelbak,paintball hydration vest,dye tactical,nc star,bt battle test,bt battle vest,tippmann vest", + "meta_description" : "Tactical Paintball Vests - Get ready for your next big scenario game with a paintball vest from Zephyr Paintball. Hold pods, tanks, hydration bladder and much more. Paintball Vests on sale now.", + "top_description" : "Woodsball a bit more up your alley? We carry a complete line of Tactical paintball vests for you. A good paintball vest will carry your pods and a tank as well as providing protection and a few extra bounces. Many of the paintball vests we carry will also hold a 2nd tank,12g co2 cartridges, hydration bladder, radio as well as your tools. Never know when your gonna need em. ", + "page_title" : "Tactical Paintball Vests on Sale", + "head_title" : "Tactical Paintball Vests | Paintball Vest Sale", + "description" : "Looking for the most customizable paintball vest possible? Try a Molle vest. Molle paintball vests allow you to choose the attachments you want. Need an extra grenade pouch? Map pocket? It's all up to you when you choose molle." + }, + ".harnessesbags.backpacks.nixon_bags_and_backpacks" : { + "meta_description" : "Nixon Backpacks - Buy your Nixon Bags At Zephyr Sports for Less Today! We carry a complete line of Nixon Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Backpacks & Bags Ship Free ", + "head_title" : "Nixon Backpacks | Nixon Bags |Nixon Luggage" + }, + ".casual_clothing.mens_clothing.sweatshirts.alien_workshop_sweatshirts" : { + "meta_description" : "Alien Workshop Sweatshirts - Buy your Alien Workshop Hoodies At Zephyr Sports for Less Today! We carry a complete line of Alien Workshop Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Alien Workshop Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Alien Workshop Sweatshirts | Alien Workshop Hoodies | Alien Workshop Hoody" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.remington_spring_airsoft_guns" : { + "meta_description" : "Remington Airsoft Guns - Buy your Remington Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Remington Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Remington Airsoft Guns On Sale & Free Shipping", + "head_title" : "Remington Airsoft Guns | Remington Airsoft Rifles | Remington Spring Airsoft Guns" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.1_search_by_size.4_x-large" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.king_arms_airsoft_guns" : { + "head_title" : "King Arms Airsoft Guns | King Arms Airsoft AEG | King Arms Airsoft Rifle" + }, + ".maddog.tactical_gear" : {}, + ".casual_clothing.mens_clothing.belts.circa_belts" : { + "meta_description" : "Circa Belts - Buy your Circa Mens Belts At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Circa BELTS @ Zephyr Sports", + "head_title" : "Circa Belts | Circa Mens Belts | Belts Circa" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.cyma_airsoft_guns" : { + "head_title" : "Cyma Airsoft Guns | Cyma Airsoft Rifles | Cyma AEG" + }, + ".apparel.jerseys.empire_paintball_jerseys.empire_tz_paintball_jerseys" : {}, + ".casual_clothing.z_shoes_and_footwear.es_shoes" : {}, + ".markerupgrades.kingmanspyder.spyder_upgrade_boards" : { + "meta_description" : "Spyder Board - Buy your Spyder Virtue Board Online at Zephyr Paintball for Less today. Free Shipping on Spyder Upgrade Boards Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Board Online On Sale Now", + "head_title" : "Spyder Board | Spyder Virtue Board |Spyder Upgrade Boards" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.action_sport_games" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_womens_backpacks_and_bags" : {}, + ".casual_clothing.mens_clothing.shirts.zoo_york_shirts" : { + "meta_description" : "Zoo York Flannel Shirts - Buy your Zoo York Polo Shirts Online At Zephyr Sports for Less Today! We carry a complete line of Zoo York Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Zoo York Shirts & Flannels Ship Free", + "head_title" : "Zoo York Flannel Shirts | Zoo York Polo Shirts | Zoo York Shirts" + }, + ".airsoft.buyers_guide.airsoft_batteries" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Buyers Guide - Airsoft Batteries" + }, + ".markerupgrades.us_army_upgrades.trigger_and_electronics_upgrades" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.proto_rail_paintball_guns" : {}, + ".scenarioupgrades.tactical_vests.full_clip_tactical_vests" : {}, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_cinch_sunglasses" : {}, + ".ybulk_buys" : { + "meta_keywords" : "bulk paintballs, bulk co2 tanks, paintballs in bulk, cheap bulk paintballs, 10 cases of paintballs, volume, bulk, volume buys", + "banner1" : "banners/09_headers/main_categories/volume_buys_001", + "meta_description" : "Looking to buy a lot of paint or co2? Well then, you have come to right place. We offer discounts on bulk buys from air tanks, paint and much more!", + "page_title" : "Bulk Paintballs - Bulk CO2 Tanks - Volume Buys", + "prodlist1_header" : "Volume Buy Product Listings", + "page_head" : "", + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/bigvolume_banner.jpg\"" + }, + ".skateboard_gear.complete_skateboards.lax" : { + "meta_description" : "LAX Skateboards - Zephyr Sports carries a complete line of LAX Complete Skateboards At the lowest prices on the web with free shipping and easy returns. Buy your Skateboards LAX Longboards Online Today.", + "page_title" : "LAX Skateboards On Sale Free Shipping", + "head_title" : "LAX Skateboards | LAX Complete Skateboards | Skateboards LAX Longboards" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_platform_watches" : { + "meta_keywords" : "Nixon Watches,nixon platform watch,nixon watch,nixon platform,nixon,mens watches,", + "meta_description" : "Nixon Watches - Brand new Nixon Platform Watch Available now @ Zephyr! Nixon Platform Watches feature slick styling and top quality functions. Search the shop, select a Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Platform Watch", + "head_title" : "Nixon Platform Watches | Nixon Platform Watch | Nixon Platform" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_smg" : { + "head_title" : "KWA SMG Airsoft Guns | KWA Sub Machine Gun" + }, + ".zdownloads" : { + "wall02_link" : "http://static.zoovy.com/img/zephyrsports/-/downloads/wallpaper/breakout/", + "linkto_05_txt" : "", + "linkto_01_txt" : "", + "linkto_02_txt" : "", + "wall01_thumb" : "downloads/wallpaper/cmyk/wallpaper_thumb_cmyk", + "linkto_04_txt" : "", + "linkto_02" : "banners/link_backs/zephyr_sports_125x125_001.jpg", + "wall01" : "downloads/wallpaper/cmyk/wallpaper_cmyk", + "logo_pack_link" : "http://static.zoovy.com/merchant/zephyrsports/09_logo_pack.zip", + "linkto_04" : "banners/link_backs/zephyr_sports_392x72_001.jpg", + "linkto_05" : "banners/link_backs/zephyr_sports_768x90_thumb.jpg", + "wall02" : "downloads/wallpaper/breakout/wallpaper_breakout.jpg", + "linkto_01" : "banners/link_backs/zephyr_sports_120x240_001", + "sticker_pack_link" : "http://static.zoovy.com/merchant/zephyrsports/zephyr_sports_sticker_pack.zip", + "description" : "\n\n\n\n
                                                                          \n\n\n\n\n\n
                                                                          ", + "sticker_pack" : "downloads/logos/sticker_pack_thumb_002.jpg", + "logo_pack" : "downloads/logos/zephyr_logos_thumb.jpg", + "linkto_03" : "banners/link_backs/zephyr_sports_234x60_001.jpg", + "linkto_03_txt" : "", + "wall01_link" : "http://static.zoovy.com/img/zephyrsports/-/downloads/wallpaper/cmyk/", + "wall02_thumb" : "downloads/wallpaper/breakout/wallpaper_thumb_breakout.jpg" + }, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.voodoo_tactical_holsters" : { + "meta_description" : "", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "" + }, + ".skateboard_gear.skateboard_accessories.skateboard_hardware" : { + "meta_keywords" : "Skateboard hardware,Skateboard Tools,Skateboard equipment,skateboarding hardware,Skateboard accessories,skateboard decks,skateboard trucks,nuts,bolts", + "meta_description" : "Skateboard Hardware - Supe up your Skate w/brand new custom Skateboarding Hardware! Zephyr Sports has all of your Skateboard Equipment and Skateboard Accessories! Nuts, Bolts, ETC! Get your Skatboard trucks how you want them set to your Skateboard Decks! Bushings, Riser Pads, and more all available for you @ Zephyr Sports!", + "page_title" : "Buy Skateboard Hardware On Sale & Free Shipping", + "head_title" : "Skateboard Hardware | Skateboard Tools | Skateboard Equipment" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_high_beam_sunglasses_" : { + "meta_description" : "Arnette High Beam Sunglasses - Zephyr Sports carries a complete line of High Beam Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette High Beam Sun Glasses Online Today.", + "page_title" : "Arnette High Beam Sunglasses On Sale Free Shipping", + "head_title" : "Arnette High Beam Sunglasses | High Beam Arnette Sunglasses | Arnette High Beam Sun Glasses" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.gameface_aeg_airsoft_guns" : { + "meta_description" : "Game Face Airsoft Guns - Gameface Airsoft Guns avalable at Zephyr Sports with Free shipping. Crosman Gameface are made by Classic Army so you know you get a quality airsoft gun.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Game Face Airsoft Guns On Sale & Free Shipping", + "head_title" : "Game Face Airsoft Guns | Gameface Airsoft | Crosman Gameface" + }, + ".markerupgrades.bob_long_upgrades.bob_long_upgrade_4c_eyes" : { + "meta_description" : "Bob Long 4c Eyes - Buy your Marq Victory Laser Eyes Online at Zephyr Paintball for Less today. Free Shipping on Intemidator Upgrade Eyes Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Bob Long 4c Eyes Online On Sale Now", + "head_title" : "Bob Long 4c Eyes | Marq Victory Laser Eyes | Intemidator Upgrade Eyes" + }, + ".casual_clothing.mens_clothing.belts.spitfire_belts" : { + "meta_keywords" : "Spitfire Belts,Spitfire Belt Buckle,Spitfire Belts,Spitfire webbed belt", + "meta_description" : "Spitfire Belts - We carry the complete line of Spitfire Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Spitfire Belts on Sale Now!", + "head_title" : "Spitfire Mens Belts | Aplinestars Belts" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.30" : {}, + ".markerupgrades.gog_paintball_gun_upgrades.gog_envy" : {}, + ".apparel.paintball_cleats.exalt_paintball_cleats" : {}, + ".casual_clothing.youth_clothing.youth_t_shirts.hurley_youth_t_shirts" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_pants.dye_c12_paintball_pants" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs.women_s_camelbak_day_star_hydration_packs" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.32" : {}, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_victor_paintball_gun_packages" : { + "meta_description" : "Spyder Victor Paintball Packages - Buy your Victor Spyder Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder Victor Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Victor Paintball Packages Online On Sale Now", + "head_title" : "Spyder Victor Paintball Packages | Victor Spyder Paintball Guns Kit | Spyder Victor Paintball Guns" + }, + ".1newitems.2008_products.2008_stiffi_gear" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_bipods" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.tshirts.north_face_t_shirts" : { + "meta_keywords" : "North Face T Shirts,North Face shirts,free shipping,North Face TShirt", + "meta_description" : "North Face T Shirts - Zephyr carries a complete line of North Face Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "North Face T Shirts at Zephyr", + "head_title" : "North Face T Shirts | North Face Shirts | North Face TShirt" + }, + ".markerupgrades.angel.angel_electronics" : {}, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases.voodoo_tactical_backpacks_and_gun_cases" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_oil_rig_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley oil rig sunglasses,polarized oakley oil rig sunglasses", + "meta_description" : "Oakley Oil Rig Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Oil Rig Sunglasses and Polarized Oakley Oil Rig Sunglasses on Sale! ", + "page_title" : "Oakley Oil Rig Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Oil Rig Sunglasses | Oakley Oil rig Polarized Sunglasses | Oakley Oil Rig" + }, + ".apparel.pants.invert_paintball_pants" : { + "meta_keywords" : "Empire Invert Paintball Pants, Invert Empire Paintball Pants, Empire Invert Paint Ball Pants, Invert Paintball, Paintball Pants, Invert Paintball Pants, Invert Pants, Empire Invert Pants, Empire Pants Online", + "meta_description" : "Empire Invert Paintball Pants - Get the best prices on Invert Empire paintball pants online at ZephyrPaintball.com.", + "page_title" : "", + "head_title" : "Empire Invert Paintball Pants | Invert Empire Paintball Pants | Empire Invert Paint Ball Pants", + "page_head" : "Empire Invert Paintball Pants - Invert Empire Paintball Pants - Empire Invert Paint Ball Pants" + }, + ".casual_clothing.mens_clothing.sweatshirts.fmf_sweatshirts" : {}, + ".airsoft.tactical_airsoft_gear.tactical_gloves" : { + "meta_keywords" : "airsoft tactical gloves,airsoft gloves,voodoo tactical gloves", + "meta_description" : "Airsoft Tactical Gloves - Zephyr carries a complete line of Airsoft gloves for all your airsoft tactical need. With Free Shipping, Low Prices and Customer Service, we can't be beat", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Airsoft Tactical Gloves at Zephyr", + "head_title" : "Tactical Gloves | Airsoft Gloves | Airsoft Tactical Gloves" + }, + ".airsoft.airsoft_bbs_ammo.12_gram" : { + "meta_keywords" : ".12 gram bb,airsoft bb, airsoft ammo", + "meta_description" : ".12 Gram Airsoft BBs. These are some of the smallest airsoft BBs on the market. They are less powerful and are intended for short range use with spring pistols and rifles. Perfect for playing in the backyard. These BBs should not be used with more powerful AEG and airsoft guns as they may break from the amount of power on them. They will also do less damage.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".12 G Airsoft BB's | .12 BBs for Airsoft | .12 Gram Airsoft BB" + }, + ".casual_clothing.mens_clothing.sweatshirts.billabong_sweastshirts" : { + "meta_description" : "Billabong Sweatshirts - Buy your Billabong Hoodies At Zephyr Sports for Less Today! We carry a complete line of Billabong Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Billabong Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Billabong Sweatshirts | Billabong Hoodies | Billabong Hoody" + }, + ".airsystems.nitrogentanks.dye" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.sly_annex_paintball_masks" : {}, + ".casual_clothing.mens_clothing.watches.slap_watches" : {}, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.uhc_airsoft_guns" : {}, + ".casual_clothing.mens_clothing.hats.silver_hats" : { + "meta_keywords" : "Silver Hats,Silver caps,Silver baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Silver Hats - Zephyr carries a complete line of Silver Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Silver", + "page_title" : "Silver Hats on Sale at Zephyr", + "head_title" : "Silver Hats | Silver Caps | Silver Baseball Hats" + }, + ".casual_clothing.womens_clothing.ladies_wallets.metal_mulisha_ladies_wallets" : {}, + ".skateboard_gear.skateboard_trucks.gullwing" : {}, + ".apparel.gloves.jt_paintball_gloves" : { + "page_title" : "", + "head_title" : "JT Paintball Gloves | JT Gloves for Paintball | JT Paintballing Gloves" + }, + ".2clearance.clearance_upgrades.clearance_triggers" : { + "head_title" : "Sale Paintball Triggers | Clearance Paintball Triggers | Paintball Triggers Sale" + }, + ".casual_clothing.mens_clothing.shorts.arbor_shorts" : { + "meta_keywords" : "arbor boardshorts,arbor shorts,arbor board shorts, surf shorts", + "meta_description" : "Arbor Shorts - Zephyr stocks a complete line of Arbor Board Shorts. Low prices, Free shipping, easy returns on all Arbor boardshorts. Trust Zephyr for all your Arbor needs. ", + "page_title" : "Arbor Shorts with Free Shipping at Zephyr", + "head_title" : "Arbor Shorts | Arbor Board Shorts | Arbor Boardshorts" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_fly_jacker_sunglasses" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses", + "meta_description" : "Black Flys Flyjacker Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Flys Flyjacker Sunglasses." + }, + ".airsoft.airsoft_guns.action_sport_games" : {}, + ".harnessesbags.paintball_gear_bags.hk_army_gear_bags" : {}, + ".casual_clothing.mens_clothing.shirts.spitfire_shirts_and_flannels" : { + "meta_description" : "Spitfire Flannel Shirts - Buy your Spitfire Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Spitfire Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Spitfire Shirts & Flannels Ship Free", + "head_title" : "Spitfire Flannel Shirts | Spitfire Polo Shirts | Spitfire Shirts" + }, + ".casual_clothing.mens_clothing.jackets.1_search_by_size.4-x-large" : {}, + ".2clearance.clearance_jerseys___apparel.v-under__20" : { + "head_title" : "Sale Paintball Clothes | Clearance Paintball Clothes | Paintball Clothes Sale" + }, + ".airsystems.hosesfittings.replacement_gauges" : { + "meta_description" : "Paintball Tank Gauges - Buy your Paintball Gauge Online at Zephyr Paintball for Less today. Free Shipping on HPA Tank Gauge Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Tank Gauges Online On Sale Now", + "head_title" : "Paintball Tank Gauges | Paintball Gauge |HPA Tank Gauge" + }, + ".scenarioupgrades.scenario_apparel.paintball_ghille_suits" : {}, + ".scenarioupgrades.us_army_camping_gear" : {}, + ".1historical_products.paintball.paintball_clothing" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_clubmaster_sunglasses" : { + "meta_keywords" : "Ray Ban Clubmaster sunglasses,Ray Ban clubmaster,ray bans", + "meta_description" : "Ray Ban Clubmaster Sunglasses now on Sale @ Zephyr Sports! One of the leading sellers of the Ray Ban Sunglasses collection! Authentic Ray Ban Clubmaster shades available in various styles! The Clubmaster by Ray Ban is made in Italy and backed with a manufacturers warranty! Get your Ray Bans while supplies last!!", + "page_title" : "Buy Ray-Ban 3016 Clubmaster Sunglasses On Sale & Free Shipping", + "head_title" : "Ray-Ban 3016 Clubmaster Sunglasses | Ray-Ban RB 3016 Clubmaster Sunglasses" + }, + ".apparel.pants.valken_paintball_pants.valken_crusade_paintball_pants" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_blok_sunglasses" : { + "meta_keywords" : "Spy Blok sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Blok Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy sunglass with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Optics Blok Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Optics Blok Sunglasses | Spy Blok Sunglasses | Spy Optic Blok" + }, + ".shop_by_brand.spetzgear" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_batwolf_sunglasses" : { + "meta_keywords" : "Oakley Batwolf Sunglasses,Batwolf oakley sunglasses,oakley Batwolf, Batwolf polarized sunglasses", + "meta_description" : "Oakley Batwolf Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Batwolf and Polarized Oakley Batwolf Sunglasses on Sale! ", + "page_title" : "Oakley Batwolf Sunglasses with Free Shipping", + "head_title" : "Oakley Batwolf Sunglasses | Batwolf Oakley Sunglassses" + }, + ".casual_clothing.mens_clothing.tshirts.dc_t_shirts" : { + "meta_keywords" : "DC T Shirts,DC shirts,free shipping,DC TShirt", + "meta_description" : "DC T Shirts - Zephyr carries a complete line of DC Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "DC T Shirts at Zephyr", + "head_title" : "DC T Shirts | DC Shirts | DC TShirt" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.aeg_high_capacity_mags" : {}, + ".markers.dye_matrix_paintball_guns.dye_dm13_paintball_guns" : { + "meta_description" : "Just Release - The Dye DM13 Paintball Gun - for 2013 Dye has made the DM13 Paintball marker lighter and more efficient than ever. The DM 13 will once again be the top tournament level paintball gun in the world. Buy your Dm13 with free shipping at Zephyr Paintball.", + "top_description" : "Dye is proud to introduce the DM13! The most advanced member of the original series of markers of the famed DM line. This is the marker that has guided the Ironmen and Damage to numerous titles, and has been the backbone of Dye's product line for almost a decade. The DM is the most reliable, well established, longest-running marker in Dye's history. It also has the capability to shoot the most fragile tournament-grade paint on the market, and carries a tradition of being among the smoothest, quietest, and most accurate paintball marker in the world. Dye has made the DM13 with a combination of tried and true technology, innovative new features that truly make this marker The Choice of Champions. The DM13 is also available in a wide variety of other colors and PGA patterns! Pick one up today and OWN THE FIELD!", + "page_title" : "Dye Dm13 Paintball Guns Ship Free at Zephyr", + "head_title" : "Dye Dm13 Paintball Guns | Dye DM 13 Paintball Markers | 2013 Dye Dm", + "zoovy:banner01" : "banners/paintball/slideshow/dye_dm13_paintball_makers_slideshow_template.jpg" + }, + ".loaders.odyssey.halo_b_paintball_loaders" : { + "meta_keywords" : "Odyssey Loaders, Odyssey Halo Loaders, Odyssey Paintball Halo Loader, Halo Loaders, Odyssey Halo, Odyssey Paintball, Paintball Halo Loaders, Paintball Equipment, Paintball Supplies", + "meta_description" : "Odyssey Loaders - With the lowest prices on Odyssey paintball Halo loaders online, ZephyrPaintball is the best place to shop for paintball equipment and supplies.", + "page_title" : "Buy Odyssey Loaders Online On Sale Now", + "head_title" : "Odyssey Loaders | Odyssey Halo Loaders | Odyssey Paintball Halo Loader", + "page_head" : "Odyssey Loaders - Odyssey Halo Loaders - Odyssey Paintball Halo Loader" + }, + ".barrels.tippmanna5.14__tippmann_a_5_barrels" : { + "meta_description" : "14 inch Tippmann A5 Paintball Barrels - Buy your 14\" Tippmann A-5 Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Tippmann A5 Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 14 inch Tippmann A5 Paintball Barrels Online On Sale Now", + "head_title" : "14 inch Tippmann A5 Paintball Barrels | 14\" Tippmann A-5 Threaded Upgrade | Tippmann A5 Paintballs Barrels" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_chief_sunglasses" : { + "meta_description" : "Smith Optics Chief Sunglasses - Zephyr Sports carries a complete line of Chief Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Chief Sun Glasses Online Today.", + "page_title" : "Smith Optics Chief Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Chief Sunglasses | Chief Smith Sunglasses Free Shipping | Buy Smith Chief Sun Glasses" + }, + ".apparel.pants.dyepants.a-_dye_c9_paintball_pants" : { + "meta_keywords" : "Dye Paintball Pants,Dye Paintball C9 Pants,Paintball Dye C9 pants,Dye Paintball,Paintball pants,Dye,Dye C9 pants,Dye pants", + "meta_description" : "Dye Paintball C9 Pants - 2009 Dye Paintball pants are still available. Get your Dye C9 Paintball pants while you still can! Limited sizes and colors are available. ", + "top_description" : "Dye Paintball C9 Pants - 2009 Dye Paintball pants are still available! Sizes and colors are limited! Each year, Dye releases new designs and colors for the new season! Pick up your C9 Pants while you still can!", + "page_title" : "Dye C9 Paintball Pants | Dye Paintball C9 Pants | Paintball Dye C9 Pants", + "head_title" : "Dye C9 Paintball Pants | Limited Stock Available" + }, + ".buyers_guide.paintball.paintball_tanks" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_twenty_sunglasses" : {}, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_player_preferred_baseball_gloves" : { + "head_title" : "Rawlings Player Preferred Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".airsoft.airsoft_apparel.hydration_packs___water_bottles" : {}, + ".markerupgrades.dye_dam_upgrades_and_accessories" : {}, + ".airsoft.airsoft_guns.s_t_armament" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.north_face_pants" : { + "meta_description" : "North Face Pants - Buy your North Face Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "North Face Pants & Jeans Ship Free", + "head_title" : "North Face Pants | North Face Jeans" + }, + ".goggles.save_phace_paintball_goggles.so_phat" : { + "meta_description" : "So Phat Series Save Phace Paintball Goggles. So Phat Series comes with one military grade anti fog and anti scratch single pane clear lens, one additional colored replacement lens, R.W.I. Foam (Replaceable, Washable, Interchangeable) and includes stuff sack, a $40 Value. So Phat Series goggles come with everything needed to maintain your goggle system. So Phat Designs - Hoorah, Boo, BC7, Warlord, and Digi Camo.", + "page_title" : "Buy Save Phace So Phat Series Online On Sale Now", + "head_title" : "Save Phace So Phat Series | So Phat Series Paintball Goggles | Save face So Phat Series" + }, + ".dye_rotor_paintball_loader.dye_rotor_upgrades" : {}, + ".casual_clothing.mens_clothing.socks.enjoi_socks" : {}, + ".markers.kingmanspyder" : { + "meta_keywords" : "spyder paintball guns, Spyder paintball markers, Spyder paintball gear, Cheap Spyder Paintball Guns, Electronic Spyder Guns, kingman spyder guns, kingman spyder paintball guns, electronic spyder guns", + "meta_description" : "Spyder Paintball Guns - Spyder Paintball Makes the best entry level Paintball Guns and Markers in the world. From Spyder Starter Packages to Spyder RSX tournament guns, Spyder has what you need", + "zs11_banner_wslideshow_slide1" : "ALT=2013+Spyder+Hammer+7+Paintball+Markers&IMG=banners%2fpaintball%2fslideshow%2fspyder__hammer_7_slideshow%2ejpg&LINK=%2fcategory%2fmarkers%2ekingmanspyder%2espyder_hammer_7_pump_paintball_gun%2f", + "banner02_link" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "prodlist1_header" : "Featured Spyder Paintball Guns", + "banner01_link" : "/category/3packagespecials.kingman_spyder_paintball_packages/ ", + "zs11_banner_wslideshow_slide3" : "ALT=2013+Kingman+Spyder+E%2dMR5+Paintball+Markers&IMG=&LINK=%2fcategory%2fmarkers%2ekingmanspyder%2espyder_mr5_paintball_guns%2f", + "description" : "

                                                                          \n\"//static.zoovy.com/img/zephyrsports/-/images/kingman_sale.jpg\"\n\n\n

                                                                          \nSpyder Paintball Guns are great for beginners and intermediate players. Over the past couple years Spyder guns have proven their durability and consistency; whether that be with Semi-automatic Spyders or Electronic Spyders. If you are looking for your first paintball gun and don't want to spend too much on a paintball gun take a look at the 09 Sonix. Since technology is always getting greater so are Spyders. They are 15% lighter, 10% shorter, more durable and easier to maintain. The 09 Sonix is a quite simple design that operates on CO2 or Compressed Air. There are no electronics in this gun but you can shoot as fast as your fingers go with its semi-automatic setup. Only requires cocking (pulling the bolt back) once, then you are ready to shoot for a whole day of paintball. And don't worry about dropping the gun or falling with it when you dive for protection. This guns durability will last on any field and any woods ball area.\n\n\n==What's more advanced?==\n\n\nMaybe you are looking for something that is more comparable with what everyone else has on the field. It's great to have your options available when it comes to shooting faster. The 09 Spyder RT is a perfect example of an electronic paintball gun that is Semi-Auto, Full Auto, 3 Round Burst & 6 Round Burst capable that is still at an affordable cost. All Aluminum construction for maximum durability, double finger trigger for fast trigger pull. Running on a 9.6 Rechargeable battery the Spyder RT will show you speed and consistency. Just plug the charger in for a few hours and enjoy all day fun! Also, this Spyder is very easy to maintain. Bolt comes out with no hassle for easy cleaning and replacement if necessary. Entire gun can be completely dissembled in less than 5 minutes!\n\n\n==Should I use CO2 or Compressed Air with my Spyder?==\n\n\n\nMost Spyders can run off both CO2 & Compressed Air. Make sure you check with the product description of the Spyder before choosing which air to operate your gun on. All Semi-Automatic Spyders are CO2 capable. Why is this? Spyders that do not have electronic components run off very few parts that can withstand the cold pressure of CO2. Some electronic guns as well can run off CO2 but may eventually ware down the gun. What are the advantages of Compressed Air? Compressed air is much easier on o-rings, gears and other internal parts where as CO2 can freeze o-rings causing them to lose their shape and break which causes leaks, CO2 also can damage wires and boards if by some chance it was directed towards the board. Also, Compressed air is much more consistent than CO2. Your shots may not always be the same with CO2 - meaning CO2 can change its form depending on the weather. During cold weather CO2 is very unreliable and ball speeds vary from one shot to the next. During rapid firing, CO2 cools the whole gun which leads to inconsistent shots. All these are speculations and you may not even run into any of these problems. We just want to make sure people are aware of the advantages of Compressed Air.\n\n\n==Does Zephyr Offer Packages?==\n\n\nYes, we do! We have all kinds of different packages that will fit your specific needs. We have basic packages such as the Bronze Package that offers a Mask, Hopper, Tank, Barrel Cleaner, Gun Oil and Barrel Protection Cover. This is the ultimate beginner package that gets you started with the very basics of Paintball. If you are considering the 09 Spyder RT you can find that gun with many different types of packages such as the Silver Package that comes with everything the Bronze does but also a 4+1 Harness that carries 4 Pods so there is no need to worry about running out of paint in game. A bigger jump from these two packages is the Nitro Packages. Let's take a look at the 1 Star Package - this package offers you a compressed air tank, electronic hopper, standard mask, gun oil, barrel cleaner and barrel protection cover. The advantages of the 1 Star include the fast response from the electronic hopper that force feeds the balls in your gun so there is no need to shake the gun! Also, the compressed air tank; like mentioned before, gives you consistency in your shots and overall performance!\n\n\n==If you are still unsure about what package to pick for your Spyder don't hesitate to give us a ring 877-814-4297 and one of our customer service representatives will be happy to match you with your Spyder Package==\n\n\n==What Upgrades are available for Spyders?==\n\n\nZephyr carries [[Spyder Barrels]:url=http://www.zephyrpaintball.com/category/barrels.spyder/], Feednecks, Bolts, Stocks, Triggers, Boards and much more to increase the performance and look of your Spyder. By adding an upgraded Spyder Barrel you will gain distance and accuracy, the updraded Bolts help with air efficiency and chopping. These are just a few of the many different upgrades that Zephyr offers for your Spyder\n", + "banner1" : "banners/categories/guns/spyder_banner.jpg", + "head_title" : "Spyder Paintball Guns | Spyder Packages | Cheap Spyder Paintball ", + "page_title" : "Buy Spyder Paintball Guns Online On Sale Now", + "sortby_var" : "Spyder Gun Type", + "zs11_banner_wslideshow_slide2" : "ALT=Kingman+Spyder+2013+MR5&IMG=&LINK=%2fcategory%2fmarkers%2ekingmanspyder%2espyder_mr5_paintball_guns%2f" + }, + ".airsoft.3packagespecials" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft AEG Packages | Airsoft Pistol Starter Kits | Airsoft Guns" + }, + ".casual_clothing.mens_clothing.sweatshirts" : { + "meta_description" : "Mens Sweatshirts - Buy your Mens Hoodies At Zephyr Sports for Less Today! We carry a complete line of Surf & Skate Sweatshirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Mens Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Mens Sweatshirts | Mens Hoodies | Surf & Skate Sweatshirts" + }, + ".safetygear.kneeelbowpads.redz_knee___elbow_pads" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys.valken" : {}, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_wraptor_sunglasses" : { + "meta_description" : "Gatorz Wraptor Sunglasses - Zephyr Sports carries a complete line of Gatorz Wraptor Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Gatorz Wraptor Online Today.", + "page_title" : "Gatorz Wraptor Sunglasses On Sale Free Shipping", + "head_title" : "Gatorz Wraptor Sunglasses | Gatorz Wraptor Sun Glasses | Sunglasses Gatorz Wraptor" + }, + ".2clearance.paintball_clearance_gear.clearance_upgrades.clearance_triggers" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4143_fire_drill_sunglasses" : { + "meta_description" : "Arnette Fire Drill Sunglasses - Zephyr Sports carries a complete line of Fire Drill Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Fire Drill Sun Glasses Online Today.", + "page_title" : "Arnette Fire Drill Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Fire Drill Sunglasses | Fire Drill Arnette Sunglasses | Arnette Fire Drill Sun Glasses" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_rage_xl_sunglasses" : { + "meta_keywords" : "Arnette, Arnette Polarized lenses, Arnette Sunglasses, Designer Sunglasses, Arnette Rage sunglasses", + "meta_description" : "Arnette Rage XL Polarized Sunglasses - Zephyr Sports now carries Arnette Designer Sunglasses! ** Arnette Polarized Lenses ** Arnette Rage XL Sunglasses @ Zephyr Sports!", + "head_title" : "Arnette Rage XL Polarized Sunglasses | Arnette Rage XL Sunglasses" + }, + ".apparel.jerseys.protojerseys.2010_proto_paintball_jerseys" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.aps_airsoft" : {}, + ".casual_clothing.womens_clothing.ladies_tank_tops.1_search_by_size.4_large_ladies_tank_tops" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.1-von_zipper_smokeout_edition_sunglasses" : { + "meta_description" : "Von Zipper Smokeout Sunglasses - Zephyr Sports carries a complete line of Buy Smokeout Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Smokeout Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Smokeout Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Smokeout Sunglasses | Buy Smokeout Von Zipper Sunglasses | Von Zipper Smokeout Sunglasses Free Shipping" + }, + ".markers.btdesignspaintballguns.bt_omega_paintball_guns" : { + "htmlvids" : "", + "meta_description" : "BT Omega Paintball Guns - Buy your Empire BT Omega Online at Zephyr Paintball for Less today. Free Shipping on Omega Tactical Paintball Markers Trust Zephyr for all your Paintball Needs", + "top_description" : "==The new BT Omega Paintball Marker will take you into battle without breaking the bank!==\n\nThe rugged aluminum body will withstand heavy duty combat situations and provides increased performance and durability. The BT Omega Paintball Gun will require little in terms of regular maintenance. Fully upgradeable, the BT Omega easily accepts numerous BT upgrades, such as the HALO powered Rip Clip, the BT1913 Barrel, the BT Clamp Elbow Kit and the Tactical Folding Stock. Carrying your marker out to battle has never been easier thanks to its secure carry handle. The BT Omega's permanent, fixed sight rail provides you a continuous lock on your opponents, thereby giving you the confidence needed to take them out of the game. Grab your gear, lock and load and hit the field running with the BT Omega today!\n\n\n", + "page_title" : "Buy BT Omega Paintball Guns Online On Sale Now", + "head_title" : "BT Omega Paintball Guns | Empire BT Omega | Omega Tactical Paintball Markers", + "zoovy:banner01" : "banners/paintball/slideshow/1_bt_omegatactical_gunslideshow", + "description" : "=BT Omega Features=\nThe BT Omega Paintball Gun has a rugged aluminum body with an adjustable multi position stock. The Omega is compatible with the BT Rip Clip Electronic loader and will work off of either CO2 or High Pressure Air HPA. Velocity on the BT Omega is easily adjustable using an allen wrench included with the gun. Other features of the Omega Paintball gun include a carry handle and fixed sight rail as well as a removable magazine that doubles as tool storage so your never caught without the allen key you need for a day of play. The Bt Omega uses a Tippmann A5 threaded barrel so there are plenty of available aftermarket barrels including the BT Apex barrel. Included with your gun will be a basic maintenance pack that includes common orings as well as the allen keys need to maintain your gun.\n\n" + }, + ".casual_clothing.mens_clothing.shoes.adio_shoes" : { + "meta_description" : "Adio Shoes - Buy your Adio Mens Shoes At Zephyr Sports for Less Today! We carry a complete line of Adio Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Adio Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Adio Shoes | Adio Mens Shoes | Adio Skate Shoes" + }, + ".3packagespecials.azodin_paintball_packages" : { + "meta_description" : "Azodin Paintball Packages - Buy your Azodin Starter Kits Online at Zephyr Paintball for Less today. Free Shipping on Azodin Paintball Packages Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Azodin Paintball Packages Online On Sale Now", + "head_title" : "Azodin Paintball Packages | Azodin Starter Kits | Azodin Paintball Packages", + "sortby_var" : "Gun Type" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb3427_active_lifestyle_sunglasses" : { + "meta_description" : "Ray Ban Active Lifestyle Sunglasses - Zephyr Sports carries a complete line of Active Lifestyle Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Active Lifestyle Sun Glasses Online Today.", + "page_title" : "Ray Ban Active Lifestyle Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Active Lifestyle Sunglasses | Active Lifestyle Ray Ban Sunglasses | RayBan Active Lifestyle Sun Glasses" + }, + ".casual_clothing.mens_clothing.hats.c1rca_circa_hats" : { + "meta_keywords" : "Blind Hats,Blind caps,Blind baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Circa Hats - Zephyr carries a complete line of Circa Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Circa", + "page_title" : "Circa Hats on Sale at Zephyr", + "head_title" : "Circa Hats | Circa Caps | Circa Baseball Hats" + }, + ".2clearance.clearance_jerseys___apparel.clearance_shorts" : { + "head_title" : "Sale Paintball Shorts | Clearance Paintball Shorts | Paintball Shorts Sale" + }, + ".casual_clothing.mens_clothing.beanies.eclipse_beanies" : { + "meta_keywords" : "Eclipse beanie,Eclipse hat,Eclipse beanies,Eclipse caps,Eclipse 686,Eclipse headwear,Eclipse cuff visor beanie,Eclipse beanie hat,Eclipse visor beanie,Eclipse visor beanies", + "meta_description" : "Eclipse Deanie - Surf style with Eclipse Beanies available now at Zephyr Sports. Get your Eclipse hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Eclipse Beanies on Sale at Zephyr Today", + "head_title" : "Eclipse Beanie | Eclipse Hat | Eclipse Beanies" + }, + ".001a_zephyr_paintball_sports_promotions_deals_sales.free_headband_with_order" : { + "zoovy:banner01" : "banners/paintball/headers/freeheadband_100order_header001.jpg" + }, + ".markers.kingmanspyder.spyder_mrx_paintball_guns" : { + "top_description2" : "Brand new for 2012 the Spyder MRX features the breakthrough \"DLS\" Dual Loading System. This unique patent pending system enables you to interchange the loading system on the MRX with a turn of the barrel; the Spyder MRX allows the user to select back and forth from an upper loader fed system and the lower magazine fed system during play. The spyder MRX is the most versatile paintball gun we've seen. Magazine fed limited paint games have been growing over the past few years. The Spyder MRX Magazine feed system allows you to play a much more tactical thinking game instead of just spraying paint and money down the barrel. But if that's the game your playing today, a twist of the spyder MRX barrel and your ready to play.", + "top_description" : "", + "banner02_link" : "/category/3packagespecials.kingman_spyder_paintball_packages.kingman_spyder_mrx_paintball_gun_packages_/", + "zoovy:banner01" : "banners/paintball/newsletters/kingman_spyder_mrx_paintball_gun_newsletter", + "description" : "Both the Spyder MRX and MRX Elite feature the new DLS loading system. The stock Spyder MRX features an adjustable stock and site rail as well as an m16 style front site and foregrip for that realistic look and feel. There is also a picatinny rail system to mount whatever tactical upgrades you can come up with. The offset feedneck allows full use of the top picatinny rail for a scope or laser site. The stock barrel on the spyder mrx is a 14\" Spyder threaded barrel with muzzle break. The MRX uses the Eko Valve system for insane air efficiency, you should see 1500+ shots from a 20 oz co2 tank. Of course the Spyder MRX will also run off of compressed air. The spyder MRX uses a side cocking aluminum bolt and has an external velocity adjuster for easy adjustments at the field. \n\n\n\n=Spyder MRX Paintball Gun Features:=\n\n*Milsim Style Semi-Auto Paintball Marker\n*Eko Valve System (Patent Pending)\n*Shoots up to 1500 shots from a 20oz CO2 Tank\n*\"DLS\" Dual Loading System (Patent Pending)\n*11 Round Magazine\n*High Impact Polymer Off-Set Clamping Feed Neck\n*Micro Ported 14\" Spyder threaded Barrel w/ Muzzle Break\n*Barrel Shroud with Front Sight\n*Assault Adjustable Sight Rail\n*Picatinny Rail Mounting System\n*Side Cocking Aluminum Bolt\n*Quick Release Striker Plug Pull Pin\n*Short Pull Single Trigger\n*Steel Braided Hose\n*External Velocity Adjuster\n*Fires only .68 caliber paintballs\n\n\nThe Spyder MRX Elite takes all of the standard features and adds a foregrip, red/green dot site, laser pointer, as well as increasing the barrel from 14\" to 18\" and adding a second 10 round magazine. ", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001" + }, + ".airsoft.slingshots.1slingshots.trumark_slingshots" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_wilshire_sunglasses" : { + "meta_description" : "Spy Optics Wilshire Sunglasses - Zephyr Sports carries a complete line of Wilshire Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Wilshire Sun Glasses Online Today.", + "page_title" : "Spy Optics Wilshire Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Wilshire Sunglasses | Wilshire Spy Sunglasses Free Shipping | Buy Spy Wilshire Sun Glasses" + }, + ".casual_clothing.mens_clothing.beanies.neff_beanies.neff_fold_beanies" : { + "meta_description" : "Neff Fold Beanies - Buy your Beanies Neff FoldAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Neff Fold Beanies @ Zephyr Sports", + "head_title" : "Neff Fold Beanies | Beanies Neff Fold" + }, + ".casual_clothing.mens_clothing.sweatshirts.enjoi_sweatshirts" : { + "meta_description" : "Enjoi Sweatshirts - Buy your Enjoi Hoodies At Zephyr Sports for Less Today! We carry a complete line of Enjoi Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Enjoi Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Enjoi Sweatshirts | Enjoi Hoodies | Enjoi Hoody" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.neff_youth_t_shirts" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_51-30_watches" : { + "meta_keywords" : "Nixon watches,nixon 51-30 watch,nixon watch,nixon 51-30 chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon 51-30 Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon 51-30 Chrono Watches", + "head_title" : "Nixon 51-30 Watches | Nixon 51-30 Chrono Watch | Nixon 5130" + }, + ".casual_clothing.mens_clothing.beanies.pb_fashion_beanies" : { + "meta_keywords" : "HK Army beanie,HK Army hat,HK Army beanies,HK Army caps,HK Army 686,HK Army headwear,HK Army cuff visor beanie,HK Army beanie hat,HK Army visor beanie,HK Army visor beanies", + "meta_description" : "HK Army Deanie - Surf style with HK Army Beanies available now at Zephyr Sports. Get your HK Army hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "HK Army Beanies on Sale at Zephyr Today", + "head_title" : "HK Army Beanie | HK Army Hat | HK Army Beanies" + }, + ".paintballs.zap_paintballs" : {}, + ".casual_clothing.mens_clothing.hats.infamous_paintball" : {}, + ".airsoft.tactical_airsoft_gear.head_gear.zan_headgear" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_c-wire_sunglasses" : { + "meta_keywords" : "Oakley C-Wire Sunglasses,C-Wire oakley sunglasses,oakley C-Wire, C-Wire polarized sunglasses", + "meta_description" : "Oakley C-Wire Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley C-Wire and Polarized Oakley C-Wire Sunglasses on Sale! ", + "page_title" : "Oakley C-Wire Sunglasses with Free Shipping", + "head_title" : "Oakley C-Wire Sunglasses | C-Wire Oakley Sunglassses" + }, + ".airsoft.tactical_airsoft_gear.camoflouge_shirts" : { + "meta_keywords" : "camouflage shirts,airsoft shirts,military shirts", + "meta_description" : "Camouflage Shirts. These are high grade military style shirts that will last through any scenario. Available in multiple camouflage patterns; wear the same uniform as the US army. These shirts provide great cover from enemies and allow you to blend in to your environment. They are also extremely durable and come in a long sleeve design for a comfortable feel while playing. Outfitted with multiple pockets to allow you to carry all the items you need for lengthy games. Easy fit made possible by a button flap style design. Military grade BDUs. ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_disclosure_womens_sunglasses" : { + "meta_keywords" : "Oakley Disclosure Womens Sunglasses,Disclosure Womens oakley sunglasses,oakley Disclosure Womens, Disclosure Womens polarized sunglasses", + "meta_description" : "Oakley Disclosure Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Disclosure Womens and Polarized Oakley Disclosure Womens Sunglasses on Sale! ", + "page_title" : "Oakley Disclosure Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Disclosure Womens Sunglasses | Disclosure Womens Oakley Sunglassses" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_mountain_bike_hydration_packs.camelbak_lobo_hydration_packs" : {}, + ".airsystems.dropforwards.shocktech" : {}, + ".paintball.paintball_scenario_upgrades.scenario_apparel.camo_paintball_jerseys" : {}, + ".airsoft.airsoft_guns.heckler___koch_airsoft_guns" : { + "meta_description" : "Heckler & Koch Airsoft Guns - Buy your H&K Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Heckler & Koch AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Heckler & Koch Airsoft Guns On Sale & Free Shipping", + "head_title" : "Heckler & Koch Airsoft Guns |H&K Airsoft Rifles | Heckler & Koch AEG", + "description" : "" + }, + ".casual_clothing.mens_clothing.hats.zero_hats" : { + "meta_keywords" : "Zero Hats,Zero caps,Zero baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Zero Hats - Zephyr carries a complete line of Zero Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Zero", + "page_title" : "Zero Hats on Sale at Zephyr", + "head_title" : "Zero Hats | Zero Caps | Zero Baseball Hats" + }, + ".apparel.pants.dyepants.dye_c10_paintball_pants" : { + "meta_keywords" : "Dye Paintball Pants,Dye Paintball C10 Pants,Paintball Dye C10 Pants,Dye Paintball,Paintball Pants,Dye,Dye C10 Pants,Dye Pants", + "meta_description" : "Dye Paintball C10 Pants - 2010 Dye Paintball Pants are still available. Get your Dye C10 Paintball Pants while you still can! Limited sizes and colors are available. ", + "top_description" : "Dye Paintball C10 Pants - 2010 Dye Paintball Pants are still available. Sizes and colors are limited! Each year, Dye releases new designs and colors for the new season! Pick up your C10 Pants while you still can!\n", + "page_title" : "Dye C10 Paintball Pants | Dye Paintball C10 Pants | Paintball Dye C10 Pants", + "head_title" : "Dye C10 Paintball Pants | Limited Stock Available" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_cylinder_set___cylinder_heads" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Cylinder Heads | Cylinder Head Airsoft | Modify Cylinder Head" + }, + ".markers.gog_paintball_guns.g1_paintball_guns" : { + "meta_description" : "GOG Paintball Guns G1 - Buy your Gog G1 Paintball Markers Online at Zephyr Paintball for Less today. Free Shipping on Gog G1 Paintball Gun Trust Zephyr for all your Paintball Needs", + "top_description2" : "The GOG G1 brings tournament firepower to a tactical paintball gun. The Gog G1 is ready to accept whatever sights and attachments you need with plenty of rails built into the marker body. The Gog G1 is competitive out of the box firing 11BPS stock. The G1 is easily upgradeable to 25 BPS with a QEV and the Blackheart board. The GOG G1 includes an adjustable feedneck to allow you to position the loader on either the left or right side, perfect for when you attach a scope or sight to your Gog G1. The stock barrel on the G1 is a 14\" tactical barrel that is plenty accurate. This isn't your typical stock barrel. The Gog G1 includes a collapsible stock to get just the right feel when you shoulder the G1. The Gog G1 paintball gun was built to run off of compressed air or co2 so you can use whatever tank you have already although Zephyr always recommends HPA for the best paintball experience. Gog paintball has released multiple attachments for the GOG G1, but most standard rail attachment will work fine with the G1.\n\n", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.gog_paintball_packages/?sortby=!zoovy:prod_name", + "description" : "The GoG G1 Paintball Marker is 2011's first new Military Sim Scenario/Woodsball Paintball Gun. Priced at only $249.95, the G1 is great for any paintball enthusiast! \n\n\nWith 7 different accessory rails and built using high quality 6000 series aluminum with high grade composite materials, the G1 is one of the most durable and customizable paintball guns on the market! \n\n\nStraight out of the box, the G1 shoots 11 Balls Per Second and can easily be upgraded to shoot up to 25 BPS. \n\n\nLow battery operated! With just a standard 9-Volt battery, the GoG G1 paintball gun will easily rock out at least 20,000 shots... That's more than 10 boxes of paint on one fresh battery! \n\n\nA unique feature on this military sim gun is the offset adjustable feedneck. This allows for various scopes and/or top rail accessories to be more effective than ever! This really enables all your scenario upgrades to play a bigger role in your success on the field! \n\n\nUnmatched Stock Accuracy! With a precision machined 14 inch tactical paintball barrel standard on the G1, you'll have no use for any other aftermarket barrels!\n\n\nThe GoG G1 is guaranteed to perform with either HPA or C02 and is fully equipped with the Max-Flow R vertical regulator firing each shot more consistent than the last!\n\n\nGet your Scenario Paintball Game On with the G1 from GoG Paintball!\n\n\nGoG G1 Features:\n* 11 bps ( upgradable to 25+ with QEV and Board )\n* Customer adjustable 'left, right or center feed neck'\n* Modes Include semi auto, fully auto and 3 shot burst also PSP & BillyBall\n* 14\" Tactical Barrel\n* M16 Style extending stock\n* Hammer free Electro-pneumatic Design\n* Simple 9-Volt Operation\n* Mulit-Gas Operation\n* Light Microswitch Trigger with 2 Adjustable Points\n* Simple Maintenance with bolt out back design\n* Low Bolt Pressure Anti-Chop technology\n* Max-Flo R Vertical Regulator\n* Standard Smart Parts Barrel Thread\n* Integrated Tactical Flashlight Mount\n* 7 Accessory Rails for ultimate mounting options\n* Built using high quality 6000 series aluminum and high grade composite materials for ultimate strength. ", + "page_title" : "Buy GOG Paintball Guns G1 Online On Sale Now", + "head_title" : "GOG Paintball Guns G1 | Gog G1 Paintball Markers | Gog G1 Paintball Gun" + }, + ".airsoft.airsoft_guns.kwc_airsoft_guns" : { + "head_title" : "KWC Airsoft Guns | KWC Airsoft Pistols" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.empire_mini_paintball_guns" : {}, + ".scenarioupgrades.tactical_vests.tiberius_arms_tactical_vests" : {}, + ".casual_clothing.mens_clothing.belts.arbor_belts" : {}, + ".airsoft.airsoft_bbs_ammo.airsoft_paintballs" : { + "meta_keywords" : "airsoft paintballs, paintball bbs, paintballs", + "meta_description" : "Airsoft Paintballs. Know exactly who and what you hit with these paint filled 6mm balls. These paintballs are great for use with kids (given the use of proper safety gear) as they prevent injury and lasting pain. Paint will wash in normal laundry and is non-toxic. Great for target practice and normal play as you can easily wash away any mess.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.hats.srh_hats" : { + "meta_keywords" : "SRH Hats,SRH caps,SRH baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "SRH Hats - Zephyr carries a complete line of SRH Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything SRH", + "page_title" : "SRH Hats on Sale at Zephyr", + "head_title" : "SRH Hats | SRH Caps | SRH Baseball Hats" + }, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_prime_sunglasses" : { + "meta_description" : "Anarchy Prime Sunglasses - Zephyr Sports carries a complete line of Anarchy Prime Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Prime Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Prime Sunglasses | Anarchy Prime Sun Glasses" + }, + ".markerupgrades.smartparts.ion.bolts" : {}, + ".airsystems.nitrogentanks.fuelnitrogentanks" : { + "meta_description" : "Empire HPA Tank - Buy your Empire Compressed Air Tank Online at Zephyr Paintball for Less today. Free Shipping on Paintball Air Bottles Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire HPA Tank Online On Sale Now", + "head_title" : "Empire HPA Tank | Empire Compressed Air Tank | Paintball Air Bottles", + "prodlist1" : "&FORMAT=DEFAULT&SRC=" + }, + ".3packagespecials.dangerous_power_paintball_packages" : { + "meta_description" : "Dangerous Power Paintball Packages - Buy your Dangerous Power Paintball Kits Online at Zephyr Paintball for Less today. Free Shipping on DP Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dangerous Power Paintball Packages Online On Sale Now", + "head_title" : "Dangerous Power Paintball Packages | Dangerous Power Paintball Kits | DP Markers" + }, + ".2clearance.clearance_hoppers" : { + "meta_keywords" : "clearance hoppers, hopper clearance, cheap paintball hoppers, discounted paintball loaders, cheap electronic hoppers", + "page_title" : "", + "head_title" : "Clearance Hoppers | Hopper Clearance | Cheap Paintball Hoppers" + }, + ".barrels.barrels_by_manufacturer.stiffi_paintball_barrels" : { + "btn_title" : "Stiffi Barrel Threads", + "subcat1_header" : "", + "meta_keywords" : "stiffi paintball barrels, carbon fiber barrels, stiffi carbon barrels, stifi carbon barrels, stifi paintball barrels, carbon fiber paintball barrels", + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n \n
                                                                          \n
                                                                          \n
                                                                          \n \n\n
                                                                          \n
                                                                          \n
                                                                          \n \n
                                                                          \n
                                                                          ", + "meta_description" : "Stiffi Paintball Barrels are known for their light weight design that will not disappoint in accuracy and distance. You will not even notice the barrel is even attached to your gun! Pick one up today from Zephyr Paintball", + "head_title" : "Stiffi Paintball Barrels | Carbon fiber barrels | Stiffi carbon barrels", + "page_title" : "Buy Stiffi Paintball Barrels Online On Sale Now", + "sortby_var" : "Stiffi Paintball Barrel Size / Type" + }, + ".maddog.tippmann_upgrades.tippmann_x_7_upgrades" : {}, + ".airsystems.12_gram_co2_cartridges" : { + "meta_description" : "12 G Co2 Cartridge - Buy your 12G CO2 Online at Zephyr Paintball for Less today. Free Shipping on Co2 12G Cartridge Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 12 G Co2 Cartridge Online On Sale Now", + "head_title" : "12 G Co2 Cartridge|12G CO2 | Co2 12G Cartridge" + }, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_altercate_sunglasses" : { + "meta_description" : "Anarchy Altercate Sunglasses - Zephyr Sports carries a complete line of Anarchy Altercate Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Altercate Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Altercate Sunglasses | Anarchy Altercate Sun Glasses" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_t_shirts" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_shelter_sunglasses" : { + "meta_description" : "Smith Optics Shelter Sunglasses - Zephyr Sports carries a complete line of Shelter Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Shelter Sun Glasses Online Today.", + "page_title" : "Smith Optics Shelter Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Shelter Sunglasses | Shelter Smith Sunglasses Free Shipping | Buy Smith Shelter Sun Glasses" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.1-search_by_size.2_small_ladies_t_shirts" : {}, + ".casual_clothing.youth_clothing.youth_socks.spitfire_socks" : {}, + ".casual_clothing.mens_clothing.hats.habitat_hats" : { + "meta_keywords" : "Habitat Hats,Habitat caps,Habitat baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Habitat Hats - Zephyr carries a complete line of Habitat Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Habitat", + "page_title" : "Habitat Hats on Sale at Zephyr", + "head_title" : "Habitat Hats | Habitat Caps | Habitat Baseball Hats" + }, + ".markerupgrades.proto_matrix_upgrades.proto_matrix_upgrade_boards" : {}, + ".safetygear.hk_army" : {}, + ".casual_clothing.youth_clothing.youth_sweatshirts" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_d_payne_sunglasses" : {}, + ".markerupgrades.bt_designs_upgrades.bt_paintball_board_upgrades" : { + "meta_description" : "BT Combat Upgrades Board - Buy your Rampage Bt Board Online at Zephyr Paintball for Less today. Free Shipping on BT Ramping Electronic Trigger Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy BT Combat Upgrades Board Online On Sale Now", + "head_title" : "BT Combat Upgrades Board |Rampage Bt Board | BT Ramping Electronic Trigger" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.beretta_spring_airsoft_guns" : { + "meta_description" : "Bereta Spring Airsoft Guns - Buy your Beretta Airsoft Pistol At Zephyr Sports for Less Today! We carry a complete line of Beretta Rifle at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Bereta Spring Airsoft Guns On Sale & Free Shipping", + "head_title" : "Bereta Spring Airsoft Guns | Beretta Airsoft Pistol | Beretta Rifle" + }, + ".barrels.barrels_by_manufacturer.deadly_wind_paintball_barrels" : { + "meta_keywords" : "deadlywind barrels, deadlywind paintball barrels, deadly wind carbon fiber barrel, cheap deadlywind barrels, deadlywind freak barrels, deadlywind barrel kits, deadlywind freak barrel kits", + "meta_description" : "DeadlyWind Carbon fiber Barrels - The best carbon fiber paintball barrel. Accepts Smart Parts Freak inserts to match any Paintball. The only Carbon Fiber barrel that allows you to use any squeegee. Buy today at Zephyr", + "top_description" : "==Deadly Wind Paintball Barrels==\n\nDeadlywind was founded in 2001 with a mission to engineer the best paintball products possible.. With their Carbon Fiber technology and lightweight design, they've done just that!\n\n\nDeadly Wind's Carbon Fiber paintball barrels are the only CF barrel to use Smart Parts Freak inserts.\n\n\nThe Deadlywind Fibur carbon fiber barrels are ultra-lightweight, accurate, and quiet. They utilize the Freak(tm) replaceable inserts, so one barrel and a few inserts will do the job of multiple barrels.\n\n\nWeighing in at an average 60grams (73 grams with insert), the Fibur is 2x to 4x lighter than other replaceable insert barrels. And it it is strong enough to be driven over with a car (Yes, Deadly Wind has done it - And does not suggest you try it on purpose!)\n\n\nUnlike other carbon fiber barrels, the Fibur barrel is built with a unique 3 layer construction. 2x2 satin Twill external, uni-direction fibers laid up in a strong multi-vector pattern, and then a super slick \"Silkfiber\" inside that can be safely swabbed. CNC align-bored segment for the insert area, CNC-ported with 3 rows of straight ports, and then hand-assembled and quality checked-- You can't get any more accurate.", + "page_title" : "Buy Deadly Wind Paintball Barrels Online On Sale Now", + "head_title" : "Deadly Wind Paintball Barrels | DeadlyWind Carbon Fiber Barrel | Deadlywind Barrels", + "page_head" : "" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.kwa_airsoft_guns" : {}, + ".casual_clothing.mens_clothing.belts.nixon_belts" : { + "meta_keywords" : "Nixon Belts,Nixon Belt Buckle,Nixon Belts,Nixon webbed belt", + "meta_description" : "Nixon Belts - We carry the complete line of Nixon Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Nixon Belts on Sale Now!", + "head_title" : "Nixon Mens Belts | Nixon Belts" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_capitol_watches" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses" : { + "meta_keywords" : "arnette eyewear, Arnete shades, arnette sunglasses, buy sunglasses, sun glasses,surf sunglasses,designer sunglasses, arnette rage, arnette sun glasses", + "meta_description" : "Arnette Eyewear - Arnette sunglasses is the top manufacturer of designer beach sun glasses. Low Prices Free Shipping. Zephyr is proud to carry the Arnete line including top styles like the Rage, swinger, Temper, Lock up, and wrath. Buy online at Zephyr Sports now.", + "page_title" : "Buy Arnette Sunglasses Online Free Shipping", + "head_title" : "Arnette Eyewear | Arnette Sunglasses | Arnette Sun glasses" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_3062_stake_out_sunglasses" : { + "meta_description" : "Arnette Stake Out Sunglasses - Zephyr Sports carries a complete line of Stake Out Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Stake Out Sun Glasses Online Today.", + "page_title" : "Arnette Stake Out Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Stake Out Sunglasses | Stake Out Arnette Sunglasses | Arnette Stake Out Sun Glasses" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_reinforced_gear_box" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft upgrade gearbox | " + }, + ".markerupgrades.planet_eclipse_etek_upgrades.etek_trigger_upgrades" : {}, + ".paintball.paintball_guns.battle_tested_paintball_guns.empire_bt_d_fender_paintball_guns" : {}, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories.ncstar_molle_accessories" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_headwear" : {}, + ".markerupgrades.proto_matrix_rail_upgrades.proto_rail_bolts" : {}, + ".3packagespecials.empire_paintball_packages" : { + "head_title" : "Empire Paintball Packages | Empire Paintball Gun Packages" + }, + ".2clearance.airsoft" : { + "head_title" : "Airsoft Gear Clearance | Airsoft Sale Gear" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.misc_internal_upgrades" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft upgrade | upgrade airsoft | upgrading airsoft gun" + }, + ".markerupgrades.feednecks.impulse_ion_sft_feednecks" : { + "meta_description" : "Impulse / Ion Feed Necks - Buy your Feednecks for Impulse / Ion Online at Zephyr Paintball for Less today. Free Shipping on Impulse / Ion Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Impulse / Ion Feed Necks Online On Sale Now", + "head_title" : "Impulse / Ion Feed Necks | Feednecks for Impulse / Ion | Impulse / Ion Feed" + }, + ".casual_clothing.mens_clothing.pants_and_jeans" : { + "meta_keywords" : "mens pants,men jeans,men pants,mens denim,mens pant,men jean,men denim,mens jean,mens skinny jeans,mens cargo pants,mens clothing pants,mens denim jeans,denim for men,mens blue jeans,mens denim pants,skate jeans,buy mens jeans,mens jean sizes,mens skate jeans,jean for men,mens jean pants\r ", + "meta_description" : "Mens Pants - Looking for Stylish Mens Jeans? Zephyr Sports has you covered with all of the top surf and skate brands of Mens Denim Pants. Easy returns and Free shipping over $75. Buy Online Today", + "page_title" : "Mens Pants On Sale & Free Shipping", + "head_title" : "Mens Pants | Mens Jeans | Mens Denim Pants" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_kings_camo_sunglasses" : { + "meta_description" : "Oakley Kings Camo Sunglasses - Buy your Kings Camo Oakley Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Oakley kings Camo at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Kings Camo Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Kings Camo Sunglasses | Kings Camo Oakley Sunglasses | Oakley kings Camo" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.taurus_spring_airsoft_guns" : { + "meta_description" : "Taurus Airsoft Pistol - Buy your Taurus Spring PistolAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Taurus Airsoft Pistol Now! On Sale & Free Shipping", + "head_title" : "Taurus Airsoft Pistol | Taurus Spring Pistol" + }, + ".airsystems.nitrogentanks.pmi" : { + "meta_keywords" : "PMI Tanks, PMI Nitrogen Tanks, Pure Energy Tanks, Nitrogen Tanks, Pure Energy, PMI Nitrogen Tanks, PMI Paintball Tanks, Paintball Tanks, Paintball Supplies", + "banner1" : "banners/categories/recall_notice.png", + "meta_description" : "PMI Tanks - Shop for PMI nitrogen tanks and pure energy tanks and paintball supplies online at ZephyrPaintball.com.", + "page_title" : "Buy PMI Tanks Online On Sale Now", + "head_title" : "PMI Tanks | PMI Nitrogen Tanks | Pure Energy Tanks", + "page_head" : "PMI Tanks - PMI Nitrogen Tanks - Pure Energy Tanks", + "banner1_link" : "http://www.paintballsolutions.com" + }, + ".shop_by_brand.mission_first_tactical" : {}, + ".1historical_products.skateboard_gear" : {}, + ".airsoft.airsoft_apparel.camoflouge_shirts" : {}, + ".markerupgrades.planet_eclipse_lv1" : { + "banner01_link" : "/category/markerupgrades.planet_eclipse_lv1.planet_eclipse_lv1_grips/", + "zoovy:banner01" : "banners/paintball/slideshow/lv1_grips_slideshow_template.jpg" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.lrg_watches" : {}, + ".airsoft.airsoft_bbs_ammo.firepower_airsoft_bb_s" : { + "meta_description" : "Firepower Airsoft BBs available at Zephyr Sports. Largest selection with free shipping for your Airsoft Headquarters", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 Firepower Airsoft BBs | .25 Gram Firepower Airsoft Pellets | .20 G Fire Power Ammo for Airsoft Guns" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.dxs_silver_paintballs" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_supertide_watches" : { + "meta_keywords" : "Nixon watches,nixon Supertide watch,nixon watch,nixon Supertide chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Supertide Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Supertide Chrono Watches", + "head_title" : "Nixon Supertide Watches | Nixon Supertide Chrono Watch | Nixon 5130" + }, + ".markers.us_army_paintball_guns.us_army_project_salvo_paintball_guns" : { + "meta_keywords" : "salvo paintball marker,tippman project salvo,project salvo marker,salvo paintball gun,project salvo paintball gun,tippmann project salvo,us army project salvo,army project salvo,tippmann salvo,salvo paintball,project salvo paintball,project salvo\r ", + "meta_description" : "Project Salvo Paintball - The US Army Project Salvo Paintball Gun made by Tippmann is the hottest new entry level paintball Gun for 2010. The Tippmann Project Salvo is fully upgradeable and bulletproof just like you come to expect from Tippmann. Get your with free Shipping at Zephyr Today.", + "top_description2" : "=US Army Project Salvo Paintball Gun=\n\nThe US Army Project Salvo Paintball Gun includes an AR15 style six position folding and collapsible stock along with an AR15 style shroud with four picatinny Rails. The Project Salvo comes with a high performance 11\" quick thread barrel using Tippmann 98 threads. It alsp includes and adjustable front and rear sight and a proven high performance inline bolt system. Upgrades for the Project Salvo Paintball Gun include the Tippmann Custom 98 Response trigger, US Army Electronic grip as well as the Custom 98 Flatline barrel. Fully Licensed US Army product.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.us_army_paintball_packages.us_army_project_salvo_paintball_gun_packages/", + "description" : "The US Army Project Salvo paintball gun from Tippmann is here. The Project Salvo is a realistic AR-15 style paintball gun that comes standard with an 11\" Tippmann 98 threaded barrel. The stock barrel provides decent accuracy, but the first thing you will want to do is upgrade your barrel for increased accuracy. Check out our complete line of [[tippmann 98 barrels]:url=/category/barrels.tippmann98]. The US Army Project salvo also includes an AR15 style 6 position adjustable stock as well as an AR15 style front shroud with picatinnty rail mounts. You can upgrade your project salvo till the cows come home for whatever look and feel your after. The project salvo also is compatible with the [[US army E-grip]:url=/product/PB-ARMY-EGRIP] as well as the [[tippmann 98 flatline barrel]:url=/product/PB-TIP-PLATFLAT] . The E-grip will allow for 15bps and multiple firing modes including semi auto, 3 shot burst and multiple full auto modes. Be sure to check out all of our Project Salvo packages for everything you need to get on the field from Zephyr.\n\n\n=US Army Project Salvo Feature Summary:=\n\n*AR15 Style 6 Position Collapsible And Folding Stock.\n*Project Salvo AR15 Style Shroud With Picatinny Rails For Customization.\n*11\" Quick Thread Barrel (98 Threads).\n*Removable And Adjustable Front And Rear Sights.\n*All Aluminum Die Cast Tippmann Project Salvo Receiver.\n*Stainless Steel Gas Line Wont Rust Or Break.\n*Proven High Performance Project Salvo In-Line Bolt System.\n*Quick Release Feeder Elbow For Easy maintenance.\n*Picatinny Rails Make Adding Scopes, Carry Handles, And Other Accessories Quick And Convenient.\n*Add U.S. Army E-Grip And Cyclone Feed To Enhance Performance of the Tippmann Project Salvo.\n*Compatible With 98 Custom Response Trigger And 98 Platinum Series Flatline Barrel.", + "top_html_focus" : "", + "htmlvids" : "", + "head_title" : "Project Salvo Paintball | Tippmann Project Salvo | US Army Project Salvo", + "page_title" : "Buy Project Salvo Paintball Online On Sale Now", + "prodlist_custom" : "&SORTBY=PRICE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones.nixon_headphones.nixon_nomadic_headphones" : {}, + ".skateboard_gear.complete_skateboards.foundation_complete_skateboards" : { + "meta_keywords" : "Foundation Skateboards, Foundation Skate board, Foundation Skateboarding \r ", + "meta_description" : "Foundation Skateboards - Foundation Skate board - Foundation Skateboarding is takin' off @ Zephyr Sports!\r ", + "page_title" : "Foundation Complete Skateboards On Sale & Free Shipping", + "head_title" : "Foundation Complete Skateboards | Foundation Skateboards | Foundation Skateboarding" + }, + ".3packagespecials.kingman_spyder_paintball_packages" : { + "meta_description" : "Spyder Paintball Packages - Buy your Spyder Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder Paintball Packages Trust Zephyr for all your Paintball Needs", + "top_description" : "Spyder is a leader in entry level paintball guns. Zephyr carries a complete line of spyder packages for all spyder guns. Click through on the categories below if you know the gun your looking for, or all our packages our listed below. Zephyr has the most spyder gun packages and will not be beat on price and service.", + "page_title" : "Buy Spyder Paintball Packages Online On Sale Now", + "head_title" : "Spyder Paintball Packages | Spyder Paintball Guns Kit | Spyder Paintball Packages", + "sortby_var" : "Spyder Gun Type", + "description" : "=Kingman Spyder Package Details=\n\n\nBronze Package - Our entry level Spyder package includes a basic 20 oz tank to get you 1000+ shots per fill as well as an entry level paintball mask,200 rd hopper, rubber pull squeegee, gun oil and Zephyr Paintball american flag barrel cover (while supplies last)\n\n\nSilver Package - Our next level Spyder kit includes everything from our bronze package, Tank, Mask, Hopper, oil, and squeegee but adds in a 4+1 harness and pods for those long games. The +1 on this harness is a tank holder. This allows you to take the weight of the tank off of your gun and on your back with the additional of a remote coil (sold seperately). \n\n\nGold Package - The gold level spyder package includes everything from our bronze package, Tank, Mask, oil, and squeegee but adds in a 4+1 harness and pods for those long games. The +1 on this harness is a tank holder. This allows you to take the weight of the tank off of your gun and on your back with the additional of a remote coil (sold seperately). Finally the gold package swaps out the 200rd gravity fed hopper for an electronic halo too loader that will feed at 20+bps.\n\n\nTitanium Package - This spyder package includes everything from our bronze package, but adds in a 6+1 harness and pods for when you really want to carry the extra paint. Most people will prefer the comfort and weight of a 4+1 harness, but we offer a spyder package with the 6+1 harness for those of you who really want to spray paint." + }, + ".misc_items.lanyards" : {}, + ".harnessesbags.backpacks.hurley_backpacks___bags" : {}, + ".loaders.hopper_accesories.empire_hopper_accesories" : { + "meta_description" : "Empire Prophecy Acessories - Buy your Prophecy Speed Feeds Online at Zephyr Paintball for Less today. Free Shipping on Prophecy Quick Feeds Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire Prophecy Acessories Online On Sale Now", + "head_title" : "Empire Prophecy Acessories | Prophecy Speed Feeds | Prophecy Quick Feeds", + "sortby_var" : "Accessory Type" + }, + ".casual_clothing.mens_clothing.sweatshirts.powell_peralta_sweatshirts" : { + "meta_description" : "Powell Sweatshirts - Buy your Powell Hoodies At Zephyr Sports for Less Today! We carry a complete line of Powell Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Powell Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Powell Sweatshirts | Powell Hoodies | Powell Hoody" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_mission_backpacks" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_fulton_sunglasses" : { + "meta_keywords" : "Von Zipper Fulton sunglasses,VZ Fulton, Von Zipper polarized sunglasses,Von Zipper Fulton,VZ Fulton glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Fulton Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Fulton sunglasses now! For Von Zipper Fulton glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Fulton Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Fulton Sunglasses | VonZipper Fulton Sunglasses | VZ Fulton Sunglasses" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.1_search_by_size" : {}, + ".airsoft.airsoft_guns.we_airsoft_guns" : { + "meta_description" : "WE Airsoft Guns - Buy your WE Airsoft Rifles Online At Zephyr Sports for Less Today! We carry a complete line of WE AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy WE Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "WE Airsoft Guns | WE Airsoft Rifles | WE AEG", + "description" : "" + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.g36_airsoft_guns" : { + "meta_description" : "G36 Airsoft Guns - Buy your H&K G36 At Zephyr Sports for Less Today! We carry a complete line of G36 AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "These G36 replica airsoft guns are designed after the original G36 developed by Heckler & Koch. The original G36 is a selective fire 5.56mm assault rifle, firing from a closed rotary bolt. The G36 has a conventional layout and a modular component design. Common to all variants of the G36 family are: the receiver and buttstock assembly, bolt carrier group with bolt and the return mechanism and guide rod. The receiver contains the barrel, carry handle with integrated sights, trigger group with pistol grip, handguard and magazine socket.\n\n\nThe G36 has been in service since 1997 and is still used all over the world. ", + "page_title" : "Buy G36 Airsoft Guns On Sale & Free Shipping", + "head_title" : "G36 Airsoft Guns |H&K G36 |G36 AEG", + "description" : "" + }, + ".markerupgrades.grips_and_grip_panels.hybrid_paintball_grips.hybrid_45_paintball_grips" : {}, + ".casual_clothing.womens_clothing.ladies_rash_guards" : {}, + ".casual_clothing.womens_clothing.ladies_socks" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.crosman_eag_electric_airsoft_guns" : { + "meta_keywords" : "Crosman AEG Electric Airsoft Guns,AEG,Electric Airsoft Gun,Electric Airsoft Guns,Crosman Soft Air Guns,Crosman,Crosman pistols,Crosman rifles,", + "meta_description" : "Crosman is a leading designer in Electronic Airsoft Guns. Providing entry-level and affordable pistols and rifles, Crosman is the perfect choice for beginners looking to get into the action as well as veterans looking to expand their collection. The Crosman name has existed in the firearms industry for almost a century and has continued to manufacture some of the most affordable airsoft guns on the market today.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Crosman AEG Electric Airsoft Guns On Sale & Free Shipping", + "head_title" : "Crosman AEG Electric Airsoft Guns | Crosman Pulse R76 | Crosman Soft Air Guns", + "description" : "" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_pants.planet_eclipse_distortion_paintball_pants" : {}, + ".markers.kingmanspyder.spyder_victor_paintball_guns" : { + "meta_keywords" : "spyder victor,victor spyder,paintball gun,victor paintball gun,paintball marker,spyder gun,victor package,spyder package", + "meta_description" : "Spyder Victor Paintball Guns - Buy your Victor Spyder Paintball Marker Online at Zephyr Paintball for Less today. Free Shipping on Spyder Victor Packages Trust Zephyr for all your Paintball gear needs", + "top_description" : "Spyder does entry level paintball! The Spyder Victor is a semi automatic paintball gun shooting .68cal standard paintballs. One pull on the two finger trigger gets one shot. The spyder victor now features the patent pending EKO Valve system allowing you to get 1600+ shots from a 20 oz co2 tank. The spyder features a metal body with a high impact polymer grip frame and feed neck. The spyder victor comes with a 9\" spyder threaded barrel and will run off of co2 or compressed air. ", + "page_title" : "Buy Spyder Victor Paintball Guns Online On Sale Now", + "head_title" : "Spyder Victor Paintball Guns | Victor Spyder Paintball Marker | Spyder Victor Packages", + "banner02_link" : "http://www.zephyrpaintball.com/category/3packagespecials.kingman_spyder_paintball_packages.spyder_victor_paintball_gun_packages/", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_jupiter_camo_sunglasses" : {}, + ".shop_by_brand.gopro_action_sports_cameras" : { + "meta_keywords" : "gopro,gopro cameras,go pro,go pro cameras,hd gopro,go pro camera,gopro camera,gopro mounts,gopro camera mounts,gopro hd helmet,gopro sports camera,sports camera,hd gopro camera,hd hero,go pro hd", + "top_html" : "", + "meta_description" : "GoPro Hd Cameras - Full line of GoPro Action Sports Cameras @ Zephyr! HD hero camera, Hd Helmet Hero, and more! Go Pro Hd Cameras feature top of the line hi definition technology! You in HD! Into Action Sports? Zephyr Sports has all your GoPro Hd Camera needs Covered! GoPro Camera mounts available! Wide variety of hd gopro camera accessories in stock! GoPro Hd cameras allow you to relive reality in high definition! Pick up your GoPro Camera today @ Zephyr!", + "top_description2" : "=Be a HERO...GoPro, in HD.=\n\nDeveloped for professional use, but at a consumer price, the HD HERO line of wearable cameras capture full HD video rivaling cameras costing 10x the price. How? Our team consists of some of the the brightest minds in Silicon Valley who also happen to be obsessed with outdoor sports, race cars, and all things moto. Athletic super geeks? Indeed.", + "zoovy:banner01" : "banners/storewide/headers/gopro_newsletter", + "description" : "=Be a HERO...GoPro, in HD.=\n\n==Professional Quality, Full HD Video==\n\n1080p, 960p, and 720p in 30 and 60 fps (720p). The HD HERO line of cameras offers three different HD resolutions, giving you three filming modes to capture the best angles for any given activity:\n\n* 1080p: 1920x1080 True HD featuring a 127 degrees angle of view, 30 fps, and 16:9 widescreen aspect ratio\n\n* 960p: 1280x960 Ultra Wide and Tall HD featuring a 170 degrees angle of view, 30 fps, and 4:3 aspect ratio. See more of the action above and below than widescreen16:9 resolutions can show.\n\n* 720p: 1280x720 Ultra Wide HD featuring a 170 degrees angle of view, both 30 and 60 fps, and 16:9 widescreen aspect ratio\n\n\n==5MP Photos, Automatically==\nHD HERO cameras can shoot hands-free, 5 megapixel photos automatically at 2 / 5 / 10 / 30 / and 60 second intervals until the batteries die or the SD card is full (2.5 hours). Or set it to single shot, triple shot, or self timer for more traditional photo taking.\n\n\n==Audio Excellence==\nWe've invested more in the HD HERO camera's sound system than most companies spend on their entire camera development. You'll only be hearing the sounds of your sport, not the howl of the wind. How? Obsessive audio engineering and an understanding that good sound is as important as good video.\n\n\n==Rechargeable Lithium-Ion, Built in Battery Warmer==\nThe rechargeable 1100mAh lithium-ion battery (included) lasts for 2.5 hours of constant recording. It can be recharged to 80% capacity in just 2 hours when plugged into a computer's USB port, or in 1 hour when plugged into a USB compatible wall or car charger. Camera can also be used while charging; handy on road trips where it's fun to leave the camera rolling. Camera also features an integrated battery heating system for keeping your battery warm in winter activities.\n\n\n==Shockproof, Bombproof, Waterproof to 180 Feet / 60 meters==\nDon't let a little water, or even a ton of water get in the way of getting the shot. Proven in heavy surf from Hawaii to Tahiti, Southern Mexico to Northern California, HD HERO cameras can handle it thanks their highly engineered polycarbonate exoskeletal housing. Waterproof to 180 feet / 60 meters and tough enough to take a spin across the asphalt, GoPros are built to take a beating. It's a GoPro...go for it. ", + "htmlvids" : "", + "head_title" : "GoPro HD | Go Pro HD Sports Camera | Go Pro Camera", + "page_title" : "Buy GoPro HD Online On Sale Now" + }, + ".harnessesbags.backpacks.camelback_backpacks.hunting_camo" : { + "meta_description" : "Camelbak Hunting Packs | Camo Camelbak Packs - Buy your At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Hunting Packs | Camo Camelbak PacksOn Sale & Free Shipping", + "head_title" : "Camelbak Hunting Packs | Camo Camelbak Packs" + }, + ".airsoft.airsoft_guns.airsoft_co2_guns.tsd_gas_airsoft_guns" : { + "meta_description" : "Teams SD Airsoft Guns - Buy your TSD Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Teams SD Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Teams SD Airsoft Guns | TSD Airsoft Guns | " + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_stache_sunglasses" : { + "meta_keywords" : "Von Zipper Stache sunglasses,VZ Stache,Von Zipper polarized sunglasses,Von Zipper Stache,VZ Stache glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Stache Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Stache sunglasses now! For Von Zipper Stache glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Stache Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Stache Sunglasses | VonZipper Stache Sunglasses | VZ Stache Sunglasses" + }, + ".shop_by_brand.king_arms" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_proof_sunglasses" : { + "meta_description" : "Smith Optics Proof Sunglasses - Zephyr Sports carries a complete line of Proof Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Proof Sun Glasses Online Today.", + "page_title" : "Smith Optics Proof Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Proof Sunglasses | Proof Smith Sunglasses Free Shipping | Buy Smith Proof Sun Glasses" + }, + ".apparel.gloves.mechanix_wear_tactical_gloves" : {}, + ".airsoft.airsoft_safety.full_airsoft_goggles" : { + "meta_description" : "Airsoft Goggles - Buy your Full Airsoft Goggles At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Goggles On Sale & Free Shipping", + "head_title" : "Airsoft Goggles | Full Airsoft Goggles" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_variable_power_scopes.bushnell_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_caveat_womens_sunglasses" : { + "meta_keywords" : "Oakley Caveat Womens Sunglasses,Caveat Womens oakley sunglasses,oakley Caveat Womens, Caveat Womens polarized sunglasses", + "meta_description" : "Oakley Caveat Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Caveat Womens and Polarized Oakley Caveat Womens Sunglasses on Sale! ", + "page_title" : "Oakley Caveat Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Caveat Womens Sunglasses | Caveat Womens Oakley Sunglassses" + }, + ".3packagespecials.empire_paintball_packages.empire_mini" : { + "meta_keywords" : "Invert Mini Paintball Guns, Invert Mini, Invert Mini Packages, Mini Invert,Invert Mini Gear,Invert Mini Supplies, Discount Invert Mini,paintball guns invert mini,invert mini gun,invert mini paintball,Invert mini marker,invert mini markers,invert mini semi", + "htmlvids" : "
                                                                          \n\n
                                                                          \n\n
                                                                          \n\n
                                                                          ", + "meta_description" : "Invert Mini Paintball Guns - Invert makes the best Tournament Paintball Guns. If your a beninner or a seasoned tournament player Grab an Invert Mini marker and get on the field", + "top_description" : "==Empire Mini==\n\nThe think-tank at Empire paintball has incorporated unique, patented valve and flow technology designs into this high performance tournament-grade marker. The single tube poppet system is not only innovative, but it delivers on a promise of incredible velocity, consistency and accuracy. The Invert MINI is small, but ergonomically designed to fit right and exceed your expectations. There are NO HOSES or barbs anywhere in this gun and circuit boards have eliminated almost every wire in the Empire MINI.", + "page_title" : "Buy Empire Mini Packages on Sale and Free Shipping", + "head_title" : "Empire Mini | Invert Mini | Invert Mini Packages", + "description" : "=Invert Mini Features:=\n* Weighing in under 2 lbs (including barrel, ASA, 9volt battery and regulator) the Invert Mini might be THE Lightest & Tightest electronic marker available\n* NEW patented proprietary P.C.P. (Pressure Controlled Poppet) operating system\n* NEW patented proprietary MINI Regulator/ASA\n* NEW patented proprietary Slipstream solenoid\n* Break Beam Anti-Chop Eyes Standard\n* Multi-mode (NXL, PSP, NPPL & Millennium) firing capability with easy tournament lockout\n* Clamping feed-neck with Ion (Smart Parts)/ICD threads\n* 11.5\" Autococker Threaded Barrel\n* No hoses to crimp or break!" + }, + ".goggles.1goggle_accesories.virtue" : {}, + ".markerupgrades.us_army_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/scenarioupgrades.stocks.tippmann_98_scenario_stocks/", + "btn1" : "zephyr_buttons/paintball_pop/products_pop/barrels_popbtn001", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/grips_btn001", + "buttonname_03" : "", + "btn1_link" : "/results.cgis?catalog=COMMON&keywords=us+army+barrel+upgrade&x=0&y=0", + "add2_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_02" : "", + "banner4" : "zephyr_buttons/stocks_btn001", + "add1_link" : "/category/barrels.tippmann98/" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.jg_jing_gong_aeg_airsoft_guns" : { + "meta_description" : "JG Airsoft Guns - Buy your JG Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of JG AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy JG Airsoft Guns On Sale & Free Shipping", + "head_title" : "JG Airsoft Guns | JG Airsoft Rifles | JG AEG" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_sideways_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,oakley sideways sunglasses,oakley polarized sideways sunglasses", + "meta_description" : "Oakley Sideways Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Sideways Sunglasses and Polarized Oakley Sideways Sunglasses on Sale! ", + "page_title" : "Oakley Sideways Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Sideways Sunglasses | Sideways Oakley Sunglasses" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_kyle_busch_kb1_sunglasses" : { + "meta_description" : "Electric Kyle Bush KB1 Sunglasses - Zephyr Sports carries a complete line of Electric Kyle Bush KB1 Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Kyle Bush KB1 Online Today.", + "page_title" : "Electric Kyle Bush KB1 Sunglasses On Sale Free Shipping", + "head_title" : "Electric Kyle Bush KB1 Sunglasses | Electric Kyle Bush KB1 Sun Glasses | Sunglasses Electric Kyle Bush KB1" + }, + ".casual_clothing.mens_clothing.shorts.eclipse_shorts" : { + "meta_description" : "Eclipse Shorts - Zephyr stocks a complete line of Eclipse Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Eclipse needs. ", + "page_title" : "Eclipse Shorts with Free Shipping at Zephyr", + "head_title" : "Eclipse Shorts | Eclipse Board Shorts" + }, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_ely_sunglasses" : { + "meta_description" : "Gatorz Ely Sunglasses - Zephyr Sports carries a complete line of Gatorz Ely Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Gatorz Ely Online Today.", + "page_title" : "Gatorz Ely Sunglasses On Sale Free Shipping", + "head_title" : "Gatorz Ely Sunglasses | Gatorz Ely Sun Glasses | Sunglasses Gatorz Ely" + }, + ".scenarioupgrades.stocks.tippmann_98_scenario_stocks" : {}, + ".markerupgrades.azodin_paintball" : { + "banner01_link" : "/category/barrels.autococker/", + "zoovy:banner01" : "banners/paintball/headers/autococker_threaded_barrels.jpg" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_fast_jacket_sunglasses" : { + "meta_keywords" : "Oakley Fast Jacket Sunglasses,Fast Jacket oakley sunglasses,oakley Fast Jacket, Fast Jacket polarized sunglasses", + "meta_description" : "Oakley Fast Jacket Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Fast Jacket and Polarized Oakley Fast Jacket Sunglasses on Sale! ", + "page_title" : "Oakley Fast Jacket Sunglasses with Free Shipping", + "head_title" : "Oakley Fast Jacket Sunglasses | Fast Jacket Oakley Sunglassses" + }, + ".airsystems.thread_protectors" : { + "meta_description" : "Paintball Thread Protectors - Buy your Paintball Tank Cap Online at Zephyr Paintball for Less today. Free Shipping on Thread Protector for Paintball Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Thread Protectors Online On Sale Now", + "head_title" : "Paintball Thread Protectors | Paintball Tank Cap | Thread Protector for Paintball" + }, + ".sponsorship.sponsor_only_specials.guns_and_gear.tournament_deals" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.us_army_alpha_tactical_paintball_guns" : {}, + ".goggles.sly_profit_paintball_goggles.sly_profit_paintball_goggles" : { + "meta_keywords" : "cheap, masks, paintball, goggles, discount, equipment, thermal,Sly,Profit,gear, velour, eye, protection, black, camo, woodland, silver, red, neon, pink, blue, limited, edition, orange, white, zinc, dual pane, gradient, tinted, flexible, comfortable, quality, protective, eye-wear", + "meta_description" : "Sly Profit Eye Protection for Less at Zephyr Sports. Largest selection, Lowest Prices Guaranteed. Free Shipping on orders over $100. Paintball masks, safety glasses, everyone needs them to play- so why not get them here. We carry all the latest styles and accessories that you could ever need including Thermal Paintball Goggles.", + "top_description2" : "Emphasize safety and function with Sly Profit Paintball Mask. Tons of great features and reviews make this one of the best paintball masks on the market today. Velvet lining, soft foam ear pieces, and its design perfectly combine to create the ultimate in comfort. Choose from a variety of colors for your Sly Profit Mask! ", + "zoovy:banner01" : "banners/paintball/slideshow/1_sly_profit_specs.jpg", + "description" : "==Sly PROFIT==\n\nThe Sly Profit mask is one of the most high tech, comfortable and affordable masks on the paintball market.\n\n\nThe Sly Profit mask has a ton of great features that make this one of the best paintball masks on the market. To start with, the Sly Profit paintball mask has two goggle bands which gives you optimal comfort and will keep the mask right on your face in even the craziest situations.\n\n\nThe dual pane thermal lens of the Sly Profit mask is very easy to pop in or to take out. Sly has made a variety of different lenses and colors for their Profit series mask including the ever popular tinted and gradient fade lenses.\n\n\nThe Sly Profit mask has a flex bottom which will give you crucial bounces in those tough games. The Ear pieces of the Sly Profit paintball mask are made using brand new technology and are more comfortable than any other mask.\n\n\nThe Soft ear pieces of the Sly Profit mask suck right into your ear and give the mask a very unique and comfortable feel. Overall this looks like a great mask for anyone who is looking to really step up their game and have every possible advantage against your competition.\n\n\n* The Sly Paintball Mask is one of the most comfortable goggles on the market.\n* The Sly mask comes with a SOLID warranty.\n* All Sly Profit Masks come with an easy to change lens.", + "htmlvids" : "
                                                                          \n\n
                                                                          ", + "page_title" : "Buy On Sale Sly Profit Paintball Masks Online Now", + "head_title" : "Sly Profit | Paintball Mask | Eye Protection" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs.women_s_luxe_camelbak_hydration_packs" : {}, + ".harnessesbags.backpacks.metal_mulisha_bags" : { + "meta_keywords" : "metal mulisha bags,metal mulisha purses, handbags,backpacks,purse", + "meta_description" : "Metal Mulisha Bags - Zephyr Sports carries a complete line of Metal Mulisha Purses and Luggage. With Free Shipping over $25 and hassle free returns, we have you covered.", + "page_title" : "Metal Mulisha Purses & Bags on Sale", + "head_title" : "Metal Mulisha Purses | Metal Mulisha Bags | Metal Mulisha Luggage" + }, + ".casual_clothing.mens_clothing.wallets.fmf_wallets" : { + "meta_description" : "DGK Wallets - Buy your DGK Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of DGK Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DGK Wallets on Sale @ Zephyr Sports", + "head_title" : "DGK Wallets | DGK Mens Wallets | DGK Wallet" + }, + ".airsoft.airsoft_guns.team_sd_sports_airsoft_guns.team_sd_sports" : { + "meta_description" : "TSD Airsoft Guns - Buy your Team SD Sport Airsoft Guns Online At Zephyr Sports for Less Today! We carry a complete line of Team SD Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy TSD Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "TSD Airsoft Guns | Team SD Sport Airsoft Guns | Team SD Airsoft Guns" + }, + ".markerupgrades.autococker.triggers" : {}, + ".3packagespecials.planet_eclipse_package_specials.geo_package_specials" : { + "meta_description" : "Planet Eclipse GEO Paintball Packages - Buy your Planet Eclipse GEO Paintball Guns Kits Online at Zephyr Paintball for Less today. Free Shipping on Eclipse GEO Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Planet Eclipse GEO Paintball Packages Online On Sale Now", + "head_title" : "Planet Eclipse GEO Paintball Packages | Planet Eclipse GEO Paintball Guns Kits | Eclipse GEO Paintball Markers" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.walther_spring_airsoft_guns" : { + "meta_description" : "Aftermath Airsoft Guns - Buy your Aftermath Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Aftermath Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Aftermath Airsoft Guns On Sale & Free Shipping", + "head_title" : "Aftermath Airsoft Guns | Aftermath Airsoft Rifles | Aftermath Spring Airsoft Guns" + }, + ".paintball.paintball_scenario_upgrades.scenario_apparel.camo_paintball_pants" : {}, + ".apparel.shoes.adio_shoes" : {}, + ".harnessesbags.backpacks.eclipse_backpacks" : { + "meta_keywords" : "Planet Eclipse Backpacks,paintball backpack,school backpack,bookbag,travel backpack,paintball gear bags,laptop backpack,men backpacks,women backpacks", + "meta_description" : "Tons of compartments for small devices, laptops, files, ETC. in these Planet Eclipse Backpacks! Men and Women backpacks! Padded Straps to keep you comfortable! Use 'em as paintball gear bags, school backpacks, travel backpacks,and more! Plenty of storage space for all your essentials! ", + "page_title" : "Eclipse Backpacks On Sale & Free Shipping", + "head_title" : "Eclipse Backpacks | Eclipse Bags" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_fixed_power_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".return_request.defective_question" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_banks_watches" : { + "meta_keywords" : "Nixon Watches,Nixon Banks,Nixon watch,Nixon Banks watch,Nixon,mens watches,Nixon mens watch", + "meta_description" : "Nixon Watches - Brand new Nixon Banks Watch available now @ Zephyr! Nixon Banks Watches features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Banks Watch", + "head_title" : "Nixon Banks Watches | Nixon Banks Watch | Nixon Banks" + }, + ".markers.tippmann.tippmann_a_5_packages" : { + "description" : "\"//static.zoovy.com/img/zephyrsports/-/banners/a5_packs_header.jpg\"" + }, + ".goggles.1goggle_accesories.microfiber_cloths" : { + "meta_description" : "paintball lens cloth - Buy your Microfiber Lens Cleaner Online at Zephyr Paintball for Less today. Free Shipping on Paintball Micro Fiber Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy paintball lens cloth Online On Sale Now", + "head_title" : "paintball lens cloth | Microfiber Lens Cleaner | Paintball Micro Fiber" + }, + ".scenarioupgrades.paintball_grenades" : {}, + ".casual_clothing.womens_clothing.ladies_t_shirts.1-search_by_size.4_large_ladies_t_shirts" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_synapse_watches" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.nixon_headphones.nixon_wire_headphones" : { + "head_title" : "Nixon Wire Headphones | Wire Nixon Head Phones | Nixon Wire Headphone" + }, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_ego_09_paintball_guns" : { + "banner1" : "banners/categories/ego9_newprice_header001.jpg", + "htmlvids" : "", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_ideal_women_s_sunglasses" : {}, + ".casual_clothing.womens_clothing.ladies_sunglasses.von_zipper_womens_sunglasses" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_passport_watches" : { + "meta_keywords" : "Nixon watches,nixon Passport watch,nixon watch,nixon Passport chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Passport Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Passport Chrono Watches", + "head_title" : "Nixon Passport Watches | Nixon Passport Chrono Watch | Nixon 5130" + }, + ".harnessesbags.backpacks.oakley_backpacks.oakley_tool_pocket_backpacks" : { + "meta_description" : "Oakley Tool Pocket Backpacks - Buy your Oakley Tool Pocket Bag At Zephyr Sports for Less Today! We carry a complete line of Tool Pocket Oakley at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Tool Pocket Backpacks On Sale & Free Shipping", + "head_title" : "Oakley Tool Pocket Backpacks | Oakley Tool Pocket Bag | Tool Pocket Oakley" + }, + ".scenarioupgrades.stocks.spyder_paintball_stocks" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_two_face_sunglasses" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_rosewood_sunglasses" : { + "meta_description" : "Spy Optics Rosewood Sunglasses - Zephyr Sports carries a complete line of Rosewood Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Rosewood Sun Glasses Online Today.", + "page_title" : "Spy Optics Rosewood Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Rosewood Sunglasses | Rosewood Spy Sunglasses Free Shipping | Buy Spy Rosewood Sun Glasses" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.dpms_aeg_electric_airsoft_rifles" : { + "meta_keywords" : "DPMS Replica Airsoft Guns,DPMS,M4,M16,M4 airsoft rifle,M16 Airsoft rifle,airsoft guns,DPMS replicas,Airsoft AEG,M4 airsoft rifle,M16 Airsoft rifle", + "meta_description" : "DPMS Replica Airsoft Guns. DPMS is responsible for some of the most popular versions of the M4 and M16 rifles. DPMS models can be found in different law enforcement agencies around the world as well as in the Jordanian army. Having created a variety of parts for these rifles, these replica airsoft guns will have many of those upgraded pieces and looks. DPMS replicas provide realistic looks and feel with a great mid-level price range. Zephyr Sports is a leading distributor of DPMS airsoft products! We carry a wide variety of Airsoft AEG 's including the M4 airsoft rifle, M16 Airsoft rifle, and more!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "DPMS Airsoft Guns On Sale & Free Shipping", + "head_title" : "DPMS Airsoft Guns | Airsoft AEG 's | DPMS Airsoft Rifle", + "description" : "" + }, + ".shop_by_brand.dakine" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_raider_watches" : {}, + ".casual_clothing.z_shoes_and_footwear.circa_shoes" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_alysium_sunglasses" : {}, + ".2clearance.1-memorial_day_sale" : { + "zs11_banner_wslideshow_slide5" : "ALT=Dye+Tactical+Jersey+BLOWOUT+SALE%21&IMG=banners%2fpaintball%2fslideshow%2fdye_tactical_jerseys_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2fapparel%2ejerseys%2edyejerseys%2edye_tactical_paintball_jerseys%2f%3fsortby%3dzoovy%253Abase_price%26size%3d15", + "zs11_banner_wslideshow_slide1" : "ALT=Sly+Harness+BLOWOUT+Sale%21&IMG=banners%2fpaintball%2fslideshow%2f1_sly_harness_sale_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2fharnessesbags%2epacks___harnesses%2esly_paintball_harnesses%2f", + "top_description" : "== Memorial Day Savings!!! ==\nSave BIG Money ALL WEEKEND LONG @ Zephyr! We have a huge selection of discount paintball gear to get you on the field for less! ", + "zs11_banner_wslideshow_slide3" : "ALT=FREE+%2475+Dye+ASSAULT+Harness+w%2f+Dye+C13+Pant+%26+Jersey+Purchase%21&IMG=banners%2fpaintball%2fslideshow%2f1_dye_c13_free_harness%2ejpg&LINK=http%3a%2f%2fwww%2ezephyrpaintball%2ecom%2fresults%2ecgis%3fcatalog%3dHOMEPAGE%26keywords%3d%252F%252FFREEC13ASSAULT%26x%3d0%26y%3d0", + "zs11_banner_wslideshow_slide2" : "ALT=FREE+BONUS+LENS+w%2f+Every+Empire+E%2dFlex+Goggle+System%21&IMG=banners%2fpaintball%2fslideshow%2f1_empire_eflex_bonuslens%2ejpg&LINK=%25SESSION%25%2fcategory%2fgoggles%2eempire_vents_goggles%2eempire_e%2dflex_paintball_masks%2f", + "zs11_banner_wslideshow_slide4" : "ALT=PRICE+DROP%21+Empire+Paintball+Hoppers+On+SALE+NOW%21&IMG=banners%2fpaintball%2fslideshow%2f1_empire_prophecy_halo_pricedrop_slideshow%2ejpg&LINK=%25SESSION%25%2fcategory%2floaders%2eempire%2f" + }, + ".markers.jtusapaintballguns.jt_raptor_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_m-frame_sunglasses.oakley_m_frame_hybrid_s_sunglasses" : { + "meta_description" : "Oakley M Frame Hybrid S Sunglasses - Zephyr Sports carries a complete line of M Frame Hybrid S Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley M Frame Hybrid S Sun Glasses Online Today.", + "page_title" : "Oakley M Frame Hybrid S Sunglasses On Sale Free Shipping", + "head_title" : "Oakley M Frame Hybrid S Sunglasses | M Frame Hybrid S Oakley Sunglasses | Oakley M Frame Hybrid S Sun Glasses" + }, + ".markerupgrades.invert_upgrades.bolts" : { + "meta_description" : "Invert Mini Bolts - Buy your Invert Bolts Online at Zephyr Paintball for Less today. Free Shipping on Mini Upgrade Bolt Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert Mini Bolts Online On Sale Now", + "head_title" : "Invert Mini Bolts | Invert Bolts | Mini Upgrade Bolt" + }, + ".markers.kingmanspyder.kingman_training" : { + "htmlvids" : "" + }, + ".harnessesbags.backpacks.enjoi_backpacks" : { + "meta_description" : "Enjoi Backpacks - Carry your board and your school gear with a bag from Enjoi. Zephyr carries a complete line of Enjoi Bags & Luggage", + "page_title" : "Enjoi Bags and Backpacks on Sale at Zephyr", + "head_title" : "Enjoi Backpacks | Enjoi Bags | Enjoi Luggage" + }, + ".0.6" : {}, + ".goggles.save_phace_paintball_goggles" : { + "meta_keywords" : "Save phace paintball goggles, save phace masks, save face paintball mask, thermal paintball goggles, custom paintball goggles, painted paintball mask", + "meta_description" : "Save Phace Paintball Goggles - Zephyr carries the complete line of save phace masks. Save face paintball masks for paintball have a hard outer shell painted with various different high quality graphics. From the Dope to the So Phat series, Save Phace has the masks to protect you and look cool.", + "top_description2" : "Be sure to add the sku PB-SPHC-SGLCLR to your cart along with promo code SPHCLENS to receive your free clear lens with every save phace goggle. While supplies Last", + "zoovy:banner_image_01" : "banners/categories/savephace_lenses_clickhere_001.jpg", + "zoovy:banner01" : "banners/paintball/headers/goggleaccessories_header001", + "banner01_link" : "/category/goggles.1goggle_accesories.save_phace_goggle_accesories/", + "page_title" : "Buy Save Phace Paintball Goggles Online On Sale Now", + "head_title" : "Save Phace Paintball Goggles | Save Phace Masks | Save Face Paintball Mask", + "sortby_var" : "Save Phace Goggle Type" + }, + ".barrels.barrels_by_manufacturer.valken_paintball_barrels" : {}, + ".paintball.player_apparel.paintball_pants" : {}, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_sugar_beach_sunglasses" : { + "meta_description" : "Maui Jim Sugar Beach Sunglasses - Zephyr Sports carries a complete line of Maui Jim Sugar Beach Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Sugar Beach Online Today.", + "page_title" : "Maui Jim Sugar Beach Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Sugar Beach Sunglasses | Maui Jim Sugar Beach Sun Glasses | Sunglasses Maui Jim Sugar Beach" + }, + ".apparel.jerseys.virtue_paintball_jerseys" : { + "page_title" : "", + "head_title" : "Virtue Paintball Jerseys | Virtue Jersey | Virtue Paintball" + }, + ".3packagespecials.azodin_paintball_packages.azodin_zenith_ii" : { + "meta_keywords" : "Azodin Zenith II Paintball Guns,Azodin Zenith Painball Markers,Azodin Zenith II Paintball Packages,Paintball equipment", + "meta_description" : "Azodin Zenith Paintball Gun Packages - Buy your Azodin Zenith II Painball Markers Online at Zephyr Paintball for Less today. Free Shipping on Azodin Zenith II Paintball Packages.", + "page_title" : "Buy Azodin Zenith Paintball Gun Packages Online On Sale Now", + "head_title" : "Azodin Zenith II Paintball Guns | Azodin Zenith Painball Markers | Azodin Zenith II Paintball Packages" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_gloves" : { + "head_title" : "Sale Paintball Gloves | Clearance Paintball Gloves | Paintball Gloves Sale" + }, + ".promotion_codes" : { + "banner4_link" : "/category/promotion_codes.free_items ", + "banner2" : "banners/categories/promo_code_spend_50_001", + "banner3_link" : "", + "banner1" : "banners/categories/how_to_005.png", + "banner4" : "images/site_specific/free_items/free_item_200_shirt_mat_002", + "banner3" : "images/site_specific/free_items/promo_code_spend_100_free_shipping_001.jpg", + "banner2_link" : "/category/promotion_codes.free_items" + }, + ".markers.empire_axe_paintball_guns.empire_sniper_paintball_guns" : { + "top_description2" : "==Empire Sniper Pump Paintball Gun==\n\nThe new Empire Sniper Pump Paintball Gun is Here. The Sniper Pump is a Tournament Level Marker. It comes with: 3 Barrel Inserts (.675, .680, .685), an On/Off ASA, Stainless Steel Pump Rods, and more. Not only is Empire bringing the pump back, they are doing so in style!! The Empire Sniper pump is available in limited quantities so act fast before we sell out again.", + "page_title" : "Empire Sniper Pump Paintball Gun", + "head_title" : "Empire Sniper Pump | Sniper Pump | Empire Sniper Paintball Guns", + "description" : "Tired of wasting paint all day? Pump paintball is a complete different game. You'll be amazed how much you will learn when you have to move around the field with your sniper pump instead of just hanging back and throwing paint. Ever wonder how that guy at the field with the pump always takes out a bunch of people while firing less than 50 shots? The empire sniper pump is insanely accurate with the included barrel inserts. The Sniper pump can either be set to use a 10 round tube for stock play, or add a 50 round hopper for a little extra paint. We recommend a 13ci compressed air tank for the Sniper pump." + }, + ".testing_help_desk.holiday_shipping_cutoffs" : { + "dynimage1" : "images=banners/holiday/holidayshipping_big_12_8_11,banners/holiday/shipping_deadlines\nlinks=%SESSION%/category/testing_help_desk.holiday_shipping_cutoffs,%SESSION%/category/testing_help_desk.holiday_shipping_cutoffs\npauses=5000,5000\nblank_behavior=none\n", + "zs_banner_right1" : "ALT=&IMG=&LINK=", + "top_description2" : "= Holiday Shipping Deadlines =\nPlease note that the dates above are not guaranteed. Rather these are typical shipping times, where weather can impact shipping speeds at this time of year. Orders must be placed by Noon on specified deadline date. Happy shopping!\n\n\n= 35% OFF FedEx Overnight Shipments* =\nZephyr is feeling generous! We want to help all of you that have procrastinated just a weeeee bit too long! We are offering 35% Off FedEx Overnight Delivery shipping rates 'til Monday (12/23) @ Noon! Orders must be over $100 & Weigh in Under 25lbs.. No coupon code required. All rates automatically discount in cart.", + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=&LINK=", + "zs_banner_right2" : "ALT=&IMG=&LINK=", + "zoovy:banner01" : "banners/holiday/holiday_shipping_lastchance_35off_nextday_slideshow.jpg", + "zs11_banner_wslideshow_slide2" : "ALT=&IMG=&LINK=" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_campus_backpacks" : { + "meta_description" : "Dakine Campus Backpacks - Buy your Campus Dakine Bags At Zephyr Sports for Less Today! We carry a complete line of Dakine Campus Packs at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Campus Backpacks & Bags Ship Free ", + "head_title" : "Dakine Campus Backpacks | Campus Dakine Bags |Dakine Campus Packs" + }, + ".apparel.gloves.paintball_gloves_by_size.2.small_paintball_gloves" : { + "page_title" : "", + "head_title" : "Small Paintball Gloves | Small Gloves for Paintball | Small Paintballing Gloves" + }, + ".casual_clothing.mens_clothing.shorts.metal_mulisha_shorts" : { + "meta_description" : "Metal Mulisha Shorts - Zephyr stocks a complete line of Metal Mulisha Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Metal Mulisha needs. ", + "page_title" : "Metal Mulisha Shorts with Free Shipping at Zephyr", + "head_title" : "Metal Mulisha Shorts | Metal Mulisha Board Shorts" + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.scar_airsoft_guns" : { + "meta_description" : "SCAR Airsoft Guns - Buy your Airsoft SCAR At Zephyr Sports for Less Today! We carry a complete line of SCAR AEG Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "Below are replica SCAR Airsoft Rifles. The original SCAR Rifle, or Special Combat Assault Rifle is made by FN Herstal for the United States Special Operations Command (SOCOM). The SCAR is manufactured in two main versions; Light and Heavy, referring to their ammunition/rate of fire. \n\n\nThe SCAR has been in service by the U.S. Armed Forces since 2009 and truly is a special forces rifle with all of its accessories and ability. ", + "page_title" : "Buy SCAR Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "SCAR Airsoft Guns |Airsoft SCAR |SCAR AEG Airsoft Gun", + "description" : "" + }, + ".casual_clothing.mens_clothing.beanies.globe_beanies" : { + "meta_keywords" : "Globe beanie,Globe hat,Globe beanies,Globe caps,Globe 686,Globe headwear,Globe cuff visor beanie,Globe beanie hat,Globe visor beanie,Globe visor beanies", + "meta_description" : "Globe Deanie - Surf style with Globe Beanies available now at Zephyr Sports. Get your Globe hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Globe Beanies on Sale at Zephyr Today", + "head_title" : "Globe Beanie | Globe Hat | Globe Beanies" + }, + ".harnessesbags.backpacks.ogio_backpacks.ogio_hydration_packs" : { + "page_title" : "", + "head_title" : "OGIO Hydration Packs Ship Free @ Zephyr Sports " + }, + ".harnessesbags.paintball_gear_bags.kingman_gear_bags___backpacks" : {}, + ".misc_items.portable_fields" : { + "meta_keywords" : "inflatable paintball fields, portable paintball fields, paintball bunkers", + "page_title" : "", + "head_title" : "Inflatable Paintball Fields | Portable Paintball Fields | Paintball Bunkers" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray-ban_rb8307_aviator_tech_sunglasses" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys.dye_clearance_paintball_jerseys" : {}, + ".markerupgrades.gog_paintball_gun_upgrades.gog_extcy" : {}, + ".snowboard_gear.snowboard_goggles.electric_snowboard_goggles.electric_eg25_snow_goggles" : { + "meta_description" : "Electric EG2.5 Goggles - Zephyr Sports carries a complete line of EG2.5 Electric Goggles At the lowest prices on the web with free shipping and easy returns. Buy your Electric Goggles EG2.5 Online Today.", + "page_title" : "Electric EG2.5 Goggles On Sale Free Shipping", + "head_title" : "Electric EG2.5 Goggles | EG2.5 Electric Goggles | Electric Goggles EG2.5" + }, + ".paintball.paintball_goggles.1goggle_accesories.dye_goggle_accesories" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.aeg_mid_capacity_mags" : {}, + ".airsoft.tactical_airsoft_gear.tactical_helmets" : { + "meta_description" : "Airsoft Tactical Helmets - Buy your Airsoft Helmets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Tactical Helmets On Sale & Free Shipping", + "head_title" : "Airsoft Tactical Helmets | Airsoft Helmets" + }, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories.511_molle_accessories" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_full_4136_bluto_sunglasses" : { + "meta_description" : "Arnette Bluto Sunglasses - Zephyr Sports carries a complete line of Bluto Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Bluto Sun Glasses Online Today.", + "page_title" : "Arnette Bluto Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Bluto Sunglasses | Bluto Arnette Sunglasses | Arnette Bluto Sun Glasses" + }, + ".3packagespecials.gog_paintball_packages.enmey_packages" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_scifly_2" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys Scifly Sunglasses", + "meta_description" : "Black Flys Scifly Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Fly Scifly Sunglasses.", + "head_title" : "Black Flys Scifly 2 Sunglasses | Black Flys Scifly Sunglasses" + }, + ".markerupgrades.proto_matrix_upgrades.proto_matrix_bolts" : {}, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_etek_paintball_guns" : { + "banner2" : "", + "meta_keywords" : "Etek 3,etek 4,etek4, Etek ego paintball guns, etek ego, etek 2 paintball gun, etek paintball gear, Eclipse Etek ego, Etek Paintball,etek3,etek 4,5,6,7,8", + "meta_description" : "Eclipse Etek Ego Paintball Guns - Etek 3 Paintball Gun in stock and shipping today. Planet Eclispe Etek 4 on the way. Finally an Eclipse Ego Paintball gun that the masses can afford. Ego performance for half the price. Etek, Etek 2, and etek3, 4,5,6 Paintball Markers available", + "top_description2" : "=Planet Eclipse Etek 4 Paintball Markers=\n\nFinally an Eclipse Etek Paintball marker that the masses can afford. Introducing the Planet Eclipse Etek 4 Ego Paintball Gun. All the performance of an Etek Ego for half the price! Check out the specs on cheap Etek 4 Paintball gear now! ", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.planet_eclipse_package_specials.etek_package_specials/", + "zoovy:banner02" : "banners/paintball/slideshow/planet_eclipse_etek4_slideshow.jpg", + "description" : "An Eclipse Marker is more than just a collection of metal and wires. It is the Complete Package. Each Etek3 Paintball Marker is hand built & tested in a Planet Eclipse facility here in the United Kingdom to ensure quality.\n\n\n\n\n=Etek LT=\nThis 'base' model features composite parts, used for the very first time on an Eclipse marker. The Feed tube, Eye Covers and Frame are manufactured from Glass Reinforced Nylon [GRN] a very durable material that is both tough and rigid. All other parts of the ETEK3 are manufactured from exactly the same materials with the finishes you will find on the Ego10 and SL range; high grade aluminum and stainless steel coupled with deep cosmetic and industrial hard anodizing. \n\n\n\n\n=Etek AM=\nThe AM is intrinsically identical to the LT, but has an All Metal construction. The Frame, Eye Covers and Feed tube are all high-grade aluminum just as you will find on the rest of the marker. The AM also has the ability to be instantly enhanced with an Emortal LCD upgrade circuit board. \n\n\n\n\n==Features:==\n\n\n\n\n\n\n\n\n* LED Board - 3 tru-colour LED indicators\n* Programmable Firing Modes\n* On/Off Purge System\n* Break Beam Sensor System\n* Fully Adjustable Trigger\n* 2-Piece Barrel - 14\"\n* S3 Inline Regulator\n* New Direct Mounted Solenoid\n* Cure Bolt\n* Zick Kit\n* New Smaller Rammer Housing\n* Deftek Offset Feed\n* One-Piece Body (No FRM)\n* Emortal LCD Circuit Board Upgradeability (AM Only!)\n", + "banner2_link" : "/category/markerupgrades.planet_eclipse_etek_upgrades.etek_trigger_upgrades/", + "htmlvids" : "", + "head_title" : "Etek 4 Ego Paintball Guns | Eclipse Etek 4 Paintball Markers | Planet Eclipse Etek 4", + "page_title" : "Buy Etek 4 Ego Paintball Guns Online On Sale Now" + }, + ".airsoft.shop_by_brand.classic_army_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Classic Army | Classic Army m15a4 | Classic Army M4" + }, + "$as_homepage" : {}, + ".shop_by_brand.draxxus_dxs" : {}, + ".return_request.not_defective" : { + "description" : "Upon completion of this form, you will be contacted within 2 business days with an RMA number and instructions for returning the item(s) in question. If you do not receive any response, please do not fill out another request. Simply call customer support at 877.814.4297 or email us at support@zephyrsports.com and include your Order# with a description of your return request. " + }, + ".markerupgrades.planet_eclipse_ego_upgrades.ego_board_upgrades" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_fixed_power_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.slg_grip_panel" : {}, + ".3packagespecials.empire_paintball_packages.empire_bt.omega" : { + "meta_keywords" : "bt omega, bt omega packages, woodsball paintball, battle tested packages, battle tested markers, omega paintball gun", + "htmlvids" : "
                                                                          \n\n
                                                                          ", + "meta_description" : "BT Omega Paintball Guns - Buy your Empire BT Omega Online at Zephyr Paintball for Less today. Free Shipping on Omega Tactical Paintball Markers Trust Zephyr for all your Paintball Needs", + "top_description" : "==The new BT Omega Paintball Marker will take you into battle without breaking the bank!==\n\nThe rugged aluminum body will withstand heavy duty combat situations and provides increased performance and durability. The Omega will require little in terms of regular maintenance. Fully upgradeable, the Omega easily accepts numerous BT upgrades, such as the HALO powered Rip Clip,the BT1913 Barrel, the BT Clamp Elbow Kit and the Tactical Folding Stock. Carrying your marker out to battle has never been easier thanks to its secure carry handle. The Omega's permanent, fixed sight rail provides you a continuous lock on your opponents, thereby giving you the confidence needed to take them out of the game. Grab your gear, lock and load and hit the field running with the Omega today!\n\n", + "page_title" : "Buy BT Omega Paintball Packages Online On Sale Now", + "head_title" : "BT Omega Paintball Guns | Empire BT Omega | Omega Tactical Paintball Markers", + "description" : "=BT Omega Features=\n\n\n* Rugged Aluminum Body\n* Multi-Position Adjustable Stock\n* BT Rip Clip Compatible\n* Accepts CO2 or High Pressure Air Sources\n* Adjustable Velocity\n* Stainless Steel Braided Air Hose\n* Secure Carry Handle\n* Fixed Sight Rail\n* Removable Magazine with Tool Storage\n* Built-In Sling Attachments\n* Comes with O-rings and allen wrenches to help maintain your gun.\n" + }, + ".safetygear.kneeelbowpads.proto" : {}, + ".3packagespecials.planet_eclipse_package_specials.etek_package_specials" : { + "meta_description" : "Planet Eclipse Etek Paintball Packages - Buy your Planet Eclipse Etek Paintball Guns Kits Online at Zephyr Paintball for Less today. Free Shipping on Eclipse Etek Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Planet Eclipse Etek Paintball Packages Online On Sale Now", + "head_title" : "Planet Eclipse Etek Paintball Packages | Planet Eclipse Etek Paintball Guns Kits | Eclipse Etek Paintball Markers" + }, + ".barrels.freakbarrels" : {}, + ".apparel.knee___elbow_pads.nxe_knee___elbow_pads" : { + "page_title" : "", + "head_title" : "NXe Elbow Pads | NXe Knee Pads | NXe Paintball Protection" + }, + ".markers.infinity_paintball_guns" : {}, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_mr100_paintball_gun_packages" : { + "head_title" : "Spyder MR100 Paintball Packages | Spyder MR100 Paintball Gun Packages" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_half_jacket_sunglasses" : { + "meta_keywords" : "Oakley Half Jacket Sunglasses,Half Jacket oakley sunglasses,oakley Half Jacket, Half Jacket polarized sunglasses", + "meta_description" : "Oakley Half Jacket Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Half Jacket and Polarized Oakley Half Jacket Sunglasses on Sale! ", + "page_title" : "Oakley Half Jacket Sunglasses with Free Shipping", + "head_title" : "Oakley Half Jacket Sunglasses | Half Jacket Oakley Sunglassses" + }, + ".airsystems.regulators.dead_on_paintball_regulators" : {}, + ".maddog.safety_gear" : {}, + ".3packagespecials.us_army_paintball_packages.us_army_carver_one_packages" : { + "meta_description" : "US Army Carver One Package - Buy your Carver One Package Online at Zephyr Paintball for Less today. Free Shipping on Tippmann carver Package Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy US Army Carver One Package Online On Sale Now", + "head_title" : "US Army Carver One Package | Carver One Package | Tippmann carver Package" + }, + ".markerupgrades.feednecks.autococker_feednecks" : { + "meta_description" : "Autococker Feed Necks - Buy your Feednecks for Autococker Online at Zephyr Paintball for Less today. Free Shipping on Autococker Feed Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Autococker Feed Necks Online On Sale Now", + "head_title" : "Autococker Feed Necks | Feednecks for Autococker | Autococker Feed" + }, + ".casual_clothing.mens_clothing.tshirts.darkstar_t_shirts" : { + "meta_keywords" : "Darkstar T Shirts,Darkstar shirts,free shipping,Darkstar TShirt", + "meta_description" : "Darkstar T Shirts - Zephyr carries a complete line of Darkstar Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Darkstar T Shirts at Zephyr", + "head_title" : "Darkstar T Shirts | Darkstar Shirts | Darkstar TShirt" + }, + ".shop_by_brand.511_tactical" : { + "top_html" : "", + "top_description2" : "=5.11 Tactical=\nIn the battle field, you can't afford to be caught without the best equipment possible. 5.11 Tactical Gear has been in the tactical industry for years, and they know better than anyone that cheap material is the difference between life and death. 5.11 Tactical Does not offer cheap material. They do not compromise your product. If you are serious about your work and play 511 is the only way to go. 5.11 offers a wide array of products ranging from belts and pants to hats and shirts. 5.11 has your back, if you are willing to choose Quality over all else.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/1_5_11_tactical_header" + }, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories.molle_mag_pouches" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsystems.tankcovers.eclipse_paintball_bottle_covers" : { + "meta_description" : "Eclipse Tank Cover - Buy your Eclipse Bottle Cover Online at Zephyr Paintball for Less today. Free Shipping on Planet Eclipse Tank Covers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Eclipse Tank Cover Online On Sale Now", + "head_title" : "Eclipse Tank Cover | Eclipse Bottle Cover | Planet Eclipse Tank Covers" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.g_g_armament_aeg_airsoft_rifles" : { + "meta_keywords" : "G&G Armament,AEG rifles,high-end AEG rifles,AK47,UMG,MP5,M16,G&G airsoft,airsoft aeg,airsoft guns,", + "meta_description" : "G&G Armament. G&G Armament is a leading designer in high-end AEG rifles. Offering a wide variety of replicas including the AK47, UMG, MP5, M16, and much more. Check out all their airsoft AEG 's! They also offer many variations of different popular rifles. Here you will find both plastic and metal body styles. G&G is a great choice for avid airsoft players looking for high-end, top of the line airsoft guns.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "G&G Armament On Sale & Free Shipping", + "head_title" : "G&G Armament | AEG Rifles | G&G Armament Airsoft", + "description" : "" + }, + ".skateboard_gear.skateboard_decks.1search_by_size.7875__decks" : { + "meta_description" : "7.875\" Skateboards Decks - Zephyr Sports carries a complete line of 7.875 Skate Deck At the lowest prices on the web with free shipping and easy returns. Buy your Skate Deck 7.875 Online Today.", + "page_title" : "7.875\" Skateboards Decks On Sale Free Shipping", + "head_title" : "7.875\" Skateboards Decks |7.875 Skate Deck | Skate Deck 7.875" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_headwear.proto_clearance_headwear" : {}, + ".zzreturns" : { + "description" : "

                                                                          Returns & Exchanges

                                                                          \nReturn Policy & Procedure
                                                                          \nWe offer a 30-Day Money Back Guarantee on all new and unused merchandise in its original packaging, (paintballs excluded). If you plan to return or exchange an item(s), then please follow the prompt bellow.
                                                                          \n

                                                                          Is the item you're returning defective?

                                                                          \n

                                                                          Hint: Did the item NOT work when you opened the box?

                                                                          \n\n
                                                                          \n
                                                                          \n
                                                                          \nPlease Note:
                                                                          \n
                                                                            \n
                                                                          • All returns are subject to a 15% restocking fee
                                                                          • \n
                                                                          • Restocking fee may be waived if Store Credit is preferred
                                                                          • \n
                                                                          • Used products may not be returned. Use is defined as any attempt to open packaging, fire, install, wear or wash.
                                                                          • \n
                                                                          • If you were shipped the incorrect item or an item that differed from the invoice, please note this under the \"Reason for Return\" section of the RMA request form. This is so you receive the appropriate RMA number.
                                                                          • \n
                                                                          • All Manufactures provide at least a 90-day (some offer 1 year) full parts and labor warranty on guns.
                                                                          • \n
                                                                          • All purchasers of paintball markers must be 18 years of age. Purchasers agree to abide to all local laws and regulations in their area.
                                                                          • \n
                                                                          • Purchasers are responsible for all importation taxes and duties imposed.
                                                                          • \n
                                                                          • We will not accept exchanges / returns on defective merchandise, please contact the manufacturer.
                                                                          • \n
                                                                          • Shipping costs for returns are the responsibility of the purchaser. Shipping will be charged on returns that received free shipping. Shipping costs will not be refunded on returns or refused packages
                                                                          • \n
                                                                          • No returns accepted without RMA (Return Merchandise Authorization) number.
                                                                          • \n

                                                                          \nFeel free to contact our office at 877.814.4297 with any questions or concerns. Zephyr Sports will not be held responsible for any typographical errors made when filling out the RMA request form. Paintball guns are not toys and should be handled as such. Airsoft guns are required to have the tip (1/4 inch) of the barrel permanently colored in blaze orange or red.

                                                                          \nAll pricing is listed in U.S. Dollars (USD$)." + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.bt_combat_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_mayfield_sunglasses" : { + "meta_description" : "Von Zipper Mayfield Sunglasses - Zephyr Sports carries a complete line of Buy Mayfield Von Zipper Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Von Zipper Mayfield Sunglasses Free Shipping Online Today.", + "page_title" : "Von Zipper Mayfield Sunglasses On Sale Free Shipping", + "head_title" : "Von Zipper Mayfield Sunglasses | Buy Mayfield Von Zipper Sunglasses | Von Zipper Mayfield Sunglasses Free Shipping" + }, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_nomad_polarized_sunglasses" : { + "meta_description" : "Suncloud Nomad Polarized Sunglasses - Zephyr Sports carries a complete line of Nomad Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Nomad Sun Glasses Online Today.", + "page_title" : "Suncloud Nomad Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Nomad Polarized Sunglasses | Nomad Suncloud Sunglasses Free Shipping | Buy Suncloud Nomad Sun Glasses" + }, + ".markers.btdesignspaintballguns.empire_bt_tracer_paintball_guns" : { + "meta_keywords" : "Empire BT Tracer Paintball Gun,BT Tracer Paintball Pistol,Empire BT Tracer Paintball Pistol,BT Paintball,Paintball Pistol,paintball gear,Pump paintball,BT Pump Paintball Gun", + "meta_description" : "Empire BT Tracer Paintball Gun - Always be prepared w/ the BT Tracer Paintball Pistol! Empire BT Tracer Paintball Guns are accurate and reliable! Don't forget to pick up a couple extra mags! Pump 'em full of paint with Empire BT Paintball gear! Play pump paintball with the Empire BT Tracer Paintball Pistol.", + "top_description" : "Empire BT Tracer Paintball Gun - The internals of the new Empire Tracer paintball gun are compatible with the original PMI Tracer which have been proven for the past 15+ years.\nWhen you take hold of the pump handle on the new BT Tracer Paintball Pistol you will feel the most comfortable and ergonomic handle. Those old days of struggling to pump your gun are gone for good.\nPicatinny rails are mounted on the top of the Empire Tracer so you can mount all of your favorite accessories. ", + "page_title" : "Buy Empire BT Tracer Paintball Gun Online On Sale Now", + "head_title" : "Empire BT Tracer Paintball Gun | BT Tracer Paintball Pistol | Empire Tracer", + "description" : "The Empire Tracer is compatible with either CO2 or HPA and will accept any Autococker threaded barrel or barrel kit. The Empire Tracer pump paintball gun is affordable to any new player, pump player or anyone looking to bring back some old memories.\n\n\n=Features:=\n\n* 68 Caliber Pump Action Gun\n* Empire Trracer Based Off Of PMI Trracer\n* Internals Compatible With PMI Trracer\n* First Strike Compatible Breech\n* Picatinny Rails\n* Cocker Threaded 14\" Barrel\n* Works w/ CO2 or HPA\n" + }, + ".airsystems.dropforwards.proto_asa_s" : {}, + ".loaders.invert_paintball_hoppers.invert_reloader_2" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.spyder_mrx_paintball_guns" : {}, + ".airsystems.regulators.dye" : { + "meta_keywords" : "paintball regulator, dye hyper regulator, dye hyper 3 regulator, hyper 4, hyper 2, DM9 regulator", + "meta_description" : "Dye Hyper Regulator - The ultimate paintball regulator from Dye. Released in 2009, the Dye Hyper 3 Regulator revolutionized the paintball world. Ultralight, eficcient and highly adjustable", + "page_title" : "Buy Dye Paintball Regulator Online On Sale Now", + "head_title" : "Dye Paintball Regulator | Dye Hyper Regulator | Dye Hyper 3 Regulator" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_51-30_tide_watches" : {}, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_heavy_metal_sunglasses" : { + "meta_description" : "Hoven Heavy Metal Sunglasses - Zephyr Sports carries a complete line of Hoven Heavy Metal Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Heavy Metal Online Today.", + "page_title" : "Hoven Heavy Metal Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Heavy Metal Sunglasses | Hoven Heavy Metal Sun Glasses | Sunglasses Hoven Heavy Metal" + }, + ".markerupgrades.grips_and_grip_panels.hybrid_paintball_grips.hybrid_ego_paintball_grips" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_roulette_hydration_packs_" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_variable_power_scopes.leapers_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.dvs_beanies" : { + "meta_keywords" : "DVS beanie,DVS hat,DVS beanies,DVS caps,DVS 686,DVS headwear,DVS cuff visor beanie,DVS beanie hat,DVS visor beanie,DVS visor beanies", + "meta_description" : "DVS Deanie - Surf style with DVS Beanies available now at Zephyr Sports. Get your DVS hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "DVS Beanies on Sale at Zephyr Today", + "head_title" : "DVS Beanie | DVS Hat | DVS Beanies" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_sonic_fly_2" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys Sonic Sunglasses", + "meta_description" : "Black Flys Sonic Fly Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Fly Sonic Fly Sunglasses.", + "head_title" : "Black Flys Sonic Fly 2 Sunglasses | Black Flys Sonic Sunglasses" + }, + ".casual_clothing.mens_clothing.hats.virtue" : {}, + ".skateboard_gear.skateboard_decks.1search_by_size" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.tippmann_x7_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.dragon_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,Dragon chrome sunglasses", + "meta_description" : "Dragon Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. ", + "head_title" : "Dragon Sunglasses | Dragon Chrome Sunglasses | Dragon Eyewear" + }, + ".maddog.ion_upgrades" : {}, + ".casual_clothing.mens_clothing.belts.metal_mulisha_belts" : { + "meta_keywords" : "Metal Mulisha Belts,Metal Mulisha Belt Buckle,Metal Mulisha Belts,Metal Mulisha webbed belt", + "meta_description" : "Metal Mulisha Belts - We carry the complete line of Metal Mulisha Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Metal Mulisha Belts on Sale Now!", + "head_title" : "Metal Mulisha Mens Belts | Aplinestars Belts" + }, + ".airsoft.airsoft_guns.ares_airsoft_guns" : { + "meta_description" : "Ares Airsoft Guns - Buy your Ares Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Ares AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Ares Airsoft Guns On Sale & Free Shipping", + "head_title" : "Ares Airsoft Guns | Ares Airsoft Rifles | Ares AEG", + "description" : "" + }, + ".markerupgrades.invert_upgrades" : { + "meta_keywords" : "invert mini,invert mini upgrades,the invert mini,my invert mini,new invert mini,invert mini barrel", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.empire_paintball_grips/", + "btn2_link" : "/category/markerupgrades.feednecks.impulse_ion_sft_feednecks/", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "btn1_link" : "/category/barrels.autococker/", + "banner4" : "zephyr_buttons/grips_btn001", + "page_title" : "Buy Invert Mini Online On Sale Now", + "btn3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.mini_grip_panel/", + "btn4_link" : "/category/paintball.paintball_guns.invert_paintball_guns.invert_package_specials/?sortby=zoovy:base_price", + "buttonname_04" : "Starter Kits", + "btn2" : "zephyr_buttons/paintball_pop/products_pop/feednecks_popbtn001", + "add1_link" : "/category/barrels.autococker/", + "banner2" : "zephyr_buttons/barrel_btn001", + "meta_description" : "Invert Mini Upgrades - Zephyr Paintball carries the largest supply upgrades for your invert mini. The Invert mini is one of the most upgradeable paintball guns on the market. Whether you are looking for a new trigger, high performance bolt or a new upgrade board, we have you covered with free shipping over $100", + "btn1" : "zephyr_buttons/paintball_pop/products_pop/barrels_popbtn001", + "buttonname_01" : "Barrels", + "btn3" : "zephyr_buttons/paintball_pop/products_pop/grips_popbtn001", + "add2_link" : "/category/markerupgrades.feednecks.impulse_ion_sft_feednecks/", + "buttonname_02" : "Feednecks", + "head_title" : "Invert Mini | Invert Mini Upgrades | The Invert Mini", + "btn4" : "zephyr_buttons/paintball_pop/products_pop/mini_guns_packages_popbtn.jpg" + }, + ".3packagespecials.tippmann_packages.tippmann_tpx_paintball_pistols" : { + "meta_description" : "Buy Tippmann TPX Pistol - Buy your Tippmann TPX Paintball Pistol Online at Zephyr Paintball for Less today. Free Shipping on TPX Tippmann Pistol Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Buy Tippmann TPX Pistol Online On Sale Now", + "head_title" : "Buy Tippmann TPX Pistol |Tippmann TPX Paintball Pistol |TPX Tippmann Pistol" + }, + ".casual_clothing.mens_clothing.shorts.hurley_shorts.hurley_phantom_boardshorts" : {}, + ".harnessesbags.backpacks.electric_backpacks_and_bags" : { + "meta_keywords" : "electric bags,electric backpacks,backpack electric,electric duffle bag,flank,electric Duffel bag,caliber corpo,mk1,elite,recoil", + "meta_description" : "Electric Bags - Top Quality Electric Backpacks with Free Shipping from Zephyr Sports. We carry a complete line of Electric Bags including Electric Duffel Bags. ", + "page_title" : "Electric Bags & Backpacks FREE Shipping at Zephyr", + "head_title" : "Electric Bags | Electric Backpacks | Electric Duffel Bag" + }, + ".casual_clothing.mens_clothing.socks.etnies_socks" : { + "meta_keywords" : "Etnies socks,Etnies mens socks,Etnies men socks", + "meta_description" : "Etnies Socks - Zephyr stocks a complete line of Etnies Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Etnies needs. ", + "page_title" : "Etnies Socks on Sale at Zephyr", + "head_title" : "Etnies Socks | Etnies Mens Socks" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_crossover_sunglasses" : { + "meta_description" : "Electric Crossover Sunglasses - Zephyr Sports carries a complete line of Electric Crossover Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Crossover Online Today.", + "page_title" : "Electric Crossover Sunglasses On Sale Free Shipping", + "head_title" : "Electric Crossover Sunglasses | Electric Crossover Sun Glasses | Sunglasses Electric Crossover" + }, + ".backpacks.camelback_backpacks.camelbak_winter_hydration_packs._camelbak_snoblast_hydration_packs_" : {}, + ".casual_clothing.mens_clothing.tshirts.powell_peralta_t_shirts" : { + "meta_keywords" : "powell peralta t shirts, skate shirts, powell shirts, Powell T shirts, ", + "meta_description" : "Powell Peralta T Shirts - Zephyr carries a complete line of Powell Shirts and Apparel. Low Prices, Free Shipping Zephyr has you covered.", + "page_title" : "Buy Powell Peralta T Shirts On Sale & Free Shipping", + "head_title" : "Powell Peralta T Shirts | Powell Shirts | Powell T Shirts" + }, + ".markerupgrades.tippmann.tippmann_x7_upgrades.tippmann_x_7_foregrip_upgrades" : {}, + ".casual_clothing.youth_clothing.youth_t_shirts.electric_youth_t_shirts" : {}, + ".harnessesbags.paintball_gear_bags.maddog_designz_gear_bags" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_farrah_sunglasses" : {}, + ".harnessesbags.packs___harnesses.java_pod_packs" : { + "meta_keywords" : "kingman harness, spyder paintball harness, kingman pod pack, kingman spyder paintball harness, spyder paintball pack, java paintball harness, java pack", + "meta_description" : "Kingman Harness - Buy your Spyder Paintball Harness Online at Zephyr Paintball for Less today. Free Shipping on Kingman Pod Pack Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Kingman Harness Online On Sale Now", + "head_title" : "Kingman Harness | Spyder Paintball Harness | Kingman Pod Pack" + }, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.nixon_headphones.nixon_tps_speakers" : { + "head_title" : "Nixon TPS Headphones | TPS Nixon Head Phones | Nixon TPS Headphone" + }, + ".scenarioupgrades.scenario_paintball_guns" : { + "meta_keywords" : "tippmann paintball guns,tactical paintball,military paintball guns,scenario paintball guns,realistic", + "ad3_link" : "/product/PB-BT-OMEGABLK/", + "btn07_name" : "Tippmann Paintball Guns", + "btn05_link" : "/category/markers.rap4_paintball_guns/", + "ad03" : "banners/paintball/side_banners/bt_deltaelite_sidebanner001", + "btn04" : "zephyr_buttons/cci_logo_btn002", + "btn07" : "zephyr_buttons/tippmann_gunpage_btn001", + "btn02_link" : "/category/markers.valken_paintball_guns/", + "btn04_name" : "CCI Paintball Guns", + "cross_bar" : "images/site_specific/hot_items_crossbard_001.jpg", + "btn04_link" : "/category/markers.cci_paintball_guns/", + "page_title" : "Buy Military Paintball Guns Online On Sale Now", + "ad2_link" : "/product/PB-TIP-X7PHENOM/", + "btn06_link" : "/category/markers.tiberius_arms_paintball_guns/", + "btn08" : "zephyr_buttons/usarmy_gunpage_btn001", + "meta_description" : "Military Paintball Guns - When your not just looking to throw Paint! Check out our line of scenario Paintball Guns for that true military look. Huge selection of Tippmann, BT and more", + "banner01" : "banners/09_headers/main_categories/scenario_guns_001.png", + "ad1" : "banners/paintball/side_banners/valken_vtac_sw_1_sidebanner001", + "btn06_name" : "Tiberius Arms Paintball Guns", + "ad01_link" : "/product/PB-VTAC-SW1BLK/", + "btn08_link" : "/category/markers.us_army_paintball_guns/", + "top_html" : "\n\n \n \n \n \n\n
                                                                          \n \n \n \n \n \n \n
                                                                          \n \n
                                                                          \n
                                                                          ", + "btn01_link" : "/category/markers.ariakon/", + "ad03_link" : "/product/PB-BT-DELITE/", + "btn06" : "zephyr_buttons/tiburiusarms_gunpage_btn001", + "ad2" : "banners/paintball/side_banners/tippmann_x7phenom_sidebanner001", + "btn02_name" : "Valken Paintball Guns", + "ad01" : "banners/paintball/side_banners/valken_vtac_sw_1_sidebanner001", + "btn05_name" : "RAP4 Paintball Guns", + "btn08_name" : "US Army Paintball Guns", + "btn05" : "zephyr_buttons/rap4_gunpage_btn001", + "3widead_title" : "Popular Scenario Paintball Guns", + "btn03" : "zephyr_buttons/bt_gunpage_btn001", + "btn01_name" : "Ariakon Paintball Guns", + "btn03_name" : "BT Paintball Guns", + "prodlist1_header" : "Featured Scenario Paintball Guns", + "btn03_link" : "/category/markers.btdesignspaintballguns/", + "btn01" : "zephyr_buttons/ariakon_gunpage_btn001", + "btn_title" : "Scenario Paintball Guns By Brand", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "ad3" : "banners/paintball/side_banners/bt_omegatactical_sidebanner001", + "btn02" : "zephyr_buttons/paintball_pop/products_pop/valkengun_popbtn001", + "ad1_link" : "/product/PB-VTAC-SW1BLK/", + "head_title" : "Military Paintball Guns | Scenario Paintball Guns | TippmannTactical Markers", + "btn07_link" : "/category/markers.tippmann/" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4144_wager_sunglasses" : { + "meta_description" : "Arnette Wager Sunglasses - Zephyr Sports carries a complete line of Wager Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Wager Sun Glasses Online Today.", + "page_title" : "Arnette Wager Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Wager Sunglasses | Wager Arnette Sunglasses | Arnette Wager Sun Glasses" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_winter_hydration_packs._camelbak_snoblast_hydration_packs_" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.team_sd_tactical_aeg_airsoft_guns" : { + "meta_description" : "TSD Airsoft Guns - Buy your Team SD Tactical Airsoft Guns Online At Zephyr Sports for Less Today! We carry a complete line of Team SD Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy TSD Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "TSD Airsoft Guns | Team SD Tactical Airsoft Guns | Team SD Airsoft Guns" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_roller_bags" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_kensington_watches" : {}, + ".airsoft.airsoft_accessories.airsoft_holsters" : { + "meta_keywords" : "Airsoft Holsters,Airsoft Pistol Holster,Airsoft Gun Holster,Airsoft Leg Holster, Airsoft Shoulder Holster,", + "meta_description" : "Airsoft Holsters for pistols and rifles. Airsoft Gun Holsters that can be attached to your shoulder, leg, or belt. Slings and Holsters are an easy way to store and carry your airsoft guns when they are not in use or when you are on the move. Good for tactical or big game scenarios, keep your rifle close and secure without have to hold it all the time. Keep an extra pistol handy when you need to. Airsoft Slings & Holsters.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Rifle Slings | Slings for Airsoft Rifles | 2 3 Point Airsoft Gun Sling" + }, + "*cart" : {}, + ".airsoft.shop_by_brand.thompson" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings" : { + "meta_keywords" : "airsoft slings, airsoft holsters, pistol holsters", + "meta_description" : "Airsoft Holsters for pistols and rifles. Airsoft Gun Holsters that can be attached to your shoulder, leg, or belt. Slings and Holsters are an easy way to store and carry your airsoft guns when they are not in use or when you are on the move. Good for tactical or big game scenarios, keep your rifle close and secure without have to hold it all the time. Keep an extra pistol handy when you need to. Airsoft Slings & Holsters. ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.accessories.lanyards.metal_mulisha_lanyards" : { + "meta_description" : "Metal Mulisha Lanyards - Buy your Lanyards Metal MulishaAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Metal Mulisha Lanyards @ Zephyr Sports", + "head_title" : "Metal Mulisha Lanyards | Lanyards Metal Mulisha" + }, + ".markers.bob_long_paintball_guns.bob_long_m_tac_paintball_gun" : { + "meta_keywords" : "Bob long mtac paintball guns, m-tac paintball, scenario paintball, scenario tactical paintball guns, marq tactical paintball", + "meta_description" : "Bob long Mtac Paintball guns - Zephyr is the largest bob long paintball Distributor on the west coast. Get the hot new M-tac paintball gun at Zephyr today with free shipping on orders over $100. Built on the Marq platform, the M-tac bring tournament firepower to tactical paintball. ", + "page_title" : "Buy bob long mtac paintball guns Online On Sale Now", + "head_title" : "bob long mtac paintball guns | M|tac paintball | Scenario Tactical Paintball Gun" + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones.nixon_headphones.nixon_block_speakers" : {}, + ".casual_clothing.mens_clothing.boots.converse_boots" : { + "meta_keywords" : "Converse boots,Converse boots,Converse tactical boots,Converse assault boot,Converse sabot boot, Converse Work boot,duty boot,leather boot,police boot,miltary boot", + "meta_description" : "Converse Boots - Get you Mens Converse Boots at Zephyr today. Free Shipping on all Converse Tactical Boots. We support Active Duty Military and Police", + "page_title" : "Converse Boots with Free Shipping at Zephyr", + "head_title" : "Converse Boots | Converse Mens Boots | Converse Tactical Boot" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_fixed_power_scopes.barska_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_experience_suglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon experience sunglasses", + "meta_description" : "Dragon Experience Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Experience Suglasses" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_pivlock_v90_sunglasses" : { + "meta_description" : "Smith Optics Pivlock V90 Sunglasses - Zephyr Sports carries a complete line of Pivlock V90 Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Pivlock V90 Sun Glasses Online Today.", + "page_title" : "Smith Optics Pivlock V90 Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Pivlock V90 Sunglasses | Pivlock V90 Smith Sunglasses Free Shipping | Buy Smith Pivlock V90 Sun Glasses" + }, + ".markerupgrades.intimidator" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts.oakley_replacement_lenses.oakley_radar_replacement_lenses" : { + "meta_description" : "Oakley Radar Lenses - Zephyr Sports carries a complete line of Radar Oakley Replacement Lenses At the lowest prices on the web with free shipping and easy returns. Buy your Radar Oakley Lenses Online Today.", + "page_title" : "Oakley Radar Lenses On Sale Free Shipping", + "head_title" : "Oakley Radar Lenses | Radar Oakley Replacement Lenses | Radar Oakley Lenses" + }, + ".apparel.shoes.1_search_by_color.black_mens_shoes" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_cletus_sunglasses" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_halfwire_20_sunglasses" : { + "meta_description" : "Oakley Halfwire Sunglasses - Buy your Half Wire 2.0 Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Oakley Half Wire at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Halfwire Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Halfwire Sunglasses | Half Wire 2.0 Sunglasses | Oakley Half Wire" + }, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_mach_fly_sunglasses" : {}, + ".casual_clothing.z-sunglasses.revision_eyewear_sunglasses" : { + "meta_description" : " - Zephyr Sports carries a complete line of At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Revision Eyewear On Sale Free Shipping", + "head_title" : "Revision Eyewear | Revision Sunglasses | Revision Goggles" + }, + ".shop_by_brand.polar" : {}, + ".2clearance.clearance_sunglasses" : {}, + ".barrels.autococker.other_autococker_paintball_barrels" : { + "meta_description" : "Autococker Sniper Paintball Barrels - Buy your Autococker Threaded Barrels Online at Zephyr Paintball for Less today. Free Shipping on Two Piece Cocker Paintball Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Autococker Sniper Paintball Barrels Online On Sale Now", + "head_title" : "Autococker Sniper Paintball Barrels | Autococker Threaded Barrels | Two Piece Cocker Paintball Barrels" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_forum_sunglasses" : { + "meta_description" : "Smith Optics Forum Sunglasses - Zephyr Sports carries a complete line of Forum Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Forum Sun Glasses Online Today.", + "page_title" : "Smith Optics Forum Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Forum Sunglasses | Forum Smith Sunglasses Free Shipping | Buy Smith Forum Sun Glasses" + }, + ".markerupgrades.smartparts.ion.triggers" : { + "prodlist1" : "&SORTBY=NONE&FORMAT=DEFAULT&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".3packagespecials.brass_eagle_packages" : { + "meta_description" : "Brass Eagle Paintball Package - Buy your Brass Eagle Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Brass Eagle Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Brass Eagle Paintball Package Online On Sale Now", + "head_title" : "Brass Eagle Paintball Package | Brass Eagle Paintball Guns | Brass Eagle Markers" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_mellor_watches" : { + "meta_description" : "Nixon Mellor Watches - Buy your Nixon Mellor Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Mellor at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Mellor Watches", + "head_title" : "Nixon Mellor Watches | Nixon Mellor Watch | Nixon Mellor" + }, + ".airsoft.airsoft_apparel.head_gear.voodoo_tactical_head_gear" : {}, + ".markers.1-electronic_paintball_guns_markers" : {}, + ".airsoft.airsoft_accessories.airsoft_bags_and_gun_cases" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Gun Case | Bag for Airsoft Gun | Pistol Guns Cases" + }, + ".skateboard_gear.skateboard_accessories.skateboard_grip_tape" : { + "meta_keywords" : "Skateboard Grip Tape,Skateboard Equipment,Skateboard Decks,Skateboard Tools,Skateboard,Grip tape", + "meta_description" : "Skateboard Grip Tape - Zephyr Sports has all your Skateboard Equipment! Customize your Skateboard Decks w/brand new rolls of Skateboard Grip Tape! Zephyr has all of your Skateboard Accessories and the Skateboard Tools to make it happen! Grip Tape @ Zephyr Sports! ", + "page_title" : "Buy Skateboard Grip Tape On Sale & Free Shipping", + "head_title" : "Skateboard Grip Tape | Skateboard Equipment | Skateboard Decks" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_fixed_power_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.element_beanies" : { + "meta_keywords" : "Element beanie,Element hat,Element beanies,Element caps,Element 686,Element headwear,Element cuff visor beanie,Element beanie hat,Element visor beanie,Element visor beanies", + "meta_description" : "Element Deanie - Surf style with Element Beanies available now at Zephyr Sports. Get your Element hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Element Beanies on Sale at Zephyr Today", + "head_title" : "Element Beanie | Element Hat | Element Beanies" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs.women_s_camelbak_helena_hydration_packs" : {}, + ".shop_by_brand.dragon" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.galil_aeg_electric_guns" : { + "meta_keywords" : "Kalashnikov,Galil Replica Airsoft Guns,airsoft replicas,CYMA Galil Rifles,CYMA Galil SAR Airsoft Guns,Galil Electronic Guns,Airsoft Electronic Guns,AEG", + "meta_description" : "Galil Replica Airsoft Guns. The Galil is a family of Israeli small arms produced by the Israel Military Industries (IMI) Ltd, the same group that produced the desert eagle pistol. The Galil family is similar to the Kalashnikov design in operation and shares similarities in the design. The Galil though, comes in many different variations. These Airsoft Electronic Guns are top quality! These AEG airsoft replicas offer a very realistic look and feel including a heavier feel for added realism. The high-end versions offer full metal bodies and higher rates of fire.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Galil Electronic Guns On Sale & Free Shipping", + "head_title" : "Galil Electronic Guns | CYMA Galil Rifles | CYMA Galil SAR Airsoft Guns", + "prodlist1_header" : "Galil AEG Electric Airsoft Guns", + "description" : "" + }, + ".casual_clothing.womens_clothing.ladies_shirts.famous_stars_and_straps_ladies_shirts" : {}, + ".apparel.shoes.etnies_shoes" : {}, + ".loaders.hopper_accesories.odyssey_halo_accesories.halo_back_plates" : { + "meta_description" : "Halo Back Plates - Buy your Halo B Back Plate Online at Zephyr Paintball for Less today. Free Shipping on Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Halo Back Plates Online On Sale Now", + "head_title" : "Halo Back Plates | Halo B Back Plate" + }, + ".casual_clothing.mens_clothing.shirts.north_face_shirts" : { + "meta_description" : "North Face Flannel Shirts - Buy your North Face Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of North Face Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "North Face Shirts & Flannels Ship Free", + "head_title" : "North Face Flannel Shirts | North Face Polo Shirts | North Face Shirts" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_charge_sunglasses" : { + "meta_description" : "Electric Charge Sunglasses - Zephyr Sports carries a complete line of Electric Charge Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Charge Online Today.", + "page_title" : "Electric Charge Sunglasses On Sale Free Shipping", + "head_title" : "Electric Charge Sunglasses | Electric Charge Sun Glasses | Sunglasses Electric Charge" + }, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_09_geo_paintball_guns" : { + "meta_keywords" : "Eclipse Geo3 Paintball Gun, Geo 3 Paintball Marker, Planet Eclipse Geo, spool valve ego, 09 eclipse geo, eclipse geo 09, geo ego", + "meta_description" : "Eclipse Geo3 Paintball Gun - The ultimate Spool valve paintball gun from Planet Eclipse. Buy your Geo 3 paintball marker first at Zephyr", + "top_description" : "The GEO 3.1 has arrived from Planet Eclipse. We received our first few GEO3.1 colors and have tested some of these guns. The GEO3 is a vast improvement over the the GEO 2. Check out the full features on the Geo3 below.", + "zoovy:banner01" : "", + "banner01_link" : "/category/3packagespecials.planet_eclipse_package_specials.geo_package_specials/", + "description" : "== Planet Eclipse Geo3 Paintball Gun ==\n\n= GEO3 Features: =\n\n* All New Solenoid Design - The Geo3 has taken the basic operating principle of the Geo 2.1 and completely reworked it. In order to achieve optimum efficiency in a wide range of circumstances it is beneficial to isolate the firing chamber from the gas supply during firing cycle so that no excess gas is lost down the barrel after the ball has exited. The Geo has always incorporated this feature by selectively controlling supply to the firing chamber via the ISCIS (Innovative Solenoid Controlled Isolation System) Valve. The Geo3 incorporates the Second Generation ISCIS Valve, a complete rework of the original principle aiming to improve efficiency and reliability. The main body of the solenoid is now all aluminum. The secondary spool-driven poppet that controls shut-off of the gas supply to the firing chamber during the firing cycle now works independently of the bolt drive side of the solenoid. The new design also no longer utilizes the back-check ball or the Purge Control Valve (PCV) of the old Geos which reduces parts count and further improves reliability. The whole mechanism is more reliable and far more robust than the old solenoid. More importantly to some, by reducing losses from the solenoid during the firing cycle there has been an increase in efficiency in the Geo3.\n*New Bolt Speed Control (BSC) - A great deal has been learned through the development, testing and subsequent on-field use of the Ego11's adjustable solenoid flow controls. By accurately controlling the flow of the bolt drive exhaust gasses through the solenoid the acceleration and speed of the bolt can be adjusted. Changes in the bolt speed results in changes to feel, sound signature, paint handling, rate of fire and even efficiency. By allowing the user access to this type of adjustment \"on-the-fly\" with an external adjuster located in the side of the frame means that a player can alter the feel and performance profile of their marker within seconds. In some cases at extreme levels of adjustment there may be need to fine tune the Geo 3 dwell to match the required bolt speed, but in general use the BSC adjustment is as simple as dialing in the velocity on the inline regulator.\n*New Geo 3 CureST AND CureST2 Bolt - With players continually wanting to shoot the most fragile paint possible we are constantly striving to improve the way that our markers receive paintballs into them, how the ball is transferred from the breech to the barrel, and how the ball is accelerated down the barrel. We do everything we can to make sure that the paint is handled in the most efficient way possible while still fulfilling all the other criteria required for a modern paintball marker to be competitive. During the loading and firing cycle the bolt plays probably the most crucial role out of all the components in the marker. With the Geo3 we incorporate a uniquely long bolt stroke. Doing this allows us to manipulate the profile and form at the head of the bolt in a significant manner when compared to other bolts and still provide a good breech seal during firing. The Extra stroke length is utilized to provide a shape to the head of the bolt that acts as a gentle interface between both the ball that is being pushed into the breech and the ball that is second in the ball stack, awaiting loading. The Geo3 bolt takes this to the next level with the CureST2 Bolt by providing a fully cushioned, rubber bolt head that is used to reduce impact forces on both the ball in the breech and the ball in the stack. It allows paint that would have previously been thought un-shootable to be shot with complete effectiveness. As if that wasn't enough, you will also find the original CureST bolt included as standard with the Geo3.\n*New Gen3 Propshaft and Can Assembly - The Geo3 comes with a modified Propshaft and Can Assembly. The propshaft still benefits from the unique spring-loaded Drive Core but modifications to the Propshaft tip improve gas flow through the bolt and past the tip while still keeping the propshaft perfectly concentric within the bolt. This Drive Core prevents air-loss both on the firing stroke of the bolt, leaving residual, previously wasted air trapped in the valve chamber, as well as ensuring the valve chamber is fully sealed prior to re-filling on the return stroke of the bolt. This results in better efficiency and faster recharge of the valve chamber in the Geo 3 paintball gun. The new Can and Bolt in the eclipse geo 3 have previous pressure relief vents that were required for safe degassing of the old ISCIS solenoid removed. The removal of these vents results in less gas wastage per shot.\n*New Frame and Trigger Geometry - The Geo 3 sees the grip-frame moved up and back over the previous generation bringing the rear hand closer to the barrel axis for an even more natural feel in the hand. Moving the hand higher and further back helps reduce the amount of felt recoil and produces a more stable platform whether firing single shots or in full ramp. The Geo3 trigger has also been borrowed directly from the Ego11 and is 4-way externally adjustable with both magnetic and leaf spring return mechanism and the option of both Opto or micro-switch actuation built in. The frame itself has been strengthened to reduce chances of accidental damage yet still designed to be the primary crumple zone in cases of large impacts.\n*New Console and Grips - Following on from successful implementation of a full length grip, push button and display window console on the Ego11 the eclipse Geo3 includes its own variation on the theme. A long, soft gripping surface added all the way up the back of the frame right up to the body interface. The Geo3 also includes the Ego11 grips with twin screws per side and their slim, sticky feel.\n*New Integrated Body Filter - The majority of solenoid and drive-train issues can be completely avoided through proper filtration of the air supply. Unfortunately air provided by fields or events isn't always perfect, so in order to better protect the users investment and to ensure that the Geo3 works for longer and better between maintenance stops there is now a replaceable filter captured within the FRM. The filter protects the solenoid unit as well as the bolt, prop shaft and can from ingress of dirt and debris from the air supply, POPS, fittings and inline reg.\n*SL3 In-Line Regulator - The Geo3 includes the SL3 reg for increased accuracy and consistentcy along with less creep and faster recharge than any previous Eclipse Reg. On top of that it will allow the Geo3 to operate with LP, MP or HP tanks with no fluctuation in performance or velocity. Switch from HP tank to LP tank without needing to adjust the regulator. New design means that the Geo3 will shoot down to the last 200psi of tank pressure with next-to-zero loss in velocity. The new SL3 regulator also has reversible and replaceable reg seal. The Geo3 naturally utilizes the incredibly popular angled swivel unit found on the Ego11.\n*POPS ASA System - The POPS ASA has quickly established itself as one of the best ASA's ever produced. It is simple to operate, quick to engage and de-gas and extremely reliable and robust. That the hose exits from the front to give a nice tight line between the ASA and reg is just a bonus.\n*Shaft4 Barrel - The Geo3 includes the Shaft4 paintball barrelwhich has been developed specifically to improve efficiency and consistency. By manipulating the length and bore of the rear control bore section the new barrel gives higher velocities than older Shaft barrels for the same settings. This leads to an improvement in both efficiency and consistency as well as reducing the sound signature of the marker.\n*Circuit Board - 16-bit, 16mips microprocessor; user-replaceable, low power, transflective LCD module with full colour backlight, redesigned for added robustness; graphical user interface; optimised solenoid drive circuitry offering increased accuracy of Dwell and ROF control; micro-switch and opto-electronic trigger sensing; audible indicator.\n*E-Portal Connectivity - Capable of connecting the Geo3 to a PC giving the ability to upload Firmware, make Splash Screens and remotely adjust parameters. (Requires Optional USB Adaptor, Software and Cable)\n\n\n= Eclipse Geo3 Paintball Gun Specifications: =\n\n*Weight - 854g/1.88lb Including 14\" Shaft4 Barrel, Battery, Feed Tube, POPS\n*Length - 520mm Including 14\" Shaft4 Barrel\n*Height - 202mm\n*Width - 31mm\n", + "banner1" : "banners/categories/geo_price_header001.jpg", + "htmlvids" : "", + "head_title" : "Eclipse Geo3 Paintball Gun | Geo 3 Paintball Marker | Planet Eclipse Geo", + "page_title" : "Buy Eclipse Geo 3 Paintball Gun Online On Sale Now" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_suplex_sunglasses" : {}, + ".casual_clothing.z_unisex_clothing_accesories.stickers" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs.camelbak_hydrobak_hydration_packs" : {}, + ".airsoft.airsoft_guns.airsoft_spring_guns.airsoft_spring_rifles" : { + "meta_keywords" : "Airsoft Spring rifles,Airsoft Spring Sniper Rifle,Airsoft Spring Rifle,Smith and Wesson,Firepower,classic army,Desert Eagle,Sig Sauer,Colt,Beretta,cheap airsoft guns,Spring Powered airsoft rifles,", + "meta_description" : "Zephyr Sports carries a wide variety of Airsoft Spring Rifles! These spring powered Airsoft replicas include guns by: Smith and Wesson, Firepower, Classic Army, Desert Eagle, Sig Sauer, Colt, Beretta and more! For cheap airsoft guns, choose Zephyr! Spring Powered airsoft rifles are low impact toy guns that are sure to entertain you and your friends!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Spring Sniper Rifle | Airsoft Spring Rifles", + "description2" : "" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.beretta_airsoft_guns" : {}, + ".harnessesbags.backpacks.famous_stars_and_straps_backpacks" : { + "meta_description" : "Famous Backpacks - Buy your Famous Bags At Zephyr Sports for Less Today! We carry a complete line of Famous Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Famous Backpacks & Bags on Sale", + "head_title" : "Famous Backpacks | Famous Bags | Famous Luggage" + }, + ".airsoft.2clearance.airsoft_clearance_gear" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Cheap Airsoft Guns | Cheap Airsoft Gear | Sale Airsoft Softair" + }, + ".skateboard_gear.skateboard_longboards.sector_9_longboard_skateboards.sector_9_mini_series_longboards" : {}, + ".casual_clothing.mens_clothing.tshirts.thunder_t_shirts" : { + "meta_keywords" : "Thunder T Shirts,Thunder shirts,free shipping,Thunder TShirt", + "meta_description" : "Thunder T Shirts - Zephyr carries a complete line of Thunder Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Thunder T Shirts at Zephyr", + "head_title" : "Thunder T Shirts | Thunder Shirts |Thunder TShirt" + }, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.maddog_sports_holsters" : {}, + ".casual_clothing.mens_clothing.belts.alpinestars_belts" : { + "meta_keywords" : "Alpinestars Belts,Alpinestars Belt Buckle,Alpinestars Belts,Alpinestars webbed belt", + "meta_description" : "AlpineStars Belts - We carry the complete line of Alpinestars Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "AlpineStars Belts on Sale Now!", + "head_title" : "AlpineStars Mens Belts | Alpinestars Belts |Alpine star Belts" + }, + ".sponsorship.sponsor_only_specials" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.nixon_headphones.nixon_block_speakers" : { + "head_title" : "Nixon Block Speakers | Nixon Speakers | Speakers Nixon" + }, + ".casual_clothing.mens_clothing.tank_tops.1-search_by_size.3-large" : {}, + ".airsoft.1new_products" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "New Airsoft Gear | New Product Releases" + }, + ".harnessesbags.paintball_gear_bags.hybrid_gear_bags" : {}, + ".casual_clothing.youth_clothing.youth_shoes.c1rca_circa_youth_shoes" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_after_party_sunglasses" : {}, + ".casual_clothing.mens_clothing.wallets.element_wallets" : { + "meta_description" : "Element Wallets - Buy your Element Mens WalletAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Element Wallets On Sale & Free Shipping", + "head_title" : "Element Wallets | Element Mens Wallet" + }, + ".paintballs.dxs_paintballs" : { + "meta_description" : "Draxxus Paintballs - Buy your DXS Paintballs Online at Zephyr Paintball for Less today. Free Shipping on DXS Silver Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Draxxus Paintballs Online On Sale Now", + "head_title" : "Draxxus Paintballs | DXS Paintballs | DXS Silver" + }, + ".2clearance.1-black_friday.skate" : { + "head_title" : "Black Friday Paintball Sale | Paintball Black Friday" + }, + ".airsoft.airsoft_safety.revision_military_eye_protection" : { + "head_title" : "Revision Military Goggles | Revision Goggles | Revision Sunglasses" + }, + ".casual_clothing.mens_clothing.beanies.neff_beanies.neff_classic_beanies" : { + "meta_description" : "Neff Classic Beanies - Buy your Beanies Neff ClassicAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Neff Classic Beanies @ Zephyr Sports", + "head_title" : "Neff Classic Beanies | Beanies Neff Classic" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb3293_sunglasses" : { + "meta_keywords" : "Ray Ban RB3293 Sunglasses ,Ray Bans,Ray Ban Sunglasses", + "meta_description" : "Ray Ban RB3293 Sunglasses are now available @ Zephyr Sports! Made in Italy, these Ray Ban Sunglasses have style and quality above all else! Backed with a manufacturers warranty, the Ray Ban RB3293 Sunglasses are a classic look that never fades! These Ray Bans are available in various colors, check em out @ Zephyr Sports!", + "page_title" : "Buy Ray-Ban RB3293 Sunglasses On Sale & Free Shipping", + "head_title" : "Ray-Ban RB3293 Sunglasses | Ray Ban RB3293 Sunglasses | Ray Ban RB 3293 Sunglasses" + }, + ".casual_clothing.mens_clothing.hats.rvca_hats" : { + "meta_keywords" : "RVCA Hats,RVCA caps,RVCA baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "RVCA Hats - Zephyr carries a complete line of RVCA Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything RVCA", + "page_title" : "RVCA Hats on Sale at Zephyr", + "head_title" : "RVCA Hats | RVCA Caps | RVCA Baseball Hats" + }, + ".3packagespecials.azodin_paintball_packages.azodin_kdii_paintball_gun_packages" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_quanta_sunglasses" : { + "meta_description" : "Spy Optics Quanta Sunglasses - Zephyr Sports carries a complete line of Quanta Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Quanta Sun Glasses Online Today.", + "page_title" : "Spy Optics Quanta Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Quanta Sunglasses | Quanta Spy Sunglasses Free Shipping | Buy Spy Quanta Sun Glasses" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_fixed_power_scopes.barska_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_primo_baseball_gloves" : { + "head_title" : "Rawlings Primo Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".casual_clothing.youth_clothing.youth_t_shirts.world_industries_t-shirts" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_embrace_womens_sunglasses" : { + "meta_keywords" : "Oakley Embrace Womens Sunglasses,Embrace Womens oakley sunglasses,oakley Embrace Womens, Embrace Womens polarized sunglasses", + "meta_description" : "Oakley Embrace Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Embrace Womens and Polarized Oakley Embrace Womens Sunglasses on Sale! ", + "page_title" : "Oakley Embrace Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Embrace Womens Sunglasses | Embrace Womens Oakley Sunglassses" + }, + ".barrels.barrels_by_manufacturer.lapco_paintball_barrels.lapco_snapshot_barrels.snapshot_barrel_tips" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_duel_backpacks" : { + "meta_description" : "Dakine Duel Backpacks - Buy your Duel Dakine Bags At Zephyr Sports for Less Today! We carry a complete line of Dakine Duel Packs at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Duel Backpacks & Bags Ship Free ", + "head_title" : "Dakine Duel Backpacks | Duel Dakine Bags |Dakine Duel Packs" + }, + ".airsoft.tactical_airsoft_gear.knee_and_elbow_pads" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_whisker_sunglasses" : { + "meta_keywords" : "Oakley Whisker Sunglasses,Whisker oakley sunglasses,oakley Whisker, Whisker polarized sunglasses", + "meta_description" : "Oakley Whisker Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Whisker and Polarized Oakley Whisker Sunglasses on Sale! ", + "page_title" : "Oakley Whisker Sunglasses with Free Shipping", + "head_title" : "Oakley Whisker Sunglasses | Whisker Oakley Sunglassses" + }, + ".airsystems.hosesfittings.tank_repair_parts" : { + "meta_description" : "Paintball Tank Parts - Buy your HPA Tank Repair Parts Online at Zephyr Paintball for Less today. Free Shipping on Paintball Tanks Repairs Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Tank Parts Online On Sale Now", + "head_title" : "Paintball Tank Parts | HPA Tank Repair Parts | Paintball Tanks Repairs" + }, + ".casual_clothing.mens_clothing.socks.empire_socks" : { + "meta_keywords" : "Empire socks,Empire mens socks,Empire men socks", + "meta_description" : "Empire Socks - Zephyr stocks a complete line of Empire Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Empire needs. ", + "page_title" : "Empire Socks On Sale & Free Shipping", + "head_title" : "Empire Socks | Empire Mens Socks" + }, + ".airsoft.airsoft_guns.echo_1_airsoft_guns.mp5_echo_1_airsoft_guns" : { + "meta_keywords" : "Echo 1 AEG,MP5 airsoft gun,AEG,MP5 Airsoft gun,sub machine gun,echo 1", + "meta_description" : "Developed by the Germans, makes the MP5 a reliable source in combat with its light design. The history of the MP5 shows the gun being used by the German Federal Police, border guard and army special forces. These replicas are designed for fast combat to get the job done by taking out your opponent with ease. Now the MP5 AEG is available for modern airsoft warfare! Zephyr Sports is a leading distributor of Echo 1 AEG 's! We carry a wide variety of MP5 airsoft guns! These Sub machine guns by echo 1 are clutch out there on the field! Get in the game with your own MP5 airsoft gun!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Echo 1 MP5 Airsoft Guns On Sale & Free Shipping", + "head_title" : "Echo 1 MP5 Airsoft Guns | Echo 1 MP5 AEG | Echo 1 MP5 Metal" + }, + ".2clearance.paintball_clearance_gear.clearance_paintball_guns" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.s_t_armament" : {}, + ".testing_help_desk.my_account" : { + "hd_answer_two" : "Once you [[login]:url=https://ssl.zoovy.com/zephyrsports/login.cgis], it will take you directly to the Customer Options page where you will be able to change your email, password, billing and shipping address.", + "hd_answer_four" : "If you have forgotten your password and know your login name (usually your email address) [[CLICK HERE]:url=https://ssl.zoovy.com/zephyrsports/login.cgis] to reset your password.", + "hd_question_three" : "I Forgot My Login Name.", + "hd_question_four" : "I Forgot My Password.", + "hd_topic_listing" : "» How do I create an account?
                                                                          \n» How do I edit my account information?
                                                                          \n» I forgot my login name.
                                                                          \n» I forgot my password.
                                                                          ", + "hd_topic" : "My Account", + "hd_question_one" : "How Do I Create an Account?", + "hd_btn" : "images/site_specific/backto_helpdesk", + "hd_answer_three" : "Your login name is usually always your email address. If you have forgot what email address you used, you can give us a call at 877-814-4297 and we will be able to help you retrieve the email used.", + "hd_question_two" : "How Do I Edit My Account Information?", + "hd_answer_one" : "At this point in time when you create your first order with us you will be able to create an account.", + "hd_link" : "/category/testing_help_desk" + }, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_ak_airsoft_rifles" : {}, + ".airsoft.airsoft_guns.beretta_airsoft_guns" : { + "meta_description" : "Beretta Airsoft Guns - Buy your Airsoft Beretta Pistol At Zephyr Sports for Less Today! We carry a complete line of Airsoft Beretta 92FS at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Beretta Airsoft Guns On Sale & Free Shipping", + "head_title" : "Beretta Airsoft Guns | Airsoft Beretta Pistol | Airsoft Beretta 92FS", + "description" : "" + }, + ".misc_items.paintball_marker_repair_kits" : {}, + ".harnessesbags.paintball_gear_bags.invert_gear_bags___backpacks" : { + "meta_keywords" : "invert paintball gear bags, invert gun bags, paintball gun bags, invert padded gun case", + "meta_description" : "Invert Paintball Gear Bags - Zephyr carries a complete line of Invert Guns bags to protect your gear. Huge selection of paintball gun bags in stock and ready to ship", + "page_title" : "Buy Invert Paintball Gear Bags Online On Sale Now", + "head_title" : "Invert Paintball Gear Bags | Invert Gun Bags | Paintball Gun Bags" + }, + ".airsoft.airsoft_safety.airsoft_goggles.dye_airsoft_goggles" : {}, + ".shop_by_brand.modefy_airsoft" : {}, + ".shop_by_brand.oakley" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n MEN'S CLOTHING\n \n
                                                                          \n
                                                                          \n
                                                                          \n WOMEN'S CLOTHING\n \n
                                                                          \n
                                                                          \n
                                                                          \n ESSENTIALS\n \n
                                                                          \n
                                                                          ", + "meta_description" : "Oakley Sunglasses - Buy your Oakley Apparal At Zephyr Sports for Less Today! We carry a complete line of Oakley Backpacks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "=Oakley, redefine your boundaries=\n\nOakley was created for world-class athletes, those who see the limits of possibility as just another challenge. Oakley looks beyond the conventional ideas of industry standards. Oakley lives to identify problems, create inventions, and wrap those inventions in art. And simply to make things better than anyone thought possible. Try Oakley Sunglasses, Oakley Apparel and Oakley backpacks on for a size and see the innovation at work. ", + "page_title" : "Buy Oakley Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Sunglasses | Oakley Apparel | Oakley Backpacks", + "description" : "=Oakley, Redefine your boundaries= \n\n==Oakley, the constant innovator==\nOakley invents each new product with a design philosophy called sculptural physics: the discipline of solving problems with science and wrapping those solutions in art. Supported by an infrastructure that includes the latest tools of technology, Oakley engineers and artisans continue to expand the company’s array of product categories.\n\n\n==Sunglasses==\nAs the undisputed leader in performance eyewear, Oakley continues to advance sport technology and redefine the lifestyle market with patented optical innovations. Numerous patents have been awarded to the inventions behind the company’s High Definition Optics® (HDO®). HDO® virtually eliminates the problems of ordinary lenses, including distortion that bends light (so objects aren’t really where they appear to be) and optical flaws that magnify images in the manner of prescription lenses made for somebody else.\n\n==Apparel==\nEngineered to optimize performance and comfort for professional athletes, Oakley apparel designs are coveted also by the lifestyle market. The company utilizes membrane technologies that maintain waterproof yet breathable barriers. Temperature is controlled with reversible heat storage, a science developed for astronauts. Rejecting the flat cutouts of conventional garment design, Oakley uses CAD/CAM digital sculpturing to achieve the comfort and fit of contours that accent the female form. Additional technologies range from the temperature control of inflatable insulation systems to the impact protection of Bio Foam panels.\n\n==Accessories==\nOakley offers a full line of accessories designed for efficiency, comfort, convenience and style. The company’s backpacks and bags are engineered with ergonomics, reinforced against punishing abuse and enhanced with premium utility features. Products are optimized for specific uses, such as the company’s surf pack that features a removable wet/dry compartment and changing mat. Oakley’s unique sculptural design produces never-before-seen aesthetics in accessories that range from wallets and belts to surfboard bags, purses and eyewear cases.\n\n" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_fourteener_hydration_packs" : {}, + ".scenarioupgrades.scenario_apparel" : {}, + ".airsoft.airsoft_guns.airsoft_electric_guns.walther_aeg_electric_airsoft_guns" : { + "meta_keywords" : "airsoft spring guns, airsoft spring gun, airsoft guns spring loaded, airsoft gun spring loaded,Cheap Airsoft guns", + "meta_description" : "Spring Airsoft Guns do not require any kind of gas or battery operation to fire. Great for beginners - low cost. For Cheap Airsoft guns, Choose Zephyr!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Spring Guns | Airsoft Guns Spring Loaded", + "description" : "" + }, + ".casual_clothing.z_shoes_and_footwear.etnies_shoes" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_fly_detector" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Fly Detector Sunglasses,Black Flys Fly Dector Sunglasses", + "meta_description" : "Black Flys Fly Detector Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Flys Fly Detector Sunglasses.", + "head_title" : "Black Flys Fly Detector Sunglasses | Fly Detector Sunglasses | Black Flys Sunglasses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_enduro_sunglasses" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_venice_sunglasses" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_division_backpacks" : { + "meta_keywords" : "Oakley Division Backpack,oakley division bags, divion Oakley pack", + "meta_description" : "Oakley Division Backpacks - Oakley Division Bags have plenty of space to carry your gear for the day. Even includes room for most laptops", + "page_title" : "Oakley Division Backpacks Free Shipping", + "head_title" : "Oakley Division Backpack | Oakley Division Bag | Oakley Division Back Pack" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.mp7_aeg_airsoft_magazines" : {}, + ".markers.worrgamesautocockers" : { + "banner1" : "banners/categories/guns/wgp_banner.jpg", + "meta_description" : "Worrgames Paintball Guns - Buy your Paintball Markers WGP Online at Zephyr Paintball for Less today. Free Shipping on WGP Autococker Paintball Gun Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Worrgames Paintball Guns Online On Sale Now", + "head_title" : "Worrgames Paintball Guns | Paintball Markers WGP | WGP Autococker Paintball Gun", + "description" : "" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_touring_sunglasses" : { + "meta_keywords" : "Spy Touring sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Touring Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy optic eyewear with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Touring Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Touring Sunglasses | Spy Optics Touring Sunglasses" + }, + ".markers.smartparts.ionpaintballguns" : { + "meta_keywords" : "Smart Parts Ion Paintball Guns, paintball gun ion, Ion paintball gun, Cheap smart parts ion paintball marker, Ion paintball package", + "meta_description" : "Smart Parts Ion Paintball Gun - The revolutionary smart parts Ion paintball gun. Finally a tournament level paintball marker for less than $200. Upgrade your Paintball marker to performance never before seen at this rice point", + "page_title" : "", + "head_title" : "Smart Parts Ion Paintball Gun | Cheap Ion Paintball Marker | Paintball Gun Ion " + }, + ".2clearance.paintball_clearance_gear" : { + "head_title" : "Paintball Sale Gear | Clearance Paintball Supplies | Paintball Shop Sale" + }, + ".apparel.pants.bt_paintball_pants" : { + "meta_keywords" : "camo paintball pants, bt paintball pants, bt pro pants", + "meta_description" : "BT Paintball Pants - Camo Paintball pants from BT offer protection, breathability and the quality you've come to count on from BT", + "page_title" : "", + "head_title" : "Camo Paintball Pants | BT Paintball Pants |Empire BT Paintballing Pants" + }, + ".airsoft.airsoft_guns.kalishnakov_airsoft_rifles" : { + "meta_keywords" : "Kalashnikov AK47 Airsoft Replicas,Kalashnikov,AK47,Airsoft Replicas,AK47 assault rifle,AK47 airsoft rifle,Cheap AK 47 Airsoft,Kalishnikov Airsoft Guns,AK 47", + "meta_description" : "Kalashnikov AK47 Airsoft Replicas. The AK47 assault rifle is one of the most popular rifles ever to exist. Created by Mikhail Timofeevich Kalashnikov, the \"Avtomat Kalashnikova 1947\" adopted by the Soviet Army later become know as the popular AK47. Many different styles of airsoft replicas exist ranging from mid-level to high-end electronic versions, including the later improved models (AK47S, AKM, AK47M, AKS-74U and AK 100). Offered in both black and wood finishes, the AK47 airsoft rifle replicas stand as some of the most popular choices for airsoft players. ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Cheap AK 47 Airsoft On Sale & Free Shipping", + "head_title" : "Cheap AK 47 Airsoft | Kalishnikov Airsoft Guns | JG AK 47 Airsoft" + }, + ".loaders.hopper_accesories.empire_hopper_accesories.reloader_b_shells" : { + "meta_description" : "Empire Loader Shells - Buy your Prophecy Replacement Shells Online at Zephyr Paintball for Less today. Free Shipping on Prophecy Loader Shells Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire Loader Shells Online On Sale Now", + "head_title" : "Empire Loader Shells | Prophecy Replacement Shells | Prophecy Loader Shells" + }, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests.bravo_tactical_vests" : { + "meta_description" : "Bravo Tactical Vests - Buy your Bravo Military Vests At Zephyr Sports for Less Today! We carry a complete line of Bravo Molle Vests at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Bravo Tactical Vests On Sale at Zephyr ", + "head_title" : "Bravo Tactical Vests | Bravo Military Vests | Bravo Molle Vests" + }, + ".markerupgrades.planet_eclipse_etek_upgrades.eclipse_etek_grips" : {}, + ".airsoft.tactical_airsoft_gear.backpacks_and_gun_cases.ncstar_bags_backpacks_and_gun_cases" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.tshirts.bones_t-shirts" : { + "meta_keywords" : "Bones T Shirts,Bones shirts,free shipping,Bones TShirt", + "meta_description" : "Bones T Shirts - Zephyr carries a complete line of Bones Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Bones T Shirts at Zephyr", + "head_title" : "Bones T Shirts | Bones Shirts |Bones TShirt" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_checko_sunglasses" : { + "meta_keywords" : "Von Zipper Checko sunglasses,VZ Checko, Von Zipper polarized sunglasses,Von Zipper Checko,VZ Checko glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Checko Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Checko sunglasses now! For Von Zipper Checko glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Checko Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Checko Sunglasses | VZ Checko Sunglasses" + }, + ".casual_clothing.youth_clothing.youth_t_shirts" : { + "meta_description" : "Youth T-shirts - Buy your Kids Tshirts Online At Zephyr Sports for Less Today! We carry a complete line of Kifds Skate Clothing at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Youth T-shirts Now! On Sale & Free Shipping", + "head_title" : "Youth T-shirts | Kids Tshirts | Kifds Skate Clothing" + }, + ".airsoft.tactical_airsoft_gear.head_gear.maddog_sports" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_jailbreak_sunglasses" : { + "meta_description" : "Electric Jailbreak Sunglasses - Zephyr Sports carries a complete line of Electric Jailbreak Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Jailbreak Online Today.", + "page_title" : "Electric Jailbreak Sunglasses On Sale Free Shipping", + "head_title" : "Electric Jailbreak Sunglasses | Electric Jailbreak Sun Glasses | Sunglasses Electric Jailbreak" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.bushnell_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markers.valken_paintball_guns" : { + "meta_keywords" : "valken sw1,valken proton,valken proton paintball gun,paintball marker,sw-1,sw1,sw1 paintball gun", + "meta_description" : "Valken Paintball Guns - Buy your Valken Sw1 Paintball Markers Online at Zephyr Paintball for Less today. Free Shipping on Valken Proton Paintball guns Trust Zephyr for all your Paintball Needs", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "prodlist1_header" : "Valken Paintball Guns", + "banner01_link" : "/category/3packagespecials.valken_paintball_packages/", + "page_title" : "Buy Valken Paintball Guns Online On Sale Now", + "head_title" : "Valken Paintball Guns | Valken Sw1 Paintball Markers | Valken Proton" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_electronics_and_wires" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Electronics Airsoft | Airsoft wiring | Airsoft wires" + }, + ".goggles.empire_vents_goggles.empire_e-flex_paintball_masks" : { + "meta_keywords" : "empire, paintball, masks, eflex, e, flex, e-flex, e flex, goggles, eye, protection, face, cheap paintball mask, empire paintball gear, empire vents, empire vents mask, thermal, dual pane", + "meta_description" : "Empire E-Flex Paintball Masks - Hot new Empire Masks. The top of the line Thermal paintball goggles. For tournaments or recreational play, Empire Paintball masks are the best choice", + "top_description" : "The Empire E-flex is ready to change the world of paintball masks. The Empire E-Flex is now in stock and shipping in limited colors and quantities. Get your empire eflex before they sell out. The empire E-flex includes the event style quick change thermal lens for easy cleaning. The ear pieces have been completely redesigned to be insanely comfortable. The mask bottom is soft for all kinds of extra bounces with plenty of porting to allow your voice to be heard throughout the field. A pro style empire E-flex strap with silicon will keep the goggles on your head and the included microfiber bag will protect your mask when your not on the field.", + "zoovy:banner01" : "", + "description" : "=Empire E-flex Mask Specifications:=\n\n*Vents system for rapid lens exchange\n*Thermal, dual-pane clear lens with zero optical distortion\n*Ultra Soft and flexible face skirt creates bounces and offers maximum breathability\n*New comfortable E-Flex thermo-foam ear pieces\n*Interchangeable with Flex skirts and Spectra frames\n*Extremely comfortable hypo-allergenic face foam\n*Pro-style Empire strap with silicone bead to keep the strap in place\n*Microfiber protective goggle bag included", + "top_html_focus" : "", + "htmlvids" : "", + "head_title" : "Empire E-flex Masks | Empire Eflex Paintball | E-flex Paintball Masks", + "page_title" : "Buy Empire E-Flex Paintball Masks On Sale Now" + }, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb3267_sunglasses" : { + "meta_keywords" : "Ray Ban RB3267 sunglasses, ray bans , ray ban sunglasses", + "meta_description" : "Ray Ban RB3267 Sunglasses are now available @ Zephyr Sports! Made in Italy, these Ray Ban Sunglasses have style and quality above all else! Backed with a manufacturers warranty, the Rayban Sunglasses are a classic look that never fades! These Ray Bans are available in various colors, check em out @ Zephyr Sports!", + "page_title" : "Buy Ray-Ban RB3267 Sunglasses On Sale & Free Shipping", + "head_title" : "Ray-Ban RB3267 Sunglasses | Ray Ban RB3267 Sunglasses | Ray Ban RB 3267 Sunglasses" + }, + ".casual_clothing.mens_clothing.shoes.dc_skate_shoes" : { + "meta_description" : "DC Shoes - Buy your DC Mens Shoes At Zephyr Sports for Less Today! We carry a complete line of DC Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DC Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "DC Shoes | DC Mens Shoes | DC Skate Shoes" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs.camelbak_rogue_hydration_packs" : {}, + ".airsoft.airsoft_guns.mossberg_airsoft_shotguns" : { + "meta_description" : "Mossberg Airsoft Guns - Buy your Mossberg Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Mossberg Airsoft Shotgun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Mossberg Airsoft Guns On Sale & Free Shipping", + "head_title" : "Mossberg Airsoft Guns | Mossberg Airsoft Rifles | Mossberg Airsoft Shotgun" + }, + ".harnessesbags.packs___harnesses.dye_pod_packs" : { + "meta_keywords" : "dye attack pack, dye harness, dye attack pack pro, dye paintball harness, dye pod holder, dye paintball pod holder, dye 09 harness, 09 dye harness, 09 dye pod holder", + "meta_description" : "Dye Attack Pack - Best prices on dye Harnesses at Zephyr. 2009 Dye Attack Pack Pro available now", + "page_title" : "Buy Dye Attack Pack Online On Sale Now", + "head_title" : "Dye Attack Pack | Dye Harness | Dye Attack Pack Pro" + }, + ".1_wip" : {}, + ".markerupgrades.proto_matrix_rail_upgrades.pmr_maintenance_kits" : {}, + ".casual_clothing.mens_clothing" : { + "meta_description" : "Mens Clothing - Buy your Mens Apparel At Zephyr Sports for Less Today! We carry a complete line of Skate Clothing at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Mens Clothing On Sale & Free Shipping", + "head_title" : "Mens Clothing | Mens Apparel | Skate Clothing" + }, + ".casual_clothing.mens_clothing.tshirts.spitfire_t_shirts" : { + "meta_keywords" : "Spitfire T Shirts,Spitfire shirts,free shipping,Spitfire TShirt", + "meta_description" : "Spitfire T Shirts - Zephyr carries a complete line of Spitfire Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Spitfire T Shirts at Zephyr", + "head_title" : "Spitfire T Shirts | Spitfire Shirts | Spifire Skate TShirt" + }, + ".shop_by_brand.d3fy_paintball" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_stance_sunglasses" : { + "meta_description" : "Arnette Stance Sunglasses - Zephyr Sports carries a complete line of Stance Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Stance Sun Glasses Online Today.", + "page_title" : "Arnette Stance Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Stance Sunglasses | Stance Arnette Sunglasses | Arnette Stance Sun Glasses" + }, + ".markers.gryphon_paintball_guns" : { + "meta_keywords" : "tippmann gryphon,gryphon paintball guns,gryphon paintball gun,tippman,tipmann,gryphon paintball marker,semi auto,entry level", + "meta_description" : "Tippmann Gryphon Paintball Guns - Buy your Gryphon Tippmann Markers Online at Zephyr Paintball for Less today. Free Shipping on Tippmann Gryphon Paintball Gun Trust Zephyr for all your Paintball Needs", + "top_description2" : "==Tippmann Gryphon Paintball Gun==\n\nThe new Tippmann Gryphon marker is lightweight and incorporates numerous premium features, including: an internal gas line for a cleaner look, a rigid and ergonomically-designed front grip, a center-feed design to maximize mobility, a high-impact body, a blade trigger for a smoother trigger pull, a high performance and ported barrel for reduced sound and improved accuracy. The Tippmann Gryphon has the legendary reliability of the Tippmann inline bolt system in a new body frame and loader position to provide a more balanced feel to the marker. The Tippmann Gryphon Paintball Gun uses a tippmann 98 threaded paintball barrel to allow for easy barrel upgrades. Get in the game and get your Tippman Gryphon today.", + "zoovy:banner01" : "banners/paintball/headers/gryphon_header.jpg", + "banner01_link" : "/category/3packagespecials.gryphon_starter_packages/", + "description" : "==Tippmann Gryphon Features:==\n\n* Internal Gasline for a cleaner look\n* Inline Bolt System that is Reliable and Proven to Perform\n* Rigid Ergonomically Designed Front Grip\n* Center Feed Design To Maximize Mobility Right or Left\n* High Impact composite Body that is Built to Last\n* Blade Trigger Designed for a Smoother Trigger Pull\n* High Performance Ported Barrel Designed to Reduce Sound and Improve Accuracy\n* New Body Frame and Loader Position to Provide a More Balanced Feel to the Marker\n* Tippmann 98 Threaded Barrel\n* Compatible with Co2 or HPA/Compressed air\n\n\nFor a rock solid entry level paintball gun, the Tippmann Gryphon can't be beat. Own your paintball gun instead of renting from the field.", + "page_title" : "Buy Tippmann Gryphon Paintball Guns Online On Sale Now", + "head_title" : "Tippmann Gryphon Paintball Guns | Gryphon Tippmann Markers | Tippman Gryphon Paintball Gun" + }, + ".barrels.tippmanna5.12__tippmann_a_5_barrels" : { + "meta_description" : "12 inch Tippmann A5 Paintball Barrels - Buy your 12\" Tippmann A-5 Threaded Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Tippmann A5 Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 12 inch Tippmann A5 Paintball Barrels Online On Sale Now", + "head_title" : "12 inch Tippmann A5 Paintball Barrels | 12\" Tippmann A-5 Threaded Upgrade | Tippmann A5 Paintballs Barrels" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_mad_dog_sunglasses" : { + "meta_description" : "Oakley Mad Dog Sunglasses - Zephyr Sports carries a complete line of Mad Dog Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Mad Dog Sun Glasses Online Today.", + "page_title" : "Oakley Mad Dog Sunglasses On Sale Free Shipping", + "head_title" : "Oakley Mad Dog Sunglasses | Mad Dog Oakley Sunglasses | Oakley Mad Dog Sun Glasses" + }, + ".apparel.jerseys.dyejerseys.dye_c12_paintball_jerseys" : { + "top_description" : "The Dye C12 jersey boasts a comfortable fit with unmatched protection. Constructed with new innovative and exclusive features like Pigsticker Protection, Bomb-Proof Construction, Prevent breathable venting & assembly, and of course the traditional patented DyeTack Performance Grip. Designed with a V-neck collar, compression formed body padding. Flexible, lightweight elbow pads and dye glove cuffs offer exceptional freedom of rotation and movement. ", + "zoovy:banner01" : "banners/paintball/slideshow/dye_c12_pants_jerseys_slideshow.jpg" + }, + ".barrels.barrels_by_manufacturer.stiffi_paintball_barrels.stiffi_tippmann_a-5___x-7_threaded_barrels" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs" : { + "meta_description" : "Camelbak Hiking Packs - Buy your Camelbak Day PacksAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Camelbak Hiking Packs On Sale & Free Shipping", + "head_title" : "Camelbak Hiking Packs | Camelbak Day Packs" + }, + ".airsystems.tankcovers.exalt_bottle_covers" : { + "meta_keywords" : "exalt tank covers, exalt bottle cover, paintball bottle cover, HPA tank cover", + "meta_description" : "Exalt Tank Covers - Straight from Canada. Lightweight protective exalt bottle cover. Protect your paintball bottle with the smallest tank cover available", + "page_title" : "Buy Exalt Tank Covers Online On Sale Now", + "head_title" : "Exalt Tank Covers | Exalt Paintball Covers | Exalt Bottle Cover" + }, + ".casual_clothing.mens_clothing.shirts.element_shirts" : { + "meta_keywords" : "element clothing,element shirt,element shirts,element clothes,element apparel,element online,element brand,element long sleeve shirt,buy element clothing,element clothing online\r ", + "meta_description" : "Element Shirts - Huge selection of Element Apparel available online at Zephyr Sports. Always the best price, Always free shipping over $75. Buy your Element Shirt online Now!", + "page_title" : "Element Shirts On Sale & Free Shipping", + "head_title" : "Element Shirts | Element Apparel | Element Shirt" + }, + ".casual_clothing.mens_clothing.socks.metal_mulisha_socks" : { + "meta_keywords" : "Metal Mulisha socks,Metal Mulisha mens socks,Metal Mulisha men socks", + "meta_description" : "Metal Mulisha Socks - Zephyr stocks a complete line of Metal Mulisha Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Metal Mulisha needs. ", + "page_title" : "Metal Mulisha Socks on Sale at Zephyr", + "head_title" : "Metal Mulisha Socks | Metal Mulisha Mens Socks" + }, + ".testing_help_desk.buyers_guide.complete_skateboard_buyers_guide" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_darkness_sunglasses" : { + "meta_keywords" : "Arnette, Arnette Polarized, Arnette Darkness Sunglasses, Designer Sunglasses", + "meta_description" : "Arnette Darkness Sunglasses - Zephyr Sports now carries Arnette Designer Sunglasses! ** Arnette Polarized Sunglasses ** Arnette Darkness Sunglasses @ Zephyr Sports!", + "head_title" : "Arnette Darkness Sunglasses | Sunglasses Arnette Darkness" + }, + ".airsoft.tactical_airsoft_gear.camoflouge_pants.511_tactical_bdu_pants" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markerupgrades.ariakon" : {}, + ".markerupgrades.empire_upgrades" : { + "meta_description" : "Empire Axe Upgrades - Buy your Empire Axe Marker Upgrades Online at Zephyr Paintball for Less today. Free Shipping on Axe Upgrades Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire Axe Upgrades Online On Sale Now", + "head_title" : "Empire Axe Upgrades | Empire Axe Marker Upgrades | Axe Upgrades" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns" : { + "meta_keywords" : "", + "meta_description" : "", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Spring Guns | Airsoft Spring Pistols | Airsoft Spring Rifles", + "description" : "" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.aeg_mid_capacity_mags" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "AEG Mid cap Mags | Mid Cap Airsoft Magazines | Airsoft Mid Caps" + }, + ".casual_clothing.mens_clothing.jackets.dakine_jackets" : { + "meta_description" : "Dakine Jackets - Buy your Dakine Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Dakine Jackets with Free Shipping", + "head_title" : "Dakine Jackets | Dakine Mens Jackets | Jackets Dakine" + }, + ".3packagespecials.empire_paintball_packages.empire_bt" : { + "head_title" : "Empire BT Paintball Packages | Empire BT Paintball Gun Packages" + }, + ".casual_clothing.womens_clothing.ladies_sweatshirts.hater_sweatshirts" : {}, + ".apparel.jerseys.dyejerseys.dye_c13_paintball_jerseys" : { + "meta_keywords" : "dye tree, atlas, dye c13, paintball jersey", + "meta_description" : "Dye C13 Paintball Jerseys - C13 Jerseys have just been released by Dye for 2013. 7 New colors are coming for the Dye C13 line. Improved padding and lighter weight are highlights for Dye this year. Check out the ultimate paintball Jerseys available at Zephyr Paintball.", + "top_description" : "Dye C13 Paintball Jerseys have just been released at world cup. Looks like we have 7 colors for 2013. C13 Jersey are shipping now. Check out the new colors for 2013 including Cubix, Atlas and DyeTree", + "page_title" : "Dye C13 Paintball Jerseys Available at Zephyr", + "head_title" : "Dye C13 Paintball Jerseys | C13 Jerseys | 2013 Dye Paintball Jersey" + }, + ".airsoft.slingshots.1slingshots.saunders_slingshots" : { + "meta_keywords" : "saunders slingshots,wrist wrocket slingshot,black mamba, slingshot saunders,saunders wrist rocket slingshot", + "meta_description" : "Saunders Slingshots - The original Wrist Rocket Slingshot from saunder. Never settle for second rate quality. Get your Slingshot Saunders today", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markers.dangerous_power_paintball_guns.dangerous_power_g3_paintball_guns.dangerous_power_g3_paintball_gun_packages" : { + "prodlist1_header" : "Dangerous Power G3 & iQ Paintball Gun Packages" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_hammerlock_sunglasses" : {}, + ".casual_clothing.mens_clothing.shoes.es_shoes" : { + "meta_description" : "ES Shoes - Buy your ES Mens Shoes At Zephyr Sports for Less Today! We carry a complete line of ES Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "ES Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "ES Shoes | ES Mens Shoes | ES Skate Shoes" + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_gg_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon GG sunglasses", + "meta_description" : "Dragon GG Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon GG Sunglasses" + }, + ".apparel.pants.tanked" : { + "meta_keywords" : "tanked pants, tanked paintball pants, tanked paintball gear, tanked apparel", + "banner1" : "", + "meta_description" : "Tanked Pants - Zephyr carries a complete line of Tanked Paintball Pants, the lightest pants in the paintball market. Tanked Paintball gear is imported direct from germany and desgin by european fashion pros.", + "page_title" : "", + "head_title" : "Tanked Pants | Tanked Paintball Pants | Tanked Paintball Gear" + }, + ".casual_clothing.womens_clothing.ladies_sunglasses.oakley_ladies_sunglasses" : {}, + ".markerupgrades.empire_upgrades.empire_vanquish_parts_and_upgrades" : {}, + ".airsoft.airsoft_guns.sig_sauer_airsoft_guns" : { + "meta_keywords" : "Sig Sauer Replica Airsoft Guns,P220,P230,gas,co2 blow back,electronic airsoft rifles,Sig Sauer guns,Sig Sauer Airsoft Pistol,Sig Sauer Co2 Pistol,sig sauer airsoft,", + "meta_description" : "Sig Sauer Replica Airsoft Guns. Sig Sauer is popular for delivering reliable firearms for well over a century. Most notable, their line of pistols the P220 & P230. These airsoft versions offer both gas & co2 blow back as well as metal bodies for added realism. Spring versions are also available making their lineup perfect for children and adults or beginners to elitist. Also available are modeled after popular Sig Sauer guns. ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Sig Sauer Airsoft Pistol On Sale & Free Shipping", + "head_title" : "Sig Sauer Airsoft Pistol | Sig Sauer Airsoft Guns | Sig Sauer Co2 Pistol", + "description" : "" + }, + ".buyers_guide.paintball.paintball_barrels" : { + "question_05" : "What size barrel should I get?", + "answer_03" : "The bore is the interior diameter of the barrel. The bore must properly match the type of paint being fired. A mismatched selection will result in velocity variations, inaccuracy and possible ball chopping.", + "html_01" : "

                                                                          FAQ (Frequently Asked Questions)

                                                                          \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                          Why should I get a new barrel?What barrel should I get?
                                                                          Why is bore size important?What are the advantages of a carbon fiber barrel?
                                                                          What size barrel should I get?Flatline & Apex Barrels
                                                                          ", + "answer_05" : "Most tournament speedball players will tell you a 14 inch barrel will give you the most accuracy and distance. Most high end guns such as Planet Eclipse Egos and Dye DMs come standard with a 14 inch 2 piece barrel which leads us to believe that it is true. Choosing the right length barrel really all depends on your style of play though. Longer barrels are usually quieter than shorter barrels but often need more gas to propel a paintball making it more inefficient. 20 inch or longer barrels are often times referred to as \"sniper barrels\".\n\n\nMost barrels are ported or vented. Porting consists of the holes on the sides of a barrel near the tip. These holes serve primarily to reduce the sound of a gun firing by allowing air to gradually escape from the barrel rather than in one load burst at the tip. In general, more porting means a quieter barrel, but more porting also requires more air to fire the ball and decreases gun efficiency. Porting is sometimes spiraled or straight, though the differences we have found are pretty minimal.", + "question_02" : "What barrel should I get?", + "answer_04" : "Carbon fiber is stronger than steel and carbon does not change with temperature fluctuations. There are very accurate and extremely light compared to other barrels. A while ago certain carbon fiber barrels were not supposed to be used with any fuzzy barrel swabs as the fibers would get caught in the barrel. Since then, companies have made drastic improvements and now you are able use not only rubber squeegees, but swabs as well.", + "answer_02" : "There are one piece barrels, two piece barrels and barrel kits available. See what fits your needs and purchase accordingly. If you have a lower end gun such as a Tippmann or Spyder, most any barrel will be an upgrade to your game. If you are not looking to spend a whole lot of money but still want a nice barrel, you may be interested in the J&J Ceramic barrel. This barrel has a ceramic coat inside that acts as a self cleaning mechanism if a ball is chopped. The ceramic coat prevents paint from sticking inside the barrel. Just shoot a couple more and it will clean itself out. This starter barrel is available for multiple types of threads.\n\n\nOne Piece Barrels: One piece barrels are machined from a single piece of material, usually either aluminum or carbon fiber.\n\n\nTwo Piece Barrels: Two piece barrels consist of a front and back. The back attaches to the marker and is machined with a specified bore between .682 and .695 caliber. The front makes up the rest of the length and contains the porting. Fronts usually have a larger bore than the back. 2 piece barrels are supposed to be more accurate than 1 piece barrels.\n\n\nBarrel Kits: There are some barrels that must use an insert or sleeve that is inserted into the barrel back. The inserts vary in bore size so that you can size whatever paint you are using perfectly. This allows your shot to be consistently accurate because your barrel bore size matches your insert bore size. Smart Parts was the original manufacturer of these inserts but have since been discontinued. They made aluminum and stainless steel inserts. The aluminum inserts could be bent or scratched easily and could change with temperature fluctuations. Stainless steel inserts were more resilient and would not change composition. TechT has recently introduced their iFIT precision barrel boring kit. The biggest obstacle with bore sizing paint is that balls are being manufactured progressively smaller and the bore sizes do not exist. This is where the iFIT comes in handy. Their 6 piece kit includes bore sizes of .670, .673, .676, .679, .682, and .685. There is also a 9 piece kit available that has one bore size smaller and two larger.", + "question_03" : "Why is bore size important?", + "answer_06" : "If you still haven't found a barrel that fits you, you may be interested in a specialized barrel. Tippmann's Flatline barrel is the only barrel on the market that puts a backspin on the paintball. It has a slightly curved barrel which applies centrifugal force to the ball creating the backspin. It offers increased accuracy but most of all distance. Targets that would normally be out of range are now achievable. The Flatline Barrel System adds 100 feet of flat trajectory.", + "question_06" : "Flatline Barrel", + "question_04" : "What are the advantages of a carbon fiber barrel?", + "return_link" : "/category/buyers_guide.paintball/", + "answer_01" : "Have you noticed your shots are curving? Is paint breaking inside your barrel? It may be time for an upgrade if these are true for you. Barrels are the most popular upgrades, especially for lower end paintball guns. A new barrel can do wonders for your game. You will increase your accuracy, distance and often times get better air efficiency. Some barrels can even be quieter than the stock barrel.", + "zoovy:banner01" : "banners/storewide/other/zephyr_buyersguide_header002", + "question_07" : "Apex Barrel", + "text_01" : "A marker's barrel directs the paintball and controls the release of the gas pocket behind it. One of the most important and popular upgrades you can do to your paintball gun is get an aftermarket barrel. Not only can you increase accuracy, but you may see a difference in range and efficiency. It can be difficult when choosing a new barrel for your gun. Many different aspects go into choosing one such as length and bore size.\n\n\nWhat kind of barrel should I get? That is a very common question among paintballers and is tough to answer. You need to look at what style of paintball you play and choose a barrel that fits your needs accordingly. We will answer various questions in this paintball barrel buyer's guide.\n", + "question_01" : "Why should I get a new barrel?", + "title_01" : "Paintball Barrels", + "answer_07" : "BT Designs have developed a barrel that can literally shoot around corners. The Apex barrel has an adjustable tip that can be used to curve the paintball. Just adjust the ramp switch to choose the desired level of curve and twist the barrel any way you like to attain left hooks, right hooks, drop shots and long flat trajectory shots. This is a popular barrel in woodsball and is commonly available for Tippmann and Spyders markers.\n\n\nTippmann modifications have become very popular. We have barrels available by Maddog Designs and BT Designs that can turn your ordinary Tippmann 98 or A5 into an M-16 or AK-47." + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.mp7_airsoft_guns" : { + "meta_description" : "MP7 Airsoft Guns - Buy your Airsoft MP7 At Zephyr Sports for Less Today! We carry a complete line of MP7 AEG Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "top_description" : "Below are replica MP7 Airsoft Sub-Machine Guns. The original MP7 is a German SMG manufactured by Heckler & Koch. What is most interesting about this particular SMG is its ammunition...\nWith the proliferation of high-quality body armor, most early pistol ammunition had been rendered useless when put to the test. In response to this trend, HK designed the MP7 to penetrate body armor, yet be small enough to be used in place of either a pistol or a submachine gun. With that, the MP7 essentially operates like a scaled-down assault rifle, firing a specially designed, armor-piercing round with a muzzle velocity nearly as high as that of many modern rifles. \n\n\n", + "page_title" : "Buy MP7 Airsoft Guns On Sale & Free Shipping", + "head_title" : "MP7 Airsoft Guns |Airsoft MP7 |MP7 AEG Airsoft Gun", + "description" : "" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_offshoot_sunglasses" : {}, + ".maddog.barrels" : {}, + ".casual_clothing.mens_clothing.rash_guards" : { + "meta_description" : "Rash Guards - Buy your Surf Rash Guards At Zephyr Sports for Less Today! We carry a complete line of Surf Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Rash Guards On Sale & Free Shipping", + "head_title" : "Rash Guards | Surf Rash Guards | Surf Shirts" + }, + ".black_friday_paintball_and_airsoft_deals.airsoft" : {}, + ".scenarioupgrades.scenario_apparel.camo_paintball_gloves" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_hiball_sunglasses" : { + "meta_description" : "Spy Optics HiBall Sunglasses - Zephyr Sports carries a complete line of HiBall Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy HiBall Sun Glasses Online Today.", + "page_title" : "Spy Optics HiBall Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics HiBall Sunglasses | HiBall Spy Sunglasses Free Shipping | Buy Spy HiBall Sun Glasses" + }, + ".harnessesbags.paintball_gear_bags.dye_gear_bags___backpacks" : { + "meta_description" : "Dye Navigator - Buy your Dye Paintball Gear Bags Online at Zephyr Paintball for Less today. Free Shipping on Dye Backpacks Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Navigator Online On Sale Now", + "head_title" : "Dye Navigator | Dye Paintball Gear Bags | Dye Backpacks" + }, + ".0001a_christmas_sale" : { + "banner4_link" : "/category/0001a_christmas_sale.0050", + "banner2" : "banners/holiday/holiday_specials_btn_10_003.jpg", + "banner3_link" : "/category/0001a_christmas_sale.0025", + "banner1" : "banners/holiday/holiday_specials.jpg", + "banner4" : "banners/holiday/holiday_specials_btn_50_001.jpg", + "banner3" : "banners/holiday/holiday_specials_btn_25_001.jpg", + "banner2_link" : "/category/0001a_christmas_sale.0010" + }, + ".apparel.head_bands_and_wraps" : {}, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.aug_aeg_airsoft_magazines" : {}, + ".casual_clothing.mens_clothing.tshirts.blind_t_shirts" : { + "meta_keywords" : "Blind T Shirts,Blind shirts,free shipping,Blind TShirt", + "meta_description" : "Blind T Shirts - Zephyr carries a complete line of Blind Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Blind T Shirts at Zephyr", + "head_title" : "Blind T Shirts | Blind Shirts | Blind TShirt" + }, + ".casual_clothing.mens_clothing.jackets.north_face_jackets" : { + "meta_description" : "North Face Jackets - Buy your North Face Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On North Face Jackets with Free Shipping", + "head_title" : "North Face Jackets | North Face Mens Jackets" + }, + ".markers.kingmanspyder.spyder_xtra_paintball_guns" : { + "meta_keywords" : "spyder extra,spyder xtra,xtra paintball gun,kingman xtra,paintball marker,semi auto,entry level,spyder xtra package", + "meta_description" : "Spyder Xtra Paintball Guns - Buy your Xtra Spyder Paintball Marker Online at Zephyr Paintball for Less today. Free Shipping on eXtra Paintball Gun Trust Zephyr for all your Paintball Needs", + "top_description" : "The Spyder Xtra paintball gun from Kingman. Bullet proof semi automatic .68cal paintball marker with the patent pending EKO valve system enabling 1600+ shots from a 20 oz co2 tank. The Spyder extra includes and aluminum body, grip frame and clamping feedneck for the ultimate in durability. The Xtra comes stock with a 9\" spyder threaded barrel and is compatible with co2 or compressed air. Looking for a complete spyder xtra package? Zephyr has you covered with the most packages at the best prices on the web. ", + "page_title" : "Buy Spyder Xtra Paintball Guns Online On Sale Now", + "head_title" : "Spyder Xtra Paintball Guns | Xtra Spyder Paintball Marker | eXtra Paintball Gun", + "banner02_link" : "http://www.zephyrpaintball.com/category/3packagespecials.kingman_spyder_paintball_packages.spyder_xtra_paintball_gun_packages/", + "zoovy:banner02" : "banners/paintball/headers/packagespecials_header001" + }, + ".casual_clothing.mens_clothing.belts.dakine_belts" : { + "meta_keywords" : "Dakine Belts,Dakine Belt Buckle,Dakine Belts,Dakine webbed belt", + "meta_description" : "Dakine Belts - We carry the complete line of Dakine Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Dakine Belts on Sale Now!", + "head_title" : "Dakine Mens Belts | Aplinestars Belts" + }, + ".casual_clothing.mens_clothing.tshirts.neff_t_shirts" : { + "meta_keywords" : "Neff T Shirts,Neff shirts,free shipping,Neff TShirt", + "meta_description" : "Neff T Shirts - Zephyr carries a complete line of Neff Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Neff Tshirt Today", + "page_title" : "Neff T Shirts at Zephyr", + "head_title" : "Neff T Shirts | Neff Shirts | Neff TShirt" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts.oakley_replacement_lenses.oakley_half_jacket_replacement_lenses" : { + "meta_description" : "Oakley Half Jacket Lenses - Zephyr Sports carries a complete line of Half Jacket Oakley Replacement Lenses At the lowest prices on the web with free shipping and easy returns. Buy your Half Jacket Oakley Lenses Online Today.", + "page_title" : "Oakley Half Jacket Lenses On Sale Free Shipping", + "head_title" : "Oakley Half Jacket Lenses | Half Jacket Oakley Replacement Lenses | Half Jacket Oakley Lenses" + }, + ".maddog.ion_upgrades.ion_front_grips" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns" : {}, + ".loaders.odyssey" : { + "meta_keywords" : "Odyssey Loaders, Odyssey Halo Loaders, Odyssey Paintball Halo Loader, Halo Loaders, Odyssey Halo, Odyssey Paintball, Paintball Halo Loaders, Paintball Equipment, Paintball Supplies", + "meta_description" : "Odyssey Loaders - With the lowest prices on Odyssey paintball Halo loaders online, ZephyrPaintball is the best place to shop for paintball equipment and supplies.", + "zoovy:banner01" : "banners/paintball/headers/hopperaccessories_header001", + "banner01_link" : "/category/loaders.hopper_accesories.odyssey_halo_accesories/", + "description" : "Highly Advanced Loader Operations - HALO. Odyssey hoppers are made from polycarbonate for a light and extremely durable hopper. The feed neck is internally reinforced with a one piece tubular sleeve to make it strong and reliable. All the screws, which hold the HALO together, screw into metal nuts; to avoid stripping out of the shell. We know the shell is durable but how about the performance? The \"catch cup\" or circular recess in the bottom of the loader gives the paint an easy track to help the flow of the paint. Centered in the catch cup is the drive cone. The drive cone has a few compartments that help direct the paintballs down the feed neck into the paintball gun. The mechanics of this hopper were well thought out to be a reliable, consistent loader. The Halo is similar to most hoppers when it comes to size and weight. It holds about 180 paintballs and will do the job for any beginner gun or even some of the top of the line paintball guns. When you are first starting out and getting the feel of paintball a standard halo will do the job. Now, when you get into the higher performing paintball guns such as a G3, Invert Mini, 09 Rail you may want to consider the [[Victory 35 Board]:url=http://www.zephyrpaintball.com/product/PB-HALO-VICTORY/Odyssey_Halo_Victory_35_Board.html]. The upgraded Victory Board allows up to 35 balls per second. Better battery life and better response. This board is not an absolute necessity but if you feel your halo is not up to par with your gun, it's something to consider. ", + "page_title" : "Buy Halo Hoppers Online On Sale Now", + "head_title" : "Halo Hoppers | Halo B Loader | Halo Paintball Loaders", + "page_head" : "" + }, + ".casual_clothing.mens_clothing.hats.obey_hats" : { + "meta_keywords" : "Obey Hats,Obey caps,Obey baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Obey Hats - Zephyr carries a complete line of Obey Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Obey", + "page_title" : "Obey Hats on Sale at Zephyr", + "head_title" : "Obey Hats | Obey Caps | Obey Baseball Hats" + }, + ".harnessesbags.backpacks.metal_mulisha_bags.metal_mulisha_womens_purses_and_bags" : { + "meta_description" : "Metal Mulisha Purses - Buy your Metal Mulisha Womens BagsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Womens Purses and Bags Backpacks & Bags Ship Free ", + "head_title" : "Metal Mulisha Purses | Metal Mulisha Womens Bags" + }, + ".3packagespecials.tippmann_packages.tippmann_98_paintball_packages" : { + "meta_description" : "Tippmann 98 Package - Buy your Tippmann 98 Packages Online at Zephyr Paintball for Less today. Free Shipping on Tippmann 98 Custom Package Trust Zephyr for all your Paintball Needs", + "top_description2" : "Tippmann 98 Packages from Zephyr. Our custom 98 packages start with a choice of the gun. The tippmann 98 comes in two main versions. The Tippmann Custom 98 Platinum gun includes Tippmanns ACT Anti Chop technology to reduce broken paint in your gun. Tippmann 98 kits are also available with the tippmann 98 ultra marker. This is the same model 98 but without tippmann's ACT technology. ", + "page_title" : "Buy Tippmann 98 Package Online On Sale Now", + "head_title" : "Tippmann 98 Package | Tippmann 98 Packages | Tippmann 98 Custom Package", + "description" : "=Tippmann Custom 98 Package Details=\n\n\nBronze Package - Our entry level Tippmann model 98 package includes a basic 20 oz tank to get you 1000+ shots per fill as well as an entry level paintball mask,200 rd hopper, rubber pull squeegee, gun oil and Zephyr Paintball american flag barrel cover (while supplies last)\n\n\nSilver Package - Our next level Tippmann 98 package includes everything from our bronze package, Tank, Mask, Hopper, oil, and squeegee but adds in a 4+1 harness and pods for those long games. The +1 on this harness is a tank holder. This allows you to take the weight of the tank off of your gun and on your back with the additional of a remote coil (sold seperately). \n\n\nGold Package - This model 98 package includes everything from our bronze package, Tank, Mask, oil, and squeegee but adds in a 4+1 harness and pods for those long games. The +1 on this harness is a tank holder. This allows you to take the weight of the tank off of your gun and on your back with the additional of a remote coil (sold seperately). Finally the gold package swaps out the 200rd gravity fed hopper for an electronic halo too loader that will feed at 20+bps.\n\n\nTitanium Package - This Tippmann 98 package includes everything from our bronze package, but adds in a 6+1 harness and pods for when you really want to carry the extra paint. Most people will prefer the comfort and weight of a 4+1 harness, but we offer a 98 package with the 6+1 harness for those of you who really want to spray paint." + }, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.nixon_headphones.nixon_nomadic_headphones" : { + "head_title" : "Nixon Nomadic Headphones | Nomadic Nixon Head Phones | Nixon Nomadic Headphone" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_modcon_sunglasses" : { + "meta_description" : "Von Zipper Modcon Sunglasses - Buy your Modcon Von Zipper Sunglasses Online At Zephyr Sports for Less Today! We carry a complete line of Von Zipper Modcon at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Von Zipper Modcon Sunglasses Now! On Sale & Free Shipping", + "head_title" : "Von Zipper Modcon Sunglasses | Modcon Von Zipper Sunglasses | Von Zipper Modcon" + }, + ".casual_clothing.mens_clothing.socks.dakine_socks" : { + "meta_keywords" : "Dakine socks,dakine mens socks,dakine men socks", + "meta_description" : "Dakine Socks - Zephyr stocks a complete line of Dakine Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Dakine needs. ", + "page_title" : "Dakine Socks on Sale at Zephyr", + "head_title" : "Dakine Socks | Dakine Mens Socks | Socks Dakine" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.h_k_spring_airsoft_pistols" : { + "meta_description" : "Heckler & Koch Airsoft Guns - Buy your H & K Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Heckler & Koch Spring Airsoft Guns at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Heckler & Koch Airsoft Guns On Sale & Free Shipping", + "head_title" : "Heckler & Koch Airsoft Guns | H & K Airsoft Rifles | Heckler & Koch Spring Airsoft Guns" + }, + ".shop_by_brand.revision_eyewear" : {}, + ".3packagespecials.azodin_paintball_packages.azodin_blitz_packages" : { + "meta_description" : "Azodin Blitz Paintball Packages - Buy your Azodin Blitz Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Blitz Azodin Marker Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Azodin Blitz Paintball Packages Online On Sale Now", + "head_title" : "Azodin Blitz Paintball Packages | Azodin Blitz Paintball Guns | Blitz Azodin Marker" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_shoreline_sunglasses" : { + "meta_description" : "Smith Optics Shoreline Sunglasses - Zephyr Sports carries a complete line of Shoreline Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Shoreline Sun Glasses Online Today.", + "page_title" : "Smith Optics Shoreline Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Shoreline Sunglasses | Shoreline Smith Sunglasses Free Shipping | Buy Smith Shoreline Sun Glasses" + }, + ".casual_clothing.womens_clothing.ladies_sandals.oakley_womens_sandals" : {}, + ".apparel.gloves" : { + "meta_keywords" : "paintball gloves,dye glove,empire gloves,empire paintball gloves,gloves paintball,dye meta gloves,invert gloves", + "meta_description" : "Gloves Paintball - Get your Paintball Gloves at Zephyr Paintball. Complete line of gloves from all the top manufacturers including Empire Paintball Gloves", + "page_title" : "", + "head_title" : "Paintball Gloves | Gloves Paintball | Empire Paintball Gloves", + "prodlist1_header" : "Featured Paintball Gloves", + "page_head" : "" + }, + ".3packagespecials.dye_paintball_package_specials.dye_dm_package_specials" : { + "meta_description" : "Dye DM Paintball Packages - Buy your DM Dye Paintball Kits Online at Zephyr Paintball for Less today. Free Shipping on Dye DM Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye DM Paintball Packages Online On Sale Now", + "head_title" : "Dye DM Paintball Packages | DM Dye Paintball Kits | Dye DM Paintball Guns" + }, + ".maddog.tippmann_upgrades" : {}, + ".airsoft.airsoft_guns.galil_airsoft_guns" : { + "meta_keywords" : "Kalashnikov,Galil Replica Airsoft Guns,airsoft replicas,CYMA Galil Rifles,CYMA Galil SAR Airsoft Guns", + "meta_description" : "Galil Replica Airsoft Guns. The Galil is a family of Israeli small arms produced by the Israel Military Industries (IMI) Ltd, the same group that produced the desert eagle pistol. The Galil family is similar to the Kalashnikov design in operation and shares similarities in the design. The Galil though, comes in many different variations. These airsoft replicas offer a very realistic look and feel including a heavier feel for added realism. The high-end versions offer full metal bodies and higher rates of fire.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "CYMA Galil Rifles On Sale & Free Shipping", + "head_title" : "CYMA Galil Rifles | CYMA Galil SAR Airsoft Guns", + "description" : "" + }, + ".promotions" : { + "top_html_focus" : "", + "dynimage1" : "images=T/tippmannrebate_big_002.jpg\nlinks=\npauses=100\nblank_behavior=none\n", + "top_description2" : "Tippmann is offering a rebate to get you on the field. Applies to all Tippmann 98 guns and packages purchased from 10/15/11 through 1/15/12. All rebates must be postmarked to tippmann prior to 1/31/12.\n\n\n\n\n\n\nTo process your gift card, you will need a copy of your invoice as well as fill out the [[Rebate Form]:popup=https://tippmann.4myrebate.com/?oc=TIP-5009]\n", + "banner01_link" : "%SESSION%/category/3packagespecials.tippmann_packages.tippmann_98_paintball_packages/", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "description" : "=All Gift cards are issued directly from Tippmann. Zephyr Sports Customer Service is unable provide the status of your gift card=\n" + }, + ".airsoft.airsoft_guns.airsoft_bb_launchers___shells.maddog_sports" : {}, + ".markerupgrades.smartparts.epiphany.epiphany_feed_necks" : {}, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_fixed_power_scopes.leapers_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Leapers rifle scopes | Leaper UTG | Leapers scopes" + }, + ".apparel.jerseys.dyejerseys.a_dye_c9_paintball_jerseys" : { + "meta_keywords" : "Dye Paintball Jersey,Dye Paintball C9 Jersey,Paintball Dye C9 Jersey,Dye Paintball,Paintball Jersey,Dye,Dye C9 Jersey,Dye Jersey", + "meta_description" : "Dye Paintball C9 Jersey - 2009 Dye Paintball jerseys are still available. Get your Dye C9 Paintball Jersey while you still can! Limited sizes and colors are available. \r ", + "page_title" : "Dye C9 Paintball Jersey | Limited Stock Available", + "head_title" : "Dye C9 Paintball Jersey - Dye Paintball C9 Jersey - Paintball Dye C9 Jersey" + }, + ".casual_clothing.mens_clothing.tshirts.tanked_t_shirts" : { + "meta_keywords" : "Tanked T Shirts,Tanked shirts,free shipping,Tanked TShirt", + "meta_description" : "Tanked T Shirts - Zephyr carries a complete line of Tanked Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Tanked T Shirts at Zephyr", + "head_title" : "Tanked T Shirts | Tanked Shirts | Tanked TShirt" + }, + ".airsystems.hosesfittings" : { + "meta_description" : "Paintball Hoses - Buy your Paintball Hose Line Online at Zephyr Paintball for Less today. Free Shipping on Air Line Paintball Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Hoses Online On Sale Now", + "head_title" : "Paintball Hoses | Paintball Hose Line | Air Line Paintball" + }, + ".markerupgrades.alien_paintball" : { + "banner01_link" : "/category/barrels.autococker/", + "zoovy:banner01" : "banners/paintball/headers/autococker_threaded_barrels.jpg" + }, + ".casual_clothing.z-sunglasses.suncloud_sunglasses.suncloud_voyage_polarized_sunglasses" : { + "meta_description" : "Suncloud Voyage Polarized Sunglasses - Zephyr Sports carries a complete line of Voyage Suncloud Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Suncloud Voyage Sun Glasses Online Today.", + "page_title" : "Suncloud Voyage Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Suncloud Voyage Polarized Sunglasses | Voyage Suncloud Sunglasses Free Shipping | Buy Suncloud Voyage Sun Glasses" + }, + ".airsystems.dropforwards.invert_asa_s" : { + "meta_description" : "Invert ASA - Buy your Invert Mini ASA Online at Zephyr Paintball for Less today. Free Shipping on Empire Relay Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Invert ASA Online On Sale Now", + "head_title" : "Invert ASA | Invert Mini ASA | Empire Relay" + }, + ".casual_clothing.mens_clothing.tshirts.toy_machine_t_shirts" : { + "meta_description" : "Toy Machine T-shirts - Buy your Toy Machine Shirts Online At Zephyr Sports for Less Today! We carry a complete line of Toy Machine Skate Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Toy Machine T-shirts Now! On Sale & Free Shipping", + "head_title" : "Toy Machine T-shirts | Toy Machine Shirts | Toy Machine Skate Shirts" + }, + ".barrels.barrels_by_manufacturer.empire_barrels" : { + "top_html_focus" : "", + "meta_keywords" : "empire superfreak, superfreak barrel,paintball, guns, freak barrel kit,barrels, upgrades, replacements, mini, marker, super freak, autococker, auto, cocker, auto-cocker, a5, a-5, a, 5, a 5, threads, aluminium, carbon fiber, 0.675, 0.680, 0.685, 0.690, 0.695, kit, system, axe, bt, invert mini, sniper", + "meta_description" : "Empire Super Freak Paintball Barrels - The hottest new barrel from Empire, the Empire Super Freak Barrel Kit System. Buy them first at Zephyr with Free Shipping", + "top_description2" : "", + "page_title" : "Buy Online Empire Super Freak Barrels On Sale Now", + "head_title" : "Empire Super Freak | Superfreak Paintball Barrels", + "description" : "==Empire Super Freak Barrel Kit System:==\n\n\nEmpire Paintball has released a new barrel system called the Super Freak that retails for $199.95. It comes with numerous tips and inserts so you can adapt to any kind of play in any weather condition. It also comes with a one of a kind Carrying Case to house all of the different components without scratching this beautiful work of art!\n\n\n===Available in Autococker and BT/Tippmann A-5 Barrel Threads.===\n\n\n=Included in the kit:=\n\n\n* (1) Super Freak Barrel Back\n* (1) 14\" Ported Aluminum Barrel Tip\n* (1) 14\" Carbon Fiber Barrel Tip\n* (1) 17\" Apex2 Barrel Tip\n* (5) Aluminum Freak Barrel Inserts in the following Bore sizes: .675, .680, .685, .690 and .695\n* (1) Soft Barrel Case with slots for each Super Freak Barrel Component\n\n\nThis kit is completely compatible with all past Smart Parts and GoG freak barrel components, so if you already have parts and want to compile them with this new system you are set! Mix and match to your liking and be a SUPER FREAK on the field!!!" + }, + ".loaders.allen_paintball_hoppers" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_loaders.valken_v-max_paintball_loaders" : {}, + ".casual_clothing.mens_clothing.beanies.nixon_beanies" : { + "meta_keywords" : "Nixon beanie,Nixon hat,Nixon beanies,Nixon caps,Nixon 686,Nixon headwear,Nixon cuff visor beanie,Nixon beanie hat,Nixon visor beanie,Nixon visor beanies", + "meta_description" : "Nixon Deanie - Surf style with Nixon Beanies available now at Zephyr Sports. Get your Nixon hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Nixon Beanies on Sale at Zephyr Today", + "head_title" : "Nixon Beanie | Nixon Hat | Nixon Beanies" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.famas_aeg_airsoft_guns" : { + "meta_description" : "FAMAS Airsoft Guns - Buy your FAMAS Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of FAMAS AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy FAMAS Airsoft Guns On Sale & Free Shipping", + "head_title" : "FAMAS Airsoft Guns | FAMAS Airsoft Rifles | FAMAS AEG" + }, + ".casual_clothing.mens_clothing.hats.neff_hats" : { + "meta_keywords" : "Neff Hats,Neff caps,Neff baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Neff Hats - Zephyr carries a complete line of Neff Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Neff", + "page_title" : "Neff Hats on Sale at Zephyr", + "head_title" : "Neff Hats | Neff Caps | Neff Baseball Hats" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_day_star_hydration_packs" : {}, + ".barrels.barrels_by_manufacturer.techt_ifit_barrel_system" : { + "htmlvids" : "", + "meta_description" : "TechT iFit Barrel System - Buy your iFit Techt Paintball Barrels Online at Zephyr Paintball for Less today. Free Shipping on TechT iFit Trust Zephyr for all your Paintball Needs", + "top_description" : "==iFIT Paintball Barrel Boring Kit==\n\nAfter buying several brands and grades of paintballs, and sizing them all, we have found that many paintball manufacturers have started manufacturing paint smaller than .679 (smallest industry standard bore available). In many cases this change to a smaller bore paintball means that your current set of barrels are too big for the paint you are forced to buy. This means you will have less accuracy/efficiency.\n\n\nThe iFIT is a totally modular system that accommodates all paintballs and re-balls being sold today! What does this mean for you? It means that with nothing more than the barrels you already have in your gear bag, you can start sizing your paintballs correctly and obtaining those increases. It works with ANY barrel, on ANY gun. The iFit Kit allows for optimal compression of any paintball to maximize the potential gains from your barrel.\n\n=Features:=\n* Works w/ ANY BARREL on ANY GUN\n* Largest range in bore sizes you will find from ANY manufacturer!\n* The iFIT Kit ranges in size from .692 down to .667.\n* The most efficient and accurate barrel kit on the Market!", + "page_title" : "Buy TechT iFit Barrel System Online On Sale Now", + "head_title" : "TechT iFit Barrel System | iFit Techt Paintball Barrels | TechT iFit", + "zoovy:banner01" : "banners/paintball/headers/1_techt_ifit_barrel_kit_header.jpg" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.m4_and_m16_style_aeg_magazines" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markers.smartparts" : { + "meta_keywords" : "smart parts paintball guns, smart parts guns, smart parts paintball, smart parts impulse, impulse paintball gun, smart parts ion, vibe paintball gun, sp ion, sp impulse, 09 impulse, smart parts 09 paintball gun", + "banner1" : "banners/categories/guns/smart_pars_banner.jpg", + "meta_description" : "Smart Parts Paintball Guns - Zephyr carries the complete line of Smart Parts Guns with free shipping over $100", + "page_title" : "", + "head_title" : "Smart Parts Paintball Guns | Smart Parts Guns | Smart Parts Impulse", + "prodlist1" : "&FORMAT=DEFAULT&SRC=" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_asian_fit_sunglasses.oakley_asian_fit_straight_jacket_sunglasses" : { + "meta_description" : "Oakley Asian Fit Straight Jacket Sunglasses - Zephyr Sports carries a complete line of Straight Jacket Asian Fit Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Straight Jacket Asian Fit Sun Glasses Online Today.", + "page_title" : "Oakley Asian Fit Straight Jacket Sunglasses On Sale Free Shipping", + "head_title" : "Oakley Asian Fit Straight Jacket Sunglasses | Straight Jacket Asian Fit Oakley Sunglasses | Oakley Straight Jacket Asian Fit Sun Glasses" + }, + ".casual_clothing.mens_clothing.sandals.sanuk_sandals" : { + "meta_description" : "Sanuk Sandals - Buy your Mens Sanuk Sandals At Zephyr Sports for Less Today! We carry a complete line of Sanuk Flip Flops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Sanuk Sandals On Sale at Zephyr Sports", + "head_title" : "Sanuk Sandals | Mens Sanuk Sandals | Sanuk Flip Flops" + }, + ".casual_clothing.mens_clothing.shorts.empire_shorts" : { + "meta_description" : "Empire Shorts - Zephyr stocks a complete line of Empire Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Empire needs. ", + "page_title" : "Empire Shorts with Free Shipping at Zephyr", + "head_title" : "Empire Shorts | Empire Board Shorts" + }, + ".casual_clothing.mens_clothing.jackets.billabong_jackets" : { + "meta_description" : "Billabong Jackets - Buy your Billabong Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Billabong Jackets with Free Shipping", + "head_title" : "Billabong Jackets | Billabong Mens Jackets | Jackets Billabong" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.1_search_by_size.1_x-small_ladies_tank_tops" : {}, + ".1newitems.2008_products.2008_jt_paintball_gear" : {}, + ".scenarioupgrades.tactical_vests.bravo_tactical_vests" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_capitol_watches" : { + "meta_keywords" : "Nixon watches,nixon Capitol watch,nixon watch,nixon Capitol chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Capitol Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Capitol Chrono Watches", + "head_title" : "Nixon Capitol Watches | Nixon Capitol Chrono Watch | Nixon 5130" + }, + ".shop_by_brand.ics_airsoft_buy_online_free_shipping_now" : {}, + ".casual_clothing.mens_clothing.belts.fox_belts" : { + "meta_description" : "Fox Belts - Buy your Fox Mens BeltsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on FOX BELTS @ Zephyr Sports", + "head_title" : "Fox Belts | Fox Mens Belts | Mens Belt Fox" + }, + ".maddog.maddog_aluminum_ions" : {}, + ".markers.macdev_paintball_guns" : {}, + ".markerupgrades.intimidator.intimidator_triggers" : {}, + ".shop_by_brand.us_army" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tPaintball Guns\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tPaintball Packages\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tOther Gear\n\t\n
                                                                          \n
                                                                          ", + "meta_description" : "US Army Paintball - Zephyr Sports carries a complete line of Paintball US Army At the lowest prices on the web with free shipping and easy returns. Buy your US Army Paintball Guns Online Today.", + "top_description2" : "=Play Smart, Play strong, US Army Paintball=\n\nManufactured by Tippmann Sports, U.S. Army Paintball guns and accessories are designed to help you take your game to the highest level of realistic play possible at a great value. At home and abroad, the U.S. Army has utilized Tippmann paintball markers in its training to emphasize the importance of fire-control measures and cover and concealment procedures. No other training device can replicate this sense of combat realism in a totally safe environment. With these markers, you will be able to play smart…and play strong. Army Strong.", + "page_title" : "US Army Paintball On Sale Free Shipping", + "head_title" : "US Army Paintball | Paintball US Army | US Army Paintball Guns", + "zoovy:banner01" : "banners/paintball/headers/usarmy_header.jpg", + "description" : "=Play Smart, Play Strong, US Army Paintball=\n\n==Army Smart, Army Strong=\nPlay like never before with unmitigated realism in your paintball gun. Done are the days of flashy Guns and Neon Yellow hoppers, this is the Army now. Grab one of the realistic weapons and get out into that scenario. It's no longer play to win, it's play to survive. So get out there and run the hottest and most realistic thing next to real steel. OORAH!\n\n\n==Tactical, Realistic Weapons==\nAll U.S ARMY Paintball Guns come with a realistic look and style ranging to AR-15's and M-16's. Most come with Rails and interchangeable stocks just like the real thing. \n\n==These aren't just for looks.==\nMade by Tippman paintball, you know these products aren't just for show. These guns will shoot, shoot and shoot till no tomorrow. Although, because they are made for the U.S. ARMY they have an undefined ruggedness that no one thought possible in the Paintball field before. These are scenario guns, not Flashy-shiny-if you drop it it will shatter into a thousand pieces-guns. \n\n==Accessories==\nMade for the hard core scenario enthusiast, these products are battle tested and ready for action. U.S. Army Paintballs, Ranger Goggles and Harnesses are quality made components made to enhance serious game. \n\n \n\n" + }, + ".apparel.shoes.1search_by_size.f_men_s_size_8_shoes" : {}, + ".casual_clothing.mens_clothing.sweatshirts.dvs_sweatshirts" : { + "meta_description" : "DVS Sweatshirts - Buy your DVS Hoodies At Zephyr Sports for Less Today! We carry a complete line of DVS Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DVS Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "DVS Sweatshirts | DVS Hoodies | DVS Hoody" + }, + ".skateboard_gear.skateboard_longboards.globe_longboards" : { + "meta_description" : "Globe Longboards - Zephyr Sports carries a complete line of Globe Longboard Skateboards Globe Skateboards Longboards At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Globe Longboards On Sale Free Shipping", + "head_title" : "Globe Longboards | Globe Longboard Skateboards Globe Skateboards Longboards" + }, + ".testing_help_desk" : { + "hd_returns_listing" : "» What is the Zephyr Return Policy?
                                                                          \n» How do I return/exchange my product?
                                                                          \n» I received the wrong product.
                                                                          \n» I received someone else's order.
                                                                          \n» My order is missing an item(s).
                                                                          ", + "hd_my_account_link" : "/category/testing_help_desk.my_account", + "hd_shipping" : "Shipping", + "hd_returns" : "Returns", + "hd_shipping_link" : "/category/testing_help_desk.shipping", + "hd_pricing_billing_link" : "/category/testing_help_desk.pricing_and_billing", + "hd_pricing_billing_listing" : "» What are my payment choices?
                                                                          \n» When will my credit card be charged?
                                                                          \n» When will my credit appear on my account?
                                                                          \n» I have questions about my charges.
                                                                          \n» I need a copy of my receipt/invoice.
                                                                          \n» Do I have to pay sales tax?
                                                                          \n» Low Price Guarantee
                                                                          \n» The buySAFE Bond Guarantee.
                                                                          ", + "hd_my_account_listing" : "» How do I create an account?
                                                                          \n» How do I edit my account information?
                                                                          \n» I forgot my login name.
                                                                          \n» I forgot my password.
                                                                          ", + "hd_buyers_guide_link" : "/category/testing_help_desk.buyers_guide", + "hd_internationl_orders_listing" : "» Do you ship to APO or FPO addresses?
                                                                          \n» Do you ship to my country?
                                                                          \n» What are my payment options?
                                                                          ", + "hd_shipping_listing" : "» Does my shipping and billing addresses have to match?
                                                                          \n» How much is shipping?
                                                                          \n» Does my package require a signature?
                                                                          \n» When will my order ship?
                                                                          \n» Can I pick up my order?
                                                                          \n» Can I track my package?
                                                                          \n» Free Zephyr Shipping.
                                                                          \n» Holiday Shipping Deadlines
                                                                          ", + "hd_about" : "About Zephyr Sports", + "hd_about_link" : "/category/testing_help_desk.about_zephyr_sports", + "hd_warranty" : "Warranty", + "hd_about_listing" : "» Contact Us
                                                                          \n» Privacy Policy
                                                                          \n» Why Shop at Zephyr Sports?
                                                                          \n» Job Opportunities
                                                                          ", + "hd_warranty_listing" : "» My Product is broken or doesn't work.
                                                                          \n» Who should I contact for warranty repairs?
                                                                          \n» Do paintballs have a warranty?
                                                                          \n» Money Back Guarantee on sunglasses.
                                                                          \n» Breakage Protection Plan on sunglasses.
                                                                          \n» General Airsoft Warranty.
                                                                          ", + "hd_pricing_billing" : "Pricing and Billing", + "hd_order_status_listing" : "» Has my order shipped?
                                                                          \n» How do I track my order?
                                                                          \n» I never received my order?
                                                                          \n» How do I cancel my order/item?
                                                                          \n» What is your out of stock policy?
                                                                          \n» An item is missing from my shipment.
                                                                          \n» My product is missing parts.
                                                                          \n» Can I make changes to my order?
                                                                          \n» Can I combine two orders?
                                                                          ", + "hd_buyers_guide_listing" : "» How do I use a coupon or promo code?
                                                                          \n» How do I find a product?
                                                                          \n» How do I navigate the site?
                                                                          \n
                                                                          » Large Order Verification", + "hd_buyers_guide" : "Buyer's Guide", + "hd_international_orders" : "International Orders", + "hd_my_account" : "My Account", + "hd_international_orders_link" : "/category/testing_help_desk.international_orders", + "hd_order_status" : "Order Status", + "hd_order_status_link" : "/category/testing_help_desk.testing_help_desk_answers", + "hd_returns_link" : "/category/testing_help_desk.returns", + "hd_warranty_link" : "/category/testing_help_desk.warranty" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_giggles_sunglasses" : { + "meta_description" : "Von Zipper Giggles Sunglasses - Buy your Giggles Von Zipper Sunglasses Online At Zephyr Sports for Less Today! We carry a complete line of Von Zipper Giggles at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Von Zipper Giggles Sunglasses Now! On Sale & Free Shipping", + "head_title" : "Von Zipper Giggles Sunglasses | Giggles Von Zipper Sunglasses | Von Zipper Giggles" + }, + ".casual_clothing.z-sunglasses.z_sunglass_cases" : { + "meta_description" : "Sunglasses Case - Zephyr Sports carries a complete line of Buy Case for Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Case Sunglass Free Shipping Online Today.", + "page_title" : "Sunglasses Case On Sale Free Shipping", + "head_title" : "Sunglasses Case | Buy Case for Sunglasses | Case Sunglass Free Shipping" + }, + ".casual_clothing.mens_clothing.tank_tops.enjoi_tank_tops" : {}, + ".maddog.dye___proto_matrix_upgrades" : {}, + ".zephyr" : { + "banner2" : "", + "banner1" : "banners/09_headers/main_categories/retail_store_001.png", + "htmlvids" : "Our New Store is now open for business at 2978 Seaborg Ave. Ventura, CA 93003. The new location is 3 times the size of the old store for our vast inventory of Sports, Paintball, and Airsoft products. Come in and see the brand new location and the 2,100 sq foot show room! You can get directions through Google here Zephyr Directions \n\n\n\n\"Outside", + "description" : "=Storefront Hours=\nSunday: \t\t8:00 - 4:00
                                                                          \nMonday: \t\t10:00 - 5:30
                                                                          \nTuesday: \t\t10:00 - 5:00
                                                                          \nWednesday: \t10:00 - 5:00
                                                                          \nThursday:\t\t10:00 - 5:30
                                                                          \nFriday: \t\t10:00 - 5:30
                                                                          \nSaturday: \t\t8:00 - 5:00
                                                                          \n
                                                                          \n\nPhone: 805-275-2040\n\n\nZephyr Sports started out in Paintball back in 2004 and has continued to expand ever since. What was a garage operation selling things here and there on Ebay as a hobby has grown exponentially for the past 8 years and has no signs of slowing down. Since its inception Zephyr has not only become one of the world's biggest Paintball suppliers, they have also broadened their horizons to: Airsoft, Skate, Baseball, Snow, Clothing, Sunglasses, Shoes and much more. Going with the flow is out of the question. Zephyr is always striving to make their customer's shopping experience as painless and simple as possible. After blowing the roof off of 2 warehouses Zephyr Sports moved to a new location 3 times the size in January 2012 and can't wait to continue to supply their customers with excellent products and service for many years to come.\n\n\n==Come get your Co2 and Compressed Air Tanks filled here. Includes Scuba Tanks (air not suitable for diving)==", + "banner2_link" : "/category/zephyr.zephyr_day_paintball_event" + }, + ".2clearance.clearance_upgrades.clearance_grips" : { + "head_title" : "Sale Paintball Grips | Clearance Paintball Grips | Paintball Grips Sale" + }, + ".shop_by_brand.lapco" : { + "top_html" : "\n\n \n \n \n\n
                                                                          \n
                                                                          \n\tLAPCO PAINTBALL GEAR\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n
                                                                          \n", + "head_title" : "Lapco Paintball Barrels | Lapco Paintball" + }, + ".airsoft.tactical_airsoft_gear.camera_and_video_systems" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.watches.freestyle_watches" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_tactical_belts.ncstar_tactical_belts" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.foundation_beanies" : { + "meta_keywords" : "Foundation beanie,Foundation hat,Foundation beanies,Foundation caps,Foundation 686,Foundation headwear,Foundation cuff visor beanie,Foundation beanie hat,Foundation visor beanie,Foundation visor beanies", + "meta_description" : "Foundation Deanie - Surf style with Foundation Beanies available now at Zephyr Sports. Get your Foundation hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Foundation Beanies on Sale at Zephyr Today", + "head_title" : "Foundation Beanie | Foundation Hat | Foundation Beanies" + }, + ".1historical_products.paintball.paintball_harnesses" : {}, + ".markers.dangerous_power_paintball_guns.dangerous_power_g3_paintball_guns" : { + "meta_keywords" : "Dangerous Power, power g3 paintball gun, dangerous power paintball, dangerous power marker, g3 paintball gun, dangerous power gun,dangerous power g3 barrel", + "meta_description" : "Dangerous Power - Maker of the Dangerous Power G3 Paintball Gun. Starting at $299, the G3 is the most advanced paintball marker ever to hit this price range", + "zoovy:banner01" : "images/site_specific/click_here/packagedeals_clickhere_btn003.gif", + "prodlist1_header" : "Dangerous Power G3 & iQ Paintball Guns", + "banner01_link" : "/category/markers.dangerous_power_paintball_guns.dangerous_power_g3_paintball_guns.dangerous_power_g3_paintball_gun_packages", + "zoovy:banner02" : "", + "description" : "From the trials and test of the Dangerous Power Threshold a new design has arrived to take the helm. The G3's entire operation utilizes only 2 moving parts and 6 O-Rings, for Maximum dependability and ease of maintenance.\nThe Dangerous Power G3 Features an easy access to bolt and assembly. Only one screw to remove No hassle Dip switch's allow for selection of 5 firing modes and adjustment of the Dwell; CFOA - Semi - 15bps, NPPL - Semi - 25bps, PSP - Ramping - 15bps, MILL - Ramping - 12bps, NXL - Ramping->Auto - 15bps, PSP - Ramping - 13bps. Operates at 180 - 200psi for more shots and ability to use brittle tournament grade paint. The G3 paintball marker accepts [[autococker threaded upgrade barrels ]:url=http://www.zephyrpaintball.com/category/barrels.autococker/] and [[DM threaded feednecks]:url=http://www.zephyrpaintball.com/category/markerupgrades.proto_slg_upgrades.proto_slg_feed_necks/]. Dangerous Power has packaged the G3 with an [[owners manual]:popup=http://forums.zephyrsports.com/showthread.php?t=10], 11 piece hex key set, replacement o-rings, warranty card, Dangerous Power key chain and Dangerous Power decals to decorate the rest of your paintball gear.\n\n\nThe G3 Limited Edition Paintball gun expands on the features of the Standard G3 by including a 14\" Dangerous Power 2-Piece tournament barrel with a .690 back, Dangerous Power Ape G3 upgrade board, High performance aluminum upgrade trigger and limited edition marker colors. \n\n\nPopular upgrades for the G3 include the [[Techt L7 bolt]:url=http://www.zephyrpaintball.com/product/PB-TT-G3L7/Tech_T_Dangerous_Power_G3_L7_Bolt.html/], Virtue or Ape Upgrade Board, Pressure measuring device and the dangerous power G3 trigger. All G3 upgrades are available at [[Zephyr]:url=http://www.zephyrpaintball.com/category/markerupgrades.dangerous_power_upgrades/].\n\n\n=The G3 will run out high or low pressure compressed air tanks only and is not compatible with Co2.=\n", + "head_title" : "Dangerous Power | Dangerous Power Paintball | G3 Paintball Gun", + "page_title" : "Buy Dangerous Power Online On Sale Now" + }, + ".markers.smartparts.ionpaintballguns.smart_parts_ion_starter_packages" : {}, + ".casual_clothing.mens_clothing.hats.smith_hats" : { + "meta_keywords" : "Smith Hats,Smith caps,Smith baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Smith Hats - Zephyr carries a complete line of Smith Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Smith", + "page_title" : "Smith Hats on Sale at Zephyr", + "head_title" : "Smith Hats | Smith Caps | Smith Baseball Hats" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.umarex_aeg_airsoft_guns" : { + "meta_description" : "Umarex Airsoft Guns - Buy your Umarex AirsoftOnline At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Umarex Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "Umarex Airsoft Guns | Umarex Airsoft" + }, + ".casual_clothing.youth_clothing" : {}, + ".goggles.2-full_coverage_paintball_goggles" : { + "meta_description" : "Full Coverage Paintball Masks - Need a little extra coverage on the paintball field? Check out these full coverage paintball goggles. They provide complete coverage of the top and back of the head so you don't get hurt.", + "page_title" : "Full Coverage Paintball Masks on Sale", + "head_title" : "Full Coverage Paintball Masks | Full Coverage Paintball Goggles" + }, + ".casual_clothing.mens_clothing.tank_tops.1-search_by_size.4-x-large" : {}, + ".apparel.pants.nxe_elevation_paintball_pants" : { + "page_title" : "", + "head_title" : "NXe Paintball Pants | Paintball NXe Pants | NXe Pants Paintball", + "prodlist1_header" : "NXe Paintball Pants", + "zoovy:banner01" : "banners/paintball/slideshow/1_nxe_paintball_pants_pricedrop_slideshow.jpg" + }, + ".casual_clothing.mens_clothing.sweatshirts.von_zipper_sweatshirts" : { + "meta_description" : "Von Zipper Sweatshirts - Buy your Von Zipper Hoodies Online At Zephyr Sports for Less Today! We carry a complete line of Von Zipper Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Von Zipper Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Von Zipper Sweatshirts | Von Zipper Hoodies | Von Zipper Hoody" + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_repo_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon repo sunglasses", + "meta_description" : "Dragon Repo Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Repo Sunglasses" + }, + ".apparel.shoes.1search_by_size.m_men_s_size_115_shoes" : {}, + ".markers.wdp_angel_paintball_guns" : {}, + ".casual_clothing.mens_clothing.hats.krooked_hats" : { + "meta_keywords" : "Krooked Hats,Krooked caps,Krooked baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Krooked Hats - Zephyr carries a complete line of Krooked Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Krooked", + "page_title" : "Krooked Hats on Sale at Zephyr", + "head_title" : "Krooked Hats | Krooked Caps | Krooked Baseball Hats" + }, + ".apparel.pants.tippmann_paintball_pants" : { + "meta_keywords" : "tippmann paintball pants, tippmann fusion pants, tippmann ultralight pants, tippmann apparel, tipman, tippman pants", + "meta_description" : "Tippmann Paintball Pants - Tippmann Fusion pants are available in a standard and lightweight version for those extra hot summer days. Tippmann Apparel is top quality camoflouge gear with the reliability you've come to expect from Tippmann.", + "page_title" : "", + "head_title" : "Tippmann Paintball Pants | Tippmann Fusion Pants | Tippmann Apparel" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_scheme_sunglasses" : { + "meta_description" : "Arnette Scheme Sunglasses - Zephyr Sports carries a complete line of Scheme Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Scheme Sun Glasses Online Today.", + "page_title" : "Arnette Scheme Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Scheme Sunglasses | Scheme Arnette Sunglasses | Arnette Scheme Sun Glasses" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_manual_watches" : {}, + ".skateboard_gear.complete_skateboards.dusters" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_major_league_baseball_sunglasses" : { + "meta_description" : "Oakley Major League Baseball Sunglasses - Zephyr Sports carries a complete line of Major League Baseball Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Major League Baseball Sun Glasses Online Today.", + "page_title" : "Oakley Major League Baseball Sunglasses On Sale Free Shipping", + "head_title" : "Oakley Major League Baseball Sunglasses | Major League Baseball Oakley Sunglasses | Oakley Major League Baseball Sun Glasses" + }, + ".casual_clothing.womens_clothing.ladies_purses_and_bags.metal_mulisha_purses_and_bags" : {}, + ".shop_by_brand.rothco" : { + "top_description2" : "==Rothco, Gear up!==\n\nRothco is America’s foremost wholesale supplier of military and outdoor products. Rothco carries an extensive line of apparel and gear available of all types: retail, wholesale, military, police, security, outdoor products, screen printers, uniform dealers, fashion retailers, and sportswear shops. For over 50 years Rtco has supplied primarily serviced independently-owned Army/Navy surplus stores across America, but in recent years ROTHCO has expanded our customer and product range to include new lines of sportswear. For over 55 years, Rothco has made timeless, vintage military inspired clothing that transcends eras and offers classic, lasting quality appeal. Rothco's vintage military clothing look-book gives a glimpse into our classic styles from our vintage paratrooper fatigues to our bags and backpacks. Try Rothco and get an authentic feel and style in whatever you do!", + "head_title" : "Rothco | Rothco Bags | Rothco shirts", + "description" : "==Rothco, Gear up!==\n\n==Rothco's mission==\n\nTo be the world’s premier provider of military, outdoor and uniform clothing and equipment to all qualified retailers and to supply the uniform of choice to the military, uniform and casual/workwear consumer.\n\nTo develop and distribute products of high quality and value from all available sources, offer the most outstanding customer service to our retail partners, deliver product quickly and accurately, and work together with them, sharing knowledge, enthusiasm, and assistance in all ways to ensure their success, thus ensuring ours.\n\nTo develop programs encouraging good community citizenship, acting locally to make a difference globally. \n\n==Rothco Quality==\n\nRothco products have the same quality you would expect to get from any military product, incompromised performance and strength regardless of the situation. So next time you put on Rothco products don't be afraid to go the long or hard way, because the tougher the situation the better the performance. Try Rothco today and you'll see why we are a proud distributor " + }, + ".3packagespecials.planet_eclipse_package_specials.ego_package_specials" : { + "meta_description" : "Planet Eclipse Ego Paintball Packages - Buy your Planet Eclipse EGO Paintball Guns Kits Online at Zephyr Paintball for Less today. Free Shipping on Eclipse EGO Paintball Markers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Planet Eclipse Ego Paintball Packages Online On Sale Now", + "head_title" : "Planet Eclipse Ego Paintball Packages | Planet Eclipse EGO Paintball Guns Kits | Eclipse EGO Paintball Markers" + }, + ".airsoft.shop_by_brand.intellect" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".3packagespecials.jt_usa_paintball_packages" : { + "head_title" : "JT Paintball Packages | JT Paintball Gun Packages" + }, + ".apparel.gloves.zephyr_sports_paintball_gloves" : { + "page_title" : "", + "head_title" : "Zephyr Paintball Gloves | Gloves Zephyr |Zephyr Paintballing Gloves" + }, + ".casual_clothing.mens_clothing.shoes.emerica_shoes" : { + "meta_description" : "Emerica Shoes - Buy your Emerica Mens Shoes At Zephyr Sports for Less Today! We carry a complete line of Emerica Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Emerica Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Emerica Shoes | Emerica Mens Shoes | Emerica Skate Shoes" + }, + ".casual_clothing.mens_clothing.accessories.misc" : {}, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_brigade_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon brigade sunglasses", + "meta_description" : "Dragon Brigade Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "page_title" : "Dragon Brigade Sunglasses On Sale & Free Shipping", + "head_title" : "Dragon Brigade Sunglasses | Dragon Brigade Sun Glasses" + }, + ".casual_clothing.z_unisex_clothing_accesories.lanyards" : { + "head_title" : "Lanyards | Stretch Lanyards | Neck Lanyards" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_spoiler_sunglasses" : { + "meta_description" : "Smith Optics Spoiler Sunglasses - Zephyr Sports carries a complete line of Spoiler Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Spoiler Sun Glasses Online Today.", + "page_title" : "Smith Optics Spoiler Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Spoiler Sunglasses | Spoiler Smith Sunglasses Free Shipping | Buy Smith Spoiler Sun Glasses" + }, + ".markerupgrades.tippmann.tippmann_x7_upgrades.tippmann_x_7_feed_upgrades" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_unit_watches" : { + "meta_keywords" : "Nixon watches,nixon Unit watch,nixon watch,nixon Unit chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Unit Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Unit Chrono Watches", + "head_title" : "Nixon Unit Watches | Nixon Unit Chrono Watch | Nixon 5130" + }, + ".airsoft.slingshots.1slingshots.firepower_slingshots" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.beanies.von_zipper_beanies" : { + "meta_keywords" : "Von Zipper beanie,Von Zipper hat,Von Zipper beanies,Von Zipper caps,Von Zipper 686,Von Zipper headwear,Von Zipper cuff visor beanie,Von Zipper beanie hat,Von Zipper visor beanie,Von Zipper visor beanies", + "meta_description" : "Von Zipper Deanie - Surf style with Von Zipper Beanies available now at Zephyr Sports. Get your Von Zipper hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Von Zipper Beanies on Sale at Zephyr Today", + "head_title" : "Von Zipper Beanie | Von Zipper Hat | Von Zipper Beanies" + }, + ".markerupgrades.kingmanspyder" : { + "add3_link" : "/category/markerupgrades.feednecks.spyder_no_holes/", + "btn2_link" : "/category/markerupgrades.feednecks.spyder_holes/", + "banner3" : "zephyr_buttons/spyder_holes_feed_btn001", + "buttonname_03" : "", + "btn1_link" : "/category/barrels.spyder/", + "banner4" : "zephyr_buttons/spyder_no_holes_feed_btn001", + "page_title" : "Buy Spyder Upgrades Online On Sale Now", + "btn3_link" : "/category/markerupgrades.feednecks.spyder_no_holes/", + "btn4_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.spyder_grip_panel/", + "banner5" : "zephyr_buttons/grips_btn001", + "buttonname_04" : "", + "add1_link" : "/category/barrels.spyder/", + "btn2" : "", + "banner2" : "zephyr_buttons/barrel_btn001", + "add4_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.spyder_grip_panel/", + "meta_description" : "Spyder Upgrades - Buy your Spyder Victor MR1 MR4 Upgrade Online at Zephyr Paintball for Less today. Free Shipping on Spyder Parts Trust Zephyr for all your Paintball Needs", + "btn1" : "", + "buttonname_01" : "", + "btn3" : "", + "add2_link" : "/category/markerupgrades.feednecks.spyder_holes/", + "buttonname_02" : "", + "head_title" : "Spyder Upgrades | Spyder Victor MR1 MR4 Upgrade | Spyder Parts", + "btn4" : "" + }, + ".2clearance.skateboards.skateboard_decks" : {}, + ".casual_clothing.mens_clothing.socks.emerica_socks" : { + "meta_keywords" : "Emerica socks,Emerica mens socks,Emerica men socks", + "meta_description" : "Emerica Socks - Zephyr stocks a complete line of Emerica Mens Socks. Low prices, Free shipping, great customer service. Trust Zephyr for all your Emerica needs. ", + "page_title" : "Emerica Socks on Sale at Zephyr", + "head_title" : "Emerica Socks | Emerica Mens Socks" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops" : {}, + ".shop_by_brand.new_designz" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_micro_fly_sunglasses" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys micro,Black Fly Micro", + "meta_description" : "Black Flys Micro Fly Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Fly Micro fly Sunglasses.", + "head_title" : "Black Flys Micro Fly Sunglasses | Black Flys Sunglasses" + }, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_match_sunglasses" : { + "meta_description" : "Hoven Match Sunglasses - Zephyr Sports carries a complete line of Hoven Match Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Match Online Today.", + "page_title" : "Hoven Match Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Match Sunglasses | Hoven Match Sun Glasses | Sunglasses Hoven Match" + }, + ".dye_i4_paintball_goggle_mask.dye_i4_replacement_lenses" : {}, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_blacken_sunglasses" : { + "meta_description" : "Anarchy Blacken Sunglasses - Zephyr Sports carries a complete line of Anarchy Blacken Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Blacken Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Blacken Sunglasses | Anarchy Blacken Sun Glasses" + }, + ".markerupgrades.kingmanspyder.spyder_grips" : { + "meta_description" : "Spyder Trigger Upgrade - Buy your Spyder Triggers Online at Zephyr Paintball for Less today. Free Shipping on Upgrade Spyder Trigger Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Trigger Upgrade Online On Sale Now", + "head_title" : "Spyder Trigger Upgrade | Spyder Triggers | Upgrade Spyder Trigger" + }, + ".casual_clothing.mens_clothing.boots.511_tactical_boots" : {}, + ".casual_clothing.mens_clothing.accessories.audio___headphones.sony_piiq_headphones" : { + "meta_keywords" : "Sony PIIQ Headphones,Sony PIIQ Head Phones, Sony PIIQ Audio", + "meta_description" : "Sony PIIQ Headphones - Zephyr stock a complete line of Sony PIIQ Head Phones. For the ultimate Audio experience buy your Sony PIIQ at Zephyr Today", + "page_title" : "Sony PIIQ Headphones with Free Shipping at Zephyr", + "head_title" : "Sony PIIQ Headphones | Sony PIIQ Head Phones" + }, + ".casual_clothing.mens_clothing.shirts.alien_workshop_shirts_and_flannels" : { + "meta_description" : "Alien Workshop Flannel Shirts - Buy your Alien Workshop Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Alien Workshop Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Alien Workshop Shirts & Flannels Ship Free", + "head_title" : "Alien Workshop Flannel Shirts | Alien Workshop Polo Shirts | Alien Workshop Shirts" + }, + ".markers.azodin.azodin_kaos_pump_paintball_guns" : {}, + ".sponsorship.team_sponsorship_packages.invert_team_packages" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.33" : {}, + ".scenarioupgrades.tactical_vests.bt_tactical_vests___accessories" : { + "head_title" : "BT Tactical Vests | BT Paintball Vests | Empire BT Battle Tested" + }, + ".casual_clothing.mens_clothing.tshirts.metal_mulisha_t_shirts" : { + "meta_keywords" : "Metal Mulisha T Shirts,Metal Mulisha shirts,free shipping,Metal Mulisha TShirt", + "meta_description" : "Metal Mulisha T Shirts - Zephyr carries a complete line of Metal Mulisha Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Metal Mulisha T Shirts at Zephyr", + "head_title" : "Metal Mulisha T Shirts | Metal Mulisha Shirts | Metal Mulisha TShirt" + }, + ".2clearance.skateboards.skateboard_misc" : {}, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_signature_series_baseball_gloves" : { + "head_title" : "Rawlings Signature Series Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_hamoa_beach_sunglasses" : { + "meta_description" : "Maui Jim Hamoa Beach Sunglasses - Zephyr Sports carries a complete line of Maui Jim Hamoa Beach Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Hamoa Beach Online Today.", + "page_title" : "Maui Jim Hamoa Beach Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Hamoa Beach Sunglasses | Maui Jim Hamoa Beach Sun Glasses | Sunglasses Maui Jim Hamoa Beach" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_chest_protectors" : {}, + ".markerupgrades.proto_matrix_upgrades.proto_matrix_triggers" : {}, + ".apparel.jerseys.tanked_paintball_jerseys" : { + "meta_keywords" : "tanked paintball jerseys, tanked paintball gear, tanked paintball", + "banner1" : "", + "meta_description" : "Tanked Paintball Jerseys -Tanked Paintball gear comes straight from germany. Designer Style, pro performance", + "page_title" : "", + "head_title" : "Tanked Paintball Jerseys | Tanked Paintball Gear" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.alpinestars_youth_sweatshirts" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_hailwood_sunglasses" : { + "meta_keywords" : "spy hailwood sunglasses,spy hailwood,spy polarized sunglasses,spy optic hailwood,spy hailwood glasses", + "meta_description" : "Spy Hailwood Sunglasses - Zephyr carries a complete line of Spy Optic Hailwood Sunglassess including Spy Optics polarized sunglasses. With Free shipping, a 30 day satisfaction guarantee and 1 year breakage protection, Zephyr Sports is your Spy Optics headquarter!", + "page_title" : "Buy Spy Hailwood Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Hailwood Sunglasses | Spy Optics Hailwood Sunglasses | Hailwood Spy Sunglasses" + }, + ".airsoft.optical_and_flashlight_upgrades.airsoft_scopes.1_variable_power_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Variable Power scopes | Variable Power | Scopes with variable power" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.tippmann_a5_paintball_guns" : {}, + ".casual_clothing.mens_clothing.beanies.analog_beanies" : { + "meta_description" : "Analog Beanies - Buy your Beanies Analog At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on ANALOG BEANIES @ Zephyr Sports", + "head_title" : "Analog Beanies | Beanies Analog" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.oakley_tank_tops" : {}, + ".scenarioupgrades.scenario_paintball_grips" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses.oakley_forsake_womens_sunglasses" : { + "meta_keywords" : "Oakley Forsake Womens Sunglasses,Forsake Womens oakley sunglasses,oakley Forsake Womens, Forsake Womens polarized sunglasses", + "meta_description" : "Oakley Forsake Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Forsake Womens and Polarized Oakley Forsake Womens Sunglasses on Sale! ", + "page_title" : "Oakley Forsake Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Forsake Womens Sunglasses | Forsake Womens Oakley Sunglassses" + }, + ".1newitems.2008_products.2008_empire_paintball_gear" : { + "prodlist_custom" : "&SORTBY=NAME&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_backdrop_sunglasses" : { + "meta_description" : "Smith Optics Backdrop Sunglasses - Zephyr Sports carries a complete line of Backdrop Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Backdrop Sun Glasses Online Today.", + "page_title" : "Smith Optics Backdrop Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Backdrop Sunglasses | Backdrop Smith Sunglasses Free Shipping | Buy Smith Backdrop Sun Glasses" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.35" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_surf_backpacks" : { + "meta_description" : "Oakley Surf Backpack - Buy your Oakley Surf Bags At Zephyr Sports for Less Today! We carry a complete line of Oakley Surf Pack at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Surf Backpack On Sale & Free Shipping", + "head_title" : "Oakley Surf Backpack | Oakley Surf Bags | Oakley Surf Pack" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_guns.invert_mini_paintball_guns" : {}, + ".casual_clothing.mens_clothing.sweatshirts.north_face_sweatshirts" : { + "meta_description" : "North Face Sweatshirts - Buy your North Face Hoodies At Zephyr Sports for Less Today! We carry a complete line of North Face Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "North Face Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "North Face Sweatshirts | North Face Hoodies | North Face Hoody" + }, + ".casual_clothing.youth_clothing.youth_sweatshirts.world_industries_sweatshirts" : {}, + ".markerupgrades.planet_eclipse_etek_upgrades.eclipse_etek_maintenance" : {}, + ".apparel.shoes.world_industries_shoes" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_heavy_hitter_sunglasses" : { + "meta_description" : "Arnette Heavy Hitter Sunglasses - Zephyr Sports carries a complete line of Heavy Hitter Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Heavy Hitter Sun Glasses Online Today.", + "page_title" : "Arnette Heavy Hitter Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Heavy Hitter Sunglasses | Heavy Hitter Arnette Sunglasses | Arnette Heavy Hitter Sun Glasses" + }, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.skullcandy_headphones" : { + "meta_keywords" : "Skullcandy Headphones,Skullcandy Head Phones, Skullcandy Audio", + "meta_description" : "Skullcandy Headphones - Zephyr stock a complete line of Skullcandy Head Phones. For the ultimate Audio experience buy your Skullcandy at Zephyr Today", + "page_title" : "Skullcandy Headphones with Free Shipping at Zephyr", + "head_title" : "Skullcandy Headphones | Skullcandy Head Phones" + }, + ".airsoft.tactical_airsoft_gear.airsoft_holsters___slings.spetzgear_holsters" : {}, + ".casual_clothing.mens_clothing.shorts.element_shorts" : { + "meta_keywords" : "element clothing,element shorts,element clothes,element apparel,element shop,element online,element skating,element board shorts,element boardshort\r ", + "meta_description" : "Element Shorts - Zephyr carries a complete line of Element Clothing at the lowest prices on the web. Free Shipping over $75 on Element Clothes and Element Board Shorts", + "page_title" : "Element Shorts with Free Shipping at Zephyr", + "head_title" : "Element Shorts | Element Clothing | Element Clothes" + }, + ".safetygear.goggles.empire_vents_goggles" : {}, + ".casual_clothing.womens_clothing.ladies_sweatshirts.oakley_sweatshirts" : {}, + ".paintball.player_apparel.paintball_pants.empire_paintball_pants" : {}, + ".shop_by_brand.bob_long" : { + "top_description2" : "=Bob Long, Paintball art=\n\nBob Long paintball is known in the world of paintball as being the highest precision Gun available. You get your money's worth for these guns. Trust us, if you have the money it is well worth the investment.These Guns are what the Pro's use. Bob Long is passionate about making the world's most advanced paintball markers and accessories. Envisioned, designed, made, and assembled entirely in America, Bob Long markers are one of the last few American-made high-end paintball markers. Check out the Bob Long collection including his most famous and well known work, the Bob Long Intimidator. Bob Long doesn't just create another paintball Gun, he creates Paintball art.\n\n\n", + "head_title" : "Bob Long | Bob long paintball | Bob Long Intimidator", + "zoovy:banner01" : "banners/paintball/headers/bob_long_header.jpg", + "description" : "=Bob Long - Paintball Art=\nBob Long makes the Highest quality, All-American guns around. These guns are efficient, high end and tournament ready. They will BLOW YOUR MIND. \n\n\n==G6R Intimidator==\nAfter a near 3 year hiatus, Bob Long has released the all-new G6R Intimidator. The newest addition to the famed Intimidator line, this Generation-6 Intimidator is sure to live up to it's legacy. With a precision fit, 2 piece chassis, this Intimidator boasts a large, low-pressure poppet chamber that allows for unreal efficiency and accuracy. Get yours today!\n\n\n=Features:=\n* Tadao-designed Odoshi board--all tournament modes supported\n* MEGA-efficient--over 2800 shots on 68\\45!\n* Quick-disconnect, clamping-cam feedneck\n* Colored Accents available in many colors\n* High Volume, Low Pressure Poppet Chamber\n* New overmolded dual-durometer grips with lightpipe for easy LED viewing\n* Dual Bearing Suspension trigger included--zero friction, high speed design\n* Ultra Low-Pressure Operation\n* 4-eye compatible, 2 eye setup included\n\n\n==V2 Victory Marq Victory V2==\nThe Legend Continues--after the release of the revolutionary \"Marq\" line of paintball markers in 2007, Bob long has raised the bar with the newest addition to the \"Victory\" line of guns. The V2 features a completely new 4-axis CNC milled exterior design and all the newest upgrades. Get yours today! \n\n\n=Features:=\n* Supercharged Motor--over 14 pods per 68\\4500 fill!\n* Revolutionary Inline Poppet Design--ultra smooth and fast\n* S7 Steel internal construction--industrial-grade reliability\n* Quick-detach rear cap for easy maintenance\n* 3D Molded supple rubber grip panels\n\n\n==Ripper Victory==\nThe Legend Continues--after the release of the revolutionary \"Marq\" line of paintball markers in 2007, Bob long has raised the bar with the newest addition to the \"Victory\" line of guns. After an extensive multi-hour process on a CNC machine, each Ripper Victory is custom anodized to the buyer's specifications. After a rigorous quality-control and testing at the factory, these custom markers are finally available for purchase. \n\n\n=Features:=\n* Supercharged Motor--over 14 pods per 68\\4500 fill!\n* Revolutionary Inline Poppet Design--ultra smooth and fast\n* S7 Steel internal construction--industrial-grade reliability\n* Quick-detach rear cap for easy maintenance\n* 3D Molded supple rubber grip panels\n* Dual-Bore Barrel Kit included\n* Custom LE Marker Bag Included" + }, + ".goggles.1goggle_accesories.save_phace_goggle_accesories" : { + "meta_description" : "Save Phace Lens - Buy your Save Phace Thermal Lens Online at Zephyr Paintball for Less today. Free Shipping on Save Phace Replacement Lens Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Save Phace Lens Online On Sale Now", + "head_title" : "Save Phace Lens | Save Phace Thermal Lens | Save Phace Replacement Lens" + }, + ".1historical_products.airguns" : {}, + ".markerupgrades.indiancreek" : { + "banner2" : "", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "description" : "=Notice=\nThe feedneck thread for Indian Creek Pro-Masters is Bushmaster. The Bushmaster thread is a 99% match to the Impulse/Ion/Shocker feedneck thread. While we do acknowledge that an Impulse/Ion/Shocker threaded feedneck will thread into the Bushmaster threaded feed hole, we do not guarantee an exact fit.", + "ad3" : "zephyr_buttons/feedneck_btn001", + "add2_link" : "/category/markerupgrades.feednecks.impulse_ion_sft_feednecks/", + "ad2" : "zephyr_buttons/barrel_btn001", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "ad4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.autococker/" + }, + ".airsoft.airsoft_guns.1_shop_by_gun_type.usp_airsoft_pistols" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "USP Airsoft Pistols | Airsoft USP Pistols | USP 45 Airsoft", + "description" : "" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_explorer_backpacks" : { + "meta_description" : "Dakine Explorer Backpacks - Buy your Explorer Dakine Bags At Zephyr Sports for Less Today! We carry a complete line of Dakine Explorer Packs at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Explorer Backpacks & Bags Ship Free ", + "head_title" : "Dakine Explorer Backpacks | Explorer Dakine Bags |Dakine Explorer Packs" + }, + ".safetygear.goggles.proto" : {}, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.marq_grip_panel" : {}, + ".scenarioupgrades.scenario_apparel.camo_paintball_pants" : {}, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_etek_2___star_frame_combo" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_high_roller_sunglasses" : { + "meta_keywords" : "Arnette Sunglasses, arnette polarized, arnette sunglass, Arnette Eyewear, Arnette Lens", + "meta_description" : "Arnette High Roller Sunglasses - Polarized Sunglasses by Arnette! High Roller Shades are the latest in Arnette Eyewear! The Polarized Arnette Lens offers UV protection and style! Check em out @ Zephyr Sports", + "head_title" : "Arnette High Roller Sunglasses | Arnette 4065 High Roller Sunglasses | Arnette High Roller" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_pilfer_sunglasses" : {}, + ".airsystems.nitrogentanks.kingmanjava" : {}, + ".casual_clothing.mens_clothing.shorts.matix_shorts" : { + "meta_description" : "Matix Shorts - Zephyr stocks a complete line of Matix Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Matix needs. ", + "page_title" : "Matix Shorts with Free Shipping at Zephyr", + "head_title" : "Matix Shorts | Matix Board Shorts" + }, + ".harnessesbags.tubes.valken_paintball_pods" : {}, + ".casual_clothing.youth_clothing.youth_sweatshirts.1_search_by_size.1_small" : {}, + ".airsoft.slingshots.1slingshots.marksman_slingshots" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsystems.regulators.shocktech" : {}, + ".loaders.hopper_accesories.dxs_pulse_hopper_accesories" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_variable_power_scopes.barska_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.watches.nixon_watches" : { + "meta_keywords" : "nixon watches,nixon watch,time teller,player,51-30,watches Nixon,Nixon Player,lodown,banks,rotolog,scout", + "meta_description" : "Nixon Watches - Zephyr Carries a complete of watches from Nixon. Get your Nixon watch today with free shipping at Zephyr Sports. From the Player to the Time Teller we have you covered", + "page_title" : "Nixon Watches Free Shipping at Zephyr Sports", + "head_title" : "Nixon Watches | Nixon Watch | Watches Nixon" + }, + ".loaders.hopper_accesories.dye_loader_accesories" : { + "htmlvids" : "\n\n\n\n
                                                                          \n\n
                                                                          ", + "meta_description" : "Dye Rotor Loader Accessories - Buy your Dye Speed Feeds Online at Zephyr Paintball for Less today. Free Shipping on Dye Rotor Kits Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Dye Rotor Loader Accessories Online On Sale Now", + "head_title" : "Dye Rotor Loader Accessories | Dye Speed Feeds | Dye Rotor Kits", + "sortby_var" : "Rotor Upgrade Type", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&" + }, + ".goggles.extreme_rage_goggles" : { + "meta_description" : "Extreme Rage Paintball Goggles - Buy your Extreme Rage Paintball Masks Online at Zephyr Paintball for Less today. Free Shipping on Extreme Rage Paintball Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Extreme Rage Paintball Goggles Online On Sale Now", + "head_title" : "Extreme Rage Paintball Goggles | Extreme Rage Paintball Masks | Extreme Rage Paintball" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_asian_fit_sunglasses.oakley_asian_fit_scalpel_sunglasses" : { + "meta_description" : "Oakley Asian Fit Scalpel Sunglasses - Zephyr Sports carries a complete line of Scalpel Asian Fit Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Scalpel Asian Fit Sun Glasses Online Today.", + "page_title" : "Oakley Asian Fit Scalpel Sunglasses On Sale Free Shipping", + "head_title" : "Oakley Asian Fit Scalpel Sunglasses | Scalpel Asian Fit Oakley Sunglasses | Oakley Scalpel Asian Fit Sun Glasses" + }, + ".markerupgrades.smartparts.vibe_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "Grips", + "add2_link" : "/category/markerupgrades.feednecks.nxt_feednecks/", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".2clearance.like_new_refurbished_guns" : { + "head_title" : "Refurbished Paintball Guns | Refurb Paintball Guns | Used Paintball Markers" + }, + ".2clearance.paintball_clearance_gear.clearance_harnesses" : { + "head_title" : "Sale Paintball Harnesses | Clearance Paintball Harnesses | Paintball Pod Pack Sale" + }, + ".paintballs.paintball_grenades" : { + "meta_description" : "Paintball Grenades - Buy your Paintball Mines Online at Zephyr Paintball for Less today. Free Shipping on Paintball Grenade Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Paintball Grenades Online On Sale Now", + "head_title" : "Paintball Grenades | Paintball Mines | Paintball Grenade" + }, + ".shop_by_brand.angel_paintball_sports" : {}, + ".safetygear.sly" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_rework_backpack" : {}, + ".airsoft.airsoft_upgrades.external_airsoft_upgrades.aeg_stocks" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Stocks | Airsoft Ak Stocks | Airsoft M4 M16 Stocks" + }, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_hoy_sunglasses" : { + "meta_description" : "Electric Hoy Sunglasses - Zephyr Sports carries a complete line of Electric Hoy Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Hoy Online Today.", + "page_title" : "Electric Hoy Sunglasses On Sale Free Shipping", + "head_title" : "Electric Hoy Sunglasses | Electric Hoy Sun Glasses | Sunglasses Electric Hoy" + }, + ".misc_items.sticker___sticker_packs" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.alpinestars_pants___jeans" : { + "meta_description" : "Alpinestars Pants - Buy your Alpinestars Mens Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Alpinestars Pants & Jeans with Free Shipping", + "head_title" : "Alpinestars Pants | Alpine Stars Mens Jackets" + }, + ".scenarioupgrades.tactical_vests.scenario_paintball_pod_packs" : {}, + ".casual_clothing.z_shoes_and_footwear.vans_shoes" : {}, + ".2clearance.free_sa-17" : { + "top_description2" : "== For a limited time, purchase any of the listed Empire or JT Markers or a package containing them and receive a free BT SA-17 pistol. (Cannot buy a SA-17 and get an SA-17 Free) Cannot be combined with any other discounts or coupons ==\n= You must add your Free pistol to the cart to receive it. =", + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=banners%2fpaintball%2fslideshow%2fempire_sa17_free_slideshow%2ejpg&LINK=" + }, + ".casual_clothing.mens_clothing.tshirts.creature_t_shirts" : { + "meta_keywords" : "Creature T Shirts,Creature shirts,free shipping,Creature TShirt", + "meta_description" : "Creature T Shirts - Zephyr carries a complete line of Creature Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Creature T Shirts at Zephyr", + "head_title" : "Creature T Shirts | Creature Shirts | Creature TShirt" + }, + ".airsoft.airsoft_spare_magazines.aeg_magazines.search_by_gun_type.m249_saw_aeg_airsoft_magazines" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_derelict_sunglasses" : { + "meta_description" : "Arnette Derelict Sunglasses - Zephyr Sports carries a complete line of Derelict Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette Derelict Sun Glasses Online Today.", + "page_title" : "Arnette Derelict Sunglasses On Sale Free Shipping", + "head_title" : "Arnette Derelict Sunglasses | Derelict Arnette Sunglasses | Arnette Derelict Sun Glasses" + }, + ".paintball.paintball_guns.planet_eclipse_ego_paintball_guns" : {}, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_raw_sunglasses" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.etnies_pants_and_jeans" : { + "meta_description" : "Etnies Pants - Buy your Etnies Jeans At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Etnies Pants & Jeans Ship Free", + "head_title" : "Etnies Pants | Etnies Jeans" + }, + ".casual_clothing.mens_clothing.shorts.oakley_shorts" : { + "meta_keywords" : "Oakley Shorts,Oakley Board Shorts,Oakley Boardshorts,oakley boardshort,oakley mens shorts,oakley mountain bike shorts,oakley ballistic shorts,oakley mtb shorts,oakley swim shorts,oakley cargo shorts,oakley tilt boardshorts,oakley dredge board shorts,oakley tilt boardshort,oakley mtb short,oakley trail mtb shorts,oakley bike short\r ", + "meta_description" : "Oakley Shorts - Huge selection of Oakley Board Shorts available online at Zephyr Sports. Always the best price, Always free shipping over $75. Buy your Oakley Boardshorts online Now!", + "page_title" : "Oakley Shorts with Free Shipping at Zephyr", + "head_title" : "Oakley Shorts | Oakley Board Shorts | Oakley Boardshorts" + }, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintballs.dxs_gold_paintballs" : {}, + ".casual_clothing.mens_clothing.jackets.nixon_jackets" : { + "meta_description" : "Nixon Jackets - Buy your Nixon Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Nixon Jackets with Free Shipping", + "head_title" : "Nixon Jackets | Nixon Mens Jackets" + }, + ".airsoft.airsoft_bbs_ammo.tsd_airsoft_bbs" : { + "meta_description" : "TSD Airsoft BBs - Zephyr stocks a complete selection of high endTeam SD Airsoft BB. Spend the extra few bucks for quality Team SD Airsoft Ammo and save yourself a bunch of headaches down the road. Airsoft fields and parents prefer TSD Bio BB. Zephyr Sports offrers free shipping on Airsoft Gear on orders over $75", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : ".20 TSD Airsoft Bio BBs | .25 Gram TSD Airsoft Pellets | .20 G Team SD Biodegradeable Ammo" + }, + ".maddog.maddog_gear_bags" : {}, + ".airsoft.airsoft_bbs_ammo.bioval_bb_s" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_jerseys.eclipse_clearance_paintball_jerseys" : {}, + ".shop_by_brand.electric" : { + "zoovy:banner01" : "" + }, + ".markerupgrades.intimidator.intimidator_feed_necks" : {}, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markers.tippmann" : { + "subcat1_header" : "Tippmann Paintball Guns", + "meta_keywords" : "Tippmann Paintball Guns, Tippmann Paintball,Tippman Kits, Tippmann Markers, Tippmann Gear, Tippmann 98, Discount Tippmann Paintball, Cheap Tippmann, Tippmann Package Kits, Custom 98 Pro, Tippmann A-5, tippmann x7, tippman tpx pistol, tippmann 98 platinum, tippmann a-5 cyclone, tippmann x7 paintball gun", + "meta_description" : "Tippmann Paintball Guns - Tippmann makes some of the best Paintball guns in the industry, from scenario to starter guns, Tippmann has what you need. Tippman Paintball Gear is of the highest quality and Made in America. From the A-5, X7, TPX Pistol, Crossover to The Custom 98. You can find what you need at tippman.", + "top_description2" : "Tippmann Paintball is the leader in scenario paintball. For over 25 years Tippmann has supplied the paintball industry with durable markers to keep you on the field, not working on your gun. The Tippmann 98 is the standard in field rental guns due to it's relability. The Tippmann A5 and X7 Phenom add better performance with that same tippmann reliability. Need a sidearm for your next big game? The tippmann tpx paintball pistol has you covered. In 2012, Tippmann entered the speedball tournament market with the release of the [[tippmann crossover]:url=%SESSION%/category/markers.tippmann.tippmann_crossover_paintball_guns/]. ", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.tippmann_packages/", + "description" : "Tippmann was one of the original innovators of Paintball Guns. Most adult players grew up playing with a Tippmann Paintball gun. Originally the Tippmann Pro Carbine revolutionized paintball and brought it into the mainstream public view. Tippmann makes some of the highest quality guns in the industry always made in the USA. From the [[Tippmann A5]:url=/category/markers.tippmann.a5/] to the Platinum edition of the [[Custom 98]:url=/category/markers.tippmann.model98/] to the [[X7 Phenom]:url=/category/markers.tippmann.tippmann_x7_paintball_guns/], you can find what you need with a Tippmann. Whether it's a starter package or a scenario gun it can all be done. Tippmann paintball guns are the most upgradeable guns made. Whether it's the E-grip, Response trigger, or Cyclone feed.\n\n\nTippmann paintball markers are known to be great entry level or scenario paintball guns due to their ease of operation, low cost and bulletproof reliability. Tippmann Model 98 Paintball guns are the most popular marker used at commercial paintball fields. The ease of upgrading a Tippmann gun is another reason for the popularity of Tippmann Guns. You can start with an affordable base version of the Tippmann Custom 98 for around $139. As you learn the game of Paintball and require more firepower, your Tippman marker will upgrade with you by installing either the Response trigger or Electronic E-grip upgrade.\n\n\n\n==What’s the difference between the 98 & A5?==\n\n\n\nOne of the major differences is the Cyclone Feed on the Tippmann A5. The Cyclone feeds a ball into the chamber every time you fire and does not require batteries. It uses excess air that would have otherwise been wasted anyways. Although the 98 Custom only comes with a standard gravity fed hopper the [[98 Cyclone Feed]:url=http://www.zephyrpaintball.com/product/PB-TIP-98CYCLONE] is available as an upgrade. Also, with the A5 there are more military cosmetic upgrades for a realistic feel – AK47, M16, M4 and many more! Both the 98 Custom & A-5 are very much dependable, accurate and the best for the price.\n\n\n\n==The Tippmann X7 Phenom==\n\n\n\nThe [[Tippmann X7]:url=/category/markers.tippmann.tippmann_x7_paintball_guns/] paintball gun is one of the most durable paintball guns on the market. Throw it, step on it, dunk it in water, cover it in dirt, tie it to the back of your truck and drag it for 4 miles. Actually, don’t do the last one. If you did though, I’d bet it would stay in tact. The durability is not the only thing great about this gun. The X7 is completely customizable. Give it that realistic look and feel with modifications such as the AK47, M16, and others. If you are looking for the ultimate tippmann paintball gun, than the X7 phenom is your gun for its consistency in shots, air efficiency and overall performance. Also, just like the A5 & 98 it’s available with the E-grip or Response Trigger. \n\n\n\n==Barrel Threads?==\n\n\n\nTippmann has two different barrel threads with its markers. The Tippmann A5 and X7 phenom paintball guns and BT combat markers use Tippmann A5 Barrel Threads. The Tippmann Custom 98, custom 98 Pro, US army guns as well as the tippmann gryphon and all Tippmann 98 Platinum markers use Tippmann 98 Threads. A5 and Model 98 threads are NOT compatible with each other. Make sure you select the appropriate Tippman barrel threading according to which Tipmann gun you own. If you ever have any questions in regards to this don’t hesitate to give us a quick ring 877-814-4297\n\n\n\n==What Barrels are Available?==\n\n\n\nTippmann paintball guns are the only markers that are compatible with the patented [[Flatline Paintball Barrel System]:url=/category/barrels.barrels_by_manufacturer.tippmann_paintball_barrels/]. The Flatline Barrel is one of the most popular barrels that is mainly designed/used for scenario/woodsball games for its major increase in distance. The reason for its popularity is because of it's curved design that puts a back spin on the ball. Giving a back spin gives you a much more accurate shot and adds distance that you will indeed notice. \n\n\n\nLeaning more towards speedball that does not require much distance but rather more accuracy. A solid barrel to start with that is inexpensive and will give you more accuracy and distance is the [[J&J Ceramic Tippmann Barrel]:url=http://www.zephyrpaintball.com/category/barrels.barrels_by_manufacturer.j_j_paintball_barrels.j_j_ceramic_one_piece_barrels/] available in A-5/X7 & 98 Threads. Given its ceramic coating; if you happen to chop a ball in the barrel, the paint will not stick to the inside of the barrel making it a self-cleaning barrel by being able to shoot a couple shots and the paint will fly right out of the barrel. Squeegee may still be necessary but will be much less of a mess. If you are looking for a light, more accurate barrel we also supply the very popular carbon fiber Stiffi & DeadlyWind Barrels. Both brands are composed of a durable carbon fiber wrap that makes your complete setup extremely light. Weight is not the only great feature about these barrels, their consistency is well looked upon and will not disappoint. These are just a few barrels available for the Tippmann's. Check out this category page for more options with the [[Tippmann A5 Barrels]:url=http://www.zephyrpaintball.com/category/barrels.tippmanna5/] & [[Tippmann 98 barrel]:url=http://www.zephyrpaintball.com/category/barrels.tippmann98/] Threads\n\n\n\n==What’s all the hype about a Remote Line?==\n\n\n\nA [[Remote Line]:url=/category/airsystems.remote_lines/] is a great upgrade to consider. Highly recommended for CO2 users – because of the cold liquid gas from the CO2 that runs directly into your Tippmann this may cause damage to internal parts that can be costly. CO2 will work fine on the Tippmanns since they are extremely durable and all components are made for it, but the consistency can be helped with a remote line. By having the remote line the CO2 does not make direct contact; the long line will distribute the CO2 appropriately into the gun which will be a lot cleaner on your gun and your shots will be more consistent. Once you have a remote line you can then put your tank in a Harness that will relieve your gun of that heavy weight. Just make sure whatever size tank you choose whether it be CO2 or Compressed air fits in the desired Harness. One that usually fits most tanks that is great to start with is the [[Maddog 4+1]:url=/product/PB-MD-41BLK/Maddog-41-Deluxe-Padded-Paintball-Harness---Black.html] Check our product descriptions for sizes and if you are not sure just remember to email or phone us!", + "banner1" : "banners/categories/guns/tippmann_banner.jpg", + "page_title" : "Buy Tippmann Custom 98 A5 X7 Paintball Guns On Sale Now", + "head_title" : "Tippmann 98 Paintball Guns | Cheap Tippman A5 Paintball Guns | Custom Tippmann X7" + }, + ".airsoft.airsoft_guns.airsoft_spring_guns.crosman_spring_airsoft_guns" : { + "meta_description" : "Crosman Airsoft Guns - Buy your Crosman Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Crosman Spring Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Crosman Airsoft Guns On Sale & Free Shipping", + "head_title" : "Crosman Airsoft Guns | Crosman Airsoft Rifles | Crosman Spring Airsoft Gun" + }, + ".airsoft.tactical_airsoft_gear.paracord_bracelets" : {}, + ".casual_clothing.mens_clothing.shoes.element_skate_shoes" : { + "meta_keywords" : "element clothing,element shoes,skate element,element skate shoes,element shoe,element skate clothes\n", + "meta_description" : "Element Shoes - Full line of Element footwear available at Zephyr Sports. Free Shipping on Element Skate Shoes. Trust Zephyr Sports for all your Element Shoe Needs", + "page_title" : "Element Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Element Shoes | Element Skate Shoes | Element Shoe" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_eyepatch_2_sunglasses" : { + "meta_keywords" : "Oakley Eyepatch 2 Sunglasses,Eyepatch 2 oakley sunglasses,oakley Eyepatch 2, Eyepatch 2 polarized sunglasses", + "meta_description" : "Oakley Eyepatch 2 Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Eyepatch 2 and Polarized Oakley Eyepatch 2 Sunglasses on Sale! ", + "page_title" : "Oakley Eyepatch 2 Sunglasses with Free Shipping", + "head_title" : "Oakley Eyepatch 2 Sunglasses | Eyepatch 2 Oakley Sunglassses" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_passport_watches" : {}, + ".airsystems.tankcovers.bottle_covers_by_tank_size.tank_covers_for_aluminum_tanks" : { + "meta_description" : "Co2 Paintball Tank Covers - Buy your Cover for 20Oz Co2 Tank Online at Zephyr Paintball for Less today. Free Shipping on Camo Tank Covers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Co2 Paintball Tank Covers Online On Sale Now", + "head_title" : "Co2 Paintball Tank Covers | Cover for 20Oz Co2 Tank |Camo Tank Covers" + }, + ".markerupgrades.grips_and_grip_panels.grips_by_frame.ultralite_grip_panel" : {}, + ".airsystems.dropforwards.empire" : {}, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests.condor_tactical_vests" : { + "meta_description" : "Condor Tactical Vests - Buy your Condor Tactical Military Vests At Zephyr Sports for Less Today! We carry a complete line of Condor Tactical Molle Vests at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "!Condor Tactical Vests On Sale at Zephyr ", + "head_title" : "Condor Tactical Vests | Condor Tactical Military Vests | Condor Tactical Molle Vests" + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones.spitfire_headphones" : { + "meta_keywords" : "Spitfire Headphones,Spitfire Head Phones, Spitfire Audio", + "meta_description" : "Spitfire Headphones - Zephyr stock a complete line of Spitfire Head Phones. For the ultimate Audio experience buy your Spitfire at Zephyr Today", + "page_title" : "Spitfire Headphones with Free Shipping at Zephyr", + "head_title" : "Spitfire Headphones | Spitfire Head Phones" + }, + ".2clearance.paintball_clearance_gear.clearance_upgrades.clearance_feednecks" : {}, + ".casual_clothing.mens_clothing.shirts.matix_shirts" : { + "meta_description" : "Matix Flannel Shirts - Buy your Matix Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Matix Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Matix Flannel Shirts On Sale & Free Shipping", + "head_title" : "Matix Flannel Shirts | Matix Polo Shirts | Matix Shirts" + }, + ".1newitems.2008_products.2008_dye_paintball_gear" : { + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.suunto_watches" : { + "meta_keywords" : "Slap watches,Slap watch,time teller,watches Slap", + "meta_description" : "Slap Watches - Zephyr Carries a complete of watches from Slap. Get your Slap watch today with free shipping at Zephyr Sports. From the Player to the Time Teller we have you covered", + "page_title" : "Slap Watches Free Shipping at Zephyr Sports", + "head_title" : "Slap Watches | SlapWatch | Watches Slap" + }, + ".casual_clothing.z-sunglasses.neff_sunglasses" : { + "meta_description" : "Neff Sunglasses Neff Eyewear - Zephyr Sports carries a complete line of Neff Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Neff Sunglasses Neff Eyewear On Sale Free Shipping", + "head_title" : "Neff Sunglasses Neff Eyewear | Neff Sun Glasses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.z_oakley_replacement_parts.oakley_replacement_lenses" : { + "meta_description" : "Replacement Oakley Lens - Zephyr Sports carries a complete line of Replacement Lenses Oakley At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Replacement Lenses Online Today.", + "page_title" : "Replacement Oakley Lens On Sale Free Shipping", + "head_title" : "Replacement Oakley Lens | Replacement Lenses Oakley | Oakley Replacement Lenses" + }, + ".casual_clothing.mens_clothing.shirts.dakine" : { + "meta_description" : "Dakine Flannel Shirts - Buy your Dakine Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Dakine Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Shirts & Flannels Ship Free", + "head_title" : "Dakine Flannel Shirts | Dakine Polo Shirts | Dakine Shirts" + }, + ".casual_clothing.z_unisex_clothing_accesories.stickers.metal_mulisha_stickers" : {}, + ".airsystems.remote_lines" : { + "meta_keywords" : "paintball remote lines, remote coil, remote line, paintball remote slide check, slide checks, paintball slide check, paintball lines, air lines, co2 remote line, compressed air remote line", + "meta_description" : "Paintball Remote Lines - Get theat heavy bottle of your paintball gun with a remote coil. Lightweight flexible tubing allows you to run Co2 or compressed air with the tank on your back. The remote line is a must for anyone who runs Co2 on your marker.", + "top_description" : "Ready to get that heavy paintball tank off your gun? It's time for a remote line. A Paintball remote coil will allow you to put your tank in a harness or vest on your back making your paintball gun much lighter. If you are playing with a co2 tank, a paintball remote line will serve as an expansion chamber virtually eliminating liquid co2 in your gun. ", + "page_title" : "Buy Paintball Remote Lines Online On Sale Now", + "head_title" : "Paintball Remote Lines | Remote Coils | Paintball Remote line", + "description" : "Paintball Remote Lines are great to have for multiple reasons. The use of CO2 means operating a cold liquid that turns into gas as it's released. This cold liquid can wear down o-ring and internal parts leading to more required maintenance. By having a remote line, the liquid CO2 does not make direct contact with the gun thus using mainly the gas to operate your gun. This gives more consistent shots and less mechanical issues. Also, by having a remote line that weight is relieved from your gun and can be held on your harness or vest. Just make sure whatever size tank you choose whether it be CO2 or Compressed air fits in the desired Harness. Another option on a remote line is a slide check. The Slide Check makes disconnecting the marker from the remote line easy and safe. When the slide is forward, the entire line, from the tank to the marker’s valve chamber is pressurized with air. When the slide is back, there is no pressure in the line between the marker and the slide check. In the back position, the marker can be removed from the remote, without depressurizing the entire line or having to turn off the tank. The line between the tank and the slide check remains at tank pressure.\n\n\n==Paintball Remote Line FAQ==" + }, + ".return_request.defective" : { + "description" : "

                                                                          Defective Merchandise

                                                                          \n

                                                                          Defective merchandise must be returned / repaired / replaced / exchanged through the manufacturer. All manufacturers provide at least a 30-day (some offer 90-day or 1 full year) parts and labor warranty on paintball products. Please review the product owner's manual before use and register your product for warranty. \n

                                                                          \n Please select the manufacturer of the defective product: \n \n

                                                                          \n
                                                                          \n

                                                                          Can't find the manufacturer

                                                                          \n

                                                                          If you do not see the manufacture of a particular item listed, then please email us at support@zephyrsports.com or call toll free to 877.814.4297. Our business hours are Mon - Fri from 9am - 6pm PST.

                                                                          " + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_polarized_sunglasses" : { + "meta_description" : "Spy Optics Polarized Sunglasses - Zephyr Sports carries a complete line of Polarized Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Polarized Sun Glasses Online Today.", + "page_title" : "Spy Optics Polarized Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Polarized Sunglasses | Polarized Spy Sunglasses Free Shipping | Buy Spy Polarized Sun Glasses" + }, + ".harnessesbags.backpacks.neff_backpacks" : { + "meta_description" : "Neff Backpacks - Buy your Neff Bags At Zephyr Sports for Less Today! We carry a complete line of Neff Luggage at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Neff Backpacks & Bags Ship Free ", + "head_title" : "Neff Backpacks | Neff Bags |Neff Luggage" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_women_s_sunglasses" : { + "meta_keywords" : "Oakley Womens Sunglasses,Womens oakley sunglasses,oakley Womens, Womens polarized sunglasses", + "meta_description" : "Oakley Womens Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Womens and Polarized Oakley Womens Sunglasses on Sale! ", + "page_title" : "Oakley Womens Sunglasses with Free Shipping", + "head_title" : "Oakley Womens Sunglasses | Womens Oakley Sunglassses" + }, + ".casual_clothing.mens_clothing.watches.vans_watches" : {}, + ".markerupgrades.indiancreek.feed_necks" : {}, + ".casual_clothing.z-sunglasses.anarchy_sunglasses_.anarchy_rally_sunglasses" : { + "meta_description" : "Anarchy Rally Sunglasses - Zephyr Sports carries a complete line of Anarchy Rally Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Online Today.", + "page_title" : "Anarchy Rally Sunglasses On Sale Free Shipping", + "head_title" : "Anarchy Rally Sunglasses | Anarchy Rally Sun Glasses" + }, + ".markerupgrades.smartparts.eos_upgrades.eos_feed_necks" : {}, + ".promotions.free_gun_case" : { + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "top_description2" : "" + }, + ".shop_by_brand.infamous" : { + "top_description2" : "== Rock what the Pros Rock!! ==\n\nTeam Infamous was formed long before a single stencil got spray painted. The team was built out of the core of the original Avalanche team. The players quit and joined the National Xball League. In the NXL the team played as Miami Effect. \n\n\nInfamous came out and won their very first National Professional Paintball League (NPPL) even beating Dynasty for the first time ever in 7 man finals. It was a major upset that changed paintball forever by reuniting all the competition. \n\n\n= Rep Infamous On & Off the Field! The Team Does** =", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/1_infamous_paintball_main_headers.jpg" + }, + ".casual_clothing.youth_clothing.youth_shorts.element_shorts" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_fast_jacket_xl" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_pants.proto_paintball_pants" : {}, + ".casual_clothing.mens_clothing.shirts.srh_shirts_and_flannels" : { + "meta_description" : "SRH Flannel Shirts - Buy your SRH Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of SRH Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "SRH Shirts & Flannels Ship Free", + "head_title" : "SRH Flannel Shirts | SRH Polo Shirts | SRH Shirts" + }, + ".casual_clothing.mens_clothing.shirts.dc_shirts" : { + "meta_description" : "DC Flannel Shirts - Buy your DC Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of DC Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DC Shirts & Flannels Ship Free", + "head_title" : "DC Flannel Shirts | DC Polo Shirts | DC Shirts" + }, + ".casual_clothing.womens_clothing.ladies_sweatshirts.neff_ladies_sweatshirts" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_collective_sunglasses" : { + "meta_description" : "Smith Optics Collective Sunglasses - Zephyr Sports carries a complete line of Collective Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Collective Sun Glasses Online Today.", + "page_title" : "Smith Optics Collective Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Collective Sunglasses | Collective Smith Sunglasses Free Shipping | Buy Smith Collective Sun Glasses" + }, + ".markerupgrades.planet_eclipse_etek_upgrades.eclipse_etek_eye_upgrades" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_ec_dc_sunglasses" : { + "meta_description" : "Electric EC/DC Sunglasses - Zephyr Sports carries a complete line of Electric EC/DC Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric EC/DC Online Today.", + "page_title" : "Electric EC/DC Sunglasses On Sale Free Shipping", + "head_title" : "Electric EC/DC Sunglasses | Electric EC/DC Sun Glasses | Sunglasses Electric EC/DC" + }, + ".airsoft.tactical_airsoft_gear.tactical_airsoft_vests.511_tactical_vests" : { + "meta_description" : "5.11 Tactical Vests - Buy your 5.11 Military Vests At Zephyr Sports for Less Today! We carry a complete line of 5.11 Molle Vests at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "!5.11 Tactical Vests On Sale at Zephyr ", + "head_title" : "5.11 Tactical Vests | 5.11 Military Vests | 5.11 Molle Vests" + }, + ".apparel.head_bands_and_wraps.exalt_paintball_head_bands_and_wraps" : {}, + ".shop_by_brand.alta_tactical" : {}, + ".markerupgrades.proto_matrix_rail_upgrades.proto_rail_grips" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb4113_jackie_ohh_iii_highstreet_sunglasses" : { + "meta_description" : "Ray Ban Jackie Ohh Sunglasses - Zephyr Sports carries a complete line of Jackie Ohh Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Jackie Ohh Sun Glasses Online Today.", + "page_title" : "Ray Ban Jackie Ohh Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Jackie Ohh Sunglasses | Jackie Ohh Ray Ban Sunglasses | RayBan Jackie Ohh Sun Glasses" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_golf_sunglasses" : { + "meta_keywords" : "Oakley Golf Sunglasses,Golf oakley sunglasses,oakley Golf, Golf polarized sunglasses", + "meta_description" : "Oakley Golf Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Golf and Polarized Oakley Golf Sunglasses on Sale! ", + "page_title" : "Oakley Golf Sunglasses with Free Shipping", + "head_title" : "Oakley Golf Sunglasses | Golf Oakley Sunglassses" + }, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_rockford_sunglasses" : { + "meta_keywords" : "Von Zipper Rockford sunglasses,VZ Rockford,Von Zipper polarized sunglasses,Von Zipper Rockford,VZ Rockford glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Rockford Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Rockford sunglasses now! For Von Zipper Rockford glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Rockford Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Rockford Sunglasses | VonZipper Rockford Sunglasses | VZ Rockford Sunglasses" + }, + ".airsoft.tactical_airsoft_gear" : { + "meta_keywords" : "Airsoft tactical gear,tactical gear,airsoft gear,molle gear,tactical vests,military,airsoft gun holsters, slings,", + "meta_description" : "Airsoft Tactical Gear - Zephyr Sports is a leading distributor of Tactical Airsoft Gear! All kinds of military styled equipment, molle tactical gear, tactical vests, and more! Got backup airsoft guns you want to use in the battle?! Zephyr Sports has airsoft holsters and airsoft slings to fit your airsoft strategy! Strap em on and get in the game! ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.mens_clothing.tshirts.cliche_t_shirts" : { + "meta_keywords" : "Cliche T Shirts,Cliche shirts,free shipping,Cliche TShirt", + "meta_description" : "Cliche T Shirts - Zephyr carries a complete line of Cliche Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Cliche T Shirts at Zephyr", + "head_title" : "Cliche T Shirts | Cliche Shirts | Cliche TShirt" + }, + ".casual_clothing.mens_clothing.shoes.fallen_shoes" : { + "meta_description" : "Fallen Shoes - Buy your Fallen Mens Shoes At Zephyr Sports for Less Today! We carry a complete line of Fallen Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Fallen Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Fallen Shoes | Fallen Mens Shoes | Fallen Skate Shoes" + }, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_dial_watches" : { + "meta_keywords" : "Nixon watches,nixon Dial watch,nixon watch,nixon Dial chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Dial Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Dial Chrono Watches", + "head_title" : "Nixon Dial Watches | Nixon Dial Chrono Watch | Nixon 5130" + }, + ".casual_clothing.mens_clothing.accessories.audio___headphones.nixon_headphones.nixon_whip_headphones" : {}, + ".casual_clothing.mens_clothing.accessories.lanyards.hk_army_lanyards" : {}, + ".shop_by_brand.hostility_mma" : {}, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_motors" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft motors | AEG motor | Motor AEG" + }, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.a_small" : {}, + ".casual_clothing.womens_clothing.ladies_socks.jox_sox_ladies_socks" : {}, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.m14_airsoft_gun_magazines" : {}, + ".casual_clothing.mens_clothing.shorts.1_search_by_size.31" : {}, + ".scenarioupgrades.tactical_vests.defcon_5_tactical_vests" : {}, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_pants.jt_clearance_paintball_pants" : {}, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_hiking_hydration_packs.camelbak_aventura_hydration_packs" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_42-20_tide_watches" : { + "meta_keywords" : "Nixon Watches,Nixon Tide Watch,Nixon Watch,Nixon 42-20 Watch,Nixon,mens watches,", + "meta_description" : "Nixon Watches - Brand new Nixon Tide Watch Available now @ Zephyr! Nixon 42-20 Tide Watches feature a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon 42-20 Tide Watch", + "head_title" : "Nixon Tide Watches | Nixon Tide Watch | Nixon 42-20" + }, + ".barrels.tippmanna5.18___tippmann_a_5_barrels" : { + "meta_description" : "Tippmann A-5 Sniper Barrels - Buy your X7 Tactical Barrels Online at Zephyr Paintball for Less today. Free Shipping on A5 Scenario Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann A-5 Sniper Barrels Online On Sale Now", + "head_title" : "Tippmann A-5 Sniper Barrels |X7 Tactical Barrels | A5 Scenario Barrels" + }, + ".search" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_defy_sunglasses" : { + "meta_keywords" : "arnette sunglasses, arnette polarized sunglasses, arnette sunglass, ", + "meta_description" : "Arnette Defy Sunglasses - Zephyr Carries several Arnette sunglass styles! Polarized lens available! Arnette Defy sunglasses now on sale!", + "head_title" : "Arnette Defy Sunglasses | Arnette Sunglasses" + }, + ".markerupgrades.bob_long_upgrades" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.marq_grip_panel/", + "meta_description" : "Bob Long Upgrades - Buy your Marq Upgrades Online at Zephyr Paintball for Less today. Free Shipping on BobLong Intimidator Parts Trust Zephyr for all your Paintball Needs", + "buttonname_01" : "", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "", + "description" : "=Notice=\nThe Marq series, Vice, and Protege all have the same style of grip panel and accept the same style of grips.\n\n\n4th Generation Intimidators and older have 45 degree style grip frames. These style of frames accept 45 degree style grips. Please be sure to confirm your marker's frame style to ensure you choose the correct grips.", + "add2_link" : "/category/markerupgrades.feednecks.intimidator_feednecks/", + "buttonname_02" : "", + "banner4" : "zephyr_buttons/grips_btn001", + "head_title" : "Bob Long Upgrades | Marq Upgrades | BobLong Intimidator Parts", + "page_title" : "Buy Bob Long Upgrades Online On Sale Now", + "add1_link" : "/category/barrels.autococker/" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs.camelbak_classic_hydration_packs" : {}, + ".airsoft_gear.2clearance.airsoft_clearance_gear" : {}, + "$auto_barrels" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_rb3429_signet_sunglasses" : { + "meta_description" : "Ray Ban Signet Sunglasses - Zephyr Sports carries a complete line of Signet Ray Ban Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your RayBan Signet Sun Glasses Online Today.", + "page_title" : "Ray Ban Signet Sunglasses On Sale Free Shipping", + "head_title" : "Ray Ban Signet Sunglasses | Signet Ray Ban Sunglasses | RayBan Signet Sun Glasses" + }, + ".airsoft.airsoft_guns.1_airsoft_guns_by_brand.g_g_armament_airsoft_guns" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_fly_no_5_sunglasses" : { + "meta_keywords" : "Black Flys Sunglasses,Black Flys Eyewear,Black Fly Sunglasses,Black Flys 5 Sunglasses,", + "meta_description" : "Black Flys 5 Sunglasses now Available @ Zephyr! Start your collection of Black Flys Eyewear! Select styles of Black Fly Sunglasses available; Black Flys No 5 sunglasses.", + "head_title" : "Black Flys Fly No 5 Sunglasses | Black Flys 5 | Black Flys no 5" + }, + ".safetygear.goggles.jtusa" : { + "head_title" : "JT USA Paintball Goggles | JT Flex Goggle | JT Spectra Paintball Mask" + }, + ".markers.bob_long_paintball_guns.bob_long_protege_paintball_guns" : {}, + ".casual_clothing.mens_clothing.shoes.dvs_shoes" : { + "meta_description" : "DVS Shoes - Buy your DVS Mens Shoes At Zephyr Sports for Less Today! We carry a complete line of DVS Skate Shoes at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DVS Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "DVS Shoes | DVS Mens Shoes | DVS Skate Shoes" + }, + ".airsoft.tactical_airsoft_gear.airsoft_flashlights" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markers.dangerous_power_paintball_guns.dangerous_power_m3a1_paintball_guns" : { + "meta_keywords" : "Dangerous Power, paintball, dangerous, power, marker, gun, m3 a1, m3-a1, m3a1,180 PSI, 280 FPS, Semi-Auto, semi, auto", + "meta_description" : "Dangerous Power - Maker of the Dangerous Power M3A1 Paintball Gun. Pick up a Dangerous Power Paintball marker at Zephyr Sports for less today.", + "top_description" : "==Dangerous Power M3-A1 Paintball Gun==\n\nThe new Dangerous Power M3-A1 was unveiled at the 2012 NPPL Surf City Open in Huntington Beach. We have a rough ETA of June and pricing is not yet official. Keep your eyes peeled for updates on this beast of a paintball gun, and we will be sure to update information as we receive it!\n\n\n=Specifications:=\n\n*180 PSI Operating Pressure at 280 FPS\n*Firing Modes: Semi-Auto, 3-Shot Burst, PSP, NXL & Millenium\n*Weight: 6 lbs\n*Clamping Feedneck\n*Inline Regulator", + "page_title" : "On Sale & Free Shipping for Dangerous Power", + "head_title" : "Dangerous Power | Dangerous Power Paintball | M3A1 Paintball Gun", + "zoovy:banner01" : "", + "zoovy:banner02" : "" + }, + ".casual_clothing.mens_clothing.wallets.spitfire_wallets" : { + "meta_description" : "Spitfire Wallets - Buy your Spitfire Mens Wallets At Zephyr Sports for Less Today! We carry a complete line of Spitfire Wallet at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Spitfire Wallets on Sale @ Zephyr Sports", + "head_title" : "Spitfire Wallets | Spitfire Mens Wallets | Spitfire Wallet" + }, + ".casual_clothing.mens_clothing.tshirts.srh_t_shirts" : { + "meta_keywords" : "SRH T Shirts,SRH shirts,free shipping,SRH TShirt", + "meta_description" : "SRH T Shirts - Zephyr carries a complete line of SRH Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "SRH T Shirts at Zephyr", + "head_title" : "SRH T Shirts | SRH Shirts | SRH TShirt" + }, + ".harnessesbags.paintball_gear_bags.ncstar_gear_bags" : { + "meta_description" : "NcStar Paintball Gear Bags - Buy your Nc Star Backpacks Online at Zephyr Paintball for Less today. Free Shipping on NcStar Bags Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy NcStar Paintball Gear Bags Online On Sale Now", + "head_title" : "NcStar Paintball Gear Bags | Nc Star Backpacks | NcStar Bags" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_fixed_power_scopes.leapers_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".safetygear.goggles.vforce" : {}, + ".airsoft.airsoft_guns.echo_1_airsoft_guns.ak47_echo_1_airsoft_guns" : { + "meta_keywords" : "AK47 airsoft,electric airsoft guns,ak47 airsoft gun,electric ak47,AK 47 Airsoft gun,electric airsoft,AK 47 Airsoft,kalashnikov,AK47 AEG,Echo 1 AK 47 Airsoft Rifle,echo 1", + "meta_description" : "Echo 1 AK 47 Airsoft Rifle - The AK47 design is one of the most commonly used rifles around the world. The long barrel gives the gun great range and accuracy. While the gun has for many years been known for “guerilla” warfare it most recently has been accommodated for tactical accessories such as; scopes, flashlights, lasers and other mountable upgrades. Zephyr Sports carries a full line of Electric Airsoft guns styled by the AK 47. These AK 47 Electric Airsoft Guns are super realistic, full auto Kalashnikovs! In the world of Electric Airsoft, the AK47 airsoft gun dominates! Cheap prices for high quality, straight from manufacturer Airsoft Essentials!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Echo 1 AK 47 Airsoft Rifle | Echo 1 AK47 RIS | Echo 1 AK47 Airsoft" + }, + ".casual_clothing.mens_clothing.belts.north_face_belts" : { + "meta_keywords" : "North Face Belts,North Face Belt Buckle,North Face Belts,North Face webbed belt", + "meta_description" : "North Face Belts - We carry the complete line of North Face Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "North Face Belts on Sale Now!", + "head_title" : "North Face Mens Belts | Aplinestars Belts" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_fixed_power_scopes.centerpoint_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".dye_i4_paintball_goggle_mask.paintball_blog.dye_dm13_paintball_gun" : { + "meta_description" : "Dye has just released the 2013 version of the DM. The DM13 will surely be the hottest tournament paintball gun for 2013.", + "top_description" : "Just released from Dye for 2013, the [[Dye DM13]:popup=www.zephyrpaintball.com/category/markers.dye_matrix_paintball_guns.dye_dm13_paintball_guns/] will be the hottest tournament paintball gun of the year. Sneak peaks seem to show an led screen, but this has yet to be confirmed by Dye. We should see the full release of the dm13 during the week of 10/22 at the world cup in florida. The [[Dye DM13]:popup=http://www.zephyrsports.com/category/paintball.paintball_guns.dye_matrix_paintball_guns.dye_dm13_paintball_guns/] will include the tournament tested ultralite barrel. Beyond the possible LED screen, we have not heard of any other new features. Additional info and pictures will be posted as available.", + "head_title" : "Dye Dm13 Paintball Gun Review" + }, + ".casual_clothing.mens_clothing.tank_tops.dvs_tank_tops" : { + "meta_description" : "DVS Tank Tops - Buy your DVS Jersey Tank Tops At Zephyr Sports for Less Today! We carry a complete line of DVS Mens Tank Tops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DVS Mens Jersey Tank Tops at Zephyr Sports", + "head_title" : "DVS Tank Tops | DVS Jersey Tank Tops | DVS Mens Tank Tops" + }, + ".casual_clothing.mens_clothing.tshirts.hurley_t_shirts" : { + "meta_keywords" : "Hurley T Shirts,Hurley shirts,free shipping,Hurley TShirt", + "meta_description" : "Hurley T Shirts - Zephyr carries a complete line of Hurley Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Hurley T Shirts at Zephyr", + "head_title" : "Hurley T Shirts | Hurley Shirts | Hurley TShirt" + }, + ".airsoft.airsoft_safety.airsoft_neck_and_face_protection" : { + "meta_description" : "Airsoft Face and Neck Protection - Buy your Airsoft Neck Protector At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Airsoft Face and Neck Protection On Sale & Free Shipping", + "head_title" : "Airsoft Face and Neck Protection |Airsoft Neck Protector" + }, + ".apparel" : { + "top_html" : "", + "meta_keywords" : "Paintball Apparel, Paintball Clothes, Paintball Clothing, Paintball Equipment, Paintball Supplies, Paintball Accessories, Paintball Shirts, Paintball Sweatshirts, Paintball Hats, Paintball Gloves, Paintball Beanies, Paintball Jersey, Paintball Hats, jersey, apparel, clothing, pants, gloves, women clothing, women's clothing, men clothing, men's clothing, pant, womens clothing, mens clothing, women apparel, clothing apparel", + "ad3_link" : "", + "add3_link" : "/category/apparel.sunglasses.oakley_sunglasses/", + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=&LINK=", + "top_description2" : "", + "prodlist2_title" : "Featured Clothing Items", + "top_html_focus" : "", + "ad2" : "", + "banner4" : "banners/sunglasses/side_banners/oakley_001", + "3widead_title" : "", + "page_title" : "Paintball Clothes on Sale at Zephyr", + "zs11_banner_wslideshow_slide2" : "ALT=&IMG=&LINK=", + "ad2_link" : "", + "add1_link" : "/category/apparel.hats___beanies.eclipse_hats___beanies/", + "banner2" : "banners/sm_promo/planet_eclipse_headwear.png", + "subcat1_header" : "", + "meta_description" : "Get all you apparel needs here. Paintball apparel from head to toe. Get all setup with new threads for on the field and off the field. And do not forget about your girl or lady friend or even guy friend. We have men's and women's apparel waiting for you to get your hands on.", + "top_description" : "Look like a real paintball player the next time your on the field! Jeans and a t-shirt may work the first few times playing paintball, but gear designed for paintball is much more comfortable and well worth the money. Pants range from $40 - $200+ while jerseys will run you $30 - $120.", + "ad1" : "", + "banner01_link" : "/results.cgis?catalog=HOMEPAGE&keywords=25ULI4&x=12&y=9", + "zoovy:banner01" : "", + "description" : "==Paintball Apparel==\n\n\n=Paintball Pants=\nYour first piece of paintball clothing should be a good pair of paintball pants. A good pair of paintball pants should have these features - Knee and Hip padding, Adjustable waist belt, highly breathable, lightweight, and durable. Basically with paintball pants the start from entry level to tournament level. Below we'll explain a few pros and cons of each level. Basically as you climb up the price scale, you will get more and more of these features. \n\n\n Entry Level Paintball Pants - Price range for a pair of entry level paintball pants is $40 - $85. Entry level pants will have an adjustable waist belt and a few pockets as well as possible a barrel swab pocket. Entry level pants will be lightweight and much more comfortable than a pair of jeans, but not as soft and supple as the tournament level paintball pants we discuss below. You will typically get very lightweight or no knee pads at all. Examples of entry level pants include the Valken Fate and Empire Prevail pants.\n\n\n Tournament Level Paintball Pants - Price range for top level paintball pants starts at about $130 - $175. With this level of pants you will get significant padding in the knee, hip and crotch area providing plenty of protection as well as an extra few bounces when you need em. You will also get a squeegee pocket as well as a padded adjustable waist belt. Pro paintball pants will have venting throughout the side to keep you cool on the hottest days. On the back of the pants you will have a padded area that helps grip your harness keeping everything where it's comfortable. Pro level Paintball pants examples include Dye, Empire Contact, Eclipse Distortion as well as Sly Pro Merc", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "ad3" : "", + "banner1" : "", + "htmlvids" : "", + "ad1_link" : "", + "head_title" : "Paintball Apparel | Paintball Clothes | Paintball Clothing", + "sortby_var" : "Clothing Type", + "page_head" : "" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_cycling_hydration_packs.camelbak_annadel_hydration_packs" : {}, + ".markers.tippmann.tippmann_crossover_paintball_guns" : { + "meta_keywords" : "tippmann crossover,crossover paintball guns,tippmann tournament,tipman,tippman,tipmann, cross over", + "meta_description" : "Tippmann Crossover - Tippmann finaly jumps into the tournament market with the new Crossover Paintball gun from Tipmann. Zephyr Paintball is the leader in Online Paintball Gear. ", + "top_description2" : "", + "top_description" : "", + "zoovy:banner01" : "", + "description" : "==Tippmann Crossover Paintball Gun==\n\nFinally!! A Tournament Paintball Gun from Tippmann. The Tippmann Crossover Paintball Gun is here. \n\nAs the leader in paintball marker durability and reliability we are taking the game to a whole new level with the introduction of the Crossover paintball gun. This new lightweight, high performance electro-pneumatic marker is designed to perform for players regardless of conditions or style of play. At the heart of the Crossover beats the latest iteration of Tippmann's FlexValve - the exclusive industry technology that allows players to switch from electronic to mechanical mode on the fly, with just the flip of a switch. A variety of other key features are also integrated into the Crossover to give players the ability to go harder than before, while traveling lighter than ever.\n\n\nThe new Tippmann Crossover is covering new ground and reaching out to an expanded group of players with this product advancement. The Tippmann Crossover was designed for the hybrid player, someone who needs a durable and reliable marker that will deliver - regardless of the style of game. As implied by its name, it's a marker that will successfully cross over to any game, anywhere, any time. While our existing modifiable and easy-to-upgrade markers remain extremely popular, we also wanted to reach out to those players seeking legendary Tippmann durability in a sleek, lightweight and bold new design.\n\n\nSome of the features incorporated into the new Tippmann Crossover paintball marker include the following: \n\n*.68 caliber electro-pneumatic marker\n*New, lightweight compact design \n*Integrated break beam anti-chop eyes\n*Ability to work in both electronic and mechanical modes\n*Low pressure operation under 300 PSI\n*Internal gasline\n*Magnetic hall effect trigger switch\n*Multiple adjustable firing modes, including semi-auto, auto-response, 3-shot burst, PSP, NPPL and Millennium\n*Tournament lock switch\n*Adjustable clamping feedneck with vertical feed\n*Machine-milled upper body \n*Bottom regulator with the ability to convert to a front regulator\n*Fully compatible with HPA and Nitrogen; for CO2, see owner's manual for details\n*Two year limited warranty\n*Tippmann A-5/X7 threads\n\nThe Tippmann Crossover is the only marker of its kind that combines the benefits of FlexValve Technology - including low recoil, low pressure operation, and the ability to switch from electronic to mechanical operation - with Tippmann durability.", + "top_html_focus" : "", + "htmlvids" : "", + "htmllinks" : "\n\n", + "head_title" : "Tippmann Crossover | Crossover Tippmann Paintball Guns", + "page_title" : "Tippmann Crossover Paintball Guns" + }, + ".harnessesbags.backpacks.dakine_backpacks.dakine_network_bagckpacks" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_loaders.halo_b_paintball_loader" : {}, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns.d_fender" : { + "meta_keywords" : "Empire Defender, Empire D*Fender, Empire BT Defender, Empire BT D*Fender, Empire Paintball Guns, Empire Paintball Markers", + "htmlvids" : "", + "meta_description" : "The Empire Defender is the latest addition to the BT line of paintball guns from Empire. The Defender features a hopper that uses proven Z2 technology integrated into the stock of the marker. With the Defender you get the convenience of mag fed play, with the performance and storage and capacity of standard hopper-fed markers.", + "top_description" : "== Empire BT D*fender Paintball Marker ==\nThe innovative genius of Empire Paintball has been at it again with the creation of the Empire BT D*Fender. This radical design moves the loader from off the top of the marker and places it within the stock of this bullpup-style masterpiece. The D*Fender has ultra-strong, lightweight magnesium shells with the high performance guts of our markers and a Z2 loader inside. Reduce your silhouette and never take a hit on your loader again. Forget its name, with the D*Fender in your hands, you'll attack!", + "page_title" : "Empire Defender Paintball Gun", + "head_title" : "BT Defender Paintball Marker", + "description" : "= Features: =\n* High performance paintball marker with integrated loader\n* Magnesium shells for high strength and light weight\n* Break Beam Eyes in breech prevent ball chops\n* Selector switch with 5 Firing modes – Semi, Burst, Ramping, Full Auto and Select Fire\n* On/Off Regulator with easy-to-mount T-Slot rail\n* Smooth, programmable bearing trigger with 3-way adjustment\n* Removable side Picatinny rails and top Picatinny rails for accessories\n\n= Functions: =\n* Inline pressure controlled poppet firing engine offers accurate fire and smooth shooting\n* Proven Z2 loader performance with auto anti-jam\n* Loader activates upon trigger pull, so constant feeding is guaranteed\n* Capable of firing 20bps with continuous loading\n* Self calibrating loader speed sensor\n* Tool-less basic maintenance/battery change\n* Battery level indicator\n* 6 AA Operation for all electronics\n\n= Included Items: =\n* Includes both a standard magnetic lid and speed feed lid\n* Ported, aluminum barrel with three Super Freak inserts (.680, .685, .690)\n* Additional Super Freak Apex2 barrel that creates shots that curve onto targets\n* Multi-position sling adapter for those long treks to the battlefield" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_inner_barrels.modify_upgrade_barrels" : {}, + ".apparel.jerseys.empire_paintball_jerseys" : { + "meta_keywords" : "Empire Paintball Jersey, Paintball Jersey Empire, Empire Paintball Jerseys, Empire Paintball, Paintball Jersey, Empire Paintball Equipment, Empire Paintball Supplies, Empire Paintball Accessories, Paintball Equipment", + "meta_description" : "Empire Paintball Jersey - Looking for the best prices on Empire paintball jerseys? Look no further then ZephyrPaintball.com for the largest selection of paintball supplies and equipment.", + "page_title" : "", + "head_title" : "Empire Paintball Jersey | Paintball Jersey Empire | Empire Paintball Jerseys", + "sortby_var" : "Empire Jersey Model Year", + "page_head" : "Empire Paintball Jersey - Paintball Jersey Empire - Empire Paintball Jerseys" + }, + ".3packagespecials.gog_paintball_packages" : { + "meta_description" : "GOG Paintball Packages - Buy your GOG Paintball Starter Kits Online at Zephyr Paintball for Less today. Free Shipping on Gog Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy GOG Paintball Packages Online On Sale Now", + "head_title" : "GOG Paintball Packages | GOG Paintball Starter Kits | Gog Paintball Guns" + }, + ".skateboard_gear.skateboard_trucks.tensor_skateboard_trucks" : { + "meta_description" : "Tensor Trucks - Zephyr Sports carries a complete line of Tensor Skateboard Trucks At the lowest prices on the web with free shipping and easy returns. Buy your Tensor Skate Trucks Online Today.", + "page_title" : "Tensor Trucks On Sale Free Shipping", + "head_title" : "Tensor Trucks | Tensor Skateboard Trucks | Tensor Skate Trucks" + }, + ".barrels.autococker.16__autococker_paintball_barrels" : { + "meta_description" : "16 inch Autococker Paintball Barrels - Buy your 16\" Autococker Threaded Barrels Online at Zephyr Paintball for Less today. Free Shipping on Cocker Paintballs Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 16 inch Autococker Paintball Barrels Online On Sale Now", + "head_title" : "16 inch Autococker Paintball Barrels | 16\" Autococker Threaded Barrels | Cocker Paintballs Barrels" + }, + ".markers.btdesignspaintballguns.bt_delta_paintball_guns" : { + "meta_keywords" : "BT Delta Paintball,BT-4 Delta Paintball Guns,Delta Paintball Marker,paintball gear,paintball guns,BT Paintball,", + "meta_description" : "BT-4 Delta Paintball Gun - Battle Tested Delta Paintball Guns are high quality, super durable paintball guns! Lightweight and reliable paintball markers that won't let you down! Customize and complete your BT Delta Paintball Gun with BT Paintball Gear; loads of marker upgrades and scenario accessories available!", + "top_description" : "For the scenario or woodsball player who wants realism, BT Paintball offers the BT4 Delta paintball gun. Based on the MP5, most recognizable submachine gun in the world, BT has created a compact, accurate paintball marker that looks like it should be carried by SEALs. The Delta paintball gun has a lightweight, balanced construction for all day play and an adjustable stock for a comfortable firing position. The clamping feedneck will accept loaders without the need for tools, or upgrade to a BT Rip Clip for HALO powered force feed loading. The Delta gun has a modular trigger, so taking it apart for cleaning is simple, and easily upgrades to the Double Trigger or the Electronic Grip Frame for increased firepower. The compact BT4 Delta is an accurate, reliable paintball gun with an authentic look that will help you and your team reign supreme on the battlefield. ", + "page_title" : "Buy BT Delta Paintball Online On Sale Now", + "head_title" : "BT Delta Paintball | BT-4 Delta Paintball Guns | Delta Paintball Marker", + "description" : "=Features:=\n\n* Slide-Away feedport for easy cleaning and maintenance.\n* Lightweight, balanced construction\n* Impact-resistant, backed-on coating\n* Modular trigger system\n* Adjustable stock\n* Upgradeable to accept BT Rip-Clip and BT Electronic Grip Frame\n* Removable grip frame for quick and easy upgrades\n* Works with CO2 or compressed air\n" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.echo_1_electric_airsoft_rifles.specialty_echo_1_airsoft_guns" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Echo 1 upgrade | Echo 1 specialized | Echo 1 Special" + }, + ".maddog.ion_upgrades.ion_feed_necks" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses.ray_ban_warrior_sunglasses" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_sentry_watches" : { + "meta_description" : "Nixon Sentry Watches - Buy your Nixon Sentry Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Sentry at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Sentry Watches", + "head_title" : "Nixon Sentry Watches | Nixon Sentry Watch | Nixon Sentry" + }, + ".airsoft.airsoft_apparel.tactical_gloves.voodoo_tactical_gloves" : {}, + ".casual_clothing.mens_clothing.shorts.dc_shorts" : { + "meta_description" : "DC Shorts - Zephyr stocks a complete line of DC Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your DC needs. ", + "page_title" : "DC Shorts with Free Shipping at Zephyr", + "head_title" : "DC Shorts | DC Board Shorts" + }, + ".casual_clothing.mens_clothing.shirts.emerica_shirts" : { + "meta_description" : "Emerica Flannel Shirts - Buy your Emerica Polo Shirts At Zephyr Sports for Less Today! We carry a complete line of Emerica Shirts at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Emerica Shirts & Flannels Ship Free", + "head_title" : "Emerica Flannel Shirts | Emerica Polo Shirts | Emerica Shirts" + }, + ".2clearance.clearance_upgrades.clearance_bolts" : { + "head_title" : "Sale Paintball Bolts | Clearance Paintball Bolts | Paintball Bolts Sale" + }, + ".snowboard_gear.snowboard_goggles.dye.dye_replacement_lenses" : {}, + ".barrels.phantom_paintball_barrels" : { + "head_title" : "Phantom Paintball Barrels | CCI Phantom Barrel" + }, + ".airsoft.airsoft_bbs_ammo.10_biodegradeable_airsoft_ammo" : { + "meta_keywords" : "bio bbs, biodegradable bbs, biodegradable ammo", + "meta_description" : "Biodegradable Airsoft BBs. Environmentaly Friendly; Decomposes within days to weeks. As ambient moisture or water comes in contact with the BB, the materials begin to degrade. Make sure to keep these in their air tight container until ready for use. Intended for use in a wide range of airsoft guns including AEG, gas & co2 guns. Some higher powered AEG guns shooting 450+ fps may experience some variation in performance as the softer material used may be affected at higher velocities.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "", + "head_title" : "Airsoft Bio BBs | Biodegradeable BB s | BB King 6mm Bio BB" + }, + ".casual_clothing.womens_clothing.ladies_sandals.reef_womens_sandals" : {}, + ".harnessesbags.backpacks.oakley_backpacks.oakley_checkpoint_computer_bag" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_asian_fit_sunglasses.oakley_asian_fit_fast_jacket_sunglasses" : {}, + ".casual_clothing.mens_clothing.shoes.sanuk_shoes" : { + "meta_description" : "Sanuk Shoes - Buy your Sanuk Sandals At Zephyr Sports for Less Today! We carry a complete line of Sanuk Shoe at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Sanuk Shoes on Sale with Free Shipping at Zephyr", + "head_title" : "Sanuk Shoes | Sanuk Sandals | Sanuk Shoe" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.aeg_bulk_buy_mags" : {}, + ".1newitems.2008_products.2008_tippmann_gear" : {}, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_nolen_sunglasses" : { + "meta_keywords" : "Spy Nolen sunglasses,spy sunglasses,spy optics sunglasses,spy sunglass,spy optical, spy optic, spy optic eyewear", + "meta_description" : "Spy Nolen Sunglasses - Zephyr is your Spy Optics Sunglasses headquarters. We carry a complete line of spy optic eyewear with free shipping, a one year breakage guarantee and 100% satisfaction guarantee. Trust Zephyr Sports for all your Spy Optic sunglass needs.", + "page_title" : "Buy Spy Nolen Sunglasses On Sale & Free Shipping", + "head_title" : "Spy Nolen Sunglasses | Spy Optics Nolen Sunglasses" + }, + ".baseball.baseball_softball_gloves.baseball_loves.rawlings_gloves.rawlings_gold_glove_baseball_gloves" : { + "head_title" : "Rawlings Gold Glove Baseball Gloves | Rawlings Baseball Gloves | Rawlings Baseball Mitt" + }, + ".airsystems.tankcovers.bottle_covers_by_tank_size.45_ci_nitro_bottle_covers" : { + "meta_description" : "45 ci Tank Cover - Buy your 48 Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Paintball Bottle Covers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 45 ci Tank Cover Online On Sale Now", + "head_title" : "45 ci Tank Cover | 48 Tank Cover | Paintball Bottle Covers" + }, + ".casual_clothing.mens_clothing.beanies.kr3w_beanies" : { + "meta_description" : "Kr3w Beanies - Buy your Beanies Kr3wAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on KR3W BEANIES @ Zephyr Sports", + "head_title" : "Kr3w Beanies | Beanies Kr3w" + }, + ".markerupgrades.tippmann.model98customandpro.tippmann_98_bolts___springs" : {}, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones.nixon_headphones.nixon_whip_headphones" : { + "head_title" : "Nixon Whip Headphones | Whip Nixon Head Phones | Nixon Whip Headphone" + }, + ".markers.btdesignspaintballguns.bt_delta_elite_paintball_guns" : { + "meta_keywords" : "bt delta elite paintball guns,delta elite paintball marker,delta elite paintball\r ", + "meta_description" : "Delta Elite Paintball - Buy your BT Delta Elite Paintball Guns Online at Zephyr Paintball for Less today. Free Shipping on Delta Elite Paintball Marker Trust Zephyr for all your Paintball Needs", + "top_description" : "==BT Delta Elite Paintball Marker==\n\nBT Paintball strives to create markers with a real-world look and feel. The BT Delta Elite paintball gun design is based on the world's pre-eminent submachine gun and is the choice of many players who desire authenticity. While it looks like it's straight off the battlefield, it has some advanced features that make it an awesome paintball marker. Manage the number of paintballs you can shoot with the Electronic Grip Frame, offering multiple firing modes, such as semi-auto, adjustable ramping and full auto. The Rip Clip force feeds paintballs using sound-activated HALO technology and when paired with the E-Grip and Double Trigger, puts more paint in the air than your opponent can duck. The Apex Barrel can create custom shot trajectories, specifying left or right hooks, drop shots and even extended range. There's no place to hide from the player using the Elite.", + "page_title" : "Buy Delta Elite Paintball Online On Sale Now", + "head_title" : "Delta Elite Paintball | BT Delta Elite Paintball Guns | Delta Elite Paintball Marker", + "description" : "The Delta Elite paintball gun has an adjustable stock for a comfortable fit and adjustable range rear sight for accurate shooting. The small, compact size is perfect for Close Quarters combat and the rate of fire will ensure you emerge victorious. The Delta Elite is tough, its baked on coating can withstand impacts and the quality construction assures it will continue to fire. Whether using CO2 or compressed Air, the Delta Elite paintball gun give you the edge over the opposition and guarantee your day will be fun. \n\n\n=Features=\n* Lightweight, Balanced Construction\n* Impact-Resistant, Baked-On Coating\n* Adjustable Stock\n* Works with CO2 or Compressed Air\n\n=Apex Barrel=\n* Multi-step trajectory control\n* Allows extended range (even in wooded areas)\n* Offers left hook, right hook or \"drop shot\" curves\n\n=Electronic Grip Frame=\n* Double finger trigger\n* Semi-Auto, PSP ramping, NXL full-auto\n\n=Rip Clip with HALO Technology=\n* Sound-activated, force-feed loader\n* Offset to the Right for Sighting Down the Barrel\n* Built-in Rip Drive to advance balls and clear jams\n* Holds over 200 paintballs" + }, + ".markerupgrades.kingmanspyder.spyder_vs_upgrades" : {}, + ".dye_rotor_paintball_loader.z_dye_rotor_blog_and_reviews.paintball_masks.proto_fp_paintball_masks" : {}, + ".casual_clothing.z-sunglasses.von_zipper_sunglasses.von_zipper_elmore_sunglasses" : { + "meta_keywords" : "Von Zipper Fulton sunglasses,VZ Fulton, Von Zipper polarized sunglasses,Von Zipper Fulton,VZ Fulton glasses,Von Zipper mens sunglasses", + "meta_description" : "Von Zipper Elmore Sunglasses - Von Zipper Polarized sunglasses are now available @ Zephyr! Get your VZ Elmore sunglasses now! For Von Zipper Elmore glasses and other Von Zipper Mens Sunglasses use Zephyr! VZ offers a lifetime guarantee against manufacturer's defects on all products. It is our pledge that your VonZipper experience is all that it can be. \n\n", + "page_title" : "Buy Von Zipper Elmore Sunglasses On Sale & Free Shipping", + "head_title" : "Von Zipper Elmore Sunglasses | VonZipper Elmore Sunglasses | VZ Elmore Sunglasses " + }, + ".casual_clothing.z-sunglasses.gatorz_sunglasses.gatorz_boxster_sunglasses" : { + "meta_description" : "Gatorz Boxster Sunglasses - Zephyr Sports carries a complete line of Gatorz Boxster Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Gatorz Boxster Online Today.", + "page_title" : "Gatorz Boxster Sunglasses On Sale Free Shipping", + "head_title" : "Gatorz Boxster Sunglasses | Gatorz Boxster Sun Glasses | Sunglasses Gatorz Boxster" + }, + ".1historical_products.clothing" : {}, + ".harnessesbags.backpacks.dakine_backpacks.dakine_travel_kits___accesories" : {}, + ".safetygear.maddog" : {}, + ".casual_clothing.mens_clothing.shorts.etnies_shorts" : { + "meta_description" : "Etnies Shorts - Zephyr stocks a complete line of Etnies Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Etnies needs. ", + "page_title" : "Etnies Shorts with Free Shipping at Zephyr", + "head_title" : "Etnies Shorts | Etnies Board Shorts" + }, + ".casual_clothing.z_unisex_clothing_accesories" : { + "zs11_banner_wslideshow_slide1" : "ALT=Zephyr+Sunglasses%21+Choose+Your+Color%21&IMG=&LINK=%25SESSION%25%2fproduct%2fZPHR%2d0810%2dSUNNIE%2dPRT%2fZephyr%2dSports%2dLimited%2dEdition%2dSummer%2dSunnies%2ehtml", + "banner01_link" : "/product/ZPHR-0810-SUNNIE-PRT/Zephyr-Sports-Limited-Edition-Summer-Sunnies.html", + "zoovy:banner01" : "banners/sunglasses/slideshow/zephyr_sunglasses_slideshow_template.jpg" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optic_lennox_sunglasses" : { + "meta_description" : "Spy Optics Lennox Sunglasses - Zephyr Sports carries a complete line of Lennox Spy Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Spy Lennox Sun Glasses Online Today.", + "page_title" : "Spy Optics Lennox Sunglasses On Sale Free Shipping", + "head_title" : "Spy Optics Lennox Sunglasses | Lennox Spy Sunglasses Free Shipping | Buy Spy Lennox Sun Glasses" + }, + ".airsoft.airsoft_guns.echo_1_airsoft_guns.m4___m16_echo_1_airsoft_guns" : { + "meta_keywords" : "m16,Eletric airsoft guns,m4 airsoft,m4 airsoft guns,m16 airsoft guns,m16 airsoft rifle,m4 gun,m4 aeg,electric m16,electric airsoft m16,electric airsoft rifles,airsoft rifles,echo 1 M4 & M16 Airsoft Guns,echo 1", + "meta_description" : "Echo 1 M4 & M16 Airsoft Guns - Zephyr Sports carries a full line of Electric airsoft guns; The M4 airsoft Rifle is an assault rifle with unmatched performance! You're bound to hit the competition with the amount of spray this baby provides! The M4 and M16 AEGs are heavy duty Airsoft Rifles! These high performance airsoft rifles bring a-whole-nother dimension into the game of airsoft! For cheap prices on high quality, straight from manufacturer Airsoft Essentials choose Zephyr! Introduced during the Vietnam era the M16 & M4 quickly became one of the most reliable guns ever created. It has proved its worth on the battlefield by not only being very accurate but also easy to clean and maintain. Given the reliability and simplicity of the gun, it makes it an easy choice for either a greenhorn or seasoned veteran.", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Echo 1 M4 Airsoft Rifle On Sale & Free Shipping", + "head_title" : "Echo 1 M4 Airsoft Rifle | Echo 1 M4 RIS | Echo 1 M4 AEG" + }, + ".markers.tippmann.tippmann_tpx_pistol" : { + "meta_keywords" : "Tippmann TPX Pistol, TPX Paintball Pistol, TPX Pistol, Tipman pistol, Tippman TPX, TPX magazine kit, paintball pistol, Tipmann, tippmann paintball pistol", + "meta_description" : "Tippmann TPX Pistol - The hot new TPX Paintball pistol from Tipmann. Get your TPX Pistol at Zephyr today. Free shipping on paintball gear orders over $100.", + "top_description" : "Need a sidearm on the field?! Tippmann has you covered! The new Tippmann TPX Paintball Pistol boasts an innovative, compact design, specially engineered to be lightweight, easy to maintain, customizable, and best of all, dependable. Whether as a backup, or your primary, the Tippmann TiPX Paintball Pistol keeps you in the game! Check out the specs and various accessories below! Grab the complete set-up w/ extra C02 cartridges and a holster! The Tippmann TPX Pistol now comes in black and Limited edition tan.", + "zoovy:banner01" : "", + "description" : "=Tippmann TPX Pistol Specs:=\nThe new TPX pistol uses standard .68 cal paintballs so you don't need to carry a second size of paint. The TPX Paintball Pistol is a great addition to any paintballer's arsenal! Self-Locking 8 Ball easy change magazines allow for a complete day of paintball fun. The TPX pistol operates off of a 12 Gram CO2 cartridge that locks securely under the barrel location giving it a balanced setup. You should get around 20-30 consistent shots off 1 cartridge. Since the CO2 cartridge is under the barrel; and not housed in the grips, this eliminates the issue of bulky grips allowing for a design that is smaller and textured for a secure feel. Another great feature that we feel is important on the tippmann tipx pistol is the CO2 trigger puncture. With other pistols screwing in the CO2 cartridge can be quite frustrating when you have to screw the cap in fast so you don't waste any of the CO2 - not the TPX pistol! Cartridge placed in easily without any wasted CO2 and will not be punctured until you pull the trigger! Don't use cartridges? Not a problem. The TPX has the ability to add an air adapter with easy access for a [[remote line]:url=/category/airsystems.remote_lines/]. Overall the tippmann TPX pistol is solidly built for rough game play and at the same time can be easily broken down for maintenance/cleaning.", + "htmlvids" : "", + "page_title" : "Buy Tippmann TPX Pistol Online On Sale Now", + "head_title" : "Tippmann TPX Pistol | Tippmann TPX Paintball Pistol | TPX Pistol" + }, + ".barrels.barrels_by_manufacturer.stiffi_paintball_barrels.stiffi_autococker_threaded_barrels" : {}, + ".markers.bob_long_paintball_guns.bob_long_victory_ripper_paintball_guns" : { + "meta_keywords" : "Bob long,bob long paintball,paintball guns,Bob Long Victory Ripper Paintball Gun,victory ripper,bob long victory,cheap bob long,paintball gun,paintball marker,paintball equipment", + "meta_description" : "Bob Long Victory Ripper Paintball Guns @ Zephyr! Full line of bob long paintball guns. Bob Long paintball gun accessories available! Pick up your Bob Long Victory Ripper today! Choose Zephyr for all your Paintball Equipment!", + "page_title" : "Buy Bob Long Paintball Online On Sale Now", + "head_title" : "Bob Long Paintball | Bob Long | Bob Long Victory Ripper" + }, + ".backpacks.camelback_backpacks.camelbak_winter_hydration_packs.camelbak_pit_boss_hydration_packs_" : {}, + ".casual_clothing.mens_clothing.jackets.eclipse_jackets" : { + "meta_description" : "Eclipse Jackets - Buy your Eclipse Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Eclipse Jackets with Free Shipping", + "head_title" : "Eclipse Jackets | Eclipse Mens Jackets" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_trace_sunglasses" : { + "meta_description" : "Smith Optics Trace Sunglasses - Zephyr Sports carries a complete line of Trace Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Trace Sun Glasses Online Today.", + "page_title" : "Smith Optics Trace Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Trace Sunglasses | Trace Smith Sunglasses Free Shipping | Buy Smith Trace Sun Glasses" + }, + ".casual_clothing.mens_clothing.jackets.electric_jackets" : { + "meta_description" : "Electric Jackets - Buy your Electric Mens Jackets At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save On Electric Jackets with Free Shipping", + "head_title" : "Electric Jackets | Electric Mens Jackets" + }, + ".casual_clothing.mens_clothing.rash_guards.dakine_rash_guards" : { + "meta_description" : "Dakine Rash Guards - Buy your Dakine Surf ShirtsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Dakine Rash Guards at Zephyr Sports", + "head_title" : "Dakine Rash Guards | Dakine Surf Shirts" + }, + ".casual_clothing.z-sunglasses.maui_jim_sunglasses.maui_jim_mahina_sunglasses" : { + "meta_description" : "Maui Jim Mahina Sunglasses - Zephyr Sports carries a complete line of Maui Jim Mahina Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Maui Jim Mahina Online Today.", + "page_title" : "Maui Jim Mahina Sunglasses On Sale Free Shipping", + "head_title" : "Maui Jim Mahina Sunglasses | Maui Jim Mahina Sun Glasses | Sunglasses Maui Jim Mahina" + }, + ".airsoft.airsoft_gun_magazines.aeg_magazines.1search_by_gun_type.mp7_airsoft_gun_magazines" : {}, + ".apparel.shoes.1_search_by_color.blue_mens_shoes" : {}, + ".harnessesbags.backpacks.dgk_backpacks" : { + "meta_description" : "DGK Backpacks - Buy your DGK BagsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "DGK Bags and Backpacks on Sale at Zephyr", + "head_title" : "DGK Backpacks | DGK Bags" + }, + ".loaders" : { + "meta_keywords" : "paintball hopper, paintball loader, cheap paintball loaders, electronic hoppers, cheap paintball loader, paintball hoppers, hoppers, loaders, paintball feeder, paintball holders", + "ad3_link" : "%SESSION%/category/loaders.empire.empire_prophecy_z2_paintball_hopper_loader/", + "add3_link" : "/category/loaders.pinokio_paintball_loaders/", + "prodlist2_title" : "Featured Loader Items", + "top_html_focus" : "
                                                                          \n
                                                                          \n
                                                                          ", + "ad2" : "banners/paintball/side_banners/virtue_spire_hopper.jpg", + "banner4" : "banners/sm_promo/pinokio_400bc_small_001.jpg", + "3widead_title" : "Featured Loaders", + "page_title" : "Buy Paintball Hoppers Online On Sale Now", + "ad2_link" : "%SESSION%/category/loaders.virtue_spire_paintball_loaders/", + "btn2" : "", + "add1_link" : "/category/loaders.dye_paintball_loaders/", + "banner2" : "banners/sm_promo/rotor_50bps_small_001.jpg", + "subcat1_header" : "Loader Categories", + "btn1" : "", + "meta_description" : "There are so many different loaders out in the paintball world. But which one is right for you and your gun? We have several choices for you to choose from, including Dye, Viewloader, Empire, Invert and Halo.", + "ad1" : "banners/paintball/side_banners/rotor_loader_sidebanner001.jpg", + "btn3" : "", + "description" : "Purchasing a Paintball loader can be super difficult if you do not know exactly what you are looking for. We have an extensive selection of both high-end and basic paintball loaders to choose from, not to mention everything in between! Here's a little run down of some of the hoppers we carry.\n\n\nOn the cheap side, better yet ~ beginner stage, we have your standard Gravity fed paintball loader. An example of this type of hopper would be the 32 Degrees standard 200 round hopper. This loader is compatible with all paintball guns on the market(Excludes Cyclone feed). However, being gravity fed, it will only feed as fast as the paintballs drop. Gravity feed hoppers usually consist of a 200 round container complete with a lid. With a maximum feed rate of 5-8BPS, these hoppers may become jammed as too many balls accumulate above the tube. Of course when this occurs, rocking the gun gently should successfully dislodge any jammed paintballs. \n\n\nNext, we have the Extreme Rage, Kingman, Invert and Tippmann paintball hoppers. These loaders are both inexpensive and effective for any player on a budget. Being electronically agitated, these hoppers provide a constant flow of paintballs to the gun at roughly 10-12 balls per second. These are good options for any type of player who does not have a ton of money but wants an effective electronic loader for their gun. The lowest level of these will run constantly while turned on. The higher end of this level including the Invert [[DHalo Too]:url=/category/loaders.invert_paintball_hoppers/] will only run as paint is needed, so your hoppers is not running if you are not shooting. \n\n\nMoving on, the Empire line of paintball hoppers range from good to great in regards to performance! Nothing stands up to rough scenario paintball competition like an Empire Hopper. Sound activated firing means this paintball hopper loads a ball every time you fire your marker. Good-bye misfires, hello rapid-fire fury! Forget about chopped balls.. Empire hoppers even let you adjust the sensitivity of the sound activated feed system. \n\nThe Empire Prophecy is Empire answer to the ultimate tournament level paintball loader. The latest incarnation of the prophecy is the [[Prophecy Z2]:url=/category/loaders.empire.empire_prophecy_z2_paintball_hopper_loader/]\n\nEasily the most recognizable paintball hoppers around, Halos have held the top spot by the pros for some time! Whether it be tournament play or just high intensity friendly fire, Halo hoppers get the job done! These babies combine incredible speed with precision monitoring. Infrared technology actually tracks the acceleration rate of the ball stack to keep the drive spring properly set. When you increase your firing rate, the Halo hopper ups the feed rate. The Halo hopper, like most other high end paintball loaders, is EYE activated which entirely does away with chopped balls! That, along with its 'stock' 22+ BPS firing rate enables its user to fire at will and own the competition! If 22+ BPS doesn't get you excited, check out halos even higher-end paintball loaders complete with upgraded V35 boards ramping up your firing abilities to just about as fast as your fingers can trigger!\n\n\n\nAnd last but certainly not least, DYE Paintball's latest and greatest paintball hopper yet.. the all new DYE Rotor[[Dye Rotor]:url=/category/loaders.dye_paintball_loaders/]! With unmatched aesthetics, the Dye Rotor does more than just look good! REVOLUTIONARY PATENTED ROTOR TECHNOLOGY - The ROTOR LOADER far exceeds pro level feed requirements with an ever impressive 50+ balls per second feed rate. No need to even speculate, just tryyy to beat this beast on the field! Battery performance on this baby is insane with 50K+ shots recorded before they got tired of counting.\n\n\nSo there you have it, start with your paintball marker and go from there! Whether you're looking to upgrade you're already-sick set-up with a high-end terror of a paintball hopper or simply just getting started, ZephyrPaintball.com has everything you need to get in the game and dominate! \n", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "ad3" : "banners/paintball/side_banners/prophecyz2_side_9_29_11", + "banner1" : "banners/09_headers/main_categories/hoppers_loaders_001", + "htmlvids" : "", + "htmllinks" : "", + "ad1_link" : "%SESSION%/category/loaders.dye_paintball_loaders/", + "head_title" : "Paintball Hoppers | Paintball Loaders | Cheap Paintball Loaders", + "page_head" : "" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_optics_bowery_sunglasses" : {}, + ".casual_clothing.z_unisex_clothing_accesories.cell_phone_cases.alpinestars_cell_phone_cases" : { + "meta_description" : "Alpinestars Phone Cases - Buy your Alpinestars Iphone CasesAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Alpinestars Iphone Cases", + "head_title" : "Alpinestars Phone Cases | Alpinestars Iphone Cases" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_asian_fit_sunglasses.oakley_asian_fit_radar_path_sunglasses" : { + "meta_description" : "Oakley Asian Fit Radar Path Sunglasses - Zephyr Sports carries a complete line of Radar Path Asian Fit Oakley Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Oakley Radar Path Asian Fit Sun Glasses Online Today.", + "page_title" : "Oakley Asian Fit Radar Path Sunglasses On Sale Free Shipping", + "head_title" : "Oakley Asian Fit Radar Path Sunglasses | Radar Path Asian Fit Oakley Sunglasses | Oakley Radar Path Asian Fit Sun Glasses" + }, + ".markers.empire_axe_paintball_guns.empire_bt_paintball_guns.tracer" : { + "meta_keywords" : "Empire BT Tracer Paintball Gun,BT Tracer Paintball Pistol,Empire BT Tracer Paintball Pistol,BT Paintball,Paintball Pistol,paintball gear,Pump paintball,BT Pump Paintball Gun", + "meta_description" : "Empire BT Tracer Paintball Gun - Always be prepared w/ the BT Tracer Paintball Pistol! Empire BT Tracer Paintball Guns are accurate and reliable! Don't forget to pick up a couple extra mags! Pump 'em full of paint with Empire BT Paintball gear! Play pump paintball with the Empire BT Tracer Paintball Pistol.", + "top_description" : "Empire BT Tracer Paintball Gun - The internals of the new Empire Tracer paintball gun are compatible with the original PMI Tracer which have been proven for the past 15+ years.\nWhen you take hold of the pump handle on the new BT Tracer Paintball Pistol you will feel the most comfortable and ergonomic handle. Those old days of struggling to pump your gun are gone for good.\nPicatinny rails are mounted on the top of the Empire Tracer so you can mount all of your favorite accessories. ", + "page_title" : "Buy Empire BT Tracer Paintball Gun Online On Sale Now", + "head_title" : "Empire BT Tracer Paintball Gun | BT Tracer Paintball Pistol | Empire Tracer", + "description" : "The Empire Tracer is compatible with either CO2 or HPA and will accept any Autococker threaded barrel or barrel kit. The Empire Tracer pump paintball gun is affordable to any new player, pump player or anyone looking to bring back some old memories.\n\n\n=Features:=\n\n* 68 Caliber Pump Action Gun\n* Empire Trracer Based Off Of PMI Trracer\n* Internals Compatible With PMI Trracer\n* First Strike Compatible Breech\n* Picatinny Rails\n* Cocker Threaded 14\" Barrel\n* Works w/ CO2 or HPA\n" + }, + ".apparel.pants.dyepants.a-_dye_c8_paintball_pants" : { + "meta_keywords" : "Dye Paintball pants,Dye Paintball C8 pants,Paintball Dye C8 pants,Dye Paintball,Paintball pants,Dye,Dye C8 pants,Dye pants", + "meta_description" : "Dye Paintball C8 Pants - 2008 Dye Paintball pants are still available. Get your Dye C8 Paintball Pants while you still can! Limited sizes and colors are available. ", + "top_description" : "Dye Paintball C8 Pants - 2008 Dye Paintball pants are still available! Sizes and colors are limited! Each year, Dye releases new designs and colors for the new season! Pick up your C8 Pants while you still can!", + "page_title" : "Dye C8 Paintball Pants | Dye Paintball C8 Pants | Paintball Dye C8 Pants", + "head_title" : "Dye C8 Paintball Pants | Limited Stock Available" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_the_six_sunglasses" : { + "meta_description" : "Arnette The Six Sunglasses - Zephyr Sports carries a complete line of The Six Arnette Sunglasses At the lowest prices on the web with free shipping and easy returns. Buy your Arnette The Six Sun Glasses Online Today.", + "page_title" : "Arnette The Six Sunglasses On Sale Free Shipping", + "head_title" : "Arnette The Six Sunglasses | The Six Arnette Sunglasses | Arnette The Six Sun Glasses" + }, + ".casual_clothing.mens_clothing.beanies.young_and_reckless_beanies" : {}, + ".shop_by_brand.sly_paintball" : { + "top_html" : "\n\n \n \n\n
                                                                          \n
                                                                          \n\tGoggles\n\t\n
                                                                          \n
                                                                          \n
                                                                          \n\tPlayer Gear\n\t
                                                                          \n
                                                                          ", + "meta_description" : "Sly Profit - Buy your Sly Paintball At Zephyr Sports for Less Today! We carry a complete line of Sly Equipment at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "top_description2" : "= Sly, enhance your game =\n\nWith a sport that is confused by Internet chat sites and self-proclaimed experts, SLY paintball brings statistical data and quality to a level paintball has never seen. All of their products are tested under extreme conditions and backed with a full manufacturer's warranty. Sly's laboratory has all the necessary components to ensure each product is thoroughly tested and guaranteed before it ever leaves the facility. Sly's unwavering devotion to manufacturing the best products on the market is their mission and promise to all paintball enthusiasts. Try Sly Profit Goggles and other Sly Equipment today to see what we're talking about.", + "page_title" : "Buy Sly Profit Now! On Sale & Free Shipping", + "head_title" : "Sly Profit | Sly Paintball | Sly Equipment", + "description" : "= Sly, Enhance your game =\n\n== Quality, and no compromise ==\nEager to expand to all reaches of the paintball market, SLY is dedicated to superior quality without compromising integrity, style or technique. Sly is for you, and dedicated to make the best product that you will ever use. Sly let's their product do the talking, just take a look below.\n\n\n== Profit Goggle systems ==\nThe Profit Goggle Systems show the way forward for any serious tournament player, putting style and function first, while emphasizing safety. \n\n* Dual-compound shaped Polycarbonate lens: 160 degrees of vertical vision, 270 degree of horizontal vision, silicone based thermo cured anti-scratch coating & thermo-flow coated with a Polyurethane based permanent anti-fog (Patents Pending)\n* Lightning fast quick release system (Patents Pending)\n* Frame is built from medium density polymer nylon and is co-molded with ultra supple Thermo Plastic Rubber\n* Ergonomically correct multi-layered and thermoformed padding\n* Integrated professionally engineered Double strap system\n* Various color combinations available\n\n== Profit Lenses ==\nThe Profit Goggle Replacement Lenses give the tournament player the flexibility to advance in any environment. \n\n\n= Features =\n* All Lenses are Dual-compound shaped Polycarbonate with 160 degrees of vertical vision, 270 degree of horizontal vision, silicone based thermo cured anti-scratch coating & thermo-flow coated with a Polyurethane based permanent anti-fog (Patents Pending)\n* Lightning fast quick release system.\n* Low Light Lenses – A variety of Warm-Tone colored tinted lenses for low light and overcast conditions.\n* Gradient Mirror Lenses – A variety of colored gradient tinted lenses with the added protection of Chrome reflective exterior coating. For bright sun-light.\n* Clear Lenses – The simplest choice for all conditions. Offers maximum clarity without compromise.\n\n\n== PRO-MERC Jerseys ==\nSLY is transforming performance gear to meet the requirements of style while emphasizing the use of striking quality textiles. \n\n\n= Features include: =\n* Open cell light-weight foam contour mapped across elbow and forearms\n* New double neck loop with stretch front for easy entry/exit\n* Bionic-stretch panels behind the elbows for freedom of movement\n* Thermoformed 3-D embossed checkered black pattern across back and front main panels\n* Triple-band mesh inserts span the chest sides and shoulders for maximum motion enhanced ventilation\n* Silver 3-D thermal logos\n* Available in all sizes" + }, + ".casual_clothing.z-sunglasses.spy_sunglasses.spy_helm" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_lodown_watches" : { + "meta_description" : "Nixon Lodown Watches - Buy your Nixon Lodown Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Lodown at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Lodown Watches", + "head_title" : "Nixon Lodown Watches | Nixon Lodown Watch | Nixon Lodown" + }, + ".casual_clothing.mens_clothing.beanies.oakley_beanies" : { + "meta_keywords" : "Oakley beanie,Oakley hat,Oakley beanies,Oakley caps,Oakley 686,Oakley headwear,Oakley cuff visor beanie,Oakley beanie hat,Oakley visor beanie,Oakley visor beanies", + "meta_description" : "Oakley Deanie - Surf style with Oakley Beanies available now at Zephyr Sports. Get your Oakley hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Oakley Beanies on Sale at Zephyr Today", + "head_title" : "Oakley Beanie | Oakley Hat | Oakley Beanies" + }, + ".casual_clothing.womens_clothing.ladies_sweatshirts.spitfire_ladies_sweatshirts" : {}, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_sentry_watches" : { + "meta_description" : "Nixon Sentry Watches - Buy your Nixon Sentry Watch At Zephyr Sports for Less Today! We carry a complete line of Nixon Sentry at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Nixon Sentry Watches", + "head_title" : "Nixon Sentry Watches | Nixon Sentry Watch | Nixon Sentry" + }, + ".casual_clothing.mens_clothing.hats.tanked_hats" : { + "meta_keywords" : "Tanked Hats,Tanked caps,Tanked baseball hats,fitted hats,fitted caps,new era,flex fit,flexfit", + "meta_description" : "Tanked Hats - Zephyr carries a complete line of Tanked Caps. With Free Shipping over $25, easy returns, and Great Customer Service Zephyr is your one stop shop for Everything Tanked", + "page_title" : "Tanked Hats on Sale at Zephyr", + "head_title" : "Tanked Hats | Tanked Caps | Tanked Baseball Hats" + }, + ".casual_clothing.z_unisex_clothing_accesories.audio___headphones" : { + "meta_description" : "Headphones - Buy your Ear BudsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Headphones On Sale & Free Shipping", + "head_title" : "Headphones | Ear Buds" + }, + ".airsoft.tactical_airsoft_gear.molle_based_airsoft_vest_accesories.voodoo_tactical_molle_accessories" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".markerupgrades.matrix.matrix_grips" : {}, + ".casual_clothing.z-sunglasses.ray_ban_sunglasses" : { + "meta_keywords" : "Ray Ban Sunglasses, Ray Ban Aviator sunglasses, wayfarer sunglasses, rayban aviator 3025, ray ban predatos", + "meta_description" : "Authentic Ray Ban Sunglasses - Ray Ban has designed some of the hottest sunglasses on the beach. From the Ray Ban Aviator Sunglasses to the Ray Ban Wayfarer, the styles have lasted for decades. Zephyr Sunglasses carries a complete line of Rayban sunglasses with a full factory warranty. Trust Zephyr", + "page_title" : "Buy Ray Ban Sunglasses On Sale & Free Shipping", + "head_title" : "Ray Ban Sunglasses | Ray Ban Aviator Sunglasses | Ray Ban Wayfarer Sunglasses" + }, + ".0001a_christmas_sale.0050" : { + "banner1" : "banners/holiday/holiday_specials_btn_50_001", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=21&SHOWSKU=&" + }, + ".paintballs.proto_paintballs" : { + "prodlist1_header" : "Proto Paintballs" + }, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_ritz_sunglasses" : { + "meta_description" : "Hoven Ritz Sunglasses - Zephyr Sports carries a complete line of Hoven Ritz Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Ritz Online Today.", + "page_title" : "Hoven Ritz Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Ritz Sunglasses | Hoven Ritz Sun Glasses | Sunglasses Hoven Ritz" + }, + ".casual_clothing.mens_clothing.beanies.sullen_beanies" : { + "meta_keywords" : "Sullen beanie,Sullen hat,Sullen beanies,Sullen caps,Sullen 686,Sullen headwear,Sullen cuff visor beanie,Sullen beanie hat,Sullen visor beanie,Sullen visor beanies", + "meta_description" : "Sullen Deanie - Surf style with Sullen Beanies available now at Zephyr Sports. Get your Sullen hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Sullen Beanies on Sale at Zephyr Today", + "head_title" : "Sullen Beanie | Sullen Hat | Sullen Beanies" + }, + ".markerupgrades.tippmann.model98customandpro" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "meta_keywords" : "tippmann 98 upgrades,custom 98 upgrades,upgrades for tippmann 98 custom,custom 98 trigger,grip", + "add3_link" : "/category/scenarioupgrades.flashlights___laser_sights/", + "meta_description" : "Tippmann 98 Upgrades - Everything you need to upgrade your custom 98. From Triggers to bolts and more we have upgrades for tippmann 98 custom. Free Shipping Knowledgeable customer service", + "zoovy:banner01" : "banners/paintball/headers/tippmann_98_barrel_upgrades_header.jpg", + "buttonname_01" : "", + "banner01_link" : "/category/barrels.tippmann98/", + "banner3" : "zephyr_buttons/grips_btn001", + "buttonname_03" : "", + "add2_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_02" : "", + "banner4" : "zephyr_buttons/flashlight_btn001", + "head_title" : "Tippmann 98 Upgrades | Custom 98 Upgrades | Upgrades for Tippmann 98 Custom", + "page_title" : "Buy Tippmann Custom 98 Upgrades Online Now", + "add1_link" : "/category/barrels.tippmann98/" + }, + ".markerupgrades.grips_and_grip_panels.hybrid_paintball_grips" : {}, + ".casual_clothing.mens_clothing.sweatshirts.1_search_by_size" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_vanguard_sunglasses" : { + "meta_description" : "Smith Optics Vanguard Sunglasses - Zephyr Sports carries a complete line of Vanguard Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Vanguard Sun Glasses Online Today.", + "page_title" : "Smith Optics Vanguard Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Vanguard Sunglasses | Vanguard Smith Sunglasses Free Shipping | Buy Smith Vanguard Sun Glasses" + }, + ".casual_clothing.mens_clothing.shorts.alpinestars_shorts" : { + "meta_description" : "AlpineStars Shorts - Zephyr stocks a complete line of Alpinestars Board Shorts. Low prices, Free shipping, great customer service. Trust Zephyr for all your Alpinestars needs. ", + "page_title" : "Alpinestars Shorts with Free Shipping at Zephyr", + "head_title" : "Alpinestars Shorts | Alpinestars Board Shorts" + }, + ".markers.protopaintballguns.proto_rail_paintball_guns" : { + "meta_keywords" : "proto matrix rail, proto rail paintball guns, Proto paintball guns, 09 proto rail, pmr, ultralight rail,2012 proto rail,2011 proto rail", + "htmlvids" : "\n", + "meta_description" : "2011 Proto Rail Paintball Gun - 2012 & 2013 Proto Rail Paintball Guns from Zephyr Paintball. Entire line of Proto Paintball Guns in stock and shipping for free today.", + "top_description" : "The Proto Rail brings tournament level performance to the masses. Need an entry level tournament paintball gun that's lightweight with plenty of firepower? The Proto Rail includes boost forward technology to increasing efficiency and rate of fire.The 2012 version of the proto rail has new 3D milling, color coded o-rings for easy maintenance. The Proto rail will only operate with compressed air, Do not use a Co2 tank. Full detail and product review below\n ", + "page_title" : "Buy Proto Rail Paintball Guns On Sale Now", + "head_title" : "Proto Rail Paintball Marker| 2013 Proto Rail Paintball Guns | 2012 Proto Rail", + "description" : "The current version of the proto rail was originally released in 2011. The rail is designed for an entry level speedball player who's looking for a light and fast paintball marker, but doesn't have $500+ to spend. \n\n=2011 Proto Rail Paintball Gun Features=\nBody - The proto rail has an all aluminum body with 3d Milling to give you the look of a more expensive gun. A shiny RAIL badge on the side of the marker stands out and looks pretty good on the gun. The feedneck on the proto rail is a clamping feed that requires the use of an allen key to lock you hopper on your gun. The feedneck uses dm or matrix threads. \n\n\nGrips and Grip Frame - The grip frame is a high impact composite. Typically composite may scare people, but proto did a good job and this frame is built to last. The proto rail grip frame has a similar feel to the DM series guns. Skinnier up top by the trigger and gets fatter on the bottom as you get to the ASA. The 45 style sticky grips are pretty comfortable and maintain grip even with a little moisture.\n\n\nBarrel - The Proto rail comes stock with a 1 piece 11\" Autococker threaded barrel. The barrel has a micro honed barrel surface for increased accuracy. This is a decent entry level barrel, but you will want to upgrade to a barrel that will allow you to change the bore size easily. Examples include the deadlywind barrel as well the dye ultralight or planet eclipse shaft 2 piece barrels.\n\n\nElectronics - Break beam eyes are standard on the proto rail. No more chopping paint in the breach, vision eyes make sure a paintball is completely in the chamber before firing. The stock proto rail gun board is an led version pre-programmed with 4 modes - Semi Auto, Millenium, PSP, and full auto.\n\n\nHow's it fire? - At a max ROF of 15 BPS, not bad I'd say. The proto rail will run off of compressed air only. DO NOT use co2 as this will damage the gun. The hyper 3 reg included provides a high flow rate and easy velocity adjustable. A rubber non slip grip covers the outside of the reg. Boost forward technology was used in the proto rail. This gives you an air cushioned push on the paintball and delayed bolt speed resulting in increased efficiency and higher rates of fire. The rail runs at a low 165psi operating pressure. The bolt can be removed out the back of the gun for easy maintenance, just make sure you degas your marker first. \n\n\n=Zephyr Tech Questions and Answer=\n\n\n=Q - What barrel thread is my proto rail?=\n A - The proto rail uses an autococker threaded barrel. The stock barrel is 11\". [[Proto rail barrels]:url= /category/barrels.autococker/] starting at about $50 up through $150+ basically with paintball barrels, you get more accuracy and less weight as the price goes higher.\n\n\n=Q - Can a Proto Rail run off of co2?=\n A - No, The rail is only compatible with compressed air. The use of co2 will damage your gun and void your warranty.\n\n\n=Q - What hopper will work on my Proto Rail? Do I need electronic?=\n A - There are really only two kinds of paintball loaders - Standard (gravity feed or electronic) or the tippmann cyclone feed. The Proto rail will use any standard paintball hopper. You can get away with using a gravity feed loader on your proto rail, but we do not recommend it. You will slow up the gun significantly if you do not have an electronic loader. Any electronic loader that will feed above 15 BPS will be suitable for the proto rail paintball gun.\n\n\n=Q - I want to upgrade the stock [[Proto rail feedneck]:url= category/markerupgrades.proto_matrix_rail_upgrades.proto_rail_feed_necks/], Can I?=\n A - Yes, a feedneck is a very common upgrade on the proto rail. The stock version requires an allen key every time you want to remove your hopper. Any Dm / Matrix threaded feedneck can be purchased and installed relatively easy. Most people can do this themselves, but your local store will also do this for a nominal fee. A dm feedneck with a clamping collar is preffered\n\n\n=Q - Is the proto rail a good gun? My friend said...=\n A - Yes, proto makes a good quality paintball gun at an entry level price that you can upgrade down the road as you get better. Of course you really won't be able to compare a gun like the proto rail to a 1000+ dm or ego, but would you compare a corvette with an Impala? Hopefully not.\n\n\n=Q - My friend was talking about a pmr. Is a pmr and a proto rail the same thing?=\n A - the PMR was the original version of the rail released many years ago, The 2011 version of the proto rail is different and is not compatible with most PMR upgrades.\n\n\n=Q - Does the Proto Rail ever go on sale?=\n A - Sorry but pricing is set on the rail and we do not expect to offer any sales on these guns.\n\n\n==Previous versions of the Proto Rail==\nThe Proto rail was originally released as the PMR as well as an 09 version. Prior versions may or may not be compatible with all upgrades. Please verify and contact us to make sure the parts you want are compatible.\n\n==The Special Edition Rail - and why it's so special==\n\n\nThe Proto Rail that was released in 2007 was an extremely reliable gun for the time. A year later the Special Edition Rail was released that completely reformed the 07. Aluminum replaced the parts that were lacking structure. The back cap that was originally plastic tended to ware down very easily causing leaks and a stripped fitting. With the Special Edition Rail, an aluminum design took place giving a more durable cap that will last longer and give a good seal. Another upgrade that we find in the Special Edition Rail is the adjustable trigger that is also composed of aluminum. Having a slick edged trigger makes it easy for fast firing. One of the main upgrades on this gun is the 2 piece Proto Barrel - 14\". The barrel on the 07 Rail was a 1 piece 12\" that lacked in accuracy and distance. By having a 2 piece, 14\" barrel you gain that accuracy and distance needed for a perfect shot on any field. There are many other upgrades on the Special Edition Rail that make the gun more air efficient, reliable and performance enhanced.\n\n\n==The 2009 Proto Matrix Rail==\n\n\nThe Proto 09 Rail has a faultless design with its compact and lightweight body styling. The Ultralite frame is a work of art. All constructed from aluminum - no plastic parts on the 09 Rail. The Ultralite frame is the major upgrade on the Proto Rail. It's the most advanced and revolutionary frame in the world of paintball. The new hour-glass shape allows for maximum control and comfort. The Roller bearing trigger offers complete and total adjustment, helping you get your trigger exactly where you want it. The frame also includes an LED light which alerts you the status of your marker without having to take your eyes off the game. Changing modes has never been so easy with the Ultralite frame. Another major upgrade on this gun is the On/Off ASA. It's such a luxury of being able to turn on and off your air flow at any given time with a simple twist of a knob. Have you ever unscrewed your tank and since all the air was built up it made a loud pop noise and an o-ring went missing. Well now the On/Off designs allows a quick and simple cut off of air flow that will release immediately from the ASA making your tank easy to unscrew off your gun. No more frustration and worrying about o-rings. The regulator of the 09 Proto Rail was also redesigned giving a more air efficient setup. Being more air efficient means you gain more shots off your tank since your gun does not need to use a lot of air to operate. Dye designed the Proto Rail with the goal of providing you with tournament grade performance at a reasonable price. \n\n\n==What upgrades are available?==\n\n\nThe 09 Proto Rail is a high performance gun right out of the box. Like most high performance guns not much is needed to boost its performance, but that does not mean there are not fun upgrades available. Carbon fiber barrels are available to make your gun lighter and more accurate such as the [[DeadlyWind Barrel]:url=/category/barrels.barrels_by_manufacturer.deadly_wind_paintball_barrels/], Bolts, Boards, Feednecks, Triggers and many other upgrades are available to enhance your Rail with its performance and looks!\n\n\n==Important Facts==\n\n- Only operates on Compressed Air/Nitrogen - will NOT work with CO2\n\n\n- Autococker barrel threads for multiple barrel options\n\n\n- Lube is a requirement to keep the o-rings from cracking that can cause leaks and other damages to your gun. \n\n\nRemember to clean your gun on a regular basis. It only takes a few minutes to completely dissemble the Proto Rail. At the end of your long day of paintball take the barrel off give it a good clean down (water is ok), clean the bolt of any paint and dirt - apply a new coat of lube on the o-rings, use q-tips to clean the eyes, open grips and clean out any paint or dirt that may of slipped in. Feel free to give our gun tech a call at 877-814-4297 if you have any questions in regards to maintenance." + }, + ".2clearance.paintball_clearance_gear.clearance_air_systems" : { + "head_title" : "Sale Paintball Air Systems | Clearance Paintball Air Systems | Paintball Air Systems Sale" + }, + ".casual_clothing.mens_clothing.watches.nixon_watches.nixon_axe_watches" : {}, + ".1newitems.2009_pinokio_gear" : {}, + ".markerupgrades.smartparts.ion_xe_upgrades.ion_xe_upgrade_boards___electronics" : {}, + ".markers.azodin.azodin_blitz_paintball_guns" : { + "meta_description" : "Azodin Blitz Paintball Guns - Buy your Azodin Blitz Painball Markers Online at Zephyr Paintball for Less today. Free Shipping on Azodin Blitz Pump Trust Zephyr for all your Paintball Needs", + "top_description2" : "==Azodin Blitz Paintball Guns==\nThe fully electronic azodin blitz features a new High Performance (HP) Valve design offering a increased air efficiency, accuracy and overall performance. The azodin blitz also features the new \"Zen II Circuit Board for improved firing modes and extended battery life. Programmed with firing modes for the major circuits the azodin \"Zen II\" Circuit board allows you to easily modify your blitz at your local paintball shop with the AZ Editor. Azodin also added the innovative \"Twist Lock II\" feedneck to the Blitz to ensure a solid grip on your paintball loader whether your diving for the snake or hanging in the back row throwing paint. The blitz is a great entry level electronic paintball marker capable of throwing plenty of paintballs at your opponents. Check out all the new Features and Colors on the Azodin Blitz below! Looking for a complete Azodin Blitz package instead of just the gun? Zephyr paintball has you covered with the largest selection of Azodin Blitz Starter kits. Click the package banner above to see all of our Blitz package kits.", + "top_description" : "", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.azodin_paintball_packages/", + "description" : "=Azodin Blitz Standard Features=\n\n*Feather Striker System\n*Anti Chop Break Beam Eye System (reduces broken paint in your gun)\n*Zen II Board With Nppl Semi, Psp Ramp, CFOA Semi and Millennium Ramp\n*Low Rise Twist Lock II Feed Neck\n*Durable Aluminum Grip Frame\n*Light Weight and Low Profile Design\n*Quick Release Delrin Bolt\n*Non-Slip Rubber Grip Pannels\n*Operates on CO2 or HPA\n*Autococker threaded barrel for easy upgrades\n*ION/Impulse Thread Feedneck\n*Low Pressure Inline Regulator: Standard ASA Thread\n*Bottom ASA: Interchangeable With Rail or Dovetail Mount", + "page_title" : "Buy Azodin Blitz Paintball Guns Online On Sale Now", + "head_title" : "Azodin Blitz Paintball Guns | Azodin Blitz Painball Markers | Azodin Blitz Pump", + "prodlist_custom" : "&SORTBY=PRICE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".dye_i4_paintball_goggle_mask.paintball_blog.dye_assault_matrix_dam_paintball_gun" : { + "htmlvids" : "", + "zs11_banner_wslideshow_slide1" : "ALT=&IMG=banners%2fpaintball%2fslideshow%2fblack%2ejpg&LINK=", + "top_description" : "The Dye DAM (Dye Assault Matrix) is the hottest new scenario paintball gun from the leader in tournament paintball. The Dye Dam allows the use of either .68 cal paintballs or Tiberius Arms First Strike rounds. You also have the option to choose from mag fed operation or use a standard hopper. The video below show the [[Dye Dam]:popup=http://www.zephyrpaintball.com/category/markers.dye_matrix_paintball_guns.dye_assault_matrix_dam_paintball_guns/] shooting with a Dye Rotor which is pretty impressive. \n\n\nThe Dye Assault Matrix features a full rail system to allow you to mount sights, scopes, or any other rail mount upgrades you can think of. Switching between hopper and mag fed firing requires just a flip of a switch. The magazine holds 20 rounds in two 10 round chambers. just flip the mag around and you have an additional 10 rounds. Additional mags will be sold separately.\n\n\nThe Dam has multiple firing modes that can be accessed through a slider on the side of the gun. Choose from semi auto, 3 shot burst, or full auto when your really ready to spray the paint.\n\n\nRemoveable Locking Feedneck - Looking to only play in mag fed mode, the included cover plate will allow you to remove the feedneck completely while protecting the internals of your gun from dirt and debris.\n\n\nThe Dye assault matrix also includes an adjustable composite stock with a hidden parts compartment for your important maintenance tools and parts. The [[Dye DAM]:popup=http://www.zephyrsports.com/category/paintball.paintball_guns.dye_matrix_paintball_guns.dye_dam_paintball_guns/] will be released in multiple colors, the initial run will be Black and Dye Cam. Pricing is expected to be over $1000, but no firm price has been released yet.\n\nKeep an eye out for this new tactical killer on your local fields and be ready to duck and cover if your team is the one with the DAM.", + "zs11_banner_wslideshow_slide3" : "ALT=&IMG=banners%2fpaintball%2fslideshow%2fgreen%2ejpg&LINK=", + "zs11_banner_wslideshow_slide2" : "ALT=&IMG=banners%2fpaintball%2fslideshow%2fdyecam%2ejpg&LINK=", + "zs11_banner_wslideshow_slide4" : "ALT=&IMG=banners%2fpaintball%2fslideshow%2ftan%2ejpg&LINK=" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4037_sunglasses" : {}, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_sls_paintball_guns" : { + "meta_description" : "Ego SLS - Buy your Planet Eclipse Ego SLS Paintball Gun Online at Zephyr Paintball for Less today. Free Shipping on Eclipse SLS Ego Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Ego SLS Online On Sale Now", + "head_title" : "Ego SLS | Planet Eclipse Ego SLS Paintball Gun | Eclipse SLS Ego", + "prodlist1_header" : "Eclipse SLS Paintball Guns" + }, + ".casual_clothing.z-sunglasses.dragon_sunglasses.dragon_chrome_sunglasses" : { + "meta_keywords" : "Dragon Sunglasses,dragon eyewear,polarized dragon sunglasses,dragon optical sunglasses,dragon chrome sunglasses", + "meta_description" : "Dragon Chrome Sunglasses - Zephyr is your Dragon Eyewear outlet! Dragon Optical Sunglasses bring innovation and creativity with their many different designs! We carry most of their line of sunglasses that are built from all sizes and shapes for that perfect fit. Polarized lenses available!! check site for details!!", + "head_title" : "Dragon Chrome Sunglasses" + }, + ".paintballs.fluid_paintballs" : {}, + ".active_duty" : { + "top_description2" : "Zephyr Paintball would like to thank all Active Duty Police and Military Members. To register as an Active Duty member, just shoot us an email at activeduty@zephyrsports.com from your official email address. Sorry but Hotmail, yahoo, etc will not work. .mil, some .gov and other Official email addresses are required.\n\n\n=Please Note our Live Chat and Customer service cannot answer questions related to Active Duty, you must use activeduty@zephyrsports.com for all inquiries=", + "top_description" : "", + "head_title" : "Active Duty Military Discounts | Paintball Discounts", + "zoovy:banner01" : "banners/storewide/headers/activemilitarypolice_header01.jpg" + }, + ".2clearance.paintball_clearance_gear.clearance_jerseys___apparel.clearance_headwear.empire" : {}, + ".casual_clothing.mens_clothing.belts" : { + "meta_description" : "Mens Belts - Buy your Skate Belts At Zephyr Sports for Less Today! We carry a complete line of Mens Belt at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Mens Belts On Sale & Free Shipping", + "head_title" : "Mens Belts | Skate Belts | Mens Belt" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_scalpel_sunglasses" : { + "meta_description" : "Oakley Scalpel Sunglasses - Buy your Scalpel Oakley Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Oakley Scalpel at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Scalpel Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Scalpel Sunglasses | Scalpel Oakley Sunglasses | Oakley Scalpel" + }, + ".harnessesbags.packs___harnesses.critical_paintball_harnesses" : { + "meta_description" : "Critical Ejection Harness - Buy your Critical Paintball Harness Online at Zephyr Paintball for Less today. Free Shipping on Critical Pod Belts Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Critical Ejection Harness Online On Sale Now", + "head_title" : "Critical Ejection Harness | Critical Paintball Harness | Critical Pod Belts" + }, + ".casual_clothing.womens_clothing.ladies_tank_tops.young___restless_tank_tops" : {}, + ".loaders.valken_v-max_paintball_loaders" : { + "meta_keywords" : "valken v-max paintball loader,vmax hopper,valken v max,marpat,v-cam,black,tiger stripe,woodland paintball hopper", + "meta_description" : "Valken V-Max Paintball Loader - The hottest new loader from Valken is available at Zephyr. Get your V-max Hopper first at Zephyr with Free Shipping. The Valken V-max will revolutionize Paintball.", + "top_description" : "The Black Valken V-Max Paintball Loader is HERE!! Standard Black or an array of camo colors! Blend in and never be out of rounds w/ the V-max by Valken! Valken V-Max Paintball Loaders showcase top of the line innovations in the realm of paintball loaders. Solid BPS with a lightweight ergonomic design! Limit the fuss on the field! Valken V-Max for high-end functionality at an even more affordable price! ", + "page_title" : "Buy Valken V-Max Paintball Loader Online On Sale Now", + "head_title" : "Valken V-Max Paintball Loader | V Max Hopper | Valken V Max", + "description" : "=Valken V-Max Features=\n*30+ balls per second\n* CAPACITY - 220 ball capacity\n*SIMPLE & REFINED DESIGN - The design of the V-Max has been refined to function simply and reliably, without the need for the complex components found on many modern loaders. Fewer parts. Fewer problems.\n*ULTRA LIGHTWEIGHT - Under 1 pound with batteries.\n*SUPER FAST TOOL-LESS DISASSEMBLY - Disassembles and reassembles in seconds, so you can spend more time playing and less time cleaning at the end of the day.\n*ONE-TOUCH ON/OFF - A one-touch On/Off button and LED display make using your V-Max Loader a breeze.\n*The standard friction lid lets you quickly reload, and is transparent to let you monitor how many paintballs you have left. Easily switch to a speed-feed in seconds, no tools needed.\n*FAST BATTERY REPLACEMENT - The battery door is located on the outside of the loader, allowing for fast & easy battery replacement, without the need for disassembly." + }, + ".casual_clothing.z_unisex_clothing_accesories.lanyards.oakley_lanyards" : { + "meta_description" : "Oakley Lanyards - Buy your Oakley Stretch LanyardsAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Save on Oakley Lanyards @ Zephyr Sports", + "head_title" : "Oakley Lanyards | Oakley Stretch Lanyards" + }, + ".scenarioupgrades.scenario_apparel.camo_paintball_pants.dye_tactical_pants" : {}, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size.27" : {}, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_breadbox_sunglasses" : {}, + ".markers.jtusapaintballguns.jt_e-kast_tactical_paintball_guns" : {}, + ".3packagespecials.us_army_paintball_packages.us_army_project_salvo_paintball_gun_packages" : { + "meta_description" : "Tippmann Project Salvo - Buy your Project Salvo Paintball Online at Zephyr Paintball for Less today. Free Shipping on Project Salvo Package Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Tippmann Project Salvo Online On Sale Now", + "head_title" : "Tippmann Project Salvo | Project Salvo Paintball | Project Salvo Package" + }, + ".casual_clothing.mens_clothing.belts.element_belts" : { + "meta_keywords" : "Element Belts,Element Belt Buckle,Element Belts,Element webbed belt", + "meta_description" : "Element Belts - We carry the complete line of Element Mens Belts. With Free Shipping, Low Prices and Easy Returns, Zephyr has you covered for all you Apparel Needs", + "page_title" : "Element Belts on Sale Now!", + "head_title" : "Element Mens Belts | Aplinestars Belts" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_rambler_sunglasses" : { + "meta_description" : "Smith Optics Rambler Sunglasses - Zephyr Sports carries a complete line of Rambler Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Rambler Sun Glasses Online Today.", + "page_title" : "Smith Optics Rambler Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Rambler Sunglasses | Rambler Smith Sunglasses Free Shipping | Buy Smith Rambler Sun Glasses" + }, + ".harnessesbags.backpacks.camelback_backpacks.camelbak_womens_hydration_packs.women_s_camelbak_vista_ft_hydration_packs" : {}, + ".markerupgrades.tippmann.model98customandpro.scenarioupgrades" : {}, + ".airsoft.airsoft_guns.1_shop_by_gun_type.g3_airsoft_guns" : { + "meta_description" : "G3 Airsoft Guns - Buy your At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy G3 Airsoft GunsOn Sale & Free Shipping", + "head_title" : "G3 Airsoft Guns" + }, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_4135_heist_sunglasses" : { + "meta_description" : "Arnette Heist Sunglasses - Buy your Arnette 4135 Heist At Zephyr Sports for Less Today! We carry a complete line of Heist Arnette 4135 Sunglasses at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Arnette Heist Sunglasses On Sale & Free Shipping", + "head_title" : "Arnette Heist Sunglasses | Arnette 4135 Heist | Heist Arnette 4135 Sunglasses" + }, + ".airsoft.airsoft_guns.echo_1_airsoft_guns.specialty_echo_1_airsoft_guns" : { + "meta_keywords" : "Echo 1 Airsoft Rifles,echo 1 airsoft guns,AEG rifles,shotgun,echo 1", + "meta_description" : "Specifically designed for long range shots, these specialty airsoft rifles use high performance BB’s for better accuracy. Built for defending an objective or player by having support systems (SAW) to focus on your target. Zephyr Sports is a leading distributor of Echo 1 Airsoft guns! We carry a wide variety of Echo 1 airsoft AEG rifles, shotguns, and more! Get your Echo 1 AEG 's @ Zephyr Sports!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Echo 1 Airsoft Rifles On Sale & Free Shipping", + "head_title" : "Echo 1 Airsoft Rifles | Echo 1 Airsoft Guns | Echo 1 G36K" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_variable_power_scopes.leapers_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".harnessesbags.paintball_gear_bags.condor_tactical" : {}, + ".casual_clothing.mens_clothing.tshirts.dgk_skate_t_shirts" : { + "meta_keywords" : "DGK T Shirts,DGK shirts,free shipping,DGK TShirt", + "meta_description" : "DGK T Shirts - Zephyr carries a complete line of DGK Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "DGK T Shirts at Zephyr", + "head_title" : "DGK T Shirts | DGK Shirts | DGK TShirt" + }, + ".shop_by_brand.von_zipper" : {}, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_skyline_sunglasses" : { + "meta_description" : "Smith Optics Skyline Sunglasses - Zephyr Sports carries a complete line of Skyline Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Skyline Sun Glasses Online Today.", + "page_title" : "Smith Optics Skyline Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Skyline Sunglasses | Skyline Smith Sunglasses Free Shipping | Buy Smith Skyline Sun Glasses" + }, + ".airsoft.airsoft_guns.airsoft_electric_guns.sig_sauer_aeg_electric_airsoft_rifles" : { + "meta_keywords" : "Sig Sauer Replica Airsoft Guns,P220,P230,gas,co2 blow back,electronic airsoft rifles,Sig Sauer guns,Sig Sauer Airsoft Pistol,Sig Sauer Co2 Pistol,sig sauer airsoft,Electronic Airsoft Rifles,Sig Sauer AEG", + "meta_description" : "Sig Sauer Replica Airsoft Guns. Sig Sauer is popular for delivering reliable firearms for well over a century. Most notable, their line of pistols the P220 & P230. These airsoft versions offer both gas & co2 blow back as well as metal bodies for added realism. Spring versions are also available making their lineup perfect for children and adults or beginners to elitist. Also available are modeled after popular Sig Sauer guns. Don't forget Sig Sauer's Electronic Guns! Sig Sauer makes realistic Electronic Airsoft Rifles! Get your Sig Sauer AEG today!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Sig Sauer Airsoft Rifle On Sale & Free Shipping", + "head_title" : "Sig Sauer Airsoft Rifle | Sig Sauer Airsoft Guns | Sig Sauer Electronic Guns", + "description" : "" + }, + ".airsoft.shop_by_brand.team_sd" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Team SD | SD airsoft | TSD Rifle" + }, + ".airsoft.airsoft_upgrades.internal_airsoft_upgrades.aeg_airsoft_inner_barrels" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Inner Barrels | Classic army inner barrel | Inner Barrel Airsoft", + "description" : "==TightBore Barrels==\nAirsoft barrels come in a variety of inner bores. The standard bore for airsoft barrels is 6.08mm. This bore was originally designed to prevent jams and keep firing even if dirtied. Anything lower than a 6.08mm barrel is considered a tightbore barrel. Tightbore barrels increase the accuracy of an airsoft gun, with the most common tight bores being 6.05mm, 6.03mm and 6.01mm. Although other bores do exist, they are very rare. The 6.03mm tightbore is believed to be the ideal barrel for AEGs that have automatic or burst functionality. This barrel provides an increase in accuracy, but is still wide enough to allow airsoft BBs to fire through it in rapid succession. For snipers and semi automatic airsoft AEGs, 6.01mm barrels provide the greatest possible accuracy without changing the length of the barrel.\n\n\n==Barrel Length==\nIncreasing the length of an airsoft barrel will always increase the accuracy more than tightening the bore. Thought the tightbore barrel will make the most use of the length the BB travels through it, lengthening the barrel will allow more length for the barrel to stabilize the shot. To protect inner barrels that are longer than the outer barrels, players often attach mock silencers or lengthen the flash hider. \n\n\n==Inner Coatings==\nMost airsoft inner barrels are machine polished on the interior of the barrel. Some barrels have special coatings to make the surface have less friction and reduce the drag on the BB as it is fired. While these barrels do improve efficiency, accuracy and fps, they can also chip and wear down providing problems later on." + }, + ".airsystems.nitrogentanks" : { + "meta_keywords" : "Paintball Nitrogen Tanks, Nitrogen Paintball Tanks, Paintball Air Tanks, Nitrogen Tanks, Paintball Nitrogen, Paintball Tanks, Tanks for Paintball, Paintball Supplies, Paintball Equipment,hpa tanks", + "add3_link" : "/product/PB-PMI-684500", + "prodlist2_title" : "Featured Air Tanks", + "description2" : "Compressed air, HPA, and nitrogen Tanks are all names for a paintball compressed air tank. Compressed air is the the preferred air source for Paintball and is what is used on most field rental guns. Compressed air tanks hold compressed air at 3000 to 4500 psi. A heavy duty air compressor is required to get these pressures. Sorry, most home air compressors cannot exceed 200 psi. HPA tanks have a regulator to control the air pressure released from your tank. Compressed air will give you a more consistent and accurate shot without the spikes and freeze-ups inherent with Co2. Most high end guns (Eclipse Ego, Dye and Proto Matrix, Angel, and Invert Mini just to name a few) are meant to run off compressed air and you will void your warranty if you attempt to use Co2. \n\n\n\n\n=Aluminum air tanks=\nThe most affordable way to switch to compressed air is with an aluminum tank. Ranging from $50 to $70, these tanks are similiar in size and weight to a 20 oz Co2 tank and will provide 500-700 shots on most guns. Aluminum HPA tanks hold 3000 PSI and need to be hydro tested every 5 years. Larger aluminum tanks like the PMI 72/3000 tank are recommended to be used with a harness that will hold the tank and a remote coil due to the weight of this size tank. \n\n\n\n\n=Carbon Fiber or Fiberglass wrapped air tanks=\nThese are the tanks that you see at professional tournaments. They are a lightweight aluminum tank that is wrapped in carbon fiber or fiberglass for strangth. Wrapped tanks will hold 3000 to 5000 PSI and weigh significantly less than an aluminum tank. Prices range from $130 to $235+ due to the expense of carbon fiber wrapping. Fiber wrapped tanks are measure by ci(cubic inches of volume) and range from 45ci up to 118 ci. Shot count will range from 700 to 1800+ depending on your marker and the size of tank used.\n\n\n\n\n=Do I need a high or low pressure tank?=\nCompressed air tanks come in both high and low pressure. High pressure tanks aare typically regulated at 750-850 Psi. Low pressure tanks range from 350 to 450 Psi. If you are switching from a paintball gun that had run off of Co2 before like a Tippmann, BT or most Spyders, you will want to get a high pressure tank. Virtually all paintball guns can run off of a high pressure compressed air tank. Eclipse Dye, and Proto recommend a high pressure tank for all of their tournament markers.\n\n\n\n\n=What is hydro testing or the hydro test date on a compressed air bottle??=\nCompressed air tanks typically have to be hydro tested every 3 to 5 years. This is a safety requirement to help keep our sport as safe as possible. All of our aluminum compressed air tanks need to be hydro testing after 5 years. Our carbon fiber or fiberglass tanks will have to be tested every 3-5 years. All of our products listings explain how often you will need to hydro test you bottle. most tanks will last through multiple hydro testing periods.\n", + "banner4" : "banners/sm_promo/pmi_684500_001.png", + "page_title" : "Buy Paintball HPA Air Tanks Online On Sale Now", + "add1_link" : "/product/PB-PMI-484500BLK/", + "subcat1_header" : "", + "banner2" : "banners/sm_promo/pmi_454500_001.png", + "meta_description" : "Paintball HPA Tanks - Shop for Paintball Air Tanks online at ZephyrPaintball, the best site to shop for Paintball Compressed Air Tanks.", + "top_description" : "Finally tired of using Co2 on your paintball gun? Step up to an HPA paintball air tank. Compressed air is much better for your gun and will provide a much more consistent shot. All paintball guns that accept a paintball tank will accept a paintball HPA tank. HPA tanks come in two basica styles, aluminum like a co2 tank, or carbon fiber wrapped aluminum. Aluminum HPA tanks are much cheaper than carbon fiber and will typically run $40 - $75 and hold up to 3000 PSI. Carbon fiber tanks are actually an aluminum cylinder that has been wrapped in carbon fiber for added strength. Carbon fiber HPA tank will run $135 to 200+. Be sure to read our further writeup on paintball tanks below.", + "description" : "We recommend you use compressed air on all paintball guns as compressed air is much more consistent and reduces the wear on the internals of your paintball gun. Prices have dropped significantly on aluminum 48/3000 compressed air tanks recently, so for an extra $20 you can get compressed air. You will get a few less shots off o a 48/3000 tank compared to 20 oz co2 tank, but you still typically will get 500+ shots which is enough for most paintball games.\n\n\n\n==Frequently asked HPA paintball Tank questions==\n\n\n=Q - What do the different numbers on the tank titles mean? 48,68,3000,4500, etc?=\n A - The first number is the size of the tank in cubic inches. The larger the number, the more air it will hold, but the tank also gets heavier as the size increases. Also remember this tank will be on the back of your paintball gun, so bigger is not always better. The second number 3000 or 4500 refer to the PSI pounds per square inch the the Hpa paintball tank will hold. \n\n\n=Q - I have a $20 co2 tank, why I need to spend more on a compressed air tank?=\n A - HPA tank will give you a much more consistent shot. Co2 is in liquid form in your tank and turns to a gas (HOPEFULLY) before entering your gun. This causes very inconsistent shots and and is very harsh on the internals of your paintball gun. Also CO2 gets very cold as you shoot. If you are playing in temperatures below 50 degress you may have serious issues with your gun freezing up and shooting snow out the barrel. Compressed air can also be filled from a scuba tank with an expensive scuba fill adapter. You no longer need a bunch of co2 tanks for a day of woodsball play. You'll be able to fill your tank all day from a scuba tank.\n\n\n=Q - I live outside of the US, can I use tanks I buy from you in my country?=\n A - You will need to do a little research on your end for this. All of our paintball air tanks have a DOT Department of Transportation certification stamp. For canada, you will need to make sure the tank has a TC or transportation canada stamp. For most of europe, you will need a Pi certification. All of the descriptions on our air paintball bottles will state which certifications apply to each tank.\n\n=Q - Are Carbon fiber tanks worth the extra $100?=\n A - Thats a matter of preference, the 4500PSI HPA tanks will way roughly half of an aluminum tank making your paintball gun much lighter and more maneuverable. Also they hold 4500 PSI instead of 3000 allowing you to get a significant shot increase out of a tank fill.\n\n\n=Q - Do I need a high or low pressure air tank?=\n A - High pressure HPA tanks(750-850PSI) will work with all guns, unless your paintball guns manual specifically require a low pressure tank(3-500PSI), we do not recommend purchasing one. Even most guns that suggest a low pressure tank, you will not notice a performance difference by using a high pressure tank.\n\n\n=Q - I see some tanks are called HPA tank, some are called compressed air tanks and some are nitro tanks. Whats the difference?=\n A - These are just different names for the same tanks. HPA = High Pressure Air is just another name for compressed air. In the past people would use nitrogen to fill there tanks. This was done for a supposed performance difference, but with today's paintball gun technology, this is not need and I have not seen a player use nitrogren in many years.\n\n\n=Q - Do I need a cover on my compressed air tank?=\n A - It is not required to have a tank cover, it is just meant to protect your expensive tank and give you a better feel against your shoulder.\n\n\n\n=Q - What is a hydro date?=\n A - Paintball air tanks hold alot of pressure, A failure of a paintball bottle will injure someone. Paintball tanks need to be tested like scuba tanks every 3-5 years. Check your tank and it will tell you the year and month it was manufactured as well as how often it is required to be hydro tested. You can get your HOA tank tested at a local scuba shop or give crossfire or ninja paintball a call. It will cost 35-$45+ any shipping fees.\n\n\n=Q - You said compressed air tanks could hurt someone. Are they dangerous?=\n A - Alot of safety features are built into HPA tanks including multiple burst discs that would safely vent the air out of the tank to prevent injury.\n\n\n=Q - I have to fly to tournaments, can I take my hpa tank on the airplane?=\n A - Yes, you will need to remove the requlator from your tank and it must be in checked baggage. For full TSA rules, be sure to search for paintball on the TSA website.\n\n\n=Q - Can I use a remote coil with a paintball air tank?=\n A - Yes most paintball remote coils have a 3000 PSI burst pressure. The pressure coming our of the regulator on your air tank is below 850PSI, so even though you have a 4500 PSI tank, the pressure released from the tank will not exceed the regulator pressure.\n\n=Do I need a high or low pressure Tank?=\n\n\nWhile all guns will run on a high pressure tank, only certain guns will run on a low pressure tank. Typically your best bet is to get a high pressure tank if you have more than one Paintball Gun. \n\n\n==All compressed air tanks are shipped empty to comply with DOT regulations. Sorry but we are unable to ship full tanks==", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "banner1" : "", + "head_title" : "Paintball Compressed Air Tanks | HPA Paintball Tanks | Paintball Air Tanks", + "sortby_var" : "Brand", + "page_head" : "", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SIZE=&SHOWSKU=&SHOWQUANTITY=0&" + }, + ".safetygear.kneeelbowpads.exalt_knee___elbow_pads" : {}, + ".casual_clothing.z-sunglasses.black_flys_sunglasses.black_flys_hi_fly_sunglasses" : {}, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_fenix_paintball_gun_packages" : { + "head_title" : "Spyder Fenix Paintball Packages | 2012 Spyder Fenix Paintball Gun Packages" + }, + ".2clearance.clearance_jerseys_apparel.v-_under_20" : { + "head_title" : "Sale Paintball Clothes | Clearance Paintball Clothes | Paintball Clothes Sale" + }, + ".casual_clothing.z-sunglasses.filtrate_sunglasses.filtrate_riff_sunglasses" : {}, + ".safetygear.dye" : { + "meta_keywords" : "dye elbow pads, knee pads,dye core pads,paintball pads,chest protector,slide shorts,neck protector", + "meta_description" : "Dye Paintball Gear _ Full Line of Dye safety gear including elbow, knee, chest, neck pads and slide shorts. Zephyr Paintball your one stop shop for everything paintball", + "page_title" : "Dye Knee and Elbow Pads ship Free", + "head_title" : "Dye Paintball Pads | Dye Knee Pads | Dye Elbow Pads" + }, + ".markers.jtusapaintballguns.jt_cybrid_paintball_guns" : { + "meta_keywords" : "jt cybrid,cybrid paintball gun, paintball marker, jt usa cybrid, entry level paintball, cybrid paintball marker.", + "meta_description" : "JT Cybrid Paintball Guns - Entry level JT Cybrid packages on Sale at Zephyr Paintball now. Buy your JT Cybrid paintball marker for less with Free shipping over $100. Shop Now", + "top_description" : "Looking for an entry level paintball gun? Take a look at the JT Cybrid. The JT cybrid is a semi automatic paintball gun meaning there are no electronics. One trigger pull, one paintball. At Zephyr we will be honest with you. We mentioned that the JT Cybrid is an entry level paintball gun. The Cybrid is meant to get you out on the field and playing. You need to learn how to play the game before you spend more money on a higher end gun. That being said, the JT Cybrid is a great gun for entry level games as well as backyard and woodsball. You will get a consistent shots in a gun that is easy to maintain. The JT Cybrid comes with a Spyder threaded barrel allowing for easy upgrading since the barrel is typically the first upgrade you want to get for your gun. The JT Cybrid has a two finger trigger to increase your rate of fire and will run off of either co2 or compressed air. ", + "page_title" : "Buy JT Cybrid on Sale Shop Now", + "head_title" : "JT Cybrid Paintball Guns | JT Cybrid Packages | JT Cybrid Paintball Marker", + "description" : "At less that $50, you really can't go wrong with the JT Cybrid if if you only use for a handful of games. Most fields will charge $25+ per day just to rent gear. Zephyr has JT Cybrid packages starting at about $80 that will give you all the gear you need to play. " + }, + ".barrels.barrels_by_manufacturer.smart_parts_paintball_barrels.smart_parts_progressive_barrels" : {}, + ".shop_by_brand.ariakon" : {}, + ".empire_prophecy_paintball_loader.empire_prophecy_z2_replacement_shells" : {}, + ".airsoft.airsoft_guns.crosman_airsoft_guns" : { + "meta_description" : "Crosman Soft Air - Buy your Crosman Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of Crosman Airsoft Rifle at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Crosman Soft Air On Sale & Free Shipping", + "head_title" : "Crosman Soft Air | Crosman Airsoft Guns | Crosman Airsoft Rifle", + "description" : "" + }, + ".shop_by_brand.sandana_paintball" : {}, + ".markers.bob_long_paintball_guns.bob_long_g6r_intimidator_paintball_guns" : { + "meta_keywords" : "g6r bob long,Bob long,bob long paintball,paintball guns,Bob Long G6R,G6R Intimidator Paintball Gun,Bob long g6r,bob long g6r paintball marker,cheap bob long,paintball gun,paintball marker,paintball equipment", + "meta_description" : "G6R Bob Long Paintball Guns @ Zephyr! Full line of bob long paintball guns. The Bob Long G6R Intimidator Paintball Gun is now in stock w/ free shipping! Bob Long paintball gun accessories available! Pick up your Bob Long G6R today! Choose Zephyr for all your Paintball Equipment!", + "page_title" : "Buy Bob Long Paintball Online On Sale Now", + "head_title" : "Bob Long Paintball | G6R Bob Long | Bob Long G6R" + }, + ".markerupgrades.tippmann.a5.tippmann_a5_stocks" : { + "prodlist1_header" : "Tippmann A-5 Stocks" + }, + ".casual_clothing.mens_clothing.tshirts.contract_killer_t_shirts" : { + "meta_keywords" : "Contract Killer T Shirts,Contract Killer shirts,free shipping,Contract Killer TShirt", + "meta_description" : "Contract Killer T Shirts - Zephyr carries a complete line of Contract Killer Shirts and T Shirts at the lowest prices on the web with Free SHipping over $25 and Easy returns. Get your Alpine Stars Tshirt Today", + "page_title" : "Contract Killer T Shirts at Zephyr", + "head_title" : "Contract Killer T Shirts | Contract Killer Shirts | Contract Killer TShirt" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_plaintiff_sunglasses" : { + "meta_keywords" : "Oakley Plaintiff Sunglasses,Plaintiff oakley sunglasses,oakley Plaintiff, Plaintiff polarized sunglasses", + "meta_description" : "Oakley Plaintiff Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Plaintiff and Polarized Oakley Plaintiff Sunglasses on Sale! ", + "page_title" : "Oakley Plaintiff Sunglasses with Free Shipping", + "head_title" : "Oakley Plaintiff Sunglasses | Plaintiff Oakley Sunglassses" + }, + ".casual_clothing.womens_clothing.ladies_shirts.1-search_by_size.2-small" : {}, + ".scenarioupgrades.scenario_apparel.camo_hats" : {}, + ".shop_by_brand.angel_sports" : {}, + ".shop_by_brand.neff" : { + "top_description2" : "=Neff, Cover up!=\n\nNeff is supported by some of the biggest snowboarders, skateboarders and surfers in the world as well as key personalities across the globe because Neff clothes are cool. Neff is currently located in Ventura, California and is internationally sold in major action sports retail stores. Neff is all about having fun and bringing new vibes and steeze to the game. “We are like a gumball machine; spitting out endless flavors for the world to consume,” stated Shaun Neff when asked to describe Neff Headwear. Neff has huge plans for the future and will continue to focus on the core roots of the brand meaning, HEADWEAR, like Neff Beanies, which has always been and will continue to be the focus in spreading the Neff love. Try looking at Zephyr's wide array of Neff products like Neff clothing and Neff hats. ", + "head_title" : "Neff Clothing | Neff Beanies | Neff Clothes", + "description" : "=Neff, Cover up!=\n\n==History==\nNeff was launched in 2002 by Shaun Neff in sunny Southern California. Growing up in Cali, surrounded by the skate, surf and snow culture, Shaun always had an aspiration to be a part of the business side of the industry. Originally starting out as a clothing company, Shaun made a couple shirts and hats and hustled his Neff product out of his car. Later that year, he moved to Utah to further his education and to spread the Neff vibe. He bought bargain beanies and headbands, tagged them with Neff, and gave them to the biggest, dopest pros in the snow industry. Shaun soon realized that in order to get snow and skate pros in on the Neff movement, his company would have to focus on headwear to avoid conflict with clothing sponsor contracts. Neff was born, being the first authentic core snow and skate headwear company in the game. That's the genius behind Neff, which spread globally under a unique niche of headwear.\n\n==Neff Headwear==\nNeff Headwear ranges from conventional beanies and hats to some of the weirdest things you've ever seen. Neff headgear is high quality and professional in quality, style and feel. Try on a Neff beanie on today and you may find it so comfortable you'll never take it off, you might want to though, especially in the shower. \n\n==Neff Clothes==\nThese are some of the dopest threads on the market,man. Try on a pair of neff socks, a Neff shirt or Neff pants and you will see why all the pros swear by this product. Neff makes everything from Snow gear to surf wear so make sure to try it all!" + }, + ".airsoft.airsoft_apparel.military_patches___accesories" : {}, + ".markerupgrades.smartparts.ion" : { + "banner2" : "zephyr_buttons/barrel_btn001", + "add3_link" : "/category/markerupgrades.grips_and_grip_panels.grips_by_frame.45_grip_panel/", + "buttonname_01" : "Barrels", + "banner3" : "zephyr_buttons/feedneck_btn001", + "buttonname_03" : "grips", + "add2_link" : "/category/markerupgrades.feednecks.impulse_ion_sft_feednecks/", + "buttonname_02" : "Feednecks", + "banner4" : "zephyr_buttons/grips_btn001", + "add1_link" : "/category/barrels.smartparts/" + }, + ".paintball.paintball_goggles" : {}, + ".casual_clothing.z-sunglasses.arnette_sunglasses.arnette_rage_sunglasses" : { + "meta_keywords" : "Arnette, Arnette Polarized lenses, Arnette Sunglasses, Designer Sunglasses, Arnette Rage sunglasses", + "meta_description" : "Arnette Rage Polarized Sunglasses - Zephyr Sports now carries Arnette Designer Sunglasses! ** Arnette Polarized Lenses ** Arnette Rage Sunglasses @ Zephyr Sports!", + "head_title" : "Arnette Rage Polarized Sunglasses | Arnette Rage Sunglasses" + }, + ".harnessesbags.paintball_gear_bags.empire_gear_bags___backpacks" : { + "meta_description" : "Empire Paintball Gear Bags - Buy your Empire Backpacks Online at Zephyr Paintball for Less today. Free Shipping on Empire Bags Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Empire Paintball Gear Bags Online On Sale Now", + "head_title" : "Empire Paintball Gear Bags | Empire Backpacks | Empire Bags" + }, + ".markerupgrades.smartparts.eos_upgrades.eos_triggers" : {}, + ".casual_clothing.mens_clothing.sweatshirts.silver_sweatshirts" : { + "meta_description" : "Silver Sweatshirts - Buy your Silver Hoodies At Zephyr Sports for Less Today! We carry a complete line of Silver Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Silver Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Silver Sweatshirts | Silver Hoodies | Silver Hoody" + }, + ".casual_clothing.z-sunglasses.krooked_sunglasses" : {}, + ".markers.planet_eclipse_ego_paintball_guns.planet_eclipse_ego_lv1_paintball_guns" : { + "meta_keywords" : "Eclipse Ego,Planet Eclipse Ego LV1,Eclipse 2013 Ego,LV1,paintball,paintball marker,paintball guns,paintball gun,ego,ego lv1 paintball markers,", + "meta_description" : "Buy Planet Eclipse Ego LV1 Paintball Guns Online! Brand new 2013 Eclipse Paintball marker, the LV1 Ego takes paintball to a whole new level. The lastest and greatest addition to the Ego family, the LV1 paintball marker is loaded with features! Upgrade today with the 2013 Planet Eclipse LV1 Ego Paintball Marker!", + "zs11_banner_wslideshow_slide1" : "ALT=Planet+Eclipse+LV1+Paintball+Grips&IMG=&LINK=%2fcategory%2fmarkerupgrades%2eplanet_eclipse_lv1%2eplanet_eclipse_lv1_grips%2f", + "top_description" : "== Ego LV1. A new chapter in Planet Eclipse Ego history. ==\n\nEgo LV1 - The First Lever Valve Operated Paintball Marker. The Ego LV1 utilizes technology never before seen in a paintball marker in order to transform the way that it shoots and feels, yet still provide the robustness, hassle-free reliability and ease of maintenance that Egos are renowned for. Anyone who has had the opportunity to shoot an Ego LV1 will tell you that there has been no compromise in any way with the performance on offer from this marker. Every aspect of the Ego LV1 has been shaped to create the ultimate expression of Eclipse passion, performance and quality. There has never been such a complete and thorough overhaul of the Ego. No stone left unturned in the pursuit of perfection. It has to be felt to be believed...", + "zoovy:banner01" : "banners/paintball/slideshow/lv1_grips_slideshow_template.jpg", + "banner01_link" : "/category/markerupgrades.planet_eclipse_lv1.planet_eclipse_lv1_grips/", + "description" : "= Ego LV1 Features =\n* Unique Lever Valve Mechanism\n* Zick3 Rammer System\n* Heavy and Light Zick3 Rammer Included\n* Cure5 Bolt\n* Internal LPR\n* SL4 Inline Regulator\n* AT Pipe Gas Transfer System\n* High Flow Onion Valve\n* Shielded Valve Spring\n* AT POPS\n* 40% Larger Valve Chamber\n* 65-80psi LPR Pressure\n* 120-135psi Inline Pressure\n* Contoured Grip and Console\n* HiGrip Foregrip and Body Sleeve\n* Adjustable Direct Acting Solenoid Valve\n* Dual Rammer Speed Controls\n* Tool-less Bolt, Rammer and Valve Removal\n* 14.5\" Shaft4 Barrel with 0.689\" Back\n* Infra-Red Break Beam Eyes\n* Replaceable Transflective Graphic LCD Module\n* Adjustable Tru-Colour RGB LCD Backlite\n* 16-Bit Microprocessor - 16 MIPS (Million Instructions Per Second)\n* Improved Solenoid Drive Circuitry for increased Velocity Consistency\n* Menu Driven User Interface\n* Ultra-Lightweight, Single Billet 3D Machined Body (Machined in the UK)\n* Deftek Offset Feed Tube\n* Clamping Feed with Sprocket Wheel Adjustment\n* Integrated Rammer Housing\n* Integrated FRM\n* Offset Bores\n* Micro-Switch and Opto Sensor Trigger Activation\n* Dual Instrument Grade Ball-Raced Trigger\n* Dual Trigger Return Mechanisms - Magnetic and Spring Trigger\n* Integrated Audible Sounding Device\n* Ramping and Semi-Auto Modes\n* Compliant with Regulations of all Major Paintball Leagues\n* E-Portal Compatible\n* Assembled and Tested at Planet Eclipse HQ in the UK", + "htmlvids" : "", + "head_title" : "Eclipse Ego | Planet Eclipse Ego LV1 | Eclipse 2013 Ego", + "page_title" : "Buy Eclipse Ego LV1 Paintball Gun Online On Sale Now" + }, + ".markerupgrades.bob_long_upgrades.bob_long_feednecks" : { + "meta_description" : "Bob Long Feednecks - Buy your Intimidator Feed Neck Online at Zephyr Paintball for Less today. Free Shipping on Feed for Bob Long Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Bob Long Feednecks Online On Sale Now", + "head_title" : "Bob Long Feednecks | Intimidator Feed Neck | Feed for Bob Long" + }, + ".apparel.pants" : { + "meta_keywords" : "Cheap Paintball Pants, Discount Paintball Pants, Paint Ball Pants, Paintball Pants, Cheap Paintball, Discount Paintball, Paint Ball, Paintball Equipment, Paintball Supplies", + "ad3_link" : "/category/apparel.pants.dyepants.dye_c14_paintball_pants/", + "add3_link" : "/category/apparel.pants.dyepants/", + "ad2" : "banners/paintball/side_banners/exalt_v3_thrasherpants_sidebanner.jpg", + "banner4" : "banners/sm_promo/dye_09_pants_price_drop.png", + "page_title" : "Paintball Pants on Sale Now", + "3widead_title" : "Popular Paintball Pants", + "ad2_link" : "/category/apparel.pants.exalt_paintball_pants/", + "add1_link" : "/category/apparel.pants.protopants/", + "subcat1_header" : "Paintball Pants Categories", + "banner2" : "banners/sm_promo/proto_09_pants_price_drop.png", + "meta_description" : "Cheap Paintball Pants - ZephyrPaintball.com is your one stop shop for paint ball pants. From discount paintball pants to the hottest new gear from Dye, Empire and Eclipse, we have you covered with free shipping over $100", + "ad1" : "banners/paintball/side_banners/empire_bt_tht_pants_sidebanner.jpg", + "dynimage1" : "images=\nlinks=\npauses=\nblank_behavior=none\n", + "ad3" : "banners/paintball/side_banners/dye_c14_pantssidebanner.jpg", + "banner1" : "banners/09_headers/main_categories/paintball_pants_001.png", + "ad1_link" : "/category/apparel.pants.bt_paintball_pants/", + "head_title" : "Cheap Paintball Pants | Discount Paintball Pants | Paint Ball Pants", + "page_head" : "" + }, + ".airsoft.shop_by_brand.crosman_airsoft" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Crosman airsoft | Crosman airsoft guns | Crosman airsoft pistols" + }, + ".airsoft.tactical_airsoft_gear.tactical_thigh_rigs.voodoo_tactical_thigh_rigs" : {}, + ".markerupgrades.planet_eclipse_etek_upgrades.eclipse_etek_upgrade_boards" : {}, + ".airsoft.airsoft_guns.airsoft_m203_grenade_launchers_and_shells" : { + "meta_description" : "Aftermath Airsoft Guns - Buy your Aftermath Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Aftermath Spring Airsoft Gun at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Aftermath Airsoft Guns On Sale & Free Shipping", + "head_title" : "Aftermath Airsoft Guns | Aftermath Airsoft Rifles | Aftermath Spring Airsoft Gun" + }, + ".markers.tippmann.model98" : { + "banner2" : "", + "meta_keywords" : "tippmann 98 custom, tippmann 98 pro, tippmann 98, tipmann 98, tippmann 98 platinum, tippmann 98 custom pro, 98 custom pro, tippmann 98 act,custom tippmann,paintball 98 custom,tippmann custom pro,tippmann 98 custom paintball,tippman 98 custom", + "meta_description" : "Tippmann Custom 98 - The standard in field paintball guns. The Custom 98 Paintball Guns offer bulletproof performance with the ability to upgrade your marker as you improve. Get your Tippmann 98 Custom Paintball Markers at Zephyr Today", + "zoovy:banner01" : "banners/paintball/headers/packagespecials_header001", + "banner01_link" : "/category/3packagespecials.tippmann_packages.tippmann_98_paintball_packages/", + "description" : "The Tippmann Custom 98 Platinum is the ultimate beginner paintball gun that requires very little maintenance. The all-metal design makes it one of the most durable paintball guns on the market (much like the A-5). Given its all-metal construction some may think its heavy but it’s actually lighter & shorter than the A-5. The Tippmann 98 may not come with a Cyclone feed but has a standard feed neck that will allow for gravity fed & electronic hoppers. Some players prefer this over the Cyclone because they get more options that best suit their needs. Don’t worry though Cyclone lovers because the [[98 Cyclone Feed]:url= http://www.zephyrpaintball.com/product/PB-TIP-98CYCLONE] is available and easy to install. Also, like the Tippmann A5 the Tippmann Custom 98 is compatible with both Compressed Air & CO2.\n\n\n==What is ACT?==\n\n\nThe ACT – Anti-Chop Technology – ensures consistent performance using a new technology that has the front and rear bolt working independently of each other. This eliminates ball chopping and improves accuracy. Ok, so we know what it is. But how does it work? It’s a simple 3 step process. 1) If a ball is trapped, the front bolt stays in position while the rear bolt continues to cycle 2) After cycling, ball drops into position and linkage arm re-engages rear bolt 3) The shot is complete without any loss of velocity or blow back. \n\n\n==Tippmann Custom 98 Platinum Edition?==\n\n\n*Split Receiver Design, which provides easier access to internal components for simplified installation of grip upgrades and modifications \n*Secure Front Sight Spring and Trigger Pins, which makes the marker easier to service and reassemble \n*Easy-to-Remove Power Tube Design with self-sealing/locking gas line makes maintaining the marker quick and easy \n*Full Depth Pockets for ASA, which eliminates the need to loosen the ASA bolts when disassembling the marker \n*New Barrel Porting and a Matte Finish, which improves marker air efficiency and reduces reflective glare \n*Picatinny Rails, which makes adding a carry handle, scopes and other accessories a snap \n*Redesigned, Vertical Front Grip, which offers improved stability and added texture for a more secure feel \n*Redesigned Sling Mount End Cap, which allows players to easily attach a variety of different sling styles \n\n\nAlso check out the Flatline Barrel. One of the most commonly used upgrades is the Flatline due to the amazing increase in distance. The flatline is the first back spin barrel ever produced. The new Platinum Flatline quickly threads into your gun that offers picatinny railing that lines up with your Platinum Edition paintball gun.\n", + "banner2_link" : "", + "banner1" : "banners/98_header", + "top_description3" : "The tippmann custom 98 paintball gun is the standard at most paintball fields. This is due to the reliability and quality offered by the Custom 98. The tippmann 98 is your choice for an entry level low maintenance gun that has plenty of room for you to upgrade as your game improves.", + "page_title" : "Buy Tippmann Custom 98 Online On Sale Now", + "head_title" : "Tippmann Custom 98 | Custom 98 Paintball Guns | Tippmann 98 Custom Paintball Marker" + }, + ".shop_by_brand.genx_global_paintball" : {}, + ".markers.jtusapaintballguns.jt_tactical_paintball_guns" : {}, + ".casual_clothing.z_shoes_and_footwear.fallen_shoes" : {}, + ".casual_clothing.mens_clothing.sweatshirts.almost_sweatshirts" : { + "meta_description" : "Almost Sweatshirts - Buy your Almost Hoodies At Zephyr Sports for Less Today! We carry a complete line of Almost Hoody at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Almost Sweatshirt Hoodies @ Zephyr Sports", + "head_title" : "Almost Sweatshirts | Almost Hoodies | Almost Hoody" + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.1-search_by_size.1_x-small_ladies_t_shirts" : {}, + ".casual_clothing.mens_clothing.sandals.hurley_sandals" : { + "meta_description" : "Hurley Sandals - Buy your Mens Hurley Sandals At Zephyr Sports for Less Today! We carry a complete line of Hurley Flip Flops at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Hurley Sandals On Sale at Zephyr Sports", + "head_title" : "Hurley Sandals | Mens Hurley Sandals | Hurley Flip Flops" + }, + ".shop_by_brand.smart_parts_paintball" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns.beretta_gas_airsoft_guns" : { + "meta_description" : "Beretta Airsoft Guns - Buy your Beretta Airsoft PistolAt Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Beretta Airsoft Guns On Sale & Free Shipping", + "head_title" : "Beretta Airsoft Guns | Beretta Airsoft Pistol" + }, + ".casual_clothing.mens_clothing.tshirts.zero_skateboards_t-shirts" : { + "meta_keywords" : "zero t shirts,zero shirt, zero clothing, apparel,zero skate", + "meta_description" : "Zero T Shirts - Zephyr carries a complete line of Zero Shirts and clothing with low prices and free shipping.", + "page_title" : "Zero T Shirts at Zephyr", + "head_title" : "Zero T Shirts | Zero Clothing | Zero Shirts" + }, + ".harnessesbags.packs___harnesses.nxe_paintball_pod_packs" : { + "meta_keywords" : "nxe harness, nxe paintball harness, nxe pod pack, nxe elevation harness", + "meta_description" : "NXE Harness - Zephyr Paintball carries a complete line of NXE Paintball Harness. The NXE pod pack is the cadilac of pod packs. Comfort, durability and style", + "page_title" : "Buy NXE Harness Online On Sale Now", + "head_title" : "NXE Harness | NXE Paintball Harness | NXE Pod Pack" + }, + ".3packagespecials.gog_paintball_packages.envy_packages" : { + "head_title" : "Gog Envy Paintball Packages | Gog Envy Paintball Gun Packages" + }, + ".airsoft.airsoft_safety" : { + "meta_keywords" : "Airsoft masks,airsoft safety goggles,airsoft safety gear,padded vests,tactical helmets,protective gear,", + "meta_description" : "Airsoft Safety Gear - Zephyr Sports is a leading distributor of Airsoft Protective gear products! If your in the game, you have to stay protected! Check out all the Saftey equipment @ Zephyr! We have everything: airsoft masks, airsoft safety goggles, padded vests, tactical helmets, and more! For cheap protective gear, choose Zephyr!", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "head_title" : "Airsoft Safety Goggles | Airsoft Safety Glasses | Airsoft Safety Gear" + }, + ".maddog.tippmann_upgrades.tippmann_98_upgrades" : {}, + ".casual_clothing.z_unisex_clothing_accesories.watches.nixon_watches.nixon_synapse_watches" : { + "meta_keywords" : "Nixon watches,nixon Synapse watch,nixon watch,nixon Synapse chrono watch,nixon,mens watches", + "meta_description" : "Nixon Watches - Brand new Nixon Synapse Chrono Watch avaiable Now @ Zephyr! This Nixon watch features a host of high-end qualities! Search the shop, select your Nixon Watch and never ask for the time again!", + "page_title" : "Nixon Synapse Chrono Watches", + "head_title" : "Nixon Synapse Watches | Nixon Synapse Chrono Watch | Nixon 5130" + }, + ".barrels.smartparts.18___impulse__ion_paintball_barrels" : { + "meta_description" : "Impulse 2 piece Barrels - Buy your Ion Sniper Barrels Online at Zephyr Paintball for Less today. Free Shipping on Impulse Tactical Barrels Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Impulse 2 piece Barrels Online On Sale Now", + "head_title" : "Impulse 2 piece Barrels | Ion Sniper Barrels | Impulse Tactical Barrels" + }, + ".shop_by_brand.airow_gun" : {}, + ".3packagespecials.tippmann_packages.tippmann_cronus_paintball_gun_packages" : { + "meta_keywords" : "tippmann cronus kronus packages,tippmann cronus starter kits,tippmann cronus tactical package,tippman,", + "meta_description" : "Tippmann Cronus packages - Tippmann cronus starter kits for all levels. From entry level tippmann cronus packages to Sniper packages, we have you covered for all things Tippmann!", + "page_title" : "Buy Tippmann Cronus Kits Online Now", + "head_title" : "Tippmann Cronus Packages | Tippmann Cronus Starter Kits | Tippmann Cronus Package" + }, + ".goggles.vforce.v_force_grill_paintball_goggles" : { + "meta_description" : "Grill Paintball Goggles - Buy your Vforce Grill Goggles Online at Zephyr Paintball for Less today. Free Shipping on V-Force Grill Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Grill Paintball Goggles Online On Sale Now", + "head_title" : "Grill Paintball Goggles | Vforce Grill Goggles | V-Force Grill" + }, + ".markers.dye_matrix_paintball_guns.dye_nt_paintball_guns" : { + "meta_keywords" : "dye nt paintball guns, Dye NT, Dye NT Paintball Markers", + "meta_description" : "Dye NT Paintball Guns - Dye NT is the hottest new highend marker from the leader in tournament paintball. Zephyr carries a complete line of Dye NT Paintball Markers with Free Shipping.", + "page_title" : "Buy Dye NT Paintball Guns Online On Sale Now", + "head_title" : "Dye NT Paintball Guns | Dye NT | Dye NT Paintball Markers ", + "description" : "The 2010 Dye NT is here. A three year culmination of engineering and design, creating the most advanced paintball gun ever made. The Dye NT Paintball Gun takes accuracy, air efficiency, design and style to a new standard by setting a benchmark for all others to follow. Dye NT Paintball Guns are the Choice of the top tournament teams.\n\n=Dye NT Paintball Gun Features=\n*Ultralite Barrel - The industry standard for accuracy, the NT comes stock with the Ultralite 14 inch barrel.\n*Next Generation Spool Valve - The NT Boost Bolt is the culmination of over 4 years of design, research, and testing. A low mass bolt minimizing recoil is controlled by the most advanced spool valve design ever.\n*Boost Forward Technology - The patent pending Boost Forward Technology controls the speed of the bolt through its cycle, providing an initial gentle push on the ball to minimize ball breakage, and then increasing in speed to maximize efficiency and consistency.\n*Automatic Valve Shutoff - The patent pending auto shutoff instantly terminates the shot chamber volume as soon as enough air is released to fire the ball. This feature ensures no air is wasted.\n*Boost Bolts Linear Secondary Solenoid Spool - The linear, second stage solenoid spool minimizes air usage and air travel allowing the NT to function with a dwell of only 6 milliseconds.\n*Low Operating Pressure - The Dye NT standard operating pressure is a low 130psi, which results in minimal recoil and sound.\n*Eye Pipe system with Performance Detents - New durable and super-flexible detents offer supreme tenderness to the most brittle of paint. New flex-spring geometry ensures that balls will not double feed into the breech.\n*Ultimate Efficiency - Based off the industry standard 68ci /4500psi compressed air tank, the Dye NT operating at 285 fps will generate 1500 to 1700 shots, depending on bolt configuration.\n*Player Performance and Shooting Comfort - By adjusting the bolt kits shot chamber volume and air flow, the Dye NT efficiency, recoil, and sound signature can be modified to the users exact performance needs.\n" + }, + ".3packagespecials.kingman_spyder_paintball_packages.spyder_xtra_paintball_gun_packages" : { + "meta_description" : "Spyder Xtra Paintball Packages - Buy your Xtra Spyder Paintball Guns Kit Online at Zephyr Paintball for Less today. Free Shipping on Spyder Xtra Paintball Guns Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Spyder Xtra Paintball Packages Online On Sale Now", + "head_title" : "Spyder Xtra Paintball Packages | Xtra Spyder Paintball Guns Kit | Spyder Xtra Paintball Guns" + }, + ".harnessesbags.backpacks.1_shop_by_bag_style.hydration_packs" : {}, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_m9" : {}, + ".scenarioupgrades.stocks.tippmann_x_7_paintball_stocks" : {}, + ".markerupgrades.grips_and_grip_panels.dye_paintball_grips" : {}, + ".shop_by_brand.hk_army_-_pb_fashion" : { + "top_description2" : "=HK Army, A new breath=\n\n==Mission==\nBreathing new life into youth’s fashion by fusing premium quality with avant-garde style, HK clothing is at the forefront of a\nnew horizon. HK Army delivers a new era of urban/lifestyle apparel. It represents the youth of today and will always be inspired and motivated by the support of its followers. HK Paintball has a new following as well, representing the new youth of the paintball era. Paintball is a dynamic sport, with a dynamic following. Try HK army Today!", + "head_title" : "HK Army | HK Clothing | HK Paintball", + "prodlist_custom" : "&SORTBY=NONE&FORMAT=CUSTOM&SRC=&ALTERNATE=0&SHOWSKU=&SHOWQUANTITY=0&", + "description" : "==HK Army, A new breath=\n\n==Mission==\nEnveloped within the music industry, HK Army's dynamic team is dedicated to\nproducing forward-thinking designs and to connect with our demographic.\nHK Army is an apparel line powered by inclusion and positive action. Whether it’s\non the street or on the stage, you will find HK Army repping the coolest clothes. \n\n==Clothing==\nHK Clothing is durable, lightweight, fashionable and just plain dope! Throw on some new HK product today and you are sure to be repping the coolest company around. " + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_split_jacket_sunglasses" : { + "meta_description" : "Oakley Split Jacket Sunglasses - Buy your Split Jacket Oakley Sunglasses At Zephyr Sports for Less Today! We carry a complete line of Oakley Split Jacket at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Buy Oakley Split Jacket Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Split Jacket Sunglasses | Split Jacket Oakley Sunglasses | Oakley Split Jacket" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.1_search_by_size" : {}, + ".airsoft.tactical_airsoft_gear.tactical_boots" : { + "meta_keywords" : "military boots,airsoft boots,scenario boots", + "meta_description" : "Military Tactical Boots. Standard issued military grade boots; built to last and hold even under the most extreme conditions. An unbeatable value; choose from either nylon/canvas or cordura/leather. Cushioned soles and venting make these a comfortable boot especially during extended games. Choose from standard lace or speed-lace designs. ", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Military Tactical Boots On Sale at Zephyr ", + "head_title" : "Military Boots | Tactical Boots | Airsoft Boots" + }, + ".casual_clothing.z-sunglasses.oakley_sunglasses.oakley_monster_dog_sunglasses" : { + "meta_keywords" : "Oakley Polarized Sunglasses,Polarized Oakley Sunglasses,oakley mens sunglasses,oakley jacket sunglasses,Monster Dog sunglasses,oakley monster dog sunglasses,polarized monster dog sunglasses", + "meta_description" : "Oakley Monster Dog Sunglasses Now Available @ Zephyr! Get your Polarized Oakley sunglasses now! Oakley Mens sunglasses available in select styles; Oakley Monster Dog and Polarized Oakley Monster Dog Sunglasses on Sale! ", + "page_title" : "Oakley Monster Dog Sunglasses On Sale & Free Shipping", + "head_title" : "Oakley Monster Dog Sunglasses | Oakley Dog Sunglass | Oakley Iridium Monster Dogs" + }, + ".markers.dye_matrix_paintball_guns.dye_dm8_paintball_guns" : { + "meta_keywords" : "Dye DM8 paintball gun, cheap dye dm8, dye dm8 paintball marker, tournament paintball gun, dye matrix gun", + "banner1" : "banners/categories/dm8_pricedrop_header_001.jpg", + "meta_description" : "Dye DM8 Paintball Gun - The ultimate tournament paintball marker at Zephyr. Dye Matrix - the gun the pros use", + "page_title" : "Buy Dye DM8 Paintball Gun Online On Sale Now", + "head_title" : "Dye DM8 Paintball Gun | Cheap Dye DM8 | DM8 Paintball Marker" + }, + ".airsoft.airsoft_guns.cybergun_airsoft_guns" : { + "meta_description" : "Cybergun Airsoft Guns - Buy your Cyber Gun Airsoft Guns At Zephyr Sports for Less Today! We carry a complete line of Cybergun Airsoft Rifle at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Cybergun Airsoft Guns On Sale & Free Shipping", + "head_title" : "Cybergun Airsoft Guns | Cyber Gun Airsoft Guns | Cybergun Airsoft Rifle", + "description" : "" + }, + ".casual_clothing.z-sunglasses.smith_sunglasses.smith_optics_maverick_sunglasses" : { + "meta_description" : "Smith Optics Maverick Sunglasses - Zephyr Sports carries a complete line of Maverick Smith Sunglasses Free Shipping At the lowest prices on the web with free shipping and easy returns. Buy your Buy Smith Maverick Sun Glasses Online Today.", + "page_title" : "Smith Optics Maverick Sunglasses On Sale Free Shipping", + "head_title" : "Smith Optics Maverick Sunglasses | Maverick Smith Sunglasses Free Shipping | Buy Smith Maverick Sun Glasses" + }, + ".casual_clothing.mens_clothing.tank_tops.1-search_by_size.2-medium" : {}, + ".goggles.1goggle_accesories.jt_usa_goggle_accesories.jt_mask_bottoms" : { + "meta_description" : "JT Goggle Mask Bottoms - Buy your JT Goggles Online at Zephyr Paintball for Less today. Free Shipping on Mask Bottoms for JT Mask Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy JT Goggle Mask Bottoms Online On Sale Now", + "head_title" : "JT Goggle Mask Bottoms | JT Goggles | Mask Bottoms for JT Mask" + }, + ".loaders.ricochet" : {}, + ".casual_clothing.z-sunglasses.electric_sunglasses.electric_hoodlum_sunglasses" : { + "meta_description" : "Electric Hoodlum Sunglasses - Zephyr Sports carries a complete line of Electric Hoodlum Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Electric Hoodlum Online Today.", + "page_title" : "Electric Hoodlum Sunglasses On Sale Free Shipping", + "head_title" : "Electric Hoodlum Sunglasses | Electric Hoodlum Sun Glasses | Sunglasses Electric Hoodlum" + }, + ".apparel.head_bands_and_wraps.dye_paintball_head_bands_and_wraps" : { + "zoovy:banner01" : "banners/paintball/slideshow/dye_headwraps_headbands_slideshow.jpg" + }, + ".loaders.hopper_accesories.odyssey_halo_accesories.halo_rip_wheels" : { + "meta_description" : "Halo Rip Wheels - Buy your Rip Wheel for Halo B Online at Zephyr Paintball for Less today. Free Shipping on Rip Drive Upgrades Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy Halo Rip Wheels Online On Sale Now", + "head_title" : "Halo Rip Wheels | Rip Wheel for Halo B | Rip Drive Upgrades" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.airsoft_scopes.1_variable_power_scopes.nc_star_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".casual_clothing.womens_clothing.ladies_t_shirts.1-search_by_size.3_medium_ladies_t_shirts" : {}, + ".shop_by_brand.inception_designs" : { + "meta_keywords" : "inception barrels, inception paintball barrels, inception barrel backs, cheap paintball barrels, inception designs paintball barrels, inception barrel kits, inception barrel tips, barrel back, barrel tips, barrel fronts, inception paintball, full inception barrels, complete paintball barrels, raw inception barrels, matte black inception barrels", + "meta_description" : "Inception Designs Paintball Barrels - Mix and Match with Inception Paintball Barrels! Barrel tips, barrel backs, and complete barrel kits available! Buy Inception Designs Paintball Barrels today @ Zephyr Paintball!", + "page_title" : "Buy Inception Paintball Barrels Online On Sale Now", + "head_title" : "Inception Designs Paintball Barrels | Inception Paintball Barrel | Inception Paintball Barrel Backs", + "zoovy:banner01" : "banners/paintball/headers/inception_designs_header.jpg" + }, + ".markers.jtusapaintballguns" : { + "banner1" : "banners/categories/guns/jt_banner.jpg", + "description" : "" + }, + ".apparel.pants.dyepants.dye_c11_paintball_pants" : { + "meta_keywords" : "Paintball Gear,Dye Paintball pants,Dye Paintball C11 pants,Paintball Dye C11 pants,Dye Paintball,Paintball pants,Dye,Dye C11 pants,Dye pants,Dye Paintball gear,2011 Dye paintball pants,", + "meta_description" : "Dye C11 Paintball Pants - Brand New Dye Paintball Gear for the 2011 Season! New designs and colors for each pair of C11 Dye Paintball pants released. Check out the new specs on Dye C11 Paintball Pants.", + "top_description2" : "=Dye Paintball C11 Paintball Pants=\n\nThe C11 Pant is the ultimate collaboration between pro athletes, product developers, material experts and designers. Featuring a harness-stabilizing back yoke, and two new micro mesh inseam materials that provide you venting and a complete range of motion in all directions. The increased venting of the C11 Pant helps make it lighter and more comfortable. Softer, 3D contoured padding on the hips and back yoke enhance protection while improving mobility. Ballistic heavy duty nylon panels with responsive air-foam padding on hips and knees now give you the ultimate in sliding protection. All this culminates in a pant engineered to perfection. \n", + "top_description" : "", + "zoovy:banner01" : "", + "banner01_link" : "http://www.zephyrpaintball.com/results.cgis?catalog=MFG&wrapper=~zephyrsports_zephyrsportscom_20100727&root=.&keywords=c11promo&x=0&y=0", + "description" : "==Check out the Brand New Specs on Dye Paintball's C11 Line of Paintball Pants!==\n\n\n\n\n=HEAVY DUTY BALLISTIC KNEES=\n\n\nWe have continued to use the proven ballistic nylon and integrated it with flex panels around the knees to help withstand the most aggressive abuse. The C11 has an improved padded knee design that wraps around the entire knee, with additional front shin, outer shin and inseam padding. Combined with flex-panels, this design keeps up with your speed and motion without being stiff, while quilted sections of responsive air-foam add protection. This reduces the wear not only on your pants, but your joints as well. \n\n\n=FLEX KNEES=\n\n\nThe key to playing good paintball is speed, movement and protection. This is the fundamental concept with our continued refinement of our knee design. The C11 provides a maximum range of motion without being stiff, and the multi panel flexible knee design offers improved durability with movement. \n\n\n=ADJUSTABLE WAIST=\n\n\nOur adjustable waist not only allows you to change the fit of your pant, but the internal elastic belt also acts as a small, comfortable kidney belt. \n\n\n=VENTING=\n\n\nThe inseam features two vented mesh materials. Whether you are crouching, crawling, kneeling or sliding, the C11 pant breathes with you. Venting also surrounds the back yoke and padded zipper fly, extending all the way down to the knee for increased circulation. \n\n\n=DOUBLE AND TRIPLE STITCHING=\n\n\nFor a pant to be durable, it needs good stitching. The seams of the C11 are double and sometimes triple stitched for durability. It's a quality feature that adds pant longevity, so you can get a full season of use and then some. \n\n\n=PADDED AND VENTED CROTCH=\n\n\nNothing is quite as essential as a padded crotch protector. We were the first to introduce this feature to the industry years ago, and now we've made it better by utilizing responsive air-foam. Increased ventilation offers even more cooling comfort. \n\n\n=SWAB POCKET=\n\n\nHolds standard flex swabs or stick swabs. \nADJUSTABLE CUFFS: For those of you who like a tight cuff, the adjustable ankle cuffs allow the perfect fit for any type of cleat. \n\n\n=VENTED NYLON=\n\n\nThe entire back of the leg, from the knee joint down, is vented nylon. Having this large of a vented area can provide more circulation than your car's air conditioner. Well, almost. \n\n\n=REINFORCED SADDLE SEAT=\n\n\nSliding can be hard on your pants. We know this from experience and that's why we've reinforced the seat with extra nylon material. \n\n\n=HYPER-FLEX YOKE=\n\n\nThe back yoke is a crucial part of your pant. It has to move, it has to protect, and it has to keep your harness in place. Harness-stabilizing direct injection keeps your pack where you need it to be. Featuring a Hyper-Flex outer section and stretch under layer for increased movement. This dual-layer with pass through venting keeps your back side cool, preventing sweat build up and harness twist. \n\n\n=3D CONTOUR PADDING=\n\n\nDye's unique design uses compression formed foam to provide extra side protection for your hip bones and thighs while diving or sliding. \n", + "page_title" : "Dye C11 Paintball Pants | Dye Paintball Gear | 2011 Dye Paintball Pants", + "head_title" : "Dye C11 Paintball Pants | Brand New 2011 Dye Paintball Gear Available Now!" + }, + ".markerupgrades.dye_dam_upgrades_and_accessories.dye_dam_spare_magazines" : {}, + ".airsoft.airsoft_guns.airsoft_co2_guns.wg_gas_airsoft_guns" : { + "meta_description" : "WG Airsoft Guns - Buy your WG Airsoft Pistols Online At Zephyr Sports for Less Today! We carry a complete line of WG Gas Pistols at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy WG Airsoft Guns Now! On Sale & Free Shipping", + "head_title" : "WG Airsoft Guns | WG Airsoft Pistols |WG Gas Pistols" + }, + ".casual_clothing.mens_clothing.socks.neff_socks" : { + "meta_description" : "Neff Socks - Buy your Neff Skate Socks At Zephyr Sports for Less Today! We carry a complete line of Neff Mens Socks at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Neff Mens Socks at Zephyr Sports", + "head_title" : "Neff Socks | Neff Skate Socks | Neff Mens Socks" + }, + ".2clearance.skateboards.skateboard_wheels" : {}, + ".airsystems.nitrogentanks.nitroduck" : { + "meta_keywords" : "Nitro Duck Tanks, Nitro Duck Paintball, NitroDuck Paintball, Nitro Duck, Duck Tanks, NitroDuck Tanks, Nitrogen Tanks, Paintball Tanks, Paintball Nitrogen Tanks", + "meta_description" : "Nitro Duck Tanks - Shop for Nitro Duck paintball supplies and accessories online at ZephyrPaintball.com.", + "page_title" : "Buy Nitro Duck Tanks Online On Sale Now", + "head_title" : "Nitro Duck Tanks | Nitro Duck Paintball | NitroDuck Paintball", + "page_head" : "Nitro Duck Tanks - Nitro Duck Paintball - NitroDuck Paintball" + }, + ".loaders.empire.empire_halo_too_paintball_hoppers_loaders" : { + "meta_keywords" : "empire halo too,invert halo too,halo too,paintball loader,paintball hopper,halo hopper,sound activated", + "meta_description" : "Empire Halo Too Loader - Tournament performance from the invert halo too for less with free shipping. The Halo too feeds over 20BPS for under $100.", + "top_description2" : "=Empire Halo Too | Invert Halo Too=\n\nThe Empire Halo Too Loader (originally Invert Halo Too loader) is the best performing paintball loader for the money. Empire paintball cuts the cost in half compared to some of the 'top' paintball loaders yet doesn't sacrifice any performance! Entry level, tournament, or just backyard woods, this paintball loader will make this an easy choice for most players. The ultra-quiet belt drive will force-feed 20+ balls-per-second, allowing your marker to throw plenty of paint at your opponent. The Freeway Anti-Jam keeps the paintball loader from jamming and breaking paintballs, so you'll still be shooting while others are busy scraping paint. The new, matte black polycarbonate shell can withstand any hit and can easily fit 180 paintballs. The onboard computer directs the sound-activated feeding and allows you to program the Motor Speed, Microphone Sensitivity and Feed Stack monitoring. But of course, with a name like Halo, you knew you'd be getting the ultimate in paintball loader technology. Put this loader on your marker and Invert will make a believer out of you Too.", + "banner02_link" : "", + "zoovy:banner01" : "banners/paintball/headers/hopperaccessories_header001", + "banner01_link" : "/category/loaders.hopper_accesories.empire_hopper_accesories/", + "htmlvids" : "", + "head_title" : "Empire Halo Too Loader | Invert Halo Too Hopper | Halo Too", + "page_title" : "Empire Halo Too Loaders Ship Free" + }, + ".apparel.head_bands_and_wraps.blackstar_headbands___wraps" : {}, + ".skateboard_gear.skateboard_longboards.dusters_cruiser_longboards" : {}, + ".casual_clothing.mens_clothing.beanies.fmf_beanies" : { + "meta_keywords" : "Fallen beanie,Fallen hat,Fallen beanies,Fallen caps,Fallen 686,Fallen headwear,Fallen cuff visor beanie,Fallen beanie hat,Fallen visor beanie,Fallen visor beanies", + "meta_description" : "Fallen Deanie - Surf style with Fallen Beanies available now at Zephyr Sports. Get your Fallen hat with free shipping, low prices and great customer service at Zephyr today", + "page_title" : "Fallen Beanies on Sale at Zephyr Today", + "head_title" : "FMF Beanie | FMF Hat | FMF Beanies" + }, + ".casual_clothing.z-sunglasses.hoven_sunglasses.hoven_verse_sunglasses" : { + "meta_description" : "Hoven Verse Sunglasses - Zephyr Sports carries a complete line of Hoven Verse Sun Glasses At the lowest prices on the web with free shipping and easy returns. Buy your Sunglasses Hoven Verse Online Today.", + "page_title" : "Hoven Verse Sunglasses On Sale Free Shipping", + "head_title" : "Hoven Verse Sunglasses | Hoven Verse Sun Glasses | Sunglasses Hoven Verse" + }, + ".airsoft.airsoft_guns.bravo_airsoft_guns" : { + "meta_description" : "Bravo Airsoft Guns - Buy your Bravo Airsoft Rifles At Zephyr Sports for Less Today! We carry a complete line of Bravo AEG at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items.", + "page_title" : "Buy Bravo Airsoft Guns On Sale & Free Shipping", + "head_title" : "Bravo Airsoft Guns | Bravo Airsoft Rifles | Bravo AEG", + "description" : "" + }, + ".casual_clothing.mens_clothing.pants_and_jeans.volcom_pants_and_jeans" : { + "meta_description" : "Volcom Pants - Buy your Volcom JeansOnline At Zephyr Sports for Less Today! We carry a complete line of at prices that won't be beat. With Free Shipping and Hassle Free Returns, you won't be dissapointed", + "page_title" : "Volcom Pants & Jeans Ship Free", + "head_title" : "Volcom Pants | Volcom Jeans" + }, + ".3packagespecials.us_army_paintball_packages" : { + "meta_description" : "US Army Packages - Buy your US Army Package Online at Zephyr Paintball for Less today. Free Shipping on US Army Alpha Package Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy US Army Packages Online On Sale Now", + "head_title" : "US Army Packages | US Army Package | US Army Alpha Package" + }, + ".scenarioupgrades.tactical_vests.bt_tactical_vests___accessories.empire_battle_tested_vest_accessories" : {}, + ".buyers_guide.paintball.paintball_scopes_and_sights" : {}, + ".airsoft.airsoft_guns.kwa_airsoft_guns.kwa_usp" : { + "head_title" : "KWA USP Airsoft Pistols | KWA USP | USP Airsoft Pistol" + }, + ".airsoft.tactical_airsoft_gear.airsoft_scopes.1_variable_power_scopes.nikon_scopes" : { + "htmllinks" : "=Disclaimer=\nAll Airsoft replica bb Guns include a safety orange muzzle tip in accordance with federal law. any attempt to remove the orange tip is a violation of federal law. Modified Airsoft Guns will not be accepted for return or exchange. It is the consumers responsibility to verify that Airsoft Guns are legal in your state/country and local jurisdiction. We are not responsible for items confiscated in customs. You must be 18 to purchase Airsoft items." + }, + ".airsystems.tankcovers.bottle_covers_by_tank_size.68ci_bottle_covers" : { + "meta_description" : "68ci Tank Cover - Buy your 68 Tank Cover Online at Zephyr Paintball for Less today. Free Shipping on Paintball Bottle Covers Trust Zephyr for all your Paintball Needs", + "page_title" : "Buy 68ci Tank Cover Online On Sale Now", + "head_title" : "68ci Tank Cover | 68 Tank Cover | Paintball Bottle Covers" + } +} diff --git a/reference/zephyrsports_c_7col_20110209.xml b/reference/zephyrsports_c_7col_20110209.xml new file mode 100644 index 000000000..d302c5dc1 --- /dev/null +++ b/reference/zephyrsports_c_7col_20110209.xml @@ -0,0 +1,729 @@ + \ No newline at end of file diff --git a/reference/zephyrsports_c_7col_20120223.xml b/reference/zephyrsports_c_7col_20120223.xml new file mode 100644 index 000000000..9dc032ad6 --- /dev/null +++ b/reference/zephyrsports_c_7col_20120223.xml @@ -0,0 +1,707 @@ + \ No newline at end of file diff --git a/reference/zephyrsports_p_tabs_20121221.xml b/reference/zephyrsports_p_tabs_20121221.xml new file mode 100644 index 000000000..b0fa74857 --- /dev/null +++ b/reference/zephyrsports_p_tabs_20121221.xml @@ -0,0 +1,1058 @@ + \ No newline at end of file diff --git a/resources/anycontent.js b/resources/anycontent.js new file mode 100644 index 000000000..283d646b4 --- /dev/null +++ b/resources/anycontent.js @@ -0,0 +1,169 @@ +/* + +///// ANYCONTENT \\\\\ + +$("#something").anycontent({'templateID':'someTemplate'}); +$("#something").anycontent({'templateID':'someTemplate','datapointer':'appProductGet|PID'}); +$("#something").anycontent({'templateID':'someTemplate','data':someDataObject}); + +see options object below for full list of suppoerted params + +either templateID or (data or datapointer) are required. + +*/ + +(function($) { + $.widget("ui.anycontent",{ + options : { + templateID : null, //The template to be used + datapointer : null, //The data pointer in adminApp.data + data : null, //The data used to populate the template +// ** 201332 -> extendByDatapointers added as a means for having multiple data objects passed into translator at the same time. + extendByDatapointers : new Array(), //an array of datapointers. will merge all the data into one object prior to translation + translateOnly : false, //will skip any add template code. + showLoading : true, //if no data is passed and createTemplateInstance used, if true will execute show loading. + showLoadingMessage : 'Fetching content...', //message passed into showLoading. + dataAttribs : {} //will be used to set data attributes on the template [data- not data()]. + }, + + _init : function(){ +// dump("BEGIN anycontent"); + var self = this, + o = self.options, //shortcut + $t = self.element; //this is the targeted element (ex: $('#bob').anymessage() then $t is bob) +// the 'or' portion will attemplate to add a template if the ID is on the DOM. +// dump(" -> _init this.element.data(): "); dump(this.element.data()); + +// dump("anycontent params: "); dump(o); + if(o.templateID && ($._app.templates[o.templateID] || self._addNewTemplate(o.templateID))) { +// dump(" -> passed template check."); + self._anyContent(); + } + else if(o.data || (o.datapointer && !$.isEmptyObject($._app.data[o.datapointer]))) { +// dump(" -> passed data check."); dump(o.data); + self._anyContent(); + } + else { + $t.anymessage({ + persistent : true, + gMessage : true, + message:"Unable to translate. Either:
                                                                          Template ["+o.templateID+"] not specified and/or does not exist ["+typeof $._app.templates[o.templateID]+"].
                                                                          OR does not specified ["+typeof o.data+"] OR no datapointer ["+o.datapointer+"] does not exist in $._app.data "}); + } +// the template code in the controller will apply dataAttribs as data-attributes. Here, we add them as actual 'data' to preserve case and support nested values. + if(!$.isEmptyObject(o.dataAttribs)) { + $t.data(o.dataAttribs); + } + $t.data('anycontent',true); //tag as anycontent. allows $(this).data('anycontent') to be used before applying anycontent('option','destroy'); + }, //_init + + _setOption : function(option,value) { + $.Widget.prototype._setOption.apply( this, arguments ); //method already exists in widget factory, so call original. + }, +// when a template is translated, what is returned from this function is the data passed into transmogrify. allows for multiple data sets. + _getData : function() { +// dump(" _getData is running"); + var + o = this.options, + eData = {}; //extended data. (didn't use data to avoid confusion w/ o.data) + + //add all the datapointers into one object. 'may' run into issues here if keys are shared. shouldn't be too much of an issue in the admin interface. + if(o.extendByDatapointers.length) { +// dump(" -> datapointers have been extended for anycontent"); + var L = o.extendByDatapointers.length; + for(var i = 0; i < L; i += 1) { + if($._app.data[o.extendByDatapointers[i]]) { + $.extend(true,eData,$._app.data[o.extendByDatapointers[i]]) + } + } + } + + //datapointer can be set in addition to data or extendbydatapointers. added near the end to preserve integrity. + if(o.datapointer && $._app.data[o.datapointer]) {$.extend(true,eData,$._app.data[o.datapointer])} + + //data can be set in addition to datapointer or extendbydatapointers. added near the end to preserve integrity. + if(o.data) {$.extend(true,eData,o.data)} + + return eData; + }, + + + _anyContent : function() { +// dump(" -> _anyContent executed."); + var o = this.options, + r = true; // what is returned. false if not able to create template. + //isTranslated is added as a data() var to any template that's been translated. A way to globally identify if translation has already occured. +// dump(" -> _anyContent this.element.data(): "); dump(this.element.data()); + + if(o.templateID && o.datapointer && $._app.data[o.datapointer] && !o.translateOnly) { +// dump(" -> template and datapointer present. transmogrify."); + this.element.hideLoading().removeClass('loadingBG'); + this.element.append($._app.renderFunctions.transmogrify(o.dataAttribs,o.templateID,this._getData())); + this.element.data('isTranslated',true); + this.element.data('isTemplated',true); + } + else if(o.templateID && o.data && !o.translateOnly) { +// dump(" -> template and data present. transmogrify."); +// dump(" -> element.tagname: "+this.element.prop("tagName")); + if(typeof jQuery().hideLoading == 'function'){this.element.hideLoading().removeClass('loadingBG')} +// dump(" -> hideLoading has run."); + this.element.append($._app.renderFunctions.transmogrify(o.dataAttribs,o.templateID,this._getData())); +// dump(" -> transmogrified"); + this.element.data('isTranslated',true); + this.element.data('isTemplated',true); +// dump(" -> data.isTranslated set to true."); + } +//a templateID was specified, just add the instance. This likely means some process outside this plugin itself is handling translation OR a placeholder has been added and translate will occur after the dispatch. + else if(o.templateID && !o.translateOnly) { +// dump(" -> templateID specified. create Instance."); + this.element.append($._app.renderFunctions.createTemplateInstance(o.templateID,o.dataAttribs)); + this.element.data('isTemplated',true); + if(o.showLoading) { + this.element.showLoading({'message':o.showLoadingMessage}); + } + } +//if just translating because the template has already been rendered + else if(o.data) { +// dump(" -> data specified, translate selector"); + $._app.renderFunctions.translateSelector(this.element,this._getData()); + this.element.hideLoading().removeClass('loadingBG'); + this.element.data('isTranslated',true); + } +//if just translating because the template has already been rendered + else if(o.datapointer && $._app.data[o.datapointer]) { +// dump(" -> data specified, translate selector"); + $._app.renderFunctions.translateSelector(this.element,this._getData()); + this.element.hideLoading().removeClass('loadingBG'); + this.element.data('isTranslated',true); + } + else { + dump(" -> in anycontent, got to the 'else' that we never expected to get to. anycontent.options follow: ",'warn'); + dump(o); + //should never get here. error handling handled in _init before this is called. + r = false; + } + + + + return r; + }, + + _addNewTemplate : function() { + var r = false; //what's returned. true if able to create template. + var $tmp = $($._app.u.jqSelector('#',this.options.templateID)); + if($tmp.length > 0) { + $._app.model.makeTemplate($tmp,this.options.templateID); + r = true; + } + else{} //do nothing. Error will get thrown later. + return r; + }, + +//clear the contents. leave the parent. + _destroy : function(){ +// dump(" -> anycontent.destroy EXECUTED"); + this.element.intervaledEmpty(); + this.element.removeData('anycontent'); +// dump(" --> this.element.data():"); dump(this.element.data()); + } + }); // create the widget +})(jQuery); \ No newline at end of file diff --git a/resources/anyplugins.css b/resources/anyplugins.css index 83abe3248..6ab4c8353 100644 --- a/resources/anyplugins.css +++ b/resources/anyplugins.css @@ -46,7 +46,7 @@ .app-icon-fail-fatal, .app-icon-fatal, .app-icon-crashed {background-position:-204px -27px;} /* red circle flame */ .app-icon-pause, .app-icon-challenge {background-position:-232px -27px;} /* orange circle pause */ .app-icon-end {background-position:-262px -27px;} /* orange circle arrow east */ -.app-icon-skip {background-position:-291px -27px;} /* orange circle arrow northeast */ +.app-icon-skip, .app-icon-missing {background-position:-291px -27px;} /* orange circle arrow northeast */ .app-icon-status {background-position:0 -56px;} /* blue circle gear */ .app-icon-future {background-position:-29px -56px;} /* blue circle curly arrow */ @@ -96,4 +96,36 @@ /* ANYPANEL */ -fieldset.ui-widget-anypanel {border:none; padding:0; margin:0;} /* get rid of some browser defaults if fieldset is the container for anypanel. */ \ No newline at end of file +fieldset.ui-widget-anypanel {border:none; padding:0; margin:0;} /* get rid of some browser defaults if fieldset is the container for anypanel. */ + + + + + +/* ANYFILEUPLOAD */ +.fileUpload_default { + height: 45px; + border: 1px solid #ccc; + margin: 0px 0 5px 0; + } + +.fileUpload_file { + height: 45px; + width:45px; + background:url(images/file-45x45.png) no-repeat; + display:block; + } + +.ui-widget-anyupload-buttonset { + float:right; + } +/* +.ui-widget-anyupload-buttonset button.ui-button { + font-size:.65em; + height:1.6em; + } +.ui-widget-anyupload-buttonset button.ui-button .ui-button-text { + padding: 0 .7em 0 2.2em; + line-height:1.4em; + } +*/ \ No newline at end of file diff --git a/resources/crypto-md5-2.5.3.js b/resources/crypto-md5-2.5.3.js new file mode 100644 index 000000000..0a7cc3c19 --- /dev/null +++ b/resources/crypto-md5-2.5.3.js @@ -0,0 +1,17 @@ +/* + * Crypto-JS v2.5.3 + * http://code.google.com/p/crypto-js/ + * (c) 2009-2012 by Jeff Mott. All rights reserved. + * http://code.google.com/p/crypto-js/wiki/License + */ +(typeof Crypto=="undefined"||!Crypto.util)&&function(){var m=window.Crypto={},o=m.util={rotl:function(h,g){return h<>>32-g},rotr:function(h,g){return h<<32-g|h>>>g},endian:function(h){if(h.constructor==Number)return o.rotl(h,8)&16711935|o.rotl(h,24)&4278255360;for(var g=0;g0;h--)g.push(Math.floor(Math.random()*256));return g},bytesToWords:function(h){for(var g=[],i=0,a=0;i>>5]|=(h[i]&255)<< +24-a%32;return g},wordsToBytes:function(h){for(var g=[],i=0;i>>5]>>>24-i%32&255);return g},bytesToHex:function(h){for(var g=[],i=0;i>>4).toString(16)),g.push((h[i]&15).toString(16));return g.join("")},hexToBytes:function(h){for(var g=[],i=0;i>>6*(3-b)&63)):g.push("=");return g.join("")},base64ToBytes:function(h){if(typeof atob=="function")return n.stringToBytes(atob(h));for(var h=h.replace(/[^A-Z0-9+\/]/ig,""),g=[],i=0,a=0;i>> +6-a*2);return g}},m=m.charenc={};m.UTF8={stringToBytes:function(h){return n.stringToBytes(unescape(encodeURIComponent(h)))},bytesToString:function(h){return decodeURIComponent(escape(n.bytesToString(h)))}};var n=m.Binary={stringToBytes:function(h){for(var g=[],i=0;i>>24)&16711935|(b[f]<<24|b[f]>>>8)&4278255360;b[g>>>5]|=128<>>9<<4)+14]=g;for(var g=i._ff,j=i._gg,k= +i._hh,l=i._ii,f=0;f>>0,d=d+n>>>0,e=e+p>>>0,c=c+q>>>0;return o.endian([a,d,e,c])};i._ff=function(a,b,g,d,e,c,f){a=a+(b&g|~b&d)+(e>>>0)+f;return(a<>>32-c)+b};i._gg=function(a,b,g,d,e,c,f){a=a+(b&d|g&~d)+(e>>>0)+f;return(a<>>32-c)+b};i._hh=function(a,b,g,d,e,c,f){a=a+(b^g^d)+(e>>>0)+f;return(a<>> +32-c)+b};i._ii=function(a,b,g,d,e,c,f){a=a+(g^(b|~d))+(e>>>0)+f;return(a<>>32-c)+b};i._blocksize=16;i._digestsize=16})(); diff --git a/resources/images/file-45x45.png b/resources/images/file-45x45.png new file mode 100644 index 000000000..726c7f94c Binary files /dev/null and b/resources/images/file-45x45.png differ diff --git a/resources/imagesloaded-3.1.4.js b/resources/imagesloaded-3.1.4.js new file mode 100644 index 000000000..321a9f8ff --- /dev/null +++ b/resources/imagesloaded-3.1.4.js @@ -0,0 +1,7 @@ +/*! + * imagesLoaded PACKAGED v3.1.4 + * JavaScript is all like "You images are done yet or what?" + * MIT License + */ + +(function(){function e(){}function t(e,t){for(var n=e.length;n--;)if(e[n].listener===t)return n;return-1}function n(e){return function(){return this[e].apply(this,arguments)}}var i=e.prototype,r=this,o=r.EventEmitter;i.getListeners=function(e){var t,n,i=this._getEvents();if("object"==typeof e){t={};for(n in i)i.hasOwnProperty(n)&&e.test(n)&&(t[n]=i[n])}else t=i[e]||(i[e]=[]);return t},i.flattenListeners=function(e){var t,n=[];for(t=0;e.length>t;t+=1)n.push(e[t].listener);return n},i.getListenersAsObject=function(e){var t,n=this.getListeners(e);return n instanceof Array&&(t={},t[e]=n),t||n},i.addListener=function(e,n){var i,r=this.getListenersAsObject(e),o="object"==typeof n;for(i in r)r.hasOwnProperty(i)&&-1===t(r[i],n)&&r[i].push(o?n:{listener:n,once:!1});return this},i.on=n("addListener"),i.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},i.once=n("addOnceListener"),i.defineEvent=function(e){return this.getListeners(e),this},i.defineEvents=function(e){for(var t=0;e.length>t;t+=1)this.defineEvent(e[t]);return this},i.removeListener=function(e,n){var i,r,o=this.getListenersAsObject(e);for(r in o)o.hasOwnProperty(r)&&(i=t(o[r],n),-1!==i&&o[r].splice(i,1));return this},i.off=n("removeListener"),i.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},i.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},i.manipulateListeners=function(e,t,n){var i,r,o=e?this.removeListener:this.addListener,s=e?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(i=n.length;i--;)o.call(this,t,n[i]);else for(i in t)t.hasOwnProperty(i)&&(r=t[i])&&("function"==typeof r?o.call(this,i,r):s.call(this,i,r));return this},i.removeEvent=function(e){var t,n=typeof e,i=this._getEvents();if("string"===n)delete i[e];else if("object"===n)for(t in i)i.hasOwnProperty(t)&&e.test(t)&&delete i[t];else delete this._events;return this},i.removeAllListeners=n("removeEvent"),i.emitEvent=function(e,t){var n,i,r,o,s=this.getListenersAsObject(e);for(r in s)if(s.hasOwnProperty(r))for(i=s[r].length;i--;)n=s[r][i],n.once===!0&&this.removeListener(e,n.listener),o=n.listener.apply(this,t||[]),o===this._getOnceReturnValue()&&this.removeListener(e,n.listener);return this},i.trigger=n("emitEvent"),i.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},i.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},i._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},i._getEvents=function(){return this._events||(this._events={})},e.noConflict=function(){return r.EventEmitter=o,e},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return e}):"object"==typeof module&&module.exports?module.exports=e:this.EventEmitter=e}).call(this),function(e){function t(t){var n=e.event;return n.target=n.target||n.srcElement||t,n}var n=document.documentElement,i=function(){};n.addEventListener?i=function(e,t,n){e.addEventListener(t,n,!1)}:n.attachEvent&&(i=function(e,n,i){e[n+i]=i.handleEvent?function(){var n=t(e);i.handleEvent.call(i,n)}:function(){var n=t(e);i.call(e,n)},e.attachEvent("on"+n,e[n+i])});var r=function(){};n.removeEventListener?r=function(e,t,n){e.removeEventListener(t,n,!1)}:n.detachEvent&&(r=function(e,t,n){e.detachEvent("on"+t,e[t+n]);try{delete e[t+n]}catch(i){e[t+n]=void 0}});var o={bind:i,unbind:r};"function"==typeof define&&define.amd?define("eventie/eventie",o):e.eventie=o}(this),function(e,t){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","eventie/eventie"],function(n,i){return t(e,n,i)}):"object"==typeof exports?module.exports=t(e,require("eventEmitter"),require("eventie")):e.imagesLoaded=t(e,e.EventEmitter,e.eventie)}(this,function(e,t,n){function i(e,t){for(var n in t)e[n]=t[n];return e}function r(e){return"[object Array]"===d.call(e)}function o(e){var t=[];if(r(e))t=e;else if("number"==typeof e.length)for(var n=0,i=e.length;i>n;n++)t.push(e[n]);else t.push(e);return t}function s(e,t,n){if(!(this instanceof s))return new s(e,t);"string"==typeof e&&(e=document.querySelectorAll(e)),this.elements=o(e),this.options=i({},this.options),"function"==typeof t?n=t:i(this.options,t),n&&this.on("always",n),this.getImages(),a&&(this.jqDeferred=new a.Deferred);var r=this;setTimeout(function(){r.check()})}function c(e){this.img=e}function f(e){this.src=e,v[e]=this}var a=e.jQuery,u=e.console,h=u!==void 0,d=Object.prototype.toString;s.prototype=new t,s.prototype.options={},s.prototype.getImages=function(){this.images=[];for(var e=0,t=this.elements.length;t>e;e++){var n=this.elements[e];"IMG"===n.nodeName&&this.addImage(n);for(var i=n.querySelectorAll("img"),r=0,o=i.length;o>r;r++){var s=i[r];this.addImage(s)}}},s.prototype.addImage=function(e){var t=new c(e);this.images.push(t)},s.prototype.check=function(){function e(e,r){return t.options.debug&&h&&u.log("confirm",e,r),t.progress(e),n++,n===i&&t.complete(),!0}var t=this,n=0,i=this.images.length;if(this.hasAnyBroken=!1,!i)return this.complete(),void 0;for(var r=0;i>r;r++){var o=this.images[r];o.on("confirm",e),o.check()}},s.prototype.progress=function(e){this.hasAnyBroken=this.hasAnyBroken||!e.isLoaded;var t=this;setTimeout(function(){t.emit("progress",t,e),t.jqDeferred&&t.jqDeferred.notify&&t.jqDeferred.notify(t,e)})},s.prototype.complete=function(){var e=this.hasAnyBroken?"fail":"done";this.isComplete=!0;var t=this;setTimeout(function(){if(t.emit(e,t),t.emit("always",t),t.jqDeferred){var n=t.hasAnyBroken?"reject":"resolve";t.jqDeferred[n](t)}})},a&&(a.fn.imagesLoaded=function(e,t){var n=new s(this,e,t);return n.jqDeferred.promise(a(this))}),c.prototype=new t,c.prototype.check=function(){var e=v[this.img.src]||new f(this.img.src);if(e.isConfirmed)return this.confirm(e.isLoaded,"cached was confirmed"),void 0;if(this.img.complete&&void 0!==this.img.naturalWidth)return this.confirm(0!==this.img.naturalWidth,"naturalWidth"),void 0;var t=this;e.on("confirm",function(e,n){return t.confirm(e.isLoaded,n),!0}),e.check()},c.prototype.confirm=function(e,t){this.isLoaded=e,this.emit("confirm",this,t)};var v={};return f.prototype=new t,f.prototype.check=function(){if(!this.isChecked){var e=new Image;n.bind(e,"load",this),n.bind(e,"error",this),e.src=this.src,this.isChecked=!0}},f.prototype.handleEvent=function(e){var t="on"+e.type;this[t]&&this[t](e)},f.prototype.onload=function(e){this.confirm(!0,"onload"),this.unbindProxyEvents(e)},f.prototype.onerror=function(e){this.confirm(!1,"onerror"),this.unbindProxyEvents(e)},f.prototype.confirm=function(e,t){this.isConfirmed=!0,this.isLoaded=e,this.emit("confirm",this,t)},f.prototype.unbindProxyEvents=function(e){n.unbind(e.target,"load",this),n.unbind(e.target,"error",this)},s}); \ No newline at end of file diff --git a/resources/jquery-2.0.3.min.js b/resources/jquery-2.0.3.min.js new file mode 100644 index 000000000..9a85bd346 --- /dev/null +++ b/resources/jquery-2.0.3.min.js @@ -0,0 +1,6 @@ +/*! jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery.min.map +*/ +(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
                                                                          ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) +};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
                                                                          "],col:[2,"","
                                                                          "],tr:[2,"","
                                                                          "],td:[3,"","
                                                                          "],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("