2014年11月24日月曜日

grunt-maven-pluginを使用したプロジェクトでtarget中の不要ファイルを削除する

前回のままだとGruntfile.jsやpackage.jsonなどがtargetに含まれてしまいます。。。 なのでこれを削除したいと思います。


target/classes
├── static
│   ├── Gruntfile.js
│   ├── js
│   │   ├── app.min.js
│   │   └── src
│   │       ├── Doramon.js
│   │       ├── main.js
│   │       └── namespace.js
│   ├── maven-properties.json
│   └── package.json
  


Mavenの情報を取得してtargetのパスを取得します。


今回はこれのoutputDirectoryを使います。
{
  "directory": "${project.build.directory}",
  "outputDirectory": "${project.build.outputDirectory}",
  "name": "${project.name}",
  "version": "${project.version}",
  "finalName": "${project.build.finalName}"
}
  
GitHub: src/main/resources/static/maven-properties.json


Gruntからtargetのパス情報を取得して不要ファイルの削除を行います。


ついでに"clean:before"という作業前に前回のJavaScriptを削除する処理を追加
module.exports = function (grunt) {
    grunt.initConfig({
        ・・・省略・・・
        mvnProp: grunt.file.readJSON('maven-properties.json'),
        ・・・省略・・・
        clean: {
            before: {
                options: {  force: true  },
                files: { src: [ "js/**/*.js" ] }
            },
            after: {
                options: {  force: true  },
                files: {
                    src: [
                        "<%= mvnProp.outputDirectory %>/static/Gruntfile.js",
                        "<%= mvnProp.outputDirectory %>/static/package.json",
                        "<%= mvnProp.outputDirectory %>/static/maven-properties.json",
                        "<%= mvnProp.outputDirectory %>/static/js/**/*.js"
                    ]
                }
            }
        },
        ・・・省略・・・
    grunt.registerTask('beforeClean', ['clean:before']);
    grunt.registerTask('default', ['mavenPrepare', 'concat', 'clean:after', 'mavenDist']);
};
  
GitHub: src/main/resources/static/Gruntfile.js

※ ※ 修正しました〜。goalsのgoalに create-resources がないとnpm installできませんでした。 ※

Gruntの"clean:before"をMavenのinitializeフェーズで動かす


<execution>
    <id>gruntInit</id>
    <phase>initialize</phase>
    <configuration>
        <gruntOptions>
            <gruntOption>beforeClean</gruntOption>
        </gruntOptions>
    </configuration>
    <goals>
        <goal>create-resources</goal>
        <goal>npm</goal>
        <goal>grunt</goal>
    </goals>
</execution>
  
GitHub: pom.xml


これで不要なファイルが消えました。


  target/classes
├── static
│   └── js
│       ├── app.min.js
│       └── src

サンプルを GitHub にあげています。 参考になれば幸いです〜。

2014年11月23日日曜日

MavenからGruntを起動する"grunt-maven-plugin"を使ってみました

みなさまはMavenプロジェクトでJSの結合やミニファイをどうなされていますか??

いろいろ探しているとMavenからGruntを起動するMavenプラグインを発見したので それについて調べてみたいと思います。


allegro/grunt-maven-plugin


"Grunt + Maven integration done right"
https://github.com/allegro/grunt-maven-plugin


Spring Bootのプロジェクトをサンプルで作成


Gruntを埋め込む対象としてSpring Bootのプロジェクトを作成しました。 Spring Bootの利用方法については下記ブログとかスライドをご参考ください〜


gitの管理からgrunt-mavenの作業場所を外す


.gitignoreにgrunt-mavenがJavaScript等の加工作業する場所を追加しました。
target-grunt
GitHub: .gitignore


nmp installする(Gruntで使用するパッケージ)を設定


maven-gruntで npm installするパッケージを指定します。"target-grunt"の中にnode_modulesがインストールされます。
{
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-cli": "~0.1.6",
    "grunt-contrib-concat": "^0.5.0",
    "grunt-maven": "~1.1.0",
    "grunt-contrib-clean": "~0.6.0"
  }
}
  
GitHub: src/main/resources/static/package.json


pom.xmlの情報をGruntに渡すファイルを設定


Pom/Project propertiesの値をファイルに書き込んでほしいものを指定する(た、多分。。調査不足)
{
  "version": "${project.version}"
}
  
src/main/resources/static/maven-properties.json

プロパティの種類は下記を参考にさせていただきました!ありがとうございます。
ねこだいすき:pom.xmlからプロパティ取得


Mavenから呼び出すGruntファイルの準備


例として複数のJavaScriptを結合してtarget/classesの中に結合した結果のJavaScriptファイルをコピーする
module.exports = function (grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        gruntMavenProperties: grunt.file.readJSON('grunt-maven.json'),
        mavenPrepare: {
            options: {
                resources: ['**']
            },
            dev: {}
        },
        concat: {
            files: {
                src: ['js/src/namespace.js', 'js/src/**/*.js', 'js/src/main.js'],
                dest: 'js/app.min.js'
            }
        },
        clean: {
            js: [
                "js/**/*.js",
                "!js/**/*.min.js"
            ]
        },
        mavenDist: {
            options: {
                warName: "classes",
                deliverables: ["js/**/*.min.js"]
            },
            dev: {}
        }
    });

    grunt.loadNpmTasks('grunt-maven');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-concat');

    grunt.registerTask('default', ['mavenPrepare', 'concat', 'mavenDist', 'clean']);
};
  
