hiiragi's ブログ

主にコンピュータ関係の備忘録を書いてます

mouseover, mouseoutのevent.target等について

target, currentTarget, relatedTarget, srcElement, fromElement, toElementが紛らわしいので調べた。

W3C DOM

target イベントが発生した要素
currentTarget イベントリスナを登録した要素
relatedTarget mouseover: 移動元の要素, mouseout: 移動先の要素

Microsoft DHTML

srcElement イベントが発生した要素
fromElement mouseover, mouseoutで移動元の要素
toElement mouseover, mouseoutで移動先の要素


参考にしたリンク, 動作確認サンプルはこちらで
http://jsdo.it/s_hiiragi/xYCP/fullscreen

任意のファイルのメモを作成する/開くコマンド

これは何?

任意のファイルのコンテキストメニュー(右クリックメニュー)からファイルにメモしたり、メモを開いたりするコマンド。

設定方法は?

HKEY_CLASSES_ROOT\*\shell\にcreateNoteキーを作成し、commandサブキーに以下をコピペする。
あとcreateNoteキーの既定値に"ファイルにメモする"をセットしておく。

cmd /c "for %%a in ("%1") do ((if not exist "%%~dpna.README.txt" (copy nul "%%~dpna.README.txt") else echo) && start "" "%%~dpna.README.txt")"

仕組みは?

  1. ファイルと同一のフォルダ内に『ファイル名(拡張子除く).README.txt』というファイルが無ければ作成し、デフォルトのエディタで開く。
  2. 既にある場合は、そのファイルを開く。

備考

  • commandキーに指定するコマンドで変数を使いたいのだけど、使えなかった(なので同じメモファイル名を何度も入力してる)。
    • 誰か教えてください。

動作確認環境

Windows XP SP3

Function.prototype.bindを名前付き引数に対応させる

使えるかどうか分からないけど。
ネイティブメソッドは引数名が取得できないので名前付き引数のbindの有難みが無い…orz

/* bindAny(thisObj[, args][, namedArgs])
 * bindAny(thisObj[, namedArgs][, args]) // Syntax sugar
 */
Function.prototype.bindAny = function(thisObj)
{
    var orig = this;
    
    var boundArgs, boundNamedArgs;
    if (Array.isArray(arguments[1])) {
        boundArgs = arguments[1];
        boundNamedArgs = arguments[2];
    } else {
        boundNamedArgs = arguments[1];
        boundArgs = arguments[2];
    }
    if (!boundArgs) boundArgs = [];
    if (!boundNamedArgs) boundNamedArgs = {};
    
    /* build pre arguments
     * 
     * 元の関数の引数名の列を取得
     * nameに対応する位置にnamedArgs[name]を入れる
     */
    var argNames = orig.toString()
        .match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(/\s*,\s*/);
    var args = [];
    for (var i = 0, l = argNames.length; i < l; ++i) {
        var name = argNames[i];
        if (boundNamedArgs.hasOwnProperty(name)) {
            args[i] = boundNamedArgs[name];
        }
    }
    
    var slice = Array.prototype.slice, 
        news = [];
    function bound()
    {
        /* build actual arguments
         * 
         * pre-argumentsの先頭から順にundefinedにargsを入れる
         * 残ったargsは末尾に追加
         */
        var ta = boundArgs.concat(slice.call(arguments));
        var a = slice.call(args);
        for (var i = 0, l = a.length; 1 <= ta.length && i < l; ++i) {
            if (typeof a[i] === 'undefined')
                a[i] = ta.shift();
        }
        if (ta.length >= 1) a = a.concat(ta);
        
        if (this instanceof bound) { /* I am a constructor! */
            if (!news[l]) {
                var as = [];
                for (var i = 0, l = a.length; i < l; ++i)
                    as.push('a[' + i + ']');
                var evs = 'news[l]=function(){return new orig('
                    + as.join(',')
                    + ');};';
                eval(evs);
            }
            var ret = news[l]();
            if (typeof ret.__proto__ === 'object') {
                ret.__proto__ = bound.prototype;
            }
            return ret;
        } else {
            return orig.apply(thisObj, a);
        }
    }
    
    function fnop() {}
    fnop.prototype = orig.prototype;
    bound.prototype = new fnop();
    return bound;
};


動作確認

function f(a, b, c, d) {
    console.log(arguments);
}

