新機能のタグを入力するサポートをします。
既に誰かが登録しているタグを、タグクラウドとして表示し、それをクリックするとテキストエリアにタグを書き出します。
指定したキーワードで、タグクラウドの表示を絞り込むことも出来ます。
タグ機能の運用が本格的になったら、公式機能として感想投稿のページにこんなの欲しいなー。
2011/05/09 PHPのsimilar_textのjavascript移植版を見つけたので、少し絞り込み条件を変更しました。
目的は、多少なりともタグの無駄な重複を軽減できるよう、もう少しアバウトな検索を実現する為です。
2011/05/11 絞り込みの際、数値を入力すると、その数値以上の登録数のタグに絞り込みます。
タグクラウド |
---|
|
select chr(60)||'style type='||chr(34)||'text/css'||chr(34)||chr(62) || 'table {' || ' width:97%;' || '}' || 'table, tr, th, td, .msg, .submsg {' || ' font-family: Meiryo UI, メイリオ, Arial, Helvetica, sans-serif;' || ' font-weight: bold;' || ' color: #ffffff !important;' || ' background: #99cc99 !important;' || ' border: none !important;' || ' -moz-border-radius: 8px;' || ' -webkit-border-radius: 8px;' || ' border-radius: 8px;' || ' margin-left:auto;' || ' margin-right:auto;' || ' line-height: 160%;' || '}' || '.submsg {' || ' background: #aaaaaa !important;' || '}' || '.tagcloud {' || ' font-size:90%;' || ' background:#ffffff;' || ' margin:2px;' || ' padding:4px;' || ' width:99%;' || ' min-height:100px;' || ' max-height:300px;' || ' height:auto;' || ' overflow:auto;' || ' float:left;' || ' -moz-border-radius: 8px;' || ' -webkit-border-radius: 8px;' || ' border-radius: 8px;' || ' line-height: 180% !important;' || '}' || '.selecttag {' || ' font-family: Meiryo UI, メイリオ, Arial, Helvetica, sans-serif;' || ' font-weight: bold;' || ' background:#ffffff;' || ' display: inline;' || ' position:relative;' || ' margin:-2px 1px;' || ' vertical-align:middle;' || ' border:1px dotted;' || ' cursor:pointer;' || ' opacity: 0.7;' || '}' || '.netabare {background:#fef033;}' || '.shinchaku {border:1px dashed #ea4355;}' || '.check {background:#a9fca9;}' || '.rank1 {font-size:150%;color:#00b800;z-index:90;padding: -1px 2px;top: 0px;}' || '.rank2 {font-size:135%;color:#00bf00;z-index:80;padding: -1px 2px;top: 0px;}' || '.rank3 {font-size:120%;color:#00c800;z-index:70;padding: 0px 2px;top: 0px;}' || '.rank4 {font-size:110%;color:#00cf00;z-index:60;padding: 0px 2px;top: 0px;}' || '.rank5 {font-size:100%;color:#00d800;z-index:50;padding: 0px 2px;top: 0px;}' || '.rank6 {font-size: 95%;color:#00df00;z-index:40;padding: 1px 3px;top:-1px;}' || '.rank7 {font-size: 90%;color:#00e800;z-index:30;padding: 1px 3px;top:-1px;}' || '.rank8 {font-size: 85%;color:#00ef00;z-index:20;padding: 1px 3px;top:-1px;}' || '.rank9 {font-size: 80%;color:#00f800;z-index:10;padding: 1px 3px;top:-1px;}' || '.normal {' || ' font-size: 100% !important;' || ' color:#00d800 !important;' || ' z-index:50 !important;' || ' padding: 0px 2px !important;' || ' top:0px !important;' || '}' || 'li.selecttag:hover {' || ' background:#b80000 !important;' || ' color:#ffffff !important;' || ' z-index:100 !important;' || '}' || chr(60)||'/style'||chr(62) || chr(60)||'form id='||chr(34)||'tag_support'||chr(34)||' class='||chr(34)||'tagcloud'||chr(34)||chr(62) || chr(60)||'span class='||chr(34)||'msg'||chr(34)||chr(62) || ' テキストエリア(最初と最後のスペースもコピーしてネ) ' || chr(60)||'/span'||chr(62) || chr(60)||'textarea style='||chr(34)||'width:98%;height:50px;'||chr(34)||' id='||chr(34)||'text'||chr(34)||chr(62) || chr(60)||'/textarea'||chr(62) || chr(60)||'br'||chr(62) || chr(60)||'span class='||chr(34)||'msg'||chr(34)||chr(62) || ' 絞り込み ' || chr(60)||'/span'||chr(62) || chr(60)||'input style='||chr(34)||'width:40%;'||chr(34)||' id='||chr(34)||'filter'||chr(34)||' onkeyup='||chr(34)||'tag_filter();'||chr(34)||' /'||chr(62) || chr(60)||'input type='||chr(34)||'button'||chr(34)||' onclick='||chr(34)||'tag_all();'||chr(34)||' value='||chr(34)||'全てのタグ'||chr(34)||' /'||chr(62) || chr(60)||'input type='||chr(34)||'button'||chr(34)||' onclick='||chr(34)||'tag_hanten();'||chr(34)||' value='||chr(34)||'強調反転'||chr(34)||' /'||chr(62) || chr(60)||'input type='||chr(34)||'button'||chr(34)||' onclick='||chr(34)||'tag_kyouchou();'||chr(34)||' value='||chr(34)||'強調切替'||chr(34)||' /'||chr(62) || chr(60)||'input type='||chr(34)||'button'||chr(34)||' onclick='||chr(34)||'tag_count();'||chr(34)||' value='||chr(34)||'登録数を表示'||chr(34)||' /'||chr(62) || chr(60)||'input type='||chr(34)||'button'||chr(34)||' onclick='||chr(34)||'tag_clear();'||chr(34)||' value='||chr(34)||'クリア'||chr(34)||' /'||chr(62) || chr(60)||'br'||chr(62) || ' ' || chr(60)||'span class='||chr(34)||'submsg'||chr(34)||chr(62) || ' ' || '文字列が似たタグに絞り込みます。数値を入力すると、タグの登録数で絞り込みます。' || chr(60)||'/span'||chr(62) || chr(60)||'br'||chr(62) || chr(60)||'span class='||chr(34)||'msg'||chr(34)||chr(62) || ' ' || chr(60)||'input type='||chr(34)||'checkbox'||chr(34)||' id='||chr(34)||'check_comment'||chr(34)||' /'||chr(62) || 'コメント追加用の『##』を自動的に付加する ' || chr(60)||'/span'||chr(62) || chr(60)||'span class='||chr(34)||'msg'||chr(34)||chr(62) || ' ' || chr(60)||'input type='||chr(34)||'checkbox'||chr(34)||' id='||chr(34)||'check_kaigyou'||chr(34)||' /'||chr(62) || 'タグをチェックする度に、改行する ' || chr(60)||'/span'||chr(62) || chr(60)||'br'||chr(62) || ' ' || chr(60)||'span class='||chr(34)||'selecttag rank5 netabare'||chr(34) || chr(62) || 'ネタバレ' || chr(60)||'/span'||chr(62) || ' ' || chr(60)||'span class='||chr(34)||'submsg'||chr(34)||chr(62) || ' ' || 'ネタバレタグは、こんな感じで表示されます。' || chr(60)||'/span'||chr(62) || ' ' || chr(60)||'span class='||chr(34)||'selecttag rank5 shinchaku'||chr(34) || chr(62) || '新着' || chr(60)||'/span'||chr(62) || ' ' || chr(60)||'span class='||chr(34)||'submsg'||chr(34)||chr(62) || ' ' || '新着タグ(3日以内に登録)は、こんな感じで表示されます。' || chr(60)||'/span'||chr(62) || chr(60)||'/form'||chr(62) || (select chr(60)||'ul class='||chr(34)||'tagcloud'||chr(34)||' id='||chr(34)||'tagcloud'||chr(34)||chr(62) || array_to_string(array_agg(tagcloud),'') || chr(60)||'/ul'||chr(62) from ( select chr(60) || 'li class='||chr(34)||'selecttag rank'||rank || coalesce((select case when netabare then ' netabare' else '' end || case when timestamp >= current_date - '3 days'::interval then ' shinchaku' else '' end from taglist as tl where tl.name = tagname limit 1), '') || chr(34) || ' title = '||chr(34)||'('||count||')'||chr(34) || ' onclick = '||chr(34)||'set_tag(this);'||chr(34) || chr(62) || tagname || chr(60)||'/li'||chr(62) as tagcloud from (select ntile(9) over (order by count(*) desc) as rank , count(*) as count , regexp_replace(tag, '^#{1}|#{2}.*$', '', 'g') as tagname from (select unnest( regexp_split_to_array(coalesce(' '||hitokoto||' ','')||coalesce(' '||regexp_replace(' '||memo||' ', '\(\r\n|\r|\n\)', ' ', 'g')||' ',''),' +') ) as tag from userreview where hitokoto ~ ' #' or memo ~ ' #' ) as foo where tag ~ '^#{1}' group by regexp_replace(tag, '^#{1}|#{2}.*$', '', 'g') ) as bar order by tagname ) as foobar ) || chr(60)||'script type='||chr(34)||'text/javascript'||chr(34)||chr(62) ||'var blank = '||chr(34)||chr(34)||';'||'\n' ||'var blank = '||chr(34)||chr(34)||';'||'\n' ||'/*@cc_on _d=document;eval('||chr(39)||'var document=_d'||chr(39)||')@*/'||'\n' ||'function set_tag(obj) {'||'\n' ||' var str = obj.innerHTML;'||'\n' ||' var txt = document.getElementById('||chr(34)||'text'||chr(34)||');'||'\n' ||' txt.focus();'||'\n' ||' var check_comment = document.getElementById('||chr(34)||'check_comment'||chr(34)||').checked;'||'\n' ||' var check_kaigyou = document.getElementById('||chr(34)||'check_kaigyou'||chr(34)||').checked;'||'\n' ||' if (obj.className.indexOf('||chr(34)||'check'||chr(34)||',0) == -1) {'||'\n' ||' if (check_comment) {str = str + '||chr(34)||'##'||chr(34)||';};'||'\n' ||' txt.innerHTML = txt.innerHTML + '||chr(34)||' #'||chr(34)||' + str.replace(/\\\([0-9]+\\\)$/, blank) + '||chr(34)||' '||chr(34)||';'||'\n' ||' txt.innerHTML = txt.innerHTML.replace(/[ {2,100}]/,'||chr(34)||' '||chr(34)||');'||'\n' ||' if (check_kaigyou) {txt.innerHTML = txt.innerHTML + String.fromCharCode(10)};'||'\n' ||' obj.className = obj.className + '||chr(34)||' check'||chr(34)||';'||'\n' ||' }'||'\n' ||'}'||'\n' ||'function tag_filter() {'||'\n' ||' var str = document.getElementById('||chr(34)||'filter'||chr(34)||').value;'||'\n' ||' var obj = document.getElementById('||chr(34)||'tagcloud'||chr(34)||').getElementsByTagName('||chr(34)||'li'||chr(34)||');'||'\n' ||' if ( isNaN(str) ) {'||'\n' ||' for (i=0;i<obj.length;i++) {'||'\n' ||' var pt = obj[i].innerHTML.length * 8;'||'\n' ||' if (pt >= 100 ) {pt = 100;}'||'\n' ||' if (similar_text(obj[i].innerHTML, str).percent >= pt || obj[i].innerHTML.indexOf(str, 0) >= 0 || str == blank) {'||'\n' ||' obj[i].style.display='||chr(34)||'inline'||chr(34)||';'||'\n' ||' } else {'||'\n' ||' obj[i].style.display='||chr(34)||'none'||chr(34)||';'||'\n' ||' }'||'\n' ||' }'||'\n' ||' } else {'||'\n' ||' for (i=0;i<obj.length;i++) {'||'\n' ||' if (eval(obj[i].title) >= str) {'||'\n' ||' obj[i].style.display='||chr(34)||'inline'||chr(34)||';'||'\n' ||' } else {'||'\n' ||' obj[i].style.display='||chr(34)||'none'||chr(34)||';'||'\n' ||' }'||'\n' ||' }'||'\n' ||' }'||'\n' ||'}'||'\n' ||'function tag_all() {'||'\n' ||' var obj = document.getElementById('||chr(34)||'tagcloud'||chr(34)||').getElementsByTagName('||chr(34)||'li'||chr(34)||');'||'\n' ||' for (i=0;i<obj.length;i++) {'||'\n' ||' obj[i].style.display='||chr(34)||'inline'||chr(34)||';'||'\n' ||' }'||'\n' ||'}'||'\n' ||'function tag_hanten() {'||'\n' ||' var obj = document.getElementById('||chr(34)||'tagcloud'||chr(34)||').getElementsByTagName('||chr(34)||'li'||chr(34)||');'||'\n' ||' for (i=0;i<obj.length;i++) {'||'\n' ||' var str = obj[i].className;'||'\n' ||' var chk = false;'||'\n' ||' for (j=1;j<10;j++) {'||'\n' ||' if(!chk) {'||'\n' ||' obj[i].className=obj[i].className.replace(j+blank,(10-j)+blank);'||'\n' ||' if(str !== obj[i].className) {chk = true};'||'\n' ||' }'||'\n' ||' }'||'\n' ||' }'||'\n' ||'}'||'\n' ||'function tag_kyouchou() {'||'\n' ||' var obj = document.getElementById('||chr(34)||'tagcloud'||chr(34)||').getElementsByTagName('||chr(34)||'li'||chr(34)||');'||'\n' ||' for (i=0;i<obj.length;i++) {'||'\n' ||' if (obj[i].className.indexOf('||chr(34)||' normal'||chr(34)||' , 0) == -1) {'||'\n' ||' obj[i].className=obj[i].className + '||chr(34)||' normal'||chr(34)||';'||'\n' ||' } else {'||'\n' ||' obj[i].className=obj[i].className.replace('||chr(34)||' normal'||chr(34)||',blank);'||'\n' ||' }'||'\n' ||' }'||'\n' ||'}'||'\n' ||'function tag_count() {'||'\n' ||' var obj = document.getElementById('||chr(34)||'tagcloud'||chr(34)||').getElementsByTagName('||chr(34)||'li'||chr(34)||');'||'\n' ||' for (i=0;i<obj.length;i++) {'||'\n' ||' if (obj[i].className.indexOf('||chr(34)||' count'||chr(34)||' , 0) == -1) {'||'\n' ||' obj[i].innerHTML = obj[i].innerHTML + obj[i].title;'||'\n' ||' obj[i].className=obj[i].className + '||chr(34)||' count'||chr(34)||';'||'\n' ||' } else {'||'\n' ||' obj[i].innerHTML = obj[i].innerHTML.substring(0,obj[i].innerHTML.length - obj[i].title.length);'||'\n' ||' obj[i].className=obj[i].className.replace('||chr(34)||' count'||chr(34)||',blank);'||'\n' ||' }'||'\n' ||' }'||'\n' ||'}'||'\n' ||'function tag_clear() {'||'\n' ||' var obj = document.getElementById('||chr(34)||'tagcloud'||chr(34)||').getElementsByTagName('||chr(34)||'li'||chr(34)||');'||'\n' ||' for (i=0;i<obj.length;i++) {'||'\n' ||' obj[i].style.display='||chr(34)||'inline'||chr(34)||';'||'\n' ||' obj[i].className=obj[i].className.replace('||chr(34)||' check'||chr(34)||',blank);'||'\n' ||' }'||'\n' ||' document.getElementById('||chr(34)||'text'||chr(34)||').innerHTML=blank;'||'\n' ||' document.getElementById('||chr(34)||'filter'||chr(34)||').value=blank;'||'\n' ||'}'||'\n' ||'function similar_text(text1, text2)'||'\n' ||'{'||'\n' ||' function similar_char(text1, len1, text2, len2)'||'\n' ||' {'||'\n' ||' function similar_str(text1, len1, text2, len2)'||'\n' ||' {'||'\n' ||' var pos1 = 0, pos2 = 0, max = 0, i, j, l;'||'\n' ||' for (i = 0; i < len1; ++i)'||'\n' ||' {'||'\n' ||' for (j = 0; j < len2; ++j)'||'\n' ||' {'||'\n' ||' for (l = 0; (i + l < len1)&&(j + l < len2)&&'||'\n' ||' (text1.charAt(i+l) == text2.charAt(j+l)); ++l);'||'\n' ||' if (l > max)'||'\n' ||' {'||'\n' ||' max = l;'||'\n' ||' pos1 = i;'||'\n' ||' pos2 = j;'||'\n' ||' }'||'\n' ||' }'||'\n' ||' }'||'\n' ||' return {'||'\n' ||' '||chr(39)||'pos1'||chr(39)||': pos1,'||'\n' ||' '||chr(39)||'pos2'||chr(39)||': pos2,'||'\n' ||' '||chr(39)||'max'||chr(39)||': max'||'\n' ||' };'||'\n' ||' }'||'\n' ||' var r = similar_str(text1, len1, text2, len2);'||'\n' ||' var sum = r.max;'||'\n' ||' if (sum)'||'\n' ||' {'||'\n' ||' if (r.pos1 && r.pos2)'||'\n' ||' {'||'\n' ||' sum += similar_char(text1, r.pos1, text2, r.pos2);'||'\n' ||' }'||'\n' ||' if((r.pos1 + r.max < len1)&&(r.pos2 + r.max < len2))'||'\n' ||' {'||'\n' ||' sum += similar_char('||'\n' ||' text1.substr(r.pos1 + r.max),'||'\n' ||' len1 - r.pos1 - r.max,'||'\n' ||' text2.substr(r.pos2 + r.max), '||'\n' ||' len2 - r.pos2 - r.max);'||'\n' ||' }'||'\n' ||' }'||'\n' ||' return sum;'||'\n' ||' }'||'\n' ||' var sim = similar_char(text1, text1.length, text2, text2.length);'||'\n' ||' return {'||'\n' ||' '||chr(39)||'similar'||chr(39)||': sim,'||'\n' ||' '||chr(39)||'percent'||chr(39)||': sim * 200.0 / (text1.length + text2.length)'||'\n' ||' };'||'\n' ||'}' || chr(60)||'/script'||chr(62) as タグクラウド