src/main/resources/static/Gruntfile.js


MavenからGruntを起動


Maven pluginsの中に↓追加しました。
<plugin>
            <groupId>pl.allegro</groupId>
            <artifactId>grunt-maven-plugin</artifactId>
            <version>1.4.1</version>
            <configuration>
                <sourceDirectory>${basedir}/src/main/resources</sourceDirectory>
                <gruntExecutable>node_modules/grunt-cli/bin/grunt</gruntExecutable>
                <runGruntWithNode>true</runGruntWithNode>
                <filteredResources>
                    <filteredResource>maven-properties.json</filteredResource>
                </filteredResources>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>create-resources</goal>
                        <goal>npm</goal>
                        <goal>grunt</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
     </plugins>
  
pom.xml

これで Mavenのcompile時にGruntを起動するようになりました。
サンプルをGitHubにあげています。
参考になれば幸いです〜。

2014年10月26日日曜日

Dragomeをちょっと使ってみました

なんだか面白そうなDragomeというライブラリを発見したのでちょっと試してみました。

Dragome Web SDK


Takes your Java code to the web
http://www.dragome.com/


なんでもJavaでフロントエンドもかけるらしいのです。

サーバーサイドをJavaで書いている方々から
よくJavaScript書きたくないと言われるので...(ToT)

JSF以外の選択肢として使えるものかちょっと調べてみました。

プロジェクトの雛形を生成


$ mvn archetype:generate -DarchetypeGroupId=com.dragome -DarchetypeArtifactId=simple-webapp-archetype -DarchetypeVersion=1.0 -DgroupId=com.example -DartifactId=hello 
$ cd hello
$ ls
pom.xml src

そのままをコンパイルして実行


$ mvn compile
$ mvn jetty:run
ブラウザで http://localhost:8080/hello/hello-world.html を実行
おお何かでました。

Say hello!のボタンを押下すると

POSTが発生して text/plainのメッセージが帰って来ました。

どんな感じでコーディングするのでしょうか。。

htmlみると...


<html>
<head>
<script type="text/javascript" src="dragome/dragome.js"></script>
</head>

<body>
 Message:
 <b data-template="message">...</b>
 <br>
 <button data-template="button">Say hello!</button>
</body>

</html>
おおお、スッキリしてますね。
ボタンのイベントとその結果の貼り付けはJavaの方に書いてあるんでしょうね。

Javaのソースは..


$ cd src/main/java

$ tree
.
└── com
    └── example
        ├── gui
        │   └── HelloWorldPage.java
        └── service
            ├── HelloWorldService.java
            └── serverside
                └── HelloWolrdServiceImpl.java
↑Javaのソースは3つありますね。

com.example.service



HelloWorldServiceインターフェースを

package com.example.service;

import ... 省略 ...; @ServiceImplementation(HelloWolrdServiceImpl.class)
public interface HelloWorldService {
    public abstract String getGreetingsFor(String name);
}

serverside.HelloWolrdServiceImplで実装してるみたい

package com.example.service.serverside;

import java.util.Date;
import com.example.service.HelloWorldService;

public class HelloWolrdServiceImpl implements HelloWorldService {
    public String getGreetingsFor(String name) {
        return "Hello " + name + "! (" + new Date() + ")";
    }
}

