Entry: ついったーのTLを60件に保つグリモンを作った
ついったーのTLを60件に保つグリモンを作った
ついったーのタイムラインが放っておくと超長くなってブラウザが重くなるので、タイムラインのサイズを一定に保つグリモンスクリプトを作った。60件より古いtweetをjQueryでremoveしている。内部的にデータがどうなってるのか分からないので効果は不明だけどDOMが減るので軽くなるだろうという憶測。
// ==UserScript== // @name tweetReduce // @namespace http://jamadam.com/ // @description Avoid Twitter Timeline size get too long // @include http://twitter.com/* // ==/UserScript== (function() { var $; var jversion = '1.2.6'; var jexist = (typeof unsafeWindow.jQuery != 'undefined'); var conflict = (jexist && unsafeWindow.jQuery.fn.jquery != jversion); // Add jQuery if not loaded if (! jexist || conflict) { var GM_JQ = document.createElement('script'); GM_JQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/' + jversion + '/jquery.js'; GM_JQ.type = 'text/javascript'; document.getElementsByTagName('body')[0].appendChild(GM_JQ); } GM_wait(); // Check if jQuery's loaded function GM_wait() { if (typeof unsafeWindow.jQuery == 'undefined' || unsafeWindow.jQuery.fn.jquery != jversion) { window.setTimeout(GM_wait,100); } else { if (conflict) { $ = unsafeWindow.jQuery.noConflict(true); } else { $ = unsafeWindow.jQuery; } letsJQuery(); } } // All your GM code must be inside this function function letsJQuery() { var topid = $('#timeline li').eq(0).attr('id'); window.setInterval(reduce, 5000); function reduce() { var newid = $('#timeline li').eq(0).attr('id'); if (topid != newid) { topid = newid; console.log($('#timeline li').length); while ($('#timeline li').length > 60) { $('#timeline li').eq(60).remove(); } } } } })();
Entry: commons markerの件数をgoogle検索結果に表示するグリモンをつくった
commons markerの件数をgoogle検索結果に表示するグリモンをつくった
[2010.01.15追記] 無駄な処理が多かったのでソースを少し整理した。
恥ずかしながら、commons markerというサービスを最近まで知らなかった。前々から出来たらいいなと思っていたことにすごく近いので使い始めてみた。
ところで、はてなブックマークのFirefoxアドオンはとても便利で、とくにGoogle検索の結果にブクマ件数が表示されるのは、クリックすべきリンクのアタリをつけるのに大変便利なのですが、同じ発想でcommons markerの件数も参考データとして意味があるかもしれないと思い、早速グリモンスクリプトで実現してみた。
googleResultWithMarker.user.jsをインストール

