fx7でresizeTo/resizeBy/moveTo/moveByがno longer apply to main windowな件

タイトル通りです。fx7からresizeTo/resizeBy/moveTo/moveByがメソッドとしては定義されていますが動作しなくなりました…。じゃなくて、no longer apply to main windowになりました。
これ系...

window.resizeTo(width, height);
window.resizeBy(width, height);
window.moveTo(x, y);
window.moveBy(x, y);

Firefox 7 for developersによれば

window.resizeTo, window.resizeBy, window.moveTo , and window.moveBy no longer apply to the main window.

https://developer.mozilla.org/en/Firefox_7_for_developers#DOM

bugzillaでの議論

565541 – Web sites shouldn't be allowed to resize main window
ここで議論されています。「websiteには、main windowのリサイズを許可すべきではない」

Comment53

For the most part, this only breaks web pages that are using this in ways that already break things. We are still allowing popup windows to resize themselves. We simply aren't allowing tabs in full-UI main browser windows to resize themselves, because they affect other tabs. In other words, we're actually fixing a lot more breakage than we're causing.

https://bugzilla.mozilla.org/show_bug.cgi?id=565541#c53

んー。読み間違いかなんなのか。スレッドを追ってもなんか話がつながっていかないんだよな…。

追記

  • 後、最初のエントリでーfirefox7でwindow.resizeTo/window.resizeByが動かなかったと記載してありましたが、「fx7+firebug」の環境ではでした。

Smartyのblockプラグインで変数を使う方法

  • block系のプラグインで変数を利用するためのプラグインの作成方法です。
  • やりたいことはsectionやforeachを利用せずに配列数に合わせてループとプラス・アルファの処理をさせたいということ。

サンプルソース

実行用のPHP
<?php
require_once 'Smarty.class.php';

$smarty = new Smarty();

$smarty->assign('array', array(
   array('foo'=>'foo1', 'bar'=>'bar1'),
   array('foo'=>'foo2', 'bar'=>'bar2')
));

$smarty->display('test.html');
テンプレート(test.html)
<{sample item=$array}>
    <{$item.foo}> -> <{$item.bar}>
<{/sample}>
block.sample.php
<?php
function smarty_block_sample($params, $content, &$smarty, &$repeat)
{
  if(is_null($content)) {
    $smarty->__temp__ = $params['item'];
    $item = array_shift($smarty->__temp__);
    $smarty->assign('item', $item);
    return;
  }

  $item = array_shift($smarty->__temp__);
  if(is_array($item))
  {
    $smarty->assign('item', $item);
    $repeat = true;
  }
  else
  {
    $repeat = false;
  }
  return $content;
}

$repeatが参照渡しになっているのがポイントですね。

ToDo

  • itemの値を上書きしているので一時的な変数に入れて元に戻す。
  • 分岐処理を精査すれば $smarty->assignを1箇所で済ませるかも?

雑感

久しぶりにSmarty触った。今は2系はバグフィックス程度(2009年最期)で、3系が開発されているんですね。

FlexでのMVC設計による開発パターン - その1 -

d:id:shogo4405:20110521:1305947042MVC的な考え方を踏襲した設計パターンです。ショッピングカート系のアプリケーションを開発するという前提で、僕ならこう設計していくよー。という話。

Modelの設計

WebServiceやHTTPServiceと連携すること考慮しておきます。ただし今回は簡単のためショッピングカートクラスの中身は次のようにシンプルにWebServiceの連携を考えない。
加えてのポイントは[Bindable]を忘れないことと、Singletoneパターンを活用すること。

myapp.controls.ShoppingCart

数量しか持っていないショッピングカート(何を買うんだろう…)で。addメソッドで数量を追加するというイメージ。

package myapp.models 
{
  [Bindable]
  public class ShoppingCart 
  {
    private static var instance:ShoppingCart = new ShoppingCart();
    // 買い物相手も数量
    public var quantity:int;
    // コンストラクタ
    public function ShoppingCart() {
       quantity = 0;
    };
    // 買い物かごのアイテムを追加
    public function add():void {
      quantity++;
    };
    public static function getInstance():ShoppingCart {
      return instance;
    };
  };
};

Controllerの設計

