PageSourceSearch

https://www.grantnebraska.com/javascripts/vnews/feedback_v3.js

js grantnebraska.com collected 2026-10-02 16:43:23 UTC 11,459 bytes, 302 lines download raw bytes

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.