@PageAliasをつけるのがhtml(View)に対応したcontroller(?)なのかな

aliasでhtmlファイル名を指定するみたい。
package com.example.gui;

import ... 省略 ...;

@PageAlias(alias = "hello-world")
public class HelloWorldPage extends DragomeVisualActivity {
    HelloWorldService helloWorldService = serviceFactory.createSyncService(HelloWorldService.class);

    public void build() {

        // <b data-template="message">
        final VisualLabel<String> label = new VisualLabelImpl<String>("message");

        // <button data-template="button">
        final VisualButton button = new VisualButtonImpl("button", new ClickListener() {
            public void clickPerformed(
          VisualComponent aVisualComponent) {

                label.setValue(
     helloWorldService.getGreetingsFor("World"));
            }
        });

        mainPanel.addChild(label);
        mainPanel.addChild(button);
    }
}

data-templateで与えた名前を...

<b data-template="message">...</b>

下記のように紐付けるみたい

final VisualLabel<String> label
    = new VisualLabelImpl<String>("message")

ボタンのイベントリスナーでサービスからの値を取得すると


final VisualButton button = new VisualButtonImpl("button", new ClickListener() {
 public void clickPerformed(VisualComponent aVisualComponent) {
  label.setValue(helloWorldService.getGreetingsFor("World"));
  }
});

AJaxになってサーバから値を取得してくれるみたいです。


すごいなぁ。

2014年9月6日土曜日

2014/09/06 その3 AngularJS福岡勉強会(第2回) - Directiveの自作 -

01.directive - restrict: 'EAC' -



    <!-- restrict: 'E' -->
    要素名で置き換え!
    <ore-panel ></ore-panel>
    
    <!-- restrict: 'A' -->
    属性名で置き換え!
    <div ore-panel="" ></div>
      
    <!-- restrict: 'C' -->
    class名で置き換え!
    <div class="ore-panel" ></div>

02.directive - parent scope -


Directive内も外側のスコープが使えます。

03.directive - isolate scope -


Directive内でscopeを宣言し外のscopeと接続する事が出来ます。
こうする事で独自Directiveを作る人は外のscopeの事を考えずに作成する事ができます。
利用する人は属性にパラメータ値を渡す事が出来ます。

04.directive - isolate scope function -


属性に渡すのは値だけでなくfunctionも渡す事が出来ます。
scope:{ 'clicked': '&' } 
引数に値を渡す時はオブジェクトの形を使用します。




twitterのハッシュタグ

質問やこうした方がいいよ〜とかありましたら、↓につぶやいてください〜

#ng_fukuoka

2014年9月5日金曜日

2014/09/06 その2 AngularJS福岡勉強会(第2回) - DOM制御とか装飾とか -

01. ng-class


ng-classを使うとclassの切り替えが出来ます。
ng-class="{ 'panel-info': !isDanger, 'panel-danger': isDanger  }" と書くと
isDangerが trueの時に'panel-danger'class(スタイルシート)が
isDangerが falseの時に'panel-info'がDOM要素につけられます。

02. ng-style


ng-styleを使うとstyleの切り替えが出来ます。

03. ng-if


ng-ifを使うと要素の表示・非表示ができます。
☆ポイント☆
display:none;ではなくて要素が作られたり消されたりします。

04. ng-if with animation


ng-ifにAnimationを追加できます
☆ポイント☆
angular-animate.jsを読んでangular.module('app', ['ngAnimate']);とモジュール追加すること
CSSでアニメーション情報を指定してあげること
jsFIddleの.ng-enter ,.ng-leave, .ng-leave.ng-leave-active, .ng-enter.ng-enter-activeを参照

05. ng-show


ng-showも要素の表示・非表示ができます。
☆ポイント☆
display:none;で表示・非表示を切り替えてます。

06. ng-show with animation


ng-showも要素の表示・非表示ができます。
☆ポイント☆
Migrating from 1.2 to 1.3
https://docs.angularjs.org/guide/migration
書き方がかわったみたい
Migrating from 1.2 to 1.3




twitterのハッシュタグ

質問やこうした方がいいよ〜とかありましたら、↓につぶやいてください〜

#ng_fukuoka

2014/09/06 その1 AngularJS福岡勉強会(第2回) - form -

01. form.input.$invalid


必須入力のinputが空の場合にテキストボックスの枠を赤くする
☆ポイント☆
 form name="fm"   で fmというFormControllerが使えるようになります。
 input name="inputCd" でfm.inputCdにNgModelControllerが使えます。

