├── .gitignore ├── README.md ├── dist ├── jsonform.css └── jsonform.js ├── examples ├── ajax.html ├── boolean.html ├── collectionobjects.html ├── index.html ├── javascripts │ ├── chosen │ │ ├── chosen-sprite.png │ │ ├── chosen-sprite@2x.png │ │ ├── chosen.css │ │ ├── chosen.jquery.js │ │ ├── chosen.jquery.min.js │ │ ├── chosen.min.css │ │ ├── chosen.proto.js │ │ └── chosen.proto.min.js │ ├── jquery.js │ ├── jquery.sortable.js │ └── underscore.js ├── select.html ├── selectajax.html ├── sortable.html └── string.html ├── gulpfile.coffee ├── gulpfile.js ├── package.json ├── src ├── fields │ ├── ajax.coffee │ ├── ajax.jst │ ├── ajax.scss │ ├── boolean.coffee │ ├── boolean.jst │ ├── boolean.scss │ ├── fieldcollection-del.jst │ ├── fieldcollection-sort.jst │ ├── fieldcollection.coffee │ ├── fieldcollection.jst │ ├── fieldcollection.scss │ ├── fieldcollectionitem.coffee │ ├── fieldcollectionitem.scss │ ├── select.coffee │ ├── select.jst │ ├── selectajax.coffee │ ├── selectajax.jst │ ├── string.coffee │ ├── string.jst │ └── string.scss ├── jsonform.coffee └── jsonform.scss └── test ├── jsonform.css └── jsonform.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSON form 2 | 3 | ![JSON Form](https://dmgpayxepw99m.cloudfront.net/jsonform.jpg) 4 | 5 | This is a javascript library that can auto-generate a form to help a user generate a JSON document. 6 | 7 | The library takes a textarea DOM element (empty or filled with existing JSON data), and a JSON object that describes the JSON you want to manipulate via the form. 8 | 9 | ```js 10 | var config = { 11 | ... 12 | } 13 | var jf = new jsonform.Form($("#myTextField")[0], config); 14 | ``` 15 | 16 | ## The config object 17 | 18 | The config object defines the outline of the JSON object that the library should generate. You can use any type of object: The only requirement is that whereever you need dynamic data input, you create an object with the property `jsType` set to the type of field you want in the form. 19 | 20 | The following json config shows a single textfield to the user: 21 | 22 | ```js 23 | var config = { 24 | "name" : { 25 | "jfType" : "StringField" 26 | } 27 | } 28 | ``` 29 | 30 | The user will then be presented with a single textfield, and the original textarea will automatically update with the latest JSON representation: 31 | 32 | ```html 33 | 38 | ``` 39 | 40 | Although that's a very simple use-case, the library supports a number of advanced fields. Look in the field parameters guide below. 41 | 42 | But what if you want the user to add more than a single name? Easy. Wrap your `jfType` object in an array, and the UI will show buttons to add/remove multiple fields. For example, this is a more complex example where a user can add up to 7 names: 43 | 44 | ```js 45 | var config = { 46 | "names" : [ 47 | { 48 | "jfType" : "StringField", 49 | "jfMax" : 7 50 | } 51 | ] 52 | } 53 | ``` 54 | 55 | Corresponding output: 56 | 57 | ```html 58 | 69 | ``` 70 | 71 | If the textarea has existing JSON data, and that data matches the schema of the JSON config, the existing JSON values will be pre-filled into the form. 72 | 73 | Look in `test/index.html` for a more complicated JSON config structure. 74 | 75 | ## Optional Configuration 76 | 77 | If you want the collection fields to be sortable, you just need to add `jquery.sortable` to the page. See `/examples/sortable.html` for an example. 78 | 79 | ## Field parameters 80 | 81 | There's a number of fields in this library, each of them with specific parameters. These params apply to all fields: 82 | 83 | ```js 84 | { 85 | "jfType" : "XXXXField", // name of field to use 86 | "jfTitle" : "My title", // label to show before the input field(s) 87 | "jfHelper" : "Do this, do that", // smaller help text to show before the input field(s) 88 | "jfValueType" : "int" // force the value to be integer over string. Helpful for text input, etc. 89 | } 90 | ``` 91 | 92 | ### BooleanField 93 | 94 | No specific options. Will show a select box with `true` or `false`. 95 | 96 | ```js 97 | { 98 | "jfType" : "BooleanField" 99 | } 100 | ``` 101 | 102 | ### StringField 103 | 104 | No specific options. Will show an input text field. 105 | 106 | ```js 107 | { 108 | "jfType" : "StringField" 109 | } 110 | ``` 111 | 112 | ### SelectField 113 | 114 | Will show a select field with options set from `jfValues`. 115 | 116 | ```js 117 | { 118 | "jfType" : "SelectField", 119 | "jfValues" : [["first", "First Item"], ["second", "Second Item"]] 120 | } 121 | ``` 122 | 123 | ### AjaxField 124 | 125 | Will show a search box that queries against an API endpoint, and populates the results in a dropdown box. It also supports parsing existing data into the dropdown, via the `jfReloadParam`. 126 | 127 | ```js 128 | { 129 | "jfType" : "AjaxField", 130 | "jfUrl" : "http://my.api", // URL for API endpoint 131 | "jfSearchParam" : "search", // query param to use for search query (http://my.api?search=QUERY) 132 | "jfParse" : function(data, vals) { }) // Parse function that receives the API response. Should return an array of [value, label] arrays for the select box. Takes an optional parameter with single values from existing JSON, to use for sorting. Look in test/index.html for an example. 133 | "jfReloadParam" : "uuid[]", // used to populate existing data. A single request will be made with all values set to this array param, and the parse function will be used to populate the fields from the response. Look in test/index.html for an example. 134 | } 135 | ``` 136 | 137 | ### SelectAjaxField 138 | 139 | Will show a select dropdown box, and whenever a value is selected, an ajaxfield below that searches a specific endpoint. This makes it possible to make a fields where the user first selects the type of API endpoint, and then searches for a specific object in that endpoint. See examples for more info. 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /dist/jsonform.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, Arial, sans-serif; } 3 | 4 | .jfForm { 5 | margin: 20px 0px; } 6 | 7 | .jfTitle { 8 | font-size: 16px; 9 | display: block; 10 | margin-top: 10px; 11 | margin-bottom: 10px; } 12 | 13 | .jfHelper { 14 | display: block; 15 | margin-top: 10px; 16 | margin-bottom: 10px; 17 | font-size: 13px; 18 | color: #838383; 19 | letter-spacing: 0.5px; 20 | font-style: italic; } 21 | 22 | a.jfBtn, a.jfBtn:link { 23 | text-decoration: none; 24 | color: #282828; 25 | display: inline-block; 26 | background-color: #F7F7F7; 27 | text-align: center; 28 | border-radius: 50%; 29 | border: 1px solid #999; 30 | margin-bottom: 10px; } 31 | 32 | .chosen-container { 33 | margin-bottom: 10px; } 34 | 35 | .jfCollectionItem { 36 | background-color: #FAFAFA; 37 | padding: 10px; 38 | border: 1px solid #C7C7C7; 39 | border-radius: 5px; 40 | margin-bottom: 5px; 41 | max-width: 400px; } 42 | 43 | .jfAdd { 44 | width: 30px; 45 | height: 30px; 46 | line-height: 30px; } 47 | 48 | .jfAdd[disabled] { 49 | opacity: 0.4; 50 | pointer-events: none; } 51 | 52 | a.jfDel { 53 | font-size: 14px; 54 | text-decoration: none; 55 | padding: 3px 5px; 56 | margin-top: 10px; 57 | margin-left: 5px; 58 | color: #DA7D7D; 59 | display: inline-block; 60 | background-color: #ECC8C8; } 61 | 62 | .jfSort { 63 | font-size: 14px; 64 | margin-top: 10px; 65 | margin-right: 5px; 66 | color: #565555; 67 | display: inline-block; 68 | background-color: #DBDBDB; 69 | text-align: center; 70 | padding: 3px 5px; 71 | vertical-align: top; 72 | border-radius: 3px; 73 | cursor: pointer; } 74 | 75 | body.dragging, body.dragging * { 76 | cursor: move !important; } 77 | 78 | .dragged { 79 | position: absolute; 80 | opacity: 0.5; 81 | z-index: 2000; } 82 | 83 | div.jfCollection .placeholder { 84 | position: relative; 85 | margin: 0; 86 | padding: 0; 87 | border: none; } 88 | div.jfCollection .placeholder:before { 89 | position: absolute; 90 | content: ""; 91 | width: 0; 92 | height: 0; 93 | margin-top: -5px; 94 | left: -5px; 95 | top: -4px; 96 | border: 5px solid transparent; 97 | border-left-color: red; 98 | border-right: none; } 99 | 100 | .jfField input[type="text"] { 101 | padding: 6px 10px; 102 | border: 1px solid #B0B0B0; 103 | border-radius: 5px; 104 | background-color: #F7F7F7; 105 | width: 300px; 106 | font-family: Helvetica, Arial, sans-serif; 107 | font-size: 13px; 108 | color: #444; 109 | outline: none; 110 | vertical-align: top; } 111 | -------------------------------------------------------------------------------- /dist/jsonform.js: -------------------------------------------------------------------------------- 1 | window.jsonform = {}; 2 | 3 | window.jsonform.helpers = { 4 | panic: function(msg) { 5 | console.error(msg); 6 | return alert(msg); 7 | }, 8 | isJsonString: function(str) { 9 | var e; 10 | try { 11 | JSON.parse(str); 12 | } catch (_error) { 13 | e = _error; 14 | return false; 15 | } 16 | return true; 17 | }, 18 | changed: function() { 19 | return jQuery.event.trigger('jf:change'); 20 | }, 21 | newField: function(jfObj) { 22 | var klass; 23 | klass = jsonform[jfObj.jfType]; 24 | if (klass) { 25 | return new jsonform[jfObj.jfType](jfObj); 26 | } else { 27 | return console.error("jsonform field doesnt exist: " + jfObj.jfType); 28 | } 29 | } 30 | }; 31 | 32 | jsonform.AjaxField = (function() { 33 | AjaxField.preloadValues = function(config, vals, success) { 34 | var query; 35 | vals = _.compact(vals); 36 | if (_.isEmpty(vals)) { 37 | return; 38 | } 39 | query = {}; 40 | query[config.jfReloadParam] = vals; 41 | return $.ajax({ 42 | url: config.jfUrl, 43 | data: query, 44 | type: 'GET', 45 | success: (function(_this) { 46 | return function(data) { 47 | return success(config.jfParse(data, vals)); 48 | }; 49 | })(this), 50 | error: function(data) { 51 | return console.log("error baby"); 52 | } 53 | }); 54 | }; 55 | 56 | function AjaxField(config) { 57 | this.config = config; 58 | this.tmpl = JST["fields/ajax"]; 59 | this.jel = $('
'); 60 | this.el = this.jel[0]; 61 | } 62 | 63 | AjaxField.prototype.render = function() { 64 | var timeout; 65 | timeout = void 0; 66 | this.jel.html(this.tmpl(this.config)); 67 | this.chosen = this.jel.find(".chosen-select").chosen({ 68 | width: "300px", 69 | allow_single_deselect: true, 70 | no_results_text: 'Searching for' 71 | }); 72 | this.jel.find(".chosen-search input").on('input', (function(_this) { 73 | return function(e) { 74 | clearTimeout(timeout); 75 | return timeout = setTimeout(function() { 76 | return _this.loadAjax(e); 77 | }, 800); 78 | }; 79 | })(this)); 80 | return this.chosen.change(jsonform.helpers.changed); 81 | }; 82 | 83 | AjaxField.prototype.getValue = function() { 84 | return this.jel.find(".chosen-select").val(); 85 | }; 86 | 87 | AjaxField.prototype.clearValues = function() { 88 | this.jel.find("select option").remove(); 89 | this.jel.find("select").append(""); 90 | return this.jel.find(".chosen-select").trigger("chosen:updated"); 91 | }; 92 | 93 | AjaxField.prototype.setValue = function(val) { 94 | if (!_.isObject(val)) { 95 | return this.constructor.preloadValues(this.config, [val], (function(_this) { 96 | return function(newVal) { 97 | return _this.setValue(newVal[0]); 98 | }; 99 | })(this)); 100 | } else { 101 | this.jel.find(".chosen-select").html(''); 102 | this.jel.find(".chosen-select").val(val[0]); 103 | this.jel.find(".chosen-select").trigger("chosen:updated"); 104 | return jsonform.helpers.changed(); 105 | } 106 | }; 107 | 108 | AjaxField.prototype.loadAjax = function(e) { 109 | var chosen, query, searchVal; 110 | chosen = this.jel.find(".chosen-container"); 111 | query = {}; 112 | searchVal = chosen.find(".chosen-search input").val(); 113 | query[this.config.jfSearchParam] = searchVal; 114 | this.clearValues(); 115 | return $.ajax({ 116 | url: this.config.jfUrl, 117 | data: query, 118 | type: 'GET', 119 | success: (function(_this) { 120 | return function(data) { 121 | var results, select; 122 | results = _this.config.jfParse(data); 123 | if (results.length === 0) { 124 | return chosen.find(".chosen-results").html("
  • No results matched \"" + searchVal + "\"
  • "); 125 | } else { 126 | select = _this.jel.find(".chosen-select"); 127 | _.each(results, function(result) { 128 | return select.append(''); 129 | }); 130 | select.trigger("chosen:updated"); 131 | return chosen.find(".chosen-search input").val(searchVal); 132 | } 133 | }; 134 | })(this), 135 | error: function(data) { 136 | return console.log("error baby"); 137 | } 138 | }); 139 | }; 140 | 141 | return AjaxField; 142 | 143 | })(); 144 | 145 | jsonform.BooleanField = (function() { 146 | function BooleanField(config) { 147 | this.config = config; 148 | this.tmpl = JST["fields/boolean"]; 149 | this.jel = $('
    '); 150 | this.el = this.jel[0]; 151 | } 152 | 153 | BooleanField.prototype.render = function() { 154 | this.jel.html(this.tmpl(this.config)); 155 | return this.jel.find(".chosen-select").chosen({ 156 | disable_search_threshold: 5, 157 | width: "300px" 158 | }).change(jsonform.helpers.changed); 159 | }; 160 | 161 | BooleanField.prototype.getValue = function() { 162 | return this.jel.find(".chosen-select").val() === "true"; 163 | }; 164 | 165 | BooleanField.prototype.setValue = function(val) { 166 | this.jel.find(".chosen-select").val(val + ""); 167 | return this.jel.find(".chosen-select").trigger("chosen:updated"); 168 | }; 169 | 170 | return BooleanField; 171 | 172 | })(); 173 | 174 | jsonform.FieldCollection = (function() { 175 | function FieldCollection(config) { 176 | this.config = config; 177 | this.tmpl = JST["fields/fieldcollection"]; 178 | this.jel = $("
    "); 179 | this.el = this.jel[0]; 180 | this.items = []; 181 | } 182 | 183 | FieldCollection.prototype.render = function() { 184 | this.jel.html(this.tmpl(this.config)); 185 | this.jel.find(".jfAdd").click((function(_this) { 186 | return function(e) { 187 | if ($(_this).is("[disabled]")) { 188 | return; 189 | } 190 | e.preventDefault(); 191 | return _this.addItem(); 192 | }; 193 | })(this)); 194 | if ($().sortable) { 195 | return this.jel.find(".jfCollection").sortable({ 196 | placeholder: ' ', 197 | itemSelector: '.jfCollectionItem', 198 | handle: 'i.jfSort', 199 | onDrop: (function(_this) { 200 | return function(item, container, _super) { 201 | _super(item, container); 202 | _this.items = _.sortBy(_this.items, function(item) { 203 | return item.jel.index(); 204 | }); 205 | return jsonform.helpers.changed(); 206 | }; 207 | })(this) 208 | }); 209 | } 210 | }; 211 | 212 | FieldCollection.prototype.getValues = function() { 213 | var results; 214 | results = _.map(this.items, function(item) { 215 | return item.getValue(); 216 | }); 217 | return _.without(results, "", void 0, null); 218 | }; 219 | 220 | FieldCollection.prototype.addItem = function(jsonValue) { 221 | var item; 222 | item = new jsonform.FieldCollectionItem(this.config, jsonValue); 223 | this.jel.find(".jfCollection").append(item.el); 224 | item.render(); 225 | this.items.push(item); 226 | item.jel.on("delete_clicked", (function(_this) { 227 | return function(e, item) { 228 | item.jel.remove(); 229 | _this.items = _.without(_this.items, item); 230 | _this.checkAddState(); 231 | return jsonform.helpers.changed(); 232 | }; 233 | })(this)); 234 | this.checkAddState(); 235 | if ($().sortable) { 236 | this.jel.find(".jfCollection").sortable("refresh"); 237 | } 238 | return jsonform.helpers.changed(); 239 | }; 240 | 241 | FieldCollection.prototype.itemsFromValues = function(vals) { 242 | return _.each(vals, (function(_this) { 243 | return function(val) { 244 | return _this.addItem(val); 245 | }; 246 | })(this)); 247 | }; 248 | 249 | FieldCollection.prototype.checkAddState = function() { 250 | if (this.config.jfMax) { 251 | if (this.items.length >= this.config.jfMax) { 252 | return this.jel.find(".jfAdd").attr("disabled", "disabled"); 253 | } else { 254 | return this.jel.find(".jfAdd").removeAttr("disabled"); 255 | } 256 | } 257 | }; 258 | 259 | return FieldCollection; 260 | 261 | })(); 262 | 263 | jsonform.FieldCollectionItem = (function() { 264 | function FieldCollectionItem(config, jsonValue) { 265 | this.jsonValue = jsonValue; 266 | this.deltmpl = JST["fields/fieldcollection-del"]; 267 | this.sorttmpl = JST["fields/fieldcollection-sort"]; 268 | this.jel = $('
    '); 269 | this.el = this.jel[0]; 270 | this.fields = []; 271 | this.config = {}; 272 | jQuery.extend(true, this.config, config); 273 | delete this.config.jfTitle; 274 | delete this.config.jfHelper; 275 | delete this.config.jfCollection; 276 | delete this.config.jfMax; 277 | if (config.jfType) { 278 | this.fields.push(jsonform.helpers.newField(this.config)); 279 | } else { 280 | _.each(this.config, (function(_this) { 281 | return function(v, k) { 282 | var field; 283 | if (v.jfType) { 284 | field = jsonform.helpers.newField(v); 285 | v.jfField = field; 286 | return _this.fields.push(field); 287 | } 288 | }; 289 | })(this)); 290 | } 291 | } 292 | 293 | FieldCollectionItem.prototype.render = function() { 294 | var del; 295 | this.jel.html(""); 296 | _.each(this.fields, (function(_this) { 297 | return function(field) { 298 | _this.jel.append(field.el); 299 | return field.render(); 300 | }; 301 | })(this)); 302 | if ($().sortable) { 303 | this.jel.append(this.sorttmpl()); 304 | } 305 | del = $(this.deltmpl()); 306 | this.jel.append(del); 307 | del.click((function(_this) { 308 | return function(e) { 309 | e.preventDefault(); 310 | return _this.jel.trigger("delete_clicked", _this); 311 | }; 312 | })(this)); 313 | if (!_.isUndefined(this.jsonValue)) { 314 | if (this.config.jfType) { 315 | return this.fields[0].setValue(this.jsonValue); 316 | } else { 317 | return _.each(this.config, (function(_this) { 318 | return function(v, k) { 319 | if (v.jfField && _this.jsonValue[k]) { 320 | return v.jfField.setValue(_this.jsonValue[k]); 321 | } 322 | }; 323 | })(this)); 324 | } 325 | } 326 | }; 327 | 328 | FieldCollectionItem.prototype.getValue = function() { 329 | var values; 330 | if (this.config.jfType) { 331 | return this.fields[0].getValue(); 332 | } else { 333 | values = {}; 334 | jQuery.extend(true, values, this.config); 335 | _.each(values, (function(_this) { 336 | return function(v, k) { 337 | if (v.jfField) { 338 | return values[k] = v.jfField.getValue(); 339 | } 340 | }; 341 | })(this)); 342 | return values; 343 | } 344 | }; 345 | 346 | return FieldCollectionItem; 347 | 348 | })(); 349 | 350 | jsonform.SelectField = (function() { 351 | function SelectField(config) { 352 | this.config = config; 353 | this.tmpl = JST["fields/select"]; 354 | this.jel = $('
    '); 355 | this.el = this.jel[0]; 356 | } 357 | 358 | SelectField.prototype.render = function() { 359 | this.jel.html(this.tmpl(this.config)); 360 | return this.jel.find(".chosen-select").chosen({ 361 | disable_search_threshold: 5, 362 | width: "300px" 363 | }).change((function(_this) { 364 | return function() { 365 | _this.jel.trigger("jf:changed"); 366 | return jsonform.helpers.changed(); 367 | }; 368 | })(this)); 369 | }; 370 | 371 | SelectField.prototype.getValue = function() { 372 | return this.jel.find(".chosen-select").val(); 373 | }; 374 | 375 | SelectField.prototype.setValue = function(val) { 376 | this.jel.find(".chosen-select").val(val + ""); 377 | return this.jel.find(".chosen-select").trigger("chosen:updated"); 378 | }; 379 | 380 | return SelectField; 381 | 382 | })(); 383 | 384 | jsonform.SelectAjaxField = (function() { 385 | function SelectAjaxField(config) { 386 | this.config = config; 387 | this.jel = $('
    '); 388 | this.el = this.jel[0]; 389 | this.selectField = new jsonform.SelectField({ 390 | jfValues: _.map(this.config.jfValues, function(val) { 391 | return val.jfValue; 392 | }) 393 | }); 394 | this.ajaxField = new jsonform.AjaxField(this.config.jfValues[0]); 395 | } 396 | 397 | SelectAjaxField.prototype.render = function() { 398 | this.jel.html(""); 399 | this.jel.append(this.selectField.el); 400 | this.jel.append(this.ajaxField.el); 401 | this.selectField.render(); 402 | this.ajaxField.render(); 403 | return this.selectField.jel.on("jf:changed", (function(_this) { 404 | return function() { 405 | return _this.selectSwitched(); 406 | }; 407 | })(this)); 408 | }; 409 | 410 | SelectAjaxField.prototype.getValue = function() { 411 | var val; 412 | val = {}; 413 | val[this.config.jfSelectKey] = this.selectField.getValue(); 414 | val[this.config.jfAjaxKey] = this.ajaxField.getValue(); 415 | return val; 416 | }; 417 | 418 | SelectAjaxField.prototype.setValue = function(val) { 419 | var ajaxConfig; 420 | this.selectField.setValue(val[this.config.jfSelectKey]); 421 | ajaxConfig = this.getConfigBySelectKey(this.selectField.getValue()); 422 | return jsonform.AjaxField.preloadValues(ajaxConfig, [val[this.config.jfAjaxKey]], (function(_this) { 423 | return function(data) { 424 | _this.ajaxField.config = ajaxConfig; 425 | return _this.ajaxField.setValue(data[0]); 426 | }; 427 | })(this)); 428 | }; 429 | 430 | SelectAjaxField.prototype.selectSwitched = function() { 431 | var ajaxConfig; 432 | ajaxConfig = this.getConfigBySelectKey(this.selectField.getValue()); 433 | this.ajaxField.config = ajaxConfig; 434 | return this.ajaxField.setValue(["", ""]); 435 | }; 436 | 437 | SelectAjaxField.prototype.getConfigBySelectKey = function(key) { 438 | return _.find(this.config.jfValues, function(conf) { 439 | return conf.jfValue[0] === key; 440 | }); 441 | }; 442 | 443 | return SelectAjaxField; 444 | 445 | })(); 446 | 447 | jsonform.StringField = (function() { 448 | function StringField(config) { 449 | this.config = config; 450 | this.tmpl = JST["fields/string"]; 451 | this.jel = $('
    '); 452 | this.el = this.jel[0]; 453 | } 454 | 455 | StringField.prototype.render = function() { 456 | this.jel.html(this.tmpl(this.config)); 457 | return this.jel.find("input").change(jsonform.helpers.changed); 458 | }; 459 | 460 | StringField.prototype.getValue = function() { 461 | return this.jel.find("input").val(); 462 | }; 463 | 464 | StringField.prototype.setValue = function(val) { 465 | return this.jel.find("input").val(val); 466 | }; 467 | 468 | return StringField; 469 | 470 | })(); 471 | 472 | jsonform.Form = (function() { 473 | function Form(txtArea, jsonConfig) { 474 | var txtval; 475 | this.jel = $('
    '); 476 | this.jtxt = $(txtArea); 477 | this.jtxt.hide(); 478 | this.fields = []; 479 | this.jsonConfig = jsonConfig; 480 | this.parseJsonConfig(this.jsonConfig); 481 | _.each(this.fields, (function(_this) { 482 | return function(field) { 483 | _this.jel.append(field.el); 484 | return field.render(); 485 | }; 486 | })(this)); 487 | $(document).bind('jf:change', (function(_this) { 488 | return function() { 489 | var json; 490 | json = _this.generateJson(_this.jsonConfig); 491 | return _this.jtxt.val(JSON.stringify(json, null, 2)); 492 | }; 493 | })(this)); 494 | this.jtxt.after(this.jel); 495 | txtval = this.jtxt.val(); 496 | if (!!txtval) { 497 | if (jsonform.helpers.isJsonString(txtval)) { 498 | this.fillFields(JSON.parse(txtval), this.jsonConfig); 499 | } else { 500 | jsonform.helpers.panic("Textarea has invalid JSON. jsonform will not work"); 501 | } 502 | } 503 | } 504 | 505 | Form.prototype.generateJson = function(obj) { 506 | var newObj, val, vals; 507 | if (_.isArray(obj)) { 508 | if (obj.length === 1 && obj[0].jfCollection) { 509 | vals = obj[0].jfCollection.getValues(); 510 | if (obj[0].jfCollection.config.jfValueType === "int") { 511 | vals = _.map(vals, function(val) { 512 | return parseInt(val); 513 | }); 514 | } 515 | return vals; 516 | } else { 517 | return _.map(obj, (function(_this) { 518 | return function(v) { 519 | return _this.generateJson(v); 520 | }; 521 | })(this)); 522 | } 523 | } else { 524 | if (obj.jfField) { 525 | val = obj.jfField.getValue(); 526 | if (obj.jfField.config.jfValueType === "int") { 527 | val = parseInt(val); 528 | } 529 | return val; 530 | } else { 531 | if (_.isObject(obj)) { 532 | newObj = {}; 533 | _.each(obj, (function(_this) { 534 | return function(v, k) { 535 | return newObj[k] = _this.generateJson(v); 536 | }; 537 | })(this)); 538 | return newObj; 539 | } else { 540 | return obj; 541 | } 542 | } 543 | } 544 | }; 545 | 546 | Form.prototype.parseJsonConfig = function(obj) { 547 | if (_.isArray(obj)) { 548 | if (obj.length === 1 && obj[0].jfCollection) { 549 | obj[0].jfCollection = new jsonform.FieldCollection(obj[0]); 550 | return this.fields.push(obj[0].jfCollection); 551 | } else { 552 | return _.each(obj, (function(_this) { 553 | return function(v) { 554 | return _this.parseJsonConfig(v); 555 | }; 556 | })(this)); 557 | } 558 | } else { 559 | if (obj.jfType) { 560 | obj.jfField = jsonform.helpers.newField(obj); 561 | return this.fields.push(obj.jfField); 562 | } else { 563 | return _.each(obj, (function(_this) { 564 | return function(v, k) { 565 | if (_.isObject(v)) { 566 | return _this.parseJsonConfig(v); 567 | } 568 | }; 569 | })(this)); 570 | } 571 | } 572 | }; 573 | 574 | Form.prototype.fillFields = function(obj, jsonConfig) { 575 | if (obj === void 0 || jsonConfig === void 0) { 576 | jsonform.helpers.panic("Existing JSON doesnt match JSON config."); 577 | } 578 | if (_.isArray(obj)) { 579 | if (jsonConfig.length === 1 && jsonConfig[0].jfCollection) { 580 | return jsonConfig[0].jfCollection.itemsFromValues(obj); 581 | } else { 582 | return _.each(obj, (function(_this) { 583 | return function(v, i) { 584 | return _this.fillFields(obj[i], jsonConfig[i]); 585 | }; 586 | })(this)); 587 | } 588 | } else { 589 | if (jsonConfig.jfField) { 590 | return jsonConfig.jfField.setValue(obj); 591 | } else { 592 | if (_.isObject(obj)) { 593 | return _.each(obj, (function(_this) { 594 | return function(v, k) { 595 | if (jsonConfig[k]) { 596 | return _this.fillFields(v, jsonConfig[k]); 597 | } else { 598 | console.log("jsonConfig object not present:"); 599 | console.log("key: ", k); 600 | return console.log("value: ", v); 601 | } 602 | }; 603 | })(this)); 604 | } 605 | } 606 | } 607 | }; 608 | 609 | return Form; 610 | 611 | })(); 612 | 613 | this.JST = {"fields/ajax": function(obj) { 614 | obj || (obj = {}); 615 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 616 | function print() { __p += __j.call(arguments, '') } 617 | with (obj) { 618 | 619 | if(typeof(jfTitle)!== 'undefined') { ; 620 | __p += '' + 621 | ((__t = ( jfTitle )) == null ? '' : __t) + 622 | ''; 623 | } ; 624 | __p += '\n'; 625 | if(typeof(jfHelper)!== 'undefined') { ; 626 | __p += '' + 627 | ((__t = ( jfHelper )) == null ? '' : __t) + 628 | ''; 629 | } ; 630 | __p += '\n\n'; 631 | 632 | } 633 | return __p 634 | }, 635 | "fields/boolean": function(obj) { 636 | obj || (obj = {}); 637 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 638 | function print() { __p += __j.call(arguments, '') } 639 | with (obj) { 640 | 641 | if(typeof(jfTitle)!== 'undefined') { ; 642 | __p += '' + 643 | ((__t = ( jfTitle )) == null ? '' : __t) + 644 | ''; 645 | } ; 646 | __p += '\n'; 647 | if(typeof(jfHelper)!== 'undefined') { ; 648 | __p += '' + 649 | ((__t = ( jfHelper )) == null ? '' : __t) + 650 | ''; 651 | } ; 652 | __p += '\n\n'; 653 | 654 | } 655 | return __p 656 | }, 657 | "fields/fieldcollection-del": function(obj) { 658 | obj || (obj = {}); 659 | var __t, __p = '', __e = _.escape; 660 | with (obj) { 661 | __p += 'Delete'; 662 | 663 | } 664 | return __p 665 | }, 666 | "fields/fieldcollection-sort": function(obj) { 667 | obj || (obj = {}); 668 | var __t, __p = '', __e = _.escape; 669 | with (obj) { 670 | __p += ''; 671 | 672 | } 673 | return __p 674 | }, 675 | "fields/fieldcollection": function(obj) { 676 | obj || (obj = {}); 677 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 678 | function print() { __p += __j.call(arguments, '') } 679 | with (obj) { 680 | 681 | if(typeof(jfTitle)!== 'undefined') { ; 682 | __p += '' + 683 | ((__t = ( jfTitle )) == null ? '' : __t) + 684 | ''; 685 | } ; 686 | __p += '\n'; 687 | if(typeof(jfHelper)!== 'undefined') { ; 688 | __p += '' + 689 | ((__t = ( jfHelper )) == null ? '' : __t) + 690 | ''; 691 | } ; 692 | __p += '\n\n+\n\n
    '; 693 | 694 | } 695 | return __p 696 | }, 697 | "fields/select": function(obj) { 698 | obj || (obj = {}); 699 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 700 | function print() { __p += __j.call(arguments, '') } 701 | with (obj) { 702 | 703 | if(typeof(jfTitle)!== 'undefined') { ; 704 | __p += '' + 705 | ((__t = ( jfTitle )) == null ? '' : __t) + 706 | ''; 707 | } ; 708 | __p += '\n'; 709 | if(typeof(jfHelper)!== 'undefined') { ; 710 | __p += '' + 711 | ((__t = ( jfHelper )) == null ? '' : __t) + 712 | ''; 713 | } ; 714 | __p += '\n\n'; 723 | 724 | } 725 | return __p 726 | }, 727 | "fields/selectajax": function(obj) { 728 | obj || (obj = {}); 729 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 730 | function print() { __p += __j.call(arguments, '') } 731 | with (obj) { 732 | 733 | if(typeof(jfTitle)!== 'undefined') { ; 734 | __p += '' + 735 | ((__t = ( jfTitle )) == null ? '' : __t) + 736 | ''; 737 | } ; 738 | __p += '\n'; 739 | if(typeof(jfHelper)!== 'undefined') { ; 740 | __p += '' + 741 | ((__t = ( jfHelper )) == null ? '' : __t) + 742 | ''; 743 | } ; 744 | __p += '\n\n'; 753 | 754 | } 755 | return __p 756 | }, 757 | "fields/string": function(obj) { 758 | obj || (obj = {}); 759 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 760 | function print() { __p += __j.call(arguments, '') } 761 | with (obj) { 762 | 763 | if(typeof(jfTitle)!== 'undefined') { ; 764 | __p += '' + 765 | ((__t = ( jfTitle )) == null ? '' : __t) + 766 | ''; 767 | } ; 768 | __p += '\n'; 769 | if(typeof(jfHelper)!== 'undefined') { ; 770 | __p += '' + 771 | ((__t = ( jfHelper )) == null ? '' : __t) + 772 | ''; 773 | } ; 774 | __p += '\n\n'; 775 | 776 | } 777 | return __p 778 | }}; -------------------------------------------------------------------------------- /examples/ajax.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSON Form test 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 |

    JSON Form test

    24 | 25 | 34 | 35 | 71 | 72 | -------------------------------------------------------------------------------- /examples/boolean.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSON Form test 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 |

    JSON Form test

    24 | 25 | 30 | 31 | 53 | 54 | -------------------------------------------------------------------------------- /examples/collectionobjects.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSON Form test 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 |

    JSON Form test

    25 | 26 | 51 | 52 | 88 | 89 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSON Form test 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 |

    JSON Form Examples

    24 | 25 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/javascripts/chosen/chosen-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreillymedia/jsonform/7d38b902dd458587c7d149ee2dde5e28e899160a/examples/javascripts/chosen/chosen-sprite.png -------------------------------------------------------------------------------- /examples/javascripts/chosen/chosen-sprite@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreillymedia/jsonform/7d38b902dd458587c7d149ee2dde5e28e899160a/examples/javascripts/chosen/chosen-sprite@2x.png -------------------------------------------------------------------------------- /examples/javascripts/chosen/chosen.css: -------------------------------------------------------------------------------- 1 | /*! 2 | Chosen, a Select Box Enhancer for jQuery and Prototype 3 | by Patrick Filler for Harvest, http://getharvest.com 4 | 5 | Version 1.4.1 6 | Full source at https://github.com/harvesthq/chosen 7 | Copyright (c) 2011-2015 Harvest http://getharvest.com 8 | 9 | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md 10 | This file is generated by `grunt build`, do not edit it by hand. 11 | */ 12 | 13 | /* @group Base */ 14 | .chosen-container { 15 | position: relative; 16 | display: inline-block; 17 | vertical-align: middle; 18 | font-size: 13px; 19 | zoom: 1; 20 | *display: inline; 21 | -webkit-user-select: none; 22 | -moz-user-select: none; 23 | user-select: none; 24 | } 25 | .chosen-container * { 26 | -webkit-box-sizing: border-box; 27 | -moz-box-sizing: border-box; 28 | box-sizing: border-box; 29 | } 30 | .chosen-container .chosen-drop { 31 | position: absolute; 32 | top: 100%; 33 | left: -9999px; 34 | z-index: 1010; 35 | width: 100%; 36 | border: 1px solid #aaa; 37 | border-top: 0; 38 | background: #fff; 39 | box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); 40 | } 41 | .chosen-container.chosen-with-drop .chosen-drop { 42 | left: 0; 43 | } 44 | .chosen-container a { 45 | cursor: pointer; 46 | } 47 | .chosen-container .search-choice .group-name, .chosen-container .chosen-single .group-name { 48 | margin-right: 4px; 49 | overflow: hidden; 50 | white-space: nowrap; 51 | text-overflow: ellipsis; 52 | font-weight: normal; 53 | color: #999999; 54 | } 55 | .chosen-container .search-choice .group-name:after, .chosen-container .chosen-single .group-name:after { 56 | content: ":"; 57 | padding-left: 2px; 58 | vertical-align: top; 59 | } 60 | 61 | /* @end */ 62 | /* @group Single Chosen */ 63 | .chosen-container-single .chosen-single { 64 | position: relative; 65 | display: block; 66 | overflow: hidden; 67 | padding: 0 0 0 8px; 68 | height: 25px; 69 | border: 1px solid #aaa; 70 | border-radius: 5px; 71 | background-color: #fff; 72 | background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4)); 73 | background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); 74 | background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); 75 | background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); 76 | background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); 77 | background-clip: padding-box; 78 | box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1); 79 | color: #444; 80 | text-decoration: none; 81 | white-space: nowrap; 82 | line-height: 24px; 83 | } 84 | .chosen-container-single .chosen-default { 85 | color: #999; 86 | } 87 | .chosen-container-single .chosen-single span { 88 | display: block; 89 | overflow: hidden; 90 | margin-right: 26px; 91 | text-overflow: ellipsis; 92 | white-space: nowrap; 93 | } 94 | .chosen-container-single .chosen-single-with-deselect span { 95 | margin-right: 38px; 96 | } 97 | .chosen-container-single .chosen-single abbr { 98 | position: absolute; 99 | top: 6px; 100 | right: 26px; 101 | display: block; 102 | width: 12px; 103 | height: 12px; 104 | background: url('chosen-sprite.png') -42px 1px no-repeat; 105 | font-size: 1px; 106 | } 107 | .chosen-container-single .chosen-single abbr:hover { 108 | background-position: -42px -10px; 109 | } 110 | .chosen-container-single.chosen-disabled .chosen-single abbr:hover { 111 | background-position: -42px -10px; 112 | } 113 | .chosen-container-single .chosen-single div { 114 | position: absolute; 115 | top: 0; 116 | right: 0; 117 | display: block; 118 | width: 18px; 119 | height: 100%; 120 | } 121 | .chosen-container-single .chosen-single div b { 122 | display: block; 123 | width: 100%; 124 | height: 100%; 125 | background: url('chosen-sprite.png') no-repeat 0px 2px; 126 | } 127 | .chosen-container-single .chosen-search { 128 | position: relative; 129 | z-index: 1010; 130 | margin: 0; 131 | padding: 3px 4px; 132 | white-space: nowrap; 133 | } 134 | .chosen-container-single .chosen-search input[type="text"] { 135 | margin: 1px 0; 136 | padding: 4px 20px 4px 5px; 137 | width: 100%; 138 | height: auto; 139 | outline: 0; 140 | border: 1px solid #aaa; 141 | background: white url('chosen-sprite.png') no-repeat 100% -20px; 142 | background: url('chosen-sprite.png') no-repeat 100% -20px; 143 | font-size: 1em; 144 | font-family: sans-serif; 145 | line-height: normal; 146 | border-radius: 0; 147 | } 148 | .chosen-container-single .chosen-drop { 149 | margin-top: -1px; 150 | border-radius: 0 0 4px 4px; 151 | background-clip: padding-box; 152 | } 153 | .chosen-container-single.chosen-container-single-nosearch .chosen-search { 154 | position: absolute; 155 | left: -9999px; 156 | } 157 | 158 | /* @end */ 159 | /* @group Results */ 160 | .chosen-container .chosen-results { 161 | color: #444; 162 | position: relative; 163 | overflow-x: hidden; 164 | overflow-y: auto; 165 | margin: 0 4px 4px 0; 166 | padding: 0 0 0 4px; 167 | max-height: 240px; 168 | -webkit-overflow-scrolling: touch; 169 | } 170 | .chosen-container .chosen-results li { 171 | display: none; 172 | margin: 0; 173 | padding: 5px 6px; 174 | list-style: none; 175 | line-height: 15px; 176 | word-wrap: break-word; 177 | -webkit-touch-callout: none; 178 | } 179 | .chosen-container .chosen-results li.active-result { 180 | display: list-item; 181 | cursor: pointer; 182 | } 183 | .chosen-container .chosen-results li.disabled-result { 184 | display: list-item; 185 | color: #ccc; 186 | cursor: default; 187 | } 188 | .chosen-container .chosen-results li.highlighted { 189 | background-color: #3875d7; 190 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc)); 191 | background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%); 192 | background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%); 193 | background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%); 194 | background-image: linear-gradient(#3875d7 20%, #2a62bc 90%); 195 | color: #fff; 196 | } 197 | .chosen-container .chosen-results li.no-results { 198 | color: #777; 199 | display: list-item; 200 | background: #f4f4f4; 201 | } 202 | .chosen-container .chosen-results li.group-result { 203 | display: list-item; 204 | font-weight: bold; 205 | cursor: default; 206 | } 207 | .chosen-container .chosen-results li.group-option { 208 | padding-left: 15px; 209 | } 210 | .chosen-container .chosen-results li em { 211 | font-style: normal; 212 | text-decoration: underline; 213 | } 214 | 215 | /* @end */ 216 | /* @group Multi Chosen */ 217 | .chosen-container-multi .chosen-choices { 218 | position: relative; 219 | overflow: hidden; 220 | margin: 0; 221 | padding: 0 5px; 222 | width: 100%; 223 | height: auto !important; 224 | height: 1%; 225 | border: 1px solid #aaa; 226 | background-color: #fff; 227 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); 228 | background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%); 229 | background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%); 230 | background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%); 231 | background-image: linear-gradient(#eeeeee 1%, #ffffff 15%); 232 | cursor: text; 233 | } 234 | .chosen-container-multi .chosen-choices li { 235 | float: left; 236 | list-style: none; 237 | } 238 | .chosen-container-multi .chosen-choices li.search-field { 239 | margin: 0; 240 | padding: 0; 241 | white-space: nowrap; 242 | } 243 | .chosen-container-multi .chosen-choices li.search-field input[type="text"] { 244 | margin: 1px 0; 245 | padding: 0; 246 | height: 25px; 247 | outline: 0; 248 | border: 0 !important; 249 | background: transparent !important; 250 | box-shadow: none; 251 | color: #999; 252 | font-size: 100%; 253 | font-family: sans-serif; 254 | line-height: normal; 255 | border-radius: 0; 256 | } 257 | .chosen-container-multi .chosen-choices li.search-choice { 258 | position: relative; 259 | margin: 3px 5px 3px 0; 260 | padding: 3px 20px 3px 5px; 261 | border: 1px solid #aaa; 262 | max-width: 100%; 263 | border-radius: 3px; 264 | background-color: #eeeeee; 265 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); 266 | background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 267 | background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 268 | background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 269 | background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 270 | background-size: 100% 19px; 271 | background-repeat: repeat-x; 272 | background-clip: padding-box; 273 | box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05); 274 | color: #333; 275 | line-height: 13px; 276 | cursor: default; 277 | } 278 | .chosen-container-multi .chosen-choices li.search-choice span { 279 | word-wrap: break-word; 280 | } 281 | .chosen-container-multi .chosen-choices li.search-choice .search-choice-close { 282 | position: absolute; 283 | top: 4px; 284 | right: 3px; 285 | display: block; 286 | width: 12px; 287 | height: 12px; 288 | background: url('chosen-sprite.png') -42px 1px no-repeat; 289 | font-size: 1px; 290 | } 291 | .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover { 292 | background-position: -42px -10px; 293 | } 294 | .chosen-container-multi .chosen-choices li.search-choice-disabled { 295 | padding-right: 5px; 296 | border: 1px solid #ccc; 297 | background-color: #e4e4e4; 298 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); 299 | background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 300 | background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 301 | background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 302 | background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 303 | color: #666; 304 | } 305 | .chosen-container-multi .chosen-choices li.search-choice-focus { 306 | background: #d4d4d4; 307 | } 308 | .chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close { 309 | background-position: -42px -10px; 310 | } 311 | .chosen-container-multi .chosen-results { 312 | margin: 0; 313 | padding: 0; 314 | } 315 | .chosen-container-multi .chosen-drop .result-selected { 316 | display: list-item; 317 | color: #ccc; 318 | cursor: default; 319 | } 320 | 321 | /* @end */ 322 | /* @group Active */ 323 | .chosen-container-active .chosen-single { 324 | border: 1px solid #5897fb; 325 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); 326 | } 327 | .chosen-container-active.chosen-with-drop .chosen-single { 328 | border: 1px solid #aaa; 329 | -moz-border-radius-bottomright: 0; 330 | border-bottom-right-radius: 0; 331 | -moz-border-radius-bottomleft: 0; 332 | border-bottom-left-radius: 0; 333 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff)); 334 | background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%); 335 | background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%); 336 | background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%); 337 | background-image: linear-gradient(#eeeeee 20%, #ffffff 80%); 338 | box-shadow: 0 1px 0 #fff inset; 339 | } 340 | .chosen-container-active.chosen-with-drop .chosen-single div { 341 | border-left: none; 342 | background: transparent; 343 | } 344 | .chosen-container-active.chosen-with-drop .chosen-single div b { 345 | background-position: -18px 2px; 346 | } 347 | .chosen-container-active .chosen-choices { 348 | border: 1px solid #5897fb; 349 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); 350 | } 351 | .chosen-container-active .chosen-choices li.search-field input[type="text"] { 352 | color: #222 !important; 353 | } 354 | 355 | /* @end */ 356 | /* @group Disabled Support */ 357 | .chosen-disabled { 358 | opacity: 0.5 !important; 359 | cursor: default; 360 | } 361 | .chosen-disabled .chosen-single { 362 | cursor: default; 363 | } 364 | .chosen-disabled .chosen-choices .search-choice .search-choice-close { 365 | cursor: default; 366 | } 367 | 368 | /* @end */ 369 | /* @group Right to Left */ 370 | .chosen-rtl { 371 | text-align: right; 372 | } 373 | .chosen-rtl .chosen-single { 374 | overflow: visible; 375 | padding: 0 8px 0 0; 376 | } 377 | .chosen-rtl .chosen-single span { 378 | margin-right: 0; 379 | margin-left: 26px; 380 | direction: rtl; 381 | } 382 | .chosen-rtl .chosen-single-with-deselect span { 383 | margin-left: 38px; 384 | } 385 | .chosen-rtl .chosen-single div { 386 | right: auto; 387 | left: 3px; 388 | } 389 | .chosen-rtl .chosen-single abbr { 390 | right: auto; 391 | left: 26px; 392 | } 393 | .chosen-rtl .chosen-choices li { 394 | float: right; 395 | } 396 | .chosen-rtl .chosen-choices li.search-field input[type="text"] { 397 | direction: rtl; 398 | } 399 | .chosen-rtl .chosen-choices li.search-choice { 400 | margin: 3px 5px 3px 0; 401 | padding: 3px 5px 3px 19px; 402 | } 403 | .chosen-rtl .chosen-choices li.search-choice .search-choice-close { 404 | right: auto; 405 | left: 4px; 406 | } 407 | .chosen-rtl.chosen-container-single-nosearch .chosen-search, 408 | .chosen-rtl .chosen-drop { 409 | left: 9999px; 410 | } 411 | .chosen-rtl.chosen-container-single .chosen-results { 412 | margin: 0 0 4px 4px; 413 | padding: 0 4px 0 0; 414 | } 415 | .chosen-rtl .chosen-results li.group-option { 416 | padding-right: 15px; 417 | padding-left: 0; 418 | } 419 | .chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div { 420 | border-right: none; 421 | } 422 | .chosen-rtl .chosen-search input[type="text"] { 423 | padding: 4px 5px 4px 20px; 424 | background: white url('chosen-sprite.png') no-repeat -30px -20px; 425 | background: url('chosen-sprite.png') no-repeat -30px -20px; 426 | direction: rtl; 427 | } 428 | .chosen-rtl.chosen-container-single .chosen-single div b { 429 | background-position: 6px 2px; 430 | } 431 | .chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b { 432 | background-position: -12px 2px; 433 | } 434 | 435 | /* @end */ 436 | /* @group Retina compatibility */ 437 | @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi), only screen and (min-resolution: 1.5dppx) { 438 | .chosen-rtl .chosen-search input[type="text"], 439 | .chosen-container-single .chosen-single abbr, 440 | .chosen-container-single .chosen-single div b, 441 | .chosen-container-single .chosen-search input[type="text"], 442 | .chosen-container-multi .chosen-choices .search-choice .search-choice-close, 443 | .chosen-container .chosen-results-scroll-down span, 444 | .chosen-container .chosen-results-scroll-up span { 445 | background-image: url('chosen-sprite@2x.png') !important; 446 | background-size: 52px 37px !important; 447 | background-repeat: no-repeat !important; 448 | } 449 | } 450 | /* @end */ 451 | -------------------------------------------------------------------------------- /examples/javascripts/chosen/chosen.jquery.min.js: -------------------------------------------------------------------------------- 1 | /* Chosen v1.4.1 | (c) 2011-2015 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ 2 | (function(){var a,AbstractChosen,Chosen,SelectParser,b,c={}.hasOwnProperty,d=function(a,b){function d(){this.constructor=a}for(var e in b)c.call(b,e)&&(a[e]=b[e]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a};SelectParser=function(){function SelectParser(){this.options_index=0,this.parsed=[]}return SelectParser.prototype.add_node=function(a){return"OPTGROUP"===a.nodeName.toUpperCase()?this.add_group(a):this.add_option(a)},SelectParser.prototype.add_group=function(a){var b,c,d,e,f,g;for(b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:this.escapeExpression(a.label),title:a.title?a.title:void 0,children:0,disabled:a.disabled,classes:a.className}),f=a.childNodes,g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(this.add_option(c,b,a.disabled));return g},SelectParser.prototype.add_option=function(a,b,c){return"OPTION"===a.nodeName.toUpperCase()?(""!==a.text?(null!=b&&(this.parsed[b].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:a.value,text:a.text,html:a.innerHTML,title:a.title?a.title:void 0,selected:a.selected,disabled:c===!0?c:a.disabled,group_array_index:b,group_label:null!=b?this.parsed[b].label:null,classes:a.className,style:a.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1):void 0},SelectParser.prototype.escapeExpression=function(a){var b,c;return null==a||a===!1?"":/[\&\<\>\"\'\`]/.test(a)?(b={"<":"<",">":">",'"':""","'":"'","`":"`"},c=/&(?!\w+;)|[\<\>\"\'\`]/g,a.replace(c,function(a){return b[a]||"&"})):a},SelectParser}(),SelectParser.select_to_array=function(a){var b,c,d,e,f;for(c=new SelectParser,f=a.childNodes,d=0,e=f.length;e>d;d++)b=f[d],c.add_node(b);return c.parsed},AbstractChosen=function(){function AbstractChosen(a,b){this.form_field=a,this.options=null!=b?b:{},AbstractChosen.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers(),this.on_ready())}return AbstractChosen.prototype.set_default_values=function(){var a=this;return this.click_test_action=function(b){return a.test_active_click(b)},this.activate_action=function(b){return a.activate_field(b)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null!=this.options.enable_split_word_search?this.options.enable_split_word_search:!0,this.group_search=null!=this.options.group_search?this.options.group_search:!0,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null!=this.options.single_backstroke_delete?this.options.single_backstroke_delete:!0,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null!=this.options.display_selected_options?this.options.display_selected_options:!0,this.display_disabled_options=null!=this.options.display_disabled_options?this.options.display_disabled_options:!0,this.include_group_label_in_selected=this.options.include_group_label_in_selected||!1},AbstractChosen.prototype.set_default_text=function(){return this.default_text=this.form_field.getAttribute("data-placeholder")?this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.options.placeholder_text_multiple||this.options.placeholder_text||AbstractChosen.default_multiple_text:this.options.placeholder_text_single||this.options.placeholder_text||AbstractChosen.default_single_text,this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||AbstractChosen.default_no_result_text},AbstractChosen.prototype.choice_label=function(a){return this.include_group_label_in_selected&&null!=a.group_label?""+a.group_label+""+a.html:a.html},AbstractChosen.prototype.mouse_enter=function(){return this.mouse_on_container=!0},AbstractChosen.prototype.mouse_leave=function(){return this.mouse_on_container=!1},AbstractChosen.prototype.input_focus=function(){var a=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return a.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},AbstractChosen.prototype.input_blur=function(){var a=this;return this.mouse_on_container?void 0:(this.active_field=!1,setTimeout(function(){return a.blur_test()},100))},AbstractChosen.prototype.results_option_build=function(a){var b,c,d,e,f;for(b="",f=this.results_data,d=0,e=f.length;e>d;d++)c=f[d],b+=c.group?this.result_add_group(c):this.result_add_option(c),(null!=a?a.first:void 0)&&(c.selected&&this.is_multiple?this.choice_build(c):c.selected&&!this.is_multiple&&this.single_set_selected_text(this.choice_label(c)));return b},AbstractChosen.prototype.result_add_option=function(a){var b,c;return a.search_match?this.include_option_in_results(a)?(b=[],a.disabled||a.selected&&this.is_multiple||b.push("active-result"),!a.disabled||a.selected&&this.is_multiple||b.push("disabled-result"),a.selected&&b.push("result-selected"),null!=a.group_array_index&&b.push("group-option"),""!==a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.style.cssText=a.style,c.setAttribute("data-option-array-index",a.array_index),c.innerHTML=a.search_text,a.title&&(c.title=a.title),this.outerHTML(c)):"":""},AbstractChosen.prototype.result_add_group=function(a){var b,c;return a.search_match||a.group_match?a.active_options>0?(b=[],b.push("group-result"),a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.innerHTML=a.search_text,a.title&&(c.title=a.title),this.outerHTML(c)):"":""},AbstractChosen.prototype.results_update_field=function(){return this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing?this.winnow_results():void 0},AbstractChosen.prototype.reset_single_select_options=function(){var a,b,c,d,e;for(d=this.results_data,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.selected?e.push(a.selected=!1):e.push(void 0);return e},AbstractChosen.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},AbstractChosen.prototype.results_search=function(){return this.results_showing?this.winnow_results():this.results_show()},AbstractChosen.prototype.winnow_results=function(){var a,b,c,d,e,f,g,h,i,j,k,l;for(this.no_results_clear(),d=0,f=this.get_search_text(),a=f.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),i=new RegExp(a,"i"),c=this.get_search_regex(a),l=this.results_data,j=0,k=l.length;k>j;j++)b=l[j],b.search_match=!1,e=null,this.include_option_in_results(b)&&(b.group&&(b.group_match=!1,b.active_options=0),null!=b.group_array_index&&this.results_data[b.group_array_index]&&(e=this.results_data[b.group_array_index],0===e.active_options&&e.search_match&&(d+=1),e.active_options+=1),b.search_text=b.group?b.label:b.html,(!b.group||this.group_search)&&(b.search_match=this.search_string_match(b.search_text,c),b.search_match&&!b.group&&(d+=1),b.search_match?(f.length&&(g=b.search_text.search(i),h=b.search_text.substr(0,g+f.length)+""+b.search_text.substr(g+f.length),b.search_text=h.substr(0,g)+""+h.substr(g)),null!=e&&(e.group_match=!0)):null!=b.group_array_index&&this.results_data[b.group_array_index].search_match&&(b.search_match=!0)));return this.result_clear_highlight(),1>d&&f.length?(this.update_results_content(""),this.no_results(f)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},AbstractChosen.prototype.get_search_regex=function(a){var b;return b=this.search_contains?"":"^",new RegExp(b+a,"i")},AbstractChosen.prototype.search_string_match=function(a,b){var c,d,e,f;if(b.test(a))return!0;if(this.enable_split_word_search&&(a.indexOf(" ")>=0||0===a.indexOf("["))&&(d=a.replace(/\[|\]/g,"").split(" "),d.length))for(e=0,f=d.length;f>e;e++)if(c=d[e],b.test(c))return!0},AbstractChosen.prototype.choices_count=function(){var a,b,c,d;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,d=this.form_field.options,b=0,c=d.length;c>b;b++)a=d[b],a.selected&&(this.selected_option_count+=1);return this.selected_option_count},AbstractChosen.prototype.choices_click=function(a){return a.preventDefault(),this.results_showing||this.is_disabled?void 0:this.results_show()},AbstractChosen.prototype.keyup_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(a.preventDefault(),this.results_showing)return this.result_select(a);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},AbstractChosen.prototype.clipboard_event_checker=function(){var a=this;return setTimeout(function(){return a.results_search()},50)},AbstractChosen.prototype.container_width=function(){return null!=this.options.width?this.options.width:""+this.form_field.offsetWidth+"px"},AbstractChosen.prototype.include_option_in_results=function(a){return this.is_multiple&&!this.display_selected_options&&a.selected?!1:!this.display_disabled_options&&a.disabled?!1:a.empty?!1:!0},AbstractChosen.prototype.search_results_touchstart=function(a){return this.touch_started=!0,this.search_results_mouseover(a)},AbstractChosen.prototype.search_results_touchmove=function(a){return this.touch_started=!1,this.search_results_mouseout(a)},AbstractChosen.prototype.search_results_touchend=function(a){return this.touch_started?this.search_results_mouseup(a):void 0},AbstractChosen.prototype.outerHTML=function(a){var b;return a.outerHTML?a.outerHTML:(b=document.createElement("div"),b.appendChild(a),b.innerHTML)},AbstractChosen.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:/iP(od|hone)/i.test(window.navigator.userAgent)?!1:/Android/i.test(window.navigator.userAgent)&&/Mobile/i.test(window.navigator.userAgent)?!1:!0},AbstractChosen.default_multiple_text="Select Some Options",AbstractChosen.default_single_text="Select an Option",AbstractChosen.default_no_result_text="No results match",AbstractChosen}(),a=jQuery,a.fn.extend({chosen:function(b){return AbstractChosen.browser_is_supported()?this.each(function(){var c,d;c=a(this),d=c.data("chosen"),"destroy"===b&&d instanceof Chosen?d.destroy():d instanceof Chosen||c.data("chosen",new Chosen(this,b))}):this}}),Chosen=function(c){function Chosen(){return b=Chosen.__super__.constructor.apply(this,arguments)}return d(Chosen,c),Chosen.prototype.setup=function(){return this.form_field_jq=a(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field_jq.hasClass("chosen-rtl")},Chosen.prototype.set_up_html=function(){var b,c;return b=["chosen-container"],b.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&b.push(this.form_field.className),this.is_rtl&&b.push("chosen-rtl"),c={"class":b.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(c.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=a("
    ",c),this.is_multiple?this.container.html('
      '):this.container.html(''+this.default_text+'
        '),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior()},Chosen.prototype.on_ready=function(){return this.form_field_jq.trigger("chosen:ready",{chosen:this})},Chosen.prototype.register_observers=function(){var a=this;return this.container.bind("touchstart.chosen",function(b){return a.container_mousedown(b),b.preventDefault()}),this.container.bind("touchend.chosen",function(b){return a.container_mouseup(b),b.preventDefault()}),this.container.bind("mousedown.chosen",function(b){a.container_mousedown(b)}),this.container.bind("mouseup.chosen",function(b){a.container_mouseup(b)}),this.container.bind("mouseenter.chosen",function(b){a.mouse_enter(b)}),this.container.bind("mouseleave.chosen",function(b){a.mouse_leave(b)}),this.search_results.bind("mouseup.chosen",function(b){a.search_results_mouseup(b)}),this.search_results.bind("mouseover.chosen",function(b){a.search_results_mouseover(b)}),this.search_results.bind("mouseout.chosen",function(b){a.search_results_mouseout(b)}),this.search_results.bind("mousewheel.chosen DOMMouseScroll.chosen",function(b){a.search_results_mousewheel(b)}),this.search_results.bind("touchstart.chosen",function(b){a.search_results_touchstart(b)}),this.search_results.bind("touchmove.chosen",function(b){a.search_results_touchmove(b)}),this.search_results.bind("touchend.chosen",function(b){a.search_results_touchend(b)}),this.form_field_jq.bind("chosen:updated.chosen",function(b){a.results_update_field(b)}),this.form_field_jq.bind("chosen:activate.chosen",function(b){a.activate_field(b)}),this.form_field_jq.bind("chosen:open.chosen",function(b){a.container_mousedown(b)}),this.form_field_jq.bind("chosen:close.chosen",function(b){a.input_blur(b)}),this.search_field.bind("blur.chosen",function(b){a.input_blur(b)}),this.search_field.bind("keyup.chosen",function(b){a.keyup_checker(b)}),this.search_field.bind("keydown.chosen",function(b){a.keydown_checker(b)}),this.search_field.bind("focus.chosen",function(b){a.input_focus(b)}),this.search_field.bind("cut.chosen",function(b){a.clipboard_event_checker(b)}),this.search_field.bind("paste.chosen",function(b){a.clipboard_event_checker(b)}),this.is_multiple?this.search_choices.bind("click.chosen",function(b){a.choices_click(b)}):this.container.bind("click.chosen",function(a){a.preventDefault()})},Chosen.prototype.destroy=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},Chosen.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field_jq[0].disabled,this.is_disabled?(this.container.addClass("chosen-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus.chosen",this.activate_action),this.close_field()):(this.container.removeClass("chosen-disabled"),this.search_field[0].disabled=!1,this.is_multiple?void 0:this.selected_item.bind("focus.chosen",this.activate_action))},Chosen.prototype.container_mousedown=function(b){return this.is_disabled||(b&&"mousedown"===b.type&&!this.results_showing&&b.preventDefault(),null!=b&&a(b.target).hasClass("search-choice-close"))?void 0:(this.active_field?this.is_multiple||!b||a(b.target)[0]!==this.selected_item[0]&&!a(b.target).parents("a.chosen-single").length||(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(this.container[0].ownerDocument).bind("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},Chosen.prototype.container_mouseup=function(a){return"ABBR"!==a.target.nodeName||this.is_disabled?void 0:this.results_reset(a)},Chosen.prototype.search_results_mousewheel=function(a){var b;return a.originalEvent&&(b=a.originalEvent.deltaY||-a.originalEvent.wheelDelta||a.originalEvent.detail),null!=b?(a.preventDefault(),"DOMMouseScroll"===a.type&&(b=40*b),this.search_results.scrollTop(b+this.search_results.scrollTop())):void 0},Chosen.prototype.blur_test=function(){return!this.active_field&&this.container.hasClass("chosen-container-active")?this.close_field():void 0},Chosen.prototype.close_field=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},Chosen.prototype.activate_field=function(){return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},Chosen.prototype.test_active_click=function(b){var c;return c=a(b.target).closest(".chosen-container"),c.length&&this.container[0]===c[0]?this.active_field=!0:this.close_field()},Chosen.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=SelectParser.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},Chosen.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){if(this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight(),b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(f>c)return this.search_results.scrollTop(c)}},Chosen.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},Chosen.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.container.addClass("chosen-with-drop"),this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.search_field.val()),this.winnow_results(),this.form_field_jq.trigger("chosen:showing_dropdown",{chosen:this}))},Chosen.prototype.update_results_content=function(a){return this.search_results.html(a)},Chosen.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},Chosen.prototype.set_tab_index=function(){var a;return this.form_field.tabIndex?(a=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=a):void 0},Chosen.prototype.set_label_behavior=function(){var b=this;return this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=a("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0?this.form_field_label.bind("click.chosen",function(a){return b.is_multiple?b.container_mousedown(a):b.activate_field()}):void 0},Chosen.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},Chosen.prototype.search_results_mouseup=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c.length?(this.result_highlight=c,this.result_select(b),this.search_field.focus()):void 0},Chosen.prototype.search_results_mouseover=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c?this.result_do_highlight(c):void 0},Chosen.prototype.search_results_mouseout=function(b){return a(b.target).hasClass("active-result")?this.result_clear_highlight():void 0},Chosen.prototype.choice_build=function(b){var c,d,e=this;return c=a("
      • ",{"class":"search-choice"}).html(""+this.choice_label(b)+""),b.disabled?c.addClass("search-choice-disabled"):(d=a("",{"class":"search-choice-close","data-option-array-index":b.array_index}),d.bind("click.chosen",function(a){return e.choice_destroy_link_click(a)}),c.append(d)),this.search_container.before(c)},Chosen.prototype.choice_destroy_link_click=function(b){return b.preventDefault(),b.stopPropagation(),this.is_disabled?void 0:this.choice_destroy(a(b.target))},Chosen.prototype.choice_destroy=function(a){return this.result_deselect(a[0].getAttribute("data-option-array-index"))?(this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.val().length<1&&this.results_hide(),a.parents("li").first().remove(),this.search_field_scale()):void 0},Chosen.prototype.results_reset=function(){return this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.form_field_jq.trigger("change"),this.active_field?this.results_hide():void 0},Chosen.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},Chosen.prototype.result_select=function(a){var b,c;return this.result_highlight?(b=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?b.removeClass("active-result"):this.reset_single_select_options(),c=this.results_data[b[0].getAttribute("data-option-array-index")],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(c):this.single_set_selected_text(this.choice_label(c)),(a.metaKey||a.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.val(""),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.form_field_jq.trigger("change",{selected:this.form_field.options[c.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,a.preventDefault(),this.search_field_scale())):void 0},Chosen.prototype.single_set_selected_text=function(a){return null==a&&(a=this.default_text),a===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").html(a)},Chosen.prototype.result_deselect=function(a){var b;return b=this.results_data[a],this.form_field.options[b.options_index].disabled?!1:(b.selected=!1,this.form_field.options[b.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[b.options_index].value}),this.search_field_scale(),!0)},Chosen.prototype.single_deselect_control_build=function(){return this.allow_single_deselect?(this.selected_item.find("abbr").length||this.selected_item.find("span").first().after(''),this.selected_item.addClass("chosen-single-with-deselect")):void 0},Chosen.prototype.get_search_text=function(){return a("
        ").text(a.trim(this.search_field.val())).html()},Chosen.prototype.winnow_results_set_highlight=function(){var a,b;return b=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),a=b.length?b.first():this.search_results.find(".active-result").first(),null!=a?this.result_do_highlight(a):void 0},Chosen.prototype.no_results=function(b){var c;return c=a('
      • '+this.results_none_found+' ""
      • '),c.find("span").first().html(b),this.search_results.append(c),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},Chosen.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},Chosen.prototype.keydown_arrow=function(){var a;return this.results_showing&&this.result_highlight?(a=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(a):void 0:this.results_show()},Chosen.prototype.keyup_arrow=function(){var a;return this.results_showing||this.is_multiple?this.result_highlight?(a=this.result_highlight.prevAll("li.active-result"),a.length?this.result_do_highlight(a.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},Chosen.prototype.keydown_backstroke=function(){var a;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(a=this.search_container.siblings("li.search-choice").last(),a.length&&!a.hasClass("search-choice-disabled")?(this.pending_backstroke=a,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0)},Chosen.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},Chosen.prototype.keydown_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),8!==b&&this.pending_backstroke&&this.clear_backstroke(),b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:this.results_showing&&a.preventDefault();break;case 32:this.disable_search&&a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:a.preventDefault(),this.keydown_arrow()}},Chosen.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){for(d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],i=0,j=g.length;j>i;i++)e=g[i],f+=e+":"+this.search_field.css(e)+";";return b=a("
        ",{style:f}),b.text(this.search_field.val()),a("body").append(b),h=b.width()+25,b.remove(),c=this.container.outerWidth(),h>c-10&&(h=c-10),this.search_field.css({width:h+"px"})}},Chosen}(AbstractChosen)}).call(this); -------------------------------------------------------------------------------- /examples/javascripts/chosen/chosen.min.css: -------------------------------------------------------------------------------- 1 | /* Chosen v1.4.1 | (c) 2011-2015 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ 2 | 3 | .chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;zoom:1;*display:inline;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chosen-container *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.chosen-container .chosen-drop{position:absolute;top:100%;left:-9999px;z-index:1010;width:100%;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15)}.chosen-container.chosen-with-drop .chosen-drop{left:0}.chosen-container a{cursor:pointer}.chosen-container .search-choice .group-name,.chosen-container .chosen-single .group-name{margin-right:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-weight:400;color:#999}.chosen-container .search-choice .group-name:after,.chosen-container .chosen-single .group-name:after{content:":";padding-left:2px;vertical-align:top}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:25px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),color-stop(100%,#f4f4f4));background:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:#fff url(chosen-sprite.png) no-repeat 100% -20px;background:url(chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{color:#444;position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;word-wrap:break-word;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:-webkit-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-moz-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-o-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{color:#777;display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;margin:0;padding:0 5px;width:100%;height:auto!important;height:1%;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(1%,#eee),color-stop(15%,#fff));background-image:-webkit-linear-gradient(#eee 1%,#fff 15%);background-image:-moz-linear-gradient(#eee 1%,#fff 15%);background-image:-o-linear-gradient(#eee 1%,#fff 15%);background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:0;height:25px;outline:0;border:0!important;background:transparent!important;box-shadow:none;color:#999;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 5px 3px 0;padding:3px 20px 3px 5px;border:1px solid #aaa;max-width:100%;border-radius:3px;background-color:#eee;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-size:100% 19px;background-repeat:repeat-x;background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice span{word-wrap:break-word}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#eee),color-stop(80%,#fff));background-image:-webkit-linear-gradient(#eee 20%,#fff 80%);background-image:-moz-linear-gradient(#eee 20%,#fff 80%);background-image:-o-linear-gradient(#eee 20%,#fff 80%);background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:0;background:transparent}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#222!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single-nosearch .chosen-search,.chosen-rtl .chosen-drop{left:9999px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:0}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:#fff url(chosen-sprite.png) no-repeat -30px -20px;background:url(chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:144dpi),only screen and (min-resolution:1.5dppx){.chosen-rtl .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-container-single .chosen-search input[type=text],.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span{background-image:url(chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}} -------------------------------------------------------------------------------- /examples/javascripts/chosen/chosen.proto.min.js: -------------------------------------------------------------------------------- 1 | /* Chosen v1.4.1 | (c) 2011-2015 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ 2 | (function(){var AbstractChosen,SelectParser,a,b={}.hasOwnProperty,c=function(a,c){function d(){this.constructor=a}for(var e in c)b.call(c,e)&&(a[e]=c[e]);return d.prototype=c.prototype,a.prototype=new d,a.__super__=c.prototype,a};SelectParser=function(){function SelectParser(){this.options_index=0,this.parsed=[]}return SelectParser.prototype.add_node=function(a){return"OPTGROUP"===a.nodeName.toUpperCase()?this.add_group(a):this.add_option(a)},SelectParser.prototype.add_group=function(a){var b,c,d,e,f,g;for(b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:this.escapeExpression(a.label),title:a.title?a.title:void 0,children:0,disabled:a.disabled,classes:a.className}),f=a.childNodes,g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(this.add_option(c,b,a.disabled));return g},SelectParser.prototype.add_option=function(a,b,c){return"OPTION"===a.nodeName.toUpperCase()?(""!==a.text?(null!=b&&(this.parsed[b].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:a.value,text:a.text,html:a.innerHTML,title:a.title?a.title:void 0,selected:a.selected,disabled:c===!0?c:a.disabled,group_array_index:b,group_label:null!=b?this.parsed[b].label:null,classes:a.className,style:a.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1):void 0},SelectParser.prototype.escapeExpression=function(a){var b,c;return null==a||a===!1?"":/[\&\<\>\"\'\`]/.test(a)?(b={"<":"<",">":">",'"':""","'":"'","`":"`"},c=/&(?!\w+;)|[\<\>\"\'\`]/g,a.replace(c,function(a){return b[a]||"&"})):a},SelectParser}(),SelectParser.select_to_array=function(a){var b,c,d,e,f;for(c=new SelectParser,f=a.childNodes,d=0,e=f.length;e>d;d++)b=f[d],c.add_node(b);return c.parsed},AbstractChosen=function(){function AbstractChosen(a,b){this.form_field=a,this.options=null!=b?b:{},AbstractChosen.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers(),this.on_ready())}return AbstractChosen.prototype.set_default_values=function(){var a=this;return this.click_test_action=function(b){return a.test_active_click(b)},this.activate_action=function(b){return a.activate_field(b)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null!=this.options.enable_split_word_search?this.options.enable_split_word_search:!0,this.group_search=null!=this.options.group_search?this.options.group_search:!0,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null!=this.options.single_backstroke_delete?this.options.single_backstroke_delete:!0,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null!=this.options.display_selected_options?this.options.display_selected_options:!0,this.display_disabled_options=null!=this.options.display_disabled_options?this.options.display_disabled_options:!0,this.include_group_label_in_selected=this.options.include_group_label_in_selected||!1},AbstractChosen.prototype.set_default_text=function(){return this.default_text=this.form_field.getAttribute("data-placeholder")?this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.options.placeholder_text_multiple||this.options.placeholder_text||AbstractChosen.default_multiple_text:this.options.placeholder_text_single||this.options.placeholder_text||AbstractChosen.default_single_text,this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||AbstractChosen.default_no_result_text},AbstractChosen.prototype.choice_label=function(a){return this.include_group_label_in_selected&&null!=a.group_label?""+a.group_label+""+a.html:a.html},AbstractChosen.prototype.mouse_enter=function(){return this.mouse_on_container=!0},AbstractChosen.prototype.mouse_leave=function(){return this.mouse_on_container=!1},AbstractChosen.prototype.input_focus=function(){var a=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return a.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},AbstractChosen.prototype.input_blur=function(){var a=this;return this.mouse_on_container?void 0:(this.active_field=!1,setTimeout(function(){return a.blur_test()},100))},AbstractChosen.prototype.results_option_build=function(a){var b,c,d,e,f;for(b="",f=this.results_data,d=0,e=f.length;e>d;d++)c=f[d],b+=c.group?this.result_add_group(c):this.result_add_option(c),(null!=a?a.first:void 0)&&(c.selected&&this.is_multiple?this.choice_build(c):c.selected&&!this.is_multiple&&this.single_set_selected_text(this.choice_label(c)));return b},AbstractChosen.prototype.result_add_option=function(a){var b,c;return a.search_match?this.include_option_in_results(a)?(b=[],a.disabled||a.selected&&this.is_multiple||b.push("active-result"),!a.disabled||a.selected&&this.is_multiple||b.push("disabled-result"),a.selected&&b.push("result-selected"),null!=a.group_array_index&&b.push("group-option"),""!==a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.style.cssText=a.style,c.setAttribute("data-option-array-index",a.array_index),c.innerHTML=a.search_text,a.title&&(c.title=a.title),this.outerHTML(c)):"":""},AbstractChosen.prototype.result_add_group=function(a){var b,c;return a.search_match||a.group_match?a.active_options>0?(b=[],b.push("group-result"),a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.innerHTML=a.search_text,a.title&&(c.title=a.title),this.outerHTML(c)):"":""},AbstractChosen.prototype.results_update_field=function(){return this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing?this.winnow_results():void 0},AbstractChosen.prototype.reset_single_select_options=function(){var a,b,c,d,e;for(d=this.results_data,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.selected?e.push(a.selected=!1):e.push(void 0);return e},AbstractChosen.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},AbstractChosen.prototype.results_search=function(){return this.results_showing?this.winnow_results():this.results_show()},AbstractChosen.prototype.winnow_results=function(){var a,b,c,d,e,f,g,h,i,j,k,l;for(this.no_results_clear(),d=0,f=this.get_search_text(),a=f.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),i=new RegExp(a,"i"),c=this.get_search_regex(a),l=this.results_data,j=0,k=l.length;k>j;j++)b=l[j],b.search_match=!1,e=null,this.include_option_in_results(b)&&(b.group&&(b.group_match=!1,b.active_options=0),null!=b.group_array_index&&this.results_data[b.group_array_index]&&(e=this.results_data[b.group_array_index],0===e.active_options&&e.search_match&&(d+=1),e.active_options+=1),b.search_text=b.group?b.label:b.html,(!b.group||this.group_search)&&(b.search_match=this.search_string_match(b.search_text,c),b.search_match&&!b.group&&(d+=1),b.search_match?(f.length&&(g=b.search_text.search(i),h=b.search_text.substr(0,g+f.length)+""+b.search_text.substr(g+f.length),b.search_text=h.substr(0,g)+""+h.substr(g)),null!=e&&(e.group_match=!0)):null!=b.group_array_index&&this.results_data[b.group_array_index].search_match&&(b.search_match=!0)));return this.result_clear_highlight(),1>d&&f.length?(this.update_results_content(""),this.no_results(f)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},AbstractChosen.prototype.get_search_regex=function(a){var b;return b=this.search_contains?"":"^",new RegExp(b+a,"i")},AbstractChosen.prototype.search_string_match=function(a,b){var c,d,e,f;if(b.test(a))return!0;if(this.enable_split_word_search&&(a.indexOf(" ")>=0||0===a.indexOf("["))&&(d=a.replace(/\[|\]/g,"").split(" "),d.length))for(e=0,f=d.length;f>e;e++)if(c=d[e],b.test(c))return!0},AbstractChosen.prototype.choices_count=function(){var a,b,c,d;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,d=this.form_field.options,b=0,c=d.length;c>b;b++)a=d[b],a.selected&&(this.selected_option_count+=1);return this.selected_option_count},AbstractChosen.prototype.choices_click=function(a){return a.preventDefault(),this.results_showing||this.is_disabled?void 0:this.results_show()},AbstractChosen.prototype.keyup_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(a.preventDefault(),this.results_showing)return this.result_select(a);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},AbstractChosen.prototype.clipboard_event_checker=function(){var a=this;return setTimeout(function(){return a.results_search()},50)},AbstractChosen.prototype.container_width=function(){return null!=this.options.width?this.options.width:""+this.form_field.offsetWidth+"px"},AbstractChosen.prototype.include_option_in_results=function(a){return this.is_multiple&&!this.display_selected_options&&a.selected?!1:!this.display_disabled_options&&a.disabled?!1:a.empty?!1:!0},AbstractChosen.prototype.search_results_touchstart=function(a){return this.touch_started=!0,this.search_results_mouseover(a)},AbstractChosen.prototype.search_results_touchmove=function(a){return this.touch_started=!1,this.search_results_mouseout(a)},AbstractChosen.prototype.search_results_touchend=function(a){return this.touch_started?this.search_results_mouseup(a):void 0},AbstractChosen.prototype.outerHTML=function(a){var b;return a.outerHTML?a.outerHTML:(b=document.createElement("div"),b.appendChild(a),b.innerHTML)},AbstractChosen.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:/iP(od|hone)/i.test(window.navigator.userAgent)?!1:/Android/i.test(window.navigator.userAgent)&&/Mobile/i.test(window.navigator.userAgent)?!1:!0},AbstractChosen.default_multiple_text="Select Some Options",AbstractChosen.default_single_text="Select an Option",AbstractChosen.default_no_result_text="No results match",AbstractChosen}(),this.Chosen=function(b){function Chosen(){return a=Chosen.__super__.constructor.apply(this,arguments)}return c(Chosen,b),Chosen.prototype.setup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field.hasClassName("chosen-rtl")},Chosen.prototype.set_default_values=function(){return Chosen.__super__.set_default_values.call(this),this.single_temp=new Template('#{default}
          '),this.multi_temp=new Template('
            '),this.no_results_temp=new Template('
          • '+this.results_none_found+' "#{terms}"
          • ')},Chosen.prototype.set_up_html=function(){var a,b;return a=["chosen-container"],a.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&a.push(this.form_field.className),this.is_rtl&&a.push("chosen-rtl"),b={"class":a.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(b.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=this.is_multiple?new Element("div",b).update(this.multi_temp.evaluate({"default":this.default_text})):new Element("div",b).update(this.single_temp.evaluate({"default":this.default_text})),this.form_field.hide().insert({after:this.container}),this.dropdown=this.container.down("div.chosen-drop"),this.search_field=this.container.down("input"),this.search_results=this.container.down("ul.chosen-results"),this.search_field_scale(),this.search_no_results=this.container.down("li.no-results"),this.is_multiple?(this.search_choices=this.container.down("ul.chosen-choices"),this.search_container=this.container.down("li.search-field")):(this.search_container=this.container.down("div.chosen-search"),this.selected_item=this.container.down(".chosen-single")),this.results_build(),this.set_tab_index(),this.set_label_behavior()},Chosen.prototype.on_ready=function(){return this.form_field.fire("chosen:ready",{chosen:this})},Chosen.prototype.register_observers=function(){var a=this;return this.container.observe("touchstart",function(b){return a.container_mousedown(b),b.preventDefault()}),this.container.observe("touchend",function(b){return a.container_mouseup(b),b.preventDefault()}),this.container.observe("mousedown",function(b){return a.container_mousedown(b)}),this.container.observe("mouseup",function(b){return a.container_mouseup(b)}),this.container.observe("mouseenter",function(b){return a.mouse_enter(b)}),this.container.observe("mouseleave",function(b){return a.mouse_leave(b)}),this.search_results.observe("mouseup",function(b){return a.search_results_mouseup(b)}),this.search_results.observe("mouseover",function(b){return a.search_results_mouseover(b)}),this.search_results.observe("mouseout",function(b){return a.search_results_mouseout(b)}),this.search_results.observe("mousewheel",function(b){return a.search_results_mousewheel(b)}),this.search_results.observe("DOMMouseScroll",function(b){return a.search_results_mousewheel(b)}),this.search_results.observe("touchstart",function(b){return a.search_results_touchstart(b)}),this.search_results.observe("touchmove",function(b){return a.search_results_touchmove(b)}),this.search_results.observe("touchend",function(b){return a.search_results_touchend(b)}),this.form_field.observe("chosen:updated",function(b){return a.results_update_field(b)}),this.form_field.observe("chosen:activate",function(b){return a.activate_field(b)}),this.form_field.observe("chosen:open",function(b){return a.container_mousedown(b)}),this.form_field.observe("chosen:close",function(b){return a.input_blur(b)}),this.search_field.observe("blur",function(b){return a.input_blur(b)}),this.search_field.observe("keyup",function(b){return a.keyup_checker(b)}),this.search_field.observe("keydown",function(b){return a.keydown_checker(b)}),this.search_field.observe("focus",function(b){return a.input_focus(b)}),this.search_field.observe("cut",function(b){return a.clipboard_event_checker(b)}),this.search_field.observe("paste",function(b){return a.clipboard_event_checker(b)}),this.is_multiple?this.search_choices.observe("click",function(b){return a.choices_click(b)}):this.container.observe("click",function(a){return a.preventDefault()})},Chosen.prototype.destroy=function(){return this.container.ownerDocument.stopObserving("click",this.click_test_action),this.form_field.stopObserving(),this.container.stopObserving(),this.search_results.stopObserving(),this.search_field.stopObserving(),null!=this.form_field_label&&this.form_field_label.stopObserving(),this.is_multiple?(this.search_choices.stopObserving(),this.container.select(".search-choice-close").each(function(a){return a.stopObserving()})):this.selected_item.stopObserving(),this.search_field.tabIndex&&(this.form_field.tabIndex=this.search_field.tabIndex),this.container.remove(),this.form_field.show()},Chosen.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field.disabled,this.is_disabled?(this.container.addClassName("chosen-disabled"),this.search_field.disabled=!0,this.is_multiple||this.selected_item.stopObserving("focus",this.activate_action),this.close_field()):(this.container.removeClassName("chosen-disabled"),this.search_field.disabled=!1,this.is_multiple?void 0:this.selected_item.observe("focus",this.activate_action))},Chosen.prototype.container_mousedown=function(a){return this.is_disabled||(a&&"mousedown"===a.type&&!this.results_showing&&a.stop(),null!=a&&a.target.hasClassName("search-choice-close"))?void 0:(this.active_field?this.is_multiple||!a||a.target!==this.selected_item&&!a.target.up("a.chosen-single")||this.results_toggle():(this.is_multiple&&this.search_field.clear(),this.container.ownerDocument.observe("click",this.click_test_action),this.results_show()),this.activate_field())},Chosen.prototype.container_mouseup=function(a){return"ABBR"!==a.target.nodeName||this.is_disabled?void 0:this.results_reset(a)},Chosen.prototype.search_results_mousewheel=function(a){var b;return b=a.deltaY||-a.wheelDelta||a.detail,null!=b?(a.preventDefault(),"DOMMouseScroll"===a.type&&(b=40*b),this.search_results.scrollTop=b+this.search_results.scrollTop):void 0},Chosen.prototype.blur_test=function(){return!this.active_field&&this.container.hasClassName("chosen-container-active")?this.close_field():void 0},Chosen.prototype.close_field=function(){return this.container.ownerDocument.stopObserving("click",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClassName("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},Chosen.prototype.activate_field=function(){return this.container.addClassName("chosen-container-active"),this.active_field=!0,this.search_field.value=this.search_field.value,this.search_field.focus()},Chosen.prototype.test_active_click=function(a){return a.target.up(".chosen-container")===this.container?this.active_field=!0:this.close_field()},Chosen.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=SelectParser.select_to_array(this.form_field),this.is_multiple?this.search_choices.select("li.search-choice").invoke("remove"):this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field.readOnly=!0,this.container.addClassName("chosen-container-single-nosearch")):(this.search_field.readOnly=!1,this.container.removeClassName("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},Chosen.prototype.result_do_highlight=function(a){var b,c,d,e,f;return this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClassName("highlighted"),d=parseInt(this.search_results.getStyle("maxHeight"),10),f=this.search_results.scrollTop,e=d+f,c=this.result_highlight.positionedOffset().top,b=c+this.result_highlight.getHeight(),b>=e?this.search_results.scrollTop=b-d>0?b-d:0:f>c?this.search_results.scrollTop=c:void 0},Chosen.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClassName("highlighted"),this.result_highlight=null},Chosen.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field.fire("chosen:maxselected",{chosen:this}),!1):(this.container.addClassName("chosen-with-drop"),this.results_showing=!0,this.search_field.focus(),this.search_field.value=this.search_field.value,this.winnow_results(),this.form_field.fire("chosen:showing_dropdown",{chosen:this}))},Chosen.prototype.update_results_content=function(a){return this.search_results.update(a)},Chosen.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClassName("chosen-with-drop"),this.form_field.fire("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},Chosen.prototype.set_tab_index=function(){var a;return this.form_field.tabIndex?(a=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field.tabIndex=a):void 0},Chosen.prototype.set_label_behavior=function(){var a=this;return this.form_field_label=this.form_field.up("label"),null==this.form_field_label&&(this.form_field_label=$$("label[for='"+this.form_field.id+"']").first()),null!=this.form_field_label?this.form_field_label.observe("click",function(b){return a.is_multiple?a.container_mousedown(b):a.activate_field()}):void 0},Chosen.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.value=this.default_text,this.search_field.addClassName("default")):(this.search_field.value="",this.search_field.removeClassName("default"))},Chosen.prototype.search_results_mouseup=function(a){var b;return b=a.target.hasClassName("active-result")?a.target:a.target.up(".active-result"),b?(this.result_highlight=b,this.result_select(a),this.search_field.focus()):void 0},Chosen.prototype.search_results_mouseover=function(a){var b;return b=a.target.hasClassName("active-result")?a.target:a.target.up(".active-result"),b?this.result_do_highlight(b):void 0},Chosen.prototype.search_results_mouseout=function(a){return a.target.hasClassName("active-result")||a.target.up(".active-result")?this.result_clear_highlight():void 0},Chosen.prototype.choice_build=function(a){var b,c,d=this;return b=new Element("li",{"class":"search-choice"}).update(""+this.choice_label(a)+""),a.disabled?b.addClassName("search-choice-disabled"):(c=new Element("a",{href:"#","class":"search-choice-close",rel:a.array_index}),c.observe("click",function(a){return d.choice_destroy_link_click(a)}),b.insert(c)),this.search_container.insert({before:b})},Chosen.prototype.choice_destroy_link_click=function(a){return a.preventDefault(),a.stopPropagation(),this.is_disabled?void 0:this.choice_destroy(a.target)},Chosen.prototype.choice_destroy=function(a){return this.result_deselect(a.readAttribute("rel"))?(this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.value.length<1&&this.results_hide(),a.up("li").remove(),this.search_field_scale()):void 0},Chosen.prototype.results_reset=function(){return this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),"function"==typeof Event.simulate&&this.form_field.simulate("change"),this.active_field?this.results_hide():void 0},Chosen.prototype.results_reset_cleanup=function(){var a;return this.current_selectedIndex=this.form_field.selectedIndex,a=this.selected_item.down("abbr"),a?a.remove():void 0},Chosen.prototype.result_select=function(a){var b,c;return this.result_highlight?(b=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field.fire("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?b.removeClassName("active-result"):this.reset_single_select_options(),b.addClassName("result-selected"),c=this.results_data[b.getAttribute("data-option-array-index")],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(c):this.single_set_selected_text(this.choice_label(c)),(a.metaKey||a.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.value="","function"!=typeof Event.simulate||!this.is_multiple&&this.form_field.selectedIndex===this.current_selectedIndex||this.form_field.simulate("change"),this.current_selectedIndex=this.form_field.selectedIndex,a.preventDefault(),this.search_field_scale())):void 0},Chosen.prototype.single_set_selected_text=function(a){return null==a&&(a=this.default_text),a===this.default_text?this.selected_item.addClassName("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClassName("chosen-default")),this.selected_item.down("span").update(a)},Chosen.prototype.result_deselect=function(a){var b;return b=this.results_data[a],this.form_field.options[b.options_index].disabled?!1:(b.selected=!1,this.form_field.options[b.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),"function"==typeof Event.simulate&&this.form_field.simulate("change"),this.search_field_scale(),!0)},Chosen.prototype.single_deselect_control_build=function(){return this.allow_single_deselect?(this.selected_item.down("abbr")||this.selected_item.down("span").insert({after:''}),this.selected_item.addClassName("chosen-single-with-deselect")):void 0},Chosen.prototype.get_search_text=function(){return this.search_field.value.strip().escapeHTML()},Chosen.prototype.winnow_results_set_highlight=function(){var a;return this.is_multiple||(a=this.search_results.down(".result-selected.active-result")),null==a&&(a=this.search_results.down(".active-result")),null!=a?this.result_do_highlight(a):void 0},Chosen.prototype.no_results=function(a){return this.search_results.insert(this.no_results_temp.evaluate({terms:a})),this.form_field.fire("chosen:no_results",{chosen:this})},Chosen.prototype.no_results_clear=function(){var a,b;for(a=null,b=[];a=this.search_results.down(".no-results");)b.push(a.remove());return b},Chosen.prototype.keydown_arrow=function(){var a;return this.results_showing&&this.result_highlight?(a=this.result_highlight.next(".active-result"))?this.result_do_highlight(a):void 0:this.results_show()},Chosen.prototype.keyup_arrow=function(){var a,b,c;return this.results_showing||this.is_multiple?this.result_highlight?(c=this.result_highlight.previousSiblings(),a=this.search_results.select("li.active-result"),b=c.intersect(a),b.length?this.result_do_highlight(b.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},Chosen.prototype.keydown_backstroke=function(){var a;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.down("a")),this.clear_backstroke()):(a=this.search_container.siblings().last(),a&&a.hasClassName("search-choice")&&!a.hasClassName("search-choice-disabled")?(this.pending_backstroke=a,this.pending_backstroke&&this.pending_backstroke.addClassName("search-choice-focus"),this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClassName("search-choice-focus")):void 0)},Chosen.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClassName("search-choice-focus"),this.pending_backstroke=null},Chosen.prototype.keydown_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),8!==b&&this.pending_backstroke&&this.clear_backstroke(),b){case 8:this.backstroke_length=this.search_field.value.length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:this.results_showing&&a.preventDefault();break;case 32:this.disable_search&&a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:a.preventDefault(),this.keydown_arrow()}},Chosen.prototype.search_field_scale=function(){var a,b,c,d,e,f,g,h,i;if(this.is_multiple){for(c=0,g=0,e="position:absolute; left: -1000px; top: -1000px; display:none;",f=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],h=0,i=f.length;i>h;h++)d=f[h],e+=d+":"+this.search_field.getStyle(d)+";";return a=new Element("div",{style:e}).update(this.search_field.value.escapeHTML()),document.body.appendChild(a),g=Element.measure(a,"width")+25,a.remove(),b=this.container.getWidth(),g>b-10&&(g=b-10),this.search_field.setStyle({width:g+"px"})}},Chosen}(AbstractChosen)}).call(this); -------------------------------------------------------------------------------- /examples/javascripts/jquery.sortable.js: -------------------------------------------------------------------------------- 1 | /* =================================================== 2 | * jquery-sortable.js v0.9.12 3 | * http://johnny.github.com/jquery-sortable/ 4 | * =================================================== 5 | * Copyright (c) 2012 Jonas von Andrian 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * ========================================================== */ 29 | 30 | 31 | !function ( $, window, pluginName, undefined){ 32 | var eventNames, 33 | containerDefaults = { 34 | // If true, items can be dragged from this container 35 | drag: true, 36 | // If true, items can be droped onto this container 37 | drop: true, 38 | // Exclude items from being draggable, if the 39 | // selector matches the item 40 | exclude: "", 41 | // If true, search for nested containers within an item 42 | nested: true, 43 | // If true, the items are assumed to be arranged vertically 44 | vertical: true 45 | }, // end container defaults 46 | groupDefaults = { 47 | // This is executed after the placeholder has been moved. 48 | // $closestItemOrContainer contains the closest item, the placeholder 49 | // has been put at or the closest empty Container, the placeholder has 50 | // been appended to. 51 | afterMove: function ($placeholder, container, $closestItemOrContainer) { 52 | }, 53 | // The exact css path between the container and its items, e.g. "> tbody" 54 | containerPath: "", 55 | // The css selector of the containers 56 | containerSelector: "ol, ul", 57 | // Distance the mouse has to travel to start dragging 58 | distance: 0, 59 | // Time in milliseconds after mousedown until dragging should start. 60 | // This option can be used to prevent unwanted drags when clicking on an element. 61 | delay: 0, 62 | // The css selector of the drag handle 63 | handle: "", 64 | // The exact css path between the item and its subcontainers 65 | itemPath: "", 66 | // The css selector of the items 67 | itemSelector: "li", 68 | // Check if the dragged item may be inside the container. 69 | // Use with care, since the search for a valid container entails a depth first search 70 | // and may be quite expensive. 71 | isValidTarget: function ($item, container) { 72 | return true 73 | }, 74 | // Executed before onDrop if placeholder is detached. 75 | // This happens if pullPlaceholder is set to false and the drop occurs outside a container. 76 | onCancel: function ($item, container, _super, event) { 77 | }, 78 | // Executed at the beginning of a mouse move event. 79 | // The Placeholder has not been moved yet. 80 | onDrag: function ($item, position, _super, event) { 81 | $item.css(position) 82 | }, 83 | // Called after the drag has been started, 84 | // that is the mouse button is beeing held down and 85 | // the mouse is moving. 86 | // The container is the closest initialized container. 87 | // Therefore it might not be the container, that actually contains the item. 88 | onDragStart: function ($item, container, _super, event) { 89 | $item.css({ 90 | height: $item.height(), 91 | width: $item.width() 92 | }) 93 | $item.addClass("dragged") 94 | $("body").addClass("dragging") 95 | }, 96 | // Called when the mouse button is beeing released 97 | onDrop: function ($item, container, _super, event) { 98 | $item.removeClass("dragged").removeAttr("style") 99 | $("body").removeClass("dragging") 100 | }, 101 | // Called on mousedown. If falsy value is returned, the dragging will not start. 102 | // If clicked on input element, ignore 103 | onMousedown: function ($item, _super, event) { 104 | if (!event.target.nodeName.match(/^(input|select)$/i)) { 105 | event.preventDefault() 106 | return true 107 | } 108 | }, 109 | // Template for the placeholder. Can be any valid jQuery input 110 | // e.g. a string, a DOM element. 111 | // The placeholder must have the class "placeholder" 112 | placeholder: '
          • ', 113 | // If true, the position of the placeholder is calculated on every mousemove. 114 | // If false, it is only calculated when the mouse is above a container. 115 | pullPlaceholder: true, 116 | // Specifies serialization of the container group. 117 | // The pair $parent/$children is either container/items or item/subcontainers. 118 | serialize: function ($parent, $children, parentIsContainer) { 119 | var result = $.extend({}, $parent.data()) 120 | 121 | if(parentIsContainer) 122 | return [$children] 123 | else if ($children[0]){ 124 | result.children = $children 125 | } 126 | 127 | delete result.subContainers 128 | delete result.sortable 129 | 130 | return result 131 | }, 132 | // Set tolerance while dragging. Positive values decrease sensitivity, 133 | // negative values increase it. 134 | tolerance: 0 135 | }, // end group defaults 136 | containerGroups = {}, 137 | groupCounter = 0, 138 | emptyBox = { 139 | left: 0, 140 | top: 0, 141 | bottom: 0, 142 | right:0 143 | }, 144 | eventNames = { 145 | start: "touchstart.sortable mousedown.sortable", 146 | drop: "touchend.sortable touchcancel.sortable mouseup.sortable", 147 | drag: "touchmove.sortable mousemove.sortable", 148 | scroll: "scroll.sortable" 149 | }, 150 | subContainerKey = "subContainers" 151 | 152 | /* 153 | * a is Array [left, right, top, bottom] 154 | * b is array [left, top] 155 | */ 156 | function d(a,b) { 157 | var x = Math.max(0, a[0] - b[0], b[0] - a[1]), 158 | y = Math.max(0, a[2] - b[1], b[1] - a[3]) 159 | return x+y; 160 | } 161 | 162 | function setDimensions(array, dimensions, tolerance, useOffset) { 163 | var i = array.length, 164 | offsetMethod = useOffset ? "offset" : "position" 165 | tolerance = tolerance || 0 166 | 167 | while(i--){ 168 | var el = array[i].el ? array[i].el : $(array[i]), 169 | // use fitting method 170 | pos = el[offsetMethod]() 171 | pos.left += parseInt(el.css('margin-left'), 10) 172 | pos.top += parseInt(el.css('margin-top'),10) 173 | dimensions[i] = [ 174 | pos.left - tolerance, 175 | pos.left + el.outerWidth() + tolerance, 176 | pos.top - tolerance, 177 | pos.top + el.outerHeight() + tolerance 178 | ] 179 | } 180 | } 181 | 182 | function getRelativePosition(pointer, element) { 183 | var offset = element.offset() 184 | return { 185 | left: pointer.left - offset.left, 186 | top: pointer.top - offset.top 187 | } 188 | } 189 | 190 | function sortByDistanceDesc(dimensions, pointer, lastPointer) { 191 | pointer = [pointer.left, pointer.top] 192 | lastPointer = lastPointer && [lastPointer.left, lastPointer.top] 193 | 194 | var dim, 195 | i = dimensions.length, 196 | distances = [] 197 | 198 | while(i--){ 199 | dim = dimensions[i] 200 | distances[i] = [i,d(dim,pointer), lastPointer && d(dim, lastPointer)] 201 | } 202 | distances = distances.sort(function (a,b) { 203 | return b[1] - a[1] || b[2] - a[2] || b[0] - a[0] 204 | }) 205 | 206 | // last entry is the closest 207 | return distances 208 | } 209 | 210 | function ContainerGroup(options) { 211 | this.options = $.extend({}, groupDefaults, options) 212 | this.containers = [] 213 | 214 | if(!this.options.rootGroup){ 215 | this.scrollProxy = $.proxy(this.scroll, this) 216 | this.dragProxy = $.proxy(this.drag, this) 217 | this.dropProxy = $.proxy(this.drop, this) 218 | this.placeholder = $(this.options.placeholder) 219 | 220 | if(!options.isValidTarget) 221 | this.options.isValidTarget = undefined 222 | } 223 | } 224 | 225 | ContainerGroup.get = function (options) { 226 | if(!containerGroups[options.group]) { 227 | if(options.group === undefined) 228 | options.group = groupCounter ++ 229 | 230 | containerGroups[options.group] = new ContainerGroup(options) 231 | } 232 | 233 | return containerGroups[options.group] 234 | } 235 | 236 | ContainerGroup.prototype = { 237 | dragInit: function (e, itemContainer) { 238 | this.$document = $(itemContainer.el[0].ownerDocument) 239 | 240 | // get item to drag 241 | this.item = $(e.target).closest(this.options.itemSelector) 242 | this.itemContainer = itemContainer 243 | 244 | if(this.item.is(this.options.exclude) || 245 | !this.options.onMousedown(this.item, groupDefaults.onMousedown, e)){ 246 | return 247 | } 248 | 249 | this.setPointer(e) 250 | this.toggleListeners('on') 251 | 252 | this.setupDelayTimer() 253 | this.dragInitDone = true 254 | }, 255 | drag: function (e) { 256 | if(!this.dragging){ 257 | if(!this.distanceMet(e) || !this.delayMet) 258 | return 259 | 260 | this.options.onDragStart(this.item, this.itemContainer, groupDefaults.onDragStart, e) 261 | this.item.before(this.placeholder) 262 | this.dragging = true 263 | } 264 | 265 | this.setPointer(e) 266 | // place item under the cursor 267 | this.options.onDrag(this.item, 268 | getRelativePosition(this.pointer, this.item.offsetParent()), 269 | groupDefaults.onDrag, 270 | e) 271 | 272 | var x = e.pageX || e.originalEvent.pageX, 273 | y = e.pageY || e.originalEvent.pageY, 274 | box = this.sameResultBox, 275 | t = this.options.tolerance 276 | 277 | if(!box || box.top - t > y || box.bottom + t < y || box.left - t > x || box.right + t < x) 278 | if(!this.searchValidTarget()) 279 | this.placeholder.detach() 280 | }, 281 | drop: function (e) { 282 | this.toggleListeners('off') 283 | 284 | this.dragInitDone = false 285 | 286 | if(this.dragging){ 287 | // processing Drop, check if placeholder is detached 288 | if(this.placeholder.closest("html")[0]) 289 | this.placeholder.before(this.item).detach() 290 | else 291 | this.options.onCancel(this.item, this.itemContainer, groupDefaults.onCancel, e) 292 | 293 | this.options.onDrop(this.item, this.getContainer(this.item), groupDefaults.onDrop, e) 294 | 295 | // cleanup 296 | this.clearDimensions() 297 | this.clearOffsetParent() 298 | this.lastAppendedItem = this.sameResultBox = undefined 299 | this.dragging = false 300 | } 301 | }, 302 | searchValidTarget: function (pointer, lastPointer) { 303 | if(!pointer){ 304 | pointer = this.relativePointer || this.pointer 305 | lastPointer = this.lastRelativePointer || this.lastPointer 306 | } 307 | 308 | var distances = sortByDistanceDesc(this.getContainerDimensions(), 309 | pointer, 310 | lastPointer), 311 | i = distances.length 312 | 313 | while(i--){ 314 | var index = distances[i][0], 315 | distance = distances[i][1] 316 | 317 | if(!distance || this.options.pullPlaceholder){ 318 | var container = this.containers[index] 319 | if(!container.disabled){ 320 | if(!this.$getOffsetParent()){ 321 | var offsetParent = container.getItemOffsetParent() 322 | pointer = getRelativePosition(pointer, offsetParent) 323 | lastPointer = getRelativePosition(lastPointer, offsetParent) 324 | } 325 | if(container.searchValidTarget(pointer, lastPointer)) 326 | return true 327 | } 328 | } 329 | } 330 | if(this.sameResultBox) 331 | this.sameResultBox = undefined 332 | }, 333 | movePlaceholder: function (container, item, method, sameResultBox) { 334 | var lastAppendedItem = this.lastAppendedItem 335 | if(!sameResultBox && lastAppendedItem && lastAppendedItem[0] === item[0]) 336 | return; 337 | 338 | item[method](this.placeholder) 339 | this.lastAppendedItem = item 340 | this.sameResultBox = sameResultBox 341 | this.options.afterMove(this.placeholder, container, item) 342 | }, 343 | getContainerDimensions: function () { 344 | if(!this.containerDimensions) 345 | setDimensions(this.containers, this.containerDimensions = [], this.options.tolerance, !this.$getOffsetParent()) 346 | return this.containerDimensions 347 | }, 348 | getContainer: function (element) { 349 | return element.closest(this.options.containerSelector).data(pluginName) 350 | }, 351 | $getOffsetParent: function () { 352 | if(this.offsetParent === undefined){ 353 | var i = this.containers.length - 1, 354 | offsetParent = this.containers[i].getItemOffsetParent() 355 | 356 | if(!this.options.rootGroup){ 357 | while(i--){ 358 | if(offsetParent[0] != this.containers[i].getItemOffsetParent()[0]){ 359 | // If every container has the same offset parent, 360 | // use position() which is relative to this parent, 361 | // otherwise use offset() 362 | // compare #setDimensions 363 | offsetParent = false 364 | break; 365 | } 366 | } 367 | } 368 | 369 | this.offsetParent = offsetParent 370 | } 371 | return this.offsetParent 372 | }, 373 | setPointer: function (e) { 374 | var pointer = this.getPointer(e) 375 | 376 | if(this.$getOffsetParent()){ 377 | var relativePointer = getRelativePosition(pointer, this.$getOffsetParent()) 378 | this.lastRelativePointer = this.relativePointer 379 | this.relativePointer = relativePointer 380 | } 381 | 382 | this.lastPointer = this.pointer 383 | this.pointer = pointer 384 | }, 385 | distanceMet: function (e) { 386 | var currentPointer = this.getPointer(e) 387 | return (Math.max( 388 | Math.abs(this.pointer.left - currentPointer.left), 389 | Math.abs(this.pointer.top - currentPointer.top) 390 | ) >= this.options.distance) 391 | }, 392 | getPointer: function(e) { 393 | return { 394 | left: e.pageX || e.originalEvent.pageX, 395 | top: e.pageY || e.originalEvent.pageY 396 | } 397 | }, 398 | setupDelayTimer: function () { 399 | var that = this 400 | this.delayMet = !this.options.delay 401 | 402 | // init delay timer if needed 403 | if (!this.delayMet) { 404 | clearTimeout(this._mouseDelayTimer); 405 | this._mouseDelayTimer = setTimeout(function() { 406 | that.delayMet = true 407 | }, this.options.delay) 408 | } 409 | }, 410 | scroll: function (e) { 411 | this.clearDimensions() 412 | this.clearOffsetParent() // TODO is this needed? 413 | }, 414 | toggleListeners: function (method) { 415 | var that = this, 416 | events = ['drag','drop','scroll'] 417 | 418 | $.each(events,function (i,event) { 419 | that.$document[method](eventNames[event], that[event + 'Proxy']) 420 | }) 421 | }, 422 | clearOffsetParent: function () { 423 | this.offsetParent = undefined 424 | }, 425 | // Recursively clear container and item dimensions 426 | clearDimensions: function () { 427 | this.traverse(function(object){ 428 | object._clearDimensions() 429 | }) 430 | }, 431 | traverse: function(callback) { 432 | callback(this) 433 | var i = this.containers.length 434 | while(i--){ 435 | this.containers[i].traverse(callback) 436 | } 437 | }, 438 | _clearDimensions: function(){ 439 | this.containerDimensions = undefined 440 | }, 441 | _destroy: function () { 442 | containerGroups[this.options.group] = undefined 443 | } 444 | } 445 | 446 | function Container(element, options) { 447 | this.el = element 448 | this.options = $.extend( {}, containerDefaults, options) 449 | 450 | this.group = ContainerGroup.get(this.options) 451 | this.rootGroup = this.options.rootGroup || this.group 452 | this.handle = this.rootGroup.options.handle || this.rootGroup.options.itemSelector 453 | 454 | var itemPath = this.rootGroup.options.itemPath 455 | this.target = itemPath ? this.el.find(itemPath) : this.el 456 | 457 | this.target.on(eventNames.start, this.handle, $.proxy(this.dragInit, this)) 458 | 459 | if(this.options.drop) 460 | this.group.containers.push(this) 461 | } 462 | 463 | Container.prototype = { 464 | dragInit: function (e) { 465 | var rootGroup = this.rootGroup 466 | 467 | if( !this.disabled && 468 | !rootGroup.dragInitDone && 469 | this.options.drag && 470 | this.isValidDrag(e)) { 471 | rootGroup.dragInit(e, this) 472 | } 473 | }, 474 | isValidDrag: function(e) { 475 | return e.which == 1 || 476 | e.type == "touchstart" && e.originalEvent.touches.length == 1 477 | }, 478 | searchValidTarget: function (pointer, lastPointer) { 479 | var distances = sortByDistanceDesc(this.getItemDimensions(), 480 | pointer, 481 | lastPointer), 482 | i = distances.length, 483 | rootGroup = this.rootGroup, 484 | validTarget = !rootGroup.options.isValidTarget || 485 | rootGroup.options.isValidTarget(rootGroup.item, this) 486 | 487 | if(!i && validTarget){ 488 | rootGroup.movePlaceholder(this, this.target, "append") 489 | return true 490 | } else 491 | while(i--){ 492 | var index = distances[i][0], 493 | distance = distances[i][1] 494 | if(!distance && this.hasChildGroup(index)){ 495 | var found = this.getContainerGroup(index).searchValidTarget(pointer, lastPointer) 496 | if(found) 497 | return true 498 | } 499 | else if(validTarget){ 500 | this.movePlaceholder(index, pointer) 501 | return true 502 | } 503 | } 504 | }, 505 | movePlaceholder: function (index, pointer) { 506 | var item = $(this.items[index]), 507 | dim = this.itemDimensions[index], 508 | method = "after", 509 | width = item.outerWidth(), 510 | height = item.outerHeight(), 511 | offset = item.offset(), 512 | sameResultBox = { 513 | left: offset.left, 514 | right: offset.left + width, 515 | top: offset.top, 516 | bottom: offset.top + height 517 | } 518 | if(this.options.vertical){ 519 | var yCenter = (dim[2] + dim[3]) / 2, 520 | inUpperHalf = pointer.top <= yCenter 521 | if(inUpperHalf){ 522 | method = "before" 523 | sameResultBox.bottom -= height / 2 524 | } else 525 | sameResultBox.top += height / 2 526 | } else { 527 | var xCenter = (dim[0] + dim[1]) / 2, 528 | inLeftHalf = pointer.left <= xCenter 529 | if(inLeftHalf){ 530 | method = "before" 531 | sameResultBox.right -= width / 2 532 | } else 533 | sameResultBox.left += width / 2 534 | } 535 | if(this.hasChildGroup(index)) 536 | sameResultBox = emptyBox 537 | this.rootGroup.movePlaceholder(this, item, method, sameResultBox) 538 | }, 539 | getItemDimensions: function () { 540 | if(!this.itemDimensions){ 541 | this.items = this.$getChildren(this.el, "item").filter(":not(.placeholder, .dragged)").get() 542 | setDimensions(this.items, this.itemDimensions = [], this.options.tolerance) 543 | } 544 | return this.itemDimensions 545 | }, 546 | getItemOffsetParent: function () { 547 | var offsetParent, 548 | el = this.el 549 | // Since el might be empty we have to check el itself and 550 | // can not do something like el.children().first().offsetParent() 551 | if(el.css("position") === "relative" || el.css("position") === "absolute" || el.css("position") === "fixed") 552 | offsetParent = el 553 | else 554 | offsetParent = el.offsetParent() 555 | return offsetParent 556 | }, 557 | hasChildGroup: function (index) { 558 | return this.options.nested && this.getContainerGroup(index) 559 | }, 560 | getContainerGroup: function (index) { 561 | var childGroup = $.data(this.items[index], subContainerKey) 562 | if( childGroup === undefined){ 563 | var childContainers = this.$getChildren(this.items[index], "container") 564 | childGroup = false 565 | 566 | if(childContainers[0]){ 567 | var options = $.extend({}, this.options, { 568 | rootGroup: this.rootGroup, 569 | group: groupCounter ++ 570 | }) 571 | childGroup = childContainers[pluginName](options).data(pluginName).group 572 | } 573 | $.data(this.items[index], subContainerKey, childGroup) 574 | } 575 | return childGroup 576 | }, 577 | $getChildren: function (parent, type) { 578 | var options = this.rootGroup.options, 579 | path = options[type + "Path"], 580 | selector = options[type + "Selector"] 581 | 582 | parent = $(parent) 583 | if(path) 584 | parent = parent.find(path) 585 | 586 | return parent.children(selector) 587 | }, 588 | _serialize: function (parent, isContainer) { 589 | var that = this, 590 | childType = isContainer ? "item" : "container", 591 | 592 | children = this.$getChildren(parent, childType).not(this.options.exclude).map(function () { 593 | return that._serialize($(this), !isContainer) 594 | }).get() 595 | 596 | return this.rootGroup.options.serialize(parent, children, isContainer) 597 | }, 598 | traverse: function(callback) { 599 | $.each(this.items || [], function(item){ 600 | var group = $.data(this, subContainerKey) 601 | if(group) 602 | group.traverse(callback) 603 | }); 604 | 605 | callback(this) 606 | }, 607 | _clearDimensions: function () { 608 | this.itemDimensions = undefined 609 | }, 610 | _destroy: function() { 611 | var that = this; 612 | 613 | this.target.off(eventNames.start, this.handle); 614 | this.el.removeData(pluginName) 615 | 616 | if(this.options.drop) 617 | this.group.containers = $.grep(this.group.containers, function(val){ 618 | return val != that 619 | }) 620 | 621 | $.each(this.items || [], function(){ 622 | $.removeData(this, subContainerKey) 623 | }) 624 | } 625 | } 626 | 627 | var API = { 628 | enable: function() { 629 | this.traverse(function(object){ 630 | object.disabled = false 631 | }) 632 | }, 633 | disable: function (){ 634 | this.traverse(function(object){ 635 | object.disabled = true 636 | }) 637 | }, 638 | serialize: function () { 639 | return this._serialize(this.el, true) 640 | }, 641 | refresh: function() { 642 | this.traverse(function(object){ 643 | object._clearDimensions() 644 | }) 645 | }, 646 | destroy: function () { 647 | this.traverse(function(object){ 648 | object._destroy(); 649 | }) 650 | } 651 | } 652 | 653 | $.extend(Container.prototype, API) 654 | 655 | /** 656 | * jQuery API 657 | * 658 | * Parameters are 659 | * either options on init 660 | * or a method name followed by arguments to pass to the method 661 | */ 662 | $.fn[pluginName] = function(methodOrOptions) { 663 | var args = Array.prototype.slice.call(arguments, 1) 664 | 665 | return this.map(function(){ 666 | var $t = $(this), 667 | object = $t.data(pluginName) 668 | 669 | if(object && API[methodOrOptions]) 670 | return API[methodOrOptions].apply(object, args) || this 671 | else if(!object && (methodOrOptions === undefined || 672 | typeof methodOrOptions === "object")) 673 | $t.data(pluginName, new Container($t, methodOrOptions)) 674 | 675 | return this 676 | }); 677 | }; 678 | 679 | }(jQuery, window, 'sortable'); -------------------------------------------------------------------------------- /examples/select.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSON Form test 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 |

            JSON Form test

            24 | 25 | 30 | 31 | 55 | 56 | -------------------------------------------------------------------------------- /examples/selectajax.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSON Form test 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 |

            JSON Form test

            24 | 25 | 42 | 43 | 110 | 111 | -------------------------------------------------------------------------------- /examples/sortable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSON Form test 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 |

            JSON Form test

            25 | 26 | 34 | 35 | 61 | 62 | -------------------------------------------------------------------------------- /examples/string.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSON Form test 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 |

            JSON Form test

            24 | 25 | 30 | 31 | 53 | 54 | -------------------------------------------------------------------------------- /gulpfile.coffee: -------------------------------------------------------------------------------- 1 | gulp = require("gulp") 2 | connect = require("gulp-connect") 3 | sass = require("gulp-sass") 4 | coffee = require("gulp-coffee") 5 | include = require("gulp-include") 6 | gulpMerge = require('gulp-merge') 7 | jstConcat = require('gulp-jst-concat') 8 | concat = require('gulp-concat') 9 | _ = require("underscore") 10 | 11 | gulp.task "build", -> 12 | 13 | # JS and JST 14 | gulpMerge( 15 | gulp.src("src/jsonform.coffee") 16 | .pipe(include()) 17 | .pipe(coffee({bare: true})) 18 | , 19 | gulp.src('src/fields/*.jst') 20 | .pipe(jstConcat('jst.js', { 21 | renameKeys: ['^.*src/(.*).jst$', '$1'] 22 | })) 23 | ).pipe(concat('jsonform.js')) 24 | .pipe(gulp.dest("dist")) 25 | .pipe(gulp.dest("test")) 26 | 27 | # CSS 28 | gulp.src("src/jsonform.scss") 29 | .pipe(sass()) 30 | .pipe(gulp.dest("dist")) 31 | .pipe(gulp.dest("test")) 32 | 33 | 34 | gulp.task "server", ["build"], -> 35 | connect.server 36 | port: 8002 37 | fallback: 'examples/index.html' 38 | gulp.watch(['src/**/*.coffee', 'src/**/*.jst', 'src/**/*.scss'], ['build']) -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | require('coffee-script/register'); 2 | require('./gulpfile.coffee'); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonform", 3 | "repository": { 4 | "type": "git", 5 | "url": "git://github.com/oreillymedia/jsonform" 6 | }, 7 | "devDependencies": { 8 | "coffee-script": "^1.9.1", 9 | "gulp": "^3.8.6", 10 | "gulp-coffee": "^2.1.1", 11 | "gulp-sass": "^0.7.2", 12 | "gulp-connect": "^2.0.6", 13 | "gulp-include": "^1.1.0", 14 | "gulp-merge": "^0.1.0", 15 | "gulp-jst-concat": "^0.0.1", 16 | "gulp-concat": "^2.5.2", 17 | "underscore": "^1.7.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/fields/ajax.coffee: -------------------------------------------------------------------------------- 1 | class jsonform.AjaxField 2 | 3 | @preloadValues: (config, vals, success) -> 4 | 5 | # remove null values 6 | vals = _.compact(vals) 7 | return if _.isEmpty(vals) 8 | 9 | query = {} 10 | query[config.jfReloadParam] = vals 11 | 12 | $.ajax( 13 | url: config.jfUrl 14 | data: query 15 | type: 'GET' 16 | success: (data) => 17 | success(config.jfParse(data, vals)) 18 | error: (data) -> 19 | console.log("error baby") 20 | ) 21 | 22 | constructor: (config) -> 23 | @config = config 24 | @tmpl = JST["fields/ajax"] 25 | @jel = $('
            ') 26 | @el = @jel[0] 27 | 28 | render: -> 29 | 30 | timeout = undefined 31 | 32 | @jel.html(@tmpl(@config)) 33 | @chosen = @jel.find(".chosen-select") 34 | .chosen( 35 | width:"300px" 36 | allow_single_deselect: true 37 | no_results_text: 'Searching for' 38 | ) 39 | @jel.find(".chosen-search input").on('input', (e) => 40 | clearTimeout(timeout) 41 | timeout = setTimeout(=> 42 | @loadAjax(e) 43 | , 800) 44 | ) 45 | 46 | @chosen.change(jsonform.helpers.changed) 47 | 48 | getValue: -> 49 | @jel.find(".chosen-select").val() 50 | 51 | clearValues: -> 52 | @jel.find("select option").remove() 53 | @jel.find("select").append("") 54 | @jel.find(".chosen-select").trigger("chosen:updated") 55 | 56 | setValue: (val) -> 57 | 58 | # if val is a primitive, we have to load the value to 59 | # use as label in the select box. This makes a HTTP request per 60 | # field, which is annoying for hundreds of fields. However, it 61 | # was too hard to implement for collections with nexted objects, so 62 | # that's how it is right now. 63 | if !_.isObject(val) 64 | @constructor.preloadValues(@config, [val], (newVal) => 65 | @setValue(newVal[0]) 66 | ) 67 | else 68 | @jel.find(".chosen-select").html('') 69 | @jel.find(".chosen-select").val(val[0]) 70 | @jel.find(".chosen-select").trigger("chosen:updated") 71 | jsonform.helpers.changed() 72 | 73 | loadAjax: (e) -> 74 | 75 | chosen = @jel.find(".chosen-container") 76 | 77 | query = {} 78 | searchVal = chosen.find(".chosen-search input").val() 79 | query[@config.jfSearchParam] = searchVal 80 | @clearValues() 81 | 82 | $.ajax( 83 | url: @config.jfUrl 84 | data: query 85 | type: 'GET' 86 | success: (data) => 87 | results = @config.jfParse(data) 88 | if results.length is 0 89 | chosen.find(".chosen-results").html("
          • No results matched \"#{searchVal}\"
          • ") 90 | else 91 | select = @jel.find(".chosen-select") 92 | _.each(results, (result) => 93 | select.append('') 94 | ) 95 | select.trigger("chosen:updated") 96 | chosen.find(".chosen-search input").val(searchVal) 97 | error: (data) -> 98 | console.log("error baby") 99 | ) 100 | 101 | -------------------------------------------------------------------------------- /src/fields/ajax.jst: -------------------------------------------------------------------------------- 1 | <% if(typeof(jfTitle)!== 'undefined') { %><%= jfTitle %><% } %> 2 | <% if(typeof(jfHelper)!== 'undefined') { %><%= jfHelper %><% } %> 3 | 4 | -------------------------------------------------------------------------------- /src/fields/ajax.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreillymedia/jsonform/7d38b902dd458587c7d149ee2dde5e28e899160a/src/fields/ajax.scss -------------------------------------------------------------------------------- /src/fields/boolean.coffee: -------------------------------------------------------------------------------- 1 | class jsonform.BooleanField 2 | 3 | constructor: (config) -> 4 | @config = config 5 | @tmpl = JST["fields/boolean"] 6 | @jel = $('
            ') 7 | @el = @jel[0] 8 | 9 | render: -> 10 | @jel.html(@tmpl(@config)) 11 | @jel.find(".chosen-select") 12 | .chosen({disable_search_threshold: 5, width:"300px"}) 13 | .change(jsonform.helpers.changed) 14 | 15 | getValue: -> 16 | @jel.find(".chosen-select").val() == "true" 17 | 18 | setValue: (val) -> 19 | @jel.find(".chosen-select").val(val + "") 20 | @jel.find(".chosen-select").trigger("chosen:updated") -------------------------------------------------------------------------------- /src/fields/boolean.jst: -------------------------------------------------------------------------------- 1 | <% if(typeof(jfTitle)!== 'undefined') { %><%= jfTitle %><% } %> 2 | <% if(typeof(jfHelper)!== 'undefined') { %><%= jfHelper %><% } %> 3 | 4 | -------------------------------------------------------------------------------- /src/fields/boolean.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreillymedia/jsonform/7d38b902dd458587c7d149ee2dde5e28e899160a/src/fields/boolean.scss -------------------------------------------------------------------------------- /src/fields/fieldcollection-del.jst: -------------------------------------------------------------------------------- 1 | Delete -------------------------------------------------------------------------------- /src/fields/fieldcollection-sort.jst: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/fields/fieldcollection.coffee: -------------------------------------------------------------------------------- 1 | class jsonform.FieldCollection 2 | 3 | constructor: (config) -> 4 | @config = config 5 | @tmpl = JST["fields/fieldcollection"] 6 | @jel = $("
            ") 7 | @el = @jel[0] 8 | 9 | # Array that itself holds an array of fields. This makes 10 | # the field collection work for a single field or a set of fields. 11 | @items = [] 12 | 13 | render: -> 14 | 15 | @jel.html(@tmpl(@config)) 16 | 17 | @jel.find(".jfAdd").click( (e) => 18 | return if $(this).is("[disabled]") 19 | e.preventDefault() 20 | @addItem() 21 | ) 22 | 23 | if $().sortable 24 | @jel.find(".jfCollection").sortable( 25 | placeholder: ' ' 26 | itemSelector: '.jfCollectionItem' 27 | handle: 'i.jfSort' 28 | onDrop: (item, container, _super) => 29 | _super(item, container) 30 | 31 | # sort by what number of child the el is 32 | @items = _.sortBy(@items, (item) -> item.jel.index()) 33 | 34 | jsonform.helpers.changed() 35 | ) 36 | 37 | getValues: -> 38 | results = _.map(@items, (item) -> item.getValue()) 39 | _.without(results, "", undefined, null) 40 | 41 | addItem: (jsonValue) -> 42 | 43 | item = new jsonform.FieldCollectionItem(@config, jsonValue) 44 | @jel.find(".jfCollection").append(item.el) 45 | item.render() 46 | @items.push(item) 47 | 48 | # listen for click on del 49 | item.jel.on("delete_clicked", (e, item) => 50 | item.jel.remove() 51 | @items = _.without(@items, item) 52 | @checkAddState() 53 | jsonform.helpers.changed() 54 | ) 55 | 56 | # check if we hide or show the add button 57 | @checkAddState() 58 | 59 | # update sortable 60 | if $().sortable 61 | @jel.find(".jfCollection").sortable("refresh") 62 | 63 | # call changed to update json 64 | jsonform.helpers.changed() 65 | 66 | itemsFromValues: (vals) -> 67 | _.each(vals, (val) => @addItem(val)) 68 | 69 | checkAddState: -> 70 | if @config.jfMax 71 | if @items.length >= @config.jfMax 72 | @jel.find(".jfAdd").attr("disabled", "disabled") 73 | else 74 | @jel.find(".jfAdd").removeAttr("disabled") 75 | -------------------------------------------------------------------------------- /src/fields/fieldcollection.jst: -------------------------------------------------------------------------------- 1 | <% if(typeof(jfTitle)!== 'undefined') { %><%= jfTitle %><% } %> 2 | <% if(typeof(jfHelper)!== 'undefined') { %><%= jfHelper %><% } %> 3 | 4 | + 5 | 6 |
            -------------------------------------------------------------------------------- /src/fields/fieldcollection.scss: -------------------------------------------------------------------------------- 1 | .jfCollectionItem { 2 | background-color: #FAFAFA; 3 | padding: 10px; 4 | border: 1px solid #C7C7C7; 5 | border-radius: 5px; 6 | margin-bottom: 5px; 7 | max-width: 400px; 8 | } 9 | 10 | .jfAdd { 11 | width: 30px; 12 | height: 30px; 13 | line-height: 30px; 14 | } 15 | 16 | .jfAdd[disabled] { 17 | opacity: 0.4; 18 | pointer-events: none; 19 | } 20 | 21 | a.jfDel { 22 | font-size: 14px; 23 | text-decoration: none; 24 | padding: 3px 5px; 25 | margin-top: 10px; 26 | margin-left: 5px; 27 | color: #DA7D7D; 28 | display: inline-block; 29 | background-color: #ECC8C8; 30 | } 31 | 32 | .jfSort { 33 | font-size: 14px; 34 | margin-top: 10px; 35 | margin-right: 5px; 36 | color: #565555; 37 | display: inline-block; 38 | background-color: #DBDBDB; 39 | text-align: center; 40 | padding: 3px 5px; 41 | vertical-align: top; 42 | border-radius: 3px; 43 | cursor: pointer; 44 | } 45 | 46 | // Draggable 47 | 48 | body.dragging, body.dragging * { 49 | cursor: move !important; 50 | } 51 | 52 | .dragged { 53 | position: absolute; 54 | opacity: 0.5; 55 | z-index: 2000; 56 | } 57 | 58 | div.jfCollection .placeholder { 59 | position: relative; 60 | margin: 0; 61 | padding: 0; 62 | border: none; 63 | &:before { 64 | position: absolute; 65 | content: ""; 66 | width: 0; 67 | height: 0; 68 | margin-top: -5px; 69 | left: -5px; 70 | top: -4px; 71 | border: 5px solid transparent; 72 | border-left-color: red; 73 | border-right: none; 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/fields/fieldcollectionitem.coffee: -------------------------------------------------------------------------------- 1 | class jsonform.FieldCollectionItem 2 | 3 | constructor: (config, jsonValue) -> 4 | 5 | @jsonValue = jsonValue 6 | @deltmpl = JST["fields/fieldcollection-del"] 7 | @sorttmpl = JST["fields/fieldcollection-sort"] 8 | @jel = $('
            ') 9 | @el = @jel[0] 10 | @fields = [] 11 | 12 | @config = {} 13 | jQuery.extend(true, @config, config) 14 | delete @config.jfTitle 15 | delete @config.jfHelper 16 | delete @config.jfCollection 17 | delete @config.jfMax 18 | 19 | # if there is a jfType on the root config object, 20 | # this will be a collection holding only single values: 21 | # [1, 2, 3, 4] 22 | if config.jfType 23 | @fields.push jsonform.helpers.newField(@config) 24 | 25 | # otherwise it will be a collection where each collection 26 | # item has a number of fields that become objects in the output: 27 | # [{..}, {..}, {..}] 28 | else 29 | _.each(@config, (v, k) => 30 | if v.jfType 31 | field = jsonform.helpers.newField(v) 32 | v.jfField = field 33 | @fields.push field 34 | ) 35 | 36 | render: -> 37 | 38 | @jel.html("") 39 | 40 | # first append all fields in this item, then render. 41 | # this makes is possible for them to instantiate chosen in render 42 | _.each(@fields, (field) => 43 | @jel.append(field.el) 44 | field.render() 45 | ) 46 | 47 | # if sortable, add sort handle 48 | if $().sortable 49 | @jel.append(@sorttmpl()) 50 | 51 | # delete button 52 | del = $(@deltmpl()) 53 | @jel.append(del) 54 | del.click( (e) => 55 | e.preventDefault() 56 | @jel.trigger("delete_clicked", @) 57 | ) 58 | 59 | # If we have values to set. 60 | if !_.isUndefined(@jsonValue) 61 | 62 | # if this is just a single field 63 | if @config.jfType 64 | @fields[0].setValue(@jsonValue) 65 | 66 | # otherwise loop through json values and 67 | # assign to fields. 68 | else 69 | _.each(@config, (v, k) => 70 | if v.jfField && @jsonValue[k] 71 | v.jfField.setValue(@jsonValue[k]) 72 | ) 73 | 74 | getValue: -> 75 | 76 | # if this is just a single field 77 | if @config.jfType 78 | @fields[0].getValue() 79 | 80 | # otherwise generate js object from the values. 81 | else 82 | values = {} 83 | jQuery.extend(true, values, @config) 84 | _.each(values, (v, k) => 85 | if v.jfField 86 | values[k] = v.jfField.getValue() 87 | ) 88 | values 89 | -------------------------------------------------------------------------------- /src/fields/fieldcollectionitem.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreillymedia/jsonform/7d38b902dd458587c7d149ee2dde5e28e899160a/src/fields/fieldcollectionitem.scss -------------------------------------------------------------------------------- /src/fields/select.coffee: -------------------------------------------------------------------------------- 1 | class jsonform.SelectField 2 | 3 | constructor: (config) -> 4 | @config = config 5 | @tmpl = JST["fields/select"] 6 | @jel = $('
            ') 7 | @el = @jel[0] 8 | 9 | render: -> 10 | @jel.html(@tmpl(@config)) 11 | @jel.find(".chosen-select") 12 | .chosen({disable_search_threshold: 5, width:"300px"}) 13 | .change(=> 14 | @jel.trigger("jf:changed") 15 | jsonform.helpers.changed() 16 | ) 17 | 18 | getValue: -> 19 | @jel.find(".chosen-select").val() 20 | 21 | setValue: (val) -> 22 | @jel.find(".chosen-select").val(val + "") 23 | @jel.find(".chosen-select").trigger("chosen:updated") -------------------------------------------------------------------------------- /src/fields/select.jst: -------------------------------------------------------------------------------- 1 | <% if(typeof(jfTitle)!== 'undefined') { %><%= jfTitle %><% } %> 2 | <% if(typeof(jfHelper)!== 'undefined') { %><%= jfHelper %><% } %> 3 | 4 | -------------------------------------------------------------------------------- /src/fields/selectajax.coffee: -------------------------------------------------------------------------------- 1 | class jsonform.SelectAjaxField 2 | 3 | constructor: (config) -> 4 | @config = config 5 | @jel = $('
            ') 6 | @el = @jel[0] 7 | @selectField = new jsonform.SelectField(jfValues: _.map(@config.jfValues, (val) -> val.jfValue)) 8 | @ajaxField = new jsonform.AjaxField(@config.jfValues[0]) 9 | 10 | render: -> 11 | @jel.html("") 12 | @jel.append(@selectField.el) 13 | @jel.append(@ajaxField.el) 14 | @selectField.render() 15 | @ajaxField.render() 16 | @selectField.jel.on("jf:changed", => @selectSwitched()) 17 | 18 | getValue: -> 19 | val = {} 20 | val[@config.jfSelectKey] = @selectField.getValue() 21 | val[@config.jfAjaxKey] = @ajaxField.getValue() 22 | val 23 | 24 | setValue: (val) -> 25 | @selectField.setValue(val[@config.jfSelectKey]) 26 | 27 | # find config based on selected key and load the 28 | # needed extra values using that config 29 | ajaxConfig = @getConfigBySelectKey(@selectField.getValue()) 30 | jsonform.AjaxField.preloadValues(ajaxConfig, [val[@config.jfAjaxKey]], (data) => 31 | @ajaxField.config = ajaxConfig 32 | @ajaxField.setValue(data[0]) 33 | ) 34 | 35 | selectSwitched: -> 36 | ajaxConfig = @getConfigBySelectKey(@selectField.getValue()) 37 | @ajaxField.config = ajaxConfig 38 | @ajaxField.setValue(["", ""]) 39 | 40 | getConfigBySelectKey: (key) -> 41 | _.find(@config.jfValues, (conf) -> 42 | conf.jfValue[0] is key 43 | ) -------------------------------------------------------------------------------- /src/fields/selectajax.jst: -------------------------------------------------------------------------------- 1 | <% if(typeof(jfTitle)!== 'undefined') { %><%= jfTitle %><% } %> 2 | <% if(typeof(jfHelper)!== 'undefined') { %><%= jfHelper %><% } %> 3 | 4 | -------------------------------------------------------------------------------- /src/fields/string.coffee: -------------------------------------------------------------------------------- 1 | class jsonform.StringField 2 | 3 | constructor: (config) -> 4 | @config = config 5 | @tmpl = JST["fields/string"] 6 | @jel = $('
            ') 7 | @el = @jel[0] 8 | 9 | render: -> 10 | @jel.html(@tmpl(@config)) 11 | @jel.find("input").change(jsonform.helpers.changed) 12 | 13 | getValue: -> 14 | @jel.find("input").val() 15 | 16 | setValue: (val) -> 17 | @jel.find("input").val(val) -------------------------------------------------------------------------------- /src/fields/string.jst: -------------------------------------------------------------------------------- 1 | <% if(typeof(jfTitle)!== 'undefined') { %><%= jfTitle %><% } %> 2 | <% if(typeof(jfHelper)!== 'undefined') { %><%= jfHelper %><% } %> 3 | 4 | -------------------------------------------------------------------------------- /src/fields/string.scss: -------------------------------------------------------------------------------- 1 | .jfField input[type="text"] { 2 | padding: 6px 10px; 3 | border: 1px solid #B0B0B0; 4 | border-radius: 5px; 5 | background-color: #F7F7F7; 6 | width: 300px; 7 | font-family: Helvetica, Arial, sans-serif; 8 | font-size: 13px; 9 | color: #444; 10 | outline: none; 11 | vertical-align: top; 12 | } -------------------------------------------------------------------------------- /src/jsonform.coffee: -------------------------------------------------------------------------------- 1 | window.jsonform = {} 2 | 3 | window.jsonform.helpers = { 4 | 5 | panic: (msg) -> 6 | console.error(msg) 7 | alert(msg) 8 | 9 | isJsonString: (str) -> 10 | try 11 | JSON.parse str 12 | catch e 13 | return false 14 | true 15 | 16 | changed: -> jQuery.event.trigger('jf:change'); 17 | 18 | newField : (jfObj) -> 19 | klass = jsonform[jfObj.jfType] 20 | if klass 21 | return new jsonform[jfObj.jfType](jfObj) 22 | else 23 | console.error "jsonform field doesnt exist: " + jfObj.jfType 24 | } 25 | 26 | #= require fields/*.coffee 27 | 28 | class jsonform.Form 29 | 30 | constructor: (txtArea, jsonConfig) -> 31 | 32 | @jel = $('
            ') 33 | @jtxt = $(txtArea) 34 | @jtxt.hide() 35 | 36 | @fields = [] 37 | @jsonConfig = jsonConfig 38 | @parseJsonConfig(@jsonConfig) 39 | 40 | # first append field elements so they are a part of the dom 41 | # this makes is possible for them to instantiate chosen in render 42 | _.each(@fields, (field) => 43 | @jel.append(field.el) 44 | field.render() 45 | ) 46 | 47 | # listen to global change events 48 | $(document).bind('jf:change', => 49 | json = @generateJson(@jsonConfig) 50 | @jtxt.val(JSON.stringify(json, null, 2)) 51 | ) 52 | 53 | @jtxt.after(@jel) 54 | 55 | # if textarea has data 56 | txtval = @jtxt.val() 57 | if !!txtval 58 | # if value is valid json 59 | if jsonform.helpers.isJsonString(txtval) 60 | @fillFields(JSON.parse(txtval), @jsonConfig) 61 | else 62 | jsonform.helpers.panic("Textarea has invalid JSON. jsonform will not work") 63 | 64 | # Recursive. 65 | generateJson: (obj) -> 66 | 67 | if _.isArray(obj) 68 | 69 | # if array has single item and it has jfCollection 70 | # get values form collection 71 | if obj.length == 1 && obj[0].jfCollection 72 | vals = obj[0].jfCollection.getValues() 73 | if obj[0].jfCollection.config.jfValueType is "int" 74 | vals = _.map(vals, (val) -> parseInt(val)) 75 | return vals 76 | else 77 | return _.map(obj, (v) => @generateJson(v)) 78 | else 79 | # if this object has a jfType 80 | if obj.jfField 81 | val = obj.jfField.getValue() 82 | if obj.jfField.config.jfValueType is "int" 83 | val = parseInt(val) 84 | val 85 | # else go deeper through the object. 86 | else 87 | # if this is an object, loop through and generate 88 | # json from all values in the object into new object 89 | if _.isObject(obj) 90 | newObj = {} 91 | _.each(obj, (v,k) => 92 | newObj[k] = @generateJson(v) 93 | ) 94 | return newObj 95 | # if not an object (string, number, etc), just return that 96 | else 97 | return obj 98 | 99 | # Recursive. 100 | parseJsonConfig: (obj) -> 101 | 102 | if _.isArray(obj) 103 | 104 | # if array has single item and it has jfCollection 105 | # convert it to a fieldcollection 106 | if obj.length == 1 && obj[0].jfCollection 107 | obj[0].jfCollection = new jsonform.FieldCollection(obj[0]) 108 | @fields.push(obj[0].jfCollection) 109 | 110 | # else parse each object in the array 111 | else 112 | _.each(obj, (v) => @parseJsonConfig(v)) 113 | 114 | else 115 | 116 | # if this object has a jfType, create this 117 | # type of field 118 | if obj.jfType 119 | obj.jfField = jsonform.helpers.newField(obj) 120 | @fields.push(obj.jfField) 121 | 122 | # else go deeper through the object. 123 | else 124 | _.each(obj, (v,k) => 125 | if _.isObject(v) 126 | @parseJsonConfig(v) 127 | ) 128 | 129 | # Recursive. This function takes an existing json object (that was generated with this library) 130 | # and loads the data into the fields. 131 | fillFields: (obj, jsonConfig) -> 132 | 133 | # basic sanity check to prevent most configuration errors 134 | if obj is undefined || jsonConfig is undefined 135 | jsonform.helpers.panic("Existing JSON doesnt match JSON config.") 136 | 137 | if _.isArray(obj) 138 | 139 | # if config has single item and it has jfCollection 140 | # create collection items with values. 141 | if jsonConfig.length == 1 && jsonConfig[0].jfCollection 142 | jsonConfig[0].jfCollection.itemsFromValues(obj) 143 | else 144 | _.each(obj, (v, i) => 145 | @fillFields(obj[i], jsonConfig[i]) 146 | ) 147 | else 148 | # if this object has a field, set value. 149 | if jsonConfig.jfField 150 | jsonConfig.jfField.setValue(obj) 151 | # else go deeper through the object. 152 | else 153 | # if this is an object, and the same object exist in the json config 154 | # loop through and fill fields inside those object values 155 | if _.isObject(obj) 156 | _.each(obj, (v,k) => 157 | if jsonConfig[k] 158 | @fillFields(v, jsonConfig[k]) 159 | else 160 | console.log "jsonConfig object not present:" 161 | console.log "key: ", k 162 | console.log "value: ", v 163 | ) -------------------------------------------------------------------------------- /src/jsonform.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, Arial, sans-serif; 3 | } 4 | 5 | // general styles for forms 6 | 7 | .jfForm { 8 | margin: 20px 0px; 9 | } 10 | 11 | .jfField { 12 | } 13 | 14 | .jfTitle { 15 | font-size: 16px; 16 | display: block; 17 | margin-top: 10px; 18 | margin-bottom: 10px; 19 | } 20 | 21 | .jfHelper { 22 | display: block; 23 | margin-top: 10px; 24 | margin-bottom: 10px; 25 | font-size: 13px; 26 | color: #838383; 27 | letter-spacing: 0.5px; 28 | font-style: italic; 29 | } 30 | 31 | a.jfBtn, a.jfBtn:link { 32 | text-decoration: none; 33 | color: #282828; 34 | display: inline-block; 35 | background-color: #F7F7F7; 36 | text-align: center; 37 | border-radius: 50%; 38 | border: 1px solid #999; 39 | margin-bottom: 10px; 40 | } 41 | 42 | // General styles for chosen 43 | 44 | .chosen-container { 45 | margin-bottom: 10px; 46 | } 47 | 48 | @import "fields/fieldcollection"; 49 | @import "fields/fieldcollectionitem"; 50 | @import "fields/boolean"; 51 | @import "fields/ajax"; 52 | @import "fields/string"; -------------------------------------------------------------------------------- /test/jsonform.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, Arial, sans-serif; } 3 | 4 | .jfForm { 5 | margin: 20px 0px; } 6 | 7 | .jfTitle { 8 | font-size: 16px; 9 | display: block; 10 | margin-top: 10px; 11 | margin-bottom: 10px; } 12 | 13 | .jfHelper { 14 | display: block; 15 | margin-top: 10px; 16 | margin-bottom: 10px; 17 | font-size: 13px; 18 | color: #838383; 19 | letter-spacing: 0.5px; 20 | font-style: italic; } 21 | 22 | a.jfBtn, a.jfBtn:link { 23 | text-decoration: none; 24 | color: #282828; 25 | display: inline-block; 26 | background-color: #F7F7F7; 27 | text-align: center; 28 | border-radius: 50%; 29 | border: 1px solid #999; 30 | margin-bottom: 10px; } 31 | 32 | .chosen-container { 33 | margin-bottom: 10px; } 34 | 35 | .jfCollectionItem { 36 | background-color: #FAFAFA; 37 | padding: 10px; 38 | border: 1px solid #C7C7C7; 39 | border-radius: 5px; 40 | margin-bottom: 5px; 41 | max-width: 400px; } 42 | 43 | .jfAdd { 44 | width: 30px; 45 | height: 30px; 46 | line-height: 30px; } 47 | 48 | .jfAdd[disabled] { 49 | opacity: 0.4; 50 | pointer-events: none; } 51 | 52 | a.jfDel { 53 | font-size: 14px; 54 | text-decoration: none; 55 | padding: 3px 5px; 56 | margin-top: 10px; 57 | margin-left: 5px; 58 | color: #DA7D7D; 59 | display: inline-block; 60 | background-color: #ECC8C8; } 61 | 62 | .jfSort { 63 | font-size: 14px; 64 | margin-top: 10px; 65 | margin-right: 5px; 66 | color: #565555; 67 | display: inline-block; 68 | background-color: #DBDBDB; 69 | text-align: center; 70 | padding: 3px 5px; 71 | vertical-align: top; 72 | border-radius: 3px; 73 | cursor: pointer; } 74 | 75 | body.dragging, body.dragging * { 76 | cursor: move !important; } 77 | 78 | .dragged { 79 | position: absolute; 80 | opacity: 0.5; 81 | z-index: 2000; } 82 | 83 | div.jfCollection .placeholder { 84 | position: relative; 85 | margin: 0; 86 | padding: 0; 87 | border: none; } 88 | div.jfCollection .placeholder:before { 89 | position: absolute; 90 | content: ""; 91 | width: 0; 92 | height: 0; 93 | margin-top: -5px; 94 | left: -5px; 95 | top: -4px; 96 | border: 5px solid transparent; 97 | border-left-color: red; 98 | border-right: none; } 99 | 100 | .jfField input[type="text"] { 101 | padding: 6px 10px; 102 | border: 1px solid #B0B0B0; 103 | border-radius: 5px; 104 | background-color: #F7F7F7; 105 | width: 300px; 106 | font-family: Helvetica, Arial, sans-serif; 107 | font-size: 13px; 108 | color: #444; 109 | outline: none; 110 | vertical-align: top; } 111 | -------------------------------------------------------------------------------- /test/jsonform.js: -------------------------------------------------------------------------------- 1 | window.jsonform = {}; 2 | 3 | window.jsonform.helpers = { 4 | panic: function(msg) { 5 | console.error(msg); 6 | return alert(msg); 7 | }, 8 | isJsonString: function(str) { 9 | var e; 10 | try { 11 | JSON.parse(str); 12 | } catch (_error) { 13 | e = _error; 14 | return false; 15 | } 16 | return true; 17 | }, 18 | changed: function() { 19 | return jQuery.event.trigger('jf:change'); 20 | }, 21 | newField: function(jfObj) { 22 | var klass; 23 | klass = jsonform[jfObj.jfType]; 24 | if (klass) { 25 | return new jsonform[jfObj.jfType](jfObj); 26 | } else { 27 | return console.error("jsonform field doesnt exist: " + jfObj.jfType); 28 | } 29 | } 30 | }; 31 | 32 | jsonform.AjaxField = (function() { 33 | AjaxField.preloadValues = function(config, vals, success) { 34 | var query; 35 | vals = _.compact(vals); 36 | if (_.isEmpty(vals)) { 37 | return; 38 | } 39 | query = {}; 40 | query[config.jfReloadParam] = vals; 41 | return $.ajax({ 42 | url: config.jfUrl, 43 | data: query, 44 | type: 'GET', 45 | success: (function(_this) { 46 | return function(data) { 47 | return success(config.jfParse(data, vals)); 48 | }; 49 | })(this), 50 | error: function(data) { 51 | return console.log("error baby"); 52 | } 53 | }); 54 | }; 55 | 56 | function AjaxField(config) { 57 | this.config = config; 58 | this.tmpl = JST["fields/ajax"]; 59 | this.jel = $('
            '); 60 | this.el = this.jel[0]; 61 | } 62 | 63 | AjaxField.prototype.render = function() { 64 | var timeout; 65 | timeout = void 0; 66 | this.jel.html(this.tmpl(this.config)); 67 | this.chosen = this.jel.find(".chosen-select").chosen({ 68 | width: "300px", 69 | allow_single_deselect: true, 70 | no_results_text: 'Searching for' 71 | }); 72 | this.jel.find(".chosen-search input").on('input', (function(_this) { 73 | return function(e) { 74 | clearTimeout(timeout); 75 | return timeout = setTimeout(function() { 76 | return _this.loadAjax(e); 77 | }, 800); 78 | }; 79 | })(this)); 80 | return this.chosen.change(jsonform.helpers.changed); 81 | }; 82 | 83 | AjaxField.prototype.getValue = function() { 84 | return this.jel.find(".chosen-select").val(); 85 | }; 86 | 87 | AjaxField.prototype.clearValues = function() { 88 | this.jel.find("select option").remove(); 89 | this.jel.find("select").append(""); 90 | return this.jel.find(".chosen-select").trigger("chosen:updated"); 91 | }; 92 | 93 | AjaxField.prototype.setValue = function(val) { 94 | if (!_.isObject(val)) { 95 | return this.constructor.preloadValues(this.config, [val], (function(_this) { 96 | return function(newVal) { 97 | return _this.setValue(newVal[0]); 98 | }; 99 | })(this)); 100 | } else { 101 | this.jel.find(".chosen-select").html(''); 102 | this.jel.find(".chosen-select").val(val[0]); 103 | this.jel.find(".chosen-select").trigger("chosen:updated"); 104 | return jsonform.helpers.changed(); 105 | } 106 | }; 107 | 108 | AjaxField.prototype.loadAjax = function(e) { 109 | var chosen, query, searchVal; 110 | chosen = this.jel.find(".chosen-container"); 111 | query = {}; 112 | searchVal = chosen.find(".chosen-search input").val(); 113 | query[this.config.jfSearchParam] = searchVal; 114 | this.clearValues(); 115 | return $.ajax({ 116 | url: this.config.jfUrl, 117 | data: query, 118 | type: 'GET', 119 | success: (function(_this) { 120 | return function(data) { 121 | var results, select; 122 | results = _this.config.jfParse(data); 123 | if (results.length === 0) { 124 | return chosen.find(".chosen-results").html("
          • No results matched \"" + searchVal + "\"
          • "); 125 | } else { 126 | select = _this.jel.find(".chosen-select"); 127 | _.each(results, function(result) { 128 | return select.append(''); 129 | }); 130 | select.trigger("chosen:updated"); 131 | return chosen.find(".chosen-search input").val(searchVal); 132 | } 133 | }; 134 | })(this), 135 | error: function(data) { 136 | return console.log("error baby"); 137 | } 138 | }); 139 | }; 140 | 141 | return AjaxField; 142 | 143 | })(); 144 | 145 | jsonform.BooleanField = (function() { 146 | function BooleanField(config) { 147 | this.config = config; 148 | this.tmpl = JST["fields/boolean"]; 149 | this.jel = $('
            '); 150 | this.el = this.jel[0]; 151 | } 152 | 153 | BooleanField.prototype.render = function() { 154 | this.jel.html(this.tmpl(this.config)); 155 | return this.jel.find(".chosen-select").chosen({ 156 | disable_search_threshold: 5, 157 | width: "300px" 158 | }).change(jsonform.helpers.changed); 159 | }; 160 | 161 | BooleanField.prototype.getValue = function() { 162 | return this.jel.find(".chosen-select").val() === "true"; 163 | }; 164 | 165 | BooleanField.prototype.setValue = function(val) { 166 | this.jel.find(".chosen-select").val(val + ""); 167 | return this.jel.find(".chosen-select").trigger("chosen:updated"); 168 | }; 169 | 170 | return BooleanField; 171 | 172 | })(); 173 | 174 | jsonform.FieldCollection = (function() { 175 | function FieldCollection(config) { 176 | this.config = config; 177 | this.tmpl = JST["fields/fieldcollection"]; 178 | this.jel = $("
            "); 179 | this.el = this.jel[0]; 180 | this.items = []; 181 | } 182 | 183 | FieldCollection.prototype.render = function() { 184 | this.jel.html(this.tmpl(this.config)); 185 | this.jel.find(".jfAdd").click((function(_this) { 186 | return function(e) { 187 | if ($(_this).is("[disabled]")) { 188 | return; 189 | } 190 | e.preventDefault(); 191 | return _this.addItem(); 192 | }; 193 | })(this)); 194 | if ($().sortable) { 195 | return this.jel.find(".jfCollection").sortable({ 196 | placeholder: ' ', 197 | itemSelector: '.jfCollectionItem', 198 | handle: 'i.jfSort', 199 | onDrop: (function(_this) { 200 | return function(item, container, _super) { 201 | _super(item, container); 202 | _this.items = _.sortBy(_this.items, function(item) { 203 | return item.jel.index(); 204 | }); 205 | return jsonform.helpers.changed(); 206 | }; 207 | })(this) 208 | }); 209 | } 210 | }; 211 | 212 | FieldCollection.prototype.getValues = function() { 213 | var results; 214 | results = _.map(this.items, function(item) { 215 | return item.getValue(); 216 | }); 217 | return _.without(results, "", void 0, null); 218 | }; 219 | 220 | FieldCollection.prototype.addItem = function(jsonValue) { 221 | var item; 222 | item = new jsonform.FieldCollectionItem(this.config, jsonValue); 223 | this.jel.find(".jfCollection").append(item.el); 224 | item.render(); 225 | this.items.push(item); 226 | item.jel.on("delete_clicked", (function(_this) { 227 | return function(e, item) { 228 | item.jel.remove(); 229 | _this.items = _.without(_this.items, item); 230 | _this.checkAddState(); 231 | return jsonform.helpers.changed(); 232 | }; 233 | })(this)); 234 | this.checkAddState(); 235 | if ($().sortable) { 236 | this.jel.find(".jfCollection").sortable("refresh"); 237 | } 238 | return jsonform.helpers.changed(); 239 | }; 240 | 241 | FieldCollection.prototype.itemsFromValues = function(vals) { 242 | return _.each(vals, (function(_this) { 243 | return function(val) { 244 | return _this.addItem(val); 245 | }; 246 | })(this)); 247 | }; 248 | 249 | FieldCollection.prototype.checkAddState = function() { 250 | if (this.config.jfMax) { 251 | if (this.items.length >= this.config.jfMax) { 252 | return this.jel.find(".jfAdd").attr("disabled", "disabled"); 253 | } else { 254 | return this.jel.find(".jfAdd").removeAttr("disabled"); 255 | } 256 | } 257 | }; 258 | 259 | return FieldCollection; 260 | 261 | })(); 262 | 263 | jsonform.FieldCollectionItem = (function() { 264 | function FieldCollectionItem(config, jsonValue) { 265 | this.jsonValue = jsonValue; 266 | this.deltmpl = JST["fields/fieldcollection-del"]; 267 | this.sorttmpl = JST["fields/fieldcollection-sort"]; 268 | this.jel = $('
            '); 269 | this.el = this.jel[0]; 270 | this.fields = []; 271 | this.config = {}; 272 | jQuery.extend(true, this.config, config); 273 | delete this.config.jfTitle; 274 | delete this.config.jfHelper; 275 | delete this.config.jfCollection; 276 | delete this.config.jfMax; 277 | if (config.jfType) { 278 | this.fields.push(jsonform.helpers.newField(this.config)); 279 | } else { 280 | _.each(this.config, (function(_this) { 281 | return function(v, k) { 282 | var field; 283 | if (v.jfType) { 284 | field = jsonform.helpers.newField(v); 285 | v.jfField = field; 286 | return _this.fields.push(field); 287 | } 288 | }; 289 | })(this)); 290 | } 291 | } 292 | 293 | FieldCollectionItem.prototype.render = function() { 294 | var del; 295 | this.jel.html(""); 296 | _.each(this.fields, (function(_this) { 297 | return function(field) { 298 | _this.jel.append(field.el); 299 | return field.render(); 300 | }; 301 | })(this)); 302 | if ($().sortable) { 303 | this.jel.append(this.sorttmpl()); 304 | } 305 | del = $(this.deltmpl()); 306 | this.jel.append(del); 307 | del.click((function(_this) { 308 | return function(e) { 309 | e.preventDefault(); 310 | return _this.jel.trigger("delete_clicked", _this); 311 | }; 312 | })(this)); 313 | if (!_.isUndefined(this.jsonValue)) { 314 | if (this.config.jfType) { 315 | return this.fields[0].setValue(this.jsonValue); 316 | } else { 317 | return _.each(this.config, (function(_this) { 318 | return function(v, k) { 319 | if (v.jfField && _this.jsonValue[k]) { 320 | return v.jfField.setValue(_this.jsonValue[k]); 321 | } 322 | }; 323 | })(this)); 324 | } 325 | } 326 | }; 327 | 328 | FieldCollectionItem.prototype.getValue = function() { 329 | var values; 330 | if (this.config.jfType) { 331 | return this.fields[0].getValue(); 332 | } else { 333 | values = {}; 334 | jQuery.extend(true, values, this.config); 335 | _.each(values, (function(_this) { 336 | return function(v, k) { 337 | if (v.jfField) { 338 | return values[k] = v.jfField.getValue(); 339 | } 340 | }; 341 | })(this)); 342 | return values; 343 | } 344 | }; 345 | 346 | return FieldCollectionItem; 347 | 348 | })(); 349 | 350 | jsonform.SelectField = (function() { 351 | function SelectField(config) { 352 | this.config = config; 353 | this.tmpl = JST["fields/select"]; 354 | this.jel = $('
            '); 355 | this.el = this.jel[0]; 356 | } 357 | 358 | SelectField.prototype.render = function() { 359 | this.jel.html(this.tmpl(this.config)); 360 | return this.jel.find(".chosen-select").chosen({ 361 | disable_search_threshold: 5, 362 | width: "300px" 363 | }).change((function(_this) { 364 | return function() { 365 | _this.jel.trigger("jf:changed"); 366 | return jsonform.helpers.changed(); 367 | }; 368 | })(this)); 369 | }; 370 | 371 | SelectField.prototype.getValue = function() { 372 | return this.jel.find(".chosen-select").val(); 373 | }; 374 | 375 | SelectField.prototype.setValue = function(val) { 376 | this.jel.find(".chosen-select").val(val + ""); 377 | return this.jel.find(".chosen-select").trigger("chosen:updated"); 378 | }; 379 | 380 | return SelectField; 381 | 382 | })(); 383 | 384 | jsonform.SelectAjaxField = (function() { 385 | function SelectAjaxField(config) { 386 | this.config = config; 387 | this.jel = $('
            '); 388 | this.el = this.jel[0]; 389 | this.selectField = new jsonform.SelectField({ 390 | jfValues: _.map(this.config.jfValues, function(val) { 391 | return val.jfValue; 392 | }) 393 | }); 394 | this.ajaxField = new jsonform.AjaxField(this.config.jfValues[0]); 395 | } 396 | 397 | SelectAjaxField.prototype.render = function() { 398 | this.jel.html(""); 399 | this.jel.append(this.selectField.el); 400 | this.jel.append(this.ajaxField.el); 401 | this.selectField.render(); 402 | this.ajaxField.render(); 403 | return this.selectField.jel.on("jf:changed", (function(_this) { 404 | return function() { 405 | return _this.selectSwitched(); 406 | }; 407 | })(this)); 408 | }; 409 | 410 | SelectAjaxField.prototype.getValue = function() { 411 | var val; 412 | val = {}; 413 | val[this.config.jfSelectKey] = this.selectField.getValue(); 414 | val[this.config.jfAjaxKey] = this.ajaxField.getValue(); 415 | return val; 416 | }; 417 | 418 | SelectAjaxField.prototype.setValue = function(val) { 419 | var ajaxConfig; 420 | this.selectField.setValue(val[this.config.jfSelectKey]); 421 | ajaxConfig = this.getConfigBySelectKey(this.selectField.getValue()); 422 | return jsonform.AjaxField.preloadValues(ajaxConfig, [val[this.config.jfAjaxKey]], (function(_this) { 423 | return function(data) { 424 | _this.ajaxField.config = ajaxConfig; 425 | return _this.ajaxField.setValue(data[0]); 426 | }; 427 | })(this)); 428 | }; 429 | 430 | SelectAjaxField.prototype.selectSwitched = function() { 431 | var ajaxConfig; 432 | ajaxConfig = this.getConfigBySelectKey(this.selectField.getValue()); 433 | this.ajaxField.config = ajaxConfig; 434 | return this.ajaxField.setValue(["", ""]); 435 | }; 436 | 437 | SelectAjaxField.prototype.getConfigBySelectKey = function(key) { 438 | return _.find(this.config.jfValues, function(conf) { 439 | return conf.jfValue[0] === key; 440 | }); 441 | }; 442 | 443 | return SelectAjaxField; 444 | 445 | })(); 446 | 447 | jsonform.StringField = (function() { 448 | function StringField(config) { 449 | this.config = config; 450 | this.tmpl = JST["fields/string"]; 451 | this.jel = $('
            '); 452 | this.el = this.jel[0]; 453 | } 454 | 455 | StringField.prototype.render = function() { 456 | this.jel.html(this.tmpl(this.config)); 457 | return this.jel.find("input").change(jsonform.helpers.changed); 458 | }; 459 | 460 | StringField.prototype.getValue = function() { 461 | return this.jel.find("input").val(); 462 | }; 463 | 464 | StringField.prototype.setValue = function(val) { 465 | return this.jel.find("input").val(val); 466 | }; 467 | 468 | return StringField; 469 | 470 | })(); 471 | 472 | jsonform.Form = (function() { 473 | function Form(txtArea, jsonConfig) { 474 | var txtval; 475 | this.jel = $('
            '); 476 | this.jtxt = $(txtArea); 477 | this.jtxt.hide(); 478 | this.fields = []; 479 | this.jsonConfig = jsonConfig; 480 | this.parseJsonConfig(this.jsonConfig); 481 | _.each(this.fields, (function(_this) { 482 | return function(field) { 483 | _this.jel.append(field.el); 484 | return field.render(); 485 | }; 486 | })(this)); 487 | $(document).bind('jf:change', (function(_this) { 488 | return function() { 489 | var json; 490 | json = _this.generateJson(_this.jsonConfig); 491 | return _this.jtxt.val(JSON.stringify(json, null, 2)); 492 | }; 493 | })(this)); 494 | this.jtxt.after(this.jel); 495 | txtval = this.jtxt.val(); 496 | if (!!txtval) { 497 | if (jsonform.helpers.isJsonString(txtval)) { 498 | this.fillFields(JSON.parse(txtval), this.jsonConfig); 499 | } else { 500 | jsonform.helpers.panic("Textarea has invalid JSON. jsonform will not work"); 501 | } 502 | } 503 | } 504 | 505 | Form.prototype.generateJson = function(obj) { 506 | var newObj, val, vals; 507 | if (_.isArray(obj)) { 508 | if (obj.length === 1 && obj[0].jfCollection) { 509 | vals = obj[0].jfCollection.getValues(); 510 | if (obj[0].jfCollection.config.jfValueType === "int") { 511 | vals = _.map(vals, function(val) { 512 | return parseInt(val); 513 | }); 514 | } 515 | return vals; 516 | } else { 517 | return _.map(obj, (function(_this) { 518 | return function(v) { 519 | return _this.generateJson(v); 520 | }; 521 | })(this)); 522 | } 523 | } else { 524 | if (obj.jfField) { 525 | val = obj.jfField.getValue(); 526 | if (obj.jfField.config.jfValueType === "int") { 527 | val = parseInt(val); 528 | } 529 | return val; 530 | } else { 531 | if (_.isObject(obj)) { 532 | newObj = {}; 533 | _.each(obj, (function(_this) { 534 | return function(v, k) { 535 | return newObj[k] = _this.generateJson(v); 536 | }; 537 | })(this)); 538 | return newObj; 539 | } else { 540 | return obj; 541 | } 542 | } 543 | } 544 | }; 545 | 546 | Form.prototype.parseJsonConfig = function(obj) { 547 | if (_.isArray(obj)) { 548 | if (obj.length === 1 && obj[0].jfCollection) { 549 | obj[0].jfCollection = new jsonform.FieldCollection(obj[0]); 550 | return this.fields.push(obj[0].jfCollection); 551 | } else { 552 | return _.each(obj, (function(_this) { 553 | return function(v) { 554 | return _this.parseJsonConfig(v); 555 | }; 556 | })(this)); 557 | } 558 | } else { 559 | if (obj.jfType) { 560 | obj.jfField = jsonform.helpers.newField(obj); 561 | return this.fields.push(obj.jfField); 562 | } else { 563 | return _.each(obj, (function(_this) { 564 | return function(v, k) { 565 | if (_.isObject(v)) { 566 | return _this.parseJsonConfig(v); 567 | } 568 | }; 569 | })(this)); 570 | } 571 | } 572 | }; 573 | 574 | Form.prototype.fillFields = function(obj, jsonConfig) { 575 | if (obj === void 0 || jsonConfig === void 0) { 576 | jsonform.helpers.panic("Existing JSON doesnt match JSON config."); 577 | } 578 | if (_.isArray(obj)) { 579 | if (jsonConfig.length === 1 && jsonConfig[0].jfCollection) { 580 | return jsonConfig[0].jfCollection.itemsFromValues(obj); 581 | } else { 582 | return _.each(obj, (function(_this) { 583 | return function(v, i) { 584 | return _this.fillFields(obj[i], jsonConfig[i]); 585 | }; 586 | })(this)); 587 | } 588 | } else { 589 | if (jsonConfig.jfField) { 590 | return jsonConfig.jfField.setValue(obj); 591 | } else { 592 | if (_.isObject(obj)) { 593 | return _.each(obj, (function(_this) { 594 | return function(v, k) { 595 | if (jsonConfig[k]) { 596 | return _this.fillFields(v, jsonConfig[k]); 597 | } else { 598 | console.log("jsonConfig object not present:"); 599 | console.log("key: ", k); 600 | return console.log("value: ", v); 601 | } 602 | }; 603 | })(this)); 604 | } 605 | } 606 | } 607 | }; 608 | 609 | return Form; 610 | 611 | })(); 612 | 613 | this.JST = {"fields/ajax": function(obj) { 614 | obj || (obj = {}); 615 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 616 | function print() { __p += __j.call(arguments, '') } 617 | with (obj) { 618 | 619 | if(typeof(jfTitle)!== 'undefined') { ; 620 | __p += '' + 621 | ((__t = ( jfTitle )) == null ? '' : __t) + 622 | ''; 623 | } ; 624 | __p += '\n'; 625 | if(typeof(jfHelper)!== 'undefined') { ; 626 | __p += '' + 627 | ((__t = ( jfHelper )) == null ? '' : __t) + 628 | ''; 629 | } ; 630 | __p += '\n\n'; 631 | 632 | } 633 | return __p 634 | }, 635 | "fields/boolean": function(obj) { 636 | obj || (obj = {}); 637 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 638 | function print() { __p += __j.call(arguments, '') } 639 | with (obj) { 640 | 641 | if(typeof(jfTitle)!== 'undefined') { ; 642 | __p += '' + 643 | ((__t = ( jfTitle )) == null ? '' : __t) + 644 | ''; 645 | } ; 646 | __p += '\n'; 647 | if(typeof(jfHelper)!== 'undefined') { ; 648 | __p += '' + 649 | ((__t = ( jfHelper )) == null ? '' : __t) + 650 | ''; 651 | } ; 652 | __p += '\n\n'; 653 | 654 | } 655 | return __p 656 | }, 657 | "fields/fieldcollection-del": function(obj) { 658 | obj || (obj = {}); 659 | var __t, __p = '', __e = _.escape; 660 | with (obj) { 661 | __p += 'Delete'; 662 | 663 | } 664 | return __p 665 | }, 666 | "fields/fieldcollection-sort": function(obj) { 667 | obj || (obj = {}); 668 | var __t, __p = '', __e = _.escape; 669 | with (obj) { 670 | __p += ''; 671 | 672 | } 673 | return __p 674 | }, 675 | "fields/fieldcollection": function(obj) { 676 | obj || (obj = {}); 677 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 678 | function print() { __p += __j.call(arguments, '') } 679 | with (obj) { 680 | 681 | if(typeof(jfTitle)!== 'undefined') { ; 682 | __p += '' + 683 | ((__t = ( jfTitle )) == null ? '' : __t) + 684 | ''; 685 | } ; 686 | __p += '\n'; 687 | if(typeof(jfHelper)!== 'undefined') { ; 688 | __p += '' + 689 | ((__t = ( jfHelper )) == null ? '' : __t) + 690 | ''; 691 | } ; 692 | __p += '\n\n+\n\n
            '; 693 | 694 | } 695 | return __p 696 | }, 697 | "fields/select": function(obj) { 698 | obj || (obj = {}); 699 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 700 | function print() { __p += __j.call(arguments, '') } 701 | with (obj) { 702 | 703 | if(typeof(jfTitle)!== 'undefined') { ; 704 | __p += '' + 705 | ((__t = ( jfTitle )) == null ? '' : __t) + 706 | ''; 707 | } ; 708 | __p += '\n'; 709 | if(typeof(jfHelper)!== 'undefined') { ; 710 | __p += '' + 711 | ((__t = ( jfHelper )) == null ? '' : __t) + 712 | ''; 713 | } ; 714 | __p += '\n\n'; 723 | 724 | } 725 | return __p 726 | }, 727 | "fields/selectajax": function(obj) { 728 | obj || (obj = {}); 729 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 730 | function print() { __p += __j.call(arguments, '') } 731 | with (obj) { 732 | 733 | if(typeof(jfTitle)!== 'undefined') { ; 734 | __p += '' + 735 | ((__t = ( jfTitle )) == null ? '' : __t) + 736 | ''; 737 | } ; 738 | __p += '\n'; 739 | if(typeof(jfHelper)!== 'undefined') { ; 740 | __p += '' + 741 | ((__t = ( jfHelper )) == null ? '' : __t) + 742 | ''; 743 | } ; 744 | __p += '\n\n'; 753 | 754 | } 755 | return __p 756 | }, 757 | "fields/string": function(obj) { 758 | obj || (obj = {}); 759 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join; 760 | function print() { __p += __j.call(arguments, '') } 761 | with (obj) { 762 | 763 | if(typeof(jfTitle)!== 'undefined') { ; 764 | __p += '' + 765 | ((__t = ( jfTitle )) == null ? '' : __t) + 766 | ''; 767 | } ; 768 | __p += '\n'; 769 | if(typeof(jfHelper)!== 'undefined') { ; 770 | __p += '' + 771 | ((__t = ( jfHelper )) == null ? '' : __t) + 772 | ''; 773 | } ; 774 | __p += '\n\n'; 775 | 776 | } 777 | return __p 778 | }}; --------------------------------------------------------------------------------