Hatena::Groupsubtech

NaN days

ブログを移転しています。最新の記事は motemen.hatenablog.com へどうぞ

2013-02-12

自分だけのオリジナルなフレーズをツイートできる userscript

| 13:24 | 自分だけのオリジナルなフレーズをツイートできる userscript - NaN days を含むブックマーク はてなブックマーク - 自分だけのオリジナルなフレーズをツイートできる userscript - NaN days

「これは新しい! ツイートすれば 100 fav 間違いなし!」なフレーズを思いついたとき、賢明な方々は

  1. 念のため一度 Google 先生にお伺いを立てる
  2. 一件もヒットしなければ満を持してツイート

という手順を踏んでいるかと思います。これをひと手間減らすのが今回ご紹介する userscript。インストールすると以下のように

f:id:motemen:20130212130926p:image

0 件の検索結果にツイートボタンが表示されます。あとはこのボタンをクリックしてツイートウィンドウを開くだけ。簡単ですね!

インストール

tweet-google-unique-query.user.jsリポジトリ)をダウンロードして、chrome://extensions に放り込むとよいです。Chrome でのみ確認していますが、Firefox などのブラウザでも使えるかもしれません。

参考リンク

  • Twitter / ?
    • テキストをツイートするだけのボタンを作りたい(URL は要らない)ときは、hashtag 版にしてハッシュタグを指定しないといいみたいです(ひどい)。
  • User Scripts - The Chromium Projects
    • Greasemonkey 由来の @include を使うとインストール時にすべてのウェブサイトに対する権限を要求しようとするので、Chrome 向けのユーザースクリプトを作るときには @match を使うのがよいです。

2013-02-08

Kyoto.js #5 で日本の連休についての発表をしました #kyotojs

| 13:31 | Kyoto.js #5 で日本の連休についての発表をしました #kyotojs - NaN days を含むブックマーク はてなブックマーク - Kyoto.js #5 で日本の連休についての発表をしました #kyotojs - NaN days

先日開催された Kyoto.js #5 で LT をしてきました。

次の連休

今後1年間の3連休が確認できる 次の連休 というサイトとその実装について紹介しました。クライアントサイド JavaScript のみで動いていて、祝日データの取得には Google Calendar API を使っています。

jquery.partyhard

また、このサイトで使用している自作の jQuery プラグイン jquery.partyhard についての紹介もしました。

使い方は簡単で、以下のようにして呼び出すだけで document.body が PARTY HARD 状態になります。

$(document.body).partyhard();

使用例は http://motemen.github.com/jquery-partyhard/demo.html をご覧ください(ロードに少し時間がかかります、あといまちょっと怖い画像が出てくるかもしれないので http://motemen.github.com/jquery-partyhard/demo.html?cat%20gif で猫を見てもよいです)。

Kyoto.js の感想

隔週で開催されていて、こういったしょうもないことも気軽に紹介できる雰囲気がいいですね。京都近辺にいらっしゃる方は是非顔を出してみては?

発表の中では mechairoi さんの Emacs Lisp から Chrome を操作する拡張 が便利そうかつ面白かったです。

2011-04-20

かっこいいコードの書き方をまとめた gist を作りました

| 19:50 | かっこいいコードの書き方をまとめた gist を作りました - NaN days を含むブックマーク はてなブックマーク - かっこいいコードの書き方をまとめた gist を作りました - NaN days

https://gist.github.com/930529

JavaScript: ユーザースクリプトを書く

以下と同様です。

// @require https://github.com/cho45/jsdeferred/blob/master/jsdeferred.userscript.js
with (D()) {
    (function () {
        // ...
    })();
}
感想

Perl: オブジェクトの文字列化

cho45 さんに教えてもらいました。以下と同様です。JS 書いた後に見るとメソッド呼び出しのように見えて???となります。

$dt . '';

以上です。よろしくお願いします。

2008-07-16

サーバーサイドに手を入れられない環境でサーバの出力をちょこっと変えてテストしてみたいとき

| 17:24 | サーバーサイドに手を入れられない環境でサーバの出力をちょこっと変えてテストしてみたいとき - NaN days を含むブックマーク はてなブックマーク - サーバーサイドに手を入れられない環境でサーバの出力をちょこっと変えてテストしてみたいとき - NaN days

そんなことってある。onload イベントに何か仕込みたいときとか、ロード完了してしまってから DOM をいじるのでは遅い。プロクソミトロン使ってもいいんだけど、手早くやりたい時は

javascript:document.documentElement.outerHTML+"<script>window.attachEvent(...)</script>"

とかすればいいのですねー。まあいろいろ弊害はあるけど。

2008-06-23

演算子を気軽に渡したい #2

| 19:42 | 演算子を気軽に渡したい #2 - NaN days を含むブックマーク はてなブックマーク - 演算子を気軽に渡したい #2 - NaN days

演算子を気軽に渡したい の続き。

