style が white-space:pre なブロック要素内で折り返すように JavaScript でハックするには

かなり限定的な話です。 スタイルシートの white-space 属性が pre 指定だと任意に改行が行われなくなるので、長い行が存在するとスクロールが入って見づらくなるのは、よく知られていると思います。 そんなときに JavaScript を適用して直して表示させる方法です。 .prestyle { white-space:pre; } となっていたときに下記のように load 時に修正します。 $(window).load(function() { $(".prestyle").each(function(){ var ctn = $(this).html(); ctn = ctn.replace(/^\\n|\\n$/g, "").replace(/\\n/g, "<br>"); $(this).html(ctn).css("white-space", "normal"); }); }); ※jQuery.js を使ってます。改行を br タグ に置き換えて white-space をノーマルに戻しています。Firefox だと前後に改行が入るようなので消しています。 IE だと中身に CR, LF が入っていても、white-space:pre や pre タグでないと innerHTML で取得するときは全てスペース化されてしまいます。 改行を活かしたいけど、HTML には手は付けられない。けれども CSS と JavaScript は付加できる。そんな場合に今回は有効な方法です。

2008年3月19日 · Toshimitsu Takahashi

「Suica 利用履歴から運賃を算出」ガジェットの UI をタブ仕様に変更

先日作った、Suica(スイカ)のガジェットだが、ユーザーインターフェイスが微妙だ。入出力のエリアを並べているので領域を広い。入力と出力が同時に見えている必要もないと思ったのでタブ化して分けてみた。それにタブ名をナビゲーションメッセージになったので、ちょっとわかりやすくなったかもしれない。 Google ガジェットでタブを使うには ModulePrefs で と使用を宣言。 1 2 3 4 5 <?xml version="1.0" encoding="utf-8"?> <Module> <ModulePrefs …> <Require feature="tabs" /> </ModulePrefs> 下記のようにタブのインスタンスを作って、addTab でタブのキャプションとそのタブの領域となる div タグの ID を引数に渡す。三番目の引数はタブが選択されたときのイベント関数を指定できる。chg の中で変換を走らせている。 1 2 3 var tabs = new _IG_Tabs(__MODULE_ID__); tabs.addTab("履歴を入力", "tabIn"); tabs.addTab("結果を表示", "tabOut", chg); タブ化すると、DOMツリーの構造が変わるため document.getElementById ではなく _gel(id) で取得する必要がある。 Content のソース 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 <script type="text/javascript"> <!-- String.prototype.trim = function() { return this.replace(/^\\s+|\\s+$/g, ''); }; String.prototype.getLines = function() { var lines = this.split("\\n"); for (var i=lines.length-1; i>=0; i--) { if (lines\[i\].trim().length == 0) { lines.splice(i, 1); } } return lines; }; function line2map(line) { var c = line.split(' '); if (c\[1\] == "物販") c\[2\] = c\[1\]; return { date: c\[0\], dept:c\[2\], arrv:c\[4\], acc: c\[5\].substr(1).replace(',',"") }; } function outtable(input) { try { var lines = input.getLines(); if (lines\[0\].indexOf('月/日') \> -1) lines.shift(); var i = lines.length - 1; var pre_acc = line2map(lines\[i\]).acc; var out = ""; while (--i >= 0) { if (lines\[i\].replace(' ',"").length == 0) continue; var item = line2map(lines\[i\]); if (item.dept.length > 0) { out += "<tr><td>" + item.date + "</td><td>" + item.dept + "</td><td>" out += item.arrv + "</td><td>" + (pre_acc - item.acc) + "</tr>"; } pre_acc = item.acc; } return '<table cellspacing="0" style="font-size:10.5pt" width="300">' + out + '</table>'; } catch(err) { return null; } } function chg(evt) { var textIn = _gel("textIn"); var ret = outtable(textIn.value); if (ret != null) _gel("textOut").innerHTML = ret; } function firstFocus(obj) { obj.value=''; obj.style.color='#000'; obj.onfocus = null; } //--> </script> <style type="text/css"> @import url(http://www.google.com/ig/tablib.css); </style> <div id="tabIn" style="height:135px;"> <textarea id="textIn" style="color:gray;font-size:10pt;width:100%;height:135px;overflow:scroll" onfocus="firstFocus(this)" onchange="chg()" >SF(電子マネー)利用履歴をペースト</textarea></td> </div> <div id="tabOut" style="height:135px;"> <div id="textOut" style="font-size:10.5pt;height:135px;padding:2px 0;overflow:scroll"></div> </div> <script> var tabs = new \_IG\_Tabs(\_\_MODULE\_ID__); tabs.addTab("履歴を入力", "tabIn"); tabs.addTab("結果を表示", "tabOut", chg); </script>

2008年1月14日 · Toshimitsu Takahashi

Google AJAX Feed API と jQuery でフィードをスライドショー表示するガジェットを作る

