JavaScriptによるRFC6570 - URI Templateの実装

JavaScriptで実装したのがdraftレベルのしか見つからなかったので作ってみました。
(↑Lv4まで対応してるのが有りました。でもせっかく作ったので引き続き公開しておきます。)

URI Templateって?

簡単に言うとURIに特化したテンプレートエンジンです。
http://www.example.com/users/{userid:1}/{userid}/」って書いといて「http://www.example.com/users/t/test/」って文字列作れたら便利だよね!?

詳しくは以下を参考にしてください。

以下からお持ち帰りください。

githubもjsdo.itも初めて使うのでおかしかったら教えてください。

スクリプト本体はこちら
gitgub→https://github.com/s025236/URI-Template
jsdo.it→http://jsdo.it/s025236/URI-Template-0.1

テストコードはこちら
http://jsdo.it/s025236/URI-Template-0.1.test

使い方

まずはscriptタグでロードします。

<script src="https://raw.github.com/s025236/URI-Template/master/URI-Template.js"></script>

あとはURI_Template::parseするだけです。

//window.useridを参照してパース結果を返します。
URI_Template::parse('http://www.example.com/users/{userid}/'); 
//オブジェクトを参照してパース結果を返します。
URI_Template::parse('http://www.example.com/users/{userid}/',{'userid' : 'test'});

仕様と不一致

RFC内に色々サンプルがあるのですが以下の理由によりいくつかテストが通りません。

  • JavaScriptに「!」はエスケープしないけど「/」はする関数なんて知らないよ…
  • OPコードが「;」の時だけなんで処理違うの?RFCがおかしいきがする。

最後に

応援コメントお待ちしております。
不具合報告や使用例等ありましたら、是非ご連絡ください。

携帯やスマートフォンでコンテンツを切替える"魔法"のapache設定 #apache

リキッドデザインとかレスポンシブウェブデザイン流行ってるけどやっぱりPC,スマートフォン,携帯(ガラケー)は別に別にコンテンツ用意したほうが良い時もありますよね。
でも「SEOとか考えると…」「URLがばらばらになっちゃって…」なんてお客様のお悩みを解決する為にいまさら感がすごいですが魔法の設定をご用意いたしました!

apacheの設定を書き換えよう

httpd.confで以下を書くだけでOKです。
virtualhostとかしてるときは適切に気書き換えてね。

#####################################################################
#(C)makoto@2ch.to
LoadModule rewrite_module    modules/mod_rewrite.so
LoadModule setenvif_module   modules/mod_setenvif.so
#browser判定
BrowserMatchNoCase "DoCoMo|KDDI|UP\.Browser|Vodafone|J\-PHONE|MOT\-|SoftBank|WILLCOM|DDIPOCKET" browser=mb
BrowserMatchNoCase "Android|BlackBerry|iPhone|iPod|Windows Phone|IEMobile" browser=sp
SetEnvIf browser ^$ browser=pc
#URLがsp,pc,mb,commonから始まってない時だけ書き換える
RewriteEngine on
RewriteLog "logs/rewrite_log"
RewriteLogLevel 0
RewriteCond %{REQUEST_URI} !^/(sp|pc|mb|common)
 RewriteRule ^/(.*) /%{ENV:browser}/$1 [PT]

UA判定ルールは時代で変わるので新鮮な情報を調べてね

コンテンツをアップロードしよう

コンテンツの配置にちょっと工夫が必要です。

  • (ドキュメントルート)/pc/ …PC向け
  • (ドキュメントルート)/sp/ …スマフォ向け
  • (ドキュメントルート)/mb/ …携帯向け
  • (ドキュメントルート)/common/ …共通のファイル

リンクの仕方に気をつけよう

「(ドキュメントルート)/(pc|mb|sp)/index.html」には
・http://サーバ/index.html
・http://サーバ/pc/index.html
というアクセスパターンがあるので基本的に相対pathでコンテンツ作ってください。
commonは共通パーツ置き場で必ず絶対pathで指定します。

URLはどうなるの?

といった、公開するURLはPC,SP,MBをつけないでください。

でOKです。

  • http://サーバ/pc/
  • http://サーバ/mb/
  • http://サーバ/sp/
  • http://サーバ/common/

に明示的にアクセスがある場合自動判定しませんので「PC版はこちら」みたいな誘導が可能です。

注意事項