_.valueOf = (function(i) {
    return function() { return (i = ++i % 2) ? 2 : 3 };
})(1);

とすると…

[ _+_, _-_, _*_, _/_, _<_, _>_, _^_, _&_, _|_ ]
// => [5, -1, 6, 0.6666666666666666, false, true, 1, 2, 3]

ウオオ!全部違う!これでもっと多くの演算子を気軽に渡せますね。_=_ とかやるとあっけなく破綻します。

2008-03-23

アーティスト名の読みを Wikipedia からぶっこ抜いて設定する

| 02:29 | アーティスト名の読みを Wikipedia からぶっこ抜いて設定する - NaN days を含むブックマーク はてなブックマーク - アーティスト名の読みを Wikipedia からぶっこ抜いて設定する - NaN days

Sort Artist というのを設定すれば、その値でソートしてくれるんだけどいちいち手入力が面倒なので、漢字で始まるアーティスト名の読みを Wiki (ウィキペディアのこと) からぶっこ抜いて設定してやる。

誤爆がありそうなので一度確認してから実行したほうがよい。

http://coderepos.org/share/browser/platform/itunes/get-sort-artist-from-wikipedia.js

var ITPlaylistSearchFieldArtists = 2;

var iTunes = WScript.CreateObject('iTunes.Application');
var libraryPlaylist = iTunes.LibraryPlaylist;

var artistsProcessed = { };

forEach(libraryPlaylist.Tracks, function(track) {
    var artist = track.Artist;
    if (artistsProcessed[artist])
        return;
    artistsProcessed[artist] = true;

    if (artist.match(/^[a-zA-Z0-9ぁ-んァ-ン]/))
        return;

    var yomi = getYomi(artist)
    if (!yomi)
        return;

    WScript.Echo(artist + ' - ' + yomi);

    try {
        forEach(libraryPlaylist.Search(artist, ITPlaylistSearchFieldArtists), function(t) {
            WScript.Echo('  ' + t.Name);
            t.SortArtist = yomi;
        });
    } catch (e) {
        // (null): ポインタが無効です というエラーが出ることがある
    }

    WScript.Sleep(1000);
});

function forEach(collection, func) {
    for (var i = 0, count = collection.Count; i < count; i++) {
        func(collection.Item(i + 1));
    }
}

