「observer」を含む日記 RSS

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

2024-06-26

非エンジニアだけどClaude3に増田ミュート作ってもらったよ

これを改善してってお願いした。何書いてあるかわからないけど動いたよ。

https://anond.hatelabo.jp/20240125203115

// ==UserScript==
// @name         増田ミュート(白塗り版)
// @namespace    http://tampermonkey.net/
// @version      2024-06-26
// @description  ミューワードを含む最小限の範囲白塗りにする
// @author       You
// @match        https://anond.hatelabo.jp/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hatelabo.jp
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const muteWords = [
        "弱者男性",
        "弱男",
        "弱者",
        "婚活",
        "男",
        "女",
        "年収",
        "下方婚",
        "発達障害",
        "発達",
        "ハッタツ",
        "ハッタショ",
        "ハッタショ",
        "競プロ",
        "競技プログラミング",
        "AtCoder",
    ];

    function whiteoutElement(element) {
        element.style.backgroundColor = 'white';
        element.style.color = 'white';
        element.style.textShadow = 'none';
        element.style.cursor = 'default';
        element.style.userSelect = 'none';  // テキスト選択を防止
        element.style.borderBottom = '1px dashed #ccc'; // 枠線を追加してテキストがあることを示す

        // リンク場合クリック無効化
        if (element.tagName === 'A') {
            element.style.pointerEvents = 'none';
            element.removeAttribute('href');
        }

        // 子要素にも適用
        Array.from(element.children).forEach(child => {
            child.style.backgroundColor = 'white';
            child.style.color = 'white';
            child.style.textShadow = 'none';
        });

        // ツールチップを追加
        element.title = 'この内容にはミューワードが含まれています';
    }

    function shouldMute(text) {
        return muteWords.some(word => {
            const parts = word.split('');
            const regex = new RegExp(parts.map(char => `${char}\\s*`).join(''), 'i');
            return regex.test(text);
        });
    }

    function findSmallestMuteableElement(element) {
        if (element.nodeType === Node.TEXT_NODE) {
            return shouldMute(element.textContent) ? element.parentElement : null;
        }

        if (element.tagName === 'PRE' || element.tagName === 'CODE') {
            return shouldMute(element.textContent) ? element : null;
        }

        for (let child of element.childNodes) {
            const result = findSmallestMuteableElement(child);
            if (result) return result;
        }

        return shouldMute(element.textContent) ? element : null;
    }

    function processElement(element) {
        const muteableElement = findSmallestMuteableElement(element);
        if (muteableElement) {
            whiteoutElement(muteableElement);
        }
    }

    function processAllElements(root = document.body) {
        const walker = document.createTreeWalker(
            root,
            NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
            null,
            false
        );

        let node;
        while (node = walker.nextNode()) {
            if (node.nodeType === Node.ELEMENT_NODE) {
                processElement(node);
            } else if (node.nodeType === Node.TEXT_NODE && node.parentElement) {
                processElement(node.parentElement);
            }
        }
    }

    function handleClickEvent(event) {
        setTimeout(() => {
            processAllElements(event.target);
        }, 100);
    }

    // 初回実行
    processAllElements();

    // クリックイベント監視
    document.body.addEventListener('click', handleClickEvent);

    // DOM変更の監視
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            if (mutation.type === 'childList') {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        processAllElements(node);
                    }
                });
            } else if (mutation.type === 'characterData') {
                processElement(mutation.target.parentNode);
            }
        });
    });

    observer.observe(document.body, { childList: true, subtree: true, characterData: true });
})();

2024-04-04

anond:20240404084711

Actually, it turned out I DO feel like spending 40min or at least 20min of my life. I'm rather fascinated. In the first video, he says "I'm not taking a view as many people did, in the early days of quantum mechanics that it's the conscious Observer looking at the system". NOTE, it's "Observing", not "Measuring" and he DOES NOT take the view of "the conscious Observer looking at the system".

Now do you really want me to continue in English or do you want to read it in Japanese?

2019-05-01

ユメミリアム式幸福論 ~~

