1/** 2 * Copyright (C) 2017 Kyle Florence 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 * @website https://github.com/kflorence/jquery-deserialize/ 19 * @version 2.0.0-rc1 20 * 21 * Dual licensed under the MIT and GPLv2 licenses. 22 */ 23(function( factory ) { 24 if ( typeof module === "object" && module.exports ) { 25 // Node/CommonJS 26 module.exports = factory( require( "jquery" ) ); 27 28 } else { 29 // Browser globals 30 factory( window.jQuery ); 31 } 32}(function( $ ) { 33 34 /** 35 * Updates a key/valueArray with the given property and value. Values will always be stored as arrays. 36 * 37 * @param prop The property to add the value to. 38 * @param value The value to add. 39 * @param obj The object to update. 40 * @returns {object} Updated object. 41 */ 42 function updateKeyValueArray( prop, value, obj ) { 43 var current = obj[ prop ]; 44 45 if ( current === undefined ) { 46 obj[ prop ] = [ value ]; 47 48 } else { 49 current.push( value ); 50 } 51 52 return obj; 53 } 54 55 /** 56 * Get all of the fields contained within the given elements by name. 57 * 58 * @param $elements jQuery object of elements. 59 * @param filter Custom filter to apply to the list of fields. 60 * @returns {object} All of the fields contained within the given elements, keyed by name. 61 */ 62 function getFieldsByName( $elements, filter ) { 63 var elementsByName = {}; 64 65 // Extract fields from elements 66 var fields = $elements 67 .map(function convertFormToElements() { 68 return this.elements ? $.makeArray( this.elements ) : this; 69 }) 70 .filter( filter || ":input:not(:disabled)" ) 71 .get(); 72 73 $.each( fields, function( index, field ) { 74 updateKeyValueArray( field.name, field, elementsByName ); 75 }); 76 77 return elementsByName; 78 } 79 80 /** 81 * Figure out the type of an element. Input type will be used first, falling back to nodeName. 82 * 83 * @param element DOM element to check type of. 84 * @returns {string} The element's type. 85 */ 86 function getElementType( element ) { 87 return ( element.type || element.nodeName ).toLowerCase(); 88 } 89 90 /** 91 * Normalize the provided data into a key/valueArray store. 92 * 93 * @param data The data provided by the user to the plugin. 94 * @returns {object} The data normalized into a key/valueArray store. 95 */ 96 function normalizeData( data ) { 97 var normalized = {}; 98 var rPlus = /\+/g; 99 100 // Convert data from .serializeObject() notation 101 if ( $.isPlainObject( data ) ) { 102 $.extend( normalized, data ); 103 104 // Convert non-array values into an array 105 $.each( normalized, function( name, value ) { 106 if ( !$.isArray( value ) ) { 107 normalized[ name ] = [ value ]; 108 } 109 }); 110 111 // Convert data from .serializeArray() notation 112 } else if ( $.isArray( data ) ) { 113 $.each( data, function( index, field ) { 114 updateKeyValueArray( field.name, field.value, normalized ); 115 }); 116 117 // Convert data from .serialize() notation 118 } else if ( typeof data === "string" ) { 119 $.each( data.split( "&" ), function( index, field ) { 120 var current = field.split( "=" ); 121 var name = decodeURIComponent( current[ 0 ].replace( rPlus, "%20" ) ); 122 var value = decodeURIComponent( current[ 1 ].replace( rPlus, "%20" ) ); 123 updateKeyValueArray( name, value, normalized ); 124 }); 125 } 126 127 return normalized; 128 } 129 130 /** 131 * Map of property name -> element types. 132 * 133 * @type {object} 134 */ 135 var updateTypes = { 136 checked: [ 137 "radio", 138 "checkbox" 139 ], 140 selected: [ 141 "option", 142 "select-one", 143 "select-multiple" 144 ], 145 value: [ 146 "button", 147 "color", 148 "date", 149 "datetime", 150 "datetime-local", 151 "email", 152 "hidden", 153 "month", 154 "number", 155 "password", 156 "range", 157 "reset", 158 "search", 159 "submit", 160 "tel", 161 "text", 162 "textarea", 163 "time", 164 "url", 165 "week" 166 ] 167 }; 168 169 /** 170 * Get the property to update on an element being updated. 171 * 172 * @param element The DOM element to get the property for. 173 * @returns The name of the property to update if element is supported, otherwise `undefined`. 174 */ 175 function getPropertyToUpdate( element ) { 176 var type = getElementType( element ); 177 var elementProperty = undefined; 178 179 $.each( updateTypes, function( property, types ) { 180 if ( $.inArray( type, types ) > -1 ) { 181 elementProperty = property; 182 return false;
183 } 184 }); 185 186 return elementProperty; 187 } 188 189 /** 190 * Update the element based on the provided data. 191 * 192 * @param element The DOM element to update. 193 * @param elementIndex The index of this element in the list of elements with the same name. 194 * @param value The serialized element value. 195 * @param valueIndex The index of the value in the list of values for elements with the same name. 196 * @param callback A function to call if the value of an element was updated. 197 */ 198 function update( element, elementIndex, value, valueIndex, callback ) { 199 var property = getPropertyToUpdate( element ); 200 201 // Handle value inputs 202 // If there are multiple value inputs with the same name, they will be populated by matching indexes. 203 if ( property == "value" && elementIndex == valueIndex ) { 204 element.value = value; 205 callback.call( element, value ); 206 207 // Handle select menus, checkboxes and radio buttons 208 } else if ( property == "checked" || property == "selected" ) { 209 var fields = []; 210 211 // Extract option fields from select menus 212 if ( element.options ) { 213 $.each( element.options, function( index, option ) { 214 fields.push( option ); 215 }); 216 217 } else { 218 fields.push( element ); 219 } 220 221 // #37: Remove selection from multiple select menus before deserialization 222 if ( element.multiple && valueIndex == 0 ) { 223 element.selectedIndex = -1; 224 } 225 226 $.each( fields, function( index, field ) { 227 if ( field.value == value ) { 228 field[ property ] = true; 229 callback.call( field, value ); 230 } 231 }); 232 } 233 } 234 235 /** 236 * Default plugin options. 237 * 238 * @type {object} 239 */ 240 var defaultOptions = { 241 change: $.noop, 242 complete: $.noop 243 }; 244 245 /** 246 * The $.deserialize function. 247 * 248 * @param data The data to deserialize. 249 * @param options Additional options. 250 * @returns {jQuery} The jQuery object that was provided to the plugin. 251 */ 252 $.fn.deserialize = function( data, options ) { 253 254 // Backwards compatible with old arguments: data, callback 255 if ( $.isFunction( options ) ) { 256 options = { complete: options }; 257 } 258 259 options = $.extend( defaultOptions, options || {} ); 260 data = normalizeData( data ); 261 262 var elementsByName = getFieldsByName( this, options.filter ); 263 264 $.each( data, function( name, values ) { 265 $.each( elementsByName[ name ], function( elementIndex, element ) { 266 $.each( values, function( valueIndex, value ) { 267 update( element, elementIndex, value, valueIndex, options.change ); 268 }); 269 }); 270 }); 271 272 options.complete.call( this ); 273 274 return this; 275 }; 276}));
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.