Merge branch 'next' of github.com:lhorie/mithril.js into next
Conflicts: docs/mithril.request.md mithril.js
This commit is contained in:
commit
0f2b7dad4d
271 changed files with 44112 additions and 182 deletions
|
|
@ -1,7 +1,44 @@
|
|||
## Change Log
|
||||
|
||||
[v0.1.26](/mithril/archive/v0.1.26) - maintenance
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- make sure input[type] is CSS-targetable [#364](https://github.com/lhorie/mithril.js/issues/364)
|
||||
- throw error if m.route.param is called before initializing routes [#361](https://github.com/lhorie/mithril.js/issues/361)
|
||||
|
||||
---
|
||||
|
||||
[v0.1.25](/mithril/archive/v0.1.25) - maintenance
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- fixed input cursor jumping regression
|
||||
- fixed interop bug when QUnit and AMD are used at the same time [#355](https://github.com/lhorie/mithril.js/issues/355)
|
||||
- fixed route arg duplication in edge case [#352](https://github.com/lhorie/mithril.js/issues/352)
|
||||
- prevented meaningless error in Chrome edge case [#358](https://github.com/lhorie/mithril.js/issues/358)
|
||||
|
||||
---
|
||||
|
||||
[v0.1.24](/mithril/archive/v0.1.24) - maintenance
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- Prevent rogue `is` attribute from being created in Chrome
|
||||
- Fix `data` regression in `m.request`
|
||||
|
||||
---
|
||||
|
||||
[v0.1.23](/mithril/archive/v0.1.23) - maintenance
|
||||
|
||||
### News:
|
||||
|
||||
- There's now support for extended custom elements (e.g. `m("button[is=my-button]")`)
|
||||
- `m.request` now supports a `initialValue` option to help prevent type errors in views when using the `background` option
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- docs now have anchor links for easier navigation
|
||||
- fixed a bunch of IE8 issues [#298](https://github.com/lhorie/mithril.js/issues/298)
|
||||
- fixed handling of `method` option in JSONP mode [#292](https://github.com/lhorie/mithril.js/issues/292)
|
||||
- fixed source map files
|
||||
|
|
@ -9,6 +46,7 @@
|
|||
- fixed template compiler edge case [#286](https://github.com/lhorie/mithril.js/issues/286)
|
||||
- fixed pathname bug in m.route [#290](https://github.com/lhorie/mithril.js/issues/290)
|
||||
- fixed pathname querystring bug in routed links [#304](https://github.com/lhorie/mithril.js/issues/304)
|
||||
- fixed handling of value in inputs when model value is not in sync with input value [#336](https://github.com/lhorie/mithril.js/issues/336)
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
## How is Mithril Different from Other Frameworks
|
||||
|
||||
There are a lot of different Javascript MVC frameworks and evaluating their merits and shortcomings can be a daunting task.
|
||||
There are a lot of different Javascript frameworks and evaluating their merits and shortcomings can be a daunting task.
|
||||
|
||||
This page aims to provide a comparison between Mithril and some of the most widely used frameworks, as well as some of the younger, but relevant ones.
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ Ember is also more opinionated in terms of how application architecture should l
|
|||
|
||||
### React
|
||||
|
||||
React is a templating engine developed by Facebook. It's relevant for comparison because it uses the same architecture as Mithril's templating engine: i.e. it acknowledges that DOM operations are the bottleneck of templating systems, and implements a virtual DOM tree which keeps track of changes and only applies diffs to the real DOM where needed.
|
||||
React is a component engine developed by Facebook. It's relevant for comparison because it uses the same architecture as Mithril's templating engine: i.e. it acknowledges that DOM operations are the bottleneck of templating systems, and implements a virtual DOM tree which keeps track of changes and only applies diffs to the real DOM where needed.
|
||||
|
||||
The most visible difference between React and Mithril is that React's *JSX* syntax does not run natively in the browser, whereas Mithril's uncompiled templates do. Both can be compiled, but React's compiled code still has function calls for each virtual DOM element; Mithril templates compile into static Javascript data structures.
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ myApp.users.index.view = function() {
|
|||
There's no rule for how you should organize code, and given that namespacing is often achieved with simple javascript, you can use simple javascript patterns to alias a long namespace and reduce the amount of typing:
|
||||
|
||||
```javascript
|
||||
new function() {
|
||||
!function() {
|
||||
var module = myApp.users.index = {}
|
||||
|
||||
module.vm = {/*...*/}
|
||||
|
|
@ -148,7 +148,7 @@ new function() {
|
|||
|
||||
return vm.something
|
||||
}
|
||||
}
|
||||
}()
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ In the case of our todo application, the view-model needs a few things: it needs
|
|||
|
||||
```javascript
|
||||
//define the view-model
|
||||
todo.vm = new function() {
|
||||
todo.vm = (function() {
|
||||
var vm = {}
|
||||
vm.init = function() {
|
||||
//a running list of todos
|
||||
|
|
@ -148,7 +148,7 @@ todo.vm = new function() {
|
|||
};
|
||||
}
|
||||
return vm
|
||||
}
|
||||
}())
|
||||
```
|
||||
|
||||
The code above defines a view-model object called `vm`. It is simply a javascript object that has a `init` function. This function initializes the `vm` object with three members: `list`, which is simply an array, `description`, which is an `m.prop` getter-setter function with an empty string as the initial value, and `add`, which is a method that adds a new Todo instance to `list` if an input description getter-setter is not an empty string.
|
||||
|
|
@ -334,10 +334,10 @@ vm.add = function() {
|
|||
vm.list.push(new todo.Todo({description: vm.description()}));
|
||||
vm.description("");
|
||||
}
|
||||
}.bind(this);
|
||||
};
|
||||
```
|
||||
|
||||
The difference with the modified version is that `add` no longer takes an argument, and we call `.bind(this)` at the end to lock the scoping of `this` inside of the `add` method.
|
||||
The difference with the modified version is that `add` no longer takes an argument.
|
||||
|
||||
With this, we can make the `onclick` binding on the template *much* simpler:
|
||||
|
||||
|
|
@ -447,7 +447,7 @@ todo.TodoList = Array;
|
|||
//stores a description for new todos before they are created
|
||||
//and takes care of the logic surrounding when adding is permitted
|
||||
//and clearing the input after adding a todo to the list
|
||||
todo.vm = new function() {
|
||||
todo.vm = (function() {
|
||||
var vm = {}
|
||||
vm.init = function() {
|
||||
//a running list of todos
|
||||
|
|
@ -465,7 +465,7 @@ todo.vm = new function() {
|
|||
};
|
||||
}
|
||||
return vm
|
||||
}
|
||||
}())
|
||||
|
||||
//the controller defines what part of the model is relevant for the current page
|
||||
//in our case, there's only one view-model that handles everything
|
||||
|
|
|
|||
1
docs/layout/ghbtns.html
Normal file
1
docs/layout/ghbtns.html
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -30,7 +30,7 @@
|
|||
<a class="button" href="mithril.min.zip">Download v$version</a>
|
||||
</p>
|
||||
|
||||
<iframe src="http://ghbtns.com/github-btn.html?user=lhorie&repo=mithril.js&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"></iframe>
|
||||
<iframe src="ghbtns.html?user=lhorie&repo=mithril.js&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"></iframe>
|
||||
|
||||
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://lhorie.github.io/mithril" data-via="LeoHorie">Tweet</a>
|
||||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
|
||||
|
|
@ -77,19 +77,22 @@
|
|||
<h2>Sample code</h2>
|
||||
|
||||
<pre><code class="language-javascript">//namespace
|
||||
var app = {};
|
||||
|
||||
//model
|
||||
var PageList = function() {
|
||||
app.PageList = function() {
|
||||
return m.request({method: "GET", url: "pages.json"});
|
||||
};
|
||||
|
||||
//controller
|
||||
var app = {};
|
||||
app.controller = function() {
|
||||
this.pages = app.PageList();
|
||||
|
||||
this.rotate = function() {
|
||||
this.pages().push(this.pages().shift())
|
||||
}.bind(this)
|
||||
var pages = app.PageList();
|
||||
return {
|
||||
pages: pages,
|
||||
rotate: function() {
|
||||
pages().push(pages().shift());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//view
|
||||
|
|
@ -98,7 +101,7 @@ app.view = function(ctrl) {
|
|||
ctrl.pages().map(function(page) {
|
||||
return m("a", {href: page.url}, page.title);
|
||||
}),
|
||||
m("a", {onclick: ctrl.rotate}, "Rotate links")
|
||||
m("button", {onclick: ctrl.rotate}, "Rotate links")
|
||||
];
|
||||
};
|
||||
|
||||
|
|
@ -121,11 +124,13 @@ app.PageList = function() {
|
|||
|
||||
//controller
|
||||
app.controller = function() {
|
||||
this.pages = app.PageList();
|
||||
|
||||
this.rotate = function() {
|
||||
this.pages().push(this.pages().shift())
|
||||
}.bind(this)
|
||||
var pages = app.PageList();
|
||||
return {
|
||||
pages: pages,
|
||||
rotate: function() {
|
||||
pages().push(pages().shift());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//view
|
||||
|
|
@ -246,7 +251,7 @@ m.module(document.getElementById("example"), app);
|
|||
|
||||
<blockquote class="twitter-tweet" lang="en"><p>Mithril: The newest JavaScript MVC library 3Kb. <a href="http://twitter.com/LeoHorie">@LeoHorie</a> got it right: It's all about good guides/docs: <a href="http://lhorie.github.io/mithril/comparison.html">lhorie.github.io/mithril/comparison.html</a></p> — David Corbacho (@dcorbacho) <a href="https://twitter.com/dcorbacho/status/446926407843991552">March 21, 2014</a></blockquote>
|
||||
|
||||
<script async src="http://platform.twitter.com/widgets.js"></script>
|
||||
<script async src="https://platform.twitter.com/widgets.js"></script>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Installation: npm install -g sweet.js
|
|||
Usage: sjs --module /template-compiler.sjs --output <output-filename>.js <input-filename>.js
|
||||
*/
|
||||
|
||||
macro m {
|
||||
macro m_impl {
|
||||
case { _ ($selector, $dynAttrs ..., $children ...) } => {
|
||||
var selectorSyntax = #{$selector};
|
||||
var selector = unwrapSyntax(selectorSyntax);
|
||||
|
|
@ -47,7 +47,7 @@ macro m {
|
|||
return #{ ({tag: $tag, attrs: $attrs , children: $children ...}) };
|
||||
}
|
||||
catch (e) {
|
||||
return #{ m($tag, {}, [$dynAttrs ..., $children ...]) }
|
||||
return #{ m_impl($tag, {}, [$dynAttrs ..., $children ...]) }
|
||||
}
|
||||
}
|
||||
case { _ ($selector, $partial ...) } => {
|
||||
|
|
@ -55,17 +55,29 @@ macro m {
|
|||
try {
|
||||
var partial = unwrapSyntax(partialSyntax);
|
||||
var isTag = partial.inner && partial.inner.length > 2 && (partial.inner[0].token.value == "tag" && partial.inner[1].token.value == ":")
|
||||
return !isTag ? #{m($selector, $partial ..., [])} : #{m($selector, {}, $partial ...)};
|
||||
return !isTag ? #{m_impl($selector, $partial ..., [])} : #{m_impl($selector, {}, $partial ...)};
|
||||
}
|
||||
catch (e) {
|
||||
return #{m($selector, {}, $partial ...)}
|
||||
return #{m_impl($selector, {}, $partial ...)}
|
||||
}
|
||||
}
|
||||
case { _ ($selector) } => {
|
||||
return #{m($selector, {}, [])};
|
||||
return #{m_impl($selector, {}, [])};
|
||||
}
|
||||
}
|
||||
|
||||
let m = macro {
|
||||
case { _ ($selector, $dynAttrs ..., $children ...) } => {
|
||||
return #{m_impl($selector, $dynAttrs ..., $children ...)}
|
||||
}
|
||||
case { _ ($selector, $partial ...) } => {
|
||||
return #{m_impl($selector, $partial ...)}
|
||||
}
|
||||
case { _ ($selector) } => {
|
||||
return #{m_impl($selector, {}, [])};
|
||||
}
|
||||
case { _ } => {
|
||||
return #{Mithril};
|
||||
return #{m};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
---
|
||||
|
||||
- [How auto-redrawing-works](#how-auto-redrawing-works)
|
||||
- [How auto-redrawing works](#how-auto-redrawing-works)
|
||||
- [Integrating multiple execution threads](#integrating-multiple-execution-threads)
|
||||
- [Integrating to legacy code](#integrating-to-legacy-code)
|
||||
- [Signature](#signature)
|
||||
|
|
@ -242,4 +242,4 @@ void startComputation()
|
|||
|
||||
```clike
|
||||
void endComputation()
|
||||
```
|
||||
```
|
||||
|
|
|
|||
|
|
@ -64,17 +64,17 @@ The example below shows how to use a SubtreeDirective object to create a static
|
|||
var app = {}
|
||||
|
||||
//here's an example plugin that determines whether data has changes.
|
||||
//in this case, it simply assume data has changed the first time, and never changes after that.
|
||||
app.bindOnce = new function() {
|
||||
//in this case, it simply assumes data has changed the first time, and never changes after that.
|
||||
app.bindOnce = (function() {
|
||||
var cache = {}
|
||||
function(view) {
|
||||
return function(view) {
|
||||
if (!cache[view.toString()]) {
|
||||
cache[view.toString()] = true
|
||||
return view()
|
||||
}
|
||||
else return {subtree: "retain"}
|
||||
}
|
||||
}
|
||||
}())
|
||||
|
||||
//here's the view
|
||||
app.view = function() {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Because Mithril encourages all entity logic to be done in the model layer, it's
|
|||
|
||||
Models are also responsible for centralizing tasks such as filtering of entity lists and validation routines, so that access to these methods is available across the application.
|
||||
|
||||
DOM manipulation should be done in the view via [`m()` and `config`](mithril). Controllers may explicitly call [`m.redraw`](mithril.redraw.md), but, if possible, it's preferable to abstract this into a service which integrates with Mithril's auto-redrawing system (see [`m.startComputation` / `m.endComputation`](mithril.computation.md)).
|
||||
DOM manipulation should be done in the view via [`m()` and `config`](mithril). Controllers may explicitly call [`m.redraw`](mithril.redraw.md), but, if possible, it's preferable to abstract this into a service which integrates with Mithril's auto-redrawing system (see [`m.startComputation` / `m.endComputation`](mithril.computation.md)). You should avoid instantiating controller classes from views.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -68,39 +68,13 @@ That organization pattern needlessly ties unrelated aspects of the application t
|
|||
|
||||
---
|
||||
|
||||
## Global Namespace Hygiene
|
||||
|
||||
For developer convenience, Mithril uses the global `m` variable as a namespace, much like jQuery uses `$`.
|
||||
|
||||
If you want to ensure global namespace hygiene, you can wrap your code in "islands" like this:
|
||||
|
||||
```javascript
|
||||
new function(m) {
|
||||
|
||||
//your code goes here
|
||||
|
||||
}(Mithril);
|
||||
```
|
||||
|
||||
If you are creating components to be used by 3rd parties, it's recommended that you always use this idiom.
|
||||
|
||||
In the unlikely case that you have another global variable called `m` in your page, you should consider renaming it to make it more descriptive, or use the idiom below to keep it intact.
|
||||
|
||||
```markup
|
||||
<script>_temp = m</script>
|
||||
<script src="mithril.js"></script>
|
||||
<script>m = _temp</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage of m.redraw
|
||||
|
||||
`m.redraw` is a method that allows you to render a template outside the scope of Mithril's auto-redrawing system.
|
||||
|
||||
Calling this method while using `m.module` or `m.route` should only be done if you have recurring asynchronous view updates (i.e. something that uses setInterval).
|
||||
|
||||
If you're integrating other non-recurring services (e.g. calling setTimeout), you should use [`m.startComputation` / `m.emdComputation`](mithril.computation.md) instead.
|
||||
If you're integrating other non-recurring services (e.g. calling setTimeout), you should use [`m.startComputation` / `m.endComputation`](mithril.computation.md) instead.
|
||||
|
||||
This is the most potentially expensive method in Mithril and should not be used at a rate faster than the rate at which the native `requestAnimationFrame` method fires (i.e. the rate at which browsers are comfortable calling recurring rendering-intensive code). Typically, this rate is around 60 calls per second.
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ Mithril relies on some Ecmascript 5 features, namely: `Array::indexOf`, `Array::
|
|||
The easiest way to polyfill these features is to include this script:
|
||||
|
||||
```javascript
|
||||
<script src="https://polyfill.io/"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.0.3/es5-shim.min.js"></script>
|
||||
```
|
||||
|
||||
This will provide all the polyfills required for the browser. You can alternatively include only specific polyfills:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue