LoginSignup
38
38

More than 5 years have passed since last update.

Atomのフレームワーク、SpacePen

Last updated at Posted at 2014-05-26

SpacePenって

Write markup on the final frontier

SpacePen is a powerful but minimalistic client-side view framework for CoffeeScript. It combines the "view" and "controller" into a single jQuery object, whose markup is expressed with an embedded DSL similar to Markaby for Ruby.

atom/space-pen

SpacePen(無重力ペン)はView層とControle層を合わせたCoffeeScriptのjQueryオブジェクト扱うフレームワークだとか何とか…

何に使うの?

AtomのPackageとかのUIはこれで書く。
もちろんそのままブラウザ上に出力させるHTMLにも使えちゃう。


とりあえずAtomパッケージ作るにあたって必要になったので学習がてらにReadmeを元に使い方を書いてみる。

どんな感じに書くの

基本的な奴

ViewClassの@contentに例えば次のように書く。

class Spacecraft extends View
  @content: ->
    @div =>
      @h1 "Spacecraft"
      @ol =>
        @li "Apollo"
        @li "Soyuz"
        @li "Space Shuttle"

見ての通りHTMLのタグ名がそのまま@contentクラス内のメソッドになっている。

また、jQueryで次のように表現するようなものは

view = new Spacecraft
view.find('ol').append('<li>Star Destroyer</li>')

view.on 'click', 'li', ->
  alert "They clicked on #{$(this).text()}"

SpacePenでは

class Spacecraft extends View
  @content: -> ...

  addSpacecraft: (name) ->
    @find('ol').append "<li>#{name}</li>"


view = new Spacecraft
view.addSpacecraft "Enterprise"

って出来るらしい。

更にコンストラクタで引数渡したりとかも、ほら。

class Spacecraft extends View
  @content: (params) ->
    @div =>
      @h1 params.title
      @ol =>
        @li name for name in params.spacecraft

view = new Spacecraft(title: "Space Weapons", spacecraft: ["TIE Fighter", "Death Star", "Warbird"])

jQueryのprototypeをオーバーライドしたり

class Spacecraft extends View
  @content: -> ...

  hide: ->
    console.log "Hiding Spacecraft List"
    super()

初期化メソッドも。

class Spacecraft extends View
  @content: -> ...

  initialize: (params) ->
    @title = params.title

アウトレット/イベント

outletイベントを使えばクラス内の他のメソッドからその要素のjQueryオブジェクトが扱える。

class Spacecraft extends View
  @content: ->
    @div =>
      @h1 "Spacecraft"
      @ol outlet: "list", =>
        @li "Apollo"
        @li "Soyuz"
        @li "Space Shuttle"

  addSpacecraft: (name) ->
    @list.append("<li>#{name}</li>")

clickイベントをつけておけばクリックしたらメソッド呼び出せる…ボタンとか。

class Spacecraft extends View
  @content: ->
    @div =>
      @h1 "Spacecraft"
      @ol =>
        @li click: 'launchSpacecraft', "Saturn V"

  launchSpacecraft: (event, element) ->
    console.log "Preparing #{element.name} for launch!"

Markup DSLの詳細

  • タグメソッド (@div,@h1みたいなの)
    ここまで見てきたようにメソッド名がそのままhtml要素になります。
    タグメソッドには次の3種類の引数がわたせます。

    • 文字列 文字列をHTMLエスケープしてタグ内のテキストにします。(ex:@div "foo"<div>foo</div>)
    • ハッシュ キーと値のペアはHTMLの属性になります。(ex:@img src: "url"<img src="url">)
    • function (=>) 関数をそのまま引数として渡すと子要素として扱われます。(ex:@ol => @li "me"<ol><li>me</li></ol>)
    • テキストメソッド
    • @text(string) 引数のテキストをHTMLエスケープして文字列として出力します。
    • @raw(string) テキストをエスケープせずにHTMLとして出力します。事前に形成されたHTMLを使うにはこれを利用します。

Subviews

@subviewを使えばコードをモジュール化出来ます。
@subview(name,view)メソッドは別のviewを呼び出し、そこに出力します。

  class Spacecraft extends View
  @content: (params) ->
    @div =>
      @subview 'launchController', new LaunchController(countdown: params.countdown)
      @h1 "Spacecraft"
      ...

