「URI」を含む日記 RSS

はてなキーワード: URIとは

2007-10-31

生け垣オートマトン

ネーミングセンスが好きだ。

英語だと、hedge automataだ。

RELAX NGというXMLスキーマ数学的な基礎らしい。

通常のオートマトンが文字列を扱うのに対して、

生け垣オートマトンは生け垣を扱う。

ここで、生け垣は順序木の順序列のことだ。

すごい理論としておもしろいので勉強中だ。

これを勉強した後と前では、RSSSOAP等のXMLの応用に対する見方も変わるかもしれない。

みんなも、下記URIをぜひ読んでみよう。

参考URI

2007-10-24

XFrames

XFramesは従来のHTMLフレームに置き換わる概念らしい。

http://www.w3.org/TR/xframes/

なかなか、日本語情報が見つからない。

分かったのは、#frames(id1=uri1,id2=uri2,...)の形でframeを直接URIで指定することぐらいだ。

英語勉強しなきゃなあ。

実際に、応用するとしてどういうことが考えられるだろうか?

2007-09-09

無断リンクをいやがる心理

・さきほども書いてあったが、はてブネガティブコメントを避けたい。

トップページから見てもらう順序を想定してコンテンツを作成してある。

トップページアクセス解析置いてるから、トップページに来てほしい。逆に、自分のページ見てる人の正確な人数が把握されないからトップページ以外は無断リンクされたくない。

