├── bower.json
├── feedback_me.jquery.json
├── examples
├── example_page.php
└── example_send_feedback.php
├── MIT-LICENSE.txt
├── ChangeLog.markdown
├── README.md
├── css
└── jquery.feedback_me.css
└── js
└── jquery.feedback_me.js
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Daniel Reznick",
3 | "name": "feedback_me",
4 | "description": "This jQuery plug-in allows user to easily add an animatable UI widget with a feedback form which slides from the side of the screen.",
5 | "version": "0.5.8",
6 | "homepage": "http://feedback-me.appspot.com/",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/vedmack/feedback_me"
10 | },
11 | "main": [
12 | "js/jquery.feedback_me.js",
13 | "css/jquery.feedback_me.css"
14 | ],
15 | "dependencies": {
16 | "jquery": ">=1.4.0"
17 | },
18 | "keywords": [
19 | "jquery",
20 | "feedback",
21 | "plugin",
22 | "slide",
23 | "form"
24 | ],
25 | "ignore": [
26 | "feedback_me.jquery.json"
27 | ]
28 | }
--------------------------------------------------------------------------------
/feedback_me.jquery.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "feedback_me",
3 | "title": "jQuery Feedback Me Plugin",
4 | "description": "This jQuery plug-in allows user to easily add an animatable UI widget with a feedback form which slides from the side of the screen.",
5 | "keywords": [
6 | "jquery",
7 | "feedback",
8 | "plugin",
9 | "slide",
10 | "form"
11 | ],
12 | "version": "0.5.8",
13 | "author": {
14 | "name": "Daniel Reznick",
15 | "url": "https://github.com/vedmack"
16 | },
17 | "licenses": [
18 | {
19 | "type": "MIT",
20 | "url": "http://www.opensource.org/licenses/mit-license.php"
21 | }
22 | ],
23 | "bugs": "https://github.com/vedmack/feedback_me/issues",
24 | "homepage": "http://feedback-me.appspot.com/",
25 | "docs": "https://github.com/vedmack/feedback_me/blob/master/README.md",
26 | "download": "https://github.com/vedmack/feedback_me/archive/master.zip",
27 | "dependencies": {
28 | "jquery": ">=1.4"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/examples/example_page.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/MIT-LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015, Daniel Reznick, vedmack@gmail.com
2 | All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ChangeLog.markdown:
--------------------------------------------------------------------------------
1 | # jQuery Feedback Me Plugin ChangeLog
2 |
3 | ## 0.5.9 (still beta)
4 |
5 | * Closed issues https://github.com/vedmack/feedback_me/issues/40
6 |
7 |
8 | ## 0.5.8
9 |
10 | * Added custom template for the delayed_options, custom_html_success and custom_html_fail are part of the delayed_options, https://github.com/vedmack/feedback_me/issues/33
11 | * Added extend for the global ajax beforeSend, https://github.com/vedmack/feedback_me/issues/34
12 |
13 |
14 | ## 0.5.7
15 |
16 | * IE8 Support
17 | * Improved the Multiple feedbacks mode
18 | * Bugs fix
19 |
20 |
21 | ## 0.5.6
22 |
23 | * Customizable pattern attribute: "name_pattern" for name input (https://github.com/vedmack/feedback_me/issues/27)
24 | * Allow jQuery.noConflict (https://github.com/vedmack/feedback_me/issues/25)
25 | * Minor fix (https://github.com/vedmack/feedback_me/issues/26)
26 |
27 | ## 0.5.5
28 |
29 | * Added highly customizable notification response for success/fail feedback sending (https://github.com/vedmack/feedback_me/issues/21)
30 | * Bug fix (https://github.com/vedmack/feedback_me/issues/24)
31 |
32 |
33 | ## 0.5.2
34 |
35 | * Added support for multiple feedbacks on page (https://github.com/vedmack/feedback_me/issues/19)
36 | * As part of the multiple feedback feature implementation ALL ids were replaced with classes (e.g #feedback_content is now .feedback_content)
37 | * Bug fix
38 |
39 |
40 | ## 0.4.8
41 |
42 | * Added "custom_html" option to allow the use of inline html code that will be embeded inside feedback_me widget (thanks to miguelfontanes)
43 | * Added "show_form" option to allow the external iframe/inline html code to appear with the original form or replace it
44 | * CSS improvements colors / rounded coreners / trigger text location / etc...
45 | * API change , when using "iframe_url" you should fedback me form explicitly: set "show_form" to false (untill now the form was hidden implicitly by default) , same goes for "custom_html"
46 |
47 |
48 | ## 0.4.6
49 |
50 | * Remove jQuery UI dependencies (the only additional required library for the plugin is jQuery) https://github.com/vedmack/feedback_me/issues/14
51 | * Bug fix clear input fields upon sending feedback, https://github.com/vedmack/feedback_me/issues/15
52 |
53 |
54 | ## 0.4.4
55 |
56 | * Fixed jquery version check for using on instead of delegate (IE specific issue)
57 |
58 |
59 | ## 0.4.3
60 |
61 | * Using CSS3 Transition for sliding out the feedback widget - jquery UI ased as a fallback for older browsers (since this version jquery UI is not a must to include).
62 |
63 |
64 | ## 0.4.0
65 |
66 | * Added "iframe_url" option to allow the use of any html file that you want, html file will be embeded inside feedback_me widget.
67 |
68 |
69 | ## 0.3.8
70 |
71 | * Bug fix Prevent form submit when there is no use in required inputs, https://github.com/vedmack/feedback_me/issues/8
72 |
73 |
74 | ## 0.3.7
75 |
76 | * Added "custom_params" option to send additional data to the server (can be used for sending: csrf token / logged in user_name / etc`)
77 |
78 |
79 | ## 0.3.4
80 |
81 | * Added option to set the position of the feedback widget (4 possible locations) : left-top / left-bottom / right-top / right-bottom
82 |
83 |
84 | ## 0.3.2
85 |
86 | * Email input is now using HTML5 type + added simple email validation
87 |
88 |
89 | ## 0.3.1
90 |
91 | * Fixed IE8 style issues
92 |
93 |
94 | ## 0.3.0
95 |
96 | * Added optional radio button list input (5 radio buttons), can be used to rank something or any other purpose, all labels of the radios are customizable (string array) and it can be set to required too + its title is also customizable
97 | * Fixed several IE8 js issues
98 |
99 |
100 | ## 0.2.7
101 |
102 | * Added optional required attribute (HTML5) for all input fields with homegrown validation
103 | * Added optional asterisk next to label of required input fields
104 |
105 |
106 | ## 0.2.5
107 |
108 | * Added customizable placeholder (HTML5) for all input fields
109 | * Better font and appearance
110 |
111 |
112 | ## 0.2.1
113 |
114 | * Changed close_on_click_outisde option to be true by default
115 | * Bug fix
116 |
117 |
118 | ## 0.2.0
119 |
120 | * Added close_on_click_outisde option (default is false)
121 | * Several code enhancements
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | jQuery Feedback Me Plugin
2 | ===========
3 |
4 | Description:
5 | =====
6 |
7 | This jQuery plug-in allows user to easily add an animatable UI widget with a feedback form which slides from the side of the screen.
8 |
9 |
10 | Contact/Social:
11 | =====
12 | If you want to ask a question use my [google group](https://groups.google.com/forum/#!forum/daniels_code)
13 |
14 | If you like my plugin, you can show your appreciation by following me in [Twitter](https://twitter.com/danielreznick) / [GitHub](https://github.com/vedmack).
15 |
16 |
17 | Features:
18 | =====
19 |
20 | - Using CSS3 Transition for sliding out the feedback widget (jquery used as a fallback for older browsers)
21 | - Multiple feedbacks on page (different locations)
22 | - Growl alike and super customizable dialog response for success/fail feedback sending
23 | - Highly customizable notification response for success/fail feedback sending
24 | - Bootstrap support
25 | - jQuery UI themes support
26 | - 4 different possible locations to place the widget
27 | - Using AJAX post to send data to server ('name', 'message' and 'email' parameters will be send to your servlet/php file etc...)
28 | - Ability to send additional custom params to server (csrf token / logged in user_name / etc`)
29 | - Ability to embed any external html file inside the feedback_me widget for maximum customization
30 | - Ability to embed inline html code inside the feedback_me widget for more customizations
31 | - RTL support (except in 0.5.2 version)
32 | - All labels are customizable
33 | - Customizable placeholder (HTML5) for all input fields
34 | - Optional required attribute (HTML5) for all input fields with homegrown validation
35 | - Optional asterisk next to label of required input fields
36 | - Optional pattern attribute (HTML5) for name input field with homegrown validation
37 |
38 |
39 |
40 | Examples:
41 | =====
42 |
43 | [Clean example](http://feedback-me.appspot.com/example_clean.html)
44 |
45 | [Clean complex example](http://feedback-me.appspot.com/example_clean_complex.html)
46 |
47 | [jQuery UI theme aware example](http://feedback-me.appspot.com/example_jqueryUI.html)
48 |
49 | [Bootstrap example](http://feedback-me.appspot.com/example_bootstrap.html)
50 |
51 | [External IFrame Example](http://feedback-me.appspot.com/example_external_iframe.html)
52 |
53 | [Custom Html Example](http://feedback-me.appspot.com/example_custom_html.html)
54 |
55 | [Multiple Feedbacks Example](http://feedback-me.appspot.com/example_clean_multiple.html)
56 |
57 | Usage:
58 | =====
59 |
60 | ```javascript
61 | $(document).ready(function(){
62 | fm_options = {
63 | jQueryUI : true,
64 | position : "left-bottom",
65 | name_placeholder:"Name please",
66 | trigger_label : "Click me",
67 | message_required : true,
68 | show_asterisk_for_required : true,
69 | feedback_url : "send_feedback"
70 | };
71 |
72 | fm.init(fm_options);
73 | });
74 | ```
75 |
76 | All available parameters + default settings (detailed explanation inside jquery.feedback_me.js) :
77 |
78 | ```javascript
79 | var default_options = {
80 | feedback_url : "",
81 | position : "left-top",
82 | jQueryUI : false,
83 | bootstrap : false,
84 | show_email : false,
85 | show_radio_button_list : false,
86 | close_on_click_outisde: true,
87 | name_label : "Name",
88 | email_label : "Email",
89 | message_label : "Message",
90 | radio_button_list_labels : ["1", "2", "3", "4", "5"],
91 | radio_button_list_title : "How would you rate my site?",
92 | name_placeholder : "",
93 | email_placeholder : "",
94 | message_placeholder : "",
95 | name_required : false,
96 | email_required : false,
97 | message_required : false,
98 | radio_button_list_required : false,
99 | show_asterisk_for_required : false,
100 | submit_label : "Send",
101 | title_label : "Feedback",
102 | trigger_label : "Feedback",
103 | custom_params : {},
104 | iframe_url : undefined,
105 | show_form: true,
106 | custom_html: "",
107 | delayed_close : true,
108 | delayed_options : {
109 | delay_success_milliseconds : 2000,
110 | delay_fail_milliseconds : 2000,
111 | sending : "Sending...",
112 | send_fail : "Sending failed.",
113 | send_success : "Feedack sent.",
114 | fail_color : undefined,
115 | success_color : undefined,
116 | custom_html_success: undefined,
117 | custom_html_fail: undefined
118 | }
119 | };
120 | ```
121 |
122 |
123 | License:
124 | =====
125 |
126 | Copyright (c) 2015 Daniel Reznick, released under the MIT license
127 |
128 |
--------------------------------------------------------------------------------
/examples/example_send_feedback.php:
--------------------------------------------------------------------------------
1 |
20 | Optionally, either storing to a database or emailing can be disabled by setting the corresponding global variable - 'feedback_me_db' or 'feedback_me_mail' - to FALSE.
21 | ************************************************/
22 |
23 | /***
24 | error_reporting (-1);
25 | ini_set ('display_errors', 'On');
26 | ***/
27 |
28 | ini_set ('output_buffering', 'Off');
29 | while (@ob_end_flush());
30 |
31 | date_default_timezone_set ('UTC');
32 |
33 | ini_set ('php.internal_encoding', 'UTF-8');
34 | mb_internal_encoding ('UTF-8');
35 |
36 | if (file_exists ('../private/fme_config.php'))
37 | {
38 | require_once ('../private/fme_config.php');
39 | } else { Result ('error'); }
40 |
41 | if (file_exists ('swift/lib/swift_required.php'))
42 | {
43 | require_once ('swift/lib/swift_required.php');
44 | } else { Result ('error'); }
45 |
46 | /***********************************************/
47 | function Result ($sStatus)
48 | /***********************************************/
49 | {
50 | /***
51 | The success() function of jquery.feedback_me.js does not check
52 | if (data['error']) { } else { }. This is the reason we do not
53 | use the dataType:'json' response below, but instead use a
54 | response that will forcefully trigger the error() function if
55 | necessary.
56 |
57 | $arResponse[$sStatus] = TRUE;
58 | header ('Content-type: application/json');
59 | print (json_encode ($arResponse));
60 | ***/
61 |
62 | switch ($sStatus)
63 | {
64 | case 'success':
65 | http_response_code (200); /*** 200 = OK ***/
66 | break;
67 | case 'error':
68 | default:
69 | http_response_code (404); /*** 404 = Not Found ***/
70 | break;
71 | }
72 | }
73 | /***********************************************/
74 | function FeedbackDB ($arFeedback)
75 | /***********************************************/
76 | {
77 | /*** Database. ***/
78 | $GLOBALS['link'] = mysqli_init();
79 | if ($GLOBALS['link'] == FALSE) { return (FALSE); }
80 | if (!@mysqli_real_connect ($GLOBALS['link'], $GLOBALS['db_host'],
81 | $GLOBALS['db_user'], $GLOBALS['db_pass'], $GLOBALS['db_dtbs']))
82 | { return (FALSE); }
83 | mysqli_set_charset ($GLOBALS['link'], 'utf8');
84 |
85 | /*** Create table. ***/
86 | $query_table = "CREATE TABLE IF NOT EXISTS `feedback_me` (
87 | `feedback_id` INT(10) UNIQUE NOT NULL AUTO_INCREMENT,
88 | `feedback_name` VARCHAR(255) NOT NULL,
89 | `feedback_email` VARCHAR(255) NOT NULL,
90 | `feedback_message` VARCHAR(255) NOT NULL,
91 | `feedback_website` VARCHAR(255) NOT NULL,
92 | `feedback_ip` VARCHAR(45) NOT NULL,
93 | `feedback_date` DATETIME NOT NULL,
94 | PRIMARY KEY (`feedback_id`));";
95 | $result_table = mysqli_query ($GLOBALS['link'], $query_table);
96 |
97 | /*** Insert feedback. ***/
98 | $query_feedback = "INSERT INTO `feedback_me` VALUES (NULL, '" .
99 | mysqli_real_escape_string ($GLOBALS['link'],
100 | $arFeedback['name']) . "', '" .
101 | mysqli_real_escape_string ($GLOBALS['link'],
102 | $arFeedback['email']) . "', '" .
103 | mysqli_real_escape_string ($GLOBALS['link'],
104 | $arFeedback['message']) . "', '" .
105 | $arFeedback['website'] . "', '" .
106 | $arFeedback['ip'] . "', '" .
107 | $arFeedback['datetime'] . "');";
108 | $result_feedback = mysqli_query ($GLOBALS['link'], $query_feedback);
109 |
110 | if (mysqli_affected_rows ($GLOBALS['link']) == 1)
111 | {
112 | $bResult = TRUE;
113 | } else {
114 | $bResult = FALSE;
115 | }
116 | mysqli_close ($GLOBALS['link']);
117 |
118 | return ($bResult);
119 | }
120 | /***********************************************/
121 | function FeedbackMail ($arFeedback)
122 | /***********************************************/
123 | {
124 | /*** Subject. ***/
125 | $sSubject = '[ ' . $arFeedback['website'] . ' ] Feedback';
126 |
127 | /*** Message. ***/
128 | $sMessage = '';
129 | if (!empty ($arFeedback['name']))
130 | { $sMessage .= 'Name: ' . $arFeedback['name'] . '
'; }
131 | if (!empty ($arFeedback['email']))
132 | { $sMessage .= 'Email: ' . $arFeedback['email'] . '
'; }
133 | $sMessage .= 'IP: ' . $arFeedback['ip'] . '
';
134 | $sMessage .= nl2br ($arFeedback['message']);
135 |
136 | $transport = Swift_SmtpTransport::newInstance(
137 | $GLOBALS['smtp_host'],
138 | $GLOBALS['smtp_port'])
139 | ->setUsername($GLOBALS['smtp_user'])
140 | ->setPassword($GLOBALS['smtp_pass'])
141 | ;
142 | $mailer = Swift_Mailer::newInstance($transport);
143 |
144 | $message = Swift_Message::newInstance()
145 | ->setSubject($sSubject)
146 | ->setFrom(array($GLOBALS['smtp_user'] => 'Feedback Me'))
147 | ->setTo($GLOBALS['mail_to'])
148 | ->setBody(
149 | '' .
150 | '' .
151 | '' .
152 | $sMessage .
153 | '' .
154 | '',
155 | 'text/html'
156 | );
157 | ;
158 |
159 | try {
160 | $bResult = $mailer->send($message);
161 | } catch (Exception $e) {
162 | /***
163 | file_put_contents ('../private/error_log.txt',
164 | $e->getMessage(), FILE_APPEND);
165 | ***/
166 | $bResult = FALSE;
167 | }
168 |
169 | return ($bResult);
170 | }
171 | /***********************************************/
172 | function GetIP ()
173 | /***********************************************/
174 | {
175 | $arServer = array (
176 | 'HTTP_CLIENT_IP',
177 | 'HTTP_X_FORWARDED_FOR',
178 | 'HTTP_X_FORWARDED',
179 | 'HTTP_X_CLUSTER_CLIENT_IP',
180 | 'HTTP_FORWARDED_FOR',
181 | 'HTTP_FORWARDED',
182 | 'REMOTE_ADDR'
183 | );
184 | foreach ($arServer as $sServer)
185 | {
186 | if (array_key_exists ($sServer, $_SERVER) === TRUE)
187 | {
188 | foreach (explode (',', $_SERVER[$sServer]) as $sIP)
189 | {
190 | if (filter_var ($sIP, FILTER_VALIDATE_IP) !== FALSE)
191 | { return ($sIP); }
192 | }
193 | }
194 | }
195 | return ('unknown');
196 | }
197 | /***********************************************/
198 |
199 | if (strtoupper ($_SERVER['REQUEST_METHOD']) === 'POST')
200 | {
201 | if ((isset ($_POST['name'])) &&
202 | (isset ($_POST['email'])) &&
203 | (isset ($_POST['message'])) &&
204 | (!empty ($_POST['message'])))
205 | {
206 | $arFeedback = array();
207 | $arFeedback['name'] = htmlspecialchars ($_POST['name'], ENT_QUOTES);
208 | $arFeedback['email'] = htmlspecialchars ($_POST['email'], ENT_QUOTES);
209 | $arFeedback['message'] = htmlspecialchars ($_POST['message'], ENT_QUOTES);
210 | $arFeedback['website'] = $GLOBALS['feedback_me_website_name'];
211 | $arFeedback['ip'] = GetIP();
212 | $arFeedback['datetime'] = date ('Y-m-d H:i:s');
213 |
214 | $bResultDB = TRUE;
215 | if ($GLOBALS['feedback_me_db'] == TRUE)
216 | { $bResultDB = FeedbackDB ($arFeedback); }
217 |
218 | $bResultMail = TRUE;
219 | if ($GLOBALS['feedback_me_mail'] == TRUE)
220 | { $bResultMail = FeedbackMail ($arFeedback); }
221 |
222 | if (($bResultDB != FALSE) && ($bResultMail != FALSE))
223 | {
224 | Result ('success');
225 | } else {
226 | Result ('error');
227 | }
228 | } else { Result ('error'); }
229 | } else { Result ('error'); }
230 | ?>
231 |
--------------------------------------------------------------------------------
/css/jquery.feedback_me.css:
--------------------------------------------------------------------------------
1 | .feedback_content, .feedback_trigger {
2 | font-size: 16px;
3 | font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, sans-serif;
4 |
5 | -webkit-transition: all 500ms ease-in-out;
6 | -moz-transition: all 500ms ease-in-out;
7 | -o-transition: all 500ms ease-in-out;
8 | transition: all 500ms ease-in-out;
9 | }
10 |
11 | .feedback_content ul {
12 | list-style: none;
13 | padding-left: 11px;
14 | }
15 |
16 | .feedback_trigger{
17 | cursor: pointer;
18 | -webkit-border-top-left-radius: 0px;
19 | -moz-border-radius-topleft: 0px;
20 | border-top-left-radius: 0px;
21 | -webkit-border-bottom-left-radius: 0px;
22 | -moz-border-radius-bottomleft: 0px;
23 | border-bottom-left-radius: 0px;
24 | z-index: 2001;
25 | }
26 |
27 | .feedback_trigger.left-top, .feedback_trigger.left-bottom , .feedback_trigger.right-top, .feedback_trigger.right-bottom {
28 | width: 40px;
29 | height: 100px;
30 | }
31 |
32 | .feedback_trigger.bottom-left{
33 | width: 100px;
34 | height: 40px;
35 | }
36 |
37 | .feedback_content {
38 | width: 380px;
39 | height: 300px;
40 | z-index: 2001;
41 | }
42 |
43 | .feedback_content.email_present {
44 | height: 360px;
45 | }
46 |
47 | .feedback_content ul li {
48 | margin-right: 20px;
49 | margin-bottom: 20px;
50 | }
51 |
52 | .feedback_content label {
53 | display: inline-block;
54 | }
55 |
56 | .feedback_name {
57 | display: block;
58 | width: 340px;
59 | }
60 |
61 | .feedback_email {
62 | display: block;
63 | width: 340px;
64 | }
65 |
66 | .feedback_message {
67 | display: block;
68 | width: 340px;
69 | resize: none;
70 | }
71 |
72 | .feedback_submit {
73 | float: right;
74 | }
75 |
76 | .feedback_trigger_text {
77 | white-space: nowrap;
78 | position: absolute;
79 | top: 40px;
80 | letter-spacing: 2px;
81 | font-size: 17px;
82 | }
83 |
84 | .left-top .feedback_trigger_text , .left-bottom .feedback_trigger_text , .right-top .feedback_trigger_text , .right-bottom .feedback_trigger_text {
85 | white-space: nowrap;
86 | position: absolute;
87 | top: 40px;
88 | letter-spacing: 2px;
89 | font-size: 17px;
90 | -webkit-transform: rotate(-90deg);
91 | -moz-transform: rotate(-90deg);
92 | -ms-transform: rotate(-90deg);
93 | -o-transform: rotate(-90deg);
94 | filter:none;
95 | }
96 |
97 | .fm_clean {
98 | background-color: #DDDDDD;
99 | }
100 |
101 | .fm_clean.feedback_trigger:hover {
102 | background-color: #CCCCCC;
103 | }
104 |
105 | .fm_clean button{
106 | padding: 5px 10px;
107 | display: inline;
108 | background: #777;
109 | border: none;
110 | color: #fff;
111 | cursor: pointer;
112 | font-weight: bold;
113 | border-radius: 5px;
114 | -moz-border-radius: 5px;
115 | -webkit-border-radius: 5px;
116 | text-shadow: 1px 1px #666;
117 | }
118 |
119 | .fm_clean button:hover {
120 | background-color: #9C9A9A;
121 | }
122 |
123 | .fm_clean .feedback_trigger_text {
124 | right: -25px;
125 | }
126 |
127 | .fm_clean .feedback_title {
128 | padding-top: 5px;
129 | }
130 |
131 | .fm_clean .feedback_title span {
132 | margin-left: 10px;
133 | }
134 |
135 | .feedback_content.fm_clean.feedback_content_closed.left-top, .feedback_content.fm_clean.feedback_content_closed.left-bottom{
136 | margin-left: -380px;
137 | }
138 |
139 | .feedback_content.fm_clean.left-top, .feedback_content.fm_clean.left-bottom{
140 | margin-left: 0px;
141 | -webkit-border-bottom-right-radius: 6px;
142 | -moz-border-bottom-right-radius: 6px;
143 | border-bottom-right-radius: 6px;
144 | -webkit-border-top-right-radius: 6px;
145 | -moz-border-top-right-radius: 6px;
146 | border-top-right-radius: 6px;
147 | }
148 |
149 | .feedback_trigger.fm_clean.feedback_trigger_closed.left-top, .feedback_trigger.fm_clean.feedback_trigger_closed.left-bottom{
150 | margin-left: 0px;
151 | }
152 |
153 | .feedback_trigger.fm_clean.left-top, .feedback_trigger.fm_clean.left-bottom{
154 | margin-left: 380px;
155 | -webkit-border-bottom-right-radius: 6px;
156 | -moz-border-bottom-right-radius: 6px;
157 | border-bottom-right-radius: 6px;
158 | -webkit-border-top-right-radius: 6px;
159 | -moz-border-top-right-radius: 6px;
160 | border-top-right-radius: 6px;
161 | }
162 |
163 | .feedback_content.fm_jquery.feedback_content_closed.left-top, .feedback_content.fm_jquery.feedback_content_closed.left-bottom {
164 | margin-left: -382px;
165 | }
166 |
167 | .feedback_content.fm_jquery.left-top, .feedback_content.fm_jquery.left-bottom {
168 | margin-left: 0px;
169 | }
170 |
171 | .feedback_trigger.fm_jquery.feedback_trigger_closed.left-top, .feedback_trigger.fm_jquery.feedback_trigger_closed.left-bottom {
172 | margin-left: 0px;
173 | }
174 |
175 | .feedback_trigger.fm_jquery.left-top, .feedback_trigger.fm_jquery.left-bottom {
176 | margin-left: 382px;
177 | -webkit-border-bottom-right-radius: 6px;
178 | -moz-border-bottom-right-radius: 6px;
179 | border-bottom-right-radius: 6px;
180 | -webkit-border-top-right-radius: 6px;
181 | -moz-border-top-right-radius: 6px;
182 | border-top-right-radius: 6px;
183 | -webkit-border-bottom-left-radius: 0;
184 | -moz-border-bottom-left-radius: 0;
185 | border-bottom-left-radius: 0;
186 | -webkit-border-top-left-radius: 0;
187 | -moz-border-top-left-radius: 0;
188 | border-top-left-radius: 0;
189 | }
190 |
191 | .fm_jquery .feedback_trigger_text {
192 | right: -20px;
193 | }
194 |
195 | .fm_jquery.feedback_content {
196 | padding: 0px;
197 | width: 380px;
198 | height: 340px;
199 | }
200 |
201 | .fm_jquery.feedback_content.email_present {
202 | height: 390px;
203 | }
204 |
205 |
206 | .fm_jquery.feedback_trigger{
207 | padding: 0px;
208 | border: 0px;
209 | }
210 |
211 | .feedback_content.fm_bootstrap.feedback_content_closed.left-top, .feedback_content.fm_bootstrap.feedback_content_closed.left-bottom {
212 | margin-left: -380px;
213 | }
214 |
215 | .feedback_content.fm_bootstrap.left-top, .feedback_content.fm_bootstrap.left-bottom {
216 | margin-left: 0px;
217 | }
218 |
219 | .feedback_trigger.fm_bootstrap.feedback_trigger_closed.left-top, .feedback_trigger.fm_bootstrap.feedback_trigger_closed.left-bottom {
220 | margin-left: 0px;
221 | }
222 |
223 | .feedback_trigger.fm_bootstrap.left-top, .feedback_trigger.fm_bootstrap.left-bottom {
224 | margin-left: 380px;
225 | }
226 |
227 |
228 | .fm_bootstrap .feedback_trigger_text {
229 | right: -25px;
230 | }
231 |
232 | .fm_bootstrap.hero-unit {
233 | padding:0px;
234 | }
235 |
236 | .fm_bootstrap.hero-unit ul {
237 | margin-left:15px;
238 | }
239 |
240 | .fm_bootstrap .feedback_title {
241 | margin-bottom: 10px;
242 | }
243 |
244 | .fm_bootstrap .feedback_title span {
245 | margin-left: 15px;
246 | }
247 |
248 | .fm_bootstrap .feedback_trigger_text {
249 | top: 35px;
250 | }
251 |
252 | .fm_bootstrap.feedback_content ul {
253 | padding: 0px;
254 | }
255 |
256 | .fm_bootstrap.feedback_content {
257 | height: 340px;
258 | }
259 |
260 | .fm_bootstrap.feedback_content.email_present {
261 | height: 430px;
262 | }
263 |
264 | .fm_bootstrap.feedback_trigger:hover{
265 | background-color: #AAAAAA;
266 | }
267 |
268 | .required_asterisk {
269 | color: red;
270 | }
271 |
272 | .feedback_content.radio_button_list_present {
273 | height: 380px;
274 | }
275 |
276 | .feedback_content.email_present.radio_button_list_present {
277 | height: 440px;
278 | }
279 |
280 | .radio_button_wrapper{
281 | display:inline-block;
282 | text-align:center;
283 | margin-right:35px;
284 | }
285 | .feedback_content .radio_button_wrapper label {
286 | display:block;
287 | }
288 |
289 | .radio_button_list_title_wrapper{
290 | margin-bottom: 10px;
291 | }
292 |
293 | .fm_jquery.feedback_content.radio_button_list_present {
294 | height: 430px;
295 | }
296 |
297 | .fm_bootstrap.feedback_content.radio_button_list_present {
298 | height: 470px;
299 | }
300 |
301 | .fm_jquery.feedback_content.email_present.radio_button_list_present {
302 | height: 500px;
303 | }
304 |
305 | .fm_bootstrap.feedback_content.email_present.radio_button_list_present {
306 | height: 550px;
307 | }
308 |
309 | @media \0screen {
310 | .fm_clean .feedback_trigger_text, .fm_jquery .feedback_trigger_text, .fm_bootstrap .feedback_trigger_text {
311 | right:-70px;
312 | width:100px;
313 | margin-top:-45px;
314 | filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.00000000, M12=1.00000000, M21=-1.00000000, M22=0.00000000,sizingMethod='auto expand');
315 | }
316 | .fm_bootstrap .feedback_trigger_text {
317 | right:-65px;
318 | margin-top:-40px;
319 | }
320 | }
321 |
322 | .feedback_trigger.left-top {
323 | position: fixed;
324 | top: 100px;
325 | left: 0;
326 | }
327 |
328 | .feedback_content.left-top {
329 | position: fixed;
330 | top: 50px;
331 | left: 0;
332 | }
333 |
334 | .feedback_trigger.left-bottom {
335 | position: fixed;
336 | bottom: 100px;
337 | left: 0;
338 | }
339 |
340 | .feedback_content.left-bottom {
341 | position: fixed;
342 | bottom: 50px;
343 | left: 0;
344 | }
345 |
346 | .feedback_trigger.right-top {
347 | position: fixed;
348 | top: 100px;
349 | right: 0;
350 | }
351 |
352 | .feedback_content.right-top {
353 | position: fixed;
354 | top: 50px;
355 | right: 0;
356 | }
357 |
358 | .feedback_trigger.right-bottom {
359 | position: fixed;
360 | bottom: 100px;
361 | right: 0;
362 | }
363 |
364 | .feedback_content.right-bottom {
365 | position: fixed;
366 | bottom: 50px;
367 | right: 0;
368 | }
369 |
370 | .feedback_content.fm_clean.feedback_content_closed.right-top, .feedback_content.fm_clean.feedback_content_closed.right-bottom{
371 | margin-right: -380px;
372 | }
373 |
374 | .feedback_content.fm_clean.right-top, .feedback_content.fm_clean.right-bottom{
375 | margin-right: 0px;
376 | -webkit-border-bottom-left-radius: 6px;
377 | -moz-border-bottom-left-radius: 6px;
378 | border-bottom-left-radius: 6px;
379 | -webkit-border-top-left-radius: 6px;
380 | -moz-border-top-left-radius: 6px;
381 | border-top-left-radius: 6px;
382 | }
383 |
384 | .feedback_content.fm_jquery.feedback_content_closed.right-top, .feedback_content.fm_jquery.feedback_content_closed.right-bottom {
385 | margin-right: -382px;
386 | }
387 |
388 | .feedback_content.fm_jquery.right-top, .feedback_content.fm_jquery.right-bottom {
389 | margin-right: 0px;
390 | }
391 |
392 | .feedback_content.fm_bootstrap.feedback_content_closed.right-top, .feedback_content.fm_bootstrap.feedback_content_closed.right-bottom {
393 | margin-right: -380px;
394 | }
395 |
396 | .feedback_content.fm_bootstrap.right-top, .feedback_content.fm_bootstrap.right-bottom {
397 | margin-right: 0px;
398 |
399 | -webkit-border-bottom-left-radius: 6px;
400 | -moz-border-bottom-left-radius: 6px;
401 | border-bottom-left-radius: 6px;
402 |
403 | -webkit-border-top-left-radius: 6px;
404 | -moz-border-top-left-radius: 6px;
405 | border-top-left-radius: 6px;
406 |
407 | -webkit-border-bottom-right-radius: 0;
408 | -moz-border-bottom-right-radius: 0;
409 | border-bottom-right-radius: 0;
410 |
411 | -webkit-border-top-right-radius: 0;
412 | -moz-border-top-right-radius: 0;
413 | border-top-right-radius: 0;
414 | }
415 |
416 |
417 | .feedback_trigger.fm_clean.feedback_trigger_closed.right-top, .feedback_trigger.fm_clean.feedback_trigger_closed.right-bottom{
418 | margin-right: 0px;
419 | }
420 |
421 | .feedback_trigger.fm_clean.right-top, .feedback_trigger.fm_clean.right-bottom{
422 | margin-right: 380px;
423 | -webkit-border-bottom-left-radius: 6px;
424 | -moz-border-bottom-left-radius: 6px;
425 | border-bottom-left-radius: 6px;
426 | -webkit-border-top-left-radius: 6px;
427 | -moz-border-top-left-radius: 6px;
428 | border-top-left-radius: 6px;
429 | }
430 |
431 | .feedback_trigger.fm_jquery.feedback_trigger_closed.right-top, .feedback_trigger.fm_jquery.feedback_trigger_closed.right-bottom {
432 | margin-right: 0px;
433 | }
434 |
435 | .feedback_trigger.fm_jquery.right-top, .feedback_trigger.fm_jquery.right-bottom {
436 | margin-right: 382px;
437 | -webkit-border-bottom-right-radius: 0;
438 | -moz-border-bottom-right-radius: 0;
439 | border-bottom-right-radius: 0;
440 | -webkit-border-top-right-radius: 0;
441 | -moz-border-top-right-radius: 0;
442 | border-top-right-radius: 0;
443 | -webkit-border-bottom-left-radius: 6px;
444 | -moz-border-bottom-left-radius: 6px;
445 | border-bottom-left-radius: 6px;
446 | -webkit-border-top-left-radius: 6px;
447 | -moz-border-top-left-radius: 6px;
448 | border-top-left-radius: 6px;
449 | }
450 |
451 | .feedback_trigger.fm_bootstrap.feedback_trigger_closed.right-top, .feedback_trigger.fm_bootstrap.feedback_trigger_closed.right-bottom {
452 | margin-right: 0px;
453 | }
454 |
455 | .feedback_trigger.fm_bootstrap.right-top, .feedback_trigger.fm_bootstrap.right-bottom {
456 | margin-right: 380px;
457 |
458 | -webkit-border-bottom-left-radius: 6px;
459 | -moz-border-bottom-left-radius: 6px;
460 | border-bottom-left-radius: 6px;
461 |
462 | -webkit-border-top-left-radius: 6px;
463 | -moz-border-top-left-radius: 6px;
464 | border-top-left-radius: 6px;
465 |
466 | -webkit-border-bottom-right-radius: 0;
467 | -moz-border-bottom-right-radius: 0;
468 | border-bottom-right-radius: 0;
469 |
470 | -webkit-border-top-right-radius: 0;
471 | -moz-border-top-right-radius: 0;
472 | border-top-right-radius: 0;
473 | }
474 |
475 | .feedback_me_frame {
476 | border: none;
477 | overflow: auto;
478 | height: 90%;
479 | width: 98%;
480 | }
481 |
482 | .feedback-delayed-dlg {
483 | position: fixed;
484 | width: 250px;
485 | height: 100px;
486 | top: 50%;
487 | left: 50%;
488 | vertical-align: middle;
489 | text-align: center;
490 | margin-left: -125px;
491 | margin-top: -50px;
492 | -webkit-border-radius: 6px;
493 | -moz-border-radius: 6px;
494 | border-radius: 6px;
495 | }
496 |
497 | .feedback-delayed-dlg.success {
498 | background-color: #2ECC40;
499 | }
500 |
501 | .feedback-delayed-dlg.fail {
502 | background-color: #FF4136;
503 | }
504 |
505 |
506 | .feedback-dlg-close {
507 | position: absolute;
508 | right: 0;
509 | padding: 1px;
510 | background: #FFFFFF;
511 | cursor: pointer;
512 | }
513 |
514 | .feedback-success-fail-message-inner {
515 | position: fixed;
516 | width: 200px;
517 | height: 50px;
518 | background-color: #FFFFFF;
519 | top: 50%;
520 | left: 50%;
521 | vertical-align: middle;
522 | text-align: center;
523 | margin-left: -100px;
524 | margin-top: -25px;
525 | -webkit-border-radius: 6px;
526 | -moz-border-radius: 6px;
527 | border-radius: 6px;
528 | line-height:50px;
529 | }
530 |
531 | .feedback-success-fail-message-inner > span{
532 | display: inline-block;
533 | vertical-align: middle;
534 | line-height: 1em;
535 | }
536 |
537 | .feedback-success-message, .feedback-fail-message {
538 | display: inline-block;
539 | width: 200px;
540 | height: 50px;
541 | }
542 |
--------------------------------------------------------------------------------
/js/jquery.feedback_me.js:
--------------------------------------------------------------------------------
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.9.beta.1 (grab latest stable from https://github.com/vedmack/feedback_me/releases)
9 | *
10 | * Author: Daniel Reznick
11 | * Info: https://github.com/vedmack/feedback_me
12 | * Contact: vedmack@gmail.com
13 | * Twitter: @danielreznick
14 | * Q&A: https://groups.google.com/forum/#!forum/daniels_code
15 | *
16 | * Copyright (c) 2014 Daniel Reznick, all rights reserved. released under the MIT license
17 | *
18 | * This source file is distributed in the hope that it will be useful, but
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 | * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
21 | */
22 | /*
23 | * Parameters:
24 | *
25 | *
26 | * -------------
27 |
28 | * feedback_url
29 | Required: true
30 | Type: String
31 | Description: URL of your servlet/php etc ('name', 'message' and 'email' parameters will be send to your servlet/php etc...)
32 |
33 | * position
34 | Required: false
35 | Type: String
36 | Default value: left-top
37 | Possible values: left-top / left-bottom / right-top / right-bottom
38 | Description: Set the position where the feedback widget will be located
39 | * jQueryUI
40 | Required: false
41 | Type: boolean
42 | Default value: false
43 | Description: Tell the plugin to use jQuery UI theme
44 |
45 | * bootstrap
46 | Required: false
47 | Type: boolean
48 | Default value: false
49 | Description: Tell the plugin to use twitter bootstrap
50 |
51 | * show_email
52 | Required: false
53 | Type: boolean
54 | Default value: false
55 | Description: Tell the plugin to display email input field
56 |
57 | * show_radio_button_list
58 | Required: false
59 | Type: boolean
60 | Default value: false
61 | Description: Tell the plugin to set of 5 radio buttons
62 |
63 | * name_label
64 | Required: false
65 | Type: String
66 | Default value: "Name"
67 | Description: Label for name input
68 |
69 | * email_label
70 | Required: false
71 | Type: String
72 | Default value: "Email"
73 | Description: Label for email input
74 |
75 | * message_label
76 | Required: false
77 | Type: String
78 | Default value: "Message"
79 | Description: Label for message input
80 |
81 | * radio_button_list_labels
82 | Required: false
83 | Type: Array of 5 strings
84 | Default value: ["1","2","3","4","5"]
85 | Description: Labels for radio button list
86 |
87 | * radio_button_list_title
88 | Required: false
89 | Type: String
90 | Default value: "How would you rate my site?"
91 | Description: Label that will appear above the list of radio button
92 |
93 | * submit_label
94 | Required: false
95 | Type: String
96 | Default value: "Send"
97 | Description: Label for submit input
98 |
99 | * title_label
100 | Required: false
101 | Type: String
102 | Default value: "Feedback"
103 | Description: Label for title text
104 |
105 | * trigger_label
106 | Required: false
107 | Type: String
108 | Default value: "Feedback"
109 | Description: Label for open/close (trigger) button
110 |
111 | * name_placeholder
112 | Required: false
113 | Type: String
114 | Default value: ""
115 | Description: Watermark for name input
116 |
117 | * email_placeholder
118 | Required: false
119 | Type: String
120 | Default value: ""
121 | Description: Watermark for email input
122 |
123 | * message_placeholder
124 | Required: false
125 | Type: String
126 | Default value: ""
127 | Description: Watermark for message input
128 |
129 | * name_pattern
130 | Required: false
131 | Type: String
132 | Default value: ""
133 | Description: Set name input pattern, you must escape your '\' chars (\ ---> \\)
134 |
135 | * name_required
136 | Required: false
137 | Type: boolean
138 | Default value: false
139 | Description: Makes input required
140 |
141 | * email_required
142 | Required: false
143 | Type: boolean
144 | Default value: false
145 | Description: Makes input required
146 |
147 | * message_required
148 | Required: false
149 | Type: boolean
150 | Default value: false
151 | Description: Makes input required
152 |
153 | * radio_button_list_required
154 | Required: false
155 | Type: boolean
156 | Default value: false
157 | Description: Makes radio inputs required
158 |
159 | * show_asterisk_for_required
160 | Required: false
161 | Type: boolean
162 | Default value: false
163 | Description: Add an asterisk to the label of the required inputs
164 |
165 | * close_on_click_outside
166 | Required: false
167 | Type: boolean
168 | Default value: true
169 | Description: Will cause the feedback dialog to be closed on clicking anywhere outside the dialog
170 |
171 | * custom_params
172 | Required: false
173 | Type: object
174 | Default value: {}
175 | 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`)
176 | * iframe_url
177 | Required: false
178 | Type: String
179 | Default value: undefined
180 | 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
181 | 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
182 | and also the position of your feedback widget left-top / left-bottom / right-top / right-bottom)
183 | * show_form
184 | Required: false
185 | Type: boolean
186 | Default value: true
187 | Description: Allows you to hide the form in the widget (and only show HTML code or iframe)
188 | * custom_html
189 | Required: false
190 | Type: String
191 | Default value: ""
192 | Description: Allows you to use any inline html code that you want, it will be placed inside feedback_me widget
193 | * delayed_close
194 | Required: false
195 | Type: boolean
196 | Default value: true
197 | Description: Enable feedback dialog upon feedback sending, a small dialog will be displayed with appropriate message in the middle
198 | of the screen and then fade out (read more about the delayed_options property)
199 | * delayed_options
200 | Required: false
201 | Type: object
202 | Default value:
203 | {
204 | delay_success_milliseconds : 2000,
205 | delay_fail_milliseconds : 2000,
206 | sending : "Sending...", //This text will appear on the "send" button while sending
207 | send_fail : "Sending failed.", //This text will appear on the fail dialog
208 | send_success : "Feedback sent.", //This text will appear on the success dialog
209 | fail_color : undefined,
210 | success_color : undefined,
211 | custom_html_success: undefined, //Allow to customize delayed success feedback with custom html code, note that the html will be wrapped with div with the following classes feedback-delayed-custom-dlg success
212 | custom_html_fail: undefined, //Allow to customize delayed fail feedback with custom html code, note that the html will be wrapped with div with the following classes feedback-delayed-custom-dlg fail
213 | }
214 | Description: Allow to customize the feedback dialog upon feedback sending
215 | *
216 | *
217 | */
218 | var fm = (function ($) {
219 |
220 | 'use strict';
221 |
222 | var fm_options_arr = {},
223 | supportsTransitions = false;
224 |
225 | function eventTargetFixUp(pEvent) {
226 | if (pEvent.target === undefined) {
227 | pEvent.target = pEvent.srcElement;
228 | }
229 | return pEvent;
230 | }
231 |
232 | function getFmOptions(event, position) {
233 | var className,
234 | selector;
235 | event = eventTargetFixUp(event);
236 | if ($(event.target).closest(".feedback_trigger").length === 1) {
237 | className = $(event.target).closest(".feedback_trigger")[0].className;
238 | } else if ($(event.target).closest(".feedback_content").length === 1) {
239 | className = $(event.target).closest(".feedback_content")[0].className;
240 | } else {
241 | if (position === undefined) {
242 | position = 'left-top';
243 | }
244 | className = position;
245 | }
246 |
247 | if (className.indexOf('left-top') !== -1) {
248 | selector = 'left-top';
249 | } else if (className.indexOf('left-bottom') !== -1) {
250 | selector = 'left-bottom';
251 | } else if (className.indexOf('right-top') !== -1) {
252 | selector = 'right-top';
253 | } else if (className.indexOf('right-bottom') !== -1) {
254 | selector = 'right-bottom';
255 | }
256 | return fm_options_arr[selector];
257 | }
258 |
259 | function triggerAction(event, position) {
260 |
261 | var animation_show = {},
262 | animation_hide = {},
263 | $fm_trigger,
264 | $fm_content;
265 |
266 | event = eventTargetFixUp(event);
267 | animation_show.marginLeft = "+=380px";
268 | animation_hide.marginLeft = "-=380px";
269 |
270 | if (fm.getFmOptions(event, position).position.indexOf("right-") !== -1) {
271 | animation_show.marginRight = "+=380px";
272 | animation_hide.marginRight = "-=380px";
273 | }
274 |
275 | $fm_trigger = $(event.target).closest(".feedback_trigger");
276 | if ($fm_trigger.length === 1) {
277 | $fm_content = $fm_trigger.next();
278 | } else {
279 | $fm_content = $(event.target).closest(".feedback_content");
280 | $fm_trigger = $fm_content.prev();
281 | }
282 | if ($fm_content.length === 0 || $fm_trigger.length === 0) {
283 | if (position === undefined) {
284 | position = 'left-top';
285 | }
286 | $fm_content = $('.' + position).closest(".feedback_content");
287 | $fm_trigger = $fm_content.prev();
288 | }
289 |
290 | if ($fm_trigger.hasClass("feedback_trigger_closed")) {
291 | if (supportsTransitions === true) {
292 | $fm_trigger.removeClass("feedback_trigger_closed");
293 | $fm_content.removeClass("feedback_content_closed");
294 | } else {
295 | $fm_trigger.add($fm_content).animate(
296 | animation_show,
297 | 150,
298 | function () {
299 | $fm_trigger.removeClass("feedback_trigger_closed");
300 | $fm_content.removeClass("feedback_content_closed");
301 | }
302 | );
303 | }
304 | } else {
305 | //first add the closed class so double (which will trigger closeFeedback function) click wont try to hide the form twice
306 | $fm_trigger.addClass("feedback_trigger_closed");
307 | $fm_content.addClass("feedback_content_closed");
308 | if (supportsTransitions === false) {
309 | $fm_trigger.add($fm_content).animate(
310 | animation_hide,
311 | 150
312 | );
313 | }
314 | }
315 | }
316 |
317 | function closeFeedback(event) {
318 | event = eventTargetFixUp(event);
319 | if (($(".feedback_content").length === 1 && $(".feedback_content").hasClass("feedback_content_closed")) ||
320 | $(event.target).closest('.feedback_content').length === 1) {
321 | return;
322 | }
323 |
324 | var animation_hide = {},
325 | option,
326 | $fm_trigger,
327 | $fm_content;
328 |
329 | for (option in fm_options_arr) {
330 | if (fm_options_arr.hasOwnProperty(option)) {
331 |
332 | $fm_content = $('.' + option).closest(".feedback_content");
333 | $fm_trigger = $fm_content.prev();
334 |
335 | if (!$fm_trigger.hasClass("feedback_trigger_closed")) {
336 | if (supportsTransitions === true) {
337 | $fm_trigger.addClass("feedback_trigger_closed");
338 | $fm_content.addClass("feedback_content_closed");
339 | } else {
340 | if (option.indexOf("left-") !== -1) {
341 | animation_hide.marginLeft = "-=380px";
342 | } else {
343 | animation_hide.marginRight = "-=380px";
344 | }
345 | if (!$fm_trigger.hasClass("feedback_kurama")) {
346 | $fm_trigger.addClass("feedback_kurama");
347 | $fm_trigger.add($fm_content).animate(
348 | animation_hide,
349 | 150,
350 | function () {
351 | var $fm_trigger,
352 | $fm_content;
353 | $fm_trigger = $(this);
354 | $fm_content = $fm_trigger.next();
355 | $fm_trigger.removeClass("feedback_kurama");
356 | $fm_trigger.addClass("feedback_trigger_closed");
357 | $fm_content.addClass("feedback_content_closed");
358 | }
359 | );
360 | }
361 | }
362 | }
363 | }
364 | }
365 | }
366 |
367 | function emailValid(str) {
368 | var lastAtPos = str.lastIndexOf('@');
369 | return (lastAtPos < (str.length - 1) && lastAtPos > 0 && str.indexOf('@@') === -1 && str.length > 2);
370 | }
371 |
372 | function validateFeedbackForm(event, position) {
373 | event = eventTargetFixUp(event);
374 | var $fm_content = $(event.target).closest(".feedback_content"),
375 | fm_options = getFmOptions(event, position);
376 | if ((fm_options.name_required === true && $fm_content.find(".feedback_name").val() === "") ||
377 | ((fm_options.email_required === true && $fm_content.find(".feedback_email").val() === "") || (fm_options.email_required === true && emailValid($fm_content.find(".feedback_email").val()) === false)) ||
378 | (fm_options.message_required === true && $fm_content.find(".feedback_message").val() === "") ||
379 | (fm_options.radio_button_list_required === true && $fm_content.find("input[name=feedback_radio]:checked").val() === undefined)) {
380 | return false;
381 | }
382 | return true;
383 |
384 | }
385 |
386 | function checkPatternFieldsOk(event, position) {
387 | var $patternFields = $("." + position + " [pattern]"),
388 | form_valid = true,
389 | i;
390 |
391 | if ($patternFields.length > 0) {
392 | for (i = 0; i < $patternFields.length; i++) {
393 | form_valid = !$patternFields[i].validity.patternMismatch;
394 | if (form_valid === false) {
395 | break;
396 | }
397 | }
398 | }
399 | return form_valid;
400 | }
401 |
402 | function checkRequiredFieldsOk(event, position) {
403 | var $reqFields = $("." + position + " [required]"),
404 | form_valid = true;
405 |
406 | if ($reqFields.length > 0) {
407 | form_valid = validateFeedbackForm(event, position);
408 | }
409 | return form_valid;
410 | }
411 |
412 | function applyCloseOnClickOutside() {
413 | var jqVersion = $().jquery.split(".");
414 | jqVersion[0] = +jqVersion[0];
415 | jqVersion[1] = +jqVersion[1];
416 | if (jqVersion[0] > 1 || (jqVersion[0] === 1 && jqVersion[1] >= 7)) {
417 | $(document).on("click", document, function (event) {
418 | closeFeedback(event);
419 | });
420 | } else {
421 | $(document).delegate("body", document, function (event) {
422 | closeFeedback(event);
423 | });
424 | }
425 | }
426 |
427 | function appendFeedbackToBody(fm_options) {
428 | var form_html = "",
429 | iframe_html = "",
430 | jQueryUIClasses1 = "",
431 | jQueryUIClasses2 = "",
432 | jQueryUIClasses3 = "",
433 | jQueryUIClasses4 = "",
434 | email_html = "",
435 | email_feedback_content_class = "",
436 | radio_button_list_html = "",
437 | radio_button_list_class = "",
438 | fm_class = " fm_clean ",
439 | jquery_class = "",
440 | bootstrap_class = "",
441 | bootstrap_btn = "",
442 | bootstrap_hero_unit = "",
443 |
444 | name_pattern = fm_options.name_pattern === "" ? "" : "pattern=\"" + fm_options.name_pattern + "\"",
445 |
446 | name_required = fm_options.name_required ? "required" : "",
447 | email_required = fm_options.email_required ? "required" : "",
448 | message_required = fm_options.message_required ? "required" : "",
449 | radio_button_list_required = fm_options.radio_button_list_required ? "required" : "",
450 |
451 | name_asterisk = fm_options.name_required && fm_options.show_asterisk_for_required ? "*" : "",
452 | email_asterisk = fm_options.email_required && fm_options.show_asterisk_for_required ? "*" : "",
453 | message_asterisk = fm_options.message_required && fm_options.show_asterisk_for_required ? "*" : "",
454 | radio_button_list_asterisk = fm_options.radio_button_list_required && fm_options.show_asterisk_for_required ? "*" : "";
455 |
456 | if (fm_options.bootstrap === true) {
457 | bootstrap_class = " fm_bootstrap ";
458 | bootstrap_btn = " btn btn-primary ";
459 | bootstrap_hero_unit = " hero-unit jumbotron ";
460 |
461 | fm_class = "";
462 | jquery_class = "";
463 | }
464 |
465 | if (fm_options.jQueryUI === true) {
466 | jquery_class = " fm_jquery ";
467 | jQueryUIClasses1 = " ui-widget-header ui-corner-all ui-helper-clearfix ";
468 | jQueryUIClasses2 = " ui-dialog ui-widget ui-widget-content ui-corner-all ";
469 | jQueryUIClasses3 = " ui-dialog-titlebar ";
470 | jQueryUIClasses4 = " ui-dialog-title ";
471 |
472 | fm_class = "";
473 | bootstrap_class = "";
474 | bootstrap_hero_unit = "";
475 | bootstrap_btn = "";
476 |
477 | }
478 |
479 | if (fm_options.show_radio_button_list === true) {
480 | radio_button_list_html = "