1/** 2 * FW_Form helpers 3 * Dependencies: jQuery 4 * Note: You can include this script in frontend (for e.g. to make you contact forms ajax submittable) 5 */ 6 7var fwForm = { 8 /** 9 * Make forms ajax submittable 10 * @param {Object} [opts] You can overwrite any 11 */ 12 initAjaxSubmit: function (opts) { 13 var opts = jQuery.extend({ 14 selector: 'form[data-fw-form-id]', 15 ajaxUrl: (typeof ajaxurl == 'undefined') ? 'wp-admin/admin-ajax.php' : ajaxurl, 16 loading: function (elements, show) { 17 elements.$form.css('position', 'relative'); 18 elements.$form.find('> .fw-form-loading').remove(); 19 20 if (show) { 21 elements.$form.append( 22 '<div' + 23 ' class="fw-form-loading"' + 24 ' style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255,255,255,0.1);"' + 25 '></div>' 26 ); 27 } 28 }, 29 onErrors: function (elements, data) { 30 if (isAdmin) { 31 fwForm.backend.showFlashMessages( 32 fwForm.backend.renderFlashMessages({error: data.errors}) 33 ); 34 } else { 35 // Frontend 36 jQuery.each(data.errors, function (inputName, message) { 37 var $input = elements.$form.find('[name="' + inputName + '"]').last(); 38 message = '<p class="form-error" style="color: #9b2922;">{message}</p>'.replace('{message}', message); 39 40 if ($input.length) { 41 // error message under input 42 $input.parent().after(message); 43 } else { 44 // if input not found, show message in form 45 elements.$form.prepend(message); 46 } 47 }); 48 } 49 }, 50 hideErrors: function (elements) { 51 elements.$form.find('.form-error').remove(); 52 }, 53 onAjaxError: function (elements, data) { 54 console.error(data.jqXHR, data.textStatus, data.errorThrown); 55 alert('Ajax error (more details in console)'); 56 }, 57 onSuccess: function (elements, ajaxData) { 58 if (isAdmin) { 59 fwForm.backend.showFlashMessages( 60 fwForm.backend.renderFlashMessages(ajaxData.flash_messages) 61 ); 62 } else { 63 var html = fwForm.frontend.renderFlashMessages(ajaxData.flash_messages); 64 65 if (!html.length) { 66 html = '<p>Success</p>'; 67 } 68 69 elements.$form.fadeOut(function () { 70 elements.$form.html(html).fadeIn(); 71 }); 72 73 // prevent multiple submit 74 elements.$form.on('submit', function (e) { 75 e.preventDefault(); 76 e.stopPropagation(); 77 }); 78 } 79 } 80 }, opts || {}), 81 isAdmin = (typeof adminpage != 'undefined' && jQuery(document.body).hasClass('wp-admin')), 82 isBusy = false; 83 84 jQuery(document.body).on('submit', opts.selector, function (e) { 85 e.preventDefault(); 86 87 if (isBusy) { 88 console.warn('Working... Try again later.') 89 return; 90 } 91 92 var $form = jQuery(this); 93 94 if (!$form.is('form[data-fw-form-id]')) { 95 console.error('This is not a FW_Form'); 96 return; 97 } 98 99 // get submit button 100 { 101 var $submitButton = $form.find('input[type="submit"][name]:focus') 102 103 if (!$submitButton.length) { 104 // in case you use this solution http://stackoverflow.com/a/5721762 105 $submitButton = $form.find('input[type="submit"][name][clicked]'); 106 } 107 108 // make sure to remove the "clicked" attribute to prevent accidental settings reset 109 $form.find('input[type="submit"][name][clicked]').removeAttr('clicked'); 110 } 111 112 var elements = { 113 $form: $form, 114 $submitButton: $submitButton 115 }; 116 117 opts.hideErrors(elements); 118 opts.loading(elements, true); 119 isBusy = true; 120 121 jQuery.ajax({ 122 type: "POST", 123 url: opts.ajaxUrl, 124 data: $form.serialize() + ($submitButton.length ? '&' + $submitButton.attr('name') + '=' + $submitButton.attr('value') : ''), 125 dataType: 'json' 126 }).done(function (r) { 127 isBusy = false;
128 opts.loading(elements, false); 129 130 if (r.success) { 131 opts.onSuccess(elements, r.data); 132 } else { 133 opts.onErrors(elements, r.data); 134 } 135 }).fail(function (jqXHR, textStatus, errorThrown) { 136 isBusy = false; 137 opts.loading(elements, false); 138 opts.onAjaxError(elements, { 139 jqXHR: jqXHR, 140 textStatus: textStatus, 141 errorThrown: errorThrown 142 }); 143 }); 144 }); 145 }, 146 backend: { 147 showFlashMessages: function (messagesHtml) { 148 var $pageTitle = jQuery('.wrap h2:first'); 149 150 while ($pageTitle.next().is('.fw-flash-messages, .fw-flash-message, .updated, .update-nag, .error')) { 151 $pageTitle.next().remove(); 152 } 153 154 $pageTitle.after('<div class="fw-flash-messages">' + messagesHtml + '</div>'); 155 156 jQuery(document.body).animate({scrollTop: 0}, 300); 157 }, 158 /** 159 * Html structure should be the same as generated by FW_Flash_Messages::_print_backend() 160 * @param {Object} flashMessages 161 * @returns {string} 162 */ 163 renderFlashMessages: function (flashMessages) { 164 var html = [], 165 typeHtml = [], 166 messageClass = ''; 167 168 jQuery.each(flashMessages, function (type, messages) { 169 typeHtml = []; 170 171 switch (type) { 172 case 'error': 173 messageClass = 'error'; 174 break; 175 case 'warning': 176 messageClass = 'update-nag'; 177 break; 178 default: 179 messageClass = 'updated'; 180 } 181 182 jQuery.each(messages, function (messageId, message) { 183 typeHtml.push('<div class="' + messageClass + ' fw-flash-message"><p>' + message + '</p></div>'); 184 }); 185 186 if (typeHtml.length) { 187 html.push( 188 '<div class="fw-flash-type-' + type + '">' + typeHtml.join('</div><div class="fw-flash-type-' + type + '">') + '</div>' 189 ); 190 } 191 }); 192 193 return html.join(''); 194 } 195 }, 196 frontend: { 197 /** 198 * Html structure is the same as generated by FW_Flash_Messages::_print_frontend() 199 * @param {Object} flashMessages 200 * @returns {string} 201 */ 202 renderFlashMessages: function (flashMessages) { 203 var html = [], 204 typeHtml = [], 205 messageClass = ''; 206 207 jQuery.each(flashMessages, function (type, messages) { 208 typeHtml = []; 209 210 jQuery.each(messages, function (messageId, message) { 211 typeHtml.push('<li class="fw-flash-message">' + message + '</li>'); 212 }); 213 214 if (typeHtml.length) { 215 html.push( 216 '<ul class="fw-flash-type-' + type + '">' + typeHtml.join('</ul><ul class="fw-flash-type-' + type + '">') + '</ul>' 217 ); 218 } 219 }); 220 221 return html.join(''); 222 } 223 } 224}; 225 226// Usage example 227if (false) { 228 jQuery(function ($) { 229 fwForm.initAjaxSubmit({ 230 selector: 'form[data-fw-form-id][data-fw-ext-forms-type="contact-forms"]', 231 ajaxUrl: ajaxurl 232 }); 233 }); 234}
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.