mx.controller.*を原則拡張するように設計します。IMXMLObjectを拡張して専用のControllerクラスをつくる…みたいなことはあえてしません。Webだったら/foo/aMethod or /foo/bMethodみたいに、メソッド数が少なくて済むけど。
GUI系だったらContollerの数が例えばボタンのイベント数。インプットフォームのイベント数と膨大になりがちになるのでこれも分割。mx.controller.*を拡張することで適当な大きさのControllerに分割します。みたいなこと必要?

package myapp.controls 
{
  import flash.events.MouseEvent;
  import mx.controls.*;
  import myapp.models.ShoppingCart;

  public class AddButtun extends Button
  {
    private var model:ShoppingCart;
		
    public function AddButtun()
    {
       this.model = ShoppingCart.getInstance();
       this.addEventListener(MouseEvent.CLICK, click);
    };

    private function click(e:*):void{
      model.add();
    };
  };
};

Viewの設計

もちろん、ここはmxmlを前提にして設計。mx.containers.*系はクラスを拡張して利用してあげること。appendChildとかメンドクサイのでしません。

Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:local="myapp.controls.*"
    >
    <mx:Script>
      <![CDATA[
      import myapp.models.*;
      [Bindable]
      public var model:ShoppingCart = ShoppingCart.getInstance();
      ]]>
    </mx:Script>
  <mx:TextInput text="{model.quantity}" />
  <local:AddButtun label="addCart" />
</mx:Application>

というわけで

上記のようにコーディングしていくと、View → Model ← Controllerで、Modelを媒介としてControllerでModelを更新してあげれば、Viewが勝手に更新されていく。実質、ControllerはViewのことを知らなくてもいい。Viewは、Controllerを知らなくていいみたいなことことができる。
これを実現している、Flexの[BIndable]で、[Bindable]を利用すると結合ぐあいがゆるく分離できるので良いです。

Greasemonkeyでjquery-uiを使うときのスニペット

jquery-uiを@requireしてもエラーで怒られたりするのでよく調べたらこんなんでいけるらしい。

// ==UserScript==
// @resource       jquery    http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js 
// @resource       jqueryui  http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js
// ==/UserScript==
(function() { 
  var head = document.getElementsByTagName('head')[0]; 
  var script = document.createElement('script');
  script.type = 'text/javascript'; 
  var jQuery = GM_getResourceText('jquery');
  var jQueryUI = GM_getResourceText('jqueryui'); 
  script.innerHTML = jQuery + jQueryUI;
  head.appendChild(script); 
  $ = unsafeWindow.$; 
})();

$(document).ready(function(){
// --
});

JavaScriptで複数人開発するときのガイドライン(マイルール)

JavaScript複数人開発するときのガイドライン(マイルール)です。SIerとかやっているとold JavaScriptやらモダンJavaScriptを見たりと色々な経験が得られるわけで…。やっぱり複数人開発するときには秩序は必要だなと思って、大体こんなルールにしていました。flex編はこの編 id:shogo4405:20110521:1305947042

こんなコード禁止

<html>
<head>
   <script type="text/javascript">
      // Todo あとでバグ修正する。仮起き。
      function foo(){
      };
      funciton bar(){
      };
   </script>
</head>
<body>
  <input type="buttun" click="foo();" id="idFoo">
  <input type="buttun" click="bar();" id="idBar">
</body>
</html>
  • 色々なスクリプトが増えてくるにつれて平気でソースコード1000行↑になる。
  • input=idFoo/input=idBar/input=idHoge...と増えていくに連れてイベントハンドラで使いたい名前が重複してくるので、衝突を防ぐ為に命名規則つけたりする。(後から)
  • fooはベテラン実装者Aさん。barの実装は初心者Bさん。fooを真似(コピペ)して書いて barでバグ発見という場合でもfooのバグを直しづらい。
  • input=idBarが不要になってもinput id="idBar"だけが削除されてJS部分削除されにくい。
  • コメントアウトされたよく分からないコードが増えてくる。
  • 1ファイルが巨大になるとその分責任が重くなる。
  • ソースコメントが見える。todo後で修正とかいうコメント見ると後っていつ?ってなる。

Flex編でも書きましたよね。似た奴。