// ==UserScript== // @name googleResultWithMarker // @namespace http://jamadam.com/blog/ // @description googleResultWithMarker // @include http://*.google.co.jp/search* // ==/UserScript== (function() { var $; var jversion = '1.3.2'; var jexist = (typeof unsafeWindow.jQuery != 'undefined'); var conflict = (jexist && unsafeWindow.jQuery.fn.jquery != jversion); // Add jQuery if not loaded if (! jexist || conflict) { var GM_JQ = document.createElement('script'); GM_JQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/' + jversion + '/jquery.js'; GM_JQ.type = 'text/javascript'; document.getElementsByTagName('body')[0].appendChild(GM_JQ); } GM_wait(); // Check if jQuery's loaded function GM_wait() { if (typeof unsafeWindow.jQuery == 'undefined' || unsafeWindow.jQuery.fn.jquery != jversion) { window.setTimeout(GM_wait,100); } else { if (conflict) { $ = unsafeWindow.jQuery.noConflict(true); } else { $ = unsafeWindow.jQuery; } letsJQuery(); } } // All your GM code must be inside this function function letsJQuery() { var array = $('#res li.g'); var procExist = false; var i = 0; var loop = function() { if (i < array.length) { if (procExist) {return;} procExist = true; var href = array.eq(i).find('h3 a').attr("href"); var pos = array.eq(i).find('span.gl'); var url = encodeURIComponent(href); var jsurl = "http://commonsmarker.com/tools/latest_info?url=" + url; unsafeWindow["__jsonp__aD3jHjaf27mZQxt"] = function(a) { if (! a || ! a.marks || ! a.marks.length) { return; } $("<a>" + a.marks.length + " markers</a>") .attr('href', "http://commonsmarker.com/page/" + href) .css({ backgroundColor:"#f5d0d0", color:"#ff0000", fontFamily:"arial,sans-serif", fontWeight:"bold", marginLeft:"4px", padding:"1px", fontSize:"85%" }) .insertAfter(pos); } $.ajax({ type: "GET", url: jsurl, dataType: "script", complete: function() { i++; procExist = false; loop(); } }); } } loop(); } })();
commons markerの公式のインターフェースはまだ機能不足なため他のユーザーの動向がよく掴めなかったんだけど、こうしてスクリプトで簡単に件数を把握できるようにしてみて分かったことは、「全然利用されてない」ということでした。予想はしていたけど。
なお、commons markerはこの手の外部スクリプトへのインターフェースや仕様を一切公開していません。今回のスクリプトはとても強引な処理と憶測で実装しているので、サーバーの仕様が変わって動かなくなることが大いに予想されます。
Entry: グリモンでjQueryのコンフリクトを避けるテンプレート
グリモンでjQueryのコンフリクトを避けるテンプレート
昨日のつづき。
グリモンスクリプトでjQueryを使うとき、他のスクリプトでロードされたjQueryの別バージョンとのコンフリクトを避けるためのテンプレート。
(function() { var $; var jversion = '1.3'; var jexist = (typeof unsafeWindow.jQuery != 'undefined'); var conflict = (jexist && unsafeWindow.jQuery.fn.jquery != jversion); // Add jQuery if not loaded if (! jexist || conflict) { var GM_JQ = document.createElement('script'); GM_JQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/' + jversion + '/jquery.js'; GM_JQ.type = 'text/javascript'; document.getElementsByTagName('body')[0].appendChild(GM_JQ); } GM_wait(); // Check if jQuery's loaded function GM_wait() { if (typeof unsafeWindow.jQuery == 'undefined' || unsafeWindow.jQuery.fn.jquery != jversion) { window.setTimeout(GM_wait,100); } else { if (conflict) { $ = unsafeWindow.jQuery.noConflict(true); } else { $ = unsafeWindow.jQuery; } letsJQuery(); } } // All your GM code must be inside this function function letsJQuery() { } })();
a
Entry: グリモンでjQuery使ったらTwitterがバグった件が解決した
グリモンでjQuery使ったらTwitterがバグった件が解決した
Twitterの公式ページに適用するためのGreasemonkeyスクリプトにjQueryを使おうと思ったら、しばらくうまく行かなかった。原因は、TwitterページがすでにjQueryの旧バージョンをロードしていたというだけ。今回はたまたま自分のスクリプトがバージョンに依存しない内容だったので、if文でjQueryの存在確認をしてからロードすることで解決した。
(function() { // Add jQuery if not loaded if (typeof unsafeWindow.jQuery == 'undefined') { var GM_JQ = document.createElement('script'); GM_JQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js'; GM_JQ.type = 'text/javascript'; document.getElementsByTagName('body')[0].appendChild(GM_JQ); } // Check if jQuery's loaded function GM_wait() { if (typeof unsafeWindow.jQuery == 'undefined') { window.setTimeout(GM_wait,100); } else { jQuery = unsafeWindow.jQuery; letsJQuery(); } } GM_wait(); // All your GM code must be inside this function function letsJQuery() { } })();
Entry: text-overflow:ellipsis
text-overflow:ellipsis
以前にこんなエントリ書いたり、こんなjQueryプラグイン作ったりしたけど、それってCSSだけでできるんじゃん!
http://www5e.biglobe.ne.jp/~access_r/hp/css/css_text_019.html
text-overflow
テキストがオーバーフロー(領域を超えてしまう事)する際にオーバーフローしたテキストを「...」で省略することが出来ます。
しかも属性名と値などのキーワードも思い描いたまんまじゃん。ただし、省略記号を有効にする指定はtext-overflow: ellipsis;だ。以前にもちゃんとググったつもりだったけど、英語の情報無視してたかなあ。
ただしFirefoxは未対応なので依然としてJavascriptでのハックは必要。また、text-overflowはIEのみの対応のようで、SafariやOperaはそれぞれの拡張属性を併記して対応できる。
a.width-limited {
display:block;
overflow: hidden;
white-space:nowrap;
-webkit-text-overflow: ellipsis; // Safari
-o-text-overflow: ellipsis; // Opera
text-overflow: ellipsis; // IE
}
Entry: Javascriptオフ対策、その2
Javascriptオフ対策、その2
検索とタグクラウドもノースクリプトで利用できるようにした。ページナビゲーションはまだない。
JS用に用意した部品のDOMをNoscriptな人に見せないために、最初は<script></script>内に書けばいいのかと思ったら失敗。<script>タグは<noscript>タグのnotでは全然なかったのだ。考えたこともなかったけど、<script>タグ内にはスクリプトしか書いちゃいけない、とのこと。今さらながら。
スクリプト用のDOMはスクリプトで書くしかないのかと思い、document.writeの列挙が頭をよぎったものの、メンテナンス性に配慮してjQueryのappendだのprependだののDOM操作で何とかする。それでも、文字のエスケープの問題もあるし、本来HTMLで書くべきものをJavascriptで書き出すのはやはり手間がかかる。でもまあいいか。
と思っていたのが昨日の話で、今日、あっけない結論に達する。まあ、ここに書くまでもないことかも。
<div class="dom_for_script" style="display:none"></div> <script type="text/javascript"> //<![CDATA[ $(".dom_for_script").show(); //]]> </script>
Entry: jQueryでCtrl + 左クリック
jQueryでCtrl + 左クリック
ブログのリンクを、Ctrl + 左クリックのときはjavascriptで処理しないように変更した。event.metakeyでmacのコマンドキーにも対応。
$(selector).live('click', function(event) { // jQueryのliveメソッドと右クリックにまつわるバグを回避 if (event.which != undefined && event.which != 1) {return} // Ctrl+左クリックの場合はキャンセル if (event.metaKey) {return} // ここに目的の処理 });
Entry: ブックマーク
Entry: ブックマーク
ブックマーク
- Slide box - a jQuery Plug-in
- Twitterを楽しむ10の方法 (my ver)
- Command Center
- NTTドコモからiPhone 3Gへの絵文字送信が可能に--全キャリア間に対応
- 2万以上の“一目ぼれ”記録「ヒトメボ」2万ユーザー突破
一目ぼれのうち、0.6%が両思いという結果が出ている。
少ねー。しかも三角関係だったらいやだな。 - バリデーションルールをインラインでわかりやすく記述できるjQueryのプラグイ『validationEngine.js』
あらら、classにデータを書いちゃう? AJAX URLも埋め込んでもいいの?
Entry: AJAXデータの取得先URLをどう管理するかという話
AJAXデータの取得先URLをどう管理するかという話
AJAX満載のサイトでアンカーに紐づいたAJAXデータの取得先URLをどう管理するかという話。with jQuery1.3.2。
HTML
<a href="./path/to/parmalink.html">通常リンク</a> <a href="./path/to/snippet.html" class="widget-opener">動的コンテンツ</a>
Javascript
$('a.widget-opener').live('click', function () { $.get($(this).attr('href'), function(html){ //appendなりprependなり }); return false; });
上記の場合、javascriptオフの人が「動的コンテンツ」を叩くとHTMLスニペットやjsonテキストが画面いっぱいに広がるページに遷移してしまったりする。 また、検索クローラーはリンク先のページを収集してしまうかもしれない。
かといって、href="#"とでもして、すべてのアンカーにidをふって、script内でURLを関連づけていくのも煩雑だ。
HTML
<a id='id1' href="#" class="widget-opener">記事1</a> <a id='id2' href="#" class="widget-opener">記事2</a> <a id='id3' href="#" class="widget-opener">記事3</a>
Javascript
url.id1 = './path/to/snippet1.html'; url.id2 = './path/to/snippet2.html'; url.id3 = './path/to/snippet3.html';
そこで、アンカータグのonclickとjQueryの$.data()メソッドでAJAX URLをインラインで管理するようにしてみた。 $.data()はDOM要素に紐づいたデータを管理することが目的という、本件におあつらえ向きなメソッド。
HTML
<a href="#" class="widget-opener" onclick="$.data(this, 'ajaxURL', './ajax1.html')">記事1</a> <a href="#" class="widget-opener" onclick="$.data(this, 'ajaxURL', './ajax3.html')">記事2</a> <a href="#" class="widget-opener" onclick="$.data(this, 'ajaxURL', './ajax3.html')">記事3</a>
Javascript
$('a.widget-opener').live('click', function () { $.get($.data(this, 'ajaxURL'), function(html){ //appendなりprependなり }); return false; });
onclickとliveでバインドしたイベントとの実行順が気になったけど、意図した順番に実行されている。ここで念のためonmousedownとかに逃げてしまうと、 今度は.trigger()が使えなくなってしまうのでonclickしかない。実行順が覆るケースがあるようなら、click.not_inlineというようにnamespacedイベントを利用して onclickイベントとの実行順を制御することもできる。
また、パーマリンクが存在するアンカーであれば、当然hrefにそれをかける。
<a href='./parmalink1.html' class="widget-opener" onclick="$.data(this, 'ajaxURL', './ajax1.html')">記事</a>
こうすることで、新規タブでリンクを開く可能性に配慮した仕組みも実現できる。実際、このブログの「最近の記事」のボタンは左クリックで新規ウィジェットを起動するけど、コンテキストメニューから新規タブでパーマリンクを開くこともできる。そして、この2つのURLをひとつのアンカータグ内で管理している。
まあ、HTML内に書くのには$.data()はちょっとだけ汚らしいというのは認める。
Subscribe to my RSS feed