02. form.input.$invalid と form.$invalid


form全体でエラーがあるのか項目単位でエラーがあるのか判別できます。
☆ポイント☆
 fm.inputCd.$invalid って書くと個別で不正が無いか確認
 fm.$invalid って書くとform全体で不正が無いか確認できます

03. form.input.$error


$errorで細かいエラーを判別出来ます。
☆ポイント☆
$error.required で必須チェックでエラーなのか
$error.maxlength で最大長でエラーなのか
$error.pattern で許されないパターンの入力なのか判別できます。

04. ngFormで formの入れ子


formを入れ子にして分割出来ます。
☆ポイント☆
ngFormで入れ子にできる
でも標準のHTML5のバリデーションはngFormに気づかない...
しかたないので novalidate で機能をOFF!

05. ngFormをngRepeatで繰り返す


ng-formはng-repeatの中で繰り返しつかえます。

おまけ blurの時に ng-modelを更新したいなぁ


どうやら1.3からng-model-options="{ updateOn: 'blur' }"って指定すると
blurイベント時にng-modelを更新するようにできるらしい!
1.2を使っている方は自分でカスタムディレクティブを作りましょう〜。
stackoverflow:How to let ng-model not update immediately?
http://stackoverflow.com/questions/14722577/how-to-let-ng-model-not-update-immediately




twitterのハッシュタグ

質問やこうした方がいいよ〜とかありましたら、↓につぶやいてください〜

#ng_fukuoka

2014年7月29日火曜日

altJS福岡勉強会第1回準備中〜

altJS福岡勉強会第1回準備中〜

今度の土曜日(2014/8/2土)にaltJS福岡勉強会第1回を開催する予定です!
http://www.zusaar.com/event/6467004

AngularJSを仕事で少し使っている私は
AngularJS2が Traceurを採用しているという事なんで

All code in AngularJS 2 is already being written in ES6. As ES6 doesn’t run in browsers today, we’re using the Traceur compiler to generate the nice ES5 that runs everywhere. We’re working with the Traceur team to build support for a few extensions like annotations and assertions. We call this set of extensions “ES6 +A”.
http://blog.angularjs.org/2014/03/angular-20.html

google/traceur-compiler を使った発表をしようと思ってます!
https://github.com/google/traceur-compiler
(まだちょっとしか触ってない&資料書いてないけど….)

traceur-compilerを使うといろいろES6の機能が使えるらしいですね。
https://github.com/google/traceur-compiler/wiki/LanguageFeatures#modules

Traceur+grunt+IntelliJ(WebStorm)で
ちょっとAngularJS1.2を使ってみようとおもいます〜。
https://github.com/aaronfrost/grunt-traceur

おまけ。ES6の機能が使える環境一覧表
http://kangax.github.io/compat-table/es6/

2014年7月6日日曜日

2014/07/05 AngularJS福岡勉強会(第1回) ご参加ありがとうございました。

2014/07/05 AngularJS福岡勉強会(第1回)

多数のご参加ありがとうございました!

そこで出た質問やお勧めのライブラリをここにまとめたいと思います。



質問


Q1.angular.moduleの名前がかぶったらどうなるの?

試してみました。まずは正常に動くバージョン

次に誤って同じ名前のmoduleを作成した場合

残念ながら、後から作成したmoduleで同じ名前のモジュールは上書きされてしまうみたいです...
おそろしい...重複した場合に検知できませんので気をつけないといけないですね...