f.bindAny(null, [1, 2], {c: 3, d: 4})(); // f(1, 2, 3, 4)
f.bindAny(null, [1, 2])();               // f(1, 2)
f.bindAny(null, [1, 2])(3, 4);           // f(1, 2, 3, 4)
f.bindAny(null, {c: 3, d: 4})(1, 2);     // f(1, 2, 3, 4)
f.bindAny(null, {c: 3, d: 4})();         // f(undefined, undefined, 3, 4)
f.bindAny(null, {c: 3})(1, 2, 4);        // f(1, 2, 3, 4)


参考

FizzBuzz

twitterで話題になってたので、各言語でジェネレータで実装。


JavaScript

function fizzbuzz_generator(n) {
 var i = 0;
 return function() {
  return ++i>n ? null : (i%3?'':'Fizz')+(i%5?'':'Buzz')||i;
 }
}

var f = fizzbuzz_generator(15);

for (var i = 0; i < 16; ++i)
 console.log( f() );


C#

using System;
using System.Collections.Generic;
 
public class Test
{
 public static IEnumerable<string> FizzBuzz(int n)
 {
  for (int i = 1; i <= n; ++i)
   yield return i%3==0 ? (i%5==0 ? "FizzBuzz" : "Fizz") : (i%5==0 ? "Buzz" : i.ToString());
  yield break;
 }
 
 public static void Main()
 {
  foreach (var i in FizzBuzz(15))
   Console.WriteLine( i );
 }
}

メソッドは全て大文字で始まるんだった。i.toString()とか書いてた。


Python

class FizzBuzz:
 def __init__(self, n):
  self.i = 1
  self.n = n
 
 def __iter__(self):
  return self
 
 def next(self):
  i = self.i
  n = self.n
  if i > n:
   raise StopIteration
  
  self.i += 1
  if i%3 == 0:
   if i%5 == 0:
    return 'FizzBuzz'
   else:
    return 'Fizz'
  elif i%5 == 0:
   return 'Buzz'
  else:
   return i

for i in FizzBuzz(15):
 print i

一発で実行できた。


PHP

<?php
class FizzBuzz implements Iterator {
 private $i_ = 1;
 private $n_ = 0;
 
 public function __construct($n) {
  $this->n_ = $n;
 }
 
 function rewind() { $this->i_ = 1; }
 
 function current()
 {
  $i = $this->i_;
  $x = ($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz');
  return $x ? $x : "${i}";
 }
 
 function key() { return $this->i_-1; }
 
 function next() { ++$this->i_; }
 
 function valid() {
  return $this->i_ <= $this->n_;
 }
}

$fb = new FizzBuzz(15);
foreach ($fb as $i) {
 echo "${i}\n";
}
?>

文字列の結合が「.」なのを忘れてて嵌った。文字列中の変数は${i}でも{$i}でも大丈夫(式は書けない)。
若干エラーメッセージが分かりづらい気が。
foreachは他の言語と違って、コレクションを先に書く。


HSP

 #module FizzBuzz n_, i_
  #modinit int n
   n_ = n
   i_ = 0
   return
  
  #modcfunc fb_moveNext
   if i_ >= n_ : return false
   i_++
   return true
  
  #modcfunc fb_current
   if i_ == 0 or i_ > n_ : return -1
   
   if i_ \ 3 == 0 {
    if i_ \ 5 == 0 {
     return "FizzBuzz"
    } else {
     return "Fizz"
    }
   } else:if i_ \ 5 == 0 {
    return "Buzz"
   }
   return i_
 #global
 
 newmod fb2, FizzBuzz, 15
 while fb_moveNext(fb2)
  mes fb_current(fb2)
 wend

剰余演算子が「\」なのを忘れてて嵌った。エラーメッセージが分かりづらい。

前回IEを起動してからの経過時間を表示する

殆どIEを使うことがないので、前回の起動からどれだけ経ってるか調べるBookmarkletを書いてみました。IE8以上で動きます。

4/8 はてな記法が原因でコードがおかしくなっていたのを修正。

以下のリンクをブックマークバーにDrag&Dropしてくださいっ!(クリックして試しに実行するのもok)
(注意:1回目のクリックでは"前回の起動日時"が保存されてないため何も起きません)
前回の起動からの経過時間

前回のクリック時の日時をlocalStorageに入れ、経過時間を計算しているだけです。
したがって正確には、「前回このBookmarkletをクリックしてからどれだけ経過したか」を表示するBookmarkletです。

はてなブログではJavaScriptを実行できる

はてなダイアリーでは出来なかったこと。

onclick属性で。

javascript:スキームで。クリック!

scriptタグで。 (ただし見たままモード編集のプレビューでは実行結果を確認できない)