「MovableType」を含む日記 RSS

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

2022-03-11

WPだいぶ使いやすくなってるな

10年前はちょっと込み入ったことしようとすると汚えコマンドライン編集画面誘導されたんだが、今そんなことないな

ようやくワープロ感覚で使えるツールになってるわ

MovableTypeとかもう消えたんか?Drupalはまだ生き残ってるみたいだな

2020-04-12

[] Tofu on fire

日本幼稚園でよく使われる「チューリップの名札」の絵文字(📛)のこと。海外ではチューリップの名札にあまり馴染みがなく、また、それが「燃えている豆腐」に見えることから

様々な呼び方があったようだが、「Tofu on fire」というワード自体は、2014年Twitter投稿が初出のようだ。

※このTweet引用した記事は、昔はてブで上がっていましたね。すっかり忘れていた。(https://twitter.com/cabel/status/513444503345037312 

絵文字自体の初出は、2002年au携帯実装された「Type C-2」(https://emojipedia.org/name-badge/

Tofu」にまつわる名称として、Webサイトテキスト表示に利用されることがあるGoogle製の「Noto Font」は、「No More Tofu」という意味から名付けられている。

由来は、デバイスフォント表示に対応していない(フォントインストールされていない)場合に、表示されるべきテキストが四角(□)に代替表示されるが、それが豆腐と呼ばれること。そして、それを「世界から無くす」ということから

ちなみに、「tofubeats(音楽アーティストとして活動)」氏のご実家は、豆腐屋ではないとのこと。名前は大体雰囲気で決めたようだ。

また、Six Apart社が展開するCMS製品MovableType」の公式キャラクター「トフくん」は、綴りが「Toph」であり、豆腐とは関係ないようだ。

2016-09-17

起業しない理由

古参ネット使いとして苦言を申すよー。

私はWEBデザイナー12年目。

紙もできる。ポスター、チラシ、雑誌のページ。

WEBコーディングは当たり前。エディタmiで直打ち。

CMSは3つ扱った。

drupal

Wordpress

movabletype

周りは独立していった人も一定数いた。

だが私は会社員を望んだ。

その理由を下記に述べる。

1.サラリー

私は恵まれたと思うくらいの会社所属している。

有給年間20日。夏休み5日。毎年年休はほぼ使い倒す。

夏休みも、5日フルにとり9連休にしている。

給料女性平均よりちょい上。

2.面倒くさい顧客シャットダウン

周りに恵まれているのである

営業さんや上司が間に入り、アホなことを言う奴らを丸く収めている。

アカ20校目とかない。

3.営業苦痛

起業したとして、いまの年収を考えると4倍の収入が得られなくてはならない計算だ。

無理。

そんなスキルあったら別の事で生かしてブイブイいわせてるわ。

4.私も青かった

くせーくせー青くせー。

高校進学校に行き、日教組と反発し。映画が撮りたくて専門学校に行く為に一年バイトして学費を貯めた。

行った専門学校はクソで。

しょーもない日雇い派遣で末端を見た。

瓶にヒビが入ってないかひたすら検品をする8時間

フォトショイラレが使えるだけで日の目を見ることができた。

5.脱線したな

まあ、あれだ。ブロガープログラミング知識はいらないぞ。

それhtmlとかcssでいけるぞ。

もしくはJavaScriptとかjquery

あとPHP

ハローワールドーとか書いてよし!とか思ったらウェルカム

ブログプログラミング始めました、とかかいたらアウト。

2016-04-22

前略、はてな様。(前編)

まずは、大変遅ればせながらはてな上場おめでとうございます。2ヶ月遅れですが。

私は一、はてな無名ファンです。

先にお断りしますと、この文章は長いです。12,000文字近くあります。そう言えば最近「長すぎて読めない」ってタグ見なくなりましたね。

元々は数日前に自分のブログに投稿したのですが、アイコンを見てもIDを見ても誰にも認識されていないであろう私がこんなことを書いているのも気持ち悪いような気がして、衝動的に消してしまいました。そんな文章ですが、せっかく書いたので思い返して増田に投下します。それでも交流のある僅かな方からは、「あ、あいつだ」とすぐバレると思いますが、全く構いません。

大げさな振りをしてしまいましたが、この、はてなの世界からゆるやかに距離を置こうと思いまして。

ハイコンテクストな話題で、関係者でも有名ユーザーでもない私が語るには随分と分不相応であろうことは承知しているのですが、私は人知れず長年このはてなという会社とそのサービス利用者でした。たぶん、相当熱心なファンのほうだと思います

しかしこのはてなという界隈、おそらく長年世間一般的には「俺ははてなが大好きなんだー!!」とはなかなか言い出しづらい雰囲気と言いますか、一部一種のギークナードか?)臭さみたいなものから逃れられないセグメント感があったために、公の場であまりそれを声を大にして語る機会が無かったという状況があったような気はしています

勝手な想像ですが、よく言われるとおり先日上場した株式会社はてなとしてはきっと、そういった閉鎖的なカルチャーからの脱却を図る必要があるのは事実なのであろうと考えています

私は「はてな界隈」という自然発生的な、「インターネット好き」が作ったプラットフォームコンシューマージェネレイテッドなコンテンツが組み合わさってできた若干マニアックな文化がとても好きで、かつてインターネットに期待していたワクワク感のようなものを自分の感性ともっとも近い形で目指している会社だなと思っていたので、はてなを好んで使っていた理由も、今これを書いている理由も、サービスが向かう方向性とのギャップが発生したということで仕方ないのかな、と考えてはいます

回りくどい書き方ですが、つまり、ここ最近(数年)の急激な利用者層の変化、人気ブログホッテントリに上がってくる記事とその使われ方の変化、新たな利用者層との精神的摩擦に疲れて消耗するのが嫌になった、ということです。

私は自分の楽しみのために自分が面白いこと書き、読むっていうスタンスで自分のスペースを使ってきたので特定のユーザー群を非難するのはその趣旨とズレるし、メタな「ブログ論」を書くつもりは無いんです。なのでわかりやすバズワードは書きませんけど、要は、そういうことです。お察し。


ここまで書いておいてから自己ツッコミを入れますが、私がここでこんなことを書いていても、おそらくそれほどの価値は無いのでしょう。

私は長年使っているとは言いながらも、所謂はてな村」と言われるような有名ユーザー層に所属するようなアカウントではないし、特別人に見られるコンテンツを上げていたわけでもコミュニケーションを取っていたわけでもないし、こんなことをグダグダ書いていても「知らない人。気持ち悪い。」で片付けられてしまうような気はします。

コンテンツもお金も落としてもいないアカウントですので、ある意味運営側の立場から見れば、「うるさいことだけごちゃごちゃ言って全くサービスに貢献しない面倒くさいアカウント」あるいは「フリーライダー」と言われても仕方がない気がします。

これは別に被害妄想を語っているわけではなくて、自分がサービスを利用して得たメリットと、お客さんとしての価値を第三者的に見た時、そういう風に判断されてしまっても仕方ないかな、と冷静に思っただけです。

最近はてなブログブクマを見ていて、「これは自分には合わないな」と思ってケチを付けたくなる機会が多くなってきたことと、でも、ケチを付ける発言力(あるいは権利)のバランスを天秤に掛けて、ああ、もう自分が楽しく見ていられる場所ではないのかな、と感じることが増えてきたことと、単なる1ユーザなのにそんなことを考えてしまうこと、考えさせられてしまうことが嫌になってきてしまったということがあって、こりゃ、私の居場所はもう無いのかもしれないな、と思いつつあるということです。

かつての掲示板サービス群から始まってブログランキングやら、SNSやら、インターネットサービスではいろんなところでこのような文化の変遷みたいな場面は見てきたはずなのだけれども、思ったより自分の生活の大きな部分にはてブが入り込んで浸透していたことに自分でもかなり驚いていますね。

前提としてなぜ、こんなマイナーキャラの私がそこまで一、ネットサービスに入れ込んでいたのかについてちょっと語らせてください。長くてすみません

私のはてな歴は12年くらいです。長かったらどうだというわけでは無いのですが、はてなを知ったのはまだ人力検索しか無かったころで、自分が実際にユーザーになったのは例の「日本人にはブログより日記」のちょっと後、「はてなダイアリーはてなブログに名称変更」とかエイプリルフールネタでやっていたころです。最古参ではなくて、ブログブームの頃に「はてな界隈」を意識するようになったので第2世代くらい、ということになるのでしょうか。

その後アカウントが一回変わっていて今のIDは5、6年くらい前に取りなおしたものなので、おそらく古参ぽさは無いですね。

はてなには他社のサービスと比べてとりわけIT系ユーザー比率が高いと思いますが、私もそうです。一貫してネット関連ですが完全な同業というわけではなく、何度か変遷を経て今は流通系事業会社インターネット事業担当になったというキャリアです。

はてなのサービスを認識した時はちょうどMovableTypeの2.6あたりが日本でも流行りだした頃で、「Web日記がhtml無しでこんなに簡単にできるなんて!」「コメントとかトラバとかすげー!コミュニティ作れまくり!」とかっていう話題で日々興奮していたのを覚えています90年代後半からネットは見ていたけれど、これからいよいよ「普通の人」にもオープンに普及していくんだなー、と夢描きながら仕事で、あるいはプライベートでどう活用しようか考えていたんですよ。「Web2.0」より2年前くらいのことですね。

その頃、ちょうどあるECサイトコミュニティサービスの担当をしていたんですね。いろいろやりましたよ。掲示板サービス炎上して閉鎖に追い込まれたり、画像著作権で揉めたり、ブログが使えるようになってからは、「ブログ商品の宣伝を書いてリンクを貼ってくれたら100ポイント!!」とかい現代であればGoogle警察が1日でぶっ飛ばしにくるようなプロモキャンペーンもせっせこ考えては公開してました。更にその後はOpenPNEベースのmixiっぽいSNSをやったりとか。

今考えるとうわーっていう企画も多かったのですが、おおらかながら大真面目にやってたんですよ。まじめに、ライトユーザーに使ってもらうにはどうしたらいいかとか、コアユーザーがどう伝搬してくれるかとか考えてました。その頃は(ネット上のマーケティングにおいては)セグメントの乖離とかそういう問題も今ほどは研究されていなかったし、たぶん自分でもまだ十分理解できてなかったんですよね。私はそんな感じの人間です。


自分語り方面脱線したので話を戻しますが、ブログブームちょい前の頃、世の中で出始めたブログアカウントを片っ端から取っては試すということをやっていたんですよ。ココログはてダから始まって、livedoor、goo、ExciteSeesaaJugem、FC2、楽天、MSN、ドリコムウェブリブログドブログYahooヤプログ、アメなんたら……

でですね、そのときにはてなの特異性に気付いたわけです。

なんだこりゃ、殺風景サイトだなぁ、なんか研究室みたいだなぁ、システム屋くさいなぁ、ってのが当時の正直な印象です。まったく間違ってないと思いますが。

ダイアリー以外の他のブログサービスはだいたい大手キャリア系か、大手ポータル系か、大手ホスティング系のいずれかじゃないですか。実際仕事で関わることがあったのはそういった会社さん達だったわけだったんですけど、私個人的にはこのはてなダイアリーってやつにとても興味を持ったんですよね。

純粋にIT系オタク集団(失礼)がコミュニティで勝負するっていう構図のサービスがすごく面白いなって思いまして、当時から実際にIT系のギーク技術記事とか、濃厚なネットのいざこざとかそういうのがぐちゃぐちゃと集積されつつあって、うわぁ危険と思いながらもはてなだけは明確に識別して見に行く感じになってたんですよね。

人力検索もそうですが、アンテナとか、キーワードとか。私はネットコミュニティをやりたくてこの世界に入ってきた人間なので、人と人をつなげるサービス、というコンセプトに対して面白いことをやろうとしている人達がいるんだなーって思ってたんです。こんな殺風景非コミュ論壇だらけのサイトなのに。なんだかそのギャップがまたすごく居心地が良くてね。よく閉鎖的って揶揄されるはてなですけど、私はそんな風に思ったことなかったな。

そう、私は村感というよりは、僻地の秘境だけどここは自由でオープンだ、っていうように感じていたんです。

今はなおさら顕著ですけど、その頃って既にインターネットサービス外来大手サービスに集約されつつあったじゃないですか。ブログにしたってMovableTypeWordpressも外から来たものだし、MySpaceとか、Facebookもそうだし、その後の流れって周知のとおりって感じじゃないですか。強いて言えばmixi……はやっぱべつにいいや。

そんな中、日本ドメスティックな小さなネットベンチャーが純粋なコミュニケーションの仕組みだけで世界観を醸成して、しかも生き残るっていうことに夢を感じたんですよ。まあ、ドメスティックっていう部分について言えば、jkondoさんが渡米した時期とかあったなぁ、とかあるんですけども。

はっきり告白しますけど、私のような自分で新しいプラットフォームを開発するほどの実力が無い中途半端ネット屋にとって、超恥ずかしながら彼らはヒーローだったんですよ。jkondoさんやnaoyaさんは私とほぼ同い年ですけど、勝手に同世代ヒーローだと思ってたんですよ。

はてなブックマークソーシャルブックマークという概念を身近に体験した時は「単なる『お気に入り』じゃなくて、興味を持ったものについて何時でも語り合える世界が作れるんだなあ」ってリアルに衝撃を受けたし、スターが登場した時は(FacebookTwitterより前に)これ、シンプルだけどもしかして世界を幸せにする機能じゃね?って感動したりしましたよ。

だいたい、jkondoさんはすごいんですよ。私など勝てる要素が無いですよ。スプリントでもロングでもヒルクライムでも絶対勝てないですよ。山も強いし、みんな山手線一周1時間48分てできます??サラッと書かれてたけど、メチャクチャ速いよ!!俺も何度もやってるけど、大真面目にやっても3時間切るのだって大変だよ。明治通り中央通りはともかく、田端駒込あたりの裏路地とかどうしてたんでしょうね。メッチャ危ないよ!!つか、あの頃の自転車クラスタみんなどこ行っちゃったんでしょうね……

何の話でしたっけ。そうそう、趣味が合いそうな人達が集ってるっていう話でしたね。

私の文章は、テキストサイトからアルファブロガーあたりまでの文章にめちゃくちゃ影響を受けていると思いますちょっと極端なことを書いたら「フロム先生の真似か」とツッコまれてドキッとしたり、写真クラスタの真似をしてやたらでかい写真を並べてみたり。最近は年に一回お正月だけに現れるmk2さんの文章を見ると涙が出そうになります。長文には慣れています。必死に調べないとついていけないような技術論議や、内蔵をさらけ出して書いたような、編集が入った本では読めないようなブログを読みたいし、そういう記事でみんなが共感していく世界が見たかったんです。

はてなブログ目次記法は便利だと思うんですけど、他所ニュースサイトに貼られた記事を引っ張って目次を並べていかがでしたか?なんていう記事を、私は単純に面白く読めないんですよ。「参考になりました!」じゃねーよ!!ならねーよ!!残念すぎるだろ!!なんて思ってたんですよ。

ここまでで既に5,000文字を超えてしまいましたが、話が飛んでしまったので一旦元に戻します。

まり、そういった「自分の好きなものを好きと言う」「好きなものを選んで、好きなものを見て共感する」という、人の本能的なコミュニケーションの楽しみの源泉のようなものを、私は求めていたんだと思います。自分の背中に正直な、泥だらけのスニーカーで追い越すような体験を期待していたんです。

もちろん、どんな時代にだって人と人のコミュニケーションにはいろいろあって、変わらないものがたくさんあるんだとは思いますよ。パソ通の時代だって、BBSの時代だって、初期のブログだって、「読みました。記念カキコ☆」はあったし、コメント欄で交流が繋がって新たな友達ができるという興奮だってあったし。

最近はてなだって、今、その興奮を新たに体験して純粋に喜びを感じている人達がいるはずだしそれはもちろん喜ばしいことなんですけど、さすがにこの情報過多なご時世なので、ツールと場所の管理と運営をしっかりやっていかないと、純粋な喜びを埋もれさせず、コンテンツの品質を保つのは相当に厳しいなという実感はありますね。

一般化、大衆化、というものはだいたいそうで、単純に「この村も昔は良かったのに」っておじいさんが言っているっていうような話ではないと思うんですよ。

こんなことを話している私自身が既にネット上では「古い側」の人間になっているのかもしれませんが、個人的には、「はてな村」とかって言われている界隈にそれほどイライラするような内輪感を感じたことは無いんですよね。実際にひどい攻撃的な言葉が飛んできて嫌な思いをしたことだってありますし、慣れ合いとかってのは昔も今もあるわけなんですけど、だいたいは好きなことを好きなように書いた、っていうモチベーションによって書かれた記事は、面白ければ当たるし、面白くなければ流行らないわけじゃないですか。読む側だって気に入ったら読めばいいし、気に入らなかったらスルーすればいい。だいたい、広い世界で見ればごく一部のできごとだっていう側面もあったわけじゃないですか。

だから、一定の、嘘を嘘と見抜ける程度のネットリテラシーさえあれば、海水浴場の中に浮かぶ邪魔漂着物があっても、農耕地が石だらけで荒地になっていても、単に避ければいいだけだって思ってたんです。

むしろ、良い記事にフォローが集まったり、ひどい記事はひどい記事でそれに集まった批判が有益だったり、そうやってやり取りを応酬する中で集合知として収斂されていくという光景は、みんなで海を掃除したり、畑を耕していくような感覚を覚えていつもネット醍醐味であり爽快ですらありました。


……でもね。最近の例の動向はちょっと様相が違っていて、私のようなユーザーにとってはもうちょっと見ているのが厳しいな、というのが本音です。商業的なまとめサイトが場を汚染している、というような話であればユーザーコミュニティによるチェックと自浄作用が働きますはてブうまいことそういう機能果たしてきたと思うんですよね。

でも、ユーザー側のほうで「良いと思ったから良いと言った」というお気に入りによるキュレーション機能が働かず、返報性の原理によるコミュニケーションが中心の場になってしまったら、今のままのはてブでは、(コメントツールとしてはともかく)少なくとも情報ツールとしての価値は大きく毀損されます。これは、ユーザーモラルもありますが、サービス構造上の問題として避けられなかったことだと思うんですよね。


海や畑が全部「あれ」になったら、もうどうしようもないでしょう。もう去るしかない。

この問題についてはさんっざんぱらたくさんの人に書き尽くされているのでここでは書くつもりないんですけど、小遣い目的で面白くない記事が量産される、共有のヘッドライン専有されて他のユーザーに影響を及ぼす、内容に関係なく相互フォローする、これらは本人の意識あるなしに関わらず、関係ない人から見たら無益です。

これについてルール違反がないのならば、サービス品質を維持するための運営/システム側の構造課題を疑ったほうが良いし、ユーザー側についても、一部の炎上チャリーンで喜ぶようなやつは単なるスパムなのでこれは単純な絶対悪ですよ。

別にネットの世界で今始まったことじゃないんですよ。むしろはてブ牧歌的で今まで性善説でよくやってこれたなっていうレベルじゃないかと思いますTwitterでも「相互フォロー推進委員会」とかあったなあ。一方的に何百人単位でフォローしてきて、ふぁぼりまくって、こっちが反応しないと砂をかけて去っていくようなのが……

ただそういう人達ごにょごにょ楽しくやってるだけならどうだっていいんですけど、今はホッテントリが明らかに使いづらくなっていたり、更には他のSNS経由でこの界隈の記事が流れてきて反応したらおかしなことになったり、実際にそういうことが発生しだしているんですよね。これが結構精神的にくるものがあるんですよね。

というわけで、そういう一団がこのサービスのほんの数%、もしかしたら0.数%の人達であり、ほとんどの普通の人は何も気にせず普通に自分の日記を書いているんだ、てことはわかっていても、でももう気持ち的にこの界隈と一緒の世界でブログを書くのは無理かもしれない。既に古参と言われる人達がかなり去っていっているし、生き残っている人達も読者層が急激に変わっていたりとかして、なんていうか、見ててつらい。

最近、ある有名人ブロガーブログを読んでいて、半年前にも同じテーマで書かれたことがある記事がホッテントリに入っていたのを見たんですけど、ふとブコメを見てみたら、半年前の記事と反応のコメントが全然違くてびっくりしたことがあったんですよ。よく見ると、並んでいるアイコンがガラリと変わっていることに気づきました。読者層が急激に入れ替わっているんですね。

この人はムラ社会に寄る人では(読者から見たイメージでは)無いし、長い人とも新しい人ともバランスのいい関係を築けていてすごいなあ、と思っていたのですが、図らずも急激に「有名人」として新規層の神輿に乗せられているように見える状態になってしまって、一方で彼自身は広告収入で儲けているようなブロガーではないし、内心複雑な気持ちなんじゃないかな、とか勝手心配をしていたりします。そういう人、何人かいますよね。余計なお世話すぎるとは思うのですが。

------------------

すみません、長すぎて登録すると切れてしまうので、途中で切ってトラバで繋げます

2015-08-22

日本Web技術界隈著名人の残念さ具合

日本技術者結構割合はてなを見ていると思う

そういう中で有名な人、について分析をしてみる

人気は勿論わかるんだけど、実績で見ていってみて、冷静に、どういう点で有名になって、今何が凄いのか?という点について考えてみる

### 伊藤直也

新卒ニフティはてな転職して、ブログ時代に知名度をあげる

はてブを作って、はてブユーザにとっては神なのかもしれない。はてなCTO

その後、グリー転職し、スマホ事業部長。2015年の大赤字化したグリー

経営問題はあったのかもしれないが、明らかにスマホ事業の苦戦はスマホ事業責任者であった、伊藤直也氏が作ったものだと言ってもおかしくはないと思う

http://www.itmedia.co.jp/news/articles/1009/07/news070_3.html

http://image.itmedia.co.jp/news/articles/1009/07/yuo_naoya_04.jpg:image=http://image.itmedia.co.jp/news/articles/1009/07/yuo_naoya_04.jpg

そして、今はフリー、とかいって優雅に寿司を食いながら技術系の人にインタビューしたり、技術顧問かいって格好をつけているけど、新しい技術にちょこっと手を出し、マスターしたつもりになっているだけで、肝心のプロダクトを出して、それがヒットしたとか、そういうものが無いので、正直何が凄いのか分からない

知名度だけが先行して実力が伴わなかった最たる例であるように感じる

はてな自体PVキーワードリンクスパムはてブブックマークページのペナルティ扱い等、伊藤氏が作った仕組みによって、大きく下落していることも忘れてはいけない。

### 宮川たつひこ

ライブドアブログを作った後シックス・アパート転職

MovableType潰して、Plagger鳴かず飛ばず

http://kessan-kanpo.blogspot.jp/2015/06/13.html

食えなくなったので、Cookpadに逃げ込んだ、というイメージ

この人も人気はあるにせよ、技術観点以外での実績というものがない

### あまちゃん

技術系の人に人気があった、というだけで、具体的に何をどうしたとか、JavaScriptを作った人でもないのにそれっぽく扱われている事にかなりの違和感があった。

ヒットプロダクトがずーーーーーーっとない状態。お花のFacebookプレゼントサービス鳴かず飛ばず

新しく作ったサービスも、200万PVを超えたとかいうことでニュースになっていたけど、200万PVでは到底食えないし、日本トップサービスPVからしてみれば誤差の範疇

http://jp.techcrunch.com/2014/04/21/140421-kactel-pictory/

一向にiOS版が出てこないし、やはりプロダクトを作るのに向いてない人なんじゃないのって思ってしまう。

というか、センス無いよ、と思い続けて5年以上、やっぱりセンスなかったな、という印象。

----

まあ要するに私がいいたいことは、人気、知名度と実力は必ずしも一致せず、

本当にトップサービスやヒットサービスをやっているような人ほど、いちいちブログなんか書かずにプロダクトに集中したり、コードを書いているよねっていう話です。

10年も前からはてな界隈では有名人だけど、今は没落している人が多いように感じるのは、実際の所、実力が無いのに過剰評価されていたことの証明だとは思う。IPO直後の株価のように、やはり実態は平均化される。

勿論、人気も実力のうち、であることは承知してはいるが、実力がないのに過大評価されている状態を見ると、なんとも残念な気持ちになってしまうのでした。

2013-04-25

ロゴ制作料なんて5000円で十分な訳

 

オシャレハットマン家入ホリエモンが「ロゴなんて5000円で十分でしょ」と言って批判されているらしいけど、それってもう英語圏では遠い昔に通り過ぎた話なんですよね。その辺のwebサービスとかのロゴなんて5000円が適正相場になってるのが英語圏現実です。本当に日本人というのは頭が古いと言うか井の中の蛙というか、日本語という壁に守られて温々育っちゃって時代遅れの主張をよーいドンで一斉に始めちゃう恥ずかしい所がありますねえ。

 

英語圏ロゴ制作の現状

そりゃ名だたる企業ロゴだったらそれなりの制作料になるわけですが、小さい企業とかローンチしたばかりのwebサービススマホアプリなどのロゴ10万以上かけて作る人はもう絶滅しました。いません。死にました。今のトレンドは「テンプレートから既成のロゴを選択して、+自分企業名のフォントだけを手作業でデザイナーに入れてもらう」形式です。つまり同じロゴを使ってる企業サービス世界中にたくさんあるわけですよ。たくさんあるって言っても世界は広いかほとんどバッティングなんてしないわけですね。例えば最近見たパン屋さん向けのロゴで人気のものは15件も売れてるわけですが、世界中にいくつパン屋さんってあるんでしょうか。星の数ほどありますね。だから被ってたって問題にはならないわけです。それが2013年ロゴに対する世界の人々の普通感覚です。

 

ロゴ制作ぐらいでクリエイティブと名乗れる時代は過ぎた

インターネットスマホアプリの普及のお陰で、ロゴに対する需要1990年に比べると15倍になったそうです。今や一般のブロガーですら自分ロゴを持つ時代ですからね、そのぐらい増えてても不思議ではありません。それに対して、ロゴを軽く作れちゃうぐらいのデザインスキルソフトを持っている人は20年前から比べるとなんと50倍になったそうです。供給量は需要の伸びを大幅に超えてるんですね。これがロゴ価格低下の最もたる原因の一つです。あんな二次元適当仕事クリエイティブなんてもう恥ずかしくて名乗れない時代なのです。(もちろんトップクラス仕事は別ですよ、あくまで下の方ってこと)

 

実例

こういった傾向は別にデザイン業界に限りません。例えばほんの8年前、2005年当時を振り返ってみましょう。

MovableTypeちょっとしたブログを書いているだけでネットメディアから取材が来ました。

CSSに詳しいというだけで書籍出版できちゃいました。

Ruby on Railsに詳しいというだけでRuby界で一目置かれました。

どれもこれも、今はその辺の20歳大学生でもできるレベルですよね。それがたった8年前はもてはやされてたわけです。

 

クラウドソーシングますます単価は下がる

ランサーズ(http://www.lancers.jp/)などの例を挙げるまでもなく、クラウドソーシングサービスによってますますクリエイティブの単価は下がっています。需給のミスマッチ価格を押し上げる方向に働きますが、ランサーズのようなサービスによってロゴ作れる人とロゴを欲している人がいとも簡単に繋がれるようになって、つまり需給ミスマッチ改善されている訳ですが、それによって何が起きるかと言うとますます価格が下がるんです。当たり前です。どんな世界もこういう風にできてます。この理屈がわからない人は学部一年生が読むような経済学教科書でも読んでから出直してください。

 

ロゴ5000円に反発している人は頭が古い、以上

僕みたいなデザイナーですらロゴ5000円は仕方ないかなと受け入れてますだってブランドCIも無いようなその辺の小さな事業主向けのロゴなんて、理屈理念へったくれも無いわけです。事業主の個人的な趣向に合わせてなんとなーーーく小綺麗なロゴを作るだけの仕事です。そんな仕事はもうまともなクリエイティブを持った人間はやってませんよ。そういう仕事で飯が食える時代はとっくの昔に過ぎたんですね。

 

なんだかこの手の話に毎回妙に怒る人いるじゃないですか。デザイナーでもないのに。なんなんでしょうねああいう人って。誰のために怒ってるの?デザイナー権利のため?それとも社会のために正義を訴える自分に酔いたいから?こんなくだらないことに怒る暇があったら他に怒るネタはあるでしょう。怒るべきネタが。ほんと暇人ですよね皆さん。

 

僕らデザイナーは怒る暇があれば勉強します。僕は毎日2時間割いて、新しい技術世界デザイン趨勢・他文化勉強・異業種との情報交換・ヘルニアにならないための運動などなど、生き残る為に必死で頑張ってます。怒ってる暇があれば勉強するのがどんな世界でも生き残るための唯一の策なんですよ。デザイン業界グローバルな流れも知らないで、感情論で「5000円は安い!人権侵害だ!」って、そういう人はサヨク活動でもやってたらいいんじゃないですか。もうそういう時代じゃないんです。

2013-02-15

オープンソースアプリ無料で利用できるホスティングサービス

始めました。

http://www.plagnet.com/

今のところmovabletypeが利用できます

評判良くなければ停止するかもしれませんが、MTブログ書きたいけど無料の所ないかなーとか、セットアップめんどくさいーって人にお勧めです。

なんでwordpressじゃなくてMT? perlが好き。

テンプレとかプラグインとかデフォルトのままです。

2011-03-30

http://anond.hatelabo.jp/20110329150439

MovableTypeのコアはPerlだ。

ちなみにPHPerの主戦場Web業界

JavaできてもServlet,JSPが下火だからWeb業界ではメシ食えない。

それよりRubyPerlおすすめするよ

2011-03-29

典型的PHPerの13の悪癖

PHPerの問題点は、視野が狭いこと。典型的には以下のような悪癖を持つ。

何も知らないかPHPを愛せるんだよ、PHPerは。だからまず、HTMLCSSJavaScriptSQLを覚えろ。次に、Javaに移行しろ。そんなに難しくないよ、Java。特に大量にコードを書けるPHPerは、速度が出てライブラリ化が容易なJavaの方が向いている。今はVPSがあるので、小規模案件でも問題ない。

15年間ほどPHPインターネットを支えてきたが、そろそろ設計の脆さが問題になっている。PHP 6の開発が振り出しに戻ったのは、不幸な事故はない。ウェブ仕事をしていれば、PHPJavaで共通する知識も多い。PHPerはJavaを覚えてPHPさよならしろ。そして恥ずかしい悪癖を直すべきだ。

2011-01-15

12時間ほどでTwitter連携webサービスを作った記録

2010年年末から年始にかけて10連休ほどあったので、新しいサイトを作ろうと思い立った。

自分スペック

何を作るか

小遣いを稼げるサイトしたい、とまず思った。

月に1万円だと、毎日コーヒーを飲んでるだけでなくなってしまうので、コーヒー代くらい稼げたらうれしいなあ。じゃあどうする。何を作る?

ということで、まずTwitterを使ったものを作ることにした

テーマ

ひとつジャンルにしぼってツイートをかき集めれば、面白い流れになるんじゃないか。人が来るんじゃないか。そう思った。togetterたいな。で、ジャンルは、個人的に興味がある子育て。ていうか毎日帰宅してから朝まで子どもの寝かしつけや夜泣き対応サイト更新する暇も、俺が寝る暇もあんまりない。ので、手がかからないことが大前提。なんだったら自動更新でもいい。

自動更新かー。と思って「ブログ 自動更新」でググったら、wordpressRSSから更新するプラグインがあるらしいことを知った。はい決定。その瞬間、「TwitterAPIからRSSを引っ張ってwordpress投稿するサイト」に決まった。

やってみた

12時間は実装を初めてから時間になります

1時間

さくらインターネットスタンダードを申し込んだ。14日お試しがあるらしいけど、仮申し込みの時点で住所も入れてコンビニ請求にしたら、数日後に請求書が送られてきてビビった。(同時にドメインも申請しちゃった)

まあ、webで申し込んで、すぐにサーバコントロールパネルという画面に入れるようになった。「クイックインストール」というリンクがあったので見てみたらMovableTypeWordPress自動インストールしてくれるらしかったので、ボタンを押したインストールできましたというので発行されたURLクリックしたけど404だった。1時間くらい404で、その日はもう寝た。

2時間

次の日の夜。これはもう、10連休を利用して毎晩1時間ずつ捻出するしかない、さくらのお試し14日あるから約14時間で作りきるしかねえ、と思った。

サイトアクセスしたwordpressが入ったページが出てきた。おお、サイトができてる!

まずTwitterを調べるか、と思って、「Twitter API」で検索したけどOauth?とかいう面倒なことをしないといけないらしかったのでやめた。じゃあ普通に検索は?と思って「Twitter 検索」で検索したら、search.twitter.comの結果はjsonatomで取得できるし、APIコール制限もないらしいのでこれに決定。検索だけで1時間たった。

3時間

夜も更けて、続けて作業した。「wordpress xml 投稿」で検索していくつか探したらFeedWordpressというプラグインがあったので入れた。あ、事前知識としてMovableTypeでのブログはやったことがあったので、プラグインを入れるみたいな話はスムーズに進められた。

で、twitter検索結果をatomで返した結果を入れてみた。ら、本当に投稿されてた。よっしゃできた、と思った。1ツイートが1エントリになってたし、投稿者もツイートした人になってた。よかった。でも、満足できなかった。

4時間

次の日。同じことを自力でやる方法を探した。「wordpress xml 投稿」で検索して、XMLパースできるようになればいいんじゃないかと思い、simplepieというPHPライブラリにたどり着いた。が、PHPなんてまったく知らないし、憶える気もなかった。actionscriptで書かせてよ、とずっと思ってた。

5時間め・6時間

次の日。「wordpress xml 投稿」でまた検索。どうやらwordpress投稿って、xmlrpcというやり方を使ってるらしかった。ので、「wordpress xmlrpc 自動投稿」で検索したら、なんかサンプルコードが載ってたのでそのまんまコピペ(結局PHPだった)。したらちゃんと投稿されていた。ふむ。ここで何を思いついたのか、「wordpress xml パース」と昨日みたいなことを検索した。simpleXML?というライブラリがあるらしかったので、それを試してみることにした。(たぶんPHPが動いたので気をよくしてたんだと思う)

こういう流れでいけると思った。考え方はactionscriptエディタに書いて、ノリであてにいった。変数に宣言するのはできた。$var1とかで宣言したことになるらしいURLRequestに相当するコードを探したら「file_get_contents」らしいことが分かった。(「PHP 外部ファイル」で検索

で、ゲットしたのはXMLなんだけど、上記検索したかにたまたま書いてあった「simplexml_load_string」というのを使うとXMLパースできそうな気がしたので、ノリで書いたactionscriptでは

var req:String = "http://search.twitter.com/?q.atom=mogemoge";

var r:URLRequest = new URLRequest(req);

var kekka:XML = r.send() as XML; ←いまここ

なので、XMLキャストしたんだろうなみたいな感じだった。E4Xを使えればいいのにPHPって馬鹿ねと思いながら寝た。

7時間

年があけて、3が日が終わりそうだった。年末にやってたこと(上記までのこと)を思い出しながら、XMLの必要な部分だけ抜き出す方法を模索したatomっていってもentryがたくさん入ってたか配列にするんだろうけど、ってんで「php foreach」を検索。なんとなくサンプルコードをまねしながら、記事タイトル、記事本文だけ取得した。あとはxmlrpcのサンプルにあわせて投稿するようにした。できた。寝た。

8時間

次の日の朝、ブログを見た。昨日更新したのしかあがってない。自動じゃねーじゃん。

で、「自動 投稿」で検索したら、クローン(cron)という仕組みを使わないといけないのだった。クローンサーバの仕組みらしく、そういえば俺はPHPをはじめDBサーバという単語を極力さけて仕事してきたので、もう気持ちが悪くなってきた。「さくらインターネット cron php」で検索して、なんとかやり方を見つけて、cronを登録した。(1時間に1回にした。設定は * * * 0)

9時間

仕事から帰ってきて、サイトを見ると、投稿が大量にたまっていた。やった!で、調子に乗ってツイッターアカウントを作った。なんだったらツイッター自動したかったので「twitter bot」で検索した。Easybotterというサンプルボットがあったので使わせてもらった。自動で一行ずつつぶやくようにした

時間外)

サイトテーマを考えてた。通勤電車で悶々とする時間

ツイートを集めることは成功したけど(毎時間100件のツイートを1エントリとして投稿してる)、それを眺めて面白いんだろうか? ボットを動かしてるけど人がくるんだろうか?

そんなとき「trivist」がはてブに載ってた。なんかにたものを感じた。やっぱツイートを引っ張ってきて投稿するサイトはアリなのか?アリなはずだ!

10時間

サイトの体裁を整えた

11時間

trivistをまねて、記事を評価(はてなスターかいいねボタンかにいもの)する仕組みが欲しくなった。「wordpress 評価 プラグイン」で「wp-postratings」というプラグイン発見して、入れてみた。どうやら1エントリーに1評価しかできないらしい。俺のサイトは1エントリーに100ツイートあるから、どのツイートを評価するのかが分からない。

いったん、wordpressの全投稿を削除した。で、cron に登録されてるPHPを、1記事に1エントリーした

12時間

エントリー投稿するついでに、Yahoo日本語解析APIをつかってツイートを分析して、名詞動詞だけを取り出そうと思った。それをタグにすれば、タグクラウドが作れると思った。はてブはずっとずっと昔からやってるからYahoo日本語解析っていうのが2006年くらいに流行ったことをなぜか憶えてたので、やってみた。できた。

なんか俺、PHP書くのが早くなってね?

そして微調整をしながら今に至る

アクセス解析を入れてみた。サイトに来てる人は、俺だけだった。

どうにかして人を増やしたい。サイト広告募集はする気がないしベタベタバナーを貼りたくなかった。みんなが気軽に見に来て、軽い気持ちで評価してくれて、更新を楽しみにしてくれるサイトしたかった。コミュニティサイトじゃないけど、やっぱりサイトコミュニケーション設計をしないと意味がないんじゃないか、見てくれるユーザはどうやったら楽しいんだろう、ということを考え続けて10日ほど経った。Twitter経由で来てくれた人が3人ほどいるようだけど、何がダメなのか分からないので増田にお願い。


ここまで書いて教えてくんじゃねーか、と思われるかもしれないが、ググレカス的な検索は上記で書いたみたいにいろいろやってきた。でも、サイトを作ってみてはじめて、ユーザに向けたサイトってどう作ればいいのかが分からないということに気づいた。

小遣い稼ぎもしたいんだけど、面白いサイトを作るヒントがほしいと思った。

kanzen21やtrivistみたいに、俺も過程を全部さらしたから辛辣意見を求む。そしてはてブされるのを待ってます

http://kosodate-now.com/

2010-09-07

IT系とかそれ以外のスキル列挙するから何ができそうか教えて欲しい

色々教えてください偉い人。

自分で考えろってのはご尤もですが、色々な方の意見が聞いてみたいのです。

純粋Java(max5000行程度)

Struts(ver2じゃないほう)上でのJava(max2000行程度)

perl(max7000行程度)

c/c++(ちょっと)

Haskell(ほんの少し)

VisualBasic.NETじゃないほう)(ほとんど忘れた)

HTML/CSS(セマンティック厨)(HTML5勉強中)(バイトWEBデザイン経験有)

javascript(簡単なものなら)

XML/XSL自作プログラムI/Oに利用)