自動判定を効率的に使うためpc,sp,mbは可能な限りディレクトリ構成を同じにしてください。
PCの1ページが携帯だと複数ページに分かれる事が多いのでファイル名は仕方ないと思います。(…ができるだけ統一)
外部サイトからのリンクは可能な限り、端末名(pc/,mb/,sp/)をつけずファイル名も指定しない(DirectoryIndexをうまく使う)ようにしてください。

関連リンク

僕が考えた最強のサーバ設定もお役に立つと思いますので是非はてなブックマークをお願いします。

最後に

はてなブックマークだと返事やお礼が大変なのでtwitterかコメでお願いします。(twitterが嬉しいです)
こういう話出来る人が周りにすくないので是非twitterで語り合いましょう。

僕が考えた最強のサーバ設定

いつの間にかさくらのVPSの標準OSがCentOS6になってたので設定を見直してみました。
月額980円/月から利用でき、2週間のお試し期間もあるのでこれを機会にサーバ設定に足を踏み入れてみてはどうでしょう?
慣れると10分くらいでウェブサーバが立ち上げれるようになります。

すみません。こんなに多くの人が見てると思わなかったんです。
お一人様サーバ向けのつもりで書いてます。
タイトルもタグもネタだったのにツッコまれまくりで恥ずかしい…

公開鍵登録しよう

どうせ自分しか触らないなしrootで作業しちゃってもいいんじゃない?
リブート(またはsshのrestart)以降秘密鍵がないとsshでログイン出来なくなるので気をつけてください。

mkdir ~/.ssh/
touch ~/.ssh/authorized_keys
chmod 700 ~/.ssh/
chmod 600 ~/.ssh/authorized_keys
echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEA5BqkP+ToroYtzOhnZ2aOJj8WqUpRcQRy/D2ojlPsQutM9Pqfo3qI+75iLpTAAkt+X0RlSBNFLfLsDgfV45IWS/5jv7CKLF/AAIU8Ke5wKVXZrC1LkZ7HfnluALhepUkeB3ilrhFQS+qeS8LHw2s2C2Ig/bGj8lXuEyt93aSREIU= makoto@2ch.to' >> ~/.ssh/authorized_keys
echo 'OPTIONS="-o PermitRootLogin=without-password -o GSSAPIAuthentication=no -o PasswordAuthentication=no"' >> /etc/sysconfig/sshd

※公開鍵は自分のに書き変えてね

id:itochan315さんから
普段からrootで作業しないのには誤操作防止の意味もあるのに、必要な時にsudoすればいい話ですよ。。
と指摘を頂きました。
個人的にはお一人様サーバだとsudoは形骸化してしまってると思ってます。

やっぱ日本人だし日本語だよね

echo 'LANG="ja_JP.UTF-8"' >> /etc/sysconfig/i18n

いらない子

yum -y remove '*.i[3-6]86'
yum -y remove mlocate cups dhclient kudzu wireless-tools
chmod -x /etc/cron.daily/makewhatis.cron
chkconfig cpuspeed off

IPv6…なにそれ美味しいの?

echo 'IPV6_DEFAULTDEV=tun6to4' >> /etc/sysconfig/network
echo 'IPV6INIT=yes' >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo 'IPV6TO4INIT=yes' >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo 'IPV6TO4_RELAY=192.88.99.1' >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo 'tun6to4 2000::/3' >> /etc/sysconfig/static-routes-ipv6
echo 'IPV6TO4_IPV4ADDR='`/sbin/ifconfig eth0 |grep 'inet addr:' | awk '{print \$2}' | sed -e 's/addr://g'` >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo 'UseDNS no' >> /etc/ssh/sshd_config

アクセス時間なんかいらなくね?

(2012/03/07 16:10 修正)
HDD遅いしイジメ良くない。noatimeをつけよう。
id:sh2さんから、はてなブックマーク
RHEL 6系はrelatimeが導入されたのでnoatimeは設定しなくていいはず。」
という指摘を頂きました。(参考)
CentOS5からの惰性で書いててすみませんでした。

漏れまくりだけどファイアーウオール

どうせ不要なサービスとか動かさないしぃとかいわないで一応default dropで設定します。
/etc/sysconfig/iptablesと/etc/sysconfig/ip6tablesを書き換えます。
IP指定がなければ同じ内容で良いみたい。