・あるWebページから、自分のページにリンクが貼ってあるということで嫌な文脈が出来るのを避けるため。(例 2ch誹謗中傷コメントの中に、自分のWebページのURI

こんな感じですかね。

2007-09-02

[][][Web::Scraper][API][JSON][JavaScript]Web::Scraperを使ってみたくてニフティクリップJSONを作ってみた

最近perl勉強してて、naoyaのはてなダイアリー - Web::ScraperWeb::Scraperを知り、試しにはてブのAPIを真似してニフティクリップコメントを吐くJSONを作った。

#!/usr/local/bin/perl -T
#
#
use strict;
use warnings;

use URI;
use Web::Scraper;
use JSON::XS;
use CGI;
use Encode;

my $q = new CGI;
print $q->header( -type=>'text/plain', -charset=>'UTF-8');

my $path_info = $q->path_info;
my $path = $path_info =~ m{^/?(nobracket/)?(http\w?)://?(.*)$}xms ? $2.'://'.$3
         :                                                          undef
         ;
exit if ! $path;
my $is_nobracket = 'true' if $1;

if ($q->query_string) {
    my $query_string = $q->query_string;
    $query_string =~ s/;/&/g;
    $path = $path.'?'.$query_string
}

$path =~ s/%23/#/;

$path =~ s/([^\w ])/'%' . unpack('H2', $1)/eg;
$path =~ tr/ /+/;

my $entry_url = "http://clip.nifty.com/entry/?url=" . $path;

my $bookmarks = scraper {
    process 'h4>a', 'user' => 'TEXT';
    process 'li.dateAndTime', 'timestamp' => 'TEXT';
    process 'a.tagtag', 'tags[]' => sub {
        my $text = $_->as_text or return;
        my $left = decode_utf8('??~P');
        my $right = decode_utf8('??~Q');
        return $text =~ /$left (.*?) $right/xms;
    };
    process 'p.comment', 'comment' => 'TEXT';
    result 'user', 'timestamp', 'tags', 'comment';
};

my $niftyclip_entry_info = scraper {
    process 'div.clipTitle>h3>a', 'title' => 'TEXT';
    process 'div.clipTitle>p.url>a', 'url' => '@href';
    process 'div.comments>div.commentsDetails',
        'bookmarks[]' => $bookmarks;
    result 'title','url','bookmarks';
};

my $niftyclip = scraper {
    process 'div#content',
        'niftyclip_entry' => $niftyclip_entry_info;
    result 'niftyclip_entry';
}->scrape(URI->new($entry_url));

exit if ! ($niftyclip->{'url'});

$niftyclip->{'entry_url'} = $entry_url;
$niftyclip->{'count'} = @{$niftyclip->{'bookmarks'}};

my $json = JSON::XS->new->utf8->encode($niftyclip);

$json = '('. $json. ')' if ! $is_nobracket;
print $json;

取得方法は

http://monm.on.coocan.jp/niftyclip/json/entry/<取得したいURL

ってすればいい。「#」は「%23」にエスケープしないとダメ

ニフティクリップのトップならこんな感じ

作りながら「取得したいURLURLエンコードするのは面倒だな」って思い、はてブAPIみたいにpath_infoでアクセスできるようにしたわけだけど、その取得したいURLquery_stringが付いてた場合にどうやってやって良いかわからず結構悩んだ。

結局、path_info+'&'+query_stringってやることで無理やり作ったけど、普通どうやるもんなんだろ?cpanに何か良いモジュールがあったりするのかな。

それと、はてブに合わせて出力の際に()を付けるようにしたけど、これだとYahoo!Pipesで使えなかったから、

http://monm.on.coocan.jp/niftyclip/json/entry/nobracket/<取得したいURL

みたいに「nobracket」付きでアクセスした場合には()を付けないようにした。

コレ使うとニフティクリップとlivedoor クリプのコメント取ってくるAPIみたいなのが作れる。

RSSで取得する場合は

http://pipes.yahoo.com/pipes/pipe.run?_id=zECBJ_VY3BGtBw6B8ivLAg&_render=rss&URL=URLエンコードしたURL

で取得できるし、jsonで取得する場合は

http://pipes.yahoo.com/pipes/pipe.run?_id=zECBJ_VY3BGtBw6B8ivLAg&_render=json&URL=URLエンコードしたURL

ってなる。

こんな感じ

とりあえずサクッと作ってみたけど、わざわざページからJSON作ってるからちょっと重い。

デザインリニューアルされたら使えなくなるし。

その頃にはJSON吐いてくれるようになるんじゃないかなと期待はしてるけど。

参考URL:

http://d.hatena.ne.jp/naoya/20070509/1178686816

http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%C3%A5%AF%A5%DE%A1%BC%A5%AF%A5%A8%A5%F3%A5%C8%A5%EA%A1%BC%BE%F0%CA%F3%BC%E8%C6%C0API?kid=184075

2007-08-21

X-REPROXY-CACHE-CLEAR もあわせて使いたい人向けショート BK

■X-Reproxy-Cache-Clear できる Perlbal プラグインCommentsAdd Star

■[Perl][CPAN][Perlbal] X-REPROXY-CACHE-FORを使いたい人向けショートBK

X-REPROXY-CACHE-FOR ヘッダが Perlbal に(というか Perlbal::Cache に)どのように解釈されるかというと、

Perlbal::Service.pm

1467 sub add_to_reproxy_url_cache {

1468 my Perlbal::Service $self;

1469 my ($reqhd, $reshd);

1470

1471 ($self, $reqhd, $reshd) = @_;

1472

(snip)

1484 my $hostname = $reqhd->header("Host") || '';

1485 my $requri = $reqhd->request_uri || '';

1486 my $key = "$hostname|$requri";

1487

(snip)

1496 $cache->set($key, [$timeout, \@headers, $urls]);

1497 }

こうなってる。ここで、

Perlbal -> mod_perl -> MogileFS

こんな風に、フロントPerlbal, バックエンドに mod_perl ハンドラでも置いて、その裏の MogileFSやりとり(をあんまさせたくないので Perlbal に直にキャッシュさせたい)という構成を考える。

この場合、

つまり、

X-REPROXY-CACHE-CLEAR: /artwork/12345

というヘッダを mod_perl から Perlbal に返す必要がある(host は補われる)

この /artwork/12345 というリクエスト URL は、 mod_perl 側から直に参照できない。

mod_perl ハンドラを例えば以下のような conf であてていたとすると、

<Location /example/artwork>

SetHandler perl-script

PerlHandler Example::Artwork

</Location>

RewriteEngine On

RewriteRule ^/artwork/(.*) http://127.0.0.1:8080/example/artwork/$1 [P,L]

ここで $r->uri をとると /example/artwork/12345 となり、これをそのまま X-REPROXY-CACHE-CLEAR で返しても Perlbal::Cacheキャッシュした key とは違うものなのでキャッシュを破棄できない。自前で $r->uri を split なりして、 /artwork/12345 を、 Rewrite される前の URL を知る必要がある。当然、どんな RewriteRule かに依存するので一般的な実装はあげられない。 Rewrite しなければもう少し話が簡単になる。

要は、

と、それぞれ意味の違った URL (key になるもの)がいくつか存在して、どれがどれやらわからなくなってしまうので、ハマりどころが多い。ありがちな(というか俺がやった)ミスとしては、 CACHE-FOR でキャッシュした状態で MogileFS からファイル実体を消してしまうと (mogile に突っ込むときkey はまた別に digest とかで作ってあったりすると余計に混乱することうけあい) Mogile にはもう存在せず、したがって mod_perl にはどうしたって知りようがない URLPerlbalキャッシュしていて 503 を返しつづける、という状態になってしまう。それから、キャッシュを自発的に消したいときというのはもともとキャッシュしてた URL (Mogile 上でのファイルのありか)が指し示すファイル実体を消したいときなので(実体がないものをいつまでもキャッシュしているのは困る、という理由)当然実体そのものも消すわけだが、

こういう手順でつくらないといけない。この URLACL を厳重にしておかないと、全ての artwork に対応するキャッシュ破棄用(つまりファイル削除用) URL を GET されまくってファイルを消されまくってしまうので非常にまずい。

我ながら乱雑で要領を得ない文章だと思うけど、こんなものでもないよりはあったほうがこれから同じことをやろうとする人にとっては多少の助けになると思うので走り書きのままで公開する。こういう、どっかに一言書いてあれば5秒でぐぐって済むことを何時間もかけてやり直すのは人類にとっての時間的損失でばからしいので、適当に間違ってるところとかを修正しつついろんなブログとかに転載しまくって世に広めてください。

2007-08-12

マークアップエンジニアって結局何やる人なの?

何か名前の響きからしてこんな感じの人を想像してたんだけど

でもいままでamachang発言((X)HTML+CSS しか出来ない人は真剣に第二の何かを探したほうがいいとか)の反応ざっと見てきたけどid:amachang(とその周辺)が「マークアップエンジニア = (X)HTML+CSS しか出来ない人」として話を進めてるのにも関わらずそれについて反論があんまりないんだよな。「趣味じゃなくて仕事として(X)HTML(とCSS)を作成するためにはこれこれこういう知識が必要なんだよ」とか「マークアップエンジニアには(X)HTMLCSSしかすることがないとでも思ってんのか馬鹿」とか言ったりするのかと思ったらほとんどそんなことなくて、むしろ同意ですとかそんなこと言われなくてもわかってるよとかJavaScriptだって同じじゃんとか見た感じそんなのばっかり。どうも俺の想像した職業とは違うらしい。

マークアップエンジニアって本当に(X)HTMLCSSの知識だけで(X)HTMLCSS書いてる人なの?反応見ててそもそも(X)HTMLCSSに理解があるのかってこと自体にまで疑問を感じるんだけど。

2007-08-08

http://anond.hatelabo.jp/20070808015717

URLURNも全部まとめてURIと言って問題なし。

というのがW3Cの公式見解だったような。

http://anond.hatelabo.jp/20070808015121

セリフの詳細が分からないけど、文章から予想するにURIでも間違って無さそうな気がする。

厳密な話からはずれるんだろうけど、URLURIの使われ方って結構曖昧に使われることが多いからあんまり気にしなくてもいいかなと思ってる。

URIでいいよね?

http://serif.hatelabo.jp/bc8f7f7cc511e49477ac52273262f506da1a03fa/6185013b8cff98399c4616671c794bc6dfe54f38

URIって識別子という大枠の中に、具体的なリソースロケーションを示す用途のURL名前空間みたいなので使うURNがあって、

それを国際化したものがIRIって事でOK?

はてなセリフへはコメントとかトラックバックってないんですよね?

2007-07-30

増田終わっただって

http://anond.hatelabo.jp/20070729073243

何が酷いのかをはっきり明示してくれないと困るな。僕は見てるだけ。

誰かと陰で笑いあってるわけでもない。何処かにURIを貼り付けて「こいつ痛いだろ酷いだろ皆でヲチろうぜ」とか言ってる訳じゃない。ただ読んで、笑ってるだけ。酷いかな? どこぞの掲示板で突撃かまして喜んでる連中よりは、少しはマシなつもりだけどね。だって、消えたら(消されたら)困る。楽しみが減ってしまう。

あと、僕のエントリひとつだけとって、増田終わったとか言うのは他の方に失礼だと思うよ。

2007-07-27

http://anond.hatelabo.jp/20070727011007

ああ、それそれ。って休止してるし。

見直してみたらURI自体は固定なのね。

完全にランダムってのはそんなに面白くないよなーと思う今日この頃

相当違うけど、なんかちょっと繋がってる、ってくらいがたぶん面白い。

この匙加減を実現できたらtoropyクローンも日の目を見るかもね。

2007-07-23

ヲチ対象の話

プライバシー保護のため一部文章に真実とは情報が含まれております、ご了承ください

元々は普通日記を見ていたんだけど、ある時期を境に急に日記が痛くなってきたので、ヲチをはじめた。

同じ事を思った人はいるらしく、その人の話題がちらほらと叩きスレに出るようになってきた。

嫌気がさしたらしいヲチ対象は日記を閉鎖、結局名前とプロフを変えて別の場所で再開することにしたようだ。

僕はいつものように、閉鎖を惜しむ文章と、励ましと、そして新しい日記URIの問い合わせのメールを送った。

ヲチ対象は、感謝言葉とともに日記URIを教えてくれた。何も知らないで。

僕は何もしなかった。ただ、日増しに痛々しくなってゆく日記を、ただ読んでいた。

僕は何もしていない。該当スレに燃料も投下していない。

ただ、読んでいるだけだ。

mixiでも、Twitterでも、恨み言のような文章を綴っているヲチ対象。

僕はただそれを読むだけだ。

貴方は少し目立ちすぎた。それだけだ。貴方程度の痛さの人間なら沢山いる。何も貴方でなくても良いんだ。

僕は何もしていない。

スレに燃料を投下しているのは、あなた自身だ。

2007-07-19

/* Ten */
if (typeof(Ten) == 'undefined') {
    Ten = {};
}
Ten.NAME = 'Ten';
Ten.VERSION = 0.06;

/* Ten.Class */
Ten.Class = function(klass, prototype) {
    if (klass && klass.initialize) {
	var c = klass.initialize;
    } else if(klass && klass.base) {
        var c = function() { return klass.base[0].apply(this, arguments) };
    } else {
	var c = function() {};
    }
    c.prototype = prototype || {};
    c.prototype.constructor = c;
    Ten.Class.inherit(c, klass);
    if (klass && klass.base) {
        for (var i = 0;  i < klass.base.length; i++) {
	    var parent = klass.base[i];
            if (i == 0) {
                c.SUPER = parent;
                c.prototype.SUPER = parent.prototype;
            }
            Ten.Class.inherit(c, parent);
            Ten.Class.inherit(c.prototype, parent.prototype);
        }
    }
    return c;
}
Ten.Class.inherit = function(child,parent) {
    for (var prop in parent) {
        if (typeof(child[prop]) != 'undefined' || prop == 'initialize') continue;
        child[prop] = parent[prop];
    }
}

/*
// Basic Ten Classes
**/

/* Ten.JSONP */
Ten.JSONP = new Ten.Class({
    initialize: function(uri,obj,method) {
        if (Ten.JSONP.Callbacks.length) {
            setTimeout(function() {new Ten.JSONP(uri,obj,method)}, 500);
            return;
        }
        var del = uri.match(/\?/) ? '&' : '?';
        uri += del + 'callback=Ten.JSONP.callback';
        if (!uri.match(/timestamp=/)) {
            uri += '&' + encodeURI(new Date());
        }
        if (obj && method) Ten.JSONP.addCallback(obj,method);
        this.script = document.createElement('script');
        this.script.src = uri;
        this.script.type = 'text/javascript';
        document.getElementsByTagName('head')[0].appendChild(this.script);
    },
    addCallback: function(obj,method) {
        Ten.JSONP.Callbacks.push({object: obj, method: method});
    },
    callback: function(args) {
        // alert('callback called');
        var cbs = Ten.JSONP.Callbacks;
        for (var i = 0; i < cbs.length; i++) {
            var cb = cbs[i];
            cb.object[cb.method].call(cb.object, args);
        }
        Ten.JSONP.Callbacks = [];
    },
    MaxBytes: 8000,
    Callbacks: []
});

/* Ten.XHR */
Ten.XHR = new Ten.Class({
    initialize: function(uri,opts,obj,method) {
        if (!uri) return;
        this.request = Ten.XHR.getXMLHttpRequest();
        this.callback = {object: obj, method: method};
        var xhr = this;
        var prc = this.processReqChange;
        this.request.onreadystatechange = function() {
            prc.apply(xhr, arguments);
        }
        var method = opts.method || 'GET';
        this.request.open(method, uri, true);
        if (method == 'POST') {
            this.request.setRequestHeader('Content-Type',
                                          'application/x-www-form-urlencoded');
        }
        var data = opts.data ? Ten.XHR.makePostData(opts.data) : null;
        this.request.send(data);
    },
    getXMLHttpRequest: function() {
        var xhr;
        var tryThese = [
            function () { return new XMLHttpRequest(); },
            function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
            function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
            function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
        ];
        for (var i = 0; i < tryThese.length; i++) {
            var func = tryThese[i];
            try {
                xhr = func;
                return func();
            } catch (e) {
                //alert(e);
            }
        }
        return xhr;
    },
    makePostData: function(data) {
        var pairs = [];
        var regexp = /%20/g;
        for (var k in data) {
            var v = data[k].toString();
            var pair = encodeURIComponent(k).replace(regexp,'+') + '=' +
                encodeURIComponent(v).replace(regexp,'+');
            pairs.push(pair);
        }
        return pairs.join('&');
    }
},{
    processReqChange: function() {
        var req = this.request;
        if (req.readyState == 4) {
            if (req.status == 200) {
                var cb = this.callback;
                cb.object[cb.method].call(cb.object, req);
            } else {
                alert("There was a problem retrieving the XML data:\n" +
                      req.statusText);
            }
        }
    }
});

/* Ten.Observer */
Ten.Observer = new Ten.Class({
    initialize: function(element,event,obj,method) {
        var func = obj;
        if (typeof(method) == 'string') {
            func = obj[method];
        }
        this.element = element;
        this.event = event;
        this.listener = function(event) {
            return func.call(obj, new Ten.Event(event || window.event));
        }
        if (this.element.addEventListener) {
            if (this.event.match(/^on(.+)$/)) {
                this.event = RegExp.$1;
            }
            this.element.addEventListener(this.event, this.listener, false);
        } else if (this.element.attachEvent) {
            this.element.attachEvent(this.event, this.listener);
        }
    }
},{
    stop: function() {
        if (this.element.removeEventListener) {
            this.element.removeEventListener(this.event,this.listener,false);
        } else if (this.element.detachEvent) {
            this.element.detachEvent(this.event,this.listener);
        }
    }
});

/* Ten.Event */
Ten.Event = new Ten.Class({
    initialize: function(event) {
        this.event = event;
    },
    keyMap: {
        8:"backspace", 9:"tab", 13:"enter", 19:"pause", 27:"escape", 32:"space",
        33:"pageup", 34:"pagedown", 35:"end", 36:"home", 37:"left", 38:"up",
        39:"right", 40:"down", 44:"printscreen", 45:"insert", 46:"delete",
        112:"f1", 113:"f2", 114:"f3", 115:"f4", 116:"f5", 117:"f6", 118:"f7",
        119:"f8", 120:"f9", 121:"f10", 122:"f11", 123:"f12",
        144:"numlock", 145:"scrolllock"
    }
},{
    mousePosition: function() {
        if (!this.event.clientX) return;
        return Ten.Geometry.getMousePosition(this.event);
    },
    isKey: function(name) {
        var ecode = this.event.keyCode;
        if (!ecode) return;
        var ename = Ten.Event.keyMap[ecode];
        if (!ename) return;
        return (ename == name);
    },
    targetIsFormElements: function() {
        var target = this.event.target;
        if (!target) return;
        var T = (target.tagName || '').toUpperCase();
        return (T == 'INPUT' || T == 'SELECT' || T == 'OPTION' ||
                T == 'BUTTON' || T == 'TEXTAREA');
    },
    stop: function() {
        var e = this.event;
        if (e.stopPropagation) {
            e.stopPropagation();
            e.preventDefault();
        } else {
            e.cancelBubble = true;
            e.returnValue = false;
        }
    }
});

/* Ten.DOM */
Ten.DOM = new Ten.Class({
    getElementsByTagAndClassName: function(tagName, className, parent) {
        if (typeof(parent) == 'undefined') {
            parent = document;
        }
        var children = parent.getElementsByTagName(tagName);
        if (className) { 
            var elements = [];
            for (var i = 0; i < children.length; i++) {
                var child = children[i];
                var cls = child.className;
                if (!cls) {
                    continue;
                }
                var classNames = cls.split(' ');
                for (var j = 0; j < classNames.length; j++) {
                    if (classNames[j] == className) {
                        elements.push(child);
                        break;
                    }
                }
            }
            return elements;
        } else {
            return children;
        }
    },
    removeEmptyTextNodes: function(element) {
        var nodes = element.childNodes;
        for (var i = 0; i < nodes.length; i++) {
            var node = nodes[i];
            if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
                node.parentNode.removeChild(node);
            }
        }
    },
    nextElement: function(elem) {
        do {
            elem = elem.nextSibling;
        } while (elem && elem.nodeType != 1);
        return elem;
    },
    prevElement: function(elem) {
        do {
            elem = elem.previousSibling;
        } while (elem && elem.nodeType != 1);
        return elem;
    },
    scrapeText: function(node) {
        var rval = [];
        (function (node) {
            var cn = node.childNodes;
            if (cn) {
                for (var i = 0; i < cn.length; i++) {
                    arguments.callee.call(this, cn[i]);
                }
            }
            var nodeValue = node.nodeValue;
            if (typeof(nodeValue) == 'string') {
                rval.push(nodeValue);
            }
        })(node);
        return rval.join('');
    },
    onLoadFunctions: [],
    loaded: false,
    timer: null,
    addEventListener: function(event,func) {
        if (event != 'load') return;
        Ten.DOM.onLoadFunctions.push(func);
        Ten.DOM.checkLoaded();
    },
    checkLoaded: function() {
        var c = Ten.DOM;
        if (c.loaded) return true;
        if (document && document.getElementsByTagName &&
            document.getElementById && document.body) {
            if (c.timer) {
                clearInterval(c.timer);
                c.timer = null;
            }
            for (var i = 0; i < c.onLoadFunctions.length; i++) {
                    c.onLoadFunctions[i]();
            }
            c.onLoadFunctions = [];
            c.loaded = true;
        } else {
            c.timer = setInterval(c.checkLoaded, 13);
        }
    }
});

/* Ten.Style */
Ten.Style = new Ten.Class({
    applyStyle: function(elem, style) {
        for (prop in style) {
            elem.style[prop] = style[prop];
        }
    }
});

/* Ten.Geometry */
Ten.Geometry = new Ten.Class({
    initialize: function() {
        if (Ten.Geometry._initialized) return;
        var func = Ten.Geometry._functions;
        var de = document.documentElement;
        if (window.innerWidth) {
            func.getWindowWidth = function() { return window.innerWidth; }
            func.getWindowHeight = function() { return window.innerHeight; }
            func.getXScroll = function() { return window.pageXOffset; }
            func.getYScroll = function() { return window.pageYOffset; }
        } else if (de && de.clientWidth) {
            func.getWindowWidth = function() { return de.clientWidth; }
            func.getWindowHeight = function() { return de.clientHeight; }
            func.getXScroll = function() { return de.scrollLeft; }
            func.getYScroll = function() { return de.scrollTop; }
        } else if (document.body.clientWidth) {
            func.getWindowWidth = function() { return document.body.clientWidth; }
            func.getWindowHeight = function() { return document.body.clientHeight; }
            func.getXScroll = function() { return document.body.scrollLeft; }
            func.getYScroll = function() { return document.body.scrollTop; }
        }
        Ten.Geometry._initialized = true;
    },
    _initialized: false,
    _functions: {},
    getScroll: function() {
        if (!Ten.Geometry._initialized) new Ten.Geometry;
        return {
            x: Ten.Geometry._functions.getXScroll(),
            y: Ten.Geometry._functions.getYScroll()
        };
    },
    getMousePosition: function(pos) {
        // pos should have clientX, clientY same as mouse event
        if ((navigator.userAgent.indexOf('Safari') > -1) &&
            (navigator.userAgent.indexOf('Version/') < 0)) {
            return {
                x: pos.clientX,
                y: pos.clientY
            };
        } else {
            var scroll = Ten.Geometry.getScroll();
            return {
                x: pos.clientX + scroll.x,
                y: pos.clientY + scroll.y
            };
        }
    },
    getElementPosition: function(e) {
        return {
            x: e.offsetLeft,
            y: e.offsetTop
        };
    },
    getWindowSize: function() {
        if (!Ten.Geometry._initialized) new Ten.Geometry;
        return {
            w: Ten.Geometry._functions.getWindowWidth(),
            h: Ten.Geometry._functions.getWindowHeight()
        };
    }
});

/* Ten.Position */
Ten.Position = new Ten.Class({
    initialize: function(x,y) {
        this.x = x;
        this.y = y;
    },
    subtract: function(a,b) {
        return new Ten.Position(a.x - b.x, a.y - b.y);
    }
});

/*
// require Ten.js
**/

/* Ten.SubWindow */
Ten.SubWindow = new Ten.Class({
    initialize: function() {
        var c = this.constructor;
        if (c.singleton && c._cache) {
            return c._cache;
        }
        var div = document.createElement('div');
        Ten.Style.applyStyle(div, Ten.SubWindow._baseStyle);
        Ten.Style.applyStyle(div, c.style);
        this.window = div;
        this.addContainerAndCloseButton();
        document.body.appendChild(div);
        if (c.draggable) {
            this._draggable = new Ten.Draggable(div, this.handle);
        }
        if (c.singleton) c._cache = this;
        return this;
    },
    _baseStyle: {
        color: '#000',
        position: 'absolute',
        display: 'none',
        zIndex: 2,
        left: 0,
        top: 0,
        backgroundColor: '#fff',
        border: '1px solid #bbb'
    },
    style: {
        padding: '2px',
        textAlign: 'center',
        borderRadius: '6px',
        MozBorderRadius: '6px',
        width: '100px',
        height: '100px'
    },
    handleStyle: {
        position: 'absolute',
        top: '0px',
        left: '0px',
        backgroundColor: '#f3f3f3',
        borderBottom: '1px solid #bbb',
        width: '100%',
        height: '30px'
    },
    containerStyle: {
        margin: '32px 0 0 0',
        padding: '0 10px'
    },
    // closeButton: 'close.gif',
    closeButton: 'http://s.hatena.com/images/close.gif',
    closeButtonStyle: {
        position: 'absolute',
        top: '8px',
        right: '10px',
        cursor: 'pointer'
    },
    _baseScreenStyle: {
        position: 'absolute',
        top: '0px',
        left: '0px',
        display: 'none',
        zIndex: 1,
        overflow: 'hidden',
        width: '100%',
        height: '100%'
    },
    screenStyle: {},
    showScreen: true,
    singleton: true,
    draggable: true,
    _cache: null
},{
    screen: null,
    windowObserver: null,
    visible: false,
    addContainerAndCloseButton: function() {
        var win = this.window;
        var c = this.constructor;
        var div = document.createElement('div');
        win.appendChild(div);
        Ten.Style.applyStyle(div, c.containerStyle);
        this.container = div;
        if (c.handleStyle) {
            var handle = document.createElement('div');
            Ten.Style.applyStyle(handle, c.handleStyle);
            win.appendChild(handle);
            this.handle = handle;
        }
        if (c.closeButton) {
	    var btn = document.createElement('img');
            btn.src = c.closeButton;
            btn.alt = 'close';
            Ten.Style.applyStyle(btn, c.closeButtonStyle);
            win.appendChild(btn);
            new Ten.Observer(btn, 'onclick', this, 'hide');
            this.closeButton = btn;
        }
        if (c.showScreen) {
            var screen = document.createElement('div');
            Ten.Style.applyStyle(screen, Ten.SubWindow._baseScreenStyle);
            Ten.Style.applyStyle(screen, c.screenStyle);
            document.body.appendChild(screen);
            this.screen = screen;
            new Ten.Observer(screen, 'onclick', this, 'hide');
        }
    },
    show: function(pos) {
        pos = (pos.x && pos.y) ? pos : {x:0, y:0};
        with (this.window.style) {
            display = 'block';
            left = pos.x + 'px';
            top = pos.y + 'px';
        }
        if (this.screen) {
            with (this.screen.style) {
                display = 'block';
                left = Ten.Geometry.getScroll().x + 'px';
                top = Ten.Geometry.getScroll().y + 'px';
            }
        }
        this.windowObserver = new Ten.Observer(document.body, 'onkeypress', this, 'handleEscape');
        this.visible = true;
    },
    handleEscape: function(e) {
        if (!e.isKey('escape')) return;
        this.hide();
    },
    hide: function() {
        if (this._draggable) this._draggable.endDrag();
        this.window.style.display = 'none';
        if (this.screen) this.screen.style.display = 'none';
        if (this.windowObserver) this.windowObserver.stop();
        this.visible = false;
    }
});

/* Ten.Draggable */
Ten.Draggable = new Ten.Class({
    initialize: function(element,handle) {
        this.element = element;
        this.handle = handle || element;
        this.startObserver = new Ten.Observer(this.handle, 'onmousedown', this, 'startDrag');
        this.handlers = [];
    }
},{
    startDrag: function(e) {
        if (e.targetIsFormElements()) return;
        this.delta = Ten.Position.subtract(
            e.mousePosition(),
            Ten.Geometry.getElementPosition(this.element)
        );
        this.handlers = [
            new Ten.Observer(document, 'onmousemove', this, 'drag'),
            new Ten.Observer(document, 'onmouseup', this, 'endDrag'),
            new Ten.Observer(this.element, 'onlosecapture', this, 'endDrag')
        ];
        e.stop();
    },
    drag: function(e) {
        var pos = Ten.Position.subtract(e.mousePosition(), this.delta);
        Ten.Style.applyStyle(this.element, {
            left: pos.x + 'px',
            top: pos.y + 'px'
        });
        e.stop();
    },
    endDrag: function(e) {
        for (var i = 0; i < this.handlers.length; i++) {
            this.handlers[i].stop();
        }
        if(e) e.stop();
    }
});

/* Hatena */
if (typeof(Hatena) == 'undefined') {
    Hatena = {};
}

/* Hatena.User */
Hatena.User = new Ten.Class({
    initialize: function(name) {
        this.name = name;
    },
    getProfileIcon: function(name) {
        if (!name) name = 'user';
        var pre = name.match(/^[\w-]{2}/)[0];
        var img = document.createElement('img');
        img.src = 'http://www.hatena.ne.jp/users/' + pre + '/' + name + '/profile_s.gif';
        img.alt = name;
        img.setAttribute('class', 'profile-icon');
        img.setAttribute('width','16px');
        img.setAttribute('height','16px');
        with (img.style) {
            margin = '0 3px';
            border = 'none';
            verticalAlign = 'middle';
        }
        return img;
    }
}, {
    profileIcon: function() {
        return Hatena.User.getProfileIcon(this.name);
    }
});

/* Hatena.Star */
if (typeof(Hatena.Star) == 'undefined') {
    Hatena.Star = {};
}

/*
// Hatena.Star.* classes //
**/
if (window.location && window.location.host.match(/hatena\.com/)) {
    Hatena.Star.BaseURL = 'http://s.hatena.com/';
} else {
    Hatena.Star.BaseURL = 'http://s.hatena.ne.jp/';
}
Hatena.Star.Token = null;

/* Hatena.Star.User */
Hatena.Star.User = new Ten.Class({
    base: [Hatena.User],
    initialize: function(name) {
        if (Hatena.Star.User._cache[name]) {
            return Hatena.Star.User._cache[name];
        } else {
            this.name = name;
            Hatena.Star.User._cache[name] = this;
            return this;
        }
    },
    _cache: {}
},{
    userPage: function() {
        return Hatena.Star.BaseURL + this.name + '/';
    }
});

/* Hatena.Star.Entry */
Hatena.Star.Entry = new Ten.Class({
    initialize: function(e) {
        this.entry = e;
        this.uri = e.uri;
        this.title = e.title;
        this.star_container = e.star_container;
        this.comment_container = e.comment_container;
        this.stars = [];
        this.comments = [];
    },
    maxStarCount: 11
},{
    flushStars: function() {
        this.stars = [];
        this.star_container.innerHTML = '';
    },
    bindStarEntry: function(se) {
        this.starEntry = se;
        for (var i = 0; i < se.stars.length; i++) {
            if (typeof(se.stars[i]) == 'number') {
                this.stars.push(new Hatena.Star.InnerCount(se.stars[i],this));
            } else {
                this.stars.push(new Hatena.Star.Star(se.stars[i]));
            }
        }
        if (se.comments && !this.comments.length) {
            for (var i = 0; i < se.comments.length; i++) {
                this.comments.push(new Hatena.Star.Comment(se.comments[i]));
            }
        }
        this.can_comment = se.can_comment;
    },
    setCanComment: function(v) {
        this.can_comment = v;
    },
    showButtons: function() {
        this.addAddButton();
        this.addCommentButton();
    },
    addAddButton: function() {
        if (this.star_container) {
            this.addButton = new Hatena.Star.AddButton(this);
            this.star_container.appendChild(this.addButton);
        }
    },
    addCommentButton: function() {
        if (this.comment_container) {
            this.commentButton = new Hatena.Star.CommentButton(this);
            this.comment_container.appendChild(this.commentButton.img);
        }
    },
    showStars: function() {
        var klass = this.constructor;
        // if (this.stars.length > klass.maxStarCount) {
        //     var ic = new Hatena.Star.InnerCount(this.stars.slice(1,this.stars.length));
        //     this.star_container.appendChild(this.stars[0]);
        //     this.star_container.appendChild(ic);
        //     this.star_container.appendChild(this.stars[this.stars.length - 1]);
        // } else {
        for (var i = 0; i < this.stars.length; i++) {
            this.star_container.appendChild(this.stars[i]);
        }
    },
    showCommentButton: function() {
        if (this.can_comment) {
            this.commentButton.show();
            if (this.comments.length) this.commentButton.activate();
        } else {
            // this.commentButton.hide();
        }
    },
    addStar: function(star) {
        this.stars.push(star);
        this.star_container.appendChild(star);
    },
    addComment: function(com) {
        if (!this.comments) this.comments = [];
        if (this.comments.length == 0) {
            this.commentButton.activate();
        }
        this.comments.push(com);
    },
    showCommentCount: function() {
        this.comment_container.innerHTML += this.comments.length;
    }
});

/* Hatena.Star.Button */
Hatena.Star.Button = new Ten.Class({
    createButton: function(args) {
        var img = document.createElement('img');
        img.src = args.src;
        img.alt = img.title = args.alt;
        with (img.style) {
	    cursor = 'pointer';
	    margin = '0 3px';
            padding = '0';
            border = 'none';
            verticalAlign = 'middle';
        }
        return img;
    }
});

/* Hatena.Star.AddButton */
Hatena.Star.AddButton = new Ten.Class({
    base: ['Hatena.Star.Button'],
    initialize: function(entry) {
        this.entry = entry;
        this.lastPosition = null;
        var img = Hatena.Star.Button.createButton({
            src: Hatena.Star.AddButton.ImgSrc,
            alt: 'Add Star'
        });
        this.observer = new Ten.Observer(img,'onclick',this,'addStar');
        this.img = img;
        return img;
    },
    ImgSrc: Hatena.Star.BaseURL + 'images/add.gif'
},{
    addStar: function(e) {
        this.lastPosition = e.mousePosition();
        var uri = Hatena.Star.BaseURL + 'star.add.json?uri=' + encodeURIComponent(this.entry.uri) +
            '&title=' + encodeURIComponent(this.entry.title);
        if (Hatena.Star.Token) {
            uri += '&token=' + Hatena.Star.Token;
        }
        new Ten.JSONP(uri, this, 'receiveResult');
    },
    receiveResult: function(args) {
        var name = args ? args.name : null;
        if (name) {
            this.entry.addStar(new Hatena.Star.Star({name: name}));
            //alert('Succeeded in Adding Star ' + args);
        } else if (args.errors) {
            var pos = this.lastPosition;
            pos.x -= 10;
            pos.y += 25;
            var scroll = Ten.Geometry.getScroll();
            var scr = new Hatena.Star.AlertScreen();
            var alert = args.errors[0];
            scr.showAlert(alert, pos);
        }
    }
});

/* Hatena.Star.CommentButton */
Hatena.Star.CommentButton = new Ten.Class({
    base: ['Hatena.Star.Button'],
    initialize: function(entry) {
        this.entry = entry;
        this.lastPosition = null;
        var img = Hatena.Star.Button.createButton({
            src: Hatena.Star.CommentButton.ImgSrc,
            alt: 'Comments'
        });
        img.style.display = 'none';
        this.observer = new Ten.Observer(img,'onclick',this,'showComments');
        this.img = img;
    },
    ImgSrc: Hatena.Star.BaseURL + 'images/comment.gif',
    ImgSrcActive: Hatena.Star.BaseURL + 'images/comment_active.gif'
},{
    showComments: function(e) {
        if (!this.screen) this.screen = new Hatena.Star.CommentScreen();
        this.screen.bindEntry(this.entry);
        var pos = e.mousePosition();
        pos.y += 25;
        this.screen.showComments(this.entry, pos);
    },
    hide: function() {
        this.img.style.display = 'none';
    },
    show: function() {
        this.img.style.display = 'inline';
    },
    activate: function() {
        this.show();
        this.img.src = Hatena.Star.CommentButton.ImgSrcActive;
    }
});

/* Hatena.Star.Star */
Hatena.Star.Star = new Ten.Class({
    initialize: function(args) {
        if (args.img) {
            this.img = args.img;
            this.name = this.img.getAttribute('alt');
        } else {
            this.name = args.name;
            var img = document.createElement('img');
            img.src = Hatena.Star.Star.ImgSrc;
            img.alt = this.name;
            with (img.style) {
                padding = '0';
                border = 'none';
            }
            this.img = img;
        }
	new Ten.Observer(this.img,'onmouseover',this,'showName');
	new Ten.Observer(this.img,'onmouseout',this,'hideName');
	if (this.name) {
            this.user = new Hatena.Star.User(this.name);
            this.img.style.cursor = 'pointer';
            new Ten.Observer(this.img,'onclick',this,'goToUserPage');
        }
        if (args.count && args.count > 1) {
            var c = document.createElement('span');
            c.setAttribute('class', 'hatena-star-inner-count');
            Ten.Style.applyStyle(c, Hatena.Star.InnerCount.style);
            c.innerHTML = args.count;
            var s = document.createElement('span');
            s.appendChild(img);
            s.appendChild(c);
            return s;
        } else {
            return this.img;
        }
    },
    ImgSrc: Hatena.Star.BaseURL + 'images/star.gif'
},{
    showName: function(e) {
        if (!this.screen) this.screen = new Hatena.Star.NameScreen();
        var pos = e.mousePosition();
        pos.x += 10;
        pos.y += 25;
        this.screen.showName(this.name, pos);
    },
    hideName: function() {
        if (!this.screen) return;
        this.screen.hide();
    },
    goToUserPage: function() {
        window.location = this.user.userPage();
    }
});

/* Hatena.Star.InnerCount */
Hatena.Star.InnerCount = new Ten.Class({
    initialize: function(count, e) {
        this.count = count;
        this.entry = e;
        var c = document.createElement('span');
        c.setAttribute('class', 'hatena-star-inner-count');
        Ten.Style.applyStyle(c, Hatena.Star.InnerCount.style);
        c.style.cursor = 'pointer';
        c.innerHTML = count;
        new Ten.Observer(c,'onclick',this,'showInnerStars');
        this.container = c;
        return c;
    },
    style: {
        color: '#f4b128',
        fontWeight: 'bold',
        fontSize: '80%',
        fontFamily: '"arial", sans-serif',
        margin: '0 2px'
    }
},{
    showInnerStars: function() {
        var url = Hatena.Star.BaseURL + 'entry.json?uri=' +
        encodeURIComponent(this.entry.uri);
        new Ten.JSONP(url, this, 'receiveStarEntry');
    },
    receiveStarEntry: function(res) {
        var se = res.entries[0];
        var e = this.entry;
        if (encodeURIComponent(se.uri) != encodeURIComponent(e.uri)) return;
        e.flushStars();
        e.bindStarEntry(se);
        e.addAddButton();
        e.showStars();
    }
});

/* Hatena.Star.Comment */
Hatena.Star.Comment = new Ten.Class({
    initialize: function(args) {
        this.name = args.name;
        this.body = args.body;
    }
},{
    asElement: function() {
        var div = document.createElement('div');
        with (div.style) {
            margin = '0px 0';
            padding = '5px 0';
            borderBottom = '1px solid #ddd';
        }
        var ico = Hatena.User.getProfileIcon(this.name);
        div.appendChild(ico);
        var span = document.createElement('span');
        with(span.style) {
            fontSize = '90%';
        }
        span.innerHTML = this.body;
        div.appendChild(span);
        return div;
    }
});

/* Hatena.Star.NameScreen */
Hatena.Star.NameScreen = new Ten.Class({
    base: [Ten.SubWindow],
    style: {
        padding: '2px',
        textAlign: 'center'
    },
    containerStyle: {
        margin: 0,
        padding: 0
    },
    handleStyle: null,
    showScreen: false,
    closeButton: null,
    draggable: false
},{
    showName: function(name, pos) {
        this.container.innerHTML = '';
        this.container.appendChild(Hatena.User.getProfileIcon(name));
        this.container.appendChild(document.createTextNode(name));
        this.show(pos);
    }
});

/* Hatena.Star.AlertScreen */
Hatena.Star.AlertScreen = new Ten.Class({
    base: [Ten.SubWindow],
    style: {
        padding: '2px',
        textAlign: 'center',
        borderRadius: '6px',
        MozBorderRadius: '6px',
        width: '240px',
        height: '120px'
    },
    handleStyle: {
        position: 'absolute',
        top: '0px',
        left: '0px',
        backgroundColor: '#f3f3f3',
        borderBottom: '1px solid #bbb',
        width: '100%',
        height: '30px',
        borderRadius: '6px 6px 0 0',
        MozBorderRadius: '6px 6px 0 0'
    }
},{
    showAlert: function(msg, pos) {
        this.container.innerHTML = msg;
        var win = Ten.Geometry.getWindowSize();
        var scr = Ten.Geometry.getScroll();
        var w = parseInt(this.constructor.style.width) + 20;
        if (pos.x + w > scr.x + win.w) pos.x = win.w + scr.x - w;
        this.show(pos);
    }
});

/* Hatena.Star.CommentScreen */
Hatena.Star.CommentScreen = new Ten.Class({
    base: [Ten.SubWindow],
    initialize: function() {
        var self = this.constructor.SUPER.call(this);
        if (!self.commentsContainer) self.addCommentsContainer();
        return self;
    },
    style: {
        width: '280px',
        height: '280px',
        overflowY: 'auto',
        padding: '2px',
        textAlign: 'center',
        borderRadius: '6px',
        MozBorderRadius: '6px'
    },
    handleStyle: {
        position: 'absolute',
        top: '0px',
        left: '0px',
        backgroundColor: '#f3f3f3',
        borderBottom: '1px solid #bbb',
        width: '100%',
        height: '30px',
        borderRadius: '6px 6px 0 0',
        MozBorderRadius: '6px 6px 0 0'
    },
    containerStyle: {
        margin: '32px 0 0 0',
        textAlign: 'left',
        padding: '0 10px'
    },
    getLoadImage: function() {
        var img = document.createElement('img');
        img.src = Hatena.Star.BaseURL + 'images/load.gif';
        img.setAttribute('alt', 'Loading');
        with (img.style) {
            verticalAlign = 'middle';
            margin = '0 2px';
        }
        return img;
    }
},{
    addCommentsContainer: function() {
        var div = document.createElement('div');
        with (div.style) {
            marginTop = '-3px';
        }
        this.container.appendChild(div);
        this.commentsContainer = div;
    },
    showComments: function(e, pos) {
        var comments = e.comments;
        if (!comments) comments = [];
        this.commentsContainer.innerHTML = '';
        for (var i=0; i<comments.length; i++) {
            this.commentsContainer.appendChild(comments[i].asElement());
        }
        if (e.starEntry && !e.can_comment) {
            this.hideCommentForm();
        } else {
            this.addCommentForm();
        }
        var win = Ten.Geometry.getWindowSize();
        var scr = Ten.Geometry.getScroll();
        var w = parseInt(this.constructor.style.width) + 20;
        if (pos.x + w > scr.x + win.w) pos.x = win.w + scr.x - w;
        this.show(pos);
    },
    bindEntry: function(e) {
        this.entry = e;
    },
    sendComment: function(e) {
        if (!e.isKey('enter')) return;
        var body = this.commentInput.value;
        if (!body) return;
        this.commentInput.disabled = 'true';
        this.showLoadImage();
        var url = Hatena.Star.BaseURL + 'comment.add.json?body=' + encodeURIComponent(body) +
            '&uri=' + encodeURIComponent(this.entry.uri) +
            '&title=' + encodeURIComponent(this.entry.title);
        new Ten.JSONP(url, this, 'receiveResult');
    },
    receiveResult: function(args) {
        if (!args.name || !args.body) return;
        this.commentInput.value = ''; 
        this.commentInput.disabled = '';
        this.hideLoadImage();
        var com = new Hatena.Star.Comment(args);
        this.entry.addComment(com);
        this.commentsContainer.appendChild(com.asElement());
    },
    showLoadImage: function() {
        if (!this.loadImage) return; 
        this.loadImage.style.display = 'inline';
    },
    hideLoadImage: function() {
        if (!this.loadImage) return; 
        this.loadImage.style.display = 'none';
    },
    hideCommentForm: function() {
        if (!this.commentForm) return;
        this.commentForm.style.display = 'none';
    },
    addCommentForm: function() {
        if (this.commentForm) {
            this.commentForm.style.display = 'block';
            return;
        }
        var form = document.createElement('div');
        this.container.appendChild(form);
        this.commentForm = form;
        with (form.style) {
            margin = '0px 0';
            padding = '5px 0';
            // borderTop = '1px solid #ddd';
        }
        //if (Hatena.Visitor) {
        //    form.appendChild(Hatena.Visitor.profileIcon());
        //} else {
        //    form.appendChild(Hatena.User.getProfileIcon());
        //}
        var input = document.createElement('input');
        input.type = 'text';
        with (input.style) {
            width = '215px';
	    border = '1px solid #bbb';
            padding = '3px';
        }
        form.appendChild(input);
        this.commentInput = input;
        var img = this.constructor.getLoadImage();
        this.loadImage = img;
        this.hideLoadImage();
        form.appendChild(img);
        new Ten.Observer(input,'onkeypress',this,'sendComment');
    }
});

/* Hatena.Star.EntryLoader */
Hatena.Star.EntryLoader = new Ten.Class({
    initialize: function() {
        var entries = Hatena.Star.EntryLoader.loadEntries();
        this.entries = [];
        for (var i = 0; i < entries.length; i++) {
            var e = new Hatena.Star.Entry(entries[i]);
            e.showButtons();
            this.entries.push(e);
        }
        this.getStarEntries();
    },
    createStarContainer: function() {
        var sc = document.createElement('span');
        sc.setAttribute('class', 'hatena-star-star-container');
        sc.style.marginLeft = '1px';
        return sc;
    },
    createCommentContainer: function() {
        var cc = document.createElement('span');
        cc.setAttribute('class', 'hatena-star-comment-container');
        cc.style.marginLeft = '1px';
        return cc;
    },
    scrapeTitle: function(node) {
        var rval = [];
        (function (node) {
            if (node.tagName == 'SPAN' &&
                (node.className == 'sanchor' ||
                 node.className == 'timestamp')) {
                     return;
            } else if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
                return;
            }
            var cn = node.childNodes;
            if (cn) {
                for (var i = 0; i < cn.length; i++) {
                    arguments.callee.call(this, cn[i]);
                }
            }
            var nodeValue = node.nodeValue;
            if (typeof(nodeValue) == 'string') {
                rval.push(nodeValue);
            }
        })(node);
        return rval.join('');
    },
    headerTagAndClassName: ['h3',null],
    getHeaders: function() {
        var t = Hatena.Star.EntryLoader.headerTagAndClassName;
        return Ten.DOM.getElementsByTagAndClassName(t[0],t[1],document);
    },
    loadEntries: function() {
        var entries = [];
        //var headers = document.getElementsByTagName('h3');
        var c = Hatena.Star.EntryLoader;
        var headers = c.getHeaders();
        for (var i = 0; i < headers.length; i++) {
            var header = headers[i];
            var a = header.getElementsByTagName('a')[0];
            if (!a) continue;
            var uri = a.href;
            var title = '';
            // Ten.DOM.removeEmptyTextNodes(header);
            var cns = header.childNodes;
            title = c.scrapeTitle(header);
            var cc = c.createCommentContainer();
            header.appendChild(cc);
            var sc = c.createStarContainer();
            header.appendChild(sc);
            entries.push({
                uri: uri,
                title: title,
                star_container: sc,
                comment_container: cc
            });
        }
        return entries;
    }
},{
    getStarEntries: function() {
        var url = Hatena.Star.BaseURL + 'entries.json?';
        for (var i = 0; i < this.entries.length; i++) {
            if (url.length > Ten.JSONP.MaxBytes) {
                new Ten.JSONP(url, this, 'receiveStarEntries');
                url = Hatena.Star.BaseURL + 'entries.json?';
            }
            url += 'uri=' + encodeURIComponent(this.entries[i].uri) + '&';
        }
        new Ten.JSONP(url, this, 'receiveStarEntries');
    },
    receiveStarEntries: function(res) {
        var entries = res.entries;
        if (!entries) entries = [];
        for (var i = 0; i < this.entries.length; i++) {
            var e = this.entries[i];
            for (var j = 0; j < entries.length; j++) {
                var se = entries[j];
                if (!se.uri) continue;
                if (encodeURIComponent(se.uri) == encodeURIComponent(e.uri)) {
                    e.bindStarEntry(se);
                    entries.splice(j,1);
                    break;
                }
            }
            if (typeof(e.can_comment) == 'undefined') {
                e.setCanComment(res.can_comment);
            }
            e.showStars();
            e.showCommentButton();
        }
    }
});