先日、オライリーの Amazon ベストセラートップ 10 のフィードを生成をした。それを今度はスライドショーっぽく表示するガジェットを作ってみる。 フィードの取得には、Google Feed API — Google Developers を使う。これで RSS/ATOM の規格に左右されないし、サーバーサイドの中継 CGI を作る必要もなくなる。 スライドショー表示はクロスフェードさせたい。Prototype + Rico より jQuery (http://jquery.com/) の方が簡単だと思うのでこちらを選択した。 Google AJAX Feed API まずは Sign-up for an API Key - Google Loader — Google Developers でアクセスキーを取得する。 Google.load はおまじない。1 はバージョンらしい。 <script type="text/javascript" src="http://www.google.com/jsapi?key=キー"></script> <script type="text/javascript"> google.load("feeds", "1"); Google.feeds.Feed(フィードのURL) で取得の準備。 setNumEntries はエントリをいくつ取るかを設定する(デフォルトは 4)。 load でコールバック関数を指定する。 Google.setOnLoadCallback(initialize); で初期化関数をロード時に実行するようにする。 取得したフィード情報は、result.feed で取れる。通常だと JSON で返る。 http://code.google.com/intl/ja/apis/ajaxfeeds/documentation/reference.html#JSON 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function initialize() { var feed = new google.feeds.Feed("http://feed.tilfin.net/amazon/oreilly-bestseller.xml"); feed.setNumEntries(10); feed.load(function(result) { if (!result.error) { var container = document.getElementById("container"); for (var i = 0; i < result.feed.entries.length; i++) { var entry = result.feed.entries\[i\]; var div = document.createElement("div"); div.innerHTML = '<a target="_blank" href="' + entry.link + '"><p>' + entry.title + '</p><div class="ctn">' + entry.content + '</div></a>'; div.className = 'page'; div.id = "page" + i; container.appendChild(div); if (i > 0) $("#page" + i).hide(); } pages = result.feed.entries.length; } }); } google.setOnLoadCallback(initialize); </script> まあ、サンプル見てわかるとおり、とても簡単。 ...

2008年1月13日 · Toshimitsu Takahashi

Suica 履歴の残額表示が使えないので、各運賃を算出するガジェットを作ってみた。

お勤めの人は会社で交通費の精算をやると思うんですね。 モバイル Suica を利用してるとネットでも JR東日本:モバイルSuica>会員メニュー 履歴を見られて便利なんですが、各乗車の運賃が出ないでその降車時の残額しか出ないのがいただけない。 ということで、SF利用履歴のページの表の部分をコピペするだけで運賃算出してくれる Google ガジェットを作ってみました。 ポイントと仕様 各項目のスペースは全角、区切りは半角なのでパースは楽。 この手のツールは対象の出力のしかたが変わってしまうと動かなくなるから寿命が短いかも。 先頭の列定義の行があっても無視するようにした。 キヨスク等での買い物分は出力し、チャージ分は出さないようにしている。 変換ボタンを押さなくても、テキストエリアからフォーカスが移ったときにコンバートするようにしている(textarea の onchange の動きがイマイチだったため)。 Content のソース 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 <script type="text/javascript"> <!-- String.prototype.trim = function() { return this.replace(/^\\s+|\\s+$/g, ''); }; String.prototype.getLines = function() { var lines = this.split("\\n"); for (var i=lines.length-1; i>=0; i--) { if (lines\[i\].trim().length == 0) { lines.splice(i, 1); } } return lines; }; function line2map(line) { var c = line.split(' '); if (c\[1\] == "物販") c\[2\] = c\[1\]; return { date: c\[0\], dept:c\[2\], arrv:c\[4\], acc: c\[5\].substr(1).replace(',',"") }; } function outtable(input) { try { var lines = input.getLines(); if (lines\[0\].indexOf('月/日') \> -1) lines.shift(); var i = lines.length - 1; var pre_acc = line2map(lines\[i\]).acc; var out = ""; while (--i >= 0) { if (lines\[i\].replace(' ',"").length == 0) continue; var item = line2map(lines\[i\]); if (item.dept.length > 0) { out += "<tr><td>" + item.date + "</td><td>" + item.dept + "</td><td>" out += item.arrv + "</td><td>" + (pre_acc - item.acc) + "</tr>"; } pre_acc = item.acc; } return '<table cellspacing="0" style="font-size:10.5pt" width="300">' + out + '</table>'; } catch(err) { return null; } } function chg(evt) { var textIn = document.getElementById('textIn'); var ret = outtable(textIn.value); if (ret != null) document.getElementById('textOut').innerHTML = ret; } function firstFocus(obj) { obj.value=''; obj.style.color='#000'; obj.onfocus = null; } //--> </script> <div id="content_div" style="border-bottom:2px solid #474;padding-top;3px;"> <table style="width:100%;" cellspacing="0"> <tr> <td><textarea id="textIn" style="float:left;color:gray;font-size:10pt;width:100%;height:75px" onfocus="firstFocus(this)" onchange="chg()" >SF(電子マネー)利用履歴をペースト</textarea></td> <td width="40"><button style="float:left;width:40px;height:75px;" onclick="chg()">変換</button></td> </tr> </table> <div id="textOut" style="border-top:2px solid #474;margin-top:3px;padding-top;3px;clear:left;height:108px;overflow:scroll"></div> </div>

2008年1月8日 · Toshimitsu Takahashi

IFRAME を使わずページをロードする(2)

今回は、jQuery を使ってみる。そしてロードしたコンテンツ内のリンクターゲットも自身にするサンプル。 Ajax Loading Test testA testB copyright testA.html, testB.html には body の innerHTML な部分しかないので、正式なHTMLファイルではない。

2007年6月3日 · Toshimitsu Takahashi