######################################################################
# makoto@2ch.to
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
######################################################################
# ループバック/ICMP/確立済みの接続
-A INPUT   -i lo   -j ACCEPT
-A OUTPUT  -o lo   -j ACCEPT
-A INPUT   -p icmp -j ACCEPT
-A OUTPUT  -p icmp -j ACCEPT
-A INPUT   -p ipv6 -j ACCEPT
-A OUTPUT  -p ipv6 -j ACCEPT
-A INPUT   -p ipv6-icmp -j ACCEPT
-A OUTPUT  -p ipv6-icmp -j ACCEPT
-A INPUT   -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT  -m state --state RELATED,ESTABLISHED -j ACCEPT
######################################################################
# OUTPUT
-A OUTPUT -m state --state NEW -p tcp --dport ssh           -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport smtp          -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport domain        -j ACCEPT
-A OUTPUT -m state --state NEW -p udp --dport domain        -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport http          -j ACCEPT
-A OUTPUT -m state --state NEW -p udp --dport ntp           -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport https         -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport mysql         -j ACCEPT
#↓memcached
#-A OUTPUT -m state --state NEW -p tcp --dport 11211         -j ACCEPT
######################################################################
# 公開ポート 必要なこだけコメントを外すこと
#-A INPUT -m state --state NEW -p tcp --dport smtp          -j ACCEPT
#-A INPUT -m state --state NEW -p tcp --dport domain        -j ACCEPT
#-A INPUT -m state --state NEW -p udp --dport domain        -j ACCEPT
 -A INPUT -m state --state NEW -p tcp --dport http          -j ACCEPT
#-A INPUT -m state --state NEW -p tcp --dport https         -j ACCEPT
#↓可能ならSAFTYを利用する
#-A INPUT -m state --state NEW -p tcp --dport ssh    -j ACCEPT
######################################################################
# 信頼できるIP
-N SAFETY
-A SAFETY -m state --state NEW -p tcp --dport ssh           -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport smtp          -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport http          -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport https         -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport mysql         -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport 11211         -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport postgres      -j ACCEPT
-A INPUT -s 自分ちの固定IP -j SAFETY
COMMIT

※CentOS5系だとip6tablesでRELATED,ESTABLISHEDが使えないので注意が必要です。

nginxさんは早くてかっこいい

SSLv2有効にしてるサイトが多くてビビる。
静的コンテンツならnginxで返してそれ以外はバックエンドに送る設定が多いけどちょっとひねってみた。
ファイルがあればnginxが返すけど特定の拡張子はバックエンドへ送る。not foundも裏に送る。