お気持ち表明がブームらしいので某声なしPaPの私もお気持ち表明がしたくなってしまいました。

こちらでは私の抱いている夢見りあむへその声の実装についての考えを適当に書き並べたのと+αについて述べていきたいと思います

まず結論から言うと、声はついていいと言うかぶっちゃけ然るべきだと思います

おそらくテコ入れとして4年?ぶりに実装された新アイドル。4年は短いようで長く、その間に社会は大きくかわってしまいました。2014年って前回のパズドラハローキティコラボよりも前なんですよ。そう考えると先カンブリア時代と大差ないレベル過去です。

そしてデレマス利益を出すために存在しているシステムの一部でしかないので、売れそうなキャラを売り出そうとしますでしょう。かつての俺嫁オタクは減少し私みたいな地雷持ちCP過激派跋扈する(それでもまだ比率は俺嫁系の方が上かもしれない)今7人中4人が既に相手のいる状態実装されていたり、数年前より大分盛況している配信をしているキャラだったり、Twitterで調べたら出てきそうなやばいやつだったり、諦観を持った農家だったり。

今様キャラクターを実装し、人気を出させ、マンネリ化を防ぐテコ入れ収入をかねようとしたのかな、炎上覚悟で。

から夢見りあむは声がつくのは普通だしぶっちゃけ既にサプぼ用意しててこれで一枠ボイスつけなくて済むラッキーwwwwwwみたいなことを運営が思っててもおかしくない。スケジュールとかたいへんだもんね。

逆にかつて実装されたキャラクターは、それこそ先カンブリア時代化石ガラパゴス生物かのような「今それある?」みたいなキャラ付けが多いと思うんです。かつてウケていた色物も受けない時代なんです。況や嘗てウケなかったものをやです。

というかそれについては人数が多いのが原因ですね。好きな人には申し訳ないけどなんの魅力も感じられないようなキャラかいます。まあ190もいたら属性分散してニッチなスピアが、所謂色物が出てくるのも当たり前だし、私に刺さらないだけかもしれないけど。

からガラパゴスのなかでも希少な存在(需要は少ない)に今総選挙県内が狙えるかと言うと、言わずもがな。Vo200でアイドルCに挑むようなものだと思います絶望の具現化かよ。

ただ、その中でこの時代でも戦えているのが多くの声付きと圏内で上がってきているアイドルだと思います。なぜ戦えているのか、それは需要があると運営様に判断されているからです。

時の流れは速いもので、南極環流も驚きの速さで進んでいきます。それにつれて客層の嗜好も変わります

また、人間は成長を好みますWJから歴史小説まで、まんがタイムきららすら成長を描きます

結果、ゲーム運営キャラクターを成長し発展させなければならなくなります。客がついてこないのでは利益も何も無いので。しか運営にも限界があり、単位時間で出来る仕事Wには上限値が存在します。

から、重心を人気キャラに置いて少しは利益を増やそうとします。種の少ない植木鉢にそれぞれ肥料を撒くよりは広大な大根畑にバーっとやった方が自分に都合がいい。

要は運営環境アイドルが種の地球モバマスです。ただし絶滅はさせられない。炎上という名のスーパープルームに全てを滅ぼされなかねないし。

ここまでの話を纏めると、新種の適応した生命体に勝つのは難しいから夢見りあむに声がつくのも普通ってことです。

ここからは夢見りあむ本体の話になります

1つ目はうわめっちゃぴんくです。祇園にどピンクマカロンショップを開いたところを想像したような色だなと思いました。

2つ目にこいつ本当に95あんのかよです。90くらいじゃない?盛ってない?

3つ目にこいつ楽そうだなです。

O-Ki-Mo-Chi-No Observer!と化していた私はどっかで見かけたこれに賛同したのですが、夢見りあむは詰みをそこまで重く捉えてなさそうなんですよね。突然来た訳でもないゆっくりとした詰みに面している時点で多分色々甘く見ていたんだと思います。それは、あまりにも面倒で理想的メンタルです。ダイヤモンドに巻き付けたうどんが切れただけでこのスポンジはザコメンタルを名乗っています。極めて健康的で羨ましい限りです。そしてなりふり構わず構って貰おうとします。周りの目を気にしないという才能です。これはメンタル接着剤を吹くようなそれの機能を持ちます。ゾウムシメンタル。

