PageSourceSearch

https://www.pref.toyama.jp/shared/system/js/furigana/ysruby.js

js pref.toyama.jp collected 2026-10-01 10:31:29 UTC 12,218 bytes, 377 lines download raw bytes

1var YSRUBY = function() {
2	// +++++ DEFINE's ++++++++++ //
3	this.ysURI = "/cgi-bin/furigana/ysruby.cgi";
4	this.uiElement = "furigana";
5	// +++++ YS Parameters +++++ //
6	this.grade  = "1";				//1~8
7	this.target = "tmp_contents";	//対象範囲を示す要素のID属性値を指定
8	this.t_data = "contents";		//対象範囲のIDをdataで指定する場合のdata名
9	this.i_data = "ignore";			//対象範囲内でルビ振りしないIDをdataで指定する場合のdata名
10	this.c_data = "target";			//対象IDをdata名で指定(ignore使用時必須)
11	this.ruby   = true;				//RUBYタグを使用する場合はTRUE
12	this.rtxt_s = "(";				//ふりがな表記の開始カッコ
13	this.rtxt_e = ")";				//ふりがな表記の終了カッコ
14	this.surface_bk = 'surface_bk';
15	this.keep_attribute = ['alt', 'value', 'placeholder'];
16	if(document.body.className.indexOf("smartphone") != -1) {
17		this.ui_on   = 'ふりがな表示';		//uiElement置換文字:ルビ振実行
18		this.ui_off  = 'ふりがな解除';		//uiElement置換文字:元に戻す
19		this.ui_load = 'ふりがな表示';		//uiElement置換文字:取得中
20	} else {
21		this.ui_on   = 'ふりがな表示';		//uiElement置換文字:ルビ振実行
22		this.ui_off  = 'ふりがな解除';		//uiElement置換文字:元に戻す
23		this.ui_load = 'ふりがな表示';		//uiElement置換文字:取得中
24	}
25	// +++++ YSRUBY Datas ++++++++ //
26	this.params = new Object();
27	this.isIE;
28	this.ruby_data = [];
29	// +++++ YSRUBY Functions ++++++++ //
30	/**
31	 * 初期化
32	 */
33	this.init = function(){
34		var ua=navigator.userAgent;
35		var isOpera=Object.prototype.toString.call(window.opera)=='[object Opera]';
36		var Gecko = ua.indexOf('Gecko')>-1&&ua.indexOf('KHTML')===-1;
37		var IE = !!window.attachEvent&&!isOpera&&!Gecko;
38		if(IE)
39			this.ruby = false;
40		this.isIE = IE;
41	};
42	/**
43	 * RUBY付HTML作成
44	 */
45	this.createRuby = function(html,data){
46		var surface_bk = this.surface_bk;
47  		var pos = 0;
48  		var lastIdx = false;
49  		//解析処理
50		var data = JSON.stringify(this.ruby_data);
51		data = JSON.parse(data);
52  		for(var i=0;i<data.length;i++) {
53			if (data[i].surface == "") {
54				continue;
55			}
56			var ruby='';
57			if(data[i].subword) {
58				ruby = data[i].surface;
59				for(var j=0;j<data[i].subword.length;j++) {
60					if(data[i].subword[j].surface == data[i].subword[j].furigana) continue;
61					ruby = this.replaceAll(ruby, data[i].subword[j].surface, this.markupRuby(data[i].subword[j].surface, data[i].subword[j].furigana, this.rtxt_s, this.rtxt_e, this.ruby));
62				}
63			} else {
64				ruby = this.markupRuby(data[i].surface, data[i].furigana, this.rtxt_s, this.rtxt_e, this.ruby);
65			}
66			var npos = html.indexOf(data[i].surface, pos);
67			if(npos==-1) continue;
68			var current_surface = data[i].surface;
69			var reg = new RegExp("(<r[bt]>[^<>]*?)" + current_surface + "([^<>]*?<\/r[bt]>)", "gi");
70			while(reg.test(html)) {
71				html = html.replace(reg, '$1' + surface_bk + '$2');
72			}
73
74			if (html.match(new RegExp(current_surface))) {
75				data[i] = {surface: '', furigana: ''};
76			}
77			html = html.replace(new RegExp(current_surface), ruby);
78			
79			html = html.replace(new RegExp(surface_bk, "g"), current_surface);
80			lastIdx = i;
81		}
82
83		this.ruby_data = data;
84		//属性値対応*RUBYタグを除去
85		if(this.ruby) {
86			html = html.replace(/="[^"]*"/gi, function($0) {
87						return $0.replace(/<\/?[^>]*>/gi,'');
88			       });
89		}
90		else {
91			html = html.replace(/[a-zA-Z -\/:-@\[-\`\{-\~]/g, '');
92		}
93		return {html:html,idx:lastIdx};
94	};
95	/**
96	 * RUBYタグ作成
97	 */
98	this.markupRuby = function(t, r, ps, pe, f){
99		return '<ruby><rb>'+t+'</rb><rp>'+ps+'</rp><rt>'+r+'</rt><rp>'+pe+'</rp></ruby>';
100	};
101	/**
102	 * 置換
103	 */
104	this.replaceAll = function(e,s,r){
105		return e.split(s).join(r);
106	};
107};
108/**
109 * jQuery
110 */
111jQuery(function(){
112	var flag = {exec:false,lock:false};
113	var oldDOM = null;
114	var ysr = new YSRUBY();
115	ysr.init();
116	var conDOM = null;
117	var igIds = {use:false};
118	var html_single_tag_old = [];
119	var count_html_single_tag = 0;
120	/**
121	 * functions
122	 */
123	//無視要素かどうか調べる
124	var isIgnore = function(dom){
125		var id = dom.prop('id');
126		if(id !== void 0 && igIds[id] !== void 0){
127			return true;
128		}
129		return false;
130	};
131
132	var encode_html = function(html) {
133		var encodedStr = html.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
134		   return '&#'+i.charCodeAt(0)+';';
135		});
136		return encodedStr;
137	}
138
139	var decode_html = function(html) {
140		var decodedStr = html.replace(/&#\d+;/gm,function(s) {
141			return String.fromCharCode(s.match(/\d+/gm)[0]);
142		});
143		return decodedStr;
144	}
145
146	//子を持たない要素に対して置換え
147	var replaceDom = function(dom,data){
148		//IEの場合OPTIONの中身が消える?とりあえずルビ振り無効化
149		if(ysr.isIE && dom.nodeType != Node.TEXT_NODE && dom.get(0).tagName.toLowerCase() == 'option'){
150			return;
151		}
152
153		if (dom.nodeType == Node.TEXT_NODE) {
154			var ysrRuby = ysr.createRuby(dom.textContent, data),
155				newdom = jQuery('<span>' + ysrRuby.html + '</span>')[0];
156				
157			if (!jQuery(dom.parentNode).get(0).hasAttribute('data-backuptext')) {
158				jQuery(dom.parentNode).attr('data-backuptext', encode_html(dom.parentNode.innerHTML));
159			}
160			for (var count = 0; count < newdom.childNodes.length; count++) {
161				dom.parentNode.insertBefore(newdom.childNodes[count].cloneNode(true), dom);
162			}
163			dom.parentNode.removeChild(dom)
164		}
165		else {
166			var ysrRuby = '';
167			// tag html not have content. Ex: img, input type, ...
168			if (dom.get(0).innerHTML == '') {
169				if (dom.get(0).outerHTML.match(/="[^"]*"/gi)) {
170					html_single_tag_old.push({id: count_html_single_tag, dom: dom.clone(true)});
171					dom.attr('data-rubyidx', count_html_single_tag);
172					count_html_single_tag++;
173				}
174				ysrRuby = ysr.createRuby(dom.get(0).outerHTML, data);
175			}
176			else {
177				if (dom.get(0).tagName.toLowerCase() != 'rt') {
178					ysrRuby = ysr.createRuby(dom.get(0).innerHTML, data);
179				}
180			}
181		}
182
183		if (ysrRuby.idx !== false && dom.nodeType != Node.TEXT_NODE) {
184			// tag html not have content. Ex: img, input type, ...
185			if (dom.get(0).innerHTML == '') {
186				dom.get(0).outerHTML = ysrRuby.html;
187			}else{
188				if (dom.get(0).tagName.toLowerCase() != 'rt') {
189					dom.get(0).innerHTML = ysrRuby.html;
190				}
191			}
192		}
193	};
194	
195	//選択した要素の全ての子要素に置換えを行う
196	var allChild = function(t,data,flag_first_check){
197		// handle TEXT_NODE
198		if (flag_first_check) {
199			t.contents().filter(function () {
200				if (this.nodeType == Node.TEXT_NODE && this.textContent.replace(/\s/g, '') != '') {
201					replaceDom(this, data);
202				}
203			});
204		}
205	    var c = t.children();
206	    if(c.length!=0){
207	        c.each(function(){
208			var $this = jQuery(this);
209			var cc = $this.children();
210			if(!isIgnore($this)){
211				if(cc.length!=0){
212						for (var i = 0; i < $this[0].childNodes.length; i++) {
213							if ($this[0].childNodes[i].nodeType == Node.TEXT_NODE && $this[0].childNodes[i].textContent.replace(/\s/g, '') != '') {
214								replaceDom($this[0].childNodes[i], data);
215							}
216						}
217					allChild($this,data,false);
218				}else{
219					if($this.get(0).tagName.toLowerCase() != 'rb'){
220						replaceDom($this,data);
221					}
222				}
223			}
224	        });
225		}else{
226			replaceDom(c,data);
227		} 
228	};
229	
230//	var reloadJS = function(){
231//		var src_arr = ['/shared/js/setting.js', '/shared/js/function.js', '/shared/js/main.js', '/shared/js/init.js'];
232//		for(i = 0; i < src_arr.length; i++){
233//			var src = src_arr[i];
234//			var oldElement = jQuery('script[src="' + src + '"]');
235//			jQuery('<script>').attr('src', src).appendTo(oldElement);
236//		}
237//	}
238	
239	/**
240	 * main
241	 */
242	//var ignoreDOM = null;
243	//jQuery('#' + ysr.uiElement).text(ysr.ui_on);
244	jQuery('#' + ysr.uiElement).html(ysr.ui_on);
245	if (jQuery('body').hasClass('furigana_on')) {
246		jQuery('body').removeClass('furigana_on');
247	}
248	//uiElement Click
249	jQuery(document).on('click', '#' + ysr.uiElement, function(){
250		if(flag.lock)return;
251		flag.lock = true;
252		var conData = jQuery(this).data(ysr.t_data);
253		if(typeof conData !== 'undefined' && conData != ''){
254			conDOM = jQuery('#' + conData);
255		}else{
256			conDOM = jQuery('#' + ysr.target);
257		}
258		//JSを削除
259		conDOM.find('script').remove();
260		//作業領域にコンテキストをクローン
261		var cloneDOM = conDOM.clone(true);
262		
263		//無視する項目
264		var igData = jQuery(this).data(ysr.i_data);
265		if(typeof igData !== 'undefined' && igData != ''){
266			var ids = igData.split(',');
267			for(var igi in ids){
268				cloneDOM.find('#' + ids[igi]).html("");
269				igIds[ids[igi]] = true;
270			}
271		}
272		if(flag.exec){
273			//ルビ振り実行後にクリック
274			//jQuery(this).text(ysr.ui_on);
275			jQuery(this).html(ysr.ui_on);
276			if (jQuery('body').hasClass('furigana_on')) {
277				jQuery('body').removeClass('furigana_on');
278			}
279			// check browser
280			if (ysr.ruby) {
281				html_single_tag_old.map(function(item) {
282					var tag_name = conDOM.find('[data-rubyidx="'+ item.id +'"]').get(0).tagName.toLowerCase();
283
284					if (tag_name === 'input') {
285						conDOM.find('[data-rubyidx="'+ item.id +'"]').get(0).value = item.dom.get(0).value;
286					}
287					else  if (tag_name === 'img') {
288						conDOM.find('[data-rubyidx="'+ item.id +'"]').get(0).alt = item.dom.get(0).alt;
289					}
290					conDOM.find('[data-rubyidx="'+ item.id +'"]').removeAttr('data-rub
290yidx');
291				});
292
293				jQuery('rt,rp').remove();
294				jQuery('rb').contents().unwrap();
295				jQuery('ruby').contents().unwrap();
296
297				jQuery('[data-backuptext]').each(function() {
298					jQuery(this).html('').append(decode_html(jQuery(this).attr('data-backuptext')));
299					jQuery(this).removeAttr('data-backuptext')
300				});
301			}
302			else {
303				conDOM.replaceWith(oldDOM);
304			}
305			count_html_single_tag = 0;
306			html_single_tag_old = [];
307			flag.lock = flag.exec = false;
308			return;
309		}else{
310			oldDOM = conDOM.clone(true);
311			//jQuery(this).text(ysr.ui_load);
312			jQuery(this).html(ysr.ui_load);
313		}
314
315		// handle remove attributes of html not in array keep_attribute
316		cloneDOM.find('*').each(function() {
317			var attributes = this.attributes;
318			var i = attributes.length;
319			while( i-- ) {
320				var attr = attributes[i];
321				if( jQuery.inArray(attr.name, ysr.keep_attribute) == -1 )
322					this.removeAttributeNode(attr);
323			}
324		})
325		
326		var params = {
327				//制限されている為、半角英数記号を置換
328				context	: cloneDOM.html().replace(/[a-zA-Z -\/:-@\[-\`\{-\~]/g,' ').replace(/[\t\n\r\f]+/g,' '),
329				grade	: ysr.grade
330		};
331		var post = jQuery.post(ysr.ysURI,params,null,'json');
332		//Ajax(POST)
333		post.done(function(ret){
334			if (ret.ysruby && ret.ysruby[0]) {
335				var ret_ysruby = ret.ysruby[0];
336				if (ret_ysruby.error && ret_ysruby.error.message) {
337					alert(ret_ysruby.error.message);
338				}
339				else if (ret_ysruby.Error && ret_ysruby.Error.Message) {
340					alert(ret_ysruby.Error.Message);
341				}
342				else if (ret_ysruby.result.word) {
343					//成功時HTML書換(ルビ振り)
344					var data_ysruby = ret_ysruby.result.word.filter(function(item) {
345						return item.roman != undefined && item.furigana !== item.surface;
346					});
347					if(ret.dictionary.length) {
348						ret.dictionary.sort(function (a, b) {
349							return b.surface.length - a.surface.length;
350						});
351						data_ysruby = ret.dictionary.concat(data_ysruby);
352					}
353					ysr.ruby_data = data_ysruby;
354					
355					allChild(conDOM,data_ysruby, true);
356					
357					//jQuery('#' + ysr.uiElement).text(ysr.ui_off);
358					jQuery('#' + ysr.uiElement).html(ysr.ui_off);
359					flag.exec = true;
360					flag.lock = false;
361					if (!jQuery('body').hasClass('furigana_on')) {
362						jQuery('body').addClass('furigana_on');
363					}
364					//reloadJS();
365				}
366				else {
367					alert("APIエラーが発生しました。");
368				}
369			}
370			else {
371				alert("APIエラーが発生しました。");
372			}
373		}).fail(function(jqXHR, textStatus, errorThrown){
374			alert("通信エラーが発生しました。");
375		});
376	});
377});

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.