集団開発するときの原理・原則

  • JavaScriptファイルはhtmlにインラインにしないで必ず開発の時は外にだす。読み込み時間を気にするとかでインラインにしたいときは、phpとかperlとかのファイル読み込み命令で読み込む。
  • サーバーにデプロイするときには、yuicompressorなの圧縮ツールを利用する。リリース後には不要なコメントも削除可能。(外部JSファイルにするメリット。)
  • 名前空間を考える。foo/bar/index.htmlに必要なJSは、foo.bar.index = {}のオブジェクトに格納する。JS自体もfoo/bar/index.jsみたいにファイル名をつける。1ファイル=1名前空間という概念。
  • 複数のJSから呼ばれるような関数群は専用の名前空間を用意。foo.globalとかね。foo/bar/bar.html、foo/bar/foo.htmlに共通して必要でもglobal使うほどじゃない奴は、foo.bar.globalとかの空間を利用。
  • htmlが不要になれば、当然jsも何も考えずに削除。1JSは独立。他のファイルには原則して依存しない。させない。依存するような関数はglobal空間を利用。

というわけで

以下のようなスタイルで開発していました。まぁ少量のコードや1人だったらメリットはないですけど。ソースコードが膨れてきて修正やら保守が入りだしたら効果が発揮すると思います。

myapp/index.html
<html>
<head>
   <script type="text/javacript" src="myapp/index.js"></script>
</head>
<body>
   <input type="buttun" click="myapp.index.foo();" id="idFoo">
   <input type="buttun" click="myapp.index.bar();" id="idBar">
</body>
</html>
muapp/index.js
if(typeof(myapp) == 'undefined'){
    myapp = {};
};
myapp.index = 
{
   foo: funciton(){},
   bar: function(){}
};

Flexアプリを複数人開発するときのガイドライン(マイルール)

flexアプリケーションを複数の開発者で開発したことがあったときに過去を反省して過去を反省した自分がよく使っていた開発方針のメモです。

よくあるコード

よくサンプルとかで見かけるソースコードです。html + JavaScriptもこんなイメージで書かれていることが多いので主流なんでしょうか。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
  <mx:Script>
    <![CDATA[
            import flash.events.MouseEvent;
            import mx.controls.Alert;
            public function clickFoo ( event:MouseEvent ):void{
                Alert.show("foo");
            };
            public function clickBar ( event:MouseEvent ):void{
                Alert.show("bar");
            };
    ]]>
  </mx:Script>
  <mx:Buttun click="clickFoo(event)" />
  <mx:Buttun click="clickBar(event)" />
</mx:Application>

この形式で開発をすすめていくと…

ということが開発の後、後になってから増えてきたりする。

集団開発するときの原理・原則

集団開発するときに↑みたいなスタイルで開発してバグ修正がしづらかったり、どこを修正していいか分からなかったりして苦慮したことを反省して次のルールで開発するようになった。

  • mx:Buttunのようなmx.controlsに所属するようなコンポーネントは必ず拡張して使う。mx.containerのようにPanelとかも中でゴニョゴニョする予定なら拡張する。
  • 1ファイル=1クラス。1開発者の割り当て。→責任の分散。
  • ファイルの中身はブラックボックス。例えその中身のソースコードや冗長な処理があっても無視。(いいのか悪いのかは置いておいて。)
  • そのクラスが不要になったら、中身をみずに削除。そのコンポーネントが依存関係にあったらコンパイラが教えてくれる。

というわけでこんな感じ

というわけでこういう感じで開発するようになりました。このスタイルに変更してから過去の遺産にお伺いたてることもなくなったので本来の創るという作業に集中できるようになりました。

main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="app.*">
  <local:FooButtun />
  <local:BarButtun />
</mx:Application>
app/FooButtun.as
package app { 
    import flash.events.MouseEvent;
    import mx.controls.Alert;

    public class FooButton extends Button {
        public function FooButtun() {
            addEventListener(MouseEvent.CLICK,  click);
        }
        private function click ( event:MouseEvent ):void{
                Alert.show("foo");
        };
    }
}
app/BarButtun.as
package app { 
    import flash.events.MouseEvent;
    import mx.controls.Alert;

    public class BarButton extends Button {
        public function BarButtun() {
            addEventListener(MouseEvent.CLICK,  click);
        }
        private function click ( event:MouseEvent ):void{
                Alert.show("bar");
        };
    }
}

maven使うときのコマンドライン

mavenを利用してslim3を利用するときのコマンドラインのメモ。mvn eclipse:eclipse のときに-DdownloadSources=trueを忘れない。

mvn archetype:generate -DarchetypeCatalog=http://slim3.googlecode.com/svn/trunk/repository
mvn eclipse:eclipse -DdownloadSources=true