で、ここから踊る本能寺の炎についての考えです。

まず「『アイドル使い捨ての消費品』が許せない」。

本当にそうですよね。百城千代子もあと2年したら飽きられるらしいですし。そもそもこの発言に石を投げると押すのをやめた瞬間ガトリングになって返ってくるの怖いです。人間いつかは飽きます

次に、「みんな頑張ってるのにこいつはちやほやされたいだけ」みたいな旨の批判

実装されて2ヶ月程度でそれを判断するとしたらモバマスは多分半分くらい消えるんじゃないですかね。初発舌打ちのあの人とかモチベも目的も持ってなかったですからね。

「うちの担当は頑張ってるのに」ならいいんです。最初からアイドルになりたかった頑張る人とかスネークならその発言は正しい。しかし、「みんな」はいけない。その時点でその批判に効力はないです。回転攻撃中の瘴気魔人に通常攻撃してるようなものです。自称雑魚でも吹けば飛ばせます

他にもいろいろあるが、オタクがちょろいのは自然の摂理なのでそれもOK。他になんか答えてほしいのがあったらコメントにでも書いてくれれば続編が出ます。そんなに見る人間いないか

で、総選挙に与えている影響ですが、どうでもいいです。

なんとも言えない状況、それだけ。

ただ言えるのは、ぶっちゃけ夢見りあむにはほぼチートに近い性質があることだけ。炎上してしまったりなんだり、すればするほど票が増えていきます。あれ?やばくないこれ?

つまるところそういう意味でも勝てない。心底マジみっともないと思うがこれは無理。夢見りあむには勝てない。少なくとも話題性においては勝てないことは明らかなのだ。だから多くのファン圏内入れば幸運しか思えない。そんなレベル

あとこれも借り受けだが、りあむガチ勢が少ないのもある。人が集まれ変人も増え、変な目線も増える。結果外部に害をもたらすこともある。りあむにはまだそれがない。りあむを批判するのはネタになるし、自担賞賛する横でライバル貶めるような厄介もりあむ本人以外は多分いない。だから誰もがそれを心地よく玩具にできる。

夢見りあむは幸せだ。他人喜怒哀楽を餌に巨大化し、本人はそれに何かを思うこともないからだ。

そんなふうに楽に過ごしたいものだ。

2018-10-11

anond:20181011184334

エビデンス

実証重視の方々にとっては「物語」の代表に見えるであろう精神分析系の心理療法も、ちゃん効果確認されるようになってきたたことです。

それこそ、そのエビデンス(論文)でも提示されればいいんじゃないですかね。

この辺りのこと?

Jonathan Shedler,"The efficacy of psychodynamic psychotherapy."(American Psychologist 2010)

Falk Leichsenring,Sven Rabung,"Effectiveness of Long-term Psychodynamic Psychotherapy: A Meta-analysis"(JAMA 2008)


フロイト理論の諸々の失敗

精神分析医のフィーリス曰く(1)、フロイト派のセラピービクトリア時代の人たちには、うまく機能していたが20世紀半ば以降、人々の「性格の鎧」の質が変わり、セラピーはうまく機能せずに行き詰まって失敗することが多かった。

フロイト派の精神分析法は、「幼少期の体験が成人してから人格の基礎となる」というものが骨子の一つ(2)だが、そのことに大打撃を与える調査が出てきた。1990年代マシュマロ実験の文献を詳しく調べたマーティンセリグマンは、幼年期のできごとが成人してから人格に影響を与えるということは、ひどい心的外傷や栄養失調があった場合にはありうるかもしれないが、それ以外では有力な証拠ほとんどないと結論づけている(3)。子供時代と成人してから性質に、ごくわずかな相関は認められるが、それは主に遺伝的(生まれつきの)性質、つまり概して明るいとか気難しいといった性質の反映として説明できるという。

