1/* vim: set ts=2 sw=2 sts=2 et: */ 2/** 3 * Ajax product notification widget 4 * 5 * @category X-Cart 6 * @package Modules 7 * @subpackage Product Notification 8 * @author Ruslan R. Fazlyev <[email protected]> 9 * @version 572af17946fc92f59611bb3a27492ea64d78fd2c, v3 (xcart_4_5_5), 2012-12-20 15:15:39, product_notification_widget.js, random 10 * @link http://www.x-cart.com/ 11 * @see ____file_see____ 12 */ 13 14// Widget :: factory 15ProductNotificationWidget = function(productid, variantid, type) { 16 // Check if jQuery is used 17 if (typeof(window.jQuery) == 'undefined') { 18 return false; 19 } 20 21 // Check if widget constants defined 22 if (typeof(window.ProductNotificationWidget_CONST) == 'undefined') { 23 return false; 24 } 25 26 // Check parameters 27 if (!type || !productid) { 28 return false; 29 } 30 31 if ( 32 typeof(variantid) == 'undefined' 33 || variantid <= 0 34 ) { 35 variantid = 0; 36 } 37 38 // Get HTML widget root element 39 var rootElement = $('#' + ProductNotificationWidget_CONST.ROOT_ELEMENT_ID_PREFIX + productid + '_' + type).get(0); 40 if (!rootElement) { 41 return false; 42 } 43 44 // Create an widget object 45 if (!rootElement.productNotificationWidget) { 46 rootElement.productNotificationWidget = new ProductNotificationWidget.obj(rootElement, productid, variantid, type); 47 } 48 49 return rootElement.productNotificationWidget; 50} 51 52// Widget :: object 53ProductNotificationWidget.obj = function(rootElement, productid, variantid, type) { 54 this.rootElement = $(rootElement); 55 this.productid = productid; 56 this.variantid = variantid; 57 this.type = type; 58 59 this.init(); 60} 61 62/* 63 * Properties 64 */ 65ProductNotificationWidget.obj.prototype.rootElement = false; 66ProductNotificationWidget.obj.prototype.type = false;
67ProductNotificationWidget.obj.prototype.productid = 0; 68ProductNotificationWidget.obj.prototype.variantid = 0; 69ProductNotificationWidget.obj.prototype.inStock = 0; 70ProductNotificationWidget.obj.prototype.minAmount = 0; 71ProductNotificationWidget.obj.prototype.submitButton = false; 72ProductNotificationWidget.obj.prototype.requestButton = false; 73ProductNotificationWidget.obj.prototype.emailInput = false; 74ProductNotificationWidget.obj.prototype.isEmailInputReset = false; 75ProductNotificationWidget.obj.prototype.isEmailInputContentChanged = false; 76 77/* 78 * Methods 79 */ 80 81// Initialize widget 82ProductNotificationWidget.obj.prototype.init = function() { 83 // Define form elements 84 this.submitButton = this.rootElement.find('#' + ProductNotificationWidget_CONST.SUBMIT_BUTTON_ELEMENT_ID_PREFIX + this.productid + '_' + this.type); 85 this.submitWaiting = this.rootElement.find('#' + ProductNotificationWidget_CONST.SUBMIT_WAITING_ELEMENT_ID_PREFIX + this.productid + '_' + this.type); 86 this.emailInput = this.rootElement.find('#' + ProductNotificationWidget_CONST.EMAIL_INPUT_ELEMENT_ID_PREFIX + this.productid + '_' + this.type); 87 this.requestButton = $('#' + ProductNotificationWidget_CONST.REQUEST_BUTTON_ELEMENT_ID_PREFIX + this.productid + '_' + this.type); 88 this.messageBlock = this.rootElement.find('#' + ProductNotificationWidget_CONST.MESSAGE_ELEMENT_ID_PREFIX + this.productid + '_' + this.type); 89 90 91 // Define email input initial state 92 if (this.emailInput.val() != ProductNotificationWidget_CONST.LBL_PROD_NOTIF_EMAIL_DEFAULT) { 93 // Email value is pre-filled 94 this.isEmailInputReset = true; 95 } 96 97 // Bind event handlers 98 var s = this; 99 100 this.requestButton.on('click', 101 function(data) { 102 return s.toggleBody(); 103 } 104 ); 105 106 if (typeof(this.requestButton.tooltip) == 'function') { 107 this.requestButton.tooltip( 108 { 109 id: 'prod_notif_tooltip', 110 extraClass: 'prod-notif-tooltip-' + this.type, 111 track: false, 112 delay: 0, 113 showURL: false, 114 fade: 200 115 } 116 ); 117 } 118 119 this.submitButton.on('click', 120 function(data) { 121 return s.submitButton_click(); 122 } 123 ); 124 125 this.emailInput.on('keydown', 126 function(event){ 127 if(event.keyCode == 13){ 128 event.preventDefault(); 129 return s.submitButton_click(); 130 } 131 } 132 ); 133 134 this.emailInput.on('focus', 135 function(data) { 136 return s.emailInput_focus(); 137 } 138 ); 139 140 this.emailInput.on('change', 141 function(data) { 142 return s.emailInput_change(); 143 } 144 ); 145 146 this.emailInput.on('blur', 147 function(data) { 148 return s.emailInput_blur(); 149 } 150 ); 151} 152 153// Refresh widget depending on product/variant data 154ProductNotificationWidget.obj.prototype.refresh = function(data) { 155 // TODO: object inheritance 156 if (typeof(data.inStock) != 'undefined' && data.inStock >= 0) { 157 this.inStock = data.inStock; 158 } 159 if (typeof(data.minAmount) != 'undefined' && data.minAmount >= 0) { 160 this.minAmount = data.minAmount; 161 } 162 163 if ('B' == this.type) { 164 if (this.inStock <= 0 || this.inStock < this.minAmount) { 165 // Product/variant is out of stock 166 this.show(); 167 168 } else { 169 this.hide(); 170 } 171 } 172 173 if ('L' == this.type) { 174 if (this.inStock > ProductNotificationWidget_CONST.PROD_NOTIF_L_AMOUNT) { 175 this.show(); 176 177 } else { 178 this.hide(); 179 } 180 } 181 182} 183 184// Hide widget 185ProductNotificationWidget.obj.prototype.hide = function() { 186 this.requestButton.hide(); 187 this.hideBody(); 188} 189 190// Show widget 191ProductNotificationWidget.obj.prototype.show = function() { 192 this.hideBody(); 193 this.clearMessages(); 194 this.requestButton.show(); 195} 196 197// Find selected variant 198ProductNotificationWidget.obj.prototype.detectProductVariant = function() { 199 if ( 200 typeof variants != 'undefined' 201 && variants 202 && typeof getPOValue == 'function' 203 ) { 204 for (var x in variants) { 205 if (!hasOwnProperty(variants, x) || variants[x][1].length == 0) { 206 continue; 207 } 208 variantid = x; 209 for (var c in variants[x][1]) { 210 if (!hasOwnProperty(variants[x][1], c)) { 211 continue; 212 } 213 214 if (getPOValue(c) != variants[x][1][c]) { 215 variantid = false;
216 break; 217 } 218 } 219 220 if (variantid) { 221 this.variantid = variantid; 222 break; 223 } 224 } 225 } 226} 227 228// Validate e-mail address 229ProductNotificationWidget.obj.prototype.checkEmail = function() { 230 var email = this.emailInput.val(); 231 232 if (!email || 0 == email.length) { 233 return false; 234 } 235 if (email.replace(/^\s+/g, '').replace(/\s+$/g, '').search(ProductNotificationWidget_CONST.PROD_NOTIF_EMAIL_REGEXP) == -1) { 236 return false; 237 } 238 239 return true; 240} 241 242// Show message to customer 243ProductNotificationWidget.obj.prototype.showMessage = function(text, isError) { 244 this.messageBlock.html(''); 245 if (isError) { 246 this.messageBlock.addClass(ProductNotificationWidget_CONST.ERROR_MSG_CSS); 247 248 } else { 249 this.messageBlock.removeClass(ProductNotificationWidget_CONST.ERROR_MSG_CSS); 250 } 251 this.messageBlock.html(text); 252} 253 254// Clear all messages and error alerts 255ProductNotificationWidget.obj.prototype.clearMessages = function() { 256 this.emailInput.removeClass(ProductNotificationWidget_CONST.INVALID_EMAIL_CSS); 257 this.messageBlock.html(''); 258} 259 260// Show/hide product notification request form 261ProductNotificationWidget.obj.prototype.toggleBody = function() { 262 if (this.isBodyVisible) { 263 this.hideBody(); 264 265 } else { 266 this.showBody(); 267 } 268} 269 270// Show product notification request form 271ProductNotificationWidget.obj.prototype.showBody = function() { 272 this.rootElement.slideDown(ProductNotificationWidget_CONST.REQUEST_FORM_SLIDE_DELAY); 273 this.isBodyVisible = true; 274} 275 276// Hide product notification request form 277ProductNotificationWidget.obj.prototype.hideBody = function() { 278 this.rootElement.slideUp('fast'); 279 this.clearMessages(); 280 this.isBodyVisible = false; 281} 282 283// Send a subscription data to the server by AJAX 284ProductNotificationWidget.obj.prototype.submit = function() { 285 this.startWaiting(); 286 287 // AJAX request 288 var s = this; 289 $.getJSON( 290 ProductNotificationWidget_CONST.PROD_NOTIF_SUBMIT_PHP, 291 { 292 "mode": ProductNotificationWidget_CONST.PROD_NOTIF_SUBMIT_MODE, 293 "productid": this.productid, 294 "variantid": this.variantid, 295 "type": this.type, 296 "email": this.email 297 }, 298 function(response) { 299 s.submitCallback(response); 300 s.stopWaiting(); 301 } 302 ); 303} 304 305// Submit callback function 306ProductNotificationWidget.obj.prototype.submitCallback = function(response) { 307 var isError = false; 308 var message = ProductNotificationWidget_CONST.ERR_SUBMIT_PROD_NOTIF_UNKNOWN; 309 if (!response) { 310 isError = true; 311 312 } else { 313 if (typeof response.status != 'undefined') { 314 if (0 == response.status) { 315 this.rootElement.find('#' + 'prod_notif_submit_block_' + this.productid + '_' + this.type).hide(); 316 this.emailInput.hide(); 317 // OK 318 // message = ProductNotificationWidget_CONST.MSG_SUBMIT_PROD_NOTIF_OK; 319 message = 'Created: ' + this.emailInput.val() + ' will be notified when this product has stock available.'; 320 321 } else if (1 == response.status) { 322 // already subscribed 323 message = ProductNotificationWidget_CONST.MSG_PROD_NOTIF_ALREADY_SUBSCRIBED; 324 } else if (typeof response.message != 'undefined' && response.message.length > 0) { 325 // Get error message 326 isError = true; 327 message = response.message; 328 } 329 } 330 } 331 332 this.showMessage(message, isError); 333 334 return true; 335} 336 337// Show waiting image 338ProductNotificationWidget.obj.prototype.startWaiting = function() { 339 this.emailInput.attr('disabled', 'disabled'); 340 this.submitButton.hide(); 341 this.submitWaiting.show(); 342} 343 344// Show waiting image 345ProductNotificationWidget.obj.prototype.stopWaiting = function() { 346 this.emailInput.removeAttr('disabled'); 347 this.submitWaiting.hide(); 348 this.submitButton.show(); 349} 350 351// Focus changing event handler for the 'email' input 352ProductNotificationWidget.obj.prototype.emailInput_focus = function() { 353 this.clearMessages(); 354 if (!this.isEmailInputReset) { 355 this.emailInput.val(''); 356 this.emailInput.removeClass(ProductNotificationWidget_CONST.DEFAULT_EMAIL_CSS); 357 this.isEmailInputReset = true; 358 } 359 return true; 360} 361 362// Text changing event handler for the 'email' input 363ProductNotificationWidget.obj.prototype.emailInput_change = function() { 364 this.isEmailInputContentChanged = true; 365 return true; 366} 367 368// 'Blur' event handler for the 'email' input 369ProductNotificationWidget.obj.prototype.emailInput_blur = function() { 370 if ( 371 !this.isEmailInputReset 372 && !this.isEmailInputContentChanged 373 ) { 374 this.emailInput.val(ProductNotificationWidget_CONST.LBL_PROD_NOTIF_EMAIL_DEFAULT); 375 this.emailInput.addClass(ProductNotificationWidget_CONST.DEFAULT_EMAIL_CSS); 376 this.isEmailInputReset = false;
377 } 378 return true; 379} 380 381// Click event handler for submit button 382ProductNotificationWidget.obj.prototype.submitButton_click = function() { 383 this.clearMessages(); 384 385 var err = false; 386 387 // Check email 388 if (!this.checkEmail()) { 389 this.emailInput.addClass(ProductNotificationWidget_CONST.INVALID_EMAIL_CSS); 390 this.showMessage(ProductNotificationWidget_CONST.ERR_PROD_NOTIF_EMAIL, true); 391 err = true; 392 } 393 394 if (!err) { 395 // Determine selected product variant 396 this.detectProductVariant(); 397 this.email = this.emailInput.val(); 398 this.submit(); 399 } 400 return false; 401} 402 403/* 404 * Define array of all product notification widgets of the page 405 */ 406ProductNotificationWidgets = [];
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.