1 2HJCONTAINER.components.ringWallPage = function(con) { 3 con.init = function() { 4 5/* 6 Filter Flow: 7 1. Using jquery against the $allSavedRings DOMFragment - Grab each of the allSavedRings and clone it 8 2. By default give the clone, css class of hide 9 3. Run clone through filter tests, if a match remove css class hide 10 4. If theres not a class of hide add it to a array of jquery objects (If this wasn't running against a domFragment then I would be hesitant, but since there's no browser repaint/refow it seemed as good an indicator as any.) 11 >>>>>> 5. Filtered results get passed to sorter flow 12 13 Sorter Flow: 14 1. Either the filter or a menu change invokes the sorter function 15 2. The sorter cares not about appearance, it is fed the array of jquery objects for the rings that should be visible 16 3. Sorter makes a temp array that features just the comparison points and array index for the jq obj representing ring elem 17 4. After making the order correct, $currentRings gets overwritten with the same jq objs - just in expected order 18 >>>>>> 5. showUpdatedResults called, this removes old results, appends new stuff and then invokes pagination 19*/ 20 21 // width of pagination 'panes', longer than you would expect to accomodate margins without tracking 1st and last in row 22 con.galleryContentWidth = 1000; 23 24 // Use this to know first time a ring is liked (first time, login modal presented if not logged in) 25 con.likeCounter = 0; 26 27 con.ringGalleryLoginModalInit(); 28 29 // For filter&sorter, following 2 crucial - $allSavedRings is domFragment, $currentRings array of JQobjs for each ring elem 30 var $allSavedRings = $(); 31 $allSavedRings = $("#ringGalleryRingsHolder").clone(); 32 con.$allSavedRings = $allSavedRings; 33 34 con.$currentRings = $(); 35 (con.$allSavedRings).find('[data-control="savedRing"]').each(function() { 36 (con.$currentRings).push($(this)); 37 }); 38 39 /* 40 Grab one of these design yours callouts and then let 41 showUpdated at the end worry about where and how often it goes in with results 42 */ 43 con.$designYoursCalloutEl = $(); 44 con.$designYoursCalloutEl = $("#container").find(".designYourOwnCalloutTemplate").first().clone(); 45 46 con.ringGalleryLikeControlActiveSrc = $("#container").find('[data-control="savedRing"]').first().attr("data-likeControlImgActiveSrc"); 47 con.ringGalleryLikeControlSrc = $("#container").find('[data-control="savedRing"]').first().attr("data-likeControlImgSrc"); 48 49 // Grab initial like status from the cookie 50 con.setLikeStatusForAllRings(); 51 52 /* Event Handlers */ 53 54 $("#ringGalleryPage").on("click", '[data-control="ringFilter"]', function(e) { 55 var cat = $(this).attr("data-category"); 56 con.filterRings($(this), cat); 57 }); 58 59 $("#ringGalleryRings").on("click", '[data-control="like"]', function(e) { 60 console.log('page like handler triggered'); 61 con.toggleLike($(this)); 62 }); 63 64 $('[data-control="modalLike"]').click(function(e) { 65 // second param true makes the toggle code update modal and parent page like indicator 66 console.log('modal like handler triggered'); 67 con.toggleLike($(this), true); 68 }); 69 70 $("#ringGallerySortBy").on("change", function() { 71 con.sortRings(con.$currentRings); 72 }); 73 74 $('.ringImg').on('click', function() { 75 var el = $(this); 76 con.showRingModal( el ); 77 }); 78 79 $("#designThisRing").on("click", con.designYourRingMakeGradCallback()); 80 81 //ringLandingPage 82 $('#savedRingLogin').click(function(e) { 83 e.preventDefault(); 84 con.viewSavedRing(); 85 }); 86 87 con.promoId = null; 88 con.genderOnLeft = false; 89 90 $(".designYourRing").on("click", con.designYourRingMakeGenderCallback(false)); 91 $(".promoArea .imageWithSubtitles").on("click", con.designYourRingMakeGenderCallback(true)); 92 //ringLandingPage 93 94 $(".gradPop button").on("click", function (e) { 95 con.designYourRingGender = "Male"; 96 con.designYourRingMaybeGo(); 97 }); 98 99 // simulate click to perform initial sort 100 $('#ringGalleryPage #filterRingByAll').trigger('click'); 101 102 con.postFacebookLoginRingSpecifics(); 103 104 con.showPassedIn(); 105 }; 106 107 con.showPassedIn = function() {
108 var rid = con.getURLParameter("ringid"); 109 if(!rid || !rid.length) 110 return; 111 112 var toFind = $("#galleryRing" + rid); 113 if(!toFind.length) 114 return; 115 116 var page = toFind.closest(".paginationPage"); 117 var pageIdx = page.index(); 118 119 selectPaginationPage(pageIdx); 120 121 toFind.find(".ringImg").trigger("click"); 122 }; 123 124 con.getURLParameter = function(name) { 125 return decodeURI((new RegExp(name + '=' + '(.+?)(&|$)').exec(window.location.search)||[,null])[1]); 126 }; 127 128 con.toggleLike = function($likeEl, withinModal) { 129 // if the like is toggled within the modal we update indicator in parent page AND via a wee function in the modal 130 // and we do some modal open and closing if its the first like 131 var withinModal = (withinModal) ? withinModal : false; 132 var $parent; 133 134 if (!withinModal) { 135 // we are liking within the parent page so can just grab the closest savedRing 136 $parent = $likeEl.closest('[data-control="savedRing"]'); 137 } else { 138 // find the parent page savedRing that matches what we are 'liking' in the detail modal 139 var $modalParent = $likeEl.closest('[data-control="savedRing"]'); 140 var modalRingData = $.parseJSON($modalParent.attr("data-info")); 141 142 $("#ringGalleryRings").find('[data-control="savedRing"]').each(function(){ 143 var data = $.parseJSON($(this).attr("data-info")); 144 if (data.id === modalRingData.id) { 145 $parent = $(this); 146 } 147 }); 148 // NOTE - we have a wee standalone functon later that specifically updates the modal after we take care of same 149 // savedRing on the parent page 150 } 151 152 var data = $.parseJSON($parent.attr("data-info")); 153 var likes = $parent.find('.likeCount').text(); 154 var ringId = data.id; 155 var idstr = ringId + "-"; 156 var updated = ""; 157 158 if (! $.cookie("herffJones-myLikedRings")) { 159 var likedRingIds = ""; 160 } else { 161 var likedRingIds = $.cookie("herffJones-myLikedRings"); 162 } 163 164 // Toggle liked value 165 if ($parent.attr("data-liked") === "false") { 166 var likeStatus = "true"; 167 $parent.attr("data-liked", likeStatus); 168 updated = likedRingIds + idstr; 169 170 var newLikes = parseInt(likes) + 1; 171 if (newLikes < 0) { 172 newLikes = 0; 173 } 174 175 $parent.find('.likeCount').text(newLikes); 176 updateLikeStatusInAllRings(newLikes, likeStatus); 177 con.likeCounter++; 178 179 if (withinModal) { 180 updateLikeStatusInDetailModal(newLikes, likeStatus); 181 } 182 183 } else { 184 var likeStatus = "false"; 185 $parent.attr("data-liked", likeStatus); 186 updated = likedRingIds.replace(idstr, ""); 187 188 var newLikes = parseInt(likes) - 1; 189 if (newLikes < 0) { 190 newLikes = 0; 191 } 192 193 $parent.find('.likeCount').text(newLikes); 194 updateLikeStatusInAllRings(newLikes, likeStatus); 195 196 if (withinModal) { 197 updateLikeStatusInDetailModal(newLikes, likeStatus); 198 } 199 } 200 201 // Reset cookie 202 // providing path param as otherwise cookie won't be deleted 203 $.cookie("herffJones-myLikedRings", null, { path: '/'}); 204 205 if (updated.length) { 206 $.cookie("herffJones-myLikedRings", updated, { expires: 999, path: '/' }); 207 } 208 209 // Since we have a wee function to update the image in the modal (if applicable), 210 // here explicitly change on parent page 211 con.toggleLikeImage($parent.find('[data-control="like"]').first(), likeStatus); 212 213 console.log('like status is ' + likeStatus); 214 215 if (con.likeCounter == 1 && ($("#container").attr("loggedIn")) !== 'true' ) { 216 con.afterLoginRingIdToSave = data.id; 217 con.afterLoginRingIdToSaveLiked = likeStatus == "true"; 218 // see if they cancel instead, this whole flow needs to be reworked 219 220 var handleClose = function() { 221 con.saveRingLikeToBackend(data.id, likeStatus == "true"); 222 $("#login-to-save-liked-rings-modal .closeBtn").off("click", handleClose); 223 }; 224 225 $("#login-to-save-liked-rings-modal .closeBtn").on("click", handleClose); 226 227 window.launchModal($("#login-to-save-liked-rings-modal"), "show", "rings/changeSchool"); 228 229 // increase like counter so if login is dismissed we don't hassle the customer with it again 230 con.likeCounter++; 231 return false; 232 } else {
233 con.saveRingLikeToBackend(data.id, likeStatus == "true"); 234 } 235 236 function updateLikeStatusInAllRings(newLikes, likeStatus) { 237 (con.$allSavedRings).find('[data-control="savedRing"]').each(function() { 238 var data = $.parseJSON($(this).attr("data-info")); 239 if(data.id === ringId) { 240 $(this).attr("data-liked", likeStatus); 241 $(this).find('.likeCount').text(newLikes); 242 } 243 }); 244 } 245 246 function updateLikeStatusInDetailModal(newLikes, likeStatus) { 247 var $detailRing = $("#ring-wall-view-ring-modal").find('[data-control="savedRing"]').first(); 248 $detailRing.attr("data-liked", likeStatus); 249 $detailRing.find('.likeCount').first().text(newLikes); 250 var $likeEl = $detailRing.find('[data-control="modalLike"]').first(); 251 con.toggleLikeImage($likeEl, likeStatus); 252 } 253 254 }; 255 con.toggleLikeImage = function($likeEl, likeStatus) { 256 if (likeStatus === "true") { 257 $likeEl.attr("src", con.ringGalleryLikeControlActiveSrc); 258 } else { 259 $likeEl.attr("src", con.ringGalleryLikeControlSrc); 260 } 261 }; 262 con.saveRingLikeToBackend = function(ringId, like) { 263 var req = con.relativePath + "/rings/" + (like ? "like" : "unlike")+ "/" + ringId; 264 $.ajax({ 265 method: 'GET', 266 url: req, 267 success: function(data){ 268 console.log('con.saveRingLikeToBackend success for ring ' + ringId + '. data is ' + data); 269 }, 270 error: function() { 271 console.log('con.saveRingLikeToBackend FAILURE for ring ' + ringId); 272 } 273 }); 274 }; 275 con.setLikeStatusForAllRings = function() { 276 // Grab likes from cookie 277 if ($.cookie("herffJones-myLikedRings")) { 278 var likedRingIds = $.cookie("herffJones-myLikedRings"); 279 } else { 280 return; 281 } 282 283 $("#ringGalleryRingsHolder").find('[data-control="savedRing"]').each(function() { 284 var data = $.parseJSON($(this).attr("data-info")); 285 var likeStatus; 286 287 if (likedRingIds.match(data.id)) { 288 likeStatus = "true"; 289 } else { 290 likeStatus = "false"; 291 } 292 293 $(this).attr("data-liked", likeStatus); 294 con.toggleLikeImage($(this).find('[data-control="like"]').first(), likeStatus); 295 }); 296 }; 297 con.filterRings = function($el, cat) { 298 var showCount = 0; 299 var $possibleMatch = $(); 300 var $filteredRings = []; 301 302 $("#ringFilters").find('[data-control="ringFilter"]').each(function() { 303 if ($(this).attr("data-category") === cat) { 304 if (! $(this).hasClass("btn-silver-active")) { 305 $(this).removeClass("btn-silver"); 306 $(this).addClass("btn-silver-active"); 307 } 308 } else { 309 if ($(this).hasClass("btn-silver-active")) { 310 $(this).removeClass("btn-silver-active"); 311 $(this).addClass("btn-silver"); 312 } 313 } 314 }); 315 316 (con.$allSavedRings).find('[data-control="savedRing"]').each(function() { 317 var data = $.parseJSON($(this).attr("data-info")); 318 $possibleMatch = $(this).clone(); 319 $possibleMatch.addClass("hide"); 320 321 if (data.title !== 'designYours') { 322 switch (cat) { 323 case "m": 324 if (data.gender && data.gender === cat) { 325 $possibleMatch.removeClass("hide"); 326 } 327 break; 328 case "f": 329 if (data.gender && data.gender === cat) { 330 $possibleMatch.removeClass("hide"); 331 } 332 break; 333 case "liked": 334 if ( $(this).attr("data-liked") === "true" ) { 335 $possibleMatch.removeClass("hide"); 336 } 337 break; 338 case "all": 339 $possibleMatch.removeClass("hide"); 340 break; 341 } 342 343 } 344 345 if (! $possibleMatch.hasClass("hide") ) { 346 showCount++; 347 $filteredRings.push($possibleMatch); 348 } 349 }); 350 351 con.sortRings($filteredRings); 352 }; 353 con.sortRings = function($currentRings) { 354 var sort = $("#ringGallerySortBy").val(); 355 356 // Build a array with just some criteria and the index of the jquery object 357 var tempArray = []; 358 for (i = 0, len = $currentRings.length; i < len; i++) { 359 var curr = $currentRings[i]; 360 361 // grab the json so we can have the sort criteria 362 var data = $.parseJSON(curr.attr("data-info")); 363 364 // date object so we can compare newest to oldest 365 var slicedDate = (data.created).slice(0, 10); 366 var splitDate = slicedDate.split("-"); 367 var slashDate = splitDate[0] + '/' + splitDate[1] + '/' + splitDate[2]; 368 var date = new Date(slashDate); 369 370 // Adding the 2 sort criteria and the original position in the array of jquery elements 371 tempArray.push([data.likeCount, date, i]); 372 } 373 374 switch (sort) { 375 case "mostPopular": 376 tempArray.sort(function(a, b) { 377 return b[0] - a[0]; 378 }); 379 380 break; 381 case "newestFirst": 382 tempArray.sort(function(a, b) { 383 return b[1] - a[1]; 384 }); 385 386 break;
387 case "oldestFirst": 388 tempArray.sort(function(a, b) { 389 return a[1] - b[1]; 390 }); 391 392 break; 393 } 394 395 // Now the tempArray is in the correct order we rebuild the currentRings array of elements to match 396 var tempSortedArray = []; 397 for (i = 0, len = tempArray.length; i < len; i++) { 398 var elpos = tempArray[i][2]; 399 var el = $currentRings[elpos] 400 tempSortedArray.push(el); 401 } 402 $currentRings = []; 403 $currentRings = tempSortedArray; 404 405 // Export the current rings now they are in correct order per current sort option 406 con.$currentRings = $currentRings; 407 408 con.showUpdatedRings($currentRings); 409 }; 410 con.showUpdatedRings = function($currentRings) { 411 $("#ringGalleryRingsHolder").remove(); 412 $("#ringGalleryPage .pagination ul").empty(); 413 var $ringGalleryRingsHolder = $('<div id="ringGalleryRingsHolder"></div>'); 414 $("#ringGalleryRings").append($ringGalleryRingsHolder); 415 416 var len = $currentRings.length; 417 for (i = 0; i < len; i++) { 418 var $currentEl = $(); 419 $currentEl = $currentRings[i]; 420 $("#ringGalleryRingsHolder").append($currentEl); 421 if ( i % 9 !== 0 ) { 422 // Insert the 'Design your own ring' callout (features text and button) here. Same dimensions as rings. 423 $("#ringGalleryRingsHolder").append(con.$designYoursCalloutEl); 424 } 425 } 426 427 con.setLikeStatusForAllRings(); 428 con.paginate(); 429 430 $('.ringImg').on('click', function() { 431 var el = $(this); 432 con.showRingModal( el ); 433 }); 434 }; 435 con.paginate = function() { 436 //window.setupPagination($("#ringGalleryPage .pagination"), $("#ringGalleryRingsHolder"), 10, con.galleryContentWidth); 437 }; 438 con.showRingModal = function( el ) { 439 440 var $saveRing = el.closest('[data-control="savedRing"]'); 441 442 if( !$saveRing.hasClass('designYours') ) { 443 var $ringWallModal = $('#ring-wall-view-ring-modal'); 444 var ringImgSrc = el.attr('src'); 445 446 // add meta data to ring in modal so the likeToggle code can use it as on parent page 447 var $detailRing = $ringWallModal.find('[data-control="savedRing"]'); 448 $detailRing.attr("data-info", $saveRing.attr('data-info')); 449 450 // Ensure like image is correctly highlighted with most recent count 451 var currentLikeImgSrc = $saveRing.find('[data-control="like"]').first().attr("src"); 452 $detailRing.find('[data-control="modalLike"]').first().attr("src", currentLikeImgSrc); 453 $detailRing.attr("data-liked", $saveRing.attr("data-liked")); 454 $detailRing.find('.likeCount').first().text($saveRing.find('.likeCount').first().text()); 455 456 var data = JSON.parse($saveRing.attr('data-info')); 457 458 switch( data.gender ) { 459 case "m": 460 con.designYourRingGender = "Male"; 461 $ringWallModal.find('.gender').addClass('male'); 462 break; 463 case "f": 464 con.designYourRingGender = "Female"; 465 $ringWallModal.find('.gender').addClass('female'); 466 break; 467 default: 468 break; 469 } 470 471 $ringWallModal.find('.ringName').html(data.title); 472 $ringWallModal.find('.date').html(data.created); 473 $ringWallModal.find('.ringImg').attr('src', ringImgSrc); 474 475 var $button = $ringWallModal.find("#designThisRing"); 476 con.designYourRingRedirect = $button.attr("linkroot") + JSON.parse($saveRing.attr("data-info")).id; 477 478 launchModal($ringWallModal, {show: true}, "ringWall/" + data.id); 479 } 480 }; 481 // This is very redundant but with a week to browse mode launch safe albeit very ugly 482 con.ringGalleryLoginModalInit = function() { 483 if (!con.$loginGallerySaveLikeModalHead) { 484 // to avoid making an ajax cal if we switch back to login, cloning the login view now 485 con.$loginGallerySaveLikeModalHead = $('#login-to-save-liked-rings-modal').find('.modal-header').first().clone(); 486 con.$loginGallerySaveLikeModalBody = $('#login-to-save-liked-rings-modal').find('.modal-body').first().clone(); 487 } 488 489 $('#login-to-save-liked-rings-modal').on('click', '.loginBtn', function(e) { 490 e.preventDefault(); 491 con.standaloneLogin($('.loginBtn'), 'ringGallery'); 492 }); 493 494 $('#login-to-save-liked-rings-modal').on('click', '#modalRegister', function(e) { 495 e.preventDefault();
496 con.ringGalleryModalRegRequest(); 497 }); 498 499 $('#login-to-save-liked-rings-modal').on('click', '#likeRingFacebookLoginButton', function(e) { 500 console.log('fb login clicked from showLoginSaveRing'); 501 $.cookie("herffJonesPostFacebookLoginAction", "ringGallery", { expires: 999, path: '/' }); 502 $.cookie("herffJonesPostFacebookLoginAction-ringIdToSave", con.afterLoginRingIdToSave, { expires: 999, path: '/' }); 503 var url = con.relativePath + '/social/facebook/signin?sRedirect=' + window.location.href; 504 window.location = url; 505 }); 506 507 }; 508 con.ringGalleryModalLoginRequest = function() { 509 $('#login-to-save-liked-rings-modal').empty(); 510 $('#login-to-save-liked-rings-modal').append( (con.$loginGallerySaveLikeModalHead).clone() ); 511 $('#login-to-save-liked-rings-modal').append( (con.$loginGallerySaveLikeModalBody).clone() ); 512 con.ringGalleryLoginModalInit(); 513 }; 514 con.ringGalleryModalRegRequest = function() { 515 var url = $("#loginRegHolder").attr("regURL"); 516 517 $.ajax({ 518 url : url, 519 type : "GET", 520 success : function(data) { 521 $('#login-to-save-liked-rings-modal').html(data); 522 $("#login-to-save-liked-rings-modal").on('click', '#modalLogin', function() { 523 con.ringGalleryModalLoginRequest(); 524 }); 525 $("#login-to-save-liked-rings-modal").on("click", '.registerBtn', function(e) { 526 con.ringGallerySubmitRegisterForm(e); 527 }); 528 529 }, 530 error: function( data ) { 531 // TO DO: redirect to standalone login page 532 } 533 }); 534 535 }; 536 con.ringGallerySubmitRegisterForm = function( e ) { 537 e.preventDefault(); 538 539 var _this = $("#login-to-save-liked-rings-modal #registerForm"); 540 var form = _this.closest('form'); 541 var url = con.relativePath + "/register"; 542 var lName = $('#lName'); 543 var fName = $('#fName'); 544 545 var email = form.find('.emailAddress').val(); 546 var errors = con.validateEmail( email ); 547 548 if( fName.val() == "") { 549 errors += "<br/>Please provide a valid first name."; 550 fName.addClass('inputError'); 551 } 552 553 if( lName.val() == "") { 554 errors += "<br/>Please provide a valid last name."; 555 lName.addClass('inputError'); 556 } 557 558 if( errors !== null ) { 559 form.find('.errors').html( errors ).show(); 560 form.find('.emailAddress').addClass('inputError'); 561 } else { 562 form.find('.errors').html('').hide(); 563 form.find('.inputError').removeClass('inputError'); 564 565 var formData = form.serialize(); 566 var registerErrors = ""; 567 568 $.ajax({ 569 url: url, 570 type: 'POST', 571 data: formData, 572 success: function( data ) { 573 574 console.log( data ); 575 576 if( data.success === false ) { 577 578 if( data.messages.password ) { 579 if(typeof data.messages.password == 'string') { 580 registerErrors = "Password: " + data.messages.password; 581 } else { 582 for(var i = 0;i<data.messages.password.length;i++ ) { 583 registerErrors += 'Password: ' + data.messages.password[i] + '<br />'; 584 } 585 } 586 } else if( data.messages.confirmPassword ) { 587 registerErrors += data.messages.confirmPassword; 588 } else { 589 registerErrors += data.messages.global; 590 } 591 592 form.find('.errors').html( registerErrors ).show(); 593 } else { 594 $('#login-to-save-liked-rings-modal').modal('hide'); 595 con.saveRingLikeToBackend(con.afterLoginRingIdToSave, con.afterLoginRingIdToSaveLiked); 596 con.updateHeaderLinksOnLogin(); 597 598 } 599 }, 600 error: function( data ) { 601 console.log( data ); 602 } 603 }); 604 } 605 }; 606}; 607 608 609 610 611
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.