1 /* 2 * Geddy JavaScript Web development framework 3 * Copyright 2112 Matthew Eernisse (mde@fleegix.org) 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 t 17 */ 18 var uri = new (function () { 19 this.getFileExtension = function (path) { 20 var match; 21 if (path) { 22 match = /.+\.(\w{2,4}$)/.exec(path); 23 } 24 return (match && match[1]) || ''; 25 }; 26 27 /** 28 * Convert a JS Object to querystring (key=val&key=val). 29 * Value in arrays will be added as multiple parameters 30 * @param obj -- an Object containing only scalars and arrays 31 * @param o -- JS object of options for how to format 32 * the return string. Supported options: 33 * consolidate: (Boolean) take values from elements that 34 * can return multiple values (multi-select, checkbox groups) 35 * and collapse into a single, comman-delimited value. 36 * Defaults to false. 37 * (e.g., thisVar=asdf,qwer,zxcv) 38 * includeEmpty: (Boolean) include keys in the string for 39 * all elements, even if they have no value set (e.g., 40 * even if elemB has no value: elemA=foo&elemB=&elemC=bar). 41 * Defaults to false. Note that some false-y values are always 42 * valid even without this option, [0, '']. This option extends 43 * coverage to [null, undefined, NaN] 44 * snakeize: (Boolean) change param names from 45 * camelCase to snake_case. Defaults to false. 46 * escapeVals: (Boolean) escape the values for XML entities. 47 * Defaults to false. 48 * @returns A querystring containing the values in the 49 * Object 50 */ 51 this.paramify = function (obj, o) { 52 var opts = o || {}, 53 str = '', 54 key, 55 val, 56 isValid, 57 itemArray, 58 arr = [], 59 arrVal; 60 61 for (var p in obj) { 62 if (Object.prototype.hasOwnProperty.call(obj, p)) { 63 val = obj[p]; 64 65 // This keeps valid falsy values like false and 0 66 // It's duplicated in the array block below. Could 67 // put it in a function but don't want the overhead 68 isValid = !( val === null || val === undefined || 69 (typeof val === 'number' && isNaN(val)) ); 70 71 key = opts.snakeize ? yam.snakeize(p) : p; 72 if (isValid) { 73 // Multiple vals -- array 74 if (this.isArray(val) && val.length) { 75 itemArray = []; 76 for (var i = 0, ii = val.length; i < ii; i++) { 77 arrVal = val[i]; 78 // This keeps valid falsy values like false and 0 79 isValid = !( arrVal === null || arrVal === undefined || 80 (typeof arrVal === 'number' && isNaN(arrVal)) ); 81 82 itemArray[i] = isValid ? encodeURIComponent(arrVal) : ''; 83 if (opts.escapeVals) { 84 itemArray[i] = yam.escapeXML(itemArray[i]); 85 } 86 } 87 // Consolidation mode -- single value joined on comma 88 if (opts.consolidate) { 89 arr.push(key + '=' + itemArray.join(',')); 90 } 91 // Normal mode -- multiple, same-named params with each val 92 else { 93 // {foo: [1, 2, 3]} => 'foo=1&foo=2&foo=3' 94 // Add into results array, as this just ends up getting 95 // joined on ampersand at the end anyhow 96 arr.push(key + '=' + itemArray.join('&' + key + '=')); 97 } 98 } 99 // Single val -- string 100 else { 101 if (opts.escapeVals) { 102 val = yam.escapeXML(val); 103 } 104 arr.push(key + '=' + encodeURIComponent(val)); 105 } 106 str += '&'; 107 } 108 else { 109 if (opts.includeEmpty) { arr.push(key + '='); } 110 } 111 } 112 } 113 return arr.join('&'); 114 }; 115 116 /** 117 * Convert the values in a query string (key=val&key=val) to 118 * an Object 119 * @param str -- A querystring 120 * @param o -- JS object of options, currently: 121 * consolidate: (Boolean) convert mutliple instances of 122 * the same key into an array of values instead of 123 * overwriting. Defaults to true. 124 * @returns JavaScript key/val object with the values from 125 * the querystring 126 */ 127 this.objectify = function (str, o) { 128 var opts = o || {}; 129 var d = {}; 130 var consolidate = typeof opts.consolidate == 'undefined' ? 131 true : opts.consolidate; 132 if (str) { 133 var arr = str.split('&'); 134 for (var i = 0; i < arr.length; i++) { 135 var pair = arr[i].split('='); 136 var name = pair[0]; 137 var val = decodeURIComponent(pair[1] || ''); 138 // "We've already got one!" -- arrayize if the flag 139 // is set 140 if (typeof d[name] != 'undefined' && consolidate) { 141 if (typeof d[name] == 'string') { 142 d[name] = [d[name]]; 143 } 144 d[name].push(val); 145 } 146 // Otherwise just set the value 147 else { 148 d[name] = val; 149 150 } 151 } 152 } 153 return d; 154 }; 155 156 })(); 157 158 exports.uri = uri; 159 160