ページに『投稿』を挿入するWordpress プラグイン:Inline Posts
3月 9th
Inline Postsとは
Wordpressの記事には、ページ(Page)と投稿(Post)の2種類があります。
WordpressのプラグインInline Postsは、ページ中に『投稿』を挿入してくれるプラグインです。
これを使うと、『投稿』をページ内のセクションのようにして扱う事ができるので、過去に書いた『投稿』をまとめてページとして公開するとうような便利な使い方ができます。
作者は、SWXの作者でもあるAral Balkan氏です。実際にSWXFormat.orgのサイトもこのプラグインを使っているようです。
インストール
- ここのページのInline Posts Wordpress Pluginのzipアーカイブをダウンロードする
- ダウンロードしたzipアーカイブの中身をWordpressのプラグインフォルダに配置して、プラグインをアクティベーションします。
使い方
使い方は簡単で、挿入したい『投稿』のIDを角括弧で2重に囲ってやるだけでOK。例えばIDが43の『投稿』は、
[[43]]
としてやります。
さらに、プラグインUltimate Category Excluderを使えば、メインページに表示したくないカテゴリの『投稿』を非表示にすることもできるので、Inline Postsと組み合わせて使うとかなり便利です。
Wordpressの管理画面のレイアウトが崩れる
1月 11th
wordpressを2.8から、2.9にアップグレードしたんですが、firefoxで管理画面(ダッシュボード)を読み込むと、CSSが無効になってレイアウトが崩れていしまった。IEでは正常に表示されるのになぜ!?(ちなみに、IE以外のブラウザでも同じような現象になる。)
まず、CSSがどこから読み込まれているのか確認をすると、管理画面のCSSは、ファイルではなく、wp-admin/load-styles.phpによって動的に生成されるものになっていた。
次に、レスポンスがどうなっているかをFirebugで確認する。
HTTP/1.x 200 OK Date: Mon, 11 Jan 2010 03:15:26 GMT Server: Apache Cache-Control: public, max-age=31536000 Content-Encoding: deflate Expires: Tue, 11 Jan 2011 03:15:26 GMT Vary: Accept-Encoding Content-Type: text/html Connection: close Transfer-Encoding: chunked
そうすると、Content-Typeがtext/htmlになっていることが判明。
header()メソッドでコンテントタイプが指定されてないのかと思い、load-styles.phpを確認すると、135行目当たりに、ちゃんと指定されている。
header('Content-Type: text/css');
んじゃ、どこか別の場所で先にヘッダが出力されている可能性があるかもしれないので、load-styles.phpの先頭にerror_reportingメソッドを追加して、エラー・ワーニングを表示するようにしてやる。
error_reporting(E_ALL);
error_reportingを有効にしてブラウザでアクセスしてみると、エラーやワーニングは発生してない模様。
ここで、もうワカラーン状態になってしまったのですけど、試しに、以下のようにヘッダーを1つ追加してみたところ…
header('Dummy: for warning');
header('Content-Type: text/css');
動いた!
なぜに?
どうやら、最初のheader()メソッドの呼び出しだけが無効になってるらしい。サーバの設定の問題なのか、何なのか…。 xoopsでも同じような現象があるらしいし、wordpressだけの問題じゃなさそう。
まぁ、とりあえず、動いたし、疲れたので、この原因究明はまた今度に。
平方根の逆数を高速に求める
1月 11th
float InvSqrtLinear(float x, int magic){
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating value
i = magic - (i>>1); // gives initial guess y0
x = *(float*)&i; // convert bits back to float
return x;
}
平方根の逆数の近似値を高速に求めるアルゴリズム。ゲームのQuake3で有名になった方法らしいです。詳しくはOrigine of Quakes3's Fast InvSqrt()に解説があるのでそちらを参照してください。
簡単に説明すると、ニュートン・ラプソン法による平方根の逆数の計算を、最初の1回だけ行って近似値を求めるという方法で、それほど精度を必要としないなら高速な計算が行えます。
これをFlashでも使えないかと思って調べてみると、mtascやhaxeの作者nicolas自身がこの記事に解説を書いてくれていました。
FlashのAS3ではByteArrayのwriteFloat()、readInt()を使ってInt型とNumber型を変換する処理を行いますが、これらのメソッドの実行速度が遅く、普通に計算するより遅くなってしまうようです。
高速にアクセスできるhaxeのVirtual Memory APIで実装すると以下のようになります。
public function prepare() {
var b = new flash.utils.ByteArray();
b.length = 1024;
flash.Memory.select(b);
}
public function invSqrt( x : Float ) : Float {
var half = 0.5 * x;
flash.Memory.setFloat(0,x);
var i = flash.Memory.getI32(0);
i = 0x5f3759df - (i>>1);
flash.Memory.setI32(0,i);
x = flash.Memory.getFloat(0);
x = x * (1.5 - half*x*x);
return x;
}
この方法だと、約700%程高速に実行できるようです。グレート!
haxe3DやphysaXeもこのメソッドを採用しているようです。
参考サイト
Haxeに用意されていないクラス・メソッドにアクセス
12月 16th
as3に存在するのに、haxeに無いクラスやメソッドを使いたい場合は_global_オブジェクトを介してアクセスを行う。
例としてflash.utils.describeTypeメソッドをhaxeから使用してみる。
package samples;
import flash.display.Sprite;
import flash.events.Event;
import flash.xml.XML;
class DescribeType extends Sprite
{
public static function main():Void {
flash.Lib.current.addChild(new DescribeType());
}
public function new() {
super();
if (stage != null) {
initialize();
}else {
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
}
private function initialize():Void {
var describeType:Dynamic->String = untyped __global__["flash.utils.describeType"];
var xml:XML = new XML(describeType(this));
trace(xml.toXMLString());
}
private function addedToStageHandler(event:Event):Void {
removeEventListener(event.type , addedToStageHandler);
initialize();
}
}
生成されるas3のコードはこんな感じ。
package samples {
import flash.utils.describeType;
import haxe.Log;
import flash.Lib;
import flash.display.Sprite;
import flash.events.Event;
import flash.Boot;
public class DescribeType extends flash.display.Sprite {
public function DescribeType() : void { if( !flash.Boot.skip_constructor ) {
super();
if(this.stage != null) {
this.initialize();
}
else {
this.addEventListener(flash.events.Event.ADDED_TO_STAGE,this.addedToStageHandler);
}
}}
protected function initialize() : void {
var describeType : Function = flash.utils.describeType;
var xml : XML = new XML(describeType(this));
haxe.Log.trace(xml.toXMLString(),{ fileName : "DescribeType.hx", lineNumber : 23, className : "nl.demonsters.debugger.DescribeType", methodName : "initialize"});
}
protected function addedToStageHandler(event : flash.events.Event) : void {
this.removeEventListener(event.type,this.addedToStageHandler);
this.initialize();
}
static public function main() : void {
flash.Lib.current.addChild(new nl.demonsters.debugger.DescribeType());
}
}
}
HaxeからSWCを利用するには
12月 16th
HaxeからSWCライブラリを利用する手順
- SWCを解凍する
SWCは、catalog.xmlとlibrary.swfをzipで圧縮したもので、hxクラスを生成するにはこのlibrary.swfが必要。解凍してlibrary.swfを取り出します。
- library.swfからhaxeのクラスを生成
hexaコンパイラのクラス生成機能を使います。コンパイラに--gen-hx-classesオプションを指定して、library.swfからhaxeクラスのソースファイルを生成します。そうすると、フォルダhxclassesが出来、中にはhaxeのクラスのソースが生成されます。クラスはhaxeからswfを利用するためのスタブとして動作します。
haxe --gen-hx-classes library.swf
- コンパイル
コンパイルを行うには、生成したクラスにクラスパスを通すのと、オプション-swf-libを指定してやります。
haxe -cp [生成したクラスへのパス] -swf-lib [swfファイルへのパス]
- 生成したhxを修正
コンパイルがそのまま成功すればOKなのですが、一部スタブの生成が上手くいかない場合があるので、修正するのは主に関数の引数の部分で、
たとえば、関数のデフォルトの値などはスタブに含まれないのでfunction someFunc(param1:Number = 1.0):void{ ・・・ }のような関数のスタブは
function someFunc(param1:Float):Void{ ・・・ }と、デフォルトの値が含まれません。これはhaxeでは、Null<Float>(NullもしくはFloatをとる)と解釈されるので、Numberしか値をとらない元のメソッドと違いが発生してエラーとなる場合があります。デフォルトの値をつけて修正します。
ほかにも、Functionオブジェクトを引数にとるような関数は、addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{ }function addEventListener(type : String, listener : Dynamic, ?useCapture : Bool = false, ?priority : Int = 0, ?useWeakReference : Bool = false) : Void;
上記のように、Functionオブジェクトのlistener パラメータがDynamic型として生成され、Dynamic->Voidと修正する必要があります。(haxeでは、引数の型だけでなく、戻り値の型もメソッドのシグネチャに含むので)
最後に試しに、Google Maps API for Flash をhaxeから使用してみます。
package samples.googlemap;
import com.google.maps.LatLng;
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.MapType;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Point;
import flash.Lib;
class Main extends MovieClip
{
static function main()
{
flash.Lib.current.addChild(new Main());
}
private var _map:Map;
public function new() {
super();
if (stage != null) {
initialize();
}else {
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
}
private function addedToStageHandler(event:Event):Void {
removeEventListener(event.type, addedToStageHandler);
initialize();
}
private function initialize():Void {
_map = new Map();
_map.key = "api_key";//use your own api key
_map.setSize(new Point(stage.stageWidth, stage.stageHeight));
_map.addEventListener(MapEvent.MAP_READY, mapReadyHandler);
addChild(_map);
}
private function mapReadyHandler(event:MapEvent):Void {
var map:Map = cast(event.target , Map);
map.setCenter(new LatLng(40.736072, -73.992062), 14, MapType.NORMAL_MAP_TYPE);
}
}
FlashDevelop import文をソートするスクリプトを書いてみた。
12月 15th
import文をソートするスクリプト
もともと、FlashDevelopには、Sort linesやSort line Groupsという機能、行をソートしてくれるものがあるんですが、テキストを選択して範囲を指定しなきゃならないのがちょっと面倒だったので、スクリプトでimport文を自動で判定してソートするようなものを作ってみた。連続するimport文を一つのグループとして、グループそれぞれについてソートを行います。
スクリプトは1つのクラスからなり、static メソッドExecute()がコールされることで実行が始まります。
ドキュメントの内容にアクセスするには、ScintillaControl コントロールを介してアクセスします。ScintillaControlというのはScintilla(シンティラ)という文書編集機能を実装したエディタコンポーネントで、シンタックスハイライトは、コード補完機能を提供してくれています。
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using PluginCore;
using PluginCore.Managers;
using FlashDevelop;
using ScintillaNet;
namespace FDScript
{
public class SortImport
{
private ScintillaControl sci;
public SortImport()
{
sci = Globals.SciControl;
}
public static void Execute()
{
SortImport app = new SortImport();
app.Run();
}
private void Run()
{
Regex r = new Regex("^\\s*import");
//import文を探す
for (Int32 i = 0; i < sci.LineCount; i++)
{
String line = sci.GetLine(i);
if (r.IsMatch(line))
{
List<String> lines = new List<String>();
lines.Add(line);
Int32 start = i;
while(true){
i++;
line = sci.GetLine(i);
if (!r.IsMatch(line))
{
break;
}
lines.Add(line);
}
Int32 end = i - 1;
if (end > start)
{
lines.Sort(CompareLines);
StringBuilder result = new StringBuilder();
foreach (String s in lines)
{
result.Append(s);
}
Int32 startPos = sci.PositionFromLine(start);
Int32 endPos = sci.PositionFromLine(end) + sci.GetLine(end).Length;
sci.SetSel(startPos, endPos);
sci.ReplaceSel(result.ToString());
}
}
}
}
private static Int32 CompareLines(String a, String b)
{
Char[] whitespace = { '\t', ' ' };
a = a.TrimStart(whitespace);
b = b.TrimStart(whitespace);
return a.CompareTo(b);
}
}
}
作成したスクリプトをFlashDevelopのメニューに登録するには、メニュー [Macro]->[Edit Macros...]と選択して、Macroダイアログを表示。
Addボタンを押して、マクロを追加する。
Entriesの項目に
ExecuteScript|Development;{スクリプトへのパス}
と記述すればOK。
jetpackからfirebugコンソールに出力できない
12月 8th
Vector.<T>を動的に生成
12月 8th
Vectorクラスは、そのコンストラクタを呼び出すときに配列の要素の型であるベースクラスを指定してインスタンス化を行います。
var vector:Vector.<BaseClass> = new Vector.<BaseClass>();
スタティックな場合はこれでいいのですが、ベースクラスが分からないようなランタイムで任意のベースラスを持ったVector生成したいような場合は、ApplicationDomain.getDefinition()やflash.utils.getDefinitionByName()を使用します。
ただ、単純に
var vecCls:Class = getDefinitionByName("Vector.<SomeClass>") as Class;
としても駄目で、VectorクラスのQualifiedName(完全修飾名)を使用する必要があります。
完全修飾名はflash.utils.getQualifiedClassName()によって得られます。
var qname:String = getQualifiedClassName('Vector');
var vector:* = getDefinitionByName(qname+".<baseclass_name>");
サンプルコード
/*
Vector をランタイムに動的生成。
*/
package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.Event;
import flash.utils.describeType;
public class FlashTest extends Sprite {
private var _tf:TextField;
public function FlashTest() {
// write as3 code here..
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
public function initialize(event:Event):void{
removeEventListener(event.type, arguments.callee);
_tf = new TextField();
addChild(_tf);
_tf.width = stage.stageWidth;
_tf.height = stage.stageHeight;
println("Start Application");
var vecSprite:* = VectorUtil.createTypedVector(Sprite, 5, true);
vecSprite[0] = new Sprite();
var desc:XML = XML(describeType(vecSprite));
println(desc.@name);
//プライベートなクラスはgetDefinitionで得ることができないっぽい。
}
private function println(str:String):void{
_tf.appendText(str);
_tf.appendText('\n');
}
private function print(str:String):void{
_tf.appendText(str);
}
}
}
import flash.system.ApplicationDomain;
import flash.utils.getQualifiedClassName;
class VectorUtil {
static public const VECTOR_QNAME:String = getQualifiedClassName(Vector);
static public function getVectorDefinition(elementCls:Class, appDomain:ApplicationDomain = null):Class {
if (!appDomain) {
appDomain = ApplicationDomain.currentDomain;
}
return appDomain.getDefinition(VECTOR_QNAME + ".<" + getQualifiedClassName(elementCls) + ">") as Class;
}
static public function createTypedVector(dataType:Class, length:uint = 0, fixed:Boolean = false, domain:ApplicationDomain=null):*{
var def:Class = getVectorDefinition(dataType, domain);
return new def(length, fixed);
}
}
mx.core.Windowは再オープン出来ない
12月 6th
mx.core.Windowは、一度close()してしまうと、open()しても表示されないようです。
Windowインスタンスを使い回せないかと、コードを書き換えたら表示されなくなったので、なぜかと思ったらそういう『仕様』でしたか・・・
これ、Flex3のリファレンスだと、
Creates the underlying NativeWindow and opens it.
としか書いてないのに、Flex4のリファレンスでは、
Creates the underlying NativeWindow and opens it. After being closed, the Window object is still a valid reference, but accessing most properties and methods will not work. Closed windows cannot be reopened.
とちゃんと書き加えられている。 やっぱ、そういうことはちゃんと書いておいて欲しいと思うわけですよ!。
PopUpMangerでダイアログボックス
12月 5th
PopUpManagerとTitleWindowを使ってダイアログボックスのような機能を実現するサンプル。
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="creationCompleteHandler(event)">
<mx:Script>
<![CDATA[
import com.matzmtok.samples.air.dialog.SampleDialog;
import mx.events.FlexEvent;
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
import mx.managers.PopUpManagerChildList;
import flash.events.MouseEvent;
[Bindable]
private var message:String;
private var _popup:SampleDialog;
public function creationCompleteHandler(event:FlexEvent):void {
openModalDialog.addEventListener(MouseEvent.CLICK, showModalDialog);
openModelessDialog.addEventListener(MouseEvent.CLICK, showModelessDialog);
}
private function showModelessDialog(e:MouseEvent):void {
var _popup:SampleDialog = PopUpManager.createPopUp(this, SampleDialog, false) as SampleDialog;
_popup.addEventListener(CloseEvent.CLOSE, _popupCloseHandler);
PopUpManager.centerPopUp(_popup);
}
public function showModalDialog(event:MouseEvent):void{
var _popup:SampleDialog = PopUpManager.createPopUp(this, SampleDialog, true ) as SampleDialog;
_popup.addEventListener(CloseEvent.CLOSE, _popupCloseHandler);
PopUpManager.centerPopUp(_popup);
}
public function _popupCloseHandler(event:CloseEvent):void{
var popup:SampleDialog = event.target as SampleDialog;
message = popup.message;
}
]]>
</mx:Script>
<mx:VBox>
<mx:Label text="Message" />
<mx:Label id="lMessage" text="{message}" width="100%" />
<mx:HBox>
<mx:Button id="openModalDialog" label="show modal dialog" />
<mx:Button id="openModelessDialog" label="show modeless dialog" />
</mx:HBox>
</mx:VBox>
</mx:WindowedApplication>
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import flash.events.Event;
import flash.events.MouseEvent;
import mx.events.CloseEvent;
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
override protected function createChildren():void{
super.createChildren();
btnOk.addEventListener(MouseEvent.CLICK, btnOkClickHandler);
btnCancel.addEventListener(MouseEvent.CLICK, btnCancelClickHandler);
title = "Sample Dialog Box";
showCloseButton = true;
addEventListener(CloseEvent.CLOSE, closeHandler);
}
private function btnCancelClickHandler(e:MouseEvent):void
{
closeHandler();
}
private function closeHandler(e:CloseEvent = null):void
{
PopUpManager.removePopUp(this);
removeEventListener(CloseEvent.CLOSE, arguments.callee);
dispatchEvent(new CloseEvent(CloseEvent.CLOSE));
}
private function btnOkClickHandler(e:MouseEvent):void
{
closeHandler();
}
public function get message():String{
return tiMessage.text;
}
public function set message(value:String):void {
tiMessage.text = value;
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%">
<mx:Label text="Enter Some Message" />
<mx:TextInput id="tiMessage" width="100%" />
<mx:Spacer width="100%" height="15" />
<mx:HBox width="100%" height="100%" horizontalAlign="center" verticalAlign="middle">
<mx:Button id="btnOk" label="OK" />
<mx:Button id="btnCancel" label="Cancel" />
</mx:HBox>
</mx:VBox>
</mx:TitleWindow>
最近のコメント