1/**************************************************************************** 2Copyright (c) 2011 The Wojo Group 3 4thewojogroup.com 5simplecartjs.com 6http://github.com/thewojogroup/simplecart-js/tree/master 7 8The MIT License 9 10Permission is hereby granted, free of charge, to any person obtaining a copy 11of this software and associated documentation files (the "Software"), to deal 12in the Software without restriction, including without limitation the rights 13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14copies of the Software, and to permit persons to whom the Software is 15furnished to do so, subject to the following conditions: 16 17The above copyright notice and this permission notice shall be included in 18all copies or substantial portions of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26THE SOFTWARE. 27****************************************************************************/ 28 29var Custom="Custom",GoogleCheckout="GoogleCheckout",PayPal="PayPal",Email="Email",AustralianDollar="AUD",AUD="AUD",CanadianDollar="CAD",CAD="CAD",CzechKoruna="CZK",CZK="CZK",DanishKrone="DKK",DKK="DKK",Euro="EUR",EUR="EUR",HongKongDollar="HKD",HKD="HKD",HungarianForint="HUF",HUF="HUF",IsraeliNewSheqel="ILS",ILS="ILS",JapaneseYen="JPY",JPY="JPY",MexicanPeso="MXN",MXN="MXN",NorwegianKrone="NOK",NOK="NOK",NewZealandDollar="NZD",NZD="NZD",PolishZloty="PLN",PLN="PLN",PoundSterling="GBP",GBP="GBP",SingaporeDollar="SGD",SGD="SGD",SwedishKrona="SEK",SEK="SEK",SwissFranc="CHF",CHF="CHF",ThaiBaht="THB",THB="THB",USDollar="USD",USD="USD"; 30function Cart(){ 31 32 var me = this; 33 /* member variables */ 34 me.nextId = 1; 35 me.Version = '2.2.2'; 36 me.Shelf = null; 37 me.items = {}; 38 me.isLoaded = false; 39 me.pageIsReady = false; 40 me.quantity = 0; 41 me.total = 0; 42 me.taxRate = 0; 43 me.taxCost = 0; 44 me.shippingFlatRate = 0; 45 me.shippingTotalRate = 0; 46 me.shippingQuantityRate = 0; 47 me.shippingRate = 0; 48 me.shippingCost = 0; 49 me.currency = USD; 50 me.checkoutTo = PayPal; 51 me.email = ""; 52 me.merchantId = ""; 53 me.successUrl = null; 54 me.cancelUrl = null; 55 me.cookieDuration = 30; // default duration in days 56 me.storagePrefix = "sc_"; 57 me.MAX_COOKIE_SIZE = 4000; 58 me.cartHeaders = ['Name','Price','Quantity','Total']; 59 me.events = {}; 60 me.sandbox = false; 61 me.paypalHTTPMethod = "GET"; 62 /* 63 cart headers: 64 you can set these to which ever order you would like, and the cart will display the appropriate headers 65 and item info. any field you have for the items in the cart can be used, and 'Total' will automatically 66 be price*quantity. 67 68 there are keywords that can be used: 69 70 1) "_input" - the field will be a text input with the value set to the given field. when the user 71 changes the value, it will update the cart. this can be useful for quantity. (ie "Quantity_input") 72 73 2) "increment" - a link with "+" that will increase the item quantity by 1 74 75 3) "decrement" - a link with "-" that will decrease the item quantity by 1 76 77 4) "remove" - a link that will remove the item from the cart 78 79 5) "_image" or "Image" - the field will be an img tag with the src set to the value. You can simply use "Image" if 80 you set a field in the items called "Image". If you have a field named something else, like "Thumb", you can add 81 the "_image" to create the image tag (ie "Thumb_image"). 82 83 6) "_noHeader" - this will skip the header for that field (ie "increment_noHeader") 84 85 86 */ 87 88 89 90 91 /****************************************************** 92 add/remove items to cart 93 ******************************************************/ 94 95 me.add = function ( values ) { 96 var me=this; 97 /* load cart values if not already loaded */ 98 if( !me.pageIsReady ) { 99 me.initializeView();
100 me.update(); 101 } 102 if( !me.isLoaded ) { 103 me.load(); 104 me.update(); 105 } 106 107 var newItem = new CartItem(); 108 109 /* check to ensure arguments have been passed in */ 110 if( !arguments || arguments.length === 0 ){ 111 error( 'No values passed for item.'); 112 return null; 113 } 114 var argumentArray = arguments; 115 if( values && typeof( values ) !== 'string' && typeof( values ) !== 'number' ){ 116 argumentArray = values; 117 } 118 119 newItem.parseValuesFromArray( argumentArray ); 120 newItem.checkQuantityAndPrice(); 121 122 if( me.trigger('beforeAdd', [newItem] ) === false ){ 123 return false; 124 } 125 var isNew = true; 126 127 /* if the item already exists, update the quantity */ 128 if( me.hasItem(newItem) ) { 129 var foundItem=me.hasItem(newItem); 130 foundItem.quantity= parseInt(foundItem.quantity,10) + parseInt(newItem.quantity,10); 131 newItem = foundItem; 132 isNew = false; 133 } else { 134 me.items[newItem.id] = newItem; 135 } 136 137 me.update(); 138 me.trigger('afterAdd', [newItem,isNew] ); 139 140 return newItem; 141 142 }; 143 144 145 me.remove = function( id ){ 146 var tempArray = {}; 147 148 me.each(function(item){ 149 if( item.id !== id ){ 150 tempArray[item.id] = item; 151 } 152 }); 153 this.items = tempArray; 154 }; 155 156 me.empty = function () { 157 me.items = {}; 158 me.update(); 159 }; 160 161 /****************************************************** 162 item accessor functions 163 ******************************************************/ 164 165 me.find = function (criteria) { 166 if( !criteria ){ 167 return null; 168 } 169 170 var results = []; 171 172 me.each(function(item,x,next){ 173 174 fits = true; 175 176 me.each( criteria , function(value,j,name){ 177 if( !item[name] || item[name] != value ){ 178 fits = false; 179 } 180 }); 181 182 if( fits ){ 183 results.push( item ); 184 } 185 }); 186 return (results.length === 0 ) ? null : results; 187 }; 188 189 190 me.each = function( array , callback ){ 191 var next, 192 x=0, 193 result; 194 195 if( typeof array === 'function' ){ 196 var cb = array 197 items = me.items; 198 } else if( typeof callback === 'function' ){ 199 var cb = callback, 200 items = array; 201 } else { 202 return; 203 } 204 205 for( next in items ){ 206 if( typeof items[next] !== "function" ){ 207 result = cb.call( me , items[next] , x , next ); 208 if( result === false ){ 209 return; 210 } 211 x++; 212 } 213 } 214 215 }; 216 217 218 me.chunk = function(str, n) { 219 if (typeof n==='undefined'){ 220 n=2; 221 } 222 var result = str.match(RegExp('.{1,'+n+'}','g')); 223 return result || []; 224 }; 225 226 227 /****************************************************** 228 checkout management 229 ******************************************************/ 230 231 me.checkout = function() { 232 if( me.quantity === 0 ){ 233 error("Cart is empty"); 234 return; 235 } 236 switch( me.checkoutTo ){ 237 case PayPal: 238 me.paypalCheckout(); 239 break; 240 case GoogleCheckout: 241 me.googleCheckout(); 242 break; 243 case Email: 244 me.emailCheckout(); 245 break; 246 default: 247 me.customCheckout(); 248 break; 249 } 250 }; 251 252 me.paypalCheckout = function() { 253 254 255 var form = document.createElement("form"), 256 counter=1, 257 current, 258 item, 259 descriptionString; 260 261 form.style.display = "none"; 262 form.method = me.paypalHTTPMethod =="GET" || me.paypalHTTPMethod == "POST" ? me.paypalHTTPMethod : "GET"; 263 form.action = me.sandbox ? "https://www.sandbox.paypal.com/cgi-bin/webscr" : "https://www.paypal.com/cgi-bin/webscr"; 264 form.acceptCharset = "utf-8"; 265 266 267 // setup hidden fields 268 form.appendChild(me.createHiddenElement("cmd", "_cart")); 269 form.appendChild(me.createHiddenElement("rm", me.paypalHTTPMethod == "POST" ? "2" : "0" )); 270 form.appendChild(me.createHiddenElement("upload", "1")); 271 form.appendChild(me.createHiddenElement("business", me.email )); 272 form.appendChild(me.createHiddenElement("currency_code", "me.currency")); 273 274 if( me.taxRate ){ 275 form.appendChild(me.createHiddenElement("tax_cart",me.taxCost )); 276 } 277 278 if( me.shipping() !== 0){ 279 form.appendChild(me.createHiddenElement("handling_cart", me.shippingCost )); 280 } 281 282 if( me.successUrl ){ 283 form.appendChild(me.createHiddenElement("return", me.successUrl )); 284 } 285 286 if( me.cancelUrl ){ 287 form.appendChild(me.createHiddenElement("cancel_return", me.cancelUrl )); 288 } 289 290 291 292 me.each(function(item,iter){ 293 294 counter = iter+1; 295 296 form.appendChild( me.createHiddenElement( "item_name_" + counter, item.name ) ); 297 form.appendChild( me.createHiddenElement( "quantity_" + counter, item.quantity ) ); 298 form.appendChild( me.createHiddenElement( "amount_" + counter, item.price ) ); 299 form.appendChild( me.createHiddenElement( "item_number_" + counter, counter ) ); 300 301 var option_count = 0; 302 303 me.each( item , function( value, x , field ){
304 if( field !== "id" && field !== "price" && field !== "quantity" && field !== "name" && field !== "shipping" && option_count < 10) { 305 form.appendChild( me.createHiddenElement( "on" + option_count + "_" + counter, field ) ); 306 form.appendChild( me.createHiddenElement( "os" + option_count + "_" + counter, value ) ); 307 option_count++; 308 } 309 }); 310 311 form.appendChild( me.createHiddenElement( "option_index_" + counter, option_count) ); 312 313 }); 314 315 316 document.body.appendChild( form ); 317 form.submit(); 318 document.body.removeChild( form ); 319 320 }; 321 322 me.googleCheckout = function() { 323 var me = this; 324 325 326 if( me.currency !== USD && me.currency !== GBP ){ 327 error( "Google Checkout only allows the USD and GBP for currency."); 328 return; 329 } else if( me.merchantId === "" || me.merchantId === null || !me.merchantId ){ 330 error( "No merchant Id for google checkout supplied."); 331 return; 332 } 333 334 var form = document.createElement("form"), 335 counter=1, 336 current, 337 item, 338 descriptionString; 339 340 form.style.display = "none"; 341 form.method = "POST"; 342 form.action = "https://checkout.google.com/api/checkout/v2/checkoutForm/Merchant/" + 343 me.merchantId; 344 form.acceptCharset = "utf-8"; 345 346 me.each(function(item,iter){ 347 348 counter = iter+1; 349 350 form.appendChild( me.createHiddenElement( "item_name_" + counter, item.name ) ); 351 form.appendChild( me.createHiddenElement( "item_quantity_" + counter, item.quantity ) ); 352 form.appendChild( me.createHiddenElement( "item_price_" + counter, item.price ) ); 353 form.appendChild( me.createHiddenElement( "item_currency_" + counter, me.currency ) ); 354 form.appendChild( me.createHiddenElement( "item_tax_rate_" + counter, me.taxRate ) ); 355 form.appendChild( me.createHiddenElement( "_charset_" , "" ) ); 356 357 descriptionString = ""; 358 359 me.each( item , function( value , x , field ){ 360 361 if( field !== "id" && 362 field !== "quantity" && 363 field !== "price" ) { 364 365 descriptionString = descriptionString + ", " + field + ": " + value; 366 } 367 }); 368 369 descriptionString = descriptionString.substring( 1 ); 370 form.appendChild( me.createHiddenElement( "item_description_" + counter, descriptionString) ); 371 372 }); 373 374 // hack for adding shipping 375 if( me.shipping() !== 0){ 376 form.appendChild(me.createHiddenElement("ship_method_name_1", "Shipping")); 377 form.appendChild(me.createHiddenElement("ship_method_price_1", parseFloat(me.shippingCost).toFixed(2))); 378 form.appendChild(me.createHiddenElement("ship_method_currency_1", me.currency)); 379 } 380 381 document.body.appendChild( form ); 382 form.submit(); 383 document.body.removeChild( form ); 384 }; 385 386 387 388 me.emailCheckout = function() { 389 return; 390 }; 391 392 me.customCheckout = function() { 393 var me = this; 394 395 396 var form = document.createElement("form"), 397 counter=1, 398 current, 399 item, 400 descriptionString; 401 402 form.style.display = "none"; 403 form.method = "POST"; 404 form.action = me.checkoutUrl; 405 406 form.acceptCharset = "utf-8"; 407 408 409 form.appendChild( me.createHiddenElement( "actualiser", 1 ) ); 410 411 412 me.each(function(item,iter){ 413 414 counter = iter+1; 415 416 417 form.appendChild( me.createHiddenElement( "item["+counter+"][itemCode]", item.code ) ); 418 form.appendChild( me.createHiddenElement( "item["+counter+"][itemLibelle]", item.name ) ); 419 form.appendChild( me.createHiddenElement( "item["+counter+"][itemQuantite]", item.quantity ) ); 420 form.appendChild( me.createHiddenElement( "item["+counter+"][itemPrixTotal]", item.price * item.quantity) ); 421 form.appendChild( me.createHiddenElement( "item["+counter+"][itemPortTotal]", item.shipping * item.quantity ) ); 422 form.appendChild( me.createHiddenElement( "item["+counter+"][itemImage]", item.image ) ); 423 form.appendChild( me.createHiddenElement( "item["+counter+"][itemPrixUnitaire]", item.price ) ); 424 form.appendChild( me.createHiddenElement( "item["+counter+"][itemPortUnitaire]", item.shipping ) ); 425 form.appendChild( me.createHiddenElement( "item["+counter+"][itemTVA]", item.tva ) ); 426 form.appendChild( me.createHiddenElement( "item["+counter+"][itemTVAPort]", item.tvaport ) ); 427 428 429 //form.appendChild( me.createHiddenElement( "item_currency_" + counter, me.currency ) ); 430 //form.appendChild( me.createHiddenElement( "item_tax_rate_" + counter, me.taxRate ) ); 431 //form.appendChild( me.createHiddenElement( "_charset_" , "" ) ); 432 433 }); 434 435 436 document.body.appendChild( form ); 437 form.submit(); 438 document.body.removeChild( form ); 439 }; 440 441 442 443
444 /****************************************************** 445 data storage and retrival 446 ******************************************************/ 447 448 /* load cart from cookie */ 449 me.load = function () { 450 var me = this, 451 id; 452 453 /* initialize variables and items array */ 454 me.items = {}; 455 me.total = 0.00; 456 me.quantity = 0; 457 458 /* retrieve item data from cookie */ 459 if( readCookie(simpleCart.storagePrefix + 'simpleCart_' + "chunks") ){ 460 var chunkCount = 1*readCookie(simpleCart.storagePrefix + 'simpleCart_' + "chunks"), 461 dataArray = [], 462 dataString = "", 463 data = "", 464 info, 465 newItem, 466 y=0; 467 if(chunkCount>0) { 468 for( y=0;y<chunkCount;y++){ 469 dataArray.push( readCookie( simpleCart.storagePrefix + 'simpleCart_' + (1 + y ) ) ); 470 } 471 472 dataString = unescape( dataArray.join("") ); 473 data = dataString.split("++"); 474 } 475 for(var x=0, xlen=data.length;x<xlen;x++){ 476 477 info = data[x].split('||'); 478 newItem = new CartItem(); 479 480 if( newItem.parseValuesFromArray( info ) ){ 481 newItem.checkQuantityAndPrice(); 482 /* store the new item in the cart */ 483 me.items[newItem.id] = newItem; 484 } 485 } 486 } 487 488 me.isLoaded = true; 489 }; 490 491 492 493 /* save cart to cookie */ 494 me.save = function () { 495 var dataString = "", 496 dataArray = [], 497 chunkCount = 0; 498 499 chunkCount = 1*readCookie(simpleCart.storagePrefix + 'simpleCart_' + "chunks"); 500 for( var j=0;j<chunkCount;j++){ 501 eraseCookie(simpleCart.storagePrefix + 'simpleCart_'+ j); 502 } 503 eraseCookie(simpleCart.storagePrefix + 'simpleCart_' + "chunks"); 504 505 506 me.each(function(item){ 507 dataString = dataString + "++" + item.print(); 508 }); 509 510 dataArray = simpleCart.chunk( dataString.substring(2) , simpleCart.MAX_COOKIE_SIZE ); 511 512 for( var x=0,xlen = dataArray.length;x<xlen;x++){ 513 createCookie(simpleCart.storagePrefix + 'simpleCart_' + (1 + x ), dataArray[x], me.cookieDuration ); 514 } 515 516 createCookie( simpleCart.storagePrefix + 'simpleCart_' + "chunks", "" + dataArray.length , me.cookieDuration ); 517 }; 518 519 520 521 /****************************************************** 522 view management 523 ******************************************************/ 524 525 me.initializeView = function() { 526 var me = this; 527 me.totalOutlets = getElementsByClassName('simpleCart_total'); 528 me.quantityOutlets = getElementsByClassName('simpleCart_quantity'); 529 me.cartDivs = getElementsByClassName('simpleCart_items'); 530 me.taxCostOutlets = getElementsByClassName('simpleCart_taxCost'); 531 me.taxRateOutlets = getElementsByClassName('simpleCart_taxRate'); 532 me.shippingCostOutlets = getElementsByClassName('simpleCart_shippingCost'); 533 me.finalTotalOutlets = getElementsByClassName('simpleCart_finalTotal'); 534 535 me.addEventToArray( getElementsByClassName('simpleCart_checkout') , simpleCart.checkout , "click"); 536 me.addEventToArray( getElementsByClassName('simpleCart_empty') , simpleCart.empty , "click" ); 537 538 me.Shelf = new Shelf(); 539 me.Shelf.readPage(); 540 541 me.pageIsReady = true; 542 543 }; 544 545 546 547 me.updateView = function() { 548 me.updateViewTotals(); 549 if( me.cartDivs && me.cartDivs.length > 0 ){ 550 me.updateCartView(); 551 } 552 }; 553 554 me.updateViewTotals = function() { 555 var outlets = [ ["quantity" , "none" ] , 556 ["total" , "currency" ] , 557 ["shippingCost" , "currency" ] , 558 ["taxCost" , "currency" ] , 559 ["taxRate" , "percentage" ] , 560 ["finalTotal" , "currency" ] ]; 561 562 for( var x=0,xlen=outlets.length; x<xlen;x++){ 563 564 var arrayName = outlets[x][0] + "Outlets", 565 outputString, 566 element; 567 568 for( var y = 0,ylen = me[ arrayName ].length; y<ylen; y++ ){ 569 switch( outlets[x][1] ){ 570 case "none": 571 outputString = "" + me[outlets[x][0]]; 572 break; 573 case "currency": 574 outputString = me.valueToCurrencyString( me[outlets[x][0]] ); 575 break; 576 case "percentage": 577 outputString = me.valueToPercentageString( me[outlets[x][0]] ); 578 break; 579 default: 580 outputString = "" + me[outlets[x][0]]; 581 break; 582 } 583 me[arrayName][y].innerHTML = "" + outputString; 584 } 585 } 586 }; 587 588 me.updateCartView = function() { 589 var newRows = [], 590 y,newRow,current,header,newCell,info,outputValue,option,headerInfo; 591 592 /* create headers row */ 593 newRow = document.createElement('div'); 594 for(var y=0,ylen = me.cartHeaders.length; y<ylen; y++ ){ 595 newCell = document.createElement('div'); 596 headerInfo = me.cartHeaders[y].split("_"); 597 598 newCell.innerHTML = me.print( headerInfo[0] ); 599 newCell.className = "item" + headerInfo[0]; 600 for(var z=1,zlen=headerInfo.length;z<zlen;z++){ 601 if( headerInfo[z].toLowerCase() == "noheader" ){ 602 newCell.style.display = "none"; 603 } 604 } 605 newRow.appendChild( newCell ); 606 607 } 608 newRow.className = "cartHeaders"; 609 newRows[0] = newRow; 610 611 /* create a row for each item in the cart */ 612 me.each(function(item, x){ 613 newRow = document.createElement('div'); 614 615 for(var y=0,ylen = me.cartHeaders.length; y<ylen; y++ ){ 616 newCell = document.createElement('div'); 617 info = me.cartHeaders[y].split("_"); 618 619 outputValue = me.createCartRow( info , item , outputValue ); 620 621 newCell.innerHTML = outputValue; 622 newCell.className = "item" + info[0]; 623 624 newRow.appendChild( newCell ); 625 } 626 newRow.className = "itemContainer"; 627 newRows[x+1] = newRow; 628 }); 629 630 631 632 for( var x=0,xlen=me.cartDivs.length; x<xlen; x++){ 633 634 /* delete current rows in div */ 635 var div = me.cartDivs[x]; 636 if( div.childNodes && div.appendChild ){ 637 while( div.childNodes[0] ){ 638 div.removeChild( div.childNodes[0] ); 639 } 640 641
642 for(var j=0, jLen = newRows.length; j<jLen; j++){ 643 div.appendChild( newRows[j] ); 644 } 645 } 646 647 } 648 }; 649 650 me.createCartRow = function( info , item , outputValue ){ 651 652 switch( info[0].toLowerCase() ){ 653 case "total": 654 outputValue = me.valueToCurrencyString(parseFloat(item.price)*parseInt(item.quantity,10) ); 655 break; 656 case "increment": 657 outputValue = me.valueToLink( "+" , "javascript:;" , "onclick=\"simpleCart.items[\'" + item.id + "\'].increment();\"" ); 658 break; 659 case "decrement": 660 outputValue = me.valueToLink( "-" , "javascript:;" , "onclick=\"simpleCart.items[\'" + item.id + "\'].decrement();\"" ); 661 break; 662 case "remove": 663 outputValue = me.valueToLink( "Retirer" , "javascript:;" , "onclick=\"simpleCart.items[\'" + item.id + "\'].remove();\"" ); 664 break; 665 case "price": 666 outputValue = me.valueToCurrencyString( item[ info[0].toLowerCase() ] ? item[info[0].toLowerCase()] : " " ); 667 break; 668 default: 669 outputValue = item[ info[0].toLowerCase() ] ? 670 typeof item[info[0].toLowerCase()] === 'function' ? 671 item[info[0].toLowerCase()].call(item) : 672 item[info[0].toLowerCase()] : 673 " "; 674 break; 675 } 676 677 for( var y=1,ylen=info.length;y<ylen;y++){ 678 option = info[y].toLowerCase(); 679 switch( option ){ 680 case "image": 681 case "img": 682 outputValue = me.valueToImageString( item.image ); 683 break; 684 case "input": 685 outputValue = me.valueToTextInput( outputValue , "onchange=\"simpleCart.items[\'" + item.id + "\'].set(\'" + info[0].toLowerCase() + "\' , this.value);\"" ); 686 break; 687 case "div": 688 case "span": 689 case "h1":
690 case "h2": 691 case "h3": 692 case "h4": 693 case "p": 694 outputValue = me.valueToElement( option , outputValue , "" ); 695 break; 696 case "noheader": 697 break; 698 default: 699 error( "unkown header option: " + option ); 700 break; 701 } 702 703 } 704 return outputValue; 705 }; 706 707 me.addEventToArray = function ( array , functionCall , theEvent ) { 708 var outlet, 709 element; 710 711 for(var x=0,xlen=array.length; x<xlen; x++ ){ 712 element = array[x]; 713 if( element.addEventListener ) { 714 element.addEventListener(theEvent, functionCall , false ); 715 } else if( element.attachEvent ) { 716 element.attachEvent( "on" + theEvent, functionCall ); 717 } 718 } 719 }; 720 721 722 me.createHiddenElement = function ( name , value ){ 723 var element = document.createElement("input"); 724 element.type = "hidden"; 725 element.name = name; 726 element.value = value; 727 return element; 728 }; 729 730 731 /****************************************************** 732 Event Management 733 ******************************************************/ 734 735 // bind a callback to a simpleCart event 736 me.bind = function( name , callback ){ 737 if( typeof callback !== 'function' ){ 738 return me; 739 } 740 741 742 if (me.events[name] === true ){ 743 callback.apply( me ); 744 } else if( typeof me.events[name] !== 'undefined' ){ 745 me.events[name].push( callback ); 746 } else { 747 me.events[name] = [ callback ]; 748 } 749 return me; 750 }; 751 752 753 // trigger event 754 me.trigger = function( name , options ){ 755 var returnval = true; 756 if( typeof me.events[name] !== 'undefined' && typeof me.events[name][0] === 'function'){ 757 for( var x=0,xlen=me.events[name].length; x<xlen; x++ ){ 758 returnval = me.events[name][x].apply( me , (options ? options : [] ) ); 759 } 760 } 761 if( returnval === false ){ 762 return false; 763 } else { 764 return true; 765 } 766 }; 767 768 // shortcut for ready function 769 me.ready = function( callback ){ 770 if( !callback ){ 771 me.trigger( 'ready' ); 772 me.events['ready'] = true; 773 } else { 774 me.bind( 'ready' , callback ); 775 } 776 return me; 777 }; 778 779 780 781 782 /****************************************************** 783 Currency management 784 ******************************************************/ 785 786 me.currencySymbol = function() { 787 switch(me.currency){ 788 case CHF: 789 return "CHF "; 790 case CZK: 791 return "CZK "; 792 case DKK: 793 return "DKK "; 794 case HUF: 795 return "HUF "; 796 case NOK: 797 return "NOK "; 798 case PLN: 799 return "PLN "; 800 case SEK: 801 return "SEK "; 802 case JPY: 803 return "¥"; 804 case EUR: 805 return "€"; 806 case GBP: 807 return "£"; 808 case CHF: 809 return "CHF "; 810 case THB: 811 return "฿"; 812 case USD: 813 case CAD: 814 case AUD: 815 case NZD: 816 case HKD: 817 case SGD: 818 return "$"; 819 default: 820 return ""; 821 } 822 }; 823 824 825 me.currencyStringForPaypalCheckout = function( value ){ 826 if( me.currencySymbol() == "$" ){ 827 return "$" + parseFloat( value ).toFixed(2); 828 } else { 829 return "" + parseFloat(value ).toFixed(2); 830 } 831 }; 832 833 /****************************************************** 834 Formatting 835 ******************************************************/ 836 837 838 me.valueToCurrencyString = function( value ) { 839 var val = parseFloat( value ); 840 if( isNaN(val)) 841 val = 0; 842 843 return val.toCurrency( me.currencySymbol() ); 844 }; 845 846 me.valueToPercentageString = function( value ){ 847 return parseFloat( 100*value ) + "%"; 848 }; 849 850 me.valueToImageString = function( value ){ 851 if( value.match(/<\s*img.*src\=/) ){ 852 return value; 853 } else { 854 return "<img src=\"" + value + "\" />"; 855 } 856 }; 857 858 me.valueToTextInput = function( value , html ){ 859 return "<input type=\"text\" value=\"" + value + "\" " + html + " />"; 860 }; 861 862 me.valueToLink = function( value, link, html){ 863 return "<a href=\"" + link + "\" " + html + " >" + value + "</a>"; 864 }; 865 866 me.valueToElement = function( type , value , html ){ 867 return "<" + type + " " + html + " > " + value + "</" + type + ">"; 868 }; 869 870 /****************************************************** 871 Duplicate management 872 ******************************************************/ 873 874 me.hasItem = function ( item ) { 875 var current, 876 matches, 877 field, 878 match=false; 879 880 me.each(function(testItem){ 881 882 matches = true; 883 884 me.each( item , function( value , x , field ){ 885
886 if( field !== "quantity" && field !== "id" && item[field] !== testItem[field] ){ 887 matches = false; 888 } 889 }); 890 891 if( matches ){ 892 match = testItem; 893 } 894 895 }); 896 return match; 897 }; 898 899 /****************************************************** 900 Language managment 901 ******************************************************/ 902 me.ln = { 903 "en_us": { 904 quantity: "Quantity" 905 , price: "Price" 906 , total: "Total" 907 , decrement: "Decrement" 908 , increment: "Increment" 909 , remove: "Remove" 910 , tax: "Tax" 911 , shipping: "Shipping" 912 , image: "Image" 913 } 914 }; 915 916 me.language = "en_us"; 917 918 me.print = function( input ) { 919 var me = this; 920 return me.ln[me.language] && me.ln[me.language][input.toLowerCase()] ? me.ln[me.language][input.toLowerCase()] : input; 921 922 }; 923 924 925 /****************************************************** 926 Cart Update managment 927 ******************************************************/ 928 929 me.update = function() { 930 if( !simpleCart.isLoaded ){ 931 simpleCart.load(); 932 } 933 if( !simpleCart.pageIsReady ){ 934 simpleCart.initializeView(); 935 } 936 me.updateTotals(); 937 me.updateView(); 938 me.save(); 939 }; 940 941 me.updateTotals = function() { 942 943 me.total = 0 ; 944 me.quantity = 0; 945 me.each(function(item){ 946 947 if( item.quantity < 1 ){ 948 item.remove(); 949 } else if( item.quantity !== null && item.quantity !== "undefined" ){ 950 me.quantity = parseInt(me.quantity,10) + parseInt(item.quantity,10); 951 } 952 if( item.price ){ 953 me.total = parseFloat(me.total) + parseInt(item.quantity,10)*parseFloat(item.price); 954 } 955 956 }); 957 me.shippingCost = me.shipping(); 958 me.taxCost = parseFloat(me.total)*me.taxRate; 959 me.finalTotal = me.shippingCost + me.taxCost + me.total; 960 }; 961 962 me.shipping = function(){ 963 if( parseInt(me.quantity,10)===0 ) 964 return 0; 965 var shipping = parseFloat(me.shippingFlatRate) + 966 parseFloat(me.shippingTotalRate)*parseFloat(me.total) + 967 parseFloat(me.shippingQuantityRate)*parseInt(me.quantity,10), 968 next; 969 970 me.each(function(nextItem){ 971 if( nextItem.shipping ){ 972 if( typeof nextItem.shipping == 'function' ){ 973 shipping += parseFloat(nextItem.shipping()); 974 } else { 975 shipping += parseFloat(nextItem.shipping); 976 } 977 } 978 }); 979 980 return shipping; 981 } 982 983 me.initialize = function() { 984 me.initializeView(); 985 me.load(); 986 me.update(); 987 me.ready(); 988 }; 989 990} 991 992/******************************************************************************************************** 993 * Cart Item Object 994 ********************************************************************************************************/ 995 996function CartItem() { 997 while( simpleCart.items["c" + simpleCart.nextId] ) 998 simpleCart.nextId++; 999 1000 this.id = "c" + simpleCart.nextId; 1001} 1002 1003 1004CartItem.prototype = { 1005 1006 set : function ( field , value ){ 1007 field = field.toLowerCase(); 1008 if( typeof( this[field] ) !== "function" && field !== "id" ){ 1009 value = "" + value; 1010 if( field == "quantity"){ 1011 value = value.replace( /[^(\d|\.)]*/gi , "" ); 1012 value = value.replace(/,*/gi, ""); 1013 value = parseInt(value,10); 1014 } else if( field == "price" ){ 1015 value = value.replace( /[^(\d|\.)]*/gi, ""); 1016 value = value.replace(/,*/gi , ""); 1017 value = parseFloat( value ); 1018 } 1019 if( typeof(value) == "number" && isNaN( value ) ){ 1020 error( "Improperly formatted input."); 1021 } else { 1022 if( typeof( value ) === "string" ){ 1023 if( value.match(/\~|\=/) ){ 1024 error("Special character ~ or = not allowed: " + value); 1025 } 1026 value = value.replace(/\~|\=/g, ""); 1027 } 1028 this[field] = value; 1029 this.checkQuantityAndPrice(); 1030 } 1031 } else { 1032 error( "Cannot change " + field + ", this is a reserved field."); 1033 } 1034 simpleCart.update(); 1035 }, 1036 1037 increment : function(){ 1038 this.quantity = parseInt(this.quantity,10) + 1; 1039 simpleCart.update(); 1040 }, 1041 1042 decrement : function(){ 1043 if( parseInt(this.quantity,10) < 2 ){ 1044 this.remove(); 1045 } else { 1046 this.quantity = parseInt(this.quantity,10) - 1; 1047 simpleCart.update(); 1048 } 1049 }, 1050 1051 print : function () { 1052 var returnString = '', 1053 field; 1054 simpleCart.each(this ,function(item,x,name){ 1055 returnString+= escape(name) + "=" + escape(item) + "||"; 1056 }); 1057 return returnString.substring(0,returnString.length-2); 1058 }, 1059 1060 1061 checkQuantityAndPrice : function() { 1062 1063 if( !this.quantity || this.quantity == null || this.quantity == 'undefined'){ 1064 this.quantity = 1; 1065 error('No quantity for item.'); 1066 } else { 1067 this.quantity = ("" + this.quantity).replace(/,*/gi, "" ); 1068 this.quantity = parseInt( ("" + this.quantity).replace( /[^(\d|\.)]*/gi, "") , 10); 1069 if( isNaN(this.quantity) ){ 1070 error('Quantity is not a number.'); 1071 this.quantity = 1; 1072 } 1073 } 1074 1075 if( !this.price || this.price == null || this.price == 'undefined'){ 1076 this.price=0.00; 1077 error('No price for item or price not properly formatted.'); 1078 } else { 1079 this.price = ("" + this.price).replace(/,*/gi, "" ); 1080 this.price = parseFloat( ("" + this.price).replace( /[^(\d|\.)]*/gi, "") ); 1081 if( isNaN(this.price) ){ 1082 error('Price is not a number.'); 1083 this.price = 0.00; 1084 } 1085 } 1086 }, 1087 1088 1089 parseValuesFromArray : function( array ) { 1090 if( array && array.length && array.length > 0) { 1091 for(var x=0, xlen=array.length; x<xlen;x++ ){ 1092 1093 /* ensure the pair does not have key delimeters */ 1094 array[x] = array[x].replace(/\|\|/g, "| |"); 1095 array[x] = array[x].replace(/\+\+/g, "+ +"); 1096 if( array[x].match(/\~/) ){ 1097 error("Special character ~ not allowed: " + array[x]); 1098 } 1099 array[x] = array[x].replace(/\~/g, ""); 1100 1101 1102 /* split the pair and save the unescaped values to the item */ 1103 var value = array[x].split('='); 1104 if( value.length>1 ){ 1105 if( value.length>2 ){ 1106 for(var j=2, jlen=value.length;j<jlen;j++){ 1107 value[1] = value[1] + "=" + value[j]; 1108 } 1109 } 1110 this[ unescape(value[0]).toLowerCase() ] = unescape(value[1]); 1111 } 1112 } 1113 return true; 1114 } else { 1115 return false;
1116 } 1117 }, 1118 1119 remove : function() { 1120 simpleCart.remove(this.id); 1121 simpleCart.update(); 1122 } 1123}; 1124 1125 1126 1127/******************************************************************************************************** 1128 * Shelf Object for managing items on shelf that can be added to cart 1129 ********************************************************************************************************/ 1130 1131function Shelf(){ 1132 this.items = {}; 1133} 1134Shelf.prototype = { 1135 1136 readPage : function () { 1137 this.items = {}; 1138 var newItems = getElementsByClassName( "simpleCart_shelfItem" ), 1139 newItem; 1140 me = this; 1141 1142 for( var x = 0, xlen = newItems.length; x<xlen; x++){ 1143 newItem = new ShelfItem(); 1144 me.checkChildren( newItems[x] , newItem ); 1145 me.items[newItem.id] = newItem; 1146 } 1147 }, 1148 1149 checkChildren : function ( item , newItem) { 1150 if( !item.childNodes ) 1151 return; 1152 for(var x=0;item.childNodes[x];x++){ 1153 1154 var node = item.childNodes[x]; 1155 if( node.className && node.className.match(/item_[^ ]+/) ){ 1156 1157 var data = /item_[^ ]+/.exec(node.className)[0].split("_"); 1158 1159 if( data[1] == "add" || data[1] == "Add" ){ 1160 var tempArray = []; 1161 tempArray.push( node ); 1162 var addFunction = simpleCart.Shelf.addToCart(newItem.id); 1163 simpleCart.addEventToArray( tempArray , addFunction , "click"); 1164 node.id = newItem.id; 1165 } else { 1166 newItem[data[1]] = node; 1167 } 1168 } 1169 if( node.childNodes[0] ){ 1170 this.checkChildren( node , newItem ); 1171 } 1172 } 1173 }, 1174 1175 empty : function () { 1176 this.items = {}; 1177 }, 1178 1179 1180 addToCart : function ( id ) { 1181 return function(){ 1182 if( simpleCart.Shelf.items[id]){ 1183 simpleCart.Shelf.items[id].addToCart(); 1184 } else { 1185 error( "Shelf item with id of " + id + " does not exist."); 1186 } 1187 }; 1188 } 1189}; 1190 1191 1192/******************************************************************************************************** 1193 * Shelf Item Object 1194 ********************************************************************************************************/ 1195 1196 1197function ShelfItem(){ 1198 this.id = "s" + simpleCart.nextId++; 1199} 1200 1201ShelfItem.prototype = { 1202 1203 remove : function () { 1204 simpleCart.Shelf.items[this.id] = null; 1205 }, 1206 1207 addToCart : function () { 1208 var outStrings = [], 1209 valueString, 1210 field; 1211 1212 for( field in this ){ 1213 if( typeof( this[field] ) !== "function" && field !== "id" ){ 1214 valueString = ""; 1215 1216 switch(field){ 1217 case "price": 1218 if( this[field].value ){ 1219 valueString = this[field].value; 1220 } else if( this[field].innerHTML ) { 1221 valueString = this[field].innerHTML; 1222 } 1223 /* remove all characters from price except digits and a period */ 1224 valueString = valueString.replace( /[^(\d|\.)]*/gi , "" ); 1225 valueString = valueString.replace( /,*/ , "" ); 1226 break; 1227 case "image": 1228 valueString = this[field].src; 1229 break; 1230 default: 1231 if( this[field].value ){ 1232 valueString = this[field].value; 1233 } else if( this[field].innerHTML ) { 1234 valueString = this[field].innerHTML; 1235 } else if( this[field].src ){ 1236 valueString = this[field].src; 1237 } else { 1238 valueString = this[field]; 1239 } 1240 break; 1241 } 1242 outStrings.push( field + "=" + valueString ); 1243 } 1244 } 1245 1246 simpleCart.add( outStrings ); 1247 } 1248}; 1249 1250 1251 1252/******************************************************************************************************** 1253 * Thanks to Peter-Paul Koch for these cookie functions (http://www.quirksmode.org/js/cookies.html) 1254 ********************************************************************************************************/ 1255function createCookie(name,value,days) { 1256 if (days) { 1257 var date = new Date(); 1258 date.setTime(date.getTime()+(days*24*60*60*1000)); 1259 var expires = "; expires="+date.toGMTString(); 1260 } 1261 else var expires = ""; 1262 value = value.replace(/\=/g, '~'); 1263 document.cookie = name + "=" + escape(value) + expires + "; path=/"; 1264} 1265 1266function readCookie(name) { 1267 var nameEQ = name + "="; 1268 var ca = document.cookie.split(';'); 1269 for(var i=0;i < ca.length;i++) { 1270 var c = ca[i]; 1271 while (c.charAt(0)==' ') c = c.substring(1,c.length); 1272 if (c.indexOf(nameEQ) === 0){ 1273 var value = unescape(c.substring(nameEQ.length, c.length)); 1274 return value.replace(/\~/g, '='); 1275 } 1276 } 1277 return null; 1278} 1279
1280function eraseCookie(name) { 1281 createCookie(name,"",-1); 1282} 1283 1284 1285//************************************************************************************************* 1286/* 1287 Developed by Robert Nyman, http://www.robertnyman.com 1288 Code/licensing: http://code.google.com/p/getelementsbyclassname/ 1289*/ 1290var getElementsByClassName = function (className, tag, elm){ 1291 if (document.getElementsByClassName) { 1292 getElementsByClassName = function (className, tag, elm) { 1293 elm = elm || document; 1294 var elements = elm.getElementsByClassName(className), 1295 nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null, 1296 returnElements = [], 1297 current; 1298 for(var i=0, il=elements.length; i<il; i+=1){ 1299 current = elements[i]; 1300 if(!nodeName || nodeName.test(current.nodeName)) { 1301 returnElements.push(current); 1302 } 1303 } 1304 return returnElements; 1305 }; 1306 } 1307 else if (document.evaluate) { 1308 getElementsByClassName = function (className, tag, elm) { 1309 tag = tag || "*"; 1310 elm = elm || document; 1311 var classes = className.split(" "), 1312 classesToCheck = "", 1313 xhtmlNamespace = "http://www.w3.org/1999/xhtml", 1314 namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null, 1315 returnElements = [], 1316 elements, 1317 node; 1318 for(var j=0, jl=classes.length; j<jl; j+=1){ 1319 classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]"; 1320 } 1321 try { 1322 elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null); 1323 } 1324 catch (e) { 1325 elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null); 1326 } 1327 while ((node = elements.iterateNext())) { 1328 returnElements.push(node); 1329 } 1330 return returnElements; 1331 }; 1332 } 1333 else { 1334 getElementsByClassName = function (className, tag, elm) { 1335 tag = tag || "*"; 1336 elm = elm || document; 1337 var classes = className.split(" "), 1338 classesToCheck = [], 1339 elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag), 1340 current, 1341 returnElements = [], 1342 match; 1343 for(var k=0, kl=classes.length; k<kl; k+=1){ 1344 classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)")); 1345 } 1346 for(var l=0, ll=elements.length; l<ll; l+=1){ 1347 current = elements[l]; 1348 match = false; 1349 for(var m=0, ml=classesToCheck.length; m<ml; m+=1){ 1350 match = classesToCheck[m].test(current.className); 1351 if (!match) { 1352 break; 1353 } 1354 } 1355 if (match) { 1356 returnElements.push(current); 1357 } 1358 } 1359 return returnElements; 1360 }; 1361 } 1362 return getElementsByClassName(className, tag, elm); 1363}; 1364 1365 1366/******************************************************************************************************** 1367 * Helpers 1368 ********************************************************************************************************/ 1369 1370 1371String.prototype.reverse=function(){return this.split("").reverse().join("");}; 1372Number.prototype.withCommas=function(){var x=6,y=parseFloat(this).toFixed(2).toString().reverse();while(x<y.length){y=y.substring(0,x)+","+y.substring(x);x+=4;}return y.reverse();}; 1373Number.prototype.toCurrency=function(){return this.withCommas()+(arguments[0]?arguments[0]:"$");}; 1374 1375 1376/******************************************************************************************************** 1377 * error management 1378 ********************************************************************************************************/ 1379 1380function error( message ){ 1381 try{ 1382 console.log( message ); 1383 }catch(err){ 1384 // alert( message ); 1385 } 1386} 1387 1388 1389var simpleCart = new Cart(); 1390 1391if( typeof jQuery !== 'undefined' ) $(document).ready(function(){simpleCart.initialize();}); 1392else if( typeof Prototype !== 'undefined') Event.observe( window, 'load', function(){simpleCart.initialize();}); 1393else window.onload = simpleCart.initialize;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.