1 /**
  2  * JavaScript file jprim.js v0.2.1 last modified 11/05/18
  3  * 
  4  * jPrim ジェイプリム プリミティブ値拡張ライブラリ
  5  * @module jprim
  6  */
  7 (function (window) {
  8 	var _toString = Object.prototype.toString,
  9 		_slice = Array.prototype.slice,
 10 		_trim = String.prototype.trim || null,
 11 		_pow = Math.pow,
 12 		_sqrt = Math.sqrt,
 13 		_round = Math.round,
 14 		_lastID = 1,
 15 		_cache = {},
 16 		_iterator,
 17 		_methods,
 18 		_data,
 19 		jPrim;
 20 	/**
 21 	 * jPrimオブジェクト
 22 	 * @namespace jPrim
 23 	 */
 24 	jPrim = function (value, options) {
 25 		options = options || {};
 26 		return jPrim.fn.init(value, options);
 27 	};
 28 	/**
 29 	 * jPrimメソッド
 30 	 * @class fn
 31 	 */
 32 	jPrim.fn = {
 33 		/**
 34 		 * jPrimオブジェクト初期化
 35 		 * 
 36 		 * @method init
 37 		 * @param {String|Number|Boolean} value 初期値
 38 		 * @param {Object} option オプション
 39 		 * @return {Object} jPrimオブジェクト
 40 		 */
 41 		init: function (value, options) {
 42 			var object;
 43 			if (isNumber(value)) {
 44 				object = new Number(value);
 45 				
 46 				extend(_methods.common, object);
 47 				extend(_methods.num, object);
 48 			} else if (isString(value)) {
 49 				object = new String(value);
 50 				
 51 				extend(_methods.common, object);
 52 				extend(_methods.str, object);
 53 			} else if (isBoolean(value)) {
 54 				object = new Boolean(value);
 55 				
 56 				extend(_methods.common, object);
 57 				extend(_methods.bool, object);
 58 			}
 59 			
 60 			object._id = generateID();
 61 			object._type = typeof object.valueOf();
 62 			
 63 			_cache[object._id] = object;
 64 			return object;
 65 		},
 66 		/**
 67 		 * イテレータ・オブジェクト初期化
 68 		 * 
 69 		 * @method iterator
 70 		 * @param {String|Number|Boolean} length 処理回数
 71 		 * @param {Function} fn コールバック関数
 72 		 * @param {Object} bind バインドするオブジェクト
 73 		 * @return {Object} イテレータ・オブジェクト
 74 		 */
 75 		iterator: function (length, fn, bind) {
 76 			var value,
 77 				index = 0;
 78 			
 79 			return {
 80 				next: function () {
 81 					if (!this.hasNext()) {
 82 						return null;
 83 					}
 84 					value = fn.call(bind, index)
 85 					index += 1;
 86 					
 87 					return value;
 88 				},
 89 				hasNext: function () {
 90 					return index < length;
 91 				},
 92 				rewind: function () {
 93 					index = 0;
 94 				},
 95 				current: function () {
 96 					return fn.call(bind, index)
 97 				},
 98 				length: length
 99 			};
100 		},
101 		/**
102 		 * データ型別のメソッド群
103 		 * @class methods
104 		 */
105 		methods: {
106 			/**
107 			 * 汎用メソッド
108 			 * @class common
109 			 */
110 			common: {
111 				/**
112 				 * jPrimオブジェクトの最新値を返します。プリミティブ値を返すため、実行するとチェーンが切れます。ネイティブのvalueOfメソッドと同じ効果です
113 				 * 
114 				 * @method getValue
115 				 * @return {Object} jPrimオブジェクトの最新値
116 				 */
117 				getValue: function () {
118 					return this.refresh().valueOf();
119 				},
120 				/**
121 				 * 最新の値を反映したjPrimオブジェクトを返します
122 				 * 
123 				 * @method refresh
124 				 * @return {Object} 最新のjPrimオブジェクト
125 				 */
126 				refresh: function () {
127 					return _cache[this._id];
128 				},
129 				/**
130 				 * jPrimオブジェクトのデータ型を変更します
131 				 * 第1引数にデータ型(number、string、boolean)を指定します
132 				 * 変更後のオブジェクト値は、変更前の値をデータ型に合わせて変換した値になります
133 				 * 
134 				 * @method changeType
135 				 * @param {String} type 変更後のデータ型
136 				 * @return {Object} データ型を変更したjPrimオブジェクト
137 				 */
138 				changeType: function (type) {
139 					var object, value = this.valueOf();
140 					if (type === 'number') {
141 						object = new Number(value);
142 						
143 						extend(_methods.common, object);
144 						extend(_methods.num, object);
145 					} else if (type === 'string') {
146 						object = new String(value);
147 						
148 						extend(_methods.common, object);
149 						extend(_methods.str, object);
150 					} else if (type === 'boolean') {
151 						object = new Boolean(value);
152 						
153 						extend(_methods.common, object);
154 						extend(_methods.bool, object);
155 					}
156 					
157 					object._id = this._id;
158 					object._type = typeof object.valueOf();
159 					
160 					_cache[object._id] = object;
161 					return object;
162 				}
163 			},
164 			/**
165 			 * 数値オブジェクト用メソッド
166 			 * @class num
167 			 */
168 			num: {
169 				/**
170 				 * @method setValue
171 				 * @param {Number} value 数値
172 				 * @return {Object} jPrimオブジェクト
173 				 */
174 				setValue: function (value) {
175 					var object = new Number(value);
176 					extend(this, object);
177 					
178 					_cache[object._id] = object;
179 					return object;
180 				},
181 				/**
182 				 * 数値を指定した範囲内に収めます
183 				 * 
184 				 * @method limit
185 				 * @param {Number} min 最小値
186 				 * @param {Number} max 最大値
187 				 * @return {Object} jPrimオブジェクト
188 				 */
189 				limit: function (min, max) {
190 					var object, value = this.valueOf();
191 					value = value < min ? min : value >= min && value <= max ? value : max;
192 						
193 					object = new Number(value);
194 					extend(this, object);
195 					
196 					_cache[object._id] = object;
197 					return object;
198 				},
199 				/**
200 				 * @method add
201 				 * @param {Number} value 数値
202 				 * @return {Object} jPrimオブジェクト
203 				 */
204 				add: function (value) {
205 					var object = new Number(this.valueOf() + value);
206 					extend(this, object);
207 					
208 					_cache[object._id] = object;
209 					return object;
210 				},
211 				/**
212 				 * @method subtract
213 				 * @param {Number} value 数値
214 				 * @return {Object} jPrimオブジェクト
215 				 */
216 				subtract: function (value) {
217 					var object = new Number(this.valueOf() - value);
218 					extend(this, object);
219 					
220 					_cache[object._id] = object;
221 					return object;
222 				},
223 				/**
224 				 * @method multiply
225 				 * @param {Number} value 数値
226 				 * @return {Object} jPrimオブジェクト
227 				 */
228 				multiply: function (value) {
229 					var object = new Number(this.valueOf() * value);
230 					extend(this, object);
231 					
232 					_cache[object._id] = object;
233 					return object;
234 				},
235 				/**
236 				 * @method divideBy
237 				 * @param {Number} value 数値
238 				 * @return {Object} jPrimオブジェクト
239 				 */
240 				divideBy: function (value) {
241 					var object = new Number(this.valueOf() / value);
242 					extend(this, object);
243 					
244 					_cache[object._id] = object;
245 					return object;
246 				},
247 				/**
248 				 * @method mod
249 				 * @param {Number} value 数値
250 				 * @return {Object} jPrimオブジェクト
251 				 */
252 				mod: function (value) {
253 					var object = new Number(this.valueOf() % value);
254 					extend(this, object);
255 					
256 					_cache[object._id] = object;
257 					return object;
258 				},
259 				/**
260 				 * @method pow
261 				 * @param {Number} value 数値
262 				 * @return {Object} jPrimオブジェクト
263 				 */
264 				pow: function (value) {
265 					var object = new Number(_pow(this.valueOf(), value));
266 					extend(this, object);
267 					
268 					_cache[object._id] = object;
269 					return object;
270 				},
271 				/**
272 				 * @method root
273 				 * @param {Number} value 数値
274 				 * @return {Object} jPrimオブジェクト
275 				 */
276 				root: function (value) {
277 					var object = new Number(_pow(this.valueOf(), 1 / value));
278 					extend(this, object);
279 					
280 					_cache[object._id] = object;
281 					return object;
282 				},
283 				/**
284 				 * @method sqrt
285 				 * @param {Number} value 数値
286 				 * @return {Object} jPrimオブジェクト
287 				 */
288 				sqrt: function () {
289 					var object = new Number(_sqrt(this.valueOf()));
290 					extend(this, object);
291 					
292 					_cache[object._id] = object;
293 					return object;
294 				},
295 				/**
296 				 * @method round
297 				 * @param {Number} precision 小数点n桁表示
298 				 * @return {Object} jPrimオブジェクト
299 				 */
300 				round: function (precision) {
301 					var object, value = this.valueOf();
302 					precision = precision || 0;
303 					value = _round(value * _pow(10, precision)) / _pow(10, precision);
304 					object = new Number(value);
305 					extend(this, object);
306 					
307 					_cache[object._id] = object;
308 					return object;
309 				},
310 				/**
311 				 * Mathオブジェクトのメソッドを呼び出して演算します
312 				 * オブジェクトの現在値は参照しません
313 				 * 第2引数以降、必要な数値等を指定します
314 				 * 
315 				 * @method math
316 				 * @param {String} math 呼び出すメソッド
317 				 * @return {Object} jPrimオブジェクト
318 				 */
319 				math: function (math) {
320 					var object, value,
321 						arg = _slice.call(arguments, 1);
322 					value = Math[math].apply(null, arg);
323 					object = new Number(value);
324 					extend(this, object);
325 					
326 					_cache[object._id] = object;
327 					return object;
328 				},
329 				/**
330 				 * 素数判定を行います。素数なら1が、素数出ないなら0が返ります
331 				 * 
332 				 * @method isPrimeNumber
333 				 * @return {Object} jPrimオブジェクト
334 				 */
335 				isPrimeNumber: function () {
336 					var object, value = this.valueOf();
337 					object = new Number(checkPrimeNumber(value));
338 					extend(this, object);
339 					
340 					_cache[object._id] = object;
341 					return object;
342 				},
343 				/**
344 				 * 現在値より大きい最初の素数を返します
345 				 * 
346 				 * @method nextPrimeNumber
347 				 * @return {Object} jPrimオブジェクト
348 				 */
349 				nextPrimeNumber: function () {
350 					var object, value = this.valueOf();
351 					do {
352 						value += 1;
353 					}
354 					while (checkPrimeNumber(value) === 0);
355 					
356 					object = new Number(value);
357 					extend(this, object);
358 					
359 					_cache[object._id] = object;
360 					return object;
361 				},
362 				/**
363 				 * フィボナッチ数列の第n項目を計算します
364 				 * 
365 				 * @method fibonacci
366 				 * @return {Object} jPrimオブジェクト
367 				 */
368 				fibonacci: function () {
369 					var object, i, v, len = this.valueOf(), f1 = 0, f2 = 1;
370 					for(i = 0; i < len; i++) {
371 						v = f1 + f2;
372 						f2 = f1;
373 						f1 = v;
374 					}
375 					object = new Number(v);
376 					extend(this, object);
377 					
378 					_cache[object._id] = object;
379 					return object;
380 				},
381 				/**
382 				 * 数列の第n項目を計算します。数値nはオブジェクトの現在値とする。等差数列はarithmetic(指定なしでも可)、等比数列はgeometricを第3引数に指定
383 				 * 
384 				 * @method progression
385 				 * @param {Number} a1 第1項
386 				 * @param {Number} value 公差(公比)
387 				 * @param {String} type 等差/等比 arithmetic/geometric
388 				 * @return {Object} jPrimオブジェクト
389 				 */
390 				progression: function (a1, value, type) {
391 					var object, count = this.valueOf(), an;
392 					count -= 1;
393 					if (typeof type === 'undefined' || type === 'arithmetic') {
394 						an = a1 + (value * count);
395 					} else {
396 						an = a1 * (_pow(value, count));
397 					}
398 					object = new Number(an);
399 					extend(this, object);
400 					
401 					_cache[object._id] = object;
402 					return object;
403 				},
404 				/**
405 				 * 数列の第n項までの和を計算します。数値nはオブジェクトの現在値とする。等差数列はarithmetic(指定なしでも可)、等比数列はgeometricを第3引数に指定
406 				 * 
407 				 * @method summation
408 				 * @param {Number} a1 第1項
409 				 * @param {Number} value 公差(公比)
410 				 * @param {String} type 等差/等比 arithmetic/geometric
411 				 * @return {Object} jPrimオブジェクト
412 				 */
413 				summation: function (a1, value, type) {
414 					var object, count = this.valueOf(), sum = 0;
415 					if (typeof type === 'undefined' || type === 'arithmetic') {
416 						while (count--) {
417 							sum += a1 + (value * count);
418 						}
419 					} else {
420 						while (count--) {
421 							sum += a1 * (_pow(value, count));
422 						}
423 					}
424 					object = new Number(sum);
425 					extend(this, object);
426 					
427 					_cache[object._id] = object;
428 					return object;
429 				},
430 				/**
431 				 * オブジェクト値(数値)の回数分だけループ処理します
432 				 * 第1引数を初期値として、第2引数に指定したコールバックの戻り値を順次加算します
433 				 * 結果はオブジェクト値に代入されます。コールバックの戻り値をfalseにするとループを抜け出します
434 				 * オブジェクトをコールバックにバインドさせたいときは、第3引数にオブジェクトを指定します
435 				 * 
436 				 * @method accumulator
437 				 * @param {Number} acc 初期値
438 				 * @param {Function} fn コールバック関数
439 				 * @param {Object} bind バインドするオブジェクト
440 				 * @return {Object} jPrimオブジェクト
441 				 */
442 				accumulator: function (acc, fn, bind) {
443 					var object, i, len = this.valueOf(), value;
444 					bind = typeof bind === 'undefined' ? null : bind;
445 					for (i = 0; i < len; i++) {
446 						value = fn.call(bind, i);
447 						if (value === false) {
448 							break;
449 						}
450 						acc += value;
451 					}
452 					object = new Number(acc);
453 					extend(this, object);
454 					
455 					_cache[object._id] = object;
456 					return object;
457 				},
458 				/**
459 				 * オブジェクト値(数値)の回数分だけループ処理します
460 				 * 
461 				 * @method loop
462 				 * @param {Object} fn コールバック関数
463 				 * @param {Object} bind バインドするオブジェクト
464 				 * @return {Object} jPrimオブジェクト
465 				 */
466 				loop: function (fn, bind) {
467 					var i, len = this.valueOf();
468 					bind = typeof bind === 'undefined' ? null : bind;
469 					for (i = 0; i < len; i++) {
470 						if (fn.call(bind, i) === false) {
471 							break;
472 						}
473 					}
474 					return this;
475 				},
476 				/**
477 				 * オブジェクト値(数値)の回数分だけ一定間隔で処理を行います
478 				 * 第1引数にミリ秒単位で時間間隔を指定します
479 				 * オブジェクト値をあらかじめ-1にすると無限ループになります
480 				 * 
481 				 * @method timer
482 				 * @param {Number} interval 処理間隔(ミリ秒)
483 				 * @param {Object} fn コールバック関数
484 				 * @param {Object} bind バインドするオブジェクト
485 				 * @return {Object} jPrimオブジェクト
486 				 */
487 				timer: function (interval, fn, bind) {
488 					var i = 0,
489 						len = this.valueOf(),
490 						t;
491 					bind = typeof bind === 'undefined' ? null : bind;
492 					t = window.setInterval(function() {
493 						if (i < len || len === -1) {
494 							if (fn.call(bind, i) === false) {
495 								window.clearInterval(t);
496 								return;
497 							}
498 							i++;
499 							return;
500 						}
501 						window.clearInterval(t);
502 					}, interval);
503 					return this;
504 				},
505 				/**
506 				 * ※このメソッドはjPrimオブジェクトを返しません
507 				 * counterメソッドはイテレータ・オブジェクトを返すメソッドです
508 				 * オブジェクト値(数値)の回数分だけイテレータ処理をします
509 				 * 返り値が通常のオブジェクトのため、メソッドチェーンは切れます
510 				 * 第1引数にコールバック関数を指定します。指定しない場合、引数をそのまま返す関数が渡されます
511 				 * オブジェクトをコールバックにバインドさせたいときは、第2引数にオブジェクトを指定します
512 				 * イテレータ・オブジェクトはnextメソッド、hasNextメソッド、rewindメソッド、currentメソッド、lengthプロパティを持ちます
513 				 * 
514 				 * @method counter
515 				 * @param {Function} fn コールバック関数
516 				 * @param {Object} bind バインドするオブジェクト
517 				 * @return {Object} イテレータ・オブジェクト
518 				 */
519 				counter: function (fn, bind) {
520 					var len = this.valueOf(),
521 						fn = fn || s,
522 						bind = bind || null;
523 					return _iterator(len, fn, bind);
524 				},
525 				/**
526 				 * オブジェクト値(数値)をコンマで区切って文字列として返します
527 				 * 
528 				 * @method format
529 				 * @return {Object} jPrimオブジェクト
530 				 */
531 				format: function () {
532 					var object, value = this.valueOf(), _id = this._id;
533 					value += '';
534 					while (value != (value = value.replace(/([+-]?\d+)(\d{3})/, '$1,$2')));
535 					
536 					object = new String(value);
537 					extend(_methods.common, object);
538 					extend(_methods.str, object);
539 					
540 					_cache[_id] = object;
541 					return object;
542 				},
543 				
544 				last: {}
545 			},
546 			/**
547 			 * 文字列オブジェクト用メソッド
548 			 * @class str
549 			 */
550 			str: {
551 				/**
552 				 * @method setValue
553 				 * @param {String} value 文字列
554 				 * @return {Object} jPrimオブジェクト
555 				 */
556 				setValue: function (value) {
557 					var object = new String(value);
558 					extend(this, object);
559 					
560 					_cache[object._id] = object;
561 					return object;
562 				},
563 				/**
564 				 * 文字列の前後の空白を削除します
565 				 * 
566 				 * @method trim
567 				 * @return {Object} jPrimオブジェクト
568 				 */
569 				trim: function () {
570 					var object, text = this.valueOf();
571 					text = _trim ? _trim.call(text) : text.replace(/^\s+/, '').replace(/\s+$/, '');
572 					object = new String(text);
573 					extend(this, object);
574 					
575 					_cache[object._id] = object;
576 					return object;
577 				},
578 				/**
579 				 * テキストに特定の文字列が含まれているかチェックします
580 				 * 文字列が含まれているときは、そのまま文字列を返し
581 				 * 含まれていないときは空文字("")を返します
582 				 * 
583 				 * @method contains
584 				 * @param {String} pattern 検索文字列
585 				 * @return {Object} jPrimオブジェクト
586 				 */
587 				contains: function (pattern) {
588 					var object, text = this.valueOf();
589 					object = new String(text.indexOf(pattern) > -1 ? pattern : '');
590 					extend(this, object);
591 					
592 					_cache[object._id] = object;
593 					return object;
594 				},
595 				/**
596 				 * テキストをフィルターにかけて文字列を抽出します
597 				 * 文字列が見つからないときは空文字("")を返します
598 				 * 
599 				 * チェックできるのは、メールアドレス(email)、より厳密には(email-strict)、郵便番号(post)、URL(url)、電話番号(phone)、IPアドレス(ip)の他、
600 				 * 時刻(time)は、HH:MM:SS形式かどうかチェック(秒は省略可)され、
601 				 * 日付(date)は、YY(YY)/MM/DDまたはYY(YY)-MM-DD形式かチェック(年は省略可)されます
602 				 * なお、メールアドレスのチェックは厳密な方を使用しても完全ではないので注意
603 				 * 
604 				 * @method extract
605 				 * @param {String} filter フィルター(email/post/url/phone/time/date)
606 				 * @return {Object} jPrimオブジェクト
607 				 */
608 				extract: (function () {
609 					var filters = {
610 						email: /([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+/,
611 						'email-strict': /(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+))*)|(?:"(?:\\[^\r\n]|[^\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+))*)|(?:\[(?:\\\S|[\x21-\x5a\x5e-\x7e])*\])))/,
612 						post: /\d{3}-?\d{4}/,
613 						url: /(https?|ftp)(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)/,
614 						phone: /\d{2,5}-?\d{1,4}-?\d{4}|\d{1,4}-?\d{4}/,
615 						time: /([01]?[0-9]|2[0-3]):([0-5][0-9])(:[0-5][0-9])?/,
616 						date: /((1?[0-9]|20)?[0-9]{2}[\/-])?(0?[1-9]|1[0-2])[\/-](0?[1-9]|[12][0-9]|3[01])/,
617 						ip: /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
618 					};
619 					
620 					return function (filter) {
621 						var object, text = this.valueOf(), match;
622 						filter = typeof filter !== 'undefined' ?
623 							( isString(filter) ? filters[filter] : filter ) : filters.email;
624 						match = text.match(filter);
625 						match = match !== null ? match[0] : '';
626 						
627 						object = new String(match);
628 						extend(this, object);
629 						
630 						_cache[object._id] = object;
631 						return object;
632 					};
633 				})(),
634 				/**
635 				 * テキストに含まれる特定の文字列(パターン)をすべて削除します
636 				 * 
637 				 * @method remove
638 				 * @param {String|RegExp} pattern 検索文字列(正規表現)
639 				 * @return {Object} jPrimオブジェクト
640 				 */
641 				remove: function (pattern) {
642 					var object = new String(this.replaceAll(pattern, ''));
643 					extend(this, object);
644 					
645 					_cache[object._id] = object;
646 					return object;
647 				},
648 				/**
649 				 * 文字列をキャメルケース(大文字と小文字の表記)に変換します
650 				 * 
651 				 * @method camelize
652 				 * @return {Object} jPrimオブジェクト
653 				 */
654 				camelize: function () {
655 					var object, value = this.valueOf();
656 					object = new String(resolve(value, 'camel'));
657 					extend(this, object);
658 					
659 					_cache[object._id] = object;
660 					return object;
661 				},
662 				/**
663 				 * 文字列をハイフン(-)でつなげる表記に変換します
664 				 * 
665 				 * @method hyphenate
666 				 * @return {Object} jPrimオブジェクト
667 				 */
668 				hyphenate: function () {
669 					var object, value = this.valueOf();
670 					object = new String(resolve(value, 'hyphen'));
671 					extend(this, object);
672 					
673 					_cache[object._id] = object;
674 					return object;
675 				},
676 				/**
677 				 * 文字列をアンダースコア(_)でつなげる表記に変換します
678 				 * 
679 				 * @method underscore
680 				 * @return {Object} jPrimオブジェクト
681 				 */
682 				underscore: function () {
683 					var object, value = this.valueOf();
684 					object = new String(resolve(value, 'underscore'));
685 					extend(this, object);
686 					
687 					_cache[object._id] = object;
688 					return object;
689 				},
690 				/**
691 				 * テキスト内の特定の文字列すべてを別の文字列で置き換えます
692 				 * 文字列または配列、正規表現リテラルの形で指定します
693 				 * 正規表現リテラルでglobalオプションがついていなくても自動的に全文検索にします
694 				 * 
695 				 * @method replaceAll
696 				 * @param {String|Array|RegExp} pattern キーワード
697 				 * @param {String} replacement 置き換え文字
698 				 * @return {Object} jPrimオブジェクト
699 				 */
700 				replaceAll: function (pattern, replacement) {
701 					var object, text = this.valueOf(), reg, str, i, len;
702 					
703 					if (isString(pattern)) {
704 						reg = new RegExp(pattern, 'gim');
705 					} else if (isArray(pattern)) {
706 						reg = new RegExp(pattern.join('|'), 'gim');
707 					} else {
708 						if (!pattern.global) {
709 							str = pattern.toString().replace(/^\/|\/\w*$/g, '').replace(/'/g, '\'').replace(/"/g, '\"');
710 							reg = new RegExp(str, 'gim');
711 						}
712 						else {
713 							reg = pattern;
714 						}
715 					}
716 					reg = text.match(reg);
717 					
718 					if (reg !== null) {
719 						for (i = 0, len = reg.length; i < len; i++) {
720 							text = text.split(reg[i]).join(replacement);
721 						}
722 					}
723 					
724 					object = new String(text);
725 					extend(this, object);
726 					
727 					_cache[object._id] = object;
728 					return object;
729 				},
730 				/**
731 				 * テキスト内の特定の文字列を別の文字列で置き換えます
732 				 * replaceAllの特殊バージョン
733 				 * 
734 				 * @method censor
735 				 * @param {String|Array|RegExp} keyword キーワード
736 				 * @param {String} replacement 置き換え文字
737 				 * @return {Object} jPrimオブジェクト
738 				 */
739 				censor: function (keyword, replacement) {
740 					var object, text = this.valueOf(), reg, str, i, len, rep;
741 					replacement = replacement || '*';
742 					
743 					if (isString(keyword)) {
744 						reg = new RegExp(keyword, 'gim');
745 					} else if (isArray(keyword)) {
746 						reg = new RegExp(keyword.join('|'), 'gim');
747 					} else {
748 						if (!keyword.global) {
749 							str = keyword.toString().replace(/^\/|\/\w*$/g, '').replace(/'/g, '\'').replace(/"/g, '\"');
750 							reg = new RegExp(str, 'gim');
751 						}
752 						else {
753 							reg = keyword;
754 						}
755 					}
756 					reg = text.match(reg);
757 					
758 					if (reg !== null) {
759 						for (i = 0, len = reg.length; i < len; i++) {
760 							rep = replacement.length > 1 ? replacement : new Array(reg[i].length + 1).join(replacement);
761 							text = text.split(reg[i]).join(rep);
762 						}
763 					}
764 					
765 					object = new String(text);
766 					extend(this, object);
767 					
768 					_cache[object._id] = object;
769 					return object;
770 				},
771 				/**
772 				 * テキスト内の文字列を全角半角・ひらカタ英数字など指定した文字に変換します
773 				 * 第1引数に以下の種類のいずれかを指定します
774 				 * 全角ひら(zen-hira)、全角カタ(zen-kata)、全角英数(zen-alpha-numeric)、全角英字(zen-alpha)、全角数字(zen-numeric)
775 				 * 半角カタ(han-kata)、半角英数(han-alpha-numeric)、半角英字(han-alpha)、半角数字(han-numeric)
776 				 * 
777 				 * @method convertCase
778 				 * @param {String} type 変換後の文字タイプ
779 				 * @return {Object} jPrimオブジェクト
780 				 */
781 				convertCase: function (type) {
782 					var object, text = this.valueOf(),
783 						data = _data.zenHanKaku,
784 						chars, reg, rep, i, len;
785 					type = type || 'zen-hira';
786 					
787 					switch (type) {
788 						case 'zen-hira':
789 							text = toZenKana(data, text, 'hira');
790 							break;
791 						case 'zen-kata':
792 							text = toZenKana(data, text, 'kata');
793 							break;
794 						case 'zen-alpha-numeric':
795 							text = toZenAlphaNumeric(data, text, 'zen-alpha-numeric');
796 							break;
797 						case 'zen-alpha':
798 							text = toZenAlphaNumeric(data, text, 'zen-alpha');
799 							break;
800 						case 'zen-numeric':
801 							text = toZenAlphaNumeric(data, text, 'zen-numeric');
802 							break;
803 						case 'han-kata':
804 							text = toHanKana(data, text);
805 							break;
806 						case 'han-alpha-numeric':
807 							text = toHanAlphaNumeric(data, text, 'han-alpha-numeric');
808 							break;
809 						case 'han-alpha':
810 							text = toHanAlphaNumeric(data, text, 'han-alpha');
811 							break;
812 						case 'han-numeric':
813 							text = toHanAlphaNumeric(data, text, 'han-numeric');
814 							break;
815 					}
816 					
817 					object = new String(text);
818 					extend(this, object);
819 					
820 					_cache[object._id] = object;
821 					return object;
822 				},
823 				/**
824 				 * ※このメソッドはjPrimオブジェクトを返しません
825 				 * enumerateメソッドはイテレータ・オブジェクトを返すメソッドです
826 				 * オブジェクト値(文字列)を正規表現にかけて、マッチした文字列を列挙します
827 				 * 返り値が通常のオブジェクトのため、メソッドチェーンは切れます
828 				 * 第1引数にパターン文字列を指定します。replaceAllメソッドとは異なり、正規表現リテラルか正規表現オブジェクトでの指定となります
829 				 * イテレータ・オブジェクトはnextメソッド、hasNextメソッド、rewindメソッド、currentメソッド、lengthプロパティを持ちます
830 				 * 
831 				 * @method enumerate
832 				 * @param {String} pattern 正規表現パターン
833 				 * @return {Object} イテレータ・オブジェクト
834 				*/
835 				enumerate: function (pattern) {
836 					var object, text = this.valueOf(),
837 						reg = text.match(pattern);
838 					
839 					if (reg === null) {
840 						reg = [];
841 					}
842 					return _iterator(reg.length, function (index) {
843 						return reg[index];
844 					});
845 				}
846 			},
847 			/**
848 			 * 真偽値オブジェクト用メソッド
849 			 * @class bool
850 			 */
851 			bool: {
852 				/**
853 				 * @method setValue
854 				 * @param {Boolean} value 真偽値
855 				 * @return {Object} jPrimオブジェクト
856 				 */
857 				setValue: function (value) {
858 					var object = new Boolean(value);
859 					extend(this, object);
860 					
861 					_cache[object._id] = object;
862 					return object;
863 				},
864 				/**
865 				 * @method toggle
866 				 * @return {Object} jPrimオブジェクト
867 				 */
868 				toggle: function () {
869 					var object = this.valueOf() === true ? new Boolean(false) : new Boolean(true);
870 					extend(this, object);
871 					
872 					_cache[object._id] = object;
873 					return object;
874 				},
875 				/**
876 				 * オブジェクト値がtrueのときのみ指定した処理をします
877 				 * 第1引数にコールバック関数、第2引数にバインドするオブジェクト(省略可)を指定します
878 				 * 処理を遅延させたいときは、第1引数にミリ秒単位で遅延時間を指定し、他のパラメーターを後に続けます
879 				 * 
880 				 * @method execute
881 				 * @param {Number} delay 遅延時間(ミリ秒)
882 				 * @param {Function} fn コールバック関数
883 				 * @param {Object} bind バインドするオブジェクト
884 				 * @return {Object} jPrimオブジェクト
885 				 */
886 				execute: function (delay, fn, bind) {
887 					var arg = arguments, t;
888 					if (typeof delay !== 'number') {
889 						bind = typeof arg[1] === 'undefined' ? null : arg[1];
890 						fn = arg[0];
891 						delay = 0;
892 					}
893 					else {
894 						bind = typeof bind === 'undefined' ? null : bind;
895 					}
896 					
897 					if (this.valueOf() === true) {
898 						t = window.setTimeout(function() {
899 							fn.call(bind);
900 							window.clearTimeout(t);
901 						}, delay);
902 					}
903 					return this;
904 				}
905 			}
906 		}
907 	};
908 	
909 	_iterator = jPrim.fn.iterator;
910 	_methods = jPrim.fn.methods;
911 	_data = {
912 		/*
913 		 * 全角半角の共通記号" 、。,.・:;?!゛゜_ー‐/~|“()[]{}「」+-=<>$%#&*@"
914 		 * 
915 		 */
916 		zenHanKaku: (function () {
917 			var source = {
918 				han: {
919 					numeric: [0x0030, 0x0039],
920 					symbol: [
921 						[0x0020, null], [null, 0xFF64], [null, 0xFF61], [0x002C, null], [0x002E, null], [null, 0xFF65], [0x003A, null], [0x003B, null],
922 						[0x003F, null], [0x0021, null], [null, 0xFF9E], [null, 0xFF9F], [0x005F, null], [null, 0xFF70], [0x002D, null],
923 						[0x002F, null], [0x007E, null], [0x007C, null], [0x0022, null], [0x0028, null], [0x0029, null], [0x005B, null], [0x005D, null],
924 						[0x007B, null], [0x007D, null], [null, 0xFF62], [null, 0xFF63], [0x002B, null], [0x002D, null], [0x003D, null],
925 						[0x003C, null], [0x003E, null], [0x0024, null], [0x0025, null], [0x0023, null], [0x0026, null], [0x002A, null], [0x0040, null]
926 					],
927 					alpha: {
928 						upperCase: [0x0041, 0x005A],
929 						lowerCase: [0x0061, 0x007A]
930 					},
931 					kana: [
932 						0xFF67, 0xFF71, 0xFF68, 0xFF72, 0xFF69, 0xFF73, 0xFF6A, 0xFF74, 0xFF6B, 0xFF75,
933 						0xFF76, [0xFF76, 0xFF9E], 0xFF77, [0xFF77, 0xFF9E], 0xFF78, [0xFF78, 0xFF9E], 0xFF79, [0xFF79, 0xFF9E], 0xFF7A, [0xFF7A, 0xFF9E],
934 						0xFF7B, [0xFF7B, 0xFF9E], 0xFF7C, [0xFF7C, 0xFF9E], 0xFF7D, [0xFF7D, 0xFF9E], 0xFF7E, [0xFF7E, 0xFF9E], 0xFF7F, [0xFF7F, 0xFF9E],
935 						0xFF80, [0xFF80, 0xFF9E], 0xFF81, [0xFF81, 0xFF9E], 0xFF6F, 0xFF82, [0xFF82, 0xFF9E], 0xFF83, [0xFF83, 0xFF9E], 0xFF84, [0xFF84, 0xFF9E],
936 						0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89,
937 						0xFF8A, [0xFF8A, 0xFF9E], [0xFF8A, 0xFF9F], 0xFF8B, [0xFF8B, 0xFF9E], [0xFF8B, 0xFF9F], 0xFF8C, [0xFF8C, 0xFF9E], [0xFF8C, 0xFF9F], 0xFF8D, [0xFF8D, 0xFF9E], [0xFF8D, 0xFF9F], 0xFF8E, [0xFF8E, 0xFF9E], [0xFF8E, 0xFF9F], 
938 						0xFF8F, 0xFF90, 0xFF91, 0xFF92, 0xFF93,
939 						0xFF6C, 0xFF94, 0xFF6D, 0xFF95, 0xFF6E, 0xFF96,
940 						0xFF97, 0xFF98, 0xFF99, 0xFF9A, 0xFF9B,
941 						null, 0xFF9C, null, null, 0xFF66, 0xFF9D
942 					]
943 				},
944 				zen: {
945 					numeric: [0xFF10, 0xFF19],
946 					symbol: [
947 						0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A, 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0xFF3F, 0x30FC, 0x2010, 0xFF0F, 0x301C, 0xFF5C, 0x201C,
948 						0xFF08, 0xFF09, 0xFF3B, 0xFF3D, 0xFF5B, 0xFF5D, 0x300C, 0x300D, 0xFF0B, 0x2212, 0xFF1D, 0xFF1C, 0xFF1E, 0xFF04, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20
949 					],
950 					alpha: {
951 						upperCase: [0xFF21, 0xFF3A],
952 						lowerCase: [0xFF41, 0xFF5A]
953 					},
954 					kana: {
955 						hira: [0x3041, 0x3093],
956 						kata: [0x30A1, 0x30F3]
957 					}
958 				}
959 			},
960 			charData = {}, prop1, prop2, prop3, i, len;
961 			
962 			for (prop1 in source) {
963 				if (source.hasOwnProperty(prop1)) {
964 					charData[prop1] = {};
965 					for (prop2 in source[prop1]) {
966 						if (prop2 == 'numeric') {
967 							charData[prop1][prop2] = [];
968 							for (i = 0, len = source[prop1][prop2][1] - source[prop1][prop2][0] + 1; i < len; i++) {
969 								charData[prop1][prop2][i] = String.fromCharCode(source[prop1][prop2][0] + i);
970 							}
971 						} else if (prop2 == 'alpha' || (prop2 == 'kana' && !isArray(source[prop1][prop2]))) {
972 							charData[prop1][prop2] = {};
973 							for (prop3 in source[prop1][prop2]) {
974 								charData[prop1][prop2][prop3] = [];
975 								for (i = 0, len = source[prop1][prop2][prop3][1] - source[prop1][prop2][prop3][0] + 1; i < len; i++) {
976 									charData[prop1][prop2][prop3][i] = String.fromCharCode(source[prop1][prop2][prop3][0] + i);
977 								}
978 							}
979 						} else {
980 							charData[prop1][prop2] = [];
981 							if (prop1 == 'han') {
982 								if (prop2 == 'symbol') {
983 									for (i = 0, len = source[prop1][prop2].length; i < len; i++) {
984 										charData[prop1][prop2][i] = [];
985 										charData[prop1][prop2][i][0] = source[prop1][prop2][i][0] === null ? null : String.fromCharCode(source[prop1][prop2][i][0]);
986 										charData[prop1][prop2][i][1] = source[prop1][prop2][i][1] === null ? null : String.fromCharCode(source[prop1][prop2][i][1]);
987 									}
988 								} else {
989 									for (i = 0, len = source[prop1][prop2].length; i < len; i++) {
990 										if (isArray(source[prop1][prop2][i])) {
991 											charData[prop1][prop2][i] = String.fromCharCode(source[prop1][prop2][i][0]) + String.fromCharCode(source[prop1][prop2][i][1]);
992 										} else {
993 											charData[prop1][prop2][i] = source[prop1][prop2][i] === null ? null : String.fromCharCode(source[prop1][prop2][i]);
994 										}
995 									}
996 								}
997 							} else {
998 								for (i = 0, len = source[prop1][prop2].length; i < len; i++) {
999 									charData[prop1][prop2][i] = String.fromCharCode(source[prop1][prop2][i]);
1000 								}
1001 							}
1002 						}
1003 					}
1004 				}
1005 			}
1006 			
1007 			return charData;
1008 		}())
1009 	};
1010 	
1011 	/* ユーティリティ関数 */
1012 	function extend() {
1013 		/* 深いコピーを選択するときは第3引数にtrueを渡す */
1014 		var i, arg = arguments, parent, child;
1015 		if (isBoolean(arg[2]) && arg[2] === true) {
1016 			parent = arg[0];
1017 			child = arg[1] || {};
1018 			for (i in parent) {
1019 				if (parent.hasOwnProperty(i)) {
1020 					if (typeof parent[i] === 'object') {
1021 						child[i] = (isArray(parent[i])) ? [] : {};
1022 						extend(true, parent[i], child[i]);
1023 					} else {
1024 						child[i] = parent[i];
1025 					}
1026 				}
1027 			}
1028 			return child;
1029 		} else {
1030 			parent = arg[0];
1031 			child = arg[1] || {};
1032 			for (i in parent) {
1033 				if (parent.hasOwnProperty(i)) {
1034 					child[i] = parent[i];
1035 				}
1036 			}
1037 			return child;
1038 		}
1039 	}
1040 	function bind(object, method) {
1041 		return function () {
1042 			method.apply(object, _slice.call(arguments));
1043 		};
1044 	}
1045 	function checkPrimeNumber(value) {
1046 		var i;
1047 		if (value < 2) {
1048 			return 0;
1049 		} else if (value === 2) {
1050 			return 1;
1051 		} else if (value % 2 === 0) {
1052 			return 0;
1053 		}
1054 		
1055 		for (i = 3; i * i <= value; i += 2) {
1056 			if(value % i === 0) {
1057 				return 0;
1058 			}
1059 		}
1060 		return 1;
1061 	}
1062 	function resolve(value, type) {
1063 		var array, i, len;
1064 		array = value.match(/^[A-Za-z][a-z0-9]*|[A-Z][a-z0-9]*|-\D[a-z0-9]*|_\D[a-z0-9]*/g);
1065 		if (array !== null) {
1066 			for (i = 0, len = array.length; i < len; i++) {
1067 				array[i] = array[i].replace(/^[_-]/, '').toLowerCase();
1068 				if (i !== 0 && typeof type !== 'undefined') {
1069 					switch (type) {
1070 						case 'camel':
1071 							array[i] = array[i].charAt(0).toUpperCase() + array[i].substring(1);
1072 							break;
1073 						case 'hyphen':
1074 							array[i] = '-' + array[i];
1075 							break;
1076 						case 'underscore':
1077 							array[i] = '_' + array[i];
1078 							break;
1079 					}
1080 				}
1081 			}
1082 		}
1083 		
1084 		return array.join('');
1085 	}
1086 	function toZenKana(data, text, type) {
1087 		var chars, reg, rep, i, len;
1088 		
1089 		type = type == 'hira' ? ['hira', 'kata'] : ['kata', 'hira'];
1090 		rep = data.zen.kana[type[0]];
1091 		chars = data.zen.kana[type[1]];
1092 		reg = new RegExp('[' + chars.join('') + ']', 'g');
1093 		text = text.replace(reg, function (match) {
1094 			return rep[chars.indexOf(match)];
1095 		});
1096 		
1097 		chars = data.han.kana;
1098 		reg = new RegExp('[' + chars.join('') + ']', 'g');
1099 		text = text.replace(reg, function (match, index) {
1100 			var value;
1101 			if (text.charCodeAt(index + 1) == 0xFF9E) {
1102 				value = rep[chars.indexOf(match) + 1];
1103 				
1104 			} else if (text.charCodeAt(index + 1) == 0xFF9F) {
1105 				value = rep[chars.indexOf(match) + 2];
1106 			} else {
1107 				value = rep[chars.indexOf(match)];
1108 			}
1109 			if (text.charCodeAt(index) == 0xFF9E || text.charCodeAt(index) == 0xFF9F) {
1110 				value = '';
1111 			}
1112 			return value;
1113 		});
1114 		
1115 		rep = data.zen.symbol;
1116 		chars = data.han.symbol.slice(0);
1117 		for (i = 0, len = chars.length; i < len; i++) {
1118 			chars[i] = chars[i][1];
1119 		}
1120 		
1121 		reg = new RegExp('[' + chars.join('') + ']', 'g');
1122 		text = text.replace(reg, function (match) {
1123 			return rep[chars.indexOf(match)];
1124 		});
1125 		
1126 		return text;
1127 	}
1128 	function toZenAlphaNumeric(data, text, type) {
1129 		var chars, reg, rep, i, len;
1130 		
1131 		if (type == 'zen-alpha-numeric') {
1132 			type = ['zen-alpha', 'zen-numeric'];
1133 		} else if (type == 'zen-alpha') {
1134 			type = ['zen-alpha'];
1135 		} else {
1136 			type = ['zen-numeric'];
1137 		}
1138 		
1139 		if (type.indexOf('zen-alpha') > -1) {
1140 			rep = data.zen.alpha.upperCase;
1141 			chars = data.han.alpha.upperCase;
1142 			reg = new RegExp('[' + chars.join('') + ']', 'g');
1143 			text = text.replace(reg, function (match) {
1144 				return rep[chars.indexOf(match)];
1145 			});
1146 			
1147 			rep = data.zen.alpha.lowerCase;
1148 			chars = data.han.alpha.lowerCase;
1149 			reg = new RegExp('[' + chars.join('') + ']', 'g');
1150 			text = text.replace(reg, function (match) {
1151 				return rep[chars.indexOf(match)];
1152 			});
1153 		}
1154 		if (type.indexOf('zen-numeric') > -1) {
1155 			rep = data.zen.numeric;
1156 			chars = data.han.numeric;
1157 			reg = new RegExp('[' + chars.join('') + ']', 'g');
1158 			text = text.replace(reg, function (match) {
1159 				return rep[chars.indexOf(match)];
1160 			});
1161 		}
1162 		
1163 		rep = data.zen.symbol;
1164 		chars = data.han.symbol.slice(0);
1165 		for (i = 0, len = chars.length; i < len; i++) {
1166 			chars[i] = chars[i][0];
1167 		}
1168 		reg = /[ ,\.:;?!_\-\/~|"()\[\]{}+=<>\$%#&*@]/g;
1169 		
1170 		text = text.replace(reg, function (match) {
1171 			return rep[chars.indexOf(match)];
1172 		});
1173 		
1174 		return text;
1175 	}
1176 	function toHanAlphaNumeric(data, text, type) {
1177 		var chars, reg, rep, i, len;
1178 		
1179 		if (type == 'han-alpha-numeric') {
1180 			type = ['han-alpha', 'han-numeric'];
1181 		} else if (type == 'han-alpha') {
1182 			type = ['han-alpha'];
1183 		} else {
1184 			type = ['han-numeric'];
1185 		}
1186 		
1187 		if (type.indexOf('han-alpha') > -1) {
1188 			rep = data.han.alpha.upperCase;
1189 			chars = data.zen.alpha.upperCase;
1190 			reg = new RegExp('[' + chars.join('') + ']', 'g');
1191 			text = text.replace(reg, function (match) {
1192 				return rep[chars.indexOf(match)];
1193 			});
1194 			rep = data.han.alpha.lowerCase;
1195 			chars = data.zen.alpha.lowerCase;
1196 			reg = new RegExp('[' + chars.join('') + ']', 'g');
1197 			text = text.replace(reg, function (match) {
1198 				return rep[chars.indexOf(match)];
1199 			});
1200 		}
1201 		if (type.indexOf('han-numeric') > -1) {
1202 			rep = data.han.numeric;
1203 			chars = data.zen.numeric;
1204 			reg = new RegExp('[' + chars.join('') + ']', 'g');
1205 			text = text.replace(reg, function (match) {
1206 				return rep[chars.indexOf(match)];
1207 			});
1208 		}
1209 		
1210 		rep = data.han.symbol.slice(0);
1211 		for (i = 0, len = rep.length; i < len; i++) {
1212 			rep[i] = rep[i][0];
1213 		}
1214 		chars = data.zen.symbol;
1215 		
1216 		reg = /[ ,.:;?!_‐/~|“()[]{}+-=<>$%#&*@]/g;
1217 		
1218 		text = text.replace(reg, function (match) {
1219 			return rep[chars.indexOf(match)];
1220 		});
1221 		
1222 		return text;
1223 	}
1224 	function toHanKana(data, text) {
1225 		var chars, reg, rep, i, len;
1226 		
1227 		rep = data.han.kana;
1228 		chars = data.zen.kana.hira;
1229 		reg = new RegExp('[' + chars.join('') + ']', 'g');
1230 		text = text.replace(reg, function (match) {
1231 			return rep[chars.indexOf(match)];
1232 		});
1233 		
1234 		chars = data.zen.kana.kata;
1235 		reg = new RegExp('[' + chars.join('') + ']', 'g');
1236 		text = text.replace(reg, function (match) {
1237 			return rep[chars.indexOf(match)];
1238 		});
1239 		
1240 		rep = data.han.symbol.slice(0);
1241 		for (i = 0, len = rep.length; i < len; i++) {
1242 			rep[i] = rep[i][1];
1243 		}
1244 		
1245 		chars = data.zen.symbol;
1246 		reg = new RegExp('[' + chars.join('') + ']', 'g');
1247 		text = text.replace(reg, function (match) {
1248 			var value;
1249 			if (rep[chars.indexOf(match)] === null) {
1250 				value = data.han.symbol[chars.indexOf(match)][0];
1251 			} else {
1252 				value = rep[chars.indexOf(match)];
1253 			}
1254 			return value;
1255 		});
1256 		
1257 		return text;
1258 	}
1259 	function generateID() {
1260 		return _lastID++;
1261 	}
1262 	function getLastID() {
1263 		return _lastID;
1264 	}
1265 	function isNumber(value) {
1266 		return _toString.call(value) === '[object Number]';
1267 	}
1268 	function isString(value) {
1269 		return _toString.call(value) === '[object String]';
1270 	}
1271 	function isBoolean(value) {
1272 		return _toString.call(value) === '[object Boolean]';
1273 	}
1274 	function isArray(value) {
1275 		return _toString.call(value) === '[object Array]';
1276 	}
1277 	function s(value) {
1278 		return value;
1279 	}
1280 	
1281 	window.jPrim = jPrim;
1282 }(window));