MovableTypeCMSとして利用。ちょっとした企業サイトレベルくらいのものの構築。簡単なプラグイン作成とかも)

Apache(セットアップと最低限の設定くらい)

Tomcat(同上)

LinuxCentOSUbuntu。セットアップとちょっとした設定程度)

IPA資格ソフトウェアネットワークデータベース

Tex論文プレゼンテーション作成

AdobeDTP製品(CS2)(雑誌編集経験有、ただし学生レベル

Oracle10g)(Bronzeレベルの知識とちょっと触ったことがある程度の経験

postgreSQL(ちょっと触ったことがある程度)

会計関連の知識(日商簿記2級)(大学管理会計をかじった)

数学系の知識(論理とか集合やらの基礎。大学計算機科学をかじった)

印刷物/WEBサイトデザイン(独学だけどそれなりに。一般人よりはそれっぽいデザインが作れるかと)

・文章/記事作成(取材→記事執筆。文章校正経験有)(随筆みたいのは無理)

漫画ゲームが大好き

2010-04-24

http://anond.hatelabo.jp/20100424103036

Wordpressサイトリンクを貼ったのが、営業妨害と受け取られたということ?

デヴィ夫人が続報を書かれたようなので、MovableTypeWordpressをやんわりとおすすめしてみた。

今のところコメント欄に反映されているみたいだけど、これも消されるのかな?

2007-07-25

http://anond.hatelabo.jp/20070725223426

ドキュメントメタデータ作成

これは現行のブログシステムによって既に実現されているよ。それが読み上げブラウザに優しいかどうかは別だけど。TeXで書いてtex2htmlでHTMLに変換してもいいし。メタデータ作成の自動化は案外存在する。いまさらスクラッチからデザインやらメタデータ作成やらをやるのは効率悪いと思う。どうしても実現したいデザインブログシステム等では出せないのなら、プログラマ雇って、Movabletype改造させるのも一つの手かな。

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-11

http://anond.hatelabo.jp/20070711134301

何かのアカウントを作る必要がないのがいい

ってあるじゃん

まさにそこ。

機能を得るための労力と、そのある意味わがまま(こだわり)と言える要望のどっちを取るかを取捨選択するのが分析作業だと思う。

たかだか内々での連絡に使用する用途が、携帯の固有番号とひもつけられる事によって本当に問題になりうるのかと言うのも判断すべき点かな。

と言うかむしろ「家族全員携帯持ってねぇよ」と言う問題の方がありそうで、mixiを捨てる致命的な理由になりそう。

後の候補は

通常の掲示板を、.htaccessが使えるサーバに設置してBASIC認証を掛けるとか、

MovableType使って非公開ページを運営するとか。

そもそも質問する人間の技量レベルが提示されてないから、提案もできないってのが本音。

2007-06-11

文を読んでやめとけと思った

Movable Typeローカルで動かしたいんだけど

そういうことって出来るの?CGIデータベースの仕組みがイマイチわかってないのだけど、データベースを用意するだけでおk?それともそれだけじゃ駄目?

できます。と言うかできるか判らない時点で冒険しないほうがいいよ。(理由:答えを見つけるに足る知識がまず無いから)

複数ユーザ日記書きたいんだけど、Movable Typeなら出来るらしいから使ってみようかなーと思ったしだいなんだけど、はてなユーザ切り替えよりは楽だよね?

ユーザの切り替えに限って聞いているんだろうけども、総合で言えば

1から環境構築しなきゃいけないサービス(自鯖MovableType)が、既存の利用するだけでいいサービス(はてな)より簡単な理由は一つも無いぞ。

アドバイスください。

・自分ところで動かすために、自分の所でサーバを立てるか、レンタルサーバを借りる。

・自分の所ならPHPとDBをインストール

MovableTypeインストールする(簡単インストールサービスとかやってるとこもあるから探そう)

日記を書く。

メンテナンス等々実際にやりたい事以外の作業も全部自己責任なので、面倒でもがんばろう。

2006-11-22

匿名ダイアリー開始に際して

ブログは、我が国にとどまらず、世界のWebの流れのなかで“小さな巨人”としての地位を築いてきた。古今東西の名文を、無料で手に入れやすい形で提供できるからこそ、人はブログを自分の師として、また青春の想い出として、書きついできたのである。

その源を、文化的にはSixApartのMovableTypeに求めるにせよ、規模の上でGoogleBloggerに求めるにせよ、いまブログインターネット利用者層の多様化に従って、ますますその意義を大きくしていると言ってよい。

ブログ意味するものは、激動の現代のみならず将来にわたって、大きくなることはあっても、小さくなることはないだろう。

はてな匿名ダイアリー」は、そのように多様化した対象に応え、ブックマークに耐えうるエントリを収録するのはもちろん、Web2.0を迎えるにあたって、既成の枠をこえる新鮮で強烈なアイ・オープナーたりたい。

その特異さ故に、この存在は、かつてブログがはじめてWebに登場したときと同じ戸惑いをブロガーに与えるかもしれない。

しかし、<Changing Time, Changing the Internet>時代は変わって、Webも変わる。時を重ねるなかで、精神の糧として、心の一隅を占めるものとして、次なるWebの担い手の若者たちに確かな評価を得られると信じて、ここに「はてな匿名ダイアリー」をリリースする。

元ネタ

http://d.hatena.ne.jp/kenkaian/20061113/1163411855

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