PageSourceSearch

https://jcdn.toastmasters.org/cassette.axd/asset/Content/Scripts/j…?b4fb0b7ab52857c9f9314db7ad19950f3fdd3dd6

js toastmasters.org collected 2026-10-01 07:13:41 UTC 25,934 bytes, 741 lines download raw bytes

1/*global $, jQuery*/
2/*jslint plusplus: true*/
3
4/*!
5* jQuery Feedback Me Plugin
6* 
7* File:			jquery.feedback_me.js
8* Version:		0.5.6
9* 
10* Author:      Daniel Reznick
11* Info:        https://github.com/vedmack/feedback_me 
12* Contact:     [email protected]
13* Twitter:	   @danielreznick
14* Q&A		   https://groups.google.com/forum/#!forum/daniels_code	
15* 
16* Copyright 2013 Daniel Reznick, all rights reserved.
17* Copyright 2013 Licensed under the MIT License (just like jQuery itself)
18* 
19* This source file is distributed in the hope that it will be useful, but 
20* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
21* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
22*/
23/*
24* Parameters:
25*
26*					
27* -------------
28
29* feedback_url
30				Required:			true
31				Type:				String
32				Description:		URL of your servlet/php etc ('name', 'message' and 'email' parameters will be send to your servlet/php etc...)
33
34* position				
35				Required:			false
36				Type:				String
37				Default value:		left-top
38				Possible values:	left-top / left-bottom / right-top / right-bottom 
39				Description:		Set the position where the feedback widget will be located
40* jQueryUI
41				Required:			false
42				Type:				boolean
43				Default value:		false
44				Description:		Tell the plugin to use jQuery UI theme
45
46* bootstrap
47				Required:			false
48				Type:				boolean
49				Default value:		false
50				Description:		Tell the plugin to use twitter bootstrap
51
52* show_email
53				Required:			false
54				Type:				boolean
55				Default value:		false
56				Description:		Tell the plugin to display email input field
57
58* show_radio_button_list
59				Required:			false
60				Type:				boolean
61				Default value:		false
62				Description:		Tell the plugin to set of 5 radio buttons
63				
64* name_label
65				Required:			false
66				Type:				String
67				Default value:		"Name"
68				Description:		Label for name input
69
70* email_label
71				Required:			false
72				Type:				String
73				Default value:		"Email"
74				Description:		Label for email input
75
76* message_label
77				Required:			false
78				Type:				String
79				Default value:		"Message"
80				Description:		Label for message input
81
82* radio_button_list_labels
83				Required:			false
84				Type:				Array of 5 strings
85				Default value:		["1","2","3","4","5"]
86				Description:		Labels for radio button list
87
88* radio_button_list_title
89				Required:			false
90				Type:				String
91				Default value:		"How would you rate my site?"
92				Description:		Label that will appear above the list of radio button
93				
94* submit_label
95				Required:			false
96				Type:				String
97				Default value:		"Send"
98				Description:		Label for submit input
99
100* title_label
101				Required:			false
102				Type:				String
103				Default value:		"Feedback"
104				Description:		Label for title text
105
106* trigger_label
107				Required:			false
108				Type:				String
109				Default value:		"Feedback"
110				Description:		Label for open/close (trigger) button
111
112* name_placeholder
113				Required:			false
114				Type:				String
115				Default value:		""
116				Description:		Watermark for name input
117
118* email_placeholder
119				Required:			false
120				Type:				String
121				Default value:		""
122				Description:		Watermark for email input
123
124* message_placeholder
125				Required:			false
126				Type:				String
127				Default value:		""
128				Description:		Watermark for message input
129
130* name_pattern				
131				Required:			false
132				Type:				String
133				Default value:		""
134				Description:		Set name input pattern, you must escape your '\' chars (\ ---> \\)
135
136* name_required
137				Required:			false
138				Type:				boolean
139				Default value:		false
140				Description:		Makes input required
141
142* email_required
143				Required:			false
144				Type:				boolean
145				Default value:		false
146				Description:		Makes input required
147
148* message_required
149				Required:			false
150				Type:				boolean
151				Default value:		false
152				Description:		Makes input required
153
154* radio_button_list_required
155				Required:			false
156				Type:				boolean
157				Default value:		false
158				Description:		Makes radio inputs required
159
160* show_asterisk_for_required
161				Required:			false
162				Type:				boolean
163				Default value:		false
164				Description:		Add an asterisk to the label of the required inputs
165
166* close_on_click_outside				
167				Required:			false
168				Type:				boolean
169				Default value:		true
170				Description:		Will cause the feedback dialog to be closed on clicking anywhere outside the dialog
171				
172* custom_params				
173				Required:			false
174				Type:				object
175				Default value:		{}
176				Description:		Use it if you want to send additional data to the server (can be used for sending: csrf token / logged in user_name / etc`)
177* iframe_url				
178				Required:			false
179				Type:				String
180				Default value:		undefined
181				Description:		Allows you to use any html file that you want, it will be placed inside feedback_me widget, (note that in order to close the feedback_me widget
182									just call the following command: parent.fm.triggerAction(event, "left-top"); don't forget to pass the "event" from you onclick call to the triggerAction function
183									and also the position of your feedback widget left-top / left-bottom / right-top / right-bottom)
184* show_form				
185				Required:			false
186				Type:				boolean
187				Default value:		true
188				Description:		Allows you to hide the form in the widget (and only show HTML code or iframe)
189* custom_html				
190				Required:			false
191				Type:				String
192				Default value:		""
193				Description:		Allows you to use any inline html code that you want, it will be placed inside feedback_me widget
194* delayed_close 
195				Required:			false
196				Type:				boolean
197				Default value:		true
198				Description:		Enable feedback dialog upon feedback sending, a small dialog will be displayed with	appropriate message in the middle
199									of the screen and then fade out (read more about the delayed_options property)
200* delayed_options
201				Required:			false
202				Type:				object
203				Default value:
204									{
205										delay_success_milliseconds : 2000,
206										delay_fail_milliseconds : 2000,
207										sending : "Sending...", //This text will appear on the "send" button while sending
208										send_fail : "Sending failed.", //This text will appear on the fail dialog
209										send_success : "Feedack sent.", //This text will appear on the success dialog
210										fail_color : undefined,
211										success_color : undefined
212									}
213				Description:		Allow to customize the feedback dialog upon feedback sending
214*
215*
216*/
217var fm = (function ($) {
218
219	'use strict';
220
221	var fm_options_arr = {},
222		supportsTransitions = false;
223
224	function getFmOptions(event, position) {
225		var className,
226			selector;
227		if ($(event.target).closest(".feedback_trigger").length === 1) {
228			className = $(event.target).closest(".feedback_trigger")[0].className;
229		} else if ($(event.target).closest(".feedback_content").length === 1) {
230			className = $(event.target).closest(".feedback_content")[0].className;
231		} else {
232			if (position === undefined) {
233				position = 'left-top';
234			}
235			className = position;
236		}
237
238		if (className.indexOf('left-top') !== -1) {
239			selector = 'left-top';
240		} else if (className.indexOf('left-bottom') !== -1) {
241			selector = 'left-bottom';
242		} else if (className.indexOf('right-top') !== -1) {
243			selector = 'right-top';
244		} else if (className.indexOf('right-bottom') !== -1) {
245			selector = 'right-bottom';
246		}
247		return fm_options_arr[selector];
248	}
249
250	function triggerAction(event, position) {
251
252		var animation_show = {},
253			animation_hide = {},
254			$fm_trigger,
255			$fm_content;
256
257		animation_show.marginLeft = "+=380px";
258		animation_hide.marginLeft = "-=380px";
259
260		if (fm.getFmOptions(event, position).position.indexOf("right-") !== -1) {
261			animation_show.marginRight = "+=380px";
262			animation_hide.marginRight = "-=380px";
263		}
264
265		$fm_trigger = $(event.target).closest(".feedback_trigger");
266		if ($fm_trigger.length === 1) {
267			$fm_content = $fm_trigger.next();
268		} else {
269			$fm_content = $(event.target).closest(".feedback_content");
270			$fm_trigger = $fm_content.prev();
271		}
272		if ($fm_content.length === 0 || $fm_trigger.length === 0) {
273			if (position === undefined) {
274				position = 'left-top';
275			}
276			$fm_content = $('.' + position).closest(".feedback_content");
277			$fm_trigger = $fm_content.prev();
278		}
279
280		if ($fm_trigger.hasClass("feedback_trigger_closed")) {
281			if (supportsTransitions === true) {
282				$fm_trigger.removeClass("feedback_trigger_closed");
283				$fm_content.removeClass("feedback_content_closed");
284			} else {
285				$fm_trigger.add($fm_content).animate(
286					animation_show,
287					150,
288					function () {
289						$fm_trigger.removeClass("feedback_trigger_closed");
290						$fm_content.removeClass("feedback_content_closed");
291					}
292				);
293			}
294			$(".feedback_email").focus();
295		} else {
296			//first add the closed class so double (which will trigger closeFeedback function) click wont try to hide the form twice
297			$fm_trigger.addClass("feedback_trigger_closed");
298			$fm_content.addClass("feedback_content_closed");
299			if (supportsTransitions === false) {
300				$fm_trigger.add($fm_content).animate(
301					animation_hide,
302					150
303				);
304			}
305		}
306	}
307
308	function closeFeedback(event) {
309
310		if (($(".feedback_content").length === 1 && $(".feedback_content").hasClass("feedback_content_closed")) ||
311				$(event.target).closest('.feedback_content').length === 1) {
312			return;
313		}
314
315		var animation_hide = {},
316			option;
317		animation_hide.marginLeft = "-=380px";
318		for (option in fm_options_arr) {
319			if (fm_options_arr.hasOwnProperty(option)) {
320				if (option.indexOf("right-") !== -1) {
321					animation_hide.marginRight = "-=380px";
322				}
323
324				$(".feedback_trigger").addClass("feedback_trigger_closed");
325				$(".feedback_content").addClass("feedback_content_closed");
326				if (supportsTransitions === false) {
327					$(".feedback_trigger , .feedback_content").animate(
328						animation_hide,
329						150
330					);
331				}
332			}
333		}
334	}
335
336	function emailValid(str) {
337		var lastAtPos = str.lastIndexOf('@');
338		return (lastAtPos < (str.length - 1) && lastAtPos > 0 && str.indexOf('@@') === -1 && str.length > 2);
339	}
340
341	function validateFeedbackForm(event, position) {
342		var $fm_content = $(event.target).closest(".feedback_content"),
343			fm_options = getFmOptions(event, position);
344		if ((fm_options.name_required === true && $fm_content.find(".feedback_name").val() === "") ||
345				((fm_options.email_required === true && $fm_content.find(".feedback_email").val() === "") || (fm_options.email_required === true && emailValid($fm_content.find(".feedback_email").val()) === false)) ||
346				(fm_options.message_required === true && $fm_content.find(".feedback_message").val() === "") ||
347				(fm_options.radio_button_list_required === true && $fm_content.find("input[name=rating]:checked").val() === undefined)) {
348			return false;
349		}
350		return true;
351
352	}
353
354	function checkPatternFieldsOk(event, position) {
355		var $patternFields = $("." + position + " [pattern]"),
356			form_valid = true,
357			i;
358
359		if ($patternFields.length > 0) {
360			for (i = 0; i < $patternFields.length; i++) {
361				form_valid = !$patternFields[i].validity.patternMismatch;
362				if (form_valid === false) {
363					break;
364				}
365			}
366		}
367		return form_valid;
368	}
369
370	function checkRequiredFieldsOk(event, position) {
371		var $reqFields = $("." + position + " [required]"),
372			form_valid = true;
373
374		if ($reqFields.length > 0) {
375			form_valid = validateFeedbackForm(event, position);
376		}
377		return form_valid;
378	}
379
380	function applyCloseOnClickOutside() {
381		var jqVersion = $().jquery.split(".");
382		jqVersion[0] = +jqVersion[0];
383		jqVersion[1] = +jqVersion[1];
384		if (jqVersion[0] >= 1 && jqVersion[1] >= 7) {
385			$(document).on("click", document, function (event) {
386				closeFeedback(event);
387			});
388		} else {
389			$(document).delegate("body", document, function (event) {
390				closeFeedback(event);
391			});
392		}
393	}
394
395	function appendFeedbackToBody(fm_options) {
396		var form_html = "",
397			iframe_html = "",
398			jQueryUIClasses1 = "",
399			jQueryUIClasses2 = "",
400			jQueryUIClasses3 = "",
401			jQueryUIClasses4 = "",
402			email_html = "",
403			email_feedback_content_class = "",
404			radio_button_list_html = "",
405			radio_button_list_class = "",
406			fm_class = " fm_clean ",
407			jquery_class = "",
408			bootstrap_class = "",
409			bootstrap_btn = "",
410			bootstrap_hero_unit = "",
411
412			name_pattern = fm_options.name_pattern === "" ? "" : "pattern=\"" + fm_options.name_pattern + "\"",
413
414			name_required = fm_options.name_required ? "required" : "",
415			email_required = fm_options.email_required ? "required" : "",
416			message_required = fm_options.message_required ? "required" : "",
417			radio_button_list_required = fm_options.radio_button_list_required ? "required" : "",
418
419			name_asterisk  = fm_options.name_required && fm_options.show_asterisk_for_required ? "<span class=\"required_asterisk\">*</span>" : "",
420			email_asterisk  = fm_options.email_required && fm_options.show_asterisk_for_required ? "<span class=\"required_asterisk\">*</span>" : "",
421			message_asterisk  = fm_options.message_required && fm_options.show_asterisk_for_required ? "<span class=\"required_asterisk\">*</span>" : "",
422			radio_button_list_asterisk = fm_options.radio_button_list_required && fm_options.show_asterisk_for_required ? "<span class=\"required_asterisk\">*</span>" : "";
423
424		if (fm_options.bootstrap === true) {
425			bootstrap_class = " fm_bootstrap ";
426			bootstrap_btn = " btn btn-primary ";
427			bootstrap_hero_unit = " hero-unit ";
428
429			fm_class = "";
430			jquery_class = "";
431		}
432
433		if (fm_options.jQueryUI === true) {
434			jquery_class = " fm_jquery ";
435			jQueryUIClasses1 = " ui-widget-header ui-corner-all ui-helper-clearfix ";
436			jQueryUIClasses2 = " ui-dialog ui-widget ui-widget-content ui-corner-all ";
437			jQueryUIClasses3 = " ui-dialog-titlebar ";
438			jQueryUIClasses4 = " ui-dialog-title ";
439
440			fm_class = "";
441			bootstrap_class = "";
442			bootstrap_hero_unit = "";
443			bootstrap_btn = "";
444
445		}
446
447		if (fm_options.show_radio_button_list === true) {
448			radio_button_list_html = "<li><div class=\"radio_button_list_title_wrapper\"><div class=\"radio_button_list_title\">" + fm_options.radio_button_list_title + radio_button_list_asterisk + "</div></div><span class=\"star-rating star-5\">";
449			radio_button_list_html += "        <input value=\"1\" type=\"radio\" name=\"rating\" class=\"rating_1\" id=\"rating_1\" " + radio_button_list_required + "\/><i></i>";
450			radio_button_list_html += "        <label for=\"rating_1\">" + fm_options.radio_button_list_labels[0] + "<\/label>";
451			radio_button_list_html += "        <input value=\"2\" type=\"radio\" name=\"rating\" class=\"rating_2\" id=\"rating_2\" \/><i></i>";
452			radio_button_list_html += "        <label for=\"rating_2\">" + fm_options.radio_button_list_labels[1] + "<\/label>";
453			radio_button_list_html += "        <input value=\"3\" type=\"radio\" name=\"rating\" class=\"rating_3\" id=\"rating_3\"\/><i></i>";
454			radio_button_list_html += "        <label for=\"rating_3\">" + fm_options.radio_button_list_labels[2] + "<\/label>";
455			radio_button_list_html += "        <input value=\"4\" type=\"radio\" name=\"rating\" class=\"rating_4\" id=\"rating_4\"\/><i></i>";
456			radio_button_list_html += "        <label for=\"rating_4\">" + fm_options.radio_button_list_labels[3] + "<\/label>";
457			radio_button_list_html += "        <input value=\"5\" type=\"radio\" name=\"rating\"  class=\"rating_5\" id=\"rating_5\"\/><i></i>";
458			radio_button_list_html += "        <label for=\"rating_5\">" + fm_options.radio_button_list_labels[4] + "<\/label>";
459			radio_button_list_html += "<\/span></li>";
460
461			radio_button_list_class = " radio_button_list_present";
462		}
463
464		if (fm_options.show_email === true) {
465			email_html = '<li>	<span class="radiolabelspan" style="font-weight: 600;font-family: Arial, Sans-Serif;">' + fm_options.email_label + '</span> ' + email_asterisk + '<input type="email" aria-label="feedback_email" name="feedback_email" aria-required="true" id="feedback_email" autocomplete="email" class="feedback_email" ' + email_required + ' placeholder="' + fm_options.email_placeholder + '"></input> </li>';
466			email_feedback_content_class = " email_present";
467		}
468
469		if (fm_options.show_form === true) {
470			form_html = '<form class="feedback_me_form">'
471				+	'<ul>'
472
473				+		 email_html
474
475				+ '<li>	<span class="radiolabelspan" style="font-weight: 600;font-family: Arial, Sans-Serif;">' + fm_options.message_label + '</span> ' + message_asterisk
476
477				+ ' <textarea rows="5" name="feedback_message" id="feedback_message" aria-required="true"  autocomplete="on" class="feedback_message" ' + message_required + ' onkeydown="textCounter(this,500)" aria-label="feedback_message" onkeyup="textCounter(this,500)" maxlength=500 placeholder="' + fm_options.message_placeholder + '"></textarea> <input id="feedbackLenGoal" aria-label="feedbackLenGoal" style="text-align: right; width:20px; border: none !important; font-size: 8pt; background-color:transparent; color:white" readonly="readonly" type="text"  value="500" autocomplete="on"/> <font style="font-size: 8pt;">character(s) remaining</font></li>'
478
479				+		 radio_button_list_html
480                + '<li><button type="button" style="margin-left: 150px;" onclick="fm.stopPropagation(event);fm.triggerAction(event);">Close</button><button type="submit" onclick="fm.sendFeedback(event,\'' + fm_options.position + '\');" class="feedback_submit ' + bootstrap_btn + '">' + fm_options.submit_label + '</button> </li>'
481				+	'</ul>'
482				+	'</form>';
483		}
484		if (fm_options.iframe_url !== undefined) {
485			iframe_html = '<iframe name="feedback_me_frame" class="feedback_me_frame" frameborder="0" src="' + fm_options.iframe_url + '"></iframe>';
486		}
487
488		$('body').append('<div style="display:none" onclick="fm.stopPropagation(event);fm.triggerAction(event);" class="feedback_trigger feedback_trigger_closed ' + fm_options.position + jQueryUIClasses1 + fm_class + jquery_class + bootstrap_class + bootstrap_hero_unit + ' hidden-print">'
489				+	'<span class="feedback_trigger_text">' + fm_options.trigger_label
490				+	'</span></div>');
491
492		$('body').append('<div class="feedback_content feedback_content_closed ' + fm_options.position + email_feedback_content_class + radio_button_list_class + jQueryUIClasses2 + fm_class + jquery_class + bootstrap_class + bootstrap_hero_unit + ' hidden-print">'
493							+ '<div class="feedback_title ' + jQueryUIClasses1 + jQueryUIClasses3 + '">'
494							+	'<span class="' + jQueryUIClasses4 + '">' + fm_options.title_label + '</span>'
495							+ '</div>'
496							+  form_html
497							+  iframe_html
498							+  fm_options.custom_html
499						+ '</div>');
500
501		if (fm_options.jQueryUI === true) {
502			$('.feedback_submit').button({
503				icons: {
504					primary: 'ui-icon-mail-closed'
505				}
506			});
507		}
508
509		if (fm_options.close_on_click_outside === true) {
510			applyCloseOnClickOutside();
511		}
512
513		//prevent form submit (needed for validation)
514		$('.feedback_me_form').submit(function (event) {
515			event.preventDefault();
516		});
517
518	}
519
520	function stopPropagation(evt) {
521		if (evt.stopPropagation !== undefined) {
522			evt.stopPropagation();
523		} else {
524			evt.cancelBubble = true;
525		}
526	}
527
528	function slideBack(fm_options, $fm_trigger, $fm_content) {
529		var animation_hide = {};
530		animation_hide.marginLeft = "-=380px";
531		if (fm_options.position.indexOf("right-") !== -1) {
532			animation_hide.marginRight = "-=380px";
533		}
534
535		if (supportsTransitions === true) {
536			$fm_trigger.addClass("feedback_trigger_closed");
537			$fm_content.addClass("feedback_content_closed");
538		} else {
539			$fm_trigger.add($fm_content).animate(
540				animation_hide,
541				150,
542				function () {
543					$fm_trigger.addClass("feedback_trigger_closed");
544				}
545			);
546		}
547	}
548	function clearInputs(event) {
549		var $fm_content = $(event.target).closest(".feedback_content");
550
551		$fm_content.find(".feedback_name").val("");
552		$fm_content.find(".feedback_message").val("");
553		$fm_content.find(".feedback_email").val("");
554		$fm_content.find(".feedback_me_form input[name=rating]").prop('checked', false);
555	}
556
557	function sendFeedback(event, position) {
558		var checkValid = checkRequiredFieldsOk(event, position),
559			checkPattern = checkPatternFieldsOk(event, position),
560			dataArray,
561			$fm_trigger,
562			$fm_content,
563			fm_options = getFmOptions(event, position);
564
565		if (checkValid === false || checkPattern === false) {
566			stopPropagation(event);
567			return;
568		}
569
570		$fm_content = $(event.target).closest(".feedback_content");
571		$fm_trigger = $(event.target).closest(".feedback_content").prev();
572
573		if (fm_options.delayed_close === true) {
574			$fm_content.find('.feedback_submit').text(fm_options.delayed_options.sending);
575		}
576
577	    var email = $fm_content.find(".feedback_email").val();
578	    var message = $fm_content.find(".feedback_message").val();
579        message += "\n\n" + FS.getCurrentSessionURL(true);
580	    var rating = $fm_content.find(".feedback_me_form input[name=rating]:checked").val();
581
582		dataArray = {
583			"name": $fm_content.find(".feedback_name").val(),
584			"message": message,
585			"email": email,
586			"radio_list_value": rating,
587			"url": $(location).attr('href')
588		};
589
590		dataArray = $.extend(fm_options.custom_params, dataArray);
591
592		$.ajax({
593			type: 'POST',
594			url: fm_options.feedback_url,
595			data: dataArray,
596			beforeSend: function (xhr) {
597				if (fm_options.delayed_close === false) {
598					slideBack(fm_options, $fm_trigger, $fm_content);
599				}
600			},
601			success: function (data) {
602				var st = "";
603				fm.clearInputs(event);
604				if (fm_options.delayed_close === true) {
605					if (fm_options.delayed_options.success_color !== undefined) {
606						st = ' style="background-color:' + fm_options.delayed_options.success_color + '" ';
607					}
608					$fm_content.find('.feedback_submit').text(fm_options.submit_label);
609					slideBack(fm_options, $fm_trigger, $fm_content);
610					$("body").append('<div ' + st + ' class="feedback-delayed-dlg success" onclick="fm.stopPropagation(event);"><span class="feedback-dlg-close" onclick="fm.closeFeedbackDelayedDlg();">X</span><span class="feedback-sucess-message">' +
611						'<span class="feedback-sucess-fail-message-inner"><span>' + fm_options.delayed_options.send_success + '</span></span></span></div>');
612					setTimeout(function () {$(".feedback-delayed-dlg").fadeOut(function () { $(this).remove(); }); }, fm_options.delayed_options.delay_success_milliseconds);
613				}
614            },
615			error: function (ob, errStr) {
616				var st = "";
617				if (fm_options.delayed_close === true) {
618					if (fm_options.delayed_options.fail_color !== undefined) {
619						st = ' style="background-color:' + fm_options.delayed_options.fail_color + '" ';
620					}
621					$fm_content.find('.feedback_submit').text(fm_options.submit_label);
622					$("body").append('<div ' + st + ' class="feedback-delayed-dlg fail" onclick="fm.stopPropagation(event);"><span class="feedback-dlg-close" onclick="fm.closeFeedbackDelayedDlg();">X</span><span class="feedback-fail-message">' +
623						'<span class="feedback-sucess-fail-message-inner"><span>' + fm_options.delayed_options.send_fail + '</span></span></span></div>');
624					setTimeout(function () {$(".feedback-delayed-dlg").fadeOut(function () { $(this).remove(); }); }, fm_options.delayed_options.delay_fail_milliseconds);
625				} else {
626					console.log("Failed to send feedback (please double check your feedback_url parameter)");
627				}
628				clearInputs(event);
629			}
630		});
631
632	    sendFeedbackToSlack(email, message, rating);
633	}
634
635    function sendFeedbackToSlack(email, message, rating) {
636        $.ajax({
637            url: "/api/sitecore/Feedback/SendFeedback",
638            method: "POST",
639            data: {
640                "Message": message,
641                "Email": email,
642                "Rating": rating
643            }
644        });
645    }
646
647	function closeFeedbackDelayedDlg() {
648		$(".feedback-delayed-dlg").fadeOut();
649	}
650
651	function detectTransitionSupport() {
652		var be = document.body || document.documentElement,
653			style = be.style,
654			p = 'transition',
655			vendors,
656			i;
657		if (typeof style[p] === 'string') {
658			supportsTransitions = true;
659			return;
660		}
661
662		vendors = ['Moz', 'Webkit', 'Khtml', 'O', 'ms'];
663		p = p.charAt(0).toUpperCase() + p.substr(1);
664		for (i = 0; i < vendors.length; i++) {
665			if (typeof style[vendors[i] + p] === 'string') {
666				supportsTransitions = true;
667				return;
668			}
669		}
670		supportsTransitions = false;
671		return;
672	}
673
674	function init(options) {
675
676		var default_options = {
677			feedback_url : "",
678			position : "left-top",
679			jQueryUI : false,
680			bootstrap : false,
681			show_email : false,
682			show_radio_button_list : false,
683			close_on_click_outside: true,
684			name_label : "Name",
685			email_label : "Email",
686			message_label : "Message",
687			radio_button_list_labels : ["1", "2", "3", "4", "5"],
688			radio_button_list_title : "How would you rate my site?",
689			name_placeholder : "",
690			email_placeholder : "",
691			message_placeholder : "",
692			name_pattern : "",
693			name_required : false,
694			email_required : false,
695			message_required: false,
696			radio_button_list_required : false,
697			show_asterisk_for_required : false,
698			submit_label : "Send",
699			title_label : "Feedback",
700			trigger_label : "Feedback",
701			custom_params : {},
702			iframe_url : undefined,
703			show_form: true,
704			custom_html : "",
705			delayed_close : true,
706			delayed_options : {
707				delay_success_milliseconds : 2000,
708				delay_fail_milliseconds : 2000,
709				sending : "Sending...",
710				send_fail : "Sending failed.",
711				send_success : "Feedack sent.",
712				fail_color : undefined,
713				success_color : undefined
714			}
715		},
716			tmp_options,
717			tmp_delayed_options;
718
719		tmp_delayed_options = $.extend(default_options.delayed_options, options.delayed_options);
720
721		tmp_options = $.extend(default_options, options);
722		tmp_options.delayed_options = tmp_delayed_options;
723
724		fm_options_arr[tmp_options.position] = tmp_options;
725
726		appendFeedbackToBody(tmp_options);
727
728		detectTransitionSupport(tmp_options);
729	}
730
731    return {
732		init : init,
733		sendFeedback : sendFeedback,
734		getFmOptions : getFmOptions,
735		triggerAction : triggerAction,
736		stopPropagation : stopPropagation,
737		clearInputs : clearInputs,
738		closeFeedbackDelayedDlg : closeFeedbackDelayedDlg
739    };
740
741}(jQuery));

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.