1// jQuery-based code to implement posting feedback within articles. 2// Rewritten for L12 template - based on Bootstrap v3.3.4 3(function($){ 4 'use strict'; 5 $(function() { 6 // Create an "inView" filter, courtesy of 7 // http://stackoverflow.com/questions/472930/in-jquery-is-there-way-for-slidedown-method-to-scroll-the-page-down-too/472954 8 $.extend($.expr[':'],{ 9 inView: function(a) { 10 var st = (document.documentElement.scrollTop || document.body.scrollTop), 11 ot = $(a).offset().top, 12 wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height(); 13 return ot > st && ($(a).height() + ot) < (st + wh); 14 } 15 }); 16 17 // Create the HTML for the feedback form and append it to the end of the feedbackBox div 18 $('#feedbackBox > div').append( 19'<div id="fbForm" style="overflow:auto; display:none;">' + 20 '<form action="">' + 21 '<p>Fill in the fields below and click Save to add a comment. (<em>* - required fields</em>)</p>' + 22 '<div class="form-group">' + 23 '<label for="fbName">* Name</label>' + 24 '<input type="text" name="fbName" id="fbName" value="" class="form-control" placeholder="Enter your name">' + 25 '</div>' + 26 '<div class="form-group">' +
27 '<label for="fbEmail">* Email</label>' + 28 '<input type="text" name="fbEmail" id="fbEmail" value="" class="form-control" placeholder="Enter your email address">' + 29 '</div>' + 30 '<div class="form-group">' + 31 '<label for="fbOccupation">Occupation:</label>' + 32 '<input type="text" name="fbOccupation" id="fbOccupation" value="" class="form-control" placeholder="Enter your occupation">' + 33 '</div>' + 34 '<div class="form-group">' + 35 '<label for="fbLocation">Location:</label>' + 36 '<input type="text" name="fbLocation" id="fbLocation" value="" class="form-control" placeholder="Enter your location">' + 37 '</div>' + 38 '<div class="form-group">' + 39 '<label>Display your email address?</label>' + 40 '<div class="radio">' + 41 '<label>' + 42 '<input type="radio" name="fbDisplayEmail" value="y" id="fbYes"> Yes' + 43 '</label>' + 44 '<label>' + 45 '<input type="radio" name="fbDisplayEmail" value="n" id="fbNo" checked="checked"> No' + 46 '</label>' + 47 '</div>' + 48 '</div>' + 49 '<div class="form-group">' + 50 '<label for="fbComment">* Feedback:</label>' + 51 '<textarea name="fbComment" id="fbComment" rows="10" class="form-control" placeholder="Enter your feedback"></textarea>' + 52 '</div>' + 53 '<p class="formButtons">' + 54 '<input type="button" id="saveFeedback" value="Save" disabled="disabled" class="btn btn-primary"> ' + 55 '<input type="button" id="cancelFeedback" value="Cancel" class="btn btn-primary">' + 56 '</p>' + 57 '</form>' + 58'</div>' 59 ); 60 61 // Cache some elements 62 var fbForm = $('#fbForm'); 63 var fbName = $('#fbName'); 64 var fbEmail = $('#fbEmail'); 65 var fbComment = $('#fbComment'); 66 var saveFeedback = $('#saveFeedback'); 67 68 // Create the HTML for the "Add New Comment" links and slide them down from above and below table 69 if ($('#feedbackBox tbody tr').length > 15) { 70 $('<p id="anc2" class="hidden-print" style="display:none;"><a href="#">Add New Comment</a></p>').insertBefore('#feedbackBox table').slideDown(); 71 } 72 $('<p id="anc" class="hidden-print" style="display:none;"><a href="#">Add New Comment</a></p>').insertAfter('#feedbackBox table').slideDown(); 73 74 // Create the HTML for the "Posted by" name "hover effect" in the feedback table 75 $('body').append( 76'<div id="namePreview">' + 77 '<p><strong>Email:</strong><span id="npEmail" /></p>' + 78 '<p><strong>Occupation:</strong><span id="npOccupation" /></p>' + 79 '<p><strong>Location:</strong><span id="npLocation" /></p>' + 80'</div>' 81 ); 82 83 var np = $('body #namePreview'); 84 np.css('opacity', 0); 85 86 // Build the text for the Ajax messages 87 var ajaxP1 = 'Please check your e-mail for a confirmation message. You must click on the URL in the message for your feedback to be submitted.'; 88 var ajaxP2 = '<strong>Thank you.</strong>'; 89 var moderatedFlag = $('#Moderated_Flag').val(); 90 var emailVerifyFlag = $('#Email_Verify_Flag').val(); 91 if (moderatedFlag && emailVerifyFlag) { 92 ajaxP2 = 'Your feedback will then be reviewed by our moderator.'; 93 } else if (moderatedFlag) { 94 ajaxP1 = 'Your feedback has been submitted for review by our moderator.'; 95 } else if (emailVerifyFlag) { 96 // Messages already set, but we need this ELSE IF in order for the ELSE to catch the right stuff 97 } else { 98 ajaxP1 = 'Your feedback has been submitted.'; 99 } 100 101 // Helper functions ------------------------------------------------------- 102 function ajaxPost() { 103 $.post( 104 '/vfeedback/action.v?ACTION=ajaxPost', 105 { 106 Name: $.trim(fbName.val()), 107 Email: $.trim(fbEmail.val()), 108 Occupation: $.trim($('#fbOccupation').val()), 109 Location: $.trim($('#fbLocation').val()), 110 Display_Email_Flag: $('#fbForm input:radio:checked').val(), 111 Comment: $.trim(fbComment.val()), 112 Topic_Name: $('#Topic_Name').val(), 113 Topic_ID: $('#Topic_ID').val() 114 }, 115 function(data) { 116 $('#ajaxLoading') 117 .find('#loadingImg').slideUp('normal', function() { 118 $('#ajaxLoading p:last').slideDown(); 119 }).end() 120 .find('p:first') 121 .animate({ opacity:'0' }, 'normal', function() { 122 $(this).html(ajaxP1); 123 }) 124 .animate({ opacity:'1' }, 'normal').end() 125 .find(':nth-child(3)') 126 .animate({ opacity:'0' }, 'normal', function() { 127 $(this).html(ajaxP2); 128 }) 129 .animate({ opacity:'1' }, 'normal'); 130 } 131 ); 132 } 133 134 function CloseDialog() { 135 fbForm.slideUp('normal', function() { 136 $('#anc, #anc2').slideDown(); 137 }); 138 } 139 140 function ToggleSaveButton(e) { 141 // Turns out to be equivalent to: if (a || b || c) 142 if ($('#fbName, #fbEmail, #fbComment').hasClass('backgroundError')) { 143 saveFeedback.attr('disabled', 'disabled'); 144 } else { 145 saveFeedback.removeAttr('disabled'); 146 } 147 } 148 149 // Event Handlers --------------------------------------------------------- 150 151 // Hover over "Posted by" name to see namePreview popup 152 var namePreview = $('#feedbackBox td.feedbackAuthor .fbName'); 153 if (namePreview.length) { 154 namePreview.mouseenter(function(e) { 155 var par = $(this).parent(); 156 var em = ''; 157 var fbe = par.find('.fbEmail'); 158 if (fbe.length) em = fbe.text(); 159 var occ = par.find('.fbOccupation').text(); 160 var loc = par.find('.fbLocation').text(); 161 162 // Put 'NA' in empty fields 163 if (em == '') em = 'NA'; if (occ == '') occ = 'NA'; if (loc == '') loc = 'NA'; 164 np.find('#npEmail').html(em); 165 np.find('#npOccupation').html(occ); 166 np.find('#npLocation').html(loc); 167 168 np.css({ 169 'left': e.pageX + 13, 170 'top': e.pageY + 5 171 }) 172 .stop() 173 .animate({ opacity: 1 }, 'normal'); 174 }).mousemove(function(e) { 175 np.css({ 176 'left': e.pageX + 13, 177 'top': e.pageY + 5 178 }); 179 }).mouseleave(function(e) { 180 // Fade out and then move it out of the way 181 np.stop().animate({ opacity: 0 }, 'normal', function () { $(this).css('top','-500px'); }); 182 }); 183 } 184 185 // "Add New Comment" link 186 $('#anc a, #anc2 a').click(function() { 187 $('#anc2').slideUp(); 188
189 $('#anc').slideUp('normal', function() { 190 // Reset fields 191 $('#fbForm .formItems input:text, #fbForm #fbComment').val(''); 192 $('#fbName, #fbEmail, #fbComment').addClass('backgroundError'); 193 $('#fbNo').attr('checked', 'checked'); 194 195 fbForm.slideDown('normal', function() { 196 // If necessary, scroll to keep the feedback form in view 197 if ($(this).is(':not(:inView)')) { 198 var sTop = $(this).offset().top; 199 200 // The L16 template has a "top bar" that can be "sticky" - take that into account when scrolling 201 if ($('.container-top-bar.sticky-top-bar').length) { 202 sTop -= ($('.container-top-bar.sticky-top-bar').outerHeight(true) + 5); 203 } 204 205 $('html,body').animate({ scrollTop: sTop }, 'normal'); 206 } 207 208 // Put the cursor in the Name field 209 fbName.focus(); 210 211 }); 212 }); 213 return false; 214 }); 215 216 // Cancel button in feedback form 217 $('#cancelFeedback').click(CloseDialog); 218 219 // Close the dialog if Escape key is pressed 220 fbForm.keyup(function(e) { 221 if (e.keyCode == 27) CloseDialog(); 222 }); 223 224 // Watch required fields and enable/disable Save button based on existence of text in those fields 225 fbName.keyup(function(e) { 226 if ($.trim($(this).val()) == '') { 227 $(this).addClass('backgroundError'); 228 } else { 229 $(this).removeClass('backgroundError'); 230 } 231 ToggleSaveButton(e); 232 }); 233 fbEmail.keyup(function(e) { 234 var em = $.trim($(this).val()); 235 if (em == '') { 236 $(this).addClass('backgroundError'); 237 } else { 238 var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; 239 if (filter.test(em)) { 240 $(this).removeClass('backgroundError'); 241 } else { 242 $(this).addClass('backgroundError'); 243 } 244 } 245 ToggleSaveButton(e); 246 }); 247 fbComment.keyup(function(e) { 248 if ($.trim($(this).val()) == '') { 249 $(this).addClass('backgroundError'); 250 } else { 251 $(this).removeClass('backgroundError'); 252 } 253 ToggleSaveButton(e); 254 }); 255 256 // Save button in feedback form 257 saveFeedback.click(function() { 258 // Only want to create the "loading" div once 259 if ($('#ajaxLoading').length == 0) { 260 $( 261'<div id="ajaxLoading" style="display:none;">' + 262 '<p />' + 263 '<p id="loadingImg"><img src="" /></p>' + 264 '<p />' + 265 '<p><input type="button" value="Close" class="btn btn-primary" /></p>' + 266'</div>' 267 ).insertAfter('#fbForm'); 268 269 $('#ajaxLoading').css({ 270 'background-color': $('#fbForm p').css('background-color'), 271 'text-align': 'center' 272 }) 273 .find('p:last input') 274 .click(function() { 275 if (!moderatedFlag && !emailVerifyFlag) { 276 // If no moderation, reload the page to display the new feedback post 277 location.reload(); 278 } else { 279 $('#ajaxLoading').slideUp('normal', function() { 280 $('#anc, #anc2').slideDown(); 281 }); 282 } 283 }); 284 } 285 286 fbForm.slideUp('normal', function() { 287 $('#ajaxLoading') 288 .find('p:first').html('Saving your feedback...').end() 289 .find('#loadingImg').removeAttr('style').end() 290 // Reset the img src - without this, the animated gif will only animate the first time a feedback is posted. 291 .find('#loadingImg img').attr('src', '').attr('src','https://socshelp.socs.net/images/ajax_bar_loader.gif').end() 292 .find(':nth-child(3)').html('...this may take a few seconds.').end() 293 .find('p:last').hide().end() 294 .slideDown('normal', function() { 295 ajaxPost(); 296 }); 297 }); 298 }); 299 300 }); 301})(jQuery); 302
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.