また心理学者のバウマイスター一同がフロイト提唱する理論メカニズムの数々を現代の文献と付き合わせて検証したところ、最も最悪な理論昇華説だということが判明した(4)。そもそも昇華説には根拠がない上、事実はその逆だと考えられる理由が多いからだ。

もちろん、フロイト理論示唆的で興味深いものが多いし、余談だが「快感原則彼岸」については現代思想の中ではかなり重要位置づけになっている。ラカン執拗にこの論文にこだわるわけだしね。

それに、フロイト批判をしたバウマイスターは、フロイト提唱する説でエネルギー重要位置に置かれていることに敬意を表して、フロイトが使っていた自己を指す言葉自我(エゴ)」を使って、「自我消耗」という言葉を「人の思考感情や行動を規制する能力が減る現象」に名付けた。自我消耗に関しては、後に脳波記録検査法(EEG)で脳内の前帯状皮質におけるスパイク発火(エラー関連陰性電位)が対応する脳機能であることが確認された(5)。


科学的な心理学

著名な心理学者であるスティーブン・ピンカーは、 今回で言えば「人生全体」「物語の蓄積」「人生の深み」といったことで、科学基本的研究方略である単純化(simplify)」を退けようとしていることに苦言を呈している(6)。 研究対象をとなる複雑な現象をいろいろなレベル単純化し、いろいろなレベルごとに 解明していくことを拒んで、複雑な現象ありのまま理解しようとしていたのでは研究はいつまでたっても現状に停滞したままになる。単純化を嫌って、複雑な現象を複雑なままで捉えようとする人文系学問に多く見られるのこうした研究方略を、ピンカーは完全な正確さを求めて「原寸大の地図」 を作った愚かな地図職人を描いたホルヘ・ルイス・ボルヘス(Jorge Luis Borges)の寓話批判している。

現代心理学の始まりブント(Wilhelm Wundt: 1832-1920)のライプチヒ大学での心理学実験室創設とされるように、そのスタートから科学を目指したものだった(7)。 人文学科学化と言っても、物理学化学実験を導入するのではなく、心理学実験手法神経科学実験手法(EEGfMRIなど)を取り入れればいいのである。また、国際的科学心理学学会APS(Association for Psychological Science)の会長だったカシオッポはこうした点に注目し、心理学科学と他の文系学問とのハブとなるべきであると主張している(8)。

個人的には、人生全体から人間理解フロイト理論人間理解よりも、人類史から人間理解(進化心理学)(9)や神経科学から人間理解の方(10)がより多くのことと整合性が有ると思うし、「物語」を一切考慮しないで休職者の約53%を予測したリシテア(11)といったことの研究心理学がより一層取り組んでいくことを願ってるわ。


▼出典

(1)Allen Wheelis,"The Quest for ldentity"(New York: Norton,1958).

(2)Sigmund Freud,"Drei Abhandlungen zur Sexualtheorie(『性理論三篇』)"(1905)

(3)M.E.P.Seligman,"What You Can Change and What You Can't :The Complete Guide to Succesful Self-Improvement"(New York:Alfred A.Knopf,1993).

(4)Roy F. Baumeister,Karen Dale,Kristin L. Sommer,"Freudian Defense Mechanisms and Empirical Findings in Modern SocialPsychology: Reaction Formation, Projection, Displacement, Undoing, Isolation, Sublimation, and Denial"(Journal of Personality,1998)

(5)Michael Inzlicht,Jennifer N. Gutsell,"Running on Empty: Neural Signals for Self-Control Failure",(Psychological Science 2007)

(6)Pinker, S."Science Is Not Your Enemy: An impassioned plea to neglected novelists, embattled professors, and tenure-less historians." (New Republic, 2013)

(7)Bringmann, W. G., Bringmann, N. J., & Ungerer, G. A."The establishment of Wundt's laboratory: An archival and documentary study." (W. G. Bringmann, & R. D. Tweney (Eds.), Wundt studies: A centennial collection (pp. 123-157). Toronto: Hogrefe. 1980)