function getYomi(artist) {
    artist = artist.replace(/\s+/g, '');

    if (!artist)
        return;

    with (new ActiveXObject('Microsoft.XMLHTTP')) {
        open('GET', 'http://ja.wikipedia.org/wiki/' + encodeURIComponent(artist), false);
        send(null);
        if (responseText.match(/b>\s*((?:<b>)?([ぁ-ん  ]+)/)) {
            return RegExp.$1.replace(' ', ' ');
        } else {
            return;
        }
    }
}

folder.jpg を iTunes のアートワークにする

| 02:24 | folder.jpg を iTunes のアートワークにする - NaN days を含むブックマーク はてなブックマーク - folder.jpg を iTunes のアートワークにする - NaN days

今まで WMP (360 との交信用) と foobar2000 (メイン) と iTunes (iPod の更新用) を同時に使ってたんだけど相性が悪くタグがぶっこわれるので iTunes オンリーにすることにした。で、名残りの folder.jpg をアートワークとして設定することにした。Windows Scripting Host から iTunes にアクセスできるということで便利。

http://coderepos.org/share/browser/platform/itunes/add-folder-jpg-to-artwork.js

var ITTrackKindFile = 1;

var iTunes = WScript.CreateObject('iTunes.Application');

var fileSystem = WScript.CreateObject('Scripting.FileSystemObject');

var tracks = iTunes.LibraryPlaylist.Tracks;
for (var i = 0, count = tracks.Count; i < count; i++) {
    var track = tracks.Item(i + 1);

    if (track.Kind != ITTrackKindFile)
        continue;

    var artworkFile = fileSystem.BuildPath(fileSystem.GetParentFolderName(fileSystem.GetFile(track.Location)), 'folder.jpg');

    if (track.Artwork.Count == 0 && fileSystem.FileExists(artworkFile)) {
        track.AddArtworkFromFile(artworkFile);
        WScript.Echo(track.Artist + ' - ' + track.Album + ' - ' + track.Name);
    }
}

2008-03-06

del.ico.us にニコ動プレーヤーを表示

| 05:46 | del.ico.us にニコ動プレーヤーを表示 - NaN days を含むブックマーク はてなブックマーク - del.ico.us にニコ動プレーヤーを表示 - NaN days

CodeRepos にコミット新しいバージョンをどうぞ

f:id:motemen:20080306215959p:image

リファラは各自偽装して下さいね。

なんか AutoPagerize のフィルタが何回も呼ばれることがあるんだけど何なんだろう?playerAdded という変数でプレーヤーの多重追加を回避してる。

AutoPagerize に対応できてなかったので修正。

コード書き直して、最初はサムネイルだけを表示するようにしました。サムネイルをクリックするとプレーヤーがロードされます。

// ==UserScript==
// @name           Add nicovideo thumbnail and player to del.icio.us
// @namespace      http://d.hatena.ne.jp/motemen/
// @include        http://del.icio.us/*
// ==/UserScript==

const PLAYER_WIDTH  = 323;
const PLAYER_HEIGHT = 256;

var playerContainer = { };

unsafeWindow.document._write = unsafeWindow.document.write;

unsafeWindow.document.write = function(html) {
    var videoID = arguments.callee.caller && arguments.callee.caller.caller && arguments.callee.caller.caller.arguments[0].v;
    if (!videoID)
        return;

    if (playerContainer[videoID])
        playerContainer[videoID].innerHTML = html;
};

function showPlayer(videoID) {
    var s = document.createElement('script');
    s.setAttribute('src', 'http://www.nicovideo.jp/thumb_watch/' + videoID + (PLAYER_WIDTH && PLAYER_HEIGHT ? '?w=' + PLAYER_WIDTH + '&h=' + PLAYER_HEIGHT : ''));
    s.setAttribute('type', 'text/javascript');
    s.setAttribute('charset', 'utf-8');
    document.body.appendChild(s);
}

function addThumbnail(a) {
    if (!a.href.match('http://www.nicovideo.jp/watch/(.+)'))
        return;
    var videoID = RegExp.$1;

    if (playerContainer[videoID])
        return;

    var thumbnail = document.createElement('img');
    thumbnail.setAttribute('src', 'http://tn-skr.smilevideo.jp/smile?i=' + videoID.match(/\d+$/)[0]);
    thumbnail.addEventListener('click', function() { showPlayer(videoID) }, true);
    thumbnail.style.cursor = 'pointer';

    var container = document.createElement('div');
    container.setAttribute('class', 'nicovideo');
    container.appendChild(thumbnail);

    a.parentNode.insertBefore(container, a.nextSibling);
    a.parentNode.insertBefore(document.createElement('br'), a.nextSibling);

    playerContainer[videoID] = container;
}

function addThumbnails(d) {
    Array.forEach((d || document).getElementsByTagName('a'), addThumbnail);
}

addThumbnails();

window.AutoPagerize && AutoPagerize.addFilter(function(ds) { ds.forEach(addThumbnails) });

MarlienMarlien2011/07/03 02:31What a great resuocre this text is.

cebysrcebysr2011/07/03 17:257Hxs10 <a href="http://yfqahdbzkusi.com/">yfqahdbzkusi</a>

2008-02-29

演算子を気軽に渡したい

| 02:17 | 演算子を気軽に渡したい - NaN days を含むブックマーク はてなブックマーク - 演算子を気軽に渡したい - NaN days

たとえば Scheme だといわゆる演算子もすべて関数なので、

(map + '(1 2 3) '(5 7 9)) ; => '(6 9 12)

と書けてカッコいい!JS だと

map(function(a, b) { return a + b }, [1, 2, 3], [5, 7, 9]);

か、まあよくて

map(add, [1, 2, 3], [5, 7, 9]);

とか。かっこわるいのでなんとかする。

var _ = function() {
    return function(func) {
        var args = Array.slice(arguments, 1);
        return Function.from(func).apply(this, args);
    };
};

_.valueOf = function() { return Math.E }; // なんでもいいので非零

_._ = function(a, b) {
    return a[b];
}

Function.from = function(func) {
    if (typeof func == 'function')
        return func;

    switch (true) {
        case func == _ + _:
            return function(a, b) { return a + b };
        case func == _ - _:
            return function(a, b) { return a - b };
        case func == _ * _:
            return function(a, b) { return a * b };
        case func == _ / _:
            return function(a, b) { return a / b };
        default:
            return function() { };
    }
};

とすると (map は下に)

map(_ + _, [1, 2, 3], [5, 7, 9]); // => [6, 9, 12]
map(_ . _, ['foo', 'bar', 'baz'], [0, 1, 'length']); // => ['f', 'a', 3]
map(_(), [function() { return 'a' }, function() { return 10 }]); // => ['a', 10]

"_" で演算子を囲ってるみたいでクールですね。諸事情により _ % _ は使えません。


文字列渡すのキモいなあと思って頭ひねってみたけどやっぱりキモかった。Function.from を挟んでる時点でいかんのかな。valueOf, toString と並んで toFunction があればなぁ。うーんうーん。

map はこれ

function map(func) {
    func = Function.from(func);

    var lists = Array.slice(arguments, 1);
    var result = [];

    for (var i = 0; ; i++) {
        var args = [];
        for (var j = 0; j < lists.length; j++) {
            if (i >= lists[j].length)
                return result;
            args.push(lists[j][i]);
        }
        result.push(func.apply(this, args));
    }

    return result;
}