Q2.controller( "XxxCtrl", function($scope)って書く時の引数の$scopeは別の名前でもいいんですか?

ダメです..$scopeという文字列で判断しますので違う名前にすると別物の扱いです。

angular.module('app', []).
controller( 'XxxCtrl', [ '$scope', function($scope) {
}]);

変更する際はこんな感じで配列でDIする機能の名前を渡しましょう。

詳しくは下記資料をご参考ください。
“AngularJSのDIの仕組み、minify対策は覚えておこう!”
http://qiita.com/kawaz/items/363f430d21ec729f1b7d


Q3.規約とか作ってますか?

うちはここの規約を参考に会社用につくっています

angularjs-style-guide

https://github.com/mgechev/angularjs-style-guide/blob/master/README-ja-jp.md




お勧めのライブラリ


controller をクラスっぽく書けるライブラリ: http://davej.github.io/angular-classy/ が結構便利です。

@odiak_i さん!情報ありがとうございます!



ありがとうございました


@osacaz4さん!
素敵な場所の提供ありがとうございます!
またお願いしますm(_ _)m

@hisashi_yanoさん、@tsubakimoto_sさん!
発表ありがとうございました。

@tsubakimoto_sさんの資料はこちらにあります。
初心者 × AngularJS × TypeScript
http://www.slideshare.net/YutaMatsumura/angular-jstypescript-slideshare-36665793

@SUGA_HEYさん!まとめて頂きありがとうございます!
AngulaJSの勉強会(2014/07/05 福岡)
http://qiita.com/sugawa0718/items/b387f52c5b4f29b8c050



twitterのハッシュタグ


#ng_fukuoka



2014年7月5日土曜日

2014/07/05 その4 AngularJS福岡勉強会(第1回) そのたネタ

自動でカンマ編集をつけるディレクティブの例など

2014/07/05 その3 AngularJS福岡勉強会(第1回)



11. ngShow Directive


標準機能のngShowディレクティブは 紐づいたデータが true の時に中の要素を表示します。




12. ngRepeat Directive


標準機能のngRepeatディレクティブは 紐づいたデータ配列分繰り返し実行されます。
ngRepeat (日本語) ngRepeat




13. ngOption Directive


SELECTの要素はngOptionで指定出来ます。




14. 自作 Directive


Directiveは自作出来ます。
自作のタグを作る事もできます。




15. クリックイベントハンドラ Directive


clickイベントはHTMLに書く形になります。




twitterのハッシュタグ

質問やもっと良いやり方などがありましたら、↓につぶやいてください〜

#ng_fukuoka








補足
ngRepeatのModelをクラスっぽく書いた例 ngAnimation

2014年7月3日木曜日

2014/07/05 その2 AngularJS福岡勉強会(第1回)



06. Controller兄弟のscopeは別物


兄弟にはきちんと別々の部屋(scope)をもっています。
お隣のscopeを覗く事が出来ません。




07. 親子関係のControllerは、子は親のscopeを使えます


scopeはDOMツリーにあわせて階層で作成されます。
自分のscopeに設定されたいない値は自分の親にあたるscopeに設定されていないか探しに行きます。




08. ngModelで値を入力


scopeのデータに値を入力する場合はngModelを使います。
Data Binding




09. Angularのサービスを作成


angular.module("hogehoge").factoryメソッドでデータと振る舞いを持つオブジェクトを登録します。
AngularのサービスはControllerからいつも同じオブジェクトが呼び出されます。
AngularJSのサービスについて Services




10. AngularのサービスでControllerのデータ共有


さきほどAngularのサービスはControllerからいつも同じオブジェクトが呼び出されるとありました。
ということはControllerが同じサービスを呼び出すとデータを共有できるということになります。


2014年7月2日水曜日

2014/07/05 その1 AngularJS福岡勉強会(第1回)



01. AngularJSの起動


ng-app属性を見つけるとAngularは動き出します。jQueryと起動が違いますね。




02. Controllerと$scope


HTMLのDOMとAngularのControllerが$scope経由で接続されます。
$scopeは接着剤みたいなイメージです。
Controllerは$scopeにデータや振る舞いを紐づけます。

Scope as Data-Model
Scope is the glue between application controller and the view.




03. Moduleという箱


angular.module("hoge",[])のように第2引数がある時は新規作成で
angular.module("hoge")のように第2引数がない場合は、利用(参照)します
ng-appでAngularJSが起動する時にどのModuleを使うか選択が出来ます。




04. ngBindを使用して$scopeに設定された値を画面に表示する


ng-bindと{{}}波カッコは、ほぼ同じ動きになります。
Controllerは$scopeに値を設定します。それが自動でDOMに描画されます。
Controllerはあくまで$scopeの事までしか知りませんし、
DOMも$scopeの事しか知りません。
Controllerの中にDOMの記述が無い事がポイントです。




05. $scopeは Objectでもデータを紐付けれます

Objectで紐づけたデータは、DOM上でhoge.fugaという形式で使う事ができます。




twitterのハッシュタグ

質問やもっと良いやり方などがありましたら、↓につぶやいてください〜

#ng_fukuoka








補足
波括弧(なみかっこ)は、ブレース・ブレイス (brace) および カーリーブラケット (curly bracket) ・カール (curl) とも言う。