1 /**
  2  * @fileOverview Extensions/helper methods for Strings
  3  * @author <a href="http://www.bobs-bits.com">Stephen Reay</a>
  4  */
  5 
  6 if (!String.prototype.replaceMulti) {
  7 	/**
  8 	 * Replace one or more sub-strings in a String with a single new value, or with values from an Array
  9 	 * @param {String|Array} findVal the sub-string(s) to find in the string
 10 	 * @param {String|Array} [replaceVal=''] the value(s) to to replace the found-substrings.
 11 	 * A String will replace all instances of the sub-strings searched for.
 12 	 * An Array will replace corresponding sub-strings, and must have same length as Array of sub-strings to find.
 13 	 * @returns {String} the new String
 14 	 */
 15 	String.prototype.replaceMulti = function replaceMulti(findVal,replaceVal) {
 16 		var that = this.toString();
 17 		if (typeof findVal === 'string') {
 18 			return that.replace(new RegExp(findVal,'g'),replaceVal);
 19 		}
 20 		else {
 21 			replaceVal = typeof replaceVal === 'string' ? [replaceVal] : replaceVal;
 22 			
 23 			for (var i = 0; i < findVal.length; i++) {
 24 				var repStr = replaceVal[i] ? replaceVal[i] : replaceVal[0];
 25 				that = that.replace(new RegExp(findVal[i],'g'),repStr);
 26 			}
 27 		}
 28 		return that;
 29 	};
 30 }	
 31 
 32 if (!String.prototype.toCamelCase) {	
 33 	/**
 34 	 * Convert a dash or space seperated String to Camel-Case
 35 	 * @returns {String} the Camel-Cased String
 36 	 * @example
 37 	 * var str1 = 'some-words-here'.toCamelCase(); //'someWordsHere'
 38 	 * var str2 = ' some words there'.toCamelCase(); //'SomeWordsThere'
 39 	 */
 40 	String.prototype.toCamelCase = function toCamelCase() {
 41 		var that = this.toString();
 42 		if (!/[\-\s]/.test(that)) {
 43 			return that;
 44 		}
 45 		
 46 		var bits = that.split(/[\-\s]/);
 47 		that = bits[0];
 48 		for (var i = 1; i < bits.length; i++) {
 49 			if (bits[i].length > 0) {
 50 				that += bits[i].charAt(0).toUpperCase();
 51 				that += bits[i].substring(1);
 52 			}
 53 		}
 54 		
 55 		return that;
 56 	 };
 57 }
 58 
 59 if (!String.prototype.toDashed) {
 60 	/**
 61 	 * Convert a Camel-Cased String into a dash-seperated String
 62 	 * @returns {String} the dash-seperated string
 63 	 * @example
 64 	 * var str1 = 'SomeValueHere'.toDashed(); //'-some-value-here'
 65 	 * var str2 = 'someValueHere'.toDashed(); //'some-value-here'
 66 	 */
 67 	String.prototype.toDashed = function toDashed() {
 68 		var that = this.toString();
 69 		
 70 		return that.replace(/([A-Z])/g, '-$1').toLowerCase();
 71 	};
 72 }
 73 
 74 if (!String.prototype.stripTags) {
 75 	/**
 76 	 * Strip HTML or XML style tags, optionally including the tag content from a String
 77 	 * @param {String} tag the tag name to remove from the String
 78 	 * @param {Boolean} [removeContent=false] flag to remove the content of the tag as well as the tag itself
 79 	 * @returns {String} the String with tags (and content if removeContent is true) removed
 80 	 * @example
 81 	 * var p = '<p id="moo"><strong>Moo</strong> cow</p>';
 82 	 * p.stripTags('p'); //'<strong>Moo</strong> cow'
 83 	 * p.stripTags('strong',true); //'<p id="moo"> cow</p>'
 84 	 */
 85 	String.prototype.stripTags = function stripTags(tag, removeContent) {
 86 		var that = this.toString();
 87 		removeContent = removeContent || false;
 88 		tag = (tag || '') + '[^>]';
 89 		var reStr = removeContent ? '<' + tag + '[.\\s]*?<\/' + tag +'*?>' : '</?' + tag + '*?>';
 90 		var re = new RegExp(reStr,'gi');
 91 		
 92 		return that.replace(re,'');
 93 	};
 94 }
 95 
 96 if (!String.prototype.stripScripts) {	
 97 	/**
 98 	 * Common-use implementation of {@link String#stripTags}
 99 	 * @requires String#stripTags
100 	 * @returns {String} the original String with the SCRIPT tags (and content) removed
101 	 * @example
102 	 * var str = '<div><script type="text/javascript">alert('foo');</script> and stuff!</div>';
103 	 * str.stripScripts(); // '<div> and stuff</div>';
104 	 */
105 	String.prototype.stripScripts = function stripScripts() {
106 		return this.toString().stripTags('script',true);
107 	};
108 }
109 
110 if (!String.prototype.trim) {
111 	/**
112 	 * Trim whitespace (or nominated character(s)/Regular Expression) from each end of a String
113 	 * @param {String|RegEx} [chars=whitespace] the character(s) or Regular Expression to remove from each end of the String. Defaults to whitespace
114 	 * @returns {String} the original String with the specified characters (or whitespace) removed from each end
115 	 * @see String.prototype.ltrim
116 	 * @see String.prototype.rtrim
117 	 * @example
118 	 * ' foo bar	'.trim(); //'foo bar'
119 	 * 'foo barf '.trim('f'); //'oo barf '
120 	 */
121 	String.prototype.trim = function trim(chars) {
122 		var that = this.toString();
123 		chars = (chars || '[\\s]') + '*';
124 		var re = new RegExp('^(' + chars + ')|(' + chars + ')$','g');
125 		return that.replace(re,'');
126 	};
127 }	 
128 
129 if (!String.prototype.ltrim) {
130 	/**
131 	 * Trim whitespace (or nominated character(s)/Regular Expression) from the beginning of a String
132 	 * @param {String|RegEx} [chars=whitespace] the character(s) or Regular Expression to remove from each end of the String. Defaults to whitespace
133 	 * @returns {String} the original String with the specified characters (or whitespace) removed from the beginning
134 	 * @see String.prototype.trim
135 	 * @see String.prototype.rtrim
136 	 * @example
137 	 * ' foo bar	'.ltrim(); //'foo bar	'
138 	 * 'foo barf '.ltrim('f'); //'oo barf '
139 	 */
140 	String.prototype.ltrim = function ltrim(chars) {
141 		var that = this.toString();
142 		chars = (chars || '[\\s]') + '*';
143 		var re = new RegExp('^' + chars);
144 		return that.replace(re,'');
145 	};
146 }
147 
148 if (!String.prototype.rtrim) {
149 	/**
150 	 * Trim whitespace (or nominated character(s)/Regular Expression) from the end of a String
151 	 * @param {String|RegEx} [chars=whitespace] the character(s) or Regular Expression to remove from each end of the String. Defaults to whitespace
152 	 * @returns {String} the original String with the specified characters (or whitespace) removed from the end
153 	 * @see String.prototype.trim
154 	 * @see String.prototype.ltrim
155 	 * @example
156 	 * ' foo bar	'.rtrim(); //' foo bar'
157 	 * 'foo barf '.rtrim('f'); //'foo barf '
158 	 */
159 	String.prototype.rtrim = function rtrim(chars) {
160 		var that = this.toString();
161 		chars = (chars || '[\\s]') + '*';
162 		var re = new RegExp(chars + '$');
163 		return that.replace(re,'');
164 	};
165 }
166 
167 if (!String.prototype.excapeRegex) {
168 	 /**
169 	  * Escape RegEx special characters
170 	  * @returns {String} the original String with all RegEx special characters escaped.
171 	  */
172 	String.prototype.escapeRegex = function escapeRegex() {
173 		var that = this.toString();
174 		var reChars = new RegExp("[.*+?|$^()\\[\\]{}\\\\]",'g');
175 		return that.replace(reChars, "\\$&");
176 		
177 	};
178 }
179 	 
180 if (!String.prototype.parseURL) {
181 	 /**
182 	  * Parse a URL string into parts, simmilar to the document.location object
183 	  * @returns {Object} an object containing the parts of the URL, simmilar to the document.location object
184 	  * @todo
185 	  * This is now broken.
186 	  */
187 	String.prototype.parseURL = function parseURL() {
188 		var that = this.toString();
189 		
190 		var anchor = document.createElement('a');
191 		anchor.setAttribute('href', that);
192 	
193 		var props = [
194 			'href',
195 			'protocol',
196 			'host',
197 			'hostname',
198 			'port',
199 			'pathname',
200 			'search',
201 			'hash'
202 		];
203 	
204 		var parts = {};
205 		props.forEach(function (prop) {
206 			parts[prop] = anchor[prop];
207 		});
208 	
209 		if (parts.pathname.charAt(0) !== '/') {
210 			parts.pathname = '/' + parts.pathname;
211 		}
212 		
213 		return parts;
214 	};
215 }
216 
217 if (!String.prototype.parseQuery) {	 
218 	 /**
219 	  * Parse a query-string such as the "search" property of the document.location object
220 	  * @param {String} [seperator=&] the character seperating the name:value pairs in the string
221 	  * @returns {Object} an object containing the key:value pairs in the String. Multiple entries with the same name will be returned in an Array
222 	  */
223 	String.prototype.parseQuery = function parseQuery(seperator, convert) {
224 		var that = this.toString().ltrim('\\?');
225 		seperator = seperator || "&";
226 		convert = convert || false;
227 		
228 		var parts = that.split(seperator);
229 		var args = {};
230 		for (var i = 0; i < parts.length; i++) {
231 			var bits = parts[i].split('=');
232 			if(args.hasOwnProperty(bits[0])) {
233 				if(!Object.isArray(args[bits[0]])) {
234 					var tmp = args[bits[0]];
235 					args[bits[0]] = [tmp];
236 				}
237 				args[bits[0]].push(bits[1]);
238 			}
239 			else{
240 				args[bits[0]] = bits[1];
241 			}	 	
242 		}	
243 		return args;
244 	};
245 }