Freeform Markup Generation

SpacePenマークアップにViewクラスを使用する必要はありません。
view.renderをタグメソッドを呼び出す関数(=>ではなく->)と呼び出します。(?)
これはアドホック使用用のドキュメントフラグメントを返します。
このメソッドは便宜上グローバル変数$$に割り当てられています。

view.list.append $$ ->
  @li =>
    @text "Starship"
    @em "Enterprise"

jQuery拡張

$.fn.view

任意のDOMオブジェクトのViewオブジェクトを取得出来ます。

view = new Spacecraft
$('body').append(view)

# assuming no other li elements on the DOM, for example purposes,
# the following expression should be true
$('li').view() == view

After Attach Hooks

The initialize method is always called when the view is still a detached DOM fragment, before it is appended to the DOM. This is usually okay, but occasionally you'll have some initialization logic that depends on the view actually being on the DOM. For example, you may depend on applying a CSS rule before measuring an element's height.

SpacePen extends jQuery manipulation methods like append, replaceWith, etc. to call afterAttach hooks on your view objects when they are appended to other elements. The hook will be called with a boolean value indicating whether the view is attached to the main DOM or just to another DOM fragment. If afterAttach is called with true, you can assume your object is attached to the page.

class Spacecraft extends View
  @content: -> ...

  afterAttach: (onDom) ->
    if onDom
      console.log "With CSS applied, my height is", @height()
    else
      console.log "I just attached to", @parent()

Before Remove Hooks

SpacePen calls the beforeRemove hook whenever a view is removed from the DOM via a jQuery method. This works if the view is removed directly with remove or indirectly when a method like empty or html is called on a parent element. This is a good place to clean up subscriptions and other view-specific state.

class Spacecraft extends View
  @content: -> ...

  initialize: ->
    $(window).on 'resize.spacecraft', -> ...

  beforeRemove: ->
    $(window).off('.spacecraft')

HTMLで使う

exampleではこのようにしています。
(別途coffee.js,jQuery.js,spec-penのコアファイルが読み込まれているので試す場合は配置に注意してください。--リポジトリをそのままclone or 展開 したのを鯖に上げればおk。)

<!DOCTYPE HTML>
<html>
<head>
  <title>Space Pen Example</title>

  <!-- coffeescript -->
  <script type="text/javascript" src="../vendor/coffee-script.js"></script>

  <!-- dependencies -->
  <script type="text/javascript" src="../vendor/jquery.js"></script>

  <!-- implementation -->
  <script type="text/coffeescript" src="../src/space-pen.coffee"></script>

  <!-- specs -->
  <script type="text/coffeescript" src="../examples/example.coffee"></script>
</head>

<body></body>

</html>
class HelloView extends View
  @content: (params) ->
    @div =>
      @div params.greeting
      @label for: 'name', "What is your name? "
      @div =>
        @input name: 'name', outlet: 'name'
        @button click: 'sayHello', "That's My Name"
      @div outlet: "personalGreeting"

  initialize: (params) ->
    @greeting = params.greeting

  sayHello: ->
    @personalGreeting.html("#{@greeting}, #{@name.val()}")

$('body').append(new HelloView(greeting: "Hi there"))

説明するまでも無いだろうので解説は省略。

Atomのスタイルガイド

メニューのPackage > Styleguide > showとかから見れます。
SpacePenとHTMLのそれぞれのマークアップの仕方が見れますね。


さいごに

SpacePenはAtomのパッケージ作るには必須とも言えますね。めんどくさいわけでもないので書けるように…


この記事はAtomから書いてAtomから投稿しています。これについては近いうちに公開するつもりなのでお楽しみに!(?)
Atomは既にQiita投稿できるMarkdownのメモ帳化しています! 結局公開できないままでした......他の方が似たようなの公開されてましたね。

Atom曰くSpacePenの時代は終わった!これからはWebComponentsだっ!だそうです。

嘘です。そんなことかいてないです(?) そこまでは言ってないけど新しいspace-penが出来る......?

2か月前で止まってるIssueだけれども気になったので貼っておきました。
以上。

38
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
38