root/websites/twicli/twicli_s.html @ 39117

Revision 29674, 9.6 kB (checked in by NeoCat, 4 years ago)

動作していなかったので修正

  • Property svn:mime-type set to text/html; charset=UTF-8
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
2<html>
3<head>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5<meta name="viewport" content="width=device-width">
6<title>twicli</title>
7<style>
8body {background-color: transparent; margin: 1px; min-height: 500px;}
9#tw, #tw_p { font-size: small; }
10#tw div div, #tw_p div div { padding: 2px; }
11img { border: 0; }
12.status { text-decoration: none; color: black; cursor: pointer; }
13.date { color: #999; font-size: x-small; }
14.fromme { background-color: #cfc; }
15.tome { background-color: #ccf; }
16#loading {opacity: 0.5; position: absolute; left: 50px; top: 2px; width: 220px; height: 19; }
17#fst { position: absolute; left: 56px; top: 0px; width: 208px; }
18#rst { position: absolute; left: 264px; top: 6px; text-decoration: none; }
19.inreply { text-decoration: none; }
20#rep { display: none; background-color: #fee; position: absolute; width: 90%; left: 4%; top: 200px; border: #666 4px solid; }
21hr { margin: 0; padding: 0; }
22form { margin: 5px; }
23</style>
24<script>
25var myname = null;
26function twAuth(a) {
27        if (a.error) return alert(a.error);
28        myname = a.screen_name;
29}
30</script>
31<script src="http://twitter.com/account/verify_credentials.json?callback=twAuth"></script>
32</head>
33<body onLoad="init()">
34<iframe style="display:none;" name="tx"></iframe>
35<a href="http://twitter.com/home" target="twitter"><b><small>Twitter</small></b></a>
36<!--発言フォーム-->
37<form name="frm" action="http://twitter.com/statuses/update.xml" method="POST" onSubmit="return twSend();" target="tx">
38<small><input id="fst" type="text" name="status"><input type="hidden" name="source" value="twicli">
39<a id="rst" href="javascript:void(resetFrm())"><img src="clr.png"></a>
40</small><img id="loading" src="loading.gif"></form>
41<!--favフォーム-->
42<form name="favf" action="" method="POST" target="tx"></form>
43
44<div id="tw"><hr></div>
45<div id="rep"><a href="javascript:closeRep()" style="color: red;">[x]</a><p id="reps"><p></div>
46
47<script>
48var nr_limit = 50;                              // 表示する更新回数の上限
49
50var seq = (new Date).getTime();
51var since_id = false;
52var in_reply_to_user = false;
53var myname = false;
54var update_ele = false;
55var reply_ele = false;
56var rep_top = 0;
57var failover_timeout = false;
58// クロスドメインなJavaScriptを呼び出し
59function loadXDomainScript(url, ele) {
60        if (ele)
61                ele.parentNode.removeChild(ele);
62        ele = document.createElement("script");
63        ele.src = url;
64        document.body.appendChild(ele);
65        return ele;
66}
67// 要素の位置を取得
68function cumulativeOffset(ele) {
69        var top = 0, left = 0;
70        do {
71                top += ele.offsetTop  || 0;
72                left += ele.offsetLeft || 0;
73                ele = ele.offsetParent;
74        } while (ele);
75        return [left, top];
76}
77// ローディング表示ON、twit更新
78function reload(to) {
79        document.getElementById("loading").style.display = "block";
80        setTimeout("update()", to);
81}
82// 発言
83function twSend() {
84        if (document.frm.status.value == '') { // 空欄であればTimeline更新のみ
85                reload(0);
86                return false;
87        }
88        if (!document.frm.status.value.match("@"+in_reply_to_user)) // @ユーザが含まれているときのみ返信先を指定
89                setReplyId(false);
90        in_reply_to_user = "";
91        document.frm.status.select();
92        setTimeout(resetFrm, 10); // twit送信後にフォームをクリア
93        reload(3000); // 送信3秒後にTimelineを更新
94}
95// フォームの初期化
96function resetFrm() {
97        document.frm.reset();
98        setReplyId(false);
99}
100// reply先の設定/解除
101function setReplyId(id) {
102        var repid = document.getElementById('in_reply_to_status_id');
103        if (repid)
104                repid.parentNode.removeChild(repid);
105        if (id) {
106                repid = document.createElement('input');
107                repid.type = 'hidden';
108                repid.id = repid.name = 'in_reply_to_status_id';
109                repid.value = id;
110                document.frm.appendChild(repid)
111        }
112}
113// reply
114function replyTo(user, id) {
115        if (window.getSelection().toString() == '') {
116                in_reply_to_user = user;
117                document.frm.status.value += "@" + user + " ";
118                setReplyId(id);
119                document.frm.status.focus();
120        }
121}
122// reply先を表示
123function dispReply(id,ele) {
124        var d = document.getElementById(id);
125        if (!d) {
126                rep_top = cumulativeOffset(ele)[1] + 20;
127                reply_ele = loadXDomainScript('http://twitter.com/statuses/show/'+id+'.json?seq='+(seq++)+'&callback=dispReply2', reply_ele);
128                return;
129        }
130        closeRep();
131        var top = cumulativeOffset(d)[1];
132        var h = d.offsetHeight;
133        var sc_top = window.pageYOffset || document.body.scrollTop;
134        var win_h = window.innerHeight;
135        if (top < sc_top) scrollTo(0, top);
136        if (sc_top+win_h < top+h) scrollTo(0, top+h-win_h);
137        var old = d.style.backgroundColor;
138        d.style.backgroundColor = '#fcc';
139        setTimeout(function(){d.style.backgroundColor = old}, 2000);
140}
141// reply先をoverlay表示 (Timelineに無い場合)
142function dispReply2(tw) {
143        document.getElementById('reps').innerHTML = makeHTML(tw);
144        document.getElementById('rep').style.display = "block";
145        document.getElementById('rep').style.top = rep_top;
146}
147// replyのoverlay表示を閉じる
148function closeRep() {
149        document.getElementById('rep').style.display='none';
150}
151// 最新twitを取得
152function update() {
153        update_ele = loadXDomainScript('http://twitter.com/statuses/friends_timeline.json?seq=' + (seq++) +
154                                                                        '&callback=twShow&count=200' + (since_id ? '&since_id='+since_id : ''), update_ele);
155}
156// twitのHTML表現を生成
157function makeHTML(tw) {
158        function d2(dig) { return (dig>9?"":"0") + dig }
159        var d = new Date(tw.created_at);
160        d = d.getDate() + "日 " + d.getHours() + ":" + d2(d.getMinutes()) + ":" + d2(d.getSeconds());
161        //ユーザアイコン
162        return (tw.user.url ? '<a target="twitter" href="'+tw.user.url+'">' : '') +
163                '<img border="0" align="left" width="24" height="24" alt="' + tw.user.name +
164                        '" src="' + tw.user.profile_image_url + '">' + (tw.user.url ? '</a>' : '') +
165                //fav
166                '<img align="right" src="http://assets3.twitter.com/images/icon_star_'+(tw.favorited?'full':'empty')+'.gif" ' +
167                'onClick="fav(this,' + tw.id + ')">' +
168                //名前(Twitter本家のリンク)
169                '<a target="twitter" href="http://twitter.com/' + tw.user.screen_name + '">' + tw.user.screen_name +
170                 /*プロフィールの名前*/ (tw.user.name!=tw.user.screen_name ? '('+tw.user.name+')' : '') + '</a>' +
171                 /* protected? */ (tw.user.protected ? '<img src="http://assets0.twitter.com/images/icon_red_lock.gif">' : '') +
172                //本文クリックで@追加
173                " <span onClick=\"replyTo('" + tw.user.screen_name + "'," + tw.id + ")\" class=\"status\">" +
174                //本文 (https〜をリンクに置換 + @をtwitter本家へのリンクに置換)
175                tw.text.replace(/(https?:\/\/[^ ]*)/g, " <a onClick=\"event.stopPropagation();\" target=\"_blank\" href=\"$1\">$1</a>")
176                                .replace(/@([0-9A-Za-z_\-]+)/g, "<a onClick=\"event.stopPropagation();\" target=\"twitter\" " +
177                                                        "href=\"http://twitter.com/$1\">@$1</a>") + '</span>' +
178                //日付
179                '<span class="date">' + d + '</span>' +
180                //返信元へのリンク
181                (tw.in_reply_to_status_id ? ' <a class="inreply" href="#" onClick="dispReply('+tw.in_reply_to_status_id+',this);return false;">☞</a>' : '') +
182                '<br clear="left">';
183}
184// favoriteの追加(f=true)/削除(f=false)
185function fav(img, id) {
186        var f = img.src.match('empty');
187        document.favf.action = 'http://twitter.com/favourings/' + (f ? 'create' : 'destroy') + '/' + id + '.xml';
188        document.favf.submit();
189        img.src = 'http://assets3.twitter.com/images/icon_star_' + (f ? 'full' : 'empty') + '.gif';
190}
191// 受信twitを表示
192function twShow(tw) {
193        document.getElementById('loading').style.display='none';
194        if (failover_timeout) clearTimeout(failover_timeout);
195        failover_timeout = false;
196        var len = tw.length;
197        if (len == 0) return;
198        var twNode = document.getElementById('tw');
199        var pNode = document.createElement('div');
200        var dummy = pNode.appendChild(document.createElement('div'));
201        for (i = len-1; i >= 0; i--) {
202                if (since_id && since_id >= tw[i].id)
203                        continue;
204                if (tw[i].user.profile_image_url) {
205                        var s = document.createElement('div');
206                        s.id = tw[i].id;
207                        s.innerHTML = makeHTML(tw[i]);
208                        if (tw[i].text.match('@'+myname+' '))
209                                s.className = "tome";
210                        if (tw[i].user.screen_name == myname)
211                                s.className = "fromme";
212                        pNode.insertBefore(s, pNode.childNodes[0]);
213                        pNode.insertBefore(document.createElement('hr'), s);
214                }
215        }
216        pNode.removeChild(dummy);
217        twNode.insertBefore(pNode, twNode.childNodes[0]);
218        var maxH = pNode.clientHeight;
219        pNode.style.overflow = "hidden";
220        if ((window.pageYOffset || document.body.scrollTop) > 10)
221                scrollBy(0, maxH);
222        else
223                animate(pNode, maxH, (new Date).getTime());
224        while (twNode.childNodes.length > nr_limit)
225                twNode.removeChild(twNode.childNodes[nr_limit]);
226        since_id = tw[0].id;
227}
228// 新規twitの出現アニメーション処理
229function animate(elem, max, start) {
230        var t = (new Date).getTime();
231        if (start+1000 <= t)
232                return elem.style.maxHeight = 'none';
233        elem.style.maxHeight = Math.ceil(max*(1-Math.cos((t-start)/1000*Math.PI))/2);
234        setTimeout(function(){ animate(elem, max, start) }, 50);
235}
236function init() {
237        setTimeout(scrollTo, 0, 0, 1);
238        // 初回アップデート
239        setTimeout(update, 0);
240        setInterval(update, 60*1000);
241}
242
243// ホイールの回転でスクロール (スクロール不可のウィンドウ・フレーム内で有効)
244function wheel(event) {
245        var delta = 0;
246        if (!event) event = window.event;
247        if (event.wheelDelta) {
248                delta = event.wheelDelta/10;
249        } else if (event.detail)
250                delta = -event.detail;
251        if (navigator.userAgent.indexOf("Firefox") != -1)
252                delta *= 10;
253        if (delta)
254                scrollBy(0, -delta);
255        if (event.preventDefault)
256                event.preventDefault();
257        event.returnValue = false;
258}
259if (window.addEventListener) window.addEventListener('DOMMouseScroll', wheel, false);
260window.onmousewheel = document.onmousewheel = wheel;
261</script>
262</body>
263</html>
Note: See TracBrowser for help on using the browser.