(8)John Cacioppo,"Psychology is a Hub Science"(Observer 2007)

(9)Martin Daly, Margo Wilson,"How evolutionary thinking inspires and disciplines psychological hypotheses." Pp. 15-22 in XT Wang & YJ Su, eds., Thus spake evolutionary psychologists.(Peking University Press,2011)

(10)一例を挙げれば、心の理論(Theory of mind)における神経科学役割とか。サイモン・バロン=コーエンが有名だろうが、研究は色々有りすぎて挙げきれない。

(11)HR テクノロジーで、人や組織パフォーマンスの最大化を図る 「リシテア/AI 分析サービス販売開始(https://www.hitachi-solutions.co.jp/company/press/news/2016/1201.pdf)

2014-01-17

http://anond.hatelabo.jp/20140117000313

元増田です。ありがとうございます

モデルで発生するイベントが多く、複雑になるほど、ビューとの関連は密になる。

ここの所は、今回の例ではいまいち見えづらい気がする。

しかに、そうですね… 

攻撃を支持した時点で刀をふりあげて、そのあいだに毒でモンスターが死んだら、納刀する、のような場合では、モデル・ビューの関連が密になる例になるでしょうか。

いや、そのときModel「刀」をつくればいいのか…

Qtsignal/slotなんかはモデル同士の通信にも使える

これは知りませんでした。基本クラスレベルObserverパターンサポートされる!しかタイプセーフ…

Mac OS XCocoaフレームワークにも KVO という同様の仕組みがありますが、型のチェックは自分でする必要があります

MOVEの考え方からいえば、モデルの責務が吸い出されて単なるデータになってしま

MOVEは望まれなかった子 - the sea of fertility

を読んで、MVCを理解した(つもりになった)ので、MOVE設計方針自体スルーしていました。

Modelから責務が吸いだされて、なくなるのが予定調和なら、OVEでよいのでは

2008-03-13

アルファでないと言われたGIGAZINEが有名ブログに認定される

詳細はこちら

http://d.hatena.ne.jp/Monar/20080312

GIGAZINEアルファブロガーでない理由

http://blog.livedoor.jp/dankogai/archives/50827276.html

そして、こっから私の意見

それ以前に小飼弾アルファブロガーなのでしょうか。

アルファブロガーという定義をあまりにも小飼さんやその他の人たちに都合のいいものに勝手に定義していないでしょうか。

アルファブロガーの定義をGIGAZINEショコタンを除外して省く様に定義しておけば、確かに絶対にGIGAZINEアルファになれるはずもありません。

GIGAZINE世界的に見ればまちがいなく、小飼何某よりも影響力の大きいブロガーです。

本の書評ばっかり書いてる人が自分をアルファだと語ってるようじゃ世界の笑いものです。

様々なジャンルニュースを紹介してとんでもないアクセス数を叩き出すGIGAZINEというサイトと、

本の書評だけを紹介する井の中のサイト、どっちがアルファでしょうか。

どっちも自分が有意義と思ったものを宣伝行為をするブログという点では同じだと思いますが。

小飼さんだけを書きましたが、いじりやすかったからです。他のブログも同じテーマGIGAZINEアルファブロガーでない理由を

小飼さん以上に熱く語っています。なぜ定義がおかしいと気が付かないのでしょうか。

そっくりそのままコピペ

http://d.hatena.ne.jp/Monar/20080312

2008-03-12 Observer紙が選ぶ!世界ブログ50選にGIGAZINEランクインしてる件 CommentsAdd Star

The world’s 50 most powerful blogs

はてなアルファブロガーズ涙目wwwww

これによると、

Gigazine is the most popular blog in Japan

だそうですよ!

ちなみにこのランキングが掲載された別冊子には10位にランクインしたGawker, Manhattan Media News and Gossipのニック・デントンのインタビューも載ってます。

15のブログを運営して、推定で1億4000万ポンド稼いでるとか。

プロブロガーってマジで存在するんだね!<<

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


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