Sirius
is a modern coffeescript MVC/MVVM framework for client-side.
- Template free — you may use any template engine or don't use any at all
- MVC style
- MVVM binding (view to view, model to view, view to model, etc)
- Built-in Collections
- Built-in Validators
- Simple for customization
- Works with jQuery, Prototype.js, and Vanillajs
- Support html5 routing
- Time events in routing
- Log all actions in an application read about
- And many others
npm install sirius
or download manually sirius.min.js and jquery_adapter.min.js or prototype_js_adapter.min.js from repo.
or only core part: sirius-core.min.js
grep -r -i -e 'fixme' -e 'todo' src
- more tests
MyController =
action: (param) ->
# ...
run: () ->
# ...
after_run: () ->
# run after `run` method
guard_event: (event) ->
if condition
true
else
false
event_action: (event, id) ->
# ...
Sometimes you need to share some actions between all controllers - some services/ajax requests, or some like this, that's simple:
CommonMethods =
ajax: (args...) ->
on_more_action: (args...) ->
# then
Sirius.Application.run
route: # you routes
adapter: # some adapter
controller_wrapper : CommonActions
# and now in you controller:
Controller =
action: (url) =
# possible use
# any method from CommonActions, like
logger.info("start ajax request")
response = ajax(url)
logger.info("stop ajax request, response #{response} given")
routes =
"application:run" : controller: MyController, action: "action"
"/plain" : controller: MyController, action: "plain"
"#/:title" : controller: MyController, action: "run"
"every 10s" : controller: MyController, action: "refresh"
"click #my-element" : controller: MyController, action: "event_action", guard: "guard_event", data: "id"
more about routing and controllers
class Person extends Sirius.BaseModel
@attrs: ["id", "name", "age"]
@comp("id_and_name", "id", "name") # <- computed field
@guid_for: "id"
@validate:
id: only_integers: true
Sirius.Application.run({route: routes, adapter: new YourAdapter()})
more about application and settings
class Person extends Sirius.BaseModel
@attrs: ["id", "name", "age"]
@guid_for: "id"
@form_name: "my-person-form"
@validate :
name:
presence: true
format: with: /^[A-Z].+/
length: min: 3, max: 7
exclusion: ["title"]
class MyValidator extends Sirius.Validator
validate: (value, attrs) ->
if value.length == 3
@msg = "Error, value should have length 3"
false
else
true
# register validator
Sirius.BaseModel.register_validator("my_validator", MyValidator)
# and use
class MyModel extends Sirius.BaseModel
@attrs: ["title"]
@validate:
title:
my_validator: some_attribute: true
In Sirius, views are an element on the page. You might bind view and other views, or model.
view = new Sirius.View("#id", (x) -> "#{x}!!!")
view.render("new content").swap()
# then in html <element id='id'>new content!!!</element>
swap
- this strategy, how to work with content. Support: swap
, append
, prepend
stretegies.
Define own strategy:
Sirius.View.register_strategy('html',
transform: (oldvalue, newvalue) -> "<b>#{newvalue}<b>"
render: (adapter, element, result, attribute) ->
if attribute == 'text'
$(element).html(result)
else
throw new Error("Html strategy work only for text, not for #{attribute}")
)
# use it
view = new Sirius.View("#element")
view.render("some text").html()
# then in html
<span id='element'><b>some text</b></span>
Also you want to swap content for any attribute:
view.render("active").swap('class')
persons = new Sirius.Collection(Person, {index: ['name']})
joe = new Person({"name": "Joe", "age" : 25})
persons.add(joe)
person.find("name", "Joe").to_json() # => {"id" : "g-u-i-d", "name" : "Joe", "age" : 25}
Supported binding: 1. view to model 2. view to view 3. model to view 4. or model|view to function.
# view
<div id="my-input">
<input type="text" />
</div>
# model
class MyModel extends Sirius.BaseModel
@attrs: ["id", "name"]
model = new MyModel()
view = new Sirius.View("#my-input")
# and now materialize!
Materializer.build(view, model) # from view to model
.field((v) -> v.zoom("input"))
.to((m) -> m.name) # or just .to('name')
.transform((result) -> "#{result.text}!")
.run()
# view1
<div id="element">
<p></p>
</div>
# view2
<div id="my-input">
<input type="text" />
</div>
view1 = new Sirius.View("#element")
view2 = new Sirius.View("#my-input")
Sirius.Materializer.build(view2, view1) # from view2 to view1
.field("input") # or field((view) -> view.zoom("input"))
.to('p') # the same ^
.handle((view, result) -> # you can define own handler
view.render(result.text).swap() # default
)
.run()
# model
class MyModel extends Sirius.BaseModel
@attrs: ["name"]
@validate:
name:
length: min: 3, max: 10
# view
<div id="view">
<div class="model-name"></div>
<span class="model-errors"></span>
</div>
model = new MyModel()
view = new Sirius.View("#view")
Sirius.Materializer.build(model, view)
.field((m) -> m.name)
.to('.model-name')
.field((m) -> m.errors.name.length) # path to validator
.to('.model-errors')
.run()
use as:
MainController =
logger: Sirius.Application.get_logger("MainController")
action: () ->
@logger.info("test")
-
install deps for todo app with
rake todo:install
-
compile:
rake todo:compile
-
run:
rake todo:run
-
open browser:
http://localhost:4567/
Use rake
for run task. Before work run rake install
for installing dependencies.
rake install
- install all dependencies
rake doc
- generate project documentation
rake build
- compile coffeescript into javascript file
rake test
- complile fixtures for tests, and run server
rake minify
- use yuicompressor for minify files
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request