/* Hatena.Star.WindowObserver */
Hatena.Star.WindowObserver = new Ten.Class({
    initialize: funct


  

2007-07-13

はてなスター」で他人に罵詈雑言を浴びせる方法

基本的に他人を褒めることしかできない「はてなスター」で他人に罵詈雑言を浴びせる方法です。

 

ttp://s.hatena.ne.jp/star.add.json?uri=http%3A%2F%2Fd.hatena.ne.jp%2F【憎いあん畜生ID】%2F0000&title=【届けたい罵詈雑言UTF-8パーセントエンコード)】&callback=Ten.JSONP.callback

 

これで

ttp://s.hatena.ne.jp/【憎いあん畜生ID】/blogs

メッセージが登録されるよ!

 

ttp://d.hatena.ne.jp/【憎いあん畜生ID】/0000

なんてページは作れないから、誰が★を送ってきたのかすらわからないよ!

仕様が変わったり、僕の勘違いだったら大変だから、ご利用は計画的に

 

1URIにつき1つしか登録されないから、複数のメッセージを送りたい場合は「0000」の部分を1回1回適当に変えようね!

 

まー、問題は、自分の

ttp://s.hatena.ne.jp/【ID】/blogs

なんて、ほとんどの人が見ないだろうってことだな。

2007-07-11

はてなスターソースコードの最後に更新履歴が載ってた

2007-07-11 v1.2 Release version

2007-05-30 v1.1 Added fold stars feature

2007-03-29 v1.0 Changed screens using Ten.SubWindow, you can d&d!

2007-03-28 v0.9 Changed Hatena.* classes to Ten v0.05.

2007-03-25 v0.8 Fixed Safari popup problem

2007-03-22 v0.7 Added active state to comment buttons

2007-03-21 v0.6 Added Comment function

2007-03-05 v0.5 Changed uri to Ridge-based paths.

2007-01-24 v0.4 Added Hatena.Diary.Entry class,

Changed Hatena.Star.Entry methods using class method

Added author parameters.

2007-01-23 v0.3 Added Hatena.Star.User class, added Hatena.js, Hatena.Star.js compatibility

2007-01-06 v0.2 Changed name spaces. Using Hatena.*, Hatena.Star.*

2007-01-05 v0.1 Initial version

4月前に大体出来てたって事かな

2007-06-17

前は「そうなんだー」で流せた話

「面白いのがあるから見て!」と動画画像URIが送られてくる。

「この前、送ったの見た!?」と尋ねられる。

「いや、ちょっと時間がなくて、まだ。」と返答しても、

それはその場しのぎでしかなくて、どうせ見なきゃいけない。

 「面白いテレビ番組があったんだけどさー」

 「あー、そうなんだーふむふむ。」

そんな風に流してた話題も今や流せなくなった。

2007-06-15

To: http://d.hatena.ne.jp/naoya/20070615/1181890785

まずこれが成立するのはやはりまずいのでは。

追記:

こんな話であれば、むしろ氏は「やり返しがしづらい」のがお気に召さなかったような希ガス

ブクマ個々が#無しのURIを持っていれば「このブクマコメントダメダメ」というやり返しがらくにできて、それでご本人も満足できたような。

2007-06-14

Re: Re: マルコをいじる人々

本人のお許しが出たのでw

2chURI書けっていうことだけど、元が消えてるので転載

抜粋はしてるけど改変はしないから安心して

対象スレはてなダイアリー 2


515 名前:名無しさん@ゴーゴーゴーゴー![sage] 投稿日:2006/11/21(火) 04:01:32 ID:IyYxgmJK ?2BP(3)
ねえ、はてな一ヶ月書いて思ったよ
俺のが一番おもしれえ
http://d.hatena.ne.jp/marco11/

688 名前:名無しさん@ゴーゴーゴーゴー![sage] 投稿日:2006/12/11(月) 03:28:53 ID:fFGPl/I2 ?2BP(333)
自分、結構使えますよw。
いろんな奴のキャラ教えてくれたら、絡んできますよ
ええ、全然なんでもアリですよ
はてな歴二ヶ月だし、うざくなったら即捨ててもかまわない垢なんでw
あの一応、隔離スレも確保してるんですけどねw
やっぱ、結局、2ちゃんが一番使い勝手いいですしねw

http://p2.2ch.net/p2/read.php?host=pc8.2ch.net&amp;bbs=blog&amp;key=1125228795&amp;rc=85#r84


701 名前:名無しさん@ゴーゴーゴーゴー![] 投稿日:2006/12/12(火) 13:20:34 ID:sNjuJOHM ?2BP(333)
ごめんおしえて
かのせって定期的に聞くね
どんな奴?
あの、俺鉄板で面白いって文章以外読む気にならない人間なんで
ちょこっと教えてクリよ
736 名前:名無しさん@ゴーゴーゴーゴー![sage] 投稿日:2006/12/14(木) 17:33:27 ID:Y58P/qbs ?2BP(333)
リアルで会うと
おまえ絶対惚れるからうざいw

737 名前:名無しさん@ゴーゴーゴーゴー![sage] 投稿日:2006/12/14(木) 17:37:17 ID:Y58P/qbs ?2BP(333)
女とか知り合うと思うもん
1ヶ月かけて、こうやってこうやってこうやったら
絶対おまえやらすんだから
今もうやらせてくれよって思う。
でも無理だろうからそうは言わないで
一ヶ月後に、案の定やってるからね

もうね、生きてて一番うざいのは、
おまえらにのみ必要で、俺には不要の説明を
おまえらが頭悪いばっかりに、しなきゃならないこと

こんな悩み、おまえらにはないの?
742 名前:名無しさん@ゴーゴーゴーゴー![sage] 投稿日:2006/12/14(木) 18:10:38 ID:Y58P/qbs ?2BP(333)
俺朝鮮人障害者差別しないけど
ガンヲタだけは同じ空気吸いたくないんだゴメンな
744 名前:名無しさん@ゴーゴーゴーゴー![sage] 投稿日:2006/12/14(木) 18:15:01 ID:Y58P/qbs ?2BP(333)
そりゃそうだろう
俺しか俺の中は見えねえんだから
俺にすら底が見えねえんだから
で、他の奴の底は、
ぼんやりとあのくらいかなって見えるんだもん

でも人間なんて、みんなそうなんじゃねえの?
サラリーマン以外w

745 名前:名無しさん@ゴーゴーゴーゴー![sage] 投稿日:2006/12/14(木) 18:17:37 ID:Y58P/qbs ?2BP(333)
『誰よりも』って断定しちゃうところをね
断定してしまうような状況と
断定してしまう迂闊な性格とを合わせて考えて
おまえが誰だかわかっちゃうんだよ2ちゃんって
まあ隠すつもりもないだろうけど、
悪いけど君に言われても燃えない

どこの押尾だw

語録、まだまだあるよ

2007-05-18

意外と古いのが参照され続けたり

URLエンコード | Diaspar Journal

まずは RFC 1738 - Uniform Resource Locators (URL)日本語訳)を参考にして、記号文字のURLエンコードがどのようにあるべきかを確認します。

いくらなんでもRFC 1738はないでしょ。RFC 2396 Uniform Resource Identifiers (URI): Generic Syntaxが出たのが1998年の8月だよ。最新のRFC 3986 Uniform Resource Identifier (URI): Generic Syntaxですら2005年1月、つまり2年以上前に出てるんだよ。

・・・といちゃもんつけようかと思ったけど、ECMAScript 3が1999年12月だからRFC 3986は参照できないね。さらにECMAScript 1にいたっては1997年6月だから、どうあがいてもRFC 1738しか参照できないわけだ。そのへんECMAScript仕様書にもちらっと書いてあるね。そこらをみんな考慮に入れて誰か改良版を作ってくれないかな、というだけいってみるテスト

2007-05-12

俺がOperaを使う理由

この記事は下書き。

Opera長所は何といっても「軽くて多機能」。「軽い」だけでも「多機能」だけでもなく、「軽くて多機能」。

軽さだけならLynxのほうが上だし、機能は無制限に拡張できるFxが最強だが、そのバランスでいえばOperaが一番優れていると思う。

以下、俺がよく使う機能について。事前に設定が必要なものを含む。

思い出したら追加するかもしれない。

2007-05-09

なるほどねえ

http://anond.hatelabo.jp/20070509112614

その話を聞いて面白いなあと思ったのは、おそらくテキストサイトBlogに相対化されちゃった真因は、

テキストサイトBlogシステム要素(URITBコメントみたいなシステム)があるんじゃないかってことだな。

中くらいの普通に面白い人々がどっとなだれ込むことになった理由のひとつがそこにあるわけだし。

だとすると、まあその推測の通りだとして、Blogというシステム進化する、あるいはBlogを従来のテキストサイトがごとく

駆逐するあたらしいシステムが出てくれば、そこにはBlog登場時に見られたのとは違うモチベーション

中くらい以上の人が入ってくる可能性があるわけだな。

でもそれはたぶんSNSでもTwitterでもないな。

その辺開発するとおもしろいんじゃないの?って誰に言ってんだ俺、ああどうせだからはてなに言おう、

おーい、梅田さん、jkondoさん、見てますか。

2007-04-14

トラバURIの/だか#だかが%になってますよ

グループダイアリー見出しがなんか#になったよね最近。でもディレクトリとしても表示されて両方ブクマできるよね。かたっぽ消えることよくあるけど。http://anond.hatelabo.jp/20070414132727

2007-04-08

コメントのフィードって

どういうURIなんでしょうかはてなダイアリーでは?

http://homepage.mac.com/naoyuki_hashimoto/iblog/index.html

ここのサイドバーみたいにコメント内容を表示させたいんですけど

あと、コメント欄って検索できないんですか?

2007-02-23

題のところに言及する相手のURIを入れるのはやめたほうが良くない? リンク張ったりブックマークしたりするとき不自然になるから、頭に「Re:」とかつけるか本文中に書くかしたほうが良いと思う。なんかさんざんがいしゅつくさいけど。

ログイン ユーザー登録
ようこそ ゲスト さん