AutoPagerizeのように自動読み込みができるjQueryプラグイン
GreasemonkeyスクリプトのAutoPagerizeやFirefox add-onのAutoPagerのように、スクロールするだけで自動ページングできるjQueryプラグインを作ってみました。
※10/22 全面的に書き直したv1.0.0をリリースしました。
詳しくはhttp://lagoscript.org/jquery/autopagerを参照してください。
サンプル
$.autopager({ nextLink : '#nav a:last', // 次ページリンクのセレクタ pageElement: '#res' // ページコンテンツ部分のセレクタ });
jQuery.autopager(options)
サイトに次ページの自動読み込み機能を付け加えます。
options
- nextLink: 次ページのリンクを持つ要素へのセレクタ
- pageElement: ページコンテンツ部分のセレクタ
- insertBefore(任意): ここで指定した要素の前に次ページのコンテンツが挿入される
- pagingPoint(任意): 自動読み込みが行われる位置指定。ページ終端からの距離(ピクセル)
- load(任意): 次ページが読み込まれた時に実行されるコールバック関数。"this"は挿入するコンテンツとなる。第一引数に読み込まれたページ番号が渡される。
- success(任意): 次ページの挿入まで成功した後に実行されるコールバック関数。"this"は挿入されたコンテンツとなる。第一引数に読み込まれたページ番号が渡される。
ソース
http://code.google.com/p/jquery-autopager/
http://jquery-autopager.googlecode.com/svn/trunk/jquery.autopager.js
(function($) { $.autopager = function(options) { var nextPageUrl; var requestedPages = [location.href]; var loading = false; if ($.browser.msie) { var scrollTopElement = $('html'); var heightElement = $(document); } else { var scrollTopElement = $(document); var heightElement = $('html'); } options = $.extend({ insertBefore: $(options.pageElement).next(), pagingPoint: 350, load: function() {}, success: function() {} }, options); setNextPageUrl(); $(window).scroll(function(){ if (!loading && nextPageUrl && $.inArray(nextPageUrl, requestedPages) < 0 && scrollHeightRemain() < options.pagingPoint) { loading = true; requestedPages.push(nextPageUrl); $.get(nextPageUrl, function(data){ var nextPage = $('<div/>').html(data); setNextPageUrl(nextPage); insertPageElement(nextPage); loading = false; }); } }); return this; function setNextPageUrl(context) { var args = [options.nextLink]; if (context) args.push(context); nextPageUrl = $.apply(null, args).attr('href'); } function insertPageElement(context) { var pageElement = $(options.pageElement, context); if (pageElement) { options.load.call(pageElement, requestedPages.length); pageElement.insertBefore(options.insertBefore); options.success.call(pageElement, requestedPages.length); } } function scrollHeightRemain() { return heightElement.height() - scrollTopElement.scrollTop() - $(window).height(); } }; })(jQuery);
参考
オプションの取り方などはAutoPagerizeを参考にさせてもらいました。
C言語で文字列のクイックソート
コマンドライン引数で受け取った文字列をstrcmpで比較してソートする。
#include <stdio.h> #include <string.h> void quicksort(char *array[], int left, int right) { if (left >= right) return; int l = left; int r = right; char *pivot = array[(left + right) / 2]; // 中央からピボットを選択 char *buf; while (1) { while (strcmp(array[l], pivot) < 0) l++; while (strcmp(array[r], pivot) > 0) r--; if (l > r) break; // pivotより小さい値を左、大きい値を右に入れ替え buf = array[l]; array[l] = array[r]; array[r] = buf; l++, r--; } // pivotより小さい領域と大きい領域をそれぞれ再帰的にソート quicksort(array, left, r); quicksort(array, l, right); } int main(int argc, char *argv[]) { int i; if (argc < 2) { fprintf(stderr, "Usage; %s ...\n", argv[0]); return 1; } quicksort(argv, 1, argc - 1); for (i = 1; i < argc; i++) { printf("%s\n", argv[i]); } return 0; }
C言語でクイックソート
Cだといちいちめんどくさい。
#include <stdio.h> void quicksort(int array[], int left, int right) { int l = left; int r = right; int pivot = array[(left + right) / 2]; // 中央からピボットを選択 int buf; while (1) { while (array[l] < pivot) l++; while (array[r] > pivot) r--; if (l > r) break; // pivotより小さい値を左、大きい値を右に入れ替え buf = array[l]; array[l] = array[r]; array[r] = buf; l++, r--; }; // pivotより小さい領域と大きい領域をそれぞれ再帰的にソート if (left < r) quicksort(array, left, r); if (l < right) quicksort(array, l, right); } int main(int argc, char *argv[]) { int i; int array[] = { 6, 4, 3, 7, 8, 0, 5, 2, 9, 1, }; int count = sizeof array / sizeof array[0]; quicksort(array, 0, count - 1); // ソート // 結果表示 for (i = 0; i < count; i++) { printf("%d\n", array[i]); } return 0; }
PHPでクイックソートというものをやってみた
一般的に最も高速なソートのアルゴリズムらしい。
アルゴリズム
1. 適当な数(ピボットという)を選択する (この場合はデータの総数の中央値が望ましい)
2. ピボットより小さい数を前方、大きい数を後方に移動させる (分割)
3. 二分割された各々のデータを、それぞれソートする
実装
<?php function quicksort($array) { if (count($array) <= 1) { return $array; } $pivot = array_shift($array); // ピボットの選択 $left = $right = array(); foreach ($array as $value) { if ($value < $pivot) { $left[] = $value; // ピボットより小さい数は左 } else { $right[] = $value; // ピボットより大きい数は右 } } // 左右のデータを再帰的にソートする return array_merge(quicksort($left), array($pivot), quicksort($right)); }
実行
<?php $array = array( 6, 4, 3, 7, 8, 5, 2, 9, 1, ); $array = quicksort($array); var_dump($array); // 1, 2, 3, 4, 5, 6, 7, 8, 9
Prototype.jsのbind()がすること
バージョン1.6.0.3。
Function.prototype.bind()
thisと引数の値を固定化した関数を返すメソッド。
第一引数にthisとなる値、第二引数以降に固定化する引数の値を指定する。
Function.prototypeを直接拡張している。
Object.extend(Function.prototype, { // 略 bind: function() { // 引数の数が1以下で、第一引数がundefinedの場合は関数をそのまま返す if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; var __method = this, // bind実行時のthisは関数そのもの args = $A(arguments), // 固定化される引数 object = args.shift(); // 関数実行時にthisとなるオブジェクト // thisと引数を固定化した関数を返す。固定化した以外の残りの引数は直接受け取ることができる return function() { // 元の関数をapplyメソッドで呼び出し、結果をreturn return __method.apply(object, args.concat($A(arguments))); } }, // 略 });
- Function.prototype.apply : 第一引数をthisに結びつけ、第二引数を引数の配列として関数を呼び出す。
Function.prototype.bindAsEventListener()
イベントのコールバック用にthisと引数の値を固定化した関数を返すメソッド。
引数の指定方法はbindと同じだが、返される関数は第一引数でeventオブジェクトを取る。
その他の引数を受け取ることはできない(コールバック関数なので必要がない)。
Object.extend(Function.prototype, { // 略 bindAsEventListener: function() { var __method = this, args = $A(arguments), object = args.shift(); // 引数にeventオブジェクトをとる関数を返す。thisと残りの引数は固定化される。 return function(event) { // eventオブジェクトを第一引数として関数を呼び出す return __method.apply(object, [event || window.event].concat(args)); } }, // 略 });
Prototype.jsの$()がすること
確認したバージョンは1.6.0.3。
$()
Prototype.jsで拡張したelementオブジェクト(の配列)を返す関数。
引数が複数の場合は、再帰的に自身を呼び出し配列にセット。その配列をreturn。
引数が一つで文字列であればidとみなしてelementオブジェクトを取得する。
Element.extendメソッドで拡張したelementをreturn。
function $(element) { if (arguments.length > 1) { // 引数が複数の場合 for (var i = 0, elements = [], length = arguments.length; i < length; i++) elements.push($(arguments[i])); // 自身を呼び出した結果を配列に入れる return elements; } if (Object.isString(element)) // 文字列の場合はIdとみなす element = document.getElementById(element); return Element.extend(element); // メソッドを追加してreturn }
Element.extend()
elementオブジェクトを拡張(メソッド追加)するメソッド。
タグごとにDOMオブジェクトが定義されているブラウザの場合は何もしない。
(あとでElement.addMethodsメソッドで直接DOMオブジェクトを拡張するため)
引数にとったelementがすでに拡張されている場合とElementノードではない場合とwindowオブジェクトの場合は何もしない。
Element.extend = (function() { // タグごとにDOMオブジェクトが定義されている場合 if (Prototype.BrowserFeatures.SpecificElementExtensions) return Prototype.K; // 引数をそのまま返すメソッドとする var Methods = { }, ByTag = Element.Methods.ByTag; var extend = Object.extend(function(element) { // すでに拡張されている、elementノードでない、windowオブジェクトの場合... if (!element || element._extendedByPrototype || element.nodeType != 1 || element == window) return element; //そのまま返す var methods = Object.clone(Methods), // 複製する tagName = element.tagName.toUpperCase(), property, value; // 特定のタグに対してのメソッド追加 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); for (property in methods) { value = methods[property]; // valueが関数で、elementにpropertyが定義されていない場合... if (Object.isFunction(value) && !(property in element)) // 第一引数に自動でthisをとるメソッドにして返す // 実際にメソッドが呼ばれるときはthis==elementとなる element[property] = value.methodize(); } element._extendedByPrototype = Prototype.emptyFunction; // 拡張済みのフラグをつける return element; }, { refresh: function() { // 全てのタグに対してメソッドを拡張する (Safariは必要なし) if (!Prototype.BrowserFeatures.ElementExtensions) { Object.extend(Methods, Element.Methods); Object.extend(Methods, Element.Methods.Simulated); } } }); extend.refresh(); return extend; })();
無名関数を作成してすぐ実行しているので、その戻り値がElement.extendにセットされる。
Methodsは追加されるメソッド群、ByTagはタグごとに追加されるメソッド群。
extend(ローカル変数)が、Element.extendの本体。
extend.refreshは全てのタグに対して追加するメソッドをMethodsに追加するメソッド。
extendとextend.refreshは共にMethodsを参照するクロージャのため、
Methodsを拡張することで追加されるメソッドを変更することができる。
- Obejct.extend : 第一引数に第二引数のプロパティを追加して返すメソッド。
- Object.clone : シャローコピーを作成して返すメソッド。
- Prototype.K : 引数をそのまま返すメソッド。
- Prototype.emptyFunction : 何もせず何も返さないメソッド。
- Function.methodize : 第一引数にthisをとるメソッドにして返すメソッド。
Ubuntuでmanが使えない
Ubuntuのデフォルトでは日本語マニュアルがインストールされていないらしい
$ man man
No manual entry for man