yum -y install nginx
chkconfig nginx on
cat > /etc/nginx/nginx.conf
######################################################################
# (c)makoto@2ch.to
user nginx;
worker_processes  2;
pid /var/run/nginx.pid;
error_log  /var/log/nginx/error.log;
events { worker_connections 1024; }
######################################################################
#
http {
  ####################################################################
  # 上位サーバの設定
  upstream backend {
    server 127.0.0.1:8080;
  }
  ####################################################################
  # 基本設定
  include           mime.types;
  sendfile          on;
  tcp_nopush        off;
  server_tokens     off;
  keepalive_timeout 1;
  ####################################################################
  # 不要ならoff
  ssi on;
  ssi_types text/x-server-parsed-html;
  ####################################################################
  #圧縮しないならoff
  gzip on;
  gzip_vary off;
  gzip_disable “MSIE [1-6]\.”;
  gzip_disable “Mozilla/4;
  gzip_types
    text/plain
    text/xml
    text/css
    application/xml
    application/xhtml+xml
    application/rss+xml
    application/javascript
    application/x-javascript
  ;
  ####################################################################
  # SSLの設定
  ssl_certificate           /etc/pki/tls/certs/localhost.crt;
  ssl_certificate_key       /etc/pki/tls/private/localhost.key;
  ssl_protocols             TLSv1.2 TLSv1.1 TLSv1; #SSLv2,SSLv3は脆弱性がある
  ssl_ciphers               HIGH:!ADH:!MD5:!SSLv3; # openssl ciphers -v 'HIGH:!ADH:!MD5:!SSLv3'
  #nginxのversionによってssl_ciphersがエラーになる場合がある
  #ssl_ciphers               HIGH:!ADH:!MD5; 
  ssl_prefer_server_ciphers on;
  ssl_session_cache         shared:SSL:10m;
  ssl_session_timeout       10m;
  ####################################################################
  # 80,443ポート
  server {
    index index.php index.html;
    root    /var/www/html;
    listen  80;
    listen  443 ssl; #不要な場合はコメントアウト
    ##################################################################
    # backendでSSLか判定するのに必要
    set $ssl 0;
    if ($scheme = 'https') { set $ssl 1; }
    proxy_set_header X-SSL $ssl;
    proxy_redirect   off;
    proxy_set_header Host            $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    ##################################################################
    # 静的コンテンツはブラウキャッシュ
    location ~ \.(gif|jpg|png|swf|css|js|txt|ico|css|html|xml)$ {
      expires 1d;
    }
    ##################################################################
    # not foundやcgi,php,plはバックエンドに渡す
    error_page 404 = @fallback;
    location ~ \.(cgi|php|pl)$ {proxy_pass http://backend;}
    location @fallback         {proxy_pass http://backend;}
  }
}

error_pageのエラーコードの後に=を追記しました。
POODLE対策の為SSLv3を禁止にしました

バックエンドはapacheが楽だよね

今までのknow howもあるし、rewrite使いたいし余計なこと考えたくない!
ZendFrameworkに興味がない人やそもそもphpに興味がない人は不要なとこは消して実行してね。

yum -y install php-ZendFramework-Cache-Backend-Memcached php-ZendFramework-Cache-Backend-Apc php-ZendFramework-Db-Adapter-Mysqli php-mbstring mod_extract_forwarded mod_ssl
echo 'date.timezone = Asia/Tokyo' >> /etc/php.d/local.ini
chkconfig httpd on
cat > /etc/httpd/conf/httpd.conf
# (C) makoto <makoto@2ch.to>
######################################################################
# 基本設定
ServerRoot /etc/httpd
PidFile run/httpd.pid

User apache
Group apache

# 接続関係
Timeout 3
KeepAlive off
KeepAliveTimeout 1
MaxKeepAliveRequests 20
#Listen 0.0.0.0:80
Listen 127.0.0.1:8080

# 起動設定
<IfModule prefork.c>
  StartServers       3
  MinSpareServers    5
  MaxSpareServers   10
  MaxClients        100
  MaxRequestsPerChild  0
</IfModule>

# 起動設定
<IfModule worker.c>
StartServers         2
MaxClients         150
MinSpareThreads     25
MaxSpareThreads     75
ThreadsPerChild     25
MaxRequestsPerChild  0
</IfModule>

# その他
ServerTokens Prod
ServerSignature Off
TraceEnable Off
######################################################################
# ディレクトリの設定
AccessFileName .htaccess
DocumentRoot /var/www/html/
######################################################################
# MIME/言語設定
LoadModule mime_module       modules/mod_mime.so
LoadModule mime_magic_module modules/mod_mime_magic.so
TypesConfig /etc/mime.types
MIMEMagicFile conf/magic
DefaultType text/plain
######################################################################
# LOG設定
ErrorLog logs/error_log
LogLevel warn
#LogLevel error
#LoadModule log_config_module modules/mod_log_config.so
#LogFormat "%h %v %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %X%D" combined
#CustomLog logs/access_log combined env=!nolog
######################################################################
# php
<IfModule prefork.c>
 LoadModule php5_module modules/libphp5.so
</IfModule>
<IfModule worker.c>
 LoadModule php5_module modules/libphp5-zts.so
</IfModule>
AddHandler php5-script .php
######################################################################
# server-status
LoadModule status_module modules/mod_status.so
ExtendedStatus On
<Location /server-status>
    SetHandler server-status
</Location>
#####################################################################
#
LoadModule dir_module modules/mod_dir.so
DirectoryIndex index.php index.html
#####################################################################
#
#LoadModule rewrite_module    modules/mod_rewrite.so
#LoadModule auth_basic_module modules/mod_auth_basic.so
#LoadModule authn_file_module modules/mod_authn_file.so
#LoadModule authz_user_module modules/mod_authz_user.so
<Directory /var/www/html>
#  AllowOverride FileInfo Options AuthConfig
  AllowOverride None
  Options FollowSymLinks
</Directory>
#####################################################################
# expiresの設定
LoadModule expires_module modules/mod_expires.so
ExpiresActive On
#ExpiresActive Off
ExpiresByType text/css "access plus 1 day"
ExpiresByType application/x-javascript "access plus 1 days"
ExpiresByType application/javascript "access plus 1 days"
ExpiresByType text/javascript "access plus 1 days"
ExpiresByType text/plain "access plus 1 days"
ExpiresByType image/gif "access plus 1 days"
ExpiresByType image/jpeg "access plus 1 days"
ExpiresByType image/jpg "access plus 1 days"
ExpiresByType image/png "access plus 1 days"
ExpiresByType image/ico "access plus 1 days"
ExpiresByType image/icon "access plus 1 days"
ExpiresByType text/ico "access plus 1 days"
ExpiresByType application/ico "access plus 1 days"
ExpiresByType image/x-icon "access plus 1 days"
#####################################################################
# mod_extract_forwarded
LoadModule proxy_module modules/mod_proxy.so
LoadModule extract_forwarded_module modules/mod_extract_forwarded.so
MEForder refuse,accept
MEFrefuse all
MEFaccept 127.0.0.1
MEFaddenv on
MEFdebug off

以下の指摘を受けて修正しました。

最新版大切

ついでに設定反映させるのにrebootもしちゃえ

yum -y update
reboot

関連リンク

携帯とかスマートフォンでコンテンツを切り替える魔法の設定もお役に立つと思いますので是非はてなブックマークをお願いします。

最後に

こういう話出来る人が周りにすくないので是非twitterで語り合いましょう。

1000PV/日の稼ぎ方|まとめて2ちゃんねるの場合

先日公開した「2ch まとめサイトのまとめサイト|まとめて2ちゃんねる」が、1000PV/日↑+android版のinstall端末数が1000↑になったのでぐたぐた日記を書いてみました。

12月13日、サイトオープン

2ch まとめサイトとしてまとめて2ちゃんねるを公開しました。

公開といっても

程度しかできず、そもそも多くの人にサイトの存在を知ってもらう方法がありませんでした。

12月21日、android版公開

HTMLやCSS,JavaScriptは書けますがJavaなんて書いた事も無いので、まともに開発してたらリリースできるの数ヵ月後になってしまいます。
いろんなサイトを見ながら環境を構築して、ブラウザにまとめて2ちゃんねるのURLを渡して終了するだけというなんちゃってアプリショートカットアプリを作りました。

androidアプリはアイコンを用意するのが大変

知人にご飯ご馳走して作ってもらいましたが絵心が無いプログラマにどうしろっていうのだろうか…プログラム作成より難関でした。

1024x500 宣伝用画像(省略可能) ←アプリケーションページの頭に出てくるのでちゃんと登録したほうが良い
180x120 プロモーション画像(省略可能) ←どこで使われるのかよくわからず
512x512 高解像度アプリケーション アイコン ←marketの一覧に出るのでとても大切
??x?? スクリーンショット 2枚 ←サイズ指定がいくつかあります
72x72 高解像度アイコン
48x48 中解像度アイコン
36x36 低解像度アイコン
16x16 favicon ←自サイトに利用

なぜお金を払ってまでアンドロイドマーケットに登録をしたのか?

アンドロイドマーケットにアプリを登録するにはgoogleに開発者登録をする必要があり2,500円が必要になります。
今回の場合、アイコン作るのにご飯代もかかっています

が!

google検索で「2ch まとめ」等関連しそうなワードで検索すると星の数ほどの結果が出てきますし、ドメインエイジの壁を乗り越えることもできませんので後発のまとめて2ちゃんねるは非常に不利です。

androidマーケットのアプリ登録数は10万程度、同様のワードで検索すると200もでてきません。

これならチャンスがある!

1月2日、igoogle版公開

(igoogleなんか使ってないので)igoogle利用者ってどれくらいいるのか謎ですが、仕分けされる様子も無いのでそれなりにユーザはいるはずです。
android版を作成した再と同じ考えで、世の中に存在する2chまとめサイト数に比べればigooleガジェット登録数なんてかわいいものです。
普段から使ってる言語(HTML,CSS,JavaScript)にgadets APIを勉強すれば良いだけだったので公開してみました。

サーバ構成

サーバサイドのアプリはまったく作っておらずRSSの収集はgoogleのfeeds APIやgadgets APIまかせ
jquery等の有名なフレームワークスクリプトは提供元のCDNまかせ
S3にコンテンツを置いてる為、アクセス数が急激に増えてもamazonが何とかしてくれるので
ユーザーの増加も安心して見てられます。

android版のインストール端末数

開発者ページから見えるグラフです。なぜか二日前までしか情報が見えません。(せめて前日にしてほしいですよね)

アクセス数

1月1日はぎりぎり1000PV/日に届かず、2日〜が1000PV超えてます。

所で!

アンドロイドマーケットに登録するのに必要なアイコンの作成
ショートカットアプリの作成
僕のアカウントでマーケットに代行登録
のパックで1サイト○万円とかで提供したら興味ある人いませんか?
興味ある人はメールかskype等でご連絡ください。

お正月の暇つぶしに2chまとめサイトはいかがですか?

人気2ちゃんねる(2ch)まとめサイト+αの更新情報を表示するサイトを作ってみました。
お正月の暇つぶし、通勤/通学、寝る前等ちょっとした時間にご利用下さい。
自分でも使ってますが気がつくと1時間くらいつぶれてます。

改修のモチベーションにつながりますので、アプリの評価、ガジェットの評価、はてなブックマーク、この日記へのコメント等フィードバックいただければ幸いです。

まとめて2ちゃんねる

スマートフォン版は通常のPCでもみれますがigoogle版の方が見やすいと思います。

以下のサイトに対応しています ※2011/1/3現在

  • ニュー速クオリティ
  • VIPPERな俺
  • 無題のドキュメント
  • あじゃじゃしたー
  • がぞ〜速報
  • はちま寄稿
  • GIGAZINE
  • 痛いニュース(ノ∀`)
  • BIPブログ
  • ワロタ日記
  • 2chコピペ保存道場
  • もみあげチャ〜シュ〜
  • 2ch】コピペ情報局
  • 虚構新聞
  • ハムスター速報
  • アルファモザイク
  • ぶる速-VIP
  • まとめたニュース
  • ぁゃιぃ(*゚ー゚)NEWS 2nd
  • 2のまとめR
  • 暇人\(^o^)/速報
  • マジキチ速報

name属性にdocumentのメソッド名を指定してはいけない例

id:masa141421356:20111201:1322749788の記事が発端ではてなブックマークで話題になっていたので調べてみた。

検証コード

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.min.js"></script>
<script>
<!--
$(function(){
	//native
	try {
		console.log( document.getElementById('target') );
	}catch($e){
		console.log( 'error:' + $e );
	};
	//jQuery
	try {
		console.log( $('#target') );
	}catch($e){
		console.log( 'error:' + $e );
	};


});
-->
</script>
<style>
</style>
</head>
<body>
<form name="getElementById"></form>
<div id="target">document.getElementByIdや$('#target')取得できるかな?</div>
</body>
</html>

結果

chromeでしか試していませんが…
思った通りgetElementByIdが使えなくなりました
iframeでも同じ現象が発生します。
aタグ,inputタグは問題ありませんでした。

JavaScriptのArrayオブジェクトにmapメソッドとshuffleメソッドを実装する方法

当局の事情聴取に対し

  • 配列をシャッフルしたかった
  • IE7,8のArrayオブジェクトにはmapメソッドがなかった(注:IE9からは実装しています)
  • 今は反省している(後で調べたら色々なサイトで記事になってた)

等と供述していたことが判った。

ないなら実装してしまえ!

とりあえずjQueryで書いてみた

if( typeof Array.prototype.map === 'undefined') Array.prototype.map = function($_){
	return jQuery.map(this,$_);
}

jQuery.mapさん何してるの!?

chromeでnative版とjQuery版のベンチを取ってみたら倍ぐらい違ったのでjQueryを使わないで実装。
native版とほぼ変わらない実行速度になりました。

if( typeof Array.prototype.map === 'undefined') Array.prototype.map = function($callback){
	var len	= this.length;
	var $_	= new Array(len);
	for(var i =0; i<len; i++){
		$_[i] = $callback.call(this,this[i],i);
	}
	return $_;
};

Schwartzianで配列のシャッフルを実装

シンプルでいいですよね。(jQuery.map版は配列を返すとマージされてしまうので動きません。)

if( typeof Array.prototype.shuffle === 'undefined') Array.prototype.shuffle = function(){
	return this
		.map(function($_){return [Math.random(),$_]})
		.sort(function(a,b){return a[0] - b[0]})
		.map(function($_){return $_[1]})
	;
};

まとめ

array.extends.jsとか適当に名前付けて保存しとこう

/* (C) makoto@2ch.to */
if( typeof Array.prototype.map === 'undefined') Array.prototype.map = function($callback){
	var len	= this.length;
	var $_	= new Array(len);
	for(var i =0; i<len; i++){
		$_[i] = $callback.call(this,this[i],i);
	}
	return $_;
};
if( typeof Array.prototype.shuffle === 'undefined') Array.prototype.shuffle = function(){
	return this
		.map(function($_){return [Math.random(),$_]})
		.sort(function(a,b){return a[0] - b[0]})
		.map(function($_){return $_[1]})
	;
};