PageSourceSearch

https://koreascience.kr/js/native.js

js koreascience.kr collected 2026-10-01 10:41:50 UTC 20,990 bytes, 754 lines download raw bytes

1window.addNative = true;
2
3/* Array에 indexOf가 정의되지 않았을 때. */
4//if ( ! Array.prototype.indexOf ) {
5//	Array.prototype.indexOf = function(obj, fromIndex) {
6//		if (fromIndex == null) {
7//			fromIndex = 0;
8//		}
9//		else if (fromIndex < 0) {
10//			fromIndex = Math.max(0, this.length + fromIndex);
11//		}
12//
13//		for (var i = fromIndex, j = this.length; i < j; i++) {
14//			if (this[i] === obj)
15//				return i;
16//		}
17//
18//		return -1;
19//	};
20//}
21
22
23//if ( ! Array.prototype.merge ) {
24	/**
25	 * 주어진 배열을 구별자를 넣어 하나의 문자열로 만든다.
26	 *
27	 * @param array 합칠 값을 가지고 있는 배열.
28	 * @param delim 구별자
29	 * @param exceptEmpty 빈값(undefined, null, '') 제외 여부.
30	 */
31//	Array.prototype.merge = function(delim, exceptEmpty) {
32//			if ( ! exceptEmpty ) return this.join(delim);
33//
34//			var arr = [];
35//			for (var i = 0; i < this.length; i++) {
36//				if ( this[i] == undefined
37//						|| this[i] == null
38//						|| this[i] == '' ) continue;
39//
40//				arr.push(this[i]);
41//			}
42//
43//			return arr.join(delim);
44//		};
45//}
46
47
48
49/* Array에 prevOf 가 정의되지 않았을 때. */
50/**
51 * 주어진 항목의 이전 항목을 돌려준다.
52 * 주어진 항목을 찾을 수 없거나 이전 항목이 없으면 null을 돌려 준다.
53 */
54//if ( ! Array.prototype.prevOf ) {
55//	Array.prototype.prevOf = function(obj, fromIndex) {
56//		var index = this.indexOf(obj, fromIndex) - 1;
57//
58//		return index < 0 ? null : this[index];
59//	};
60//}
61
62/**
63 * 주어진 항목의 다음 항목을 돌려준다.
64 * 주어진 항목을 찾을 수 없거나 다음 항목이 없으면 null을 돌려 준다.
65 */
66//if ( ! Array.prototype.nextOf ) {
67//	Array.prototype.nextOf = function(obj, fromIndex) {
68//		var index = this.indexOf(obj, fromIndex) + 1;
69//
70//		return index < 0 || this.length <= index ? null : this[index];
71//	};
72//}
73
74
75
76/**
77 * String에 trim 함수가 없으면 추가.
78 */
79if ( ! String.prototype.trim ) {
80	String.prototype.trim = function() {
81		if ( ! String._trimRegExp ) {
82			String._trimRegExp  = /(^\s+)|(\s+$)/gi;
83		}
84
85		return this.replace(String._trimRegExp, "");
86	};
87}
88
89/**
90 * String에 startsWith 함수가 없으면 추가.
91 */
92if ( ! String.prototype.startsWith ) {
93	String.prototype.startsWith = function(searchString, position){
94		position = position || 0;
95
96		return this.substr(position, searchString.length) === searchString;
97	};
98}
99
100/**
101 * String에 startsWith 함수가 없으면 추가.
102 */
103if ( ! String.prototype.endsWith ) {
104	String.prototype.endsWith = function(searchString, position) {
105		var subjectString = this.toString();
106		if (typeof position !== 'number' || ! isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
107
108			position = subjectString.length;
109		}
110
111		position -= searchString.length;
112		var lastIndex = subjectString.lastIndexOf(searchString, position);
113
114		return lastIndex !== -1 && lastIndex === position;
115	};
116}
117
118/**
119 * String에 padLeft 메쏘드 추가.
120 */
121if ( ! String.prototype.padLeft ) {
122	String.prototype.lpad = String.prototype.padLeft = function(width, ch) {
123		width = Math.max(0, width);
124		ch    = ch == undefined || ch == null ? ' ' : ch;
125
126		var str = this;
127		var count = width - this.length;
128		for (var i = 0; i < count; i++) {
129			str = ch + str;
130		}
131
132		return str;
133	};
134}
135
136/**
137 * String에 padRight 메쏘드 추가.
138 */
139if ( ! String.prototype.padRight ) {
140	String.prototype.rpad = String.prototype.padRight = function(width, ch) {
141		width = Math.max(0, width);
142		ch    = ch == undefined || ch == null ? ' ' : ch;
143
144		var str = this;
145		var count = width - this.length;
146		for (var i = 0; i < count; i++) {
147			str += ch;
148		}
149
150		return str;
151	};
152}
153
154
155if ( ! String.prototype.hashCode ) {
156	String.prototype.hashCode = function() {
157		for (var r = 0, i = 0; i < this.length; i++) {
158			r = ( r << 5 ) - r + this.charCodeAt(i), r &= r;
159		}
160
161		return r
162	};
163}
164
165
166if ( window.jQuery && jQuery.tmpl) {
167	if ( ! String.render ) {
168		/**
169		 * 템플릿을 이용한 렌더러.
170		 * jquery.tmpl 플러그인에 의존한다.
171		 *
172		 * @param data  현재 렌더링 중인 열의 데이터.
173		 * @param tmpl 템플릿 문자열.
174		 * @param tmplName 템플릿 캐쉬 명칭.
175		 */
176		String.render = function(data, tmpl, tmplName) {
177			if ( tmpl == undefined || tmpl === null ) return tmpl;
178
179			if ( typeof(tmpl) !== 'string' ) tmpl = tmpl.toString();
180
181			if ( ! tmplName ) tmplName = 'tmpl-' + tmpl.hashCode();
182
183
184			/* 등록되지 않은 Template이면 등록한다. */
185			if (tmplName && ! $.template[tmplName] ) {
186				$.template(tmplName, tmpl);
187			}
188
189			var tmplFunc = $.template(tmplName);
190
191			return tmplFunc($, { data: data }).join('');
192		};
193	}
194}
195
196
197if ( ! String.prototype.render ) {
198	/**
199	 * 템플릿을 이용한 렌더러.
200	 * jquery.tmpl 플러그인에 의존한다.
201	 *
202	 * @param data  현재 렌더링 중인 열의 데이터.
203	 * @param tmpl 템플릿 문자열.
204	 * @param tmplName 템플릿 캐쉬 명칭.
205	 */
206	String.prototype.render = function(data, tmplName) {
207		return String.render(data, this.toString(), tmplName);
208	};
209}
210
211
212/**
213 * Number에 padLeft 메쏘드 추가.
214 */
215if ( ! Number.prototype.padLeft ) {
216	Number.prototype.lpad = Number.prototype.padLeft = function(width, ch) {
217		return this.toString().padLeft(width, ch);
218	};
219}
220
221
222/**
223 * Number에 padRight 메쏘드 추가.
224 */
225if ( ! Number.prototype.padRight ) {
226	Number.prototype.rpad = Number.prototype.padRight = function(width, ch) {
227		return this.toString().padRight(width, ch);
228	};
229}
230
231/**
232 * Number에 format 메쏘드 추가.
233 */
234if ( ! Number.prototype.format ) {
235	Number.FORMAT_REGEXP = /(^[+-]?\d+)(\d{3})/;
236
237	Number.prototype.format = function() {
238		if ( this == 0 ) return 0;
239
240		var reg = Number.FORMAT_REGEXP;
241		var noStr = (this + '');
242
243		while (reg.test(noStr)) {
244			noStr = noStr.replace(reg, '$1' + ',' + '$2');
245		}
246
247		return noStr;
248	};
249}
250
251
252if ( ! Date.prototype.format ) {
253	Date.FORMAT_SHORT = 'yyyy-MM-dd';
254	Date.FORMAT_MID   = 'yyyy-MM-dd';
255	Date.FORMAT_LONG  = 'yyyy-MM-dd';
256	Date.FORMAT_FULL  = 'yyyy-MM-dd';
257
258	Date.prototype.format = function(format) {
259		if ( ! this.valueOf()) return '';
260
261		format = format || Date.FORMAT_SHORT;
262
263
264		var weekName = ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'];
265		var d = this;
266
267		return format.replace(/(yyyy|yy|MM|M|dd|d|E|HH|H|hh|h|mm|m|ss|s|a\/p)/g, function($1) {
268			var val = $1;
269			switch ($1) {
270				case 'yyyy': val = d.getFullYear(); break;
271				case 'yy'  : val = (d.getFullYear() % 1000).padLeft(2, '0');  break;
272				case 'MM'  : val = (d.getMonth() + 1).padLeft(2, '0');  break;
273				case 'M'   : val = d.getMonth() + 1;  break;
274				case 'dd'  : val = d.getDate().padLeft(2, '0');  break;
275				case 'd'   : val = d.getDate();  break;
276				case 'E'   : val = weekName[d.getDay()];  break;
277				case 'HH'  : val = d.getHours().padLeft(2, '0');  break;
278				case 'H'   : val = d.getHours();  break;
279				case 'hh'  : val = ((h = d.getHours() % 12) ? h : 12).padLeft(2, '0');  break;
280				case 'h'   : val = ((h = d.getHours() % 12) ? h : 12);  break;
281				case 'mm'  : val = d.getMinutes().padLeft(2, '0');  break;
282				case 'm'   : val = d.getMinutes();  break;
283				case 'ss'  : val = d.getSeconds().padLeft(2, '0');  break;
284				case 's'   : val = d.getSeconds();  break;
285				case 'a/p' : val = d.getHours() < 12 ? '오전' : '오후';  break;
286				default:
287			}
288
289			return val;
290		});
291	};
292
293	/**
294	 * 주어진 Date 객체를 주어진 형태로 포매팅하여 돌려 준다.
295	 * date 파라미터 값이 없으면 빈 문자열을 돌려주고,
296	 * 값이 있는데 Date 객체가 아닐 때는 그대로 돌려 준다.
297	 */
298	Date.format = function(date, format) {
299		if ( date == null ) return '';
300
301		return date.getFullYear ? date.format(format) : (date || '');
302	};
303}
304
305if ( ! Date.addYear ) {
306	/**
307	 * 주어진 Date 객체에 주어진 연수 만큼 더한 새로운 Date 객체를 돌려 준다.
308	 */
309	Date.addYear = function(date, number) {
310		return new Date((date.getFullYear() + number), date.getMonth(), date.getDate());
311	};
312}
313
314if ( ! Date.addMonth ) {
315	/**
316	 * 주어진 Date 객체에 주어진 개월 수 만큼 더한 새로운 Date 객체를 돌려 준다.
317	 */
318	Date.addMonth = function(date, number) {
319		return new Date(date.getFullYear(), (date.getMonth() + number), date.getDate());
320	};
321}
322
323if ( ! Date.addDate) {
324	/**
325	 * 주어진 Date 객체에 주어진 일수 만큼 더한 새로운 Date 객체를 돌려 준다.
326	 */
327	Date.addDate = function(date, number) {
328		return new Date(date.getFullYear(), date.getMonth(), (date.getDate()+number));
329	};
330}
331
332
333if ( ! Date.prototype.addMonth ) {
334	/**
335	 * Date 객체의 주어진 개월수 만큼 더한다.
336	 */
337	Date.prototype.addMonth = function(number) {
338		this.setFullYear(this.getFullYear(), this.getMonth() + number);
339
340		return this;
341	};
342}
343
344(function() {
345	var reOnlyNo1 = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/;
346	var reOnlyNo2 = /^(\d{4})(\d{2})(\d{2})$/;
347	var reISO = /^((\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}(?:\.\d*)))(?:Z|(\+|-)([\d|:]*))?$/;
348
349	if ( ! Date.converts ) {
350		/**
351		 * 입력받은 날짜정보 문자열을 Date 객체로 변환하여 돌려 준다.
352		 * 만일 문자열이 아니거나, 형식이 맞지 않으면 값을 그대로 돌려 준다.
353		 */
354		Date.converts = function(value) {
355			if ( ! value || typeof value !== 'string' ) return value;
356
357			var date = null;
358			var a = null;
359
360			if ( reISO.test(value) ) {
361				a = reISO.exec(value);
362				if (a) {
363					date = new Date(a[1]);
364				}
365			}
366			else if ( reOnlyNo1.test(value) ) {
367				a = reOnlyNo1.exec(value);
368				if (a) {
369					date = new Date(a[1], a[2] - 1, a[3], a[4], a[5], a[6]);
370				}
371			}
372			else if ( reOnlyNo2.test(value) ) {
373				a = reOnlyNo2.exec(value);
374				if (a) {
375					date = new Date(a[1], a[2] - 1, a[3]);
376				}
377			}
378
379			return date;
380		};
381	}
382})();
383
384if ( ! Date.isDate ) {
385	/**
386	 * 주어진 값이 Date 객체인지 여부를 돌려 준다.
387	 */
388	Date.isDate = function(value) {
389		if ( ! value ) return false;
390
391		return ! ! value.getFullYear;
392	};
393}
394
395
396if ( ! Date.prototype.compareTo ) {
397	Date.UNIT_YEAR  = 0;
398	Date.UNIT_MONTH = 1;
399	Date.UNIT_DATE  = 2;
400	Date.UNIT_HOUR  = 3;
401	Date.UNIT_MINUTE = 4;
402	Date.UNIT_SECOND = 5;
403	Date.UNIT_MILISECOND = 6;
404
405	Date.COMP_METHOD_ARR = [
406		'getFullYear'    ,
407		'getMonth'       ,
408		'getDate'        ,
409		'getHours'       ,
410		'getMinutes'     ,
411		'getSeconds'     ,
412		'getMilliseconds'
413	];
414
415	/**
416	 * 주어진 Date 객체와 비교하여 자신이 이르면 1을, 같으면 0을, 느리면 -1을
417	 * 돌려 준다. 단 파라미터에 따라 연, 월, 일, 시, 분, 초까지 비교한다.
418	 *
419	 * @param compared 비교 대상이 될 Date 객체.
420	 * @param unit 비교할 최소 단위. 없으면 밀리초까지 비교한다.
421	 */
422	Date.prototype.compareTo = function(compared, unit) {
423		if ( ! compared || ! compared['getFullYear'] ) {
424			throw '비교할 파라미터의 값으로 Date 객체가 아닌 값이 넘어왔습니다.';
425		}
426
427		if ( ! unit || unit < 0 || unit > 6 ) unit = Date.COMP_MILISECOND;
428
429
430		for (var i = 0; i < Date.COMP_METHOD_ARR.length; i++) {
431			var method = Date.COMP_METHOD_ARR[i];
432
433			// 같지 않을 때 판단.
434			if ( compared[method]() - this[method]() != 0 ) {
435				return compared[method]() - this[method]() > 0 ? 1 : -1;
436			}
437
438			// 같은데 현재 단위까지 비교라면 0
439			if ( i == unit ) return 0;
440		}
441
442		// 여기까지 왔으면 같은 값
443		return 0;
444	};
445}
446
447if ( ! Date.prototype.same ) {
448	/**
449	 * 이 Date 객체가 주어진 Date 객체와 주어진 단위까지 값이
450	 * 같은지 여부를 돌려 준다.
451	 */
452	Date.prototype.same = function(compared, unit) {
453		return this.compareTo(compared, unit) == 0;
454	};
455}
456
457if ( ! Date.prototype.before ) {
458	/**
459	 * 주어진 단위까지 비교했을 때, 이 Date 객체가 주어진 Date 객체의
460	 * 이전인지 여부를 돌려 준다.
461	 */
462	Date.prototype.before = function(compared, unit) {
463		return this.compareTo(compared, unit) > 0;
464	}
465}
466
467if ( ! Date.prototype.beforeOrSame ) {
468	/**
469	 * 주어진 단위까지 비교했을 때, 이 Date 객체가 주어진 Date 객체의
470	 * 이전이거나 같은지 여부를 돌려 준다.
471	 */
472	Date.prototype.beforeOrSame = function(compared, unit) {
473		return this.before(compared, unit) || this.same(compared, unit);
474	}
475}
476
477if ( ! Date.prototype.after ) {
478	/**
479	 * 주어진 단위까지 비교했을 때, 이 Date 객체가 주어진 Date 객체의
480	 * 이후인지 여부를 돌려 준다.
481	 */
482	Date.prototype.after = function(compared, unit) {
483		return this.compareTo(compared, unit) < 0;
484	}
485}
486
487if ( ! Date.prototype.sameOrAfter ) {
488	/**
489	 * 주어진 단위까지 비교했을 때, 이 Date 객체가 주어진 Date 객체의
490	 * 같거나 이후인지 여부를 돌려 준다.
491	 */
492	Date.prototype.sameOrAfter = function(compared, unit) {
493		return this.same(compared, unit) || this.after(compared, unit);
494	}
495}
496
497
498if ( ! Date.prototype.formatDiff ) {
499	Date.MS_PER_SECOND = 1000;
500	Date.MS_PER_MINUTE = 1000 * 60;
501	Date.MS_PER_HOUR   = 1000 * 60 * 60;
502	Date.MS_PER_DAY    = 1000 * 60 * 60 * 24;
503
504	/**
505	 * 자기와 주어진 Date 객체 사이의 시간차를 '?일 ?시간 ?분 ?초 ?ms' 형태의
506	 * 문자열로 돌려 준다.
507	 *
508	 * @param date 시간차를 구할 대상 Date 객체. 없으면 현재 시간을 담은 Date객체가 사용된다.
509	 * @param unitCh 어느 정도까지 구할 것인가 값(대소문자 구별).
510	 *                    밀리초('ms'), 초('s'), 분('m'), 시간('h'), 일('d'). 없거나 기타 값이면 초('s')까지 표현.
511	 * @returns 시간차를 표현하는 문자열.
512	 */
513	Date.prototype.formatDiff = function(date, unitCh) {
514		if ( typeof(date) === 'string' ) {
515			unitCh = date;
516			date = new Date();
517		}
518
519		date = date || new Date();
520		unitCh = unitCh || 's';
521
522		var unit = 2;
523		var suffix = '초';
524
525		switch (unitCh) {
526			case 'd'  : unit = 1; suffix = '일'; break;
527			case 'h'  : unit = 2; suffix = '시간'; break;
528			case 'm'  : unit = 3; suffix = '분'; break;
529			case 's'  : unit = 4; suffix = '초'; break;
530			case 'ms' : unit = 5; suffix = '밀리초'; break;
531		}
532
533		var intervalMs = Math.abs(this.getTime() - date.getTime());
534
535		var texts = [];
536
537		if ( unit >= 1 && intervalMs / Date.MS_PER_DAY >= 1) {
538			texts.push(Math.round(intervalMs / Date.MS_PER_DAY) + '일');
539			intervalMs = intervalMs % Date.MS_PER_DAY;
540		}
541
542		if ( unit >= 2 && (intervalMs / Date.MS_PER_HOUR >= 1 || texts.length > 0) ) {
543			texts.push(Math.round(intervalMs / Date.MS_PER_HOUR) + '시간');
544			intervalMs = intervalMs % Date.MS_PER_HOUR;
545		}
546
547		if ( unit >= 3 && (intervalMs / Date.MS_PER_MINUTE >= 1 || texts.length > 0) ) {
548			texts.push(Math.round(intervalMs / Date.MS_PER_MINUTE) + '분');
549			intervalMs = intervalMs % Date.MS_PER_MINUTE;
550		}
551
552		if ( unit >= 4 && (intervalMs / Date.MS_PER_SECOND >= 1 || texts.length > 0) ) {
553			texts.push(Math.round(intervalMs / Date.MS_PER_SECOND) + '초');
554			intervalMs = intervalMs % Date.MS_PER_SECOND;
555		}
556
557		if ( unit >= 5 && ( intervalMs >= 1 || texts.length > 0) ) {
558			texts.push(intervalMs + '밀리초');
559		}
560
561		/* 아무것도 없다면. */
562		if ( texts.length == 0 ) {
563			texts.push(0 + suffix);
564		}
565
566
567		return texts.join(' ');
568	}
569}
570
571
572(function() {
573	/**
574	 * JSON 값 중 일자(시간) 형식의 문자열(yyyy-MM-ddTHH:mm:ss.Z)을
575	 * Date 객체로 치환하는 처리를 하기 위해 원 JSON Parser를 Hooking 한다.
576	 */
577	if ( ! window.JSON || ! window.JSON.parse ) return;
578
579	var reISO = /^((\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)))(?:Z|(\+|-)([\d|:]*))?$/;
580	var reMsAjax = /^\/Date\((d|-|.*)\)[\/|\\]$/;
581
582	var _origParse = window.JSON.parse;
583
584	window.JSON.parse = function(text) {
585		return _origParse(text, function(key, value) {
586			var a;
587
588			if (typeof value === 'string'
589					&& value.length > 0
590					&& (reISO.test(value) || reMsAjax.test(value)) ) {
591				var a = reISO.exec(value);
592				if (a) {
593					var date = new Date(a[1]);
594
595					date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
596
597					return date;
598				}
599
600				a = reMsAjax.exec(value);
601				if (a) {
602					var b = a[1].split(/[-+,.]/);
603					return new Date(b[0] ? +b[0] : 0 - +b[1]);
604				}
605
606			}
607
608			return value;
609		});
610	};
611})();
612
613
614/**
615 * TextArea 입력폼에 현재 커서 위치에 삽입하기 함수 추가.
616 */
617if ( window.HTMLTextAreaElement != undefined && ! HTMLTextAreaElement.prototype.insertAtCaret ) {
618	HTMLTextAreaElement.prototype.insertAtCaret = function(value) {
619		if ( document.selection ) {
620		//IE support
621			this.focus();
622			sel = document.selection.createRange();
623			sel.text = value;
624		}
625		else if ( this.selectionStart || this.selectionStart == 0 ) {
626			// Chrome, Firefox, Netscape support
627			HTMLTextAreaElement.prototype.insertAtCaret = function(value) {
628				var startPos = this.selectionStart;
629				var endPos   = this.selectionEnd;
630
631				this.value = this.value.substring(0, startPos)
632						+ value
633						+ this.value.substring(endPos);
634			};
635		}
636		else {
637			this.value += value;
638		}
639	};
640}
641
642
643if ( ! window.gui ) {
644	window.gui = {};
645
646	/**
647	 * 윈도우를 주어진 좌표에 띄운다. 위치가 주어지지 않으면
648	 * 윈도우가 화면 가운데 오도록 띄운다.
649	 *
650	 * @param name 창 이름.
651	 * @param url 창에 사용할 주소.
652	 * @param width 창 너비. "full" 화면 꽉 찬 너비.
653	 * @param height 창 높이. "full" 화면 꽉 찬 높이. 값이 없으면 width 값과 동일.
654	 * @param option 기타 Option 문자열. window.open 메쏘드의 option 값으로 사용된다.
655	 * @param topPx 창의 상단을 기준으로 한 위치.
656	 * @param leftPx 창의 화면 왼쪽면을 기준으로 한 위치.
657	 */
658	window.gui.openWindow = function(name, url, width, height, option, topPx, leftPx) {
659		if ( ! height ) height = width;
660
661		if ( width  == 'full' ) width  = screen.availWidth;
662		if ( height == 'full' ) height = screen.availHeight;
663
664		width  = Math.min(width , screen.availWidth );
665		height = Math.min(height, screen.availHeight);
666
667		/* 창이 화면 가운데 위치하도록 하기 위해 left 위치 값 계산. */
668		if ( ! leftPx ) leftPx = ( screen.availWidth - width ) / 2;
669
670		/* 창이 화면 가운데에서 약간(?) 위에 위치하도록 하기 위해 top 위치 값 계산. */
671		if ( ! topPx  ) {
672			topPx  = ( screen.availHeight - height ) / 2;
673			topPx -= screen.availHeight * 0.02;
674		}
675
676
677		option = "width=" + width
678				+ ",height=" + height
679				+ ",top=" + topPx
680				+ ",left=" + leftPx
681				+ (option == undefined || option.length == 0 ? "" : "," + option);
682
683		name = name.replace(/-/g, '_');
684
685		var win = window.open(url, name, option);
686
687		if ( win ) win.focus();
688
689		return win;
690	}
691
692
693	/**
694	 * 대화 창을 띄운다.
695	 */
696	window.gui.openDialog = function(name, url, width, height, option) {
697		if ( ! option ) option = "";
698
699		option = (option.indexOf('alwaysRaised') > -1 ? '' : "alwaysRaised=yes")
700				+ (option.indexOf('dependent') > -1 ? '' : ",dependent=yes")
701				+ (option.indexOf('menubar') > -1 ? '' : ",menubar=no")
702				+ (option.indexOf('location') > -1 ? '' : ",location=no")
703				+ (option.indexOf('satatus') > -1 ? '' : ",satatus=no")
704				+ (option.indexOf('toolbar') > -1 ? '' : ",toolbar=no")
705				+ (option.indexOf('scrollbars') > -1 ? '' : ",scrollbars=yes")
706				+ (option.indexOf('resizable') > -1 ? '' : ",resizable=no")
707				+ "," + option;
708
709		return window.gui.openWindow(name, url, width, height, option);
710	}
711}
712
713(function($) {
714	$.fn.selectText = function() {
715		var doc = document;
716		var element = this[0];
717
718		if (doc.body.createTextRange) {
719			var range = document.body.createTextRange();
720			range.moveToElementText(element);
721			range.select();
722		} else if (window.getSelection) {
723			var selection = window.getSelection();
724			var range = document.createRange();
725			range.selectNodeContents(element);
726			selection.removeAllRanges();
727			selection.addRange(range);
728		}
729	};
730})(jQuery);
731
732function copyToClipboard(element, message) {
733	var tempInput = document.createElement('input');
734	var body = document.body;
735
736	body.appendChild(tempInput);
737
738	if ( element && element.appendChild ) {
739		tempInput.value = element.innerText;
740	}
741	else {
742		tempInput.value = element;
743	}
744
745	tempInput.select();
746
747	document.execCommand("copy");
748
749	body.removeChild(tempInput);
750
751	if ( message ) {
752		alert(message);
753	}
754}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.