From 9ea782f759d9e5cff40a2b1b5ce3bc7f55fce8a7 Mon Sep 17 00:00:00 2001 From: David Niergarth Date: Mon, 26 May 2014 23:51:16 -0500 Subject: [PATCH 1/2] Copy edit docs --- docs/auto-redrawing.md | 8 +++--- docs/benchmarks.md | 4 +-- docs/comparison.md | 22 ++++++++--------- docs/compiling-templates.md | 2 +- docs/components.md | 4 +-- docs/designing-a-model-layer.md | 8 +++--- docs/getting-started.md | 44 +++++++++++++++++---------------- docs/how-to-read-signatures.md | 10 ++++---- docs/installation.md | 10 ++++---- docs/integration.md | 2 +- docs/mithril.deferred.md | 2 +- docs/mithril.md | 6 ++--- docs/mithril.module.md | 4 +-- docs/mithril.request.md | 6 ++--- docs/mithril.route.md | 6 ++--- docs/mithril.trust.md | 6 ++--- docs/practices.md | 12 ++++----- docs/routing.md | 22 ++++++++--------- docs/web-services.md | 20 +++++++-------- 19 files changed, 100 insertions(+), 98 deletions(-) diff --git a/docs/auto-redrawing.md b/docs/auto-redrawing.md index fac7299f..488a8cbf 100644 --- a/docs/auto-redrawing.md +++ b/docs/auto-redrawing.md @@ -41,11 +41,11 @@ You should not use these methods if your code is intended to run repeatedly (e.g When [integrating with third party libraries](integration.md), you might find that you need to call asynchronous methods from outside of Mithril's API. -In order to integrate non-trivial asynchronous code to Mithril's auto-redrawing system, you need to ensure all execution threads call `m.startComputation` / `m.endComputation`. +In order to integrate non-trivial asynchronous code with Mithril's auto-redrawing system, you need to ensure all execution threads call `m.startComputation` / `m.endComputation`. An execution thread is basically any amount of code that runs before other asynchronous threads start to run. -Integrating multiple execution threads can be done in a two different ways: in a layered fashion or in comprehensive fashion +Integrating multiple execution threads can be done in two different ways: in a layered fashion or in comprehensive fashion. #### Layered integration @@ -86,7 +86,7 @@ var doBoth = function(callback) { #### Comprehensive integration -Comprehensive integration is recommended if integrating a monolithic series of asynchronous operations. In contrast to layered integration, it minimizes the number of `m.startComputation` / `m.endComputation` to avoid clutter. +Comprehensive integration is recommended if integrating a monolithic series of asynchronous operations. In contrast to layered integration, it minimizes the number of `m.startComputation` / `m.endComputation` calls to avoid clutter. The example below shows a convoluted series of AJAX requests implemented with a third party library. @@ -106,4 +106,4 @@ var doSomething = function(callback) { }); }); }; -``` \ No newline at end of file +``` diff --git a/docs/benchmarks.md b/docs/benchmarks.md index 73952b41..4a6b4d0c 100644 --- a/docs/benchmarks.md +++ b/docs/benchmarks.md @@ -1,12 +1,12 @@ ## Benchmarks -These benchmarks were designed to measure Javascript running time for Mithril in comparison with other popular Javascript MVC frameworks. Javascript running time is significant because the gzipped size of a framework can be misleading in terms of how much code actually runs on page loads. In my experience, page loads happen far more commonly than one would expect in single page applications: power users open multiple tabs, and mobile users are open and close the browser very frequently. And as far as templating engines go, the initial page load represents the worst case for the rendering algorithm since there are very little room for performance optimization tricks. It's arguably also [one of the most important metric when it comes to performance](http://blog.kissmetrics.com/loading-time/). +These benchmarks were designed to measure Javascript running time for Mithril in comparison with other popular Javascript MVC frameworks. Javascript running time is significant because the gzipped size of a framework can be misleading in terms of how much code actually runs on page loads. In my experience, page loads happen far more commonly than one would expect in single page applications: power users open multiple tabs, and mobile users open and close the browser very frequently. And as far as templating engines go, the initial page load represents the worst case for the rendering algorithm since there is very little room for performance optimization tricks. It's arguably also [one of the most important metrics when it comes to performance](http://blog.kissmetrics.com/loading-time/). The numbers shown here are best-run results for all frameworks, except for Mithril's case, for which I'm taking the worst-run result. The numbers aren't statistically rigorous (e.g. I didn't bother to calculate standard deviation), but they should be enough to give a rough idea of what is faster than what. Generally speaking, these tests are making a deliberate effort to be **biased in favor of other frameworks:** for example, I don't load "optional-but-usually-used-in-real-life" things like the router module for Angular, or Marionette in Backbone's case, and I load the entirety of Mithril. In addition, this test deliberately avoids triggering `requestAnimationFrame`-based performance optimizations for Mithril, since this optimization does not exist in many frameworks and [*severely* skews numbers in Mithril's favor](http://jsperf.com/angular-vs-knockout-vs-ember/308) in CPU-intensive situations like parallax sites. I'm also NOT using the [Mithril template compiler](compiling-templates.md), which would also skew the benchmark in Mithril's favor. -To run the execution time tests below, click on their respective links, run the profiler from your desired browser's developer tools and measure the running time of a page refresh (Lower is better). +To run the execution time tests below, click on their respective links, run the profiler from your desired browser's developer tools and measure the running time of a page refresh (lower is better).
diff --git a/docs/comparison.md b/docs/comparison.md index 4366842f..09b020bc 100644 --- a/docs/comparison.md +++ b/docs/comparison.md @@ -10,7 +10,7 @@ One of the most obvious differences between Mithril and most frameworks is in fi Note that while a small gzipped size can look appealing, that number is often used to "hide the weight" of the uncompressed code: remember that the decompressed Javascript still needs to be parsed and evaluated on every page load, and this cost (which can be in the dozens of milliseconds range for some frameworks in some browsers) cannot be cached. -This cost might be less of a concern in single page apps, but not necessarily if the app is typically opened simultaneously in multiple tabs, or in less powerful devices. +This cost might be less of a concern in single page apps, but not necessarily if the app is typically opened simultaneously in multiple tabs, or run on less powerful devices. The performance tests in the homepage show execution times for parsing and evaluation of Mithril's code, compared to some popular frameworks. As you can see, it paints a much less flattering picture for some frameworks than when we look at gzipped size alone. @@ -20,9 +20,9 @@ Another point of comparison is documentation. Most of the popular frameworks hav This is a problem particularly for frameworks that had breaking changes in the past: It's common to find answers in StackOverflow that are out-of-date and no longer work with the latest version of said frameworks. -Mithril has more documentation in this site than the amount of code in the framework, and none of the documentation is auto-generated. +Mithril has more documentation in its Github repo than source code, and none of the documentation is auto-generated. -All API points are explained in prose, and have code examples. Because the entire documentation is hand-crafted, you get the benefit of actually having explanations for things that documentation generator tools don't support well (for example, interfaces and callback parameter documentation). +All API points are explained in prose, and have code examples. Because the entire documentation is hand-crafted, you get the benefit of actually having explanations for things that documentation-generator tools don't support well (for example, interfaces and callback parameter documentation). In addition, this guide section covers topics related to how to fit all the pieces together. @@ -72,11 +72,11 @@ Backbone was originally designed as a way to structure jQuery-based applications As with jQuery, Mithril differs from Backbone by enforcing view code to be written in a declarative style. -Another marking difference is that Backbone is workflow agnostic, that is, there's no one idiomatic way to organize applications. This is good for framework adoption, but not necessarily ideal for team scalability and codebase discoverability. +Another marking difference is that Backbone is workflow agnostic, providing no idiomatic way to organize applications. This is good for framework adoption, but not necessarily ideal for team scalability and codebase discoverability. -In contrast, Mithril encourages that applications be developed using the patterns found throughout this guide. This discourages "bastardized" MVC pattern variations and architecturing style fragmentation. +In contrast, Mithril encourages you to develop applications using the patterns found throughout this guide, and discourages the use of "bastardized" MVC pattern variations. -One technical aspect that is also different is that Backbone is heavily event-oriented. Mithril, on the other hand, purposely avoids the observer pattern in an attempt to abolish "come-from hell", i.e. a class of debugging problems where you don't know what triggers some code because of a long chain of events triggering other events. +One technical aspect that is also different is that Backbone is heavily event-oriented. Mithril, on the other hand, purposely avoids the observer pattern in an attempt to abolish "come-from hell", a class of debugging problems where you don't know what triggers some code because of a long chain of events triggering other events. A particularly nasty instance of this problem that sometimes occurs in "real-time" applications is when event triggering chains become circular due to a conditional statement bug, causing infinite loops and browser crashes. @@ -88,17 +88,17 @@ Angular is an MVC framework maintained by Google, and it provides a declarative The main difference between Angular templates and Mithril templates is that Angular templates follow the tradition of being defined in HTML. This has the benefit of cleaner syntax for writing static text, but it comes with the disadvantage of features getting awkwardly tied to HTML syntax, as well as providing poor debugging support. -One thing you may have noticed in the homepage is that, out of the box, Angular is not as performant as other frameworks. Steep performance degradation is a notoriously common issue in non-trivial Angular applications and there are several third party libraries which attempt to get around performance problems. Speaking from experience, it's generally difficult to reason about performance in Angular. +One thing you may have noticed on the [Mithril homepage](http://lhorie.github.io/mithril/index.html#performance) is that, out of the box, Angular is not as performant as other frameworks. Steep performance degradation is a notoriously common issue in non-trivial Angular applications and there are several third party libraries which attempt to get around performance problems. Speaking from experience, it's generally difficult to reason about performance in Angular. Mithril takes some learnings from that and implements a templating redrawing system that renders less aggressively, is less complex and is easier to profile. -A noteworthy difference between Angular and Mithril is in framework complexity: Angular implements several subsystems that would seem more logical in programming language implementations (e.g. a parser, a dynamic scoping mechanism, decorators, etc). Mithril, on the other hand, tries to provide only features to support a more classic MVC paradigm. +A noteworthy difference between Angular and Mithril is in framework complexity: Angular implements several subsystems that would seem more logical in programming language implementations (e.g. a parser, a dynamic scoping mechanism, decorators, etc). Mithril, on the other hand, tries to provide only features that support a more classic MVC paradigm. ### Ember Ember is a highly comprehensive MVC framework, providing a large API that covers not only traditional MVC patterns, but also a vast range of helper utilities as well. -The biggest difference between Ember and Mithril is summarized in the Architecture section above: Ember's comprehensiveness come at a cost of a steep learning curve, and a high degree of vendor lock-in. +The biggest difference between Ember and Mithril is summarized in the Architecture section above: Ember's comprehensiveness comes at the cost of a steep learning curve and a high degree of vendor lock-in. Ember is also more opinionated in terms of how application architecture should look, and as a result, tends to be less transparent in terms of what is actually happening under the hood. @@ -106,7 +106,7 @@ Ember is also more opinionated in terms of how application architecture should l 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. -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. +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. Another difference is that Mithril, being an MVC framework, rather than a templating engine, provides an auto-redrawing system that is aware of network asynchrony and that can render views efficiently without cluttering application code with redraw calls, and without letting the developer unintentionally bleed out of the MVC pattern. @@ -124,7 +124,7 @@ As with Angular, Knockout templates are written in HTML, and therefore have the ### Vue -Vue is a relatively new and unknown templating engine, but it boasts impressive results in its performance benchmark. +Vue is a relatively new templating engine, but it boasts impressive results in its performance benchmark. It is not a full MVC framework, but it is similar to Angular templates, and uses the same terminology for its features (e.g. directives and filters). diff --git a/docs/compiling-templates.md b/docs/compiling-templates.md index cb4ca8f8..a0dde027 100644 --- a/docs/compiling-templates.md +++ b/docs/compiling-templates.md @@ -4,7 +4,7 @@ You can optionally pre-compile templates that use `m()` by running the [`templat Compiling a template transforms the nested function calls of a template into a raw virtual DOM tree (which is merely a collection of native Javascript objects that is ready to be rendered via [`m.render`](mithril.render.md)). This means that compiled templates don't need to parse the string in `m("div#foo")` and they don't incur the cost of the function call. -It's worth mentioning that Mithril has built-in mechanisms elsewhere that take care of real bottlenecks like browser repaint management and DOM updating. This optional compilation tool is merely "icing on the cake" that speeds up the javascript run-time of templates (which is already fast even without compilation - see performance test in the homepage). +It's worth mentioning that Mithril has built-in mechanisms elsewhere that take care of real bottlenecks like browser repaint management and DOM updating. This optional compilation tool is merely "icing on the cake" that speeds up the Javascript run-time of templates (which is already fast, even without compilation - see the [performance section on the homepage](http://lhorie.github.io/mithril/index.html#performance)). The macro takes regular Mithril templates like the one below: diff --git a/docs/components.md b/docs/components.md index 66bc5006..b1988fcc 100644 --- a/docs/components.md +++ b/docs/components.md @@ -67,9 +67,9 @@ projectList.view = function(ctrl) { m.module(document.body, dashboard); ``` -As you can see, components look exactly like regular modules - it's turtles all the way down! Remember that modules are simply dumb containers for `controller` and `view` classes. +As you can see, components look exactly like regular modules - it's [turtles all the way down](https://en.wikipedia.org/wiki/Turtles_all_the_way_down)! Remember that modules are simply dumb containers for `controller` and `view` classes. -This means components are decoupled both *horizontally* and *vertically*. It's possible to refactor each component as a isolated unit of logic (which itself follows the MVC pattern). And we can do so without touching the rest of the application (as long as the component API stays the same). +This means components are decoupled both *horizontally* and *vertically*. It's possible to refactor each component as an isolated unit of logic (which itself follows the MVC pattern). And we can do so without touching the rest of the application (as long as the component API stays the same). Similarly, it's possible to mix and match different classes to make mix-in anonymous components (e.g. it's straightforward to build several views - for, say, a mobile app - that use the same controller). diff --git a/docs/designing-a-model-layer.md b/docs/designing-a-model-layer.md index bfbe2e0f..f5df2630 100644 --- a/docs/designing-a-model-layer.md +++ b/docs/designing-a-model-layer.md @@ -2,14 +2,14 @@ When creating the data layer of an application, it's common for developers to settle on an ActiveRecord pattern (in a nutshell that means one class equals one database table). However, this choice is often done out of tradition rather than based on its merits. -The problem, as it specifically relates to frontend MVC, is that UIs are becoming more focused on end-users needs and the one-entity-type-per-request doesn't always support that end goal well. +The problem, as it specifically relates to frontend MVC, is that UIs are becoming more focused on end-user needs and the one-entity-type-per-request doesn't always support that end goal well. -Take for example an application's dashboard. It typically displays a summary of various things for the current logged in user, usually ranked in some not-so-trivial way (e.g. 5 most popular projects, or the projects with the latest activity, or upcoming team vacations, etc). If you think in terms of a traditional SQL database, it's pretty clear that basic CRUD is inadequate: you're going to need some joins, ranking, filtering, and possibly even more complex things like recursiveness - in other words, you're going to be needing the full extent of a modern relational database's features. +Take for example an application's dashboard. It typically displays a summary of various things for the current logged in user, usually ranked in some not-so-trivial way (e.g. five most popular projects, or the projects with the latest activity, or upcoming team vacations, etc). If you think in terms of a traditional SQL database, it's pretty clear that basic CRUD is inadequate: you're going to need some joins, ranking, filtering, and possibly even more complex things like recursiveness - in other words, you're going to be needing the full extent of a modern relational database's features. -When we think of RESTful APIs over HTTP, the years of research and work done in the database world generally feel like an afterthought: we generally represent relationships with URL hacks (e.g. `/user/1/project/10`), but this pattern tends to fall apart with more complex requirements (e.g. one would expect that a "team vacations" resource returns both a list of users hierarchically related to yourself, as well as their vacation information: start date, end date, vacation days left, etc. (remember vacation can span across weekends or statutory holidays, so that's another join or two depending on the employee's country!). +When we think of RESTful APIs over HTTP, the years of research and work done in the database world generally feel like an afterthought: we generally represent relationships with URL hacks (e.g. `/user/1/project/10`), but this pattern tends to fall apart with more complex requirements (e.g. one would expect that a "team vacations" resource returns both a list of users hierarchically related to the logged in user, as well as their vacation information: start date, end date, vacation days left, etc (remember vacation can span across weekends or statutory holidays, so that's another join or two depending on the employee's country!). Consider that this dashboard probably displays some user information. Where should this data come from? One request for the user info, and another for the user's vacations? What about the team? If the dashboard shows other team metrics, where should that basic team info come from? How many HTTP requests are we up to now? If the dashboard has self-contained customizable widgets, are we requesting duplicate information from different modules? -As you start running into situations like this, it's clear that naively requesting ActiveRecord entries from separate controllers quickly becomes unwieldy. \ No newline at end of file +As you start running into situations like this, it's clear that naively requesting ActiveRecord entries from separate controllers quickly becomes unwieldy. diff --git a/docs/getting-started.md b/docs/getting-started.md index cec324de..4a9bfc85 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -2,7 +2,7 @@ ### What is Mithril? -Mithril is a client-side Javascript MVC framework, i.e. it's a tool to make application code divided into a data layer (called "**M**odel"), a UI layer (called **V**iew), and a glue layer (called **C**ontroller) +Mithril is a client-side Javascript MVC framework, i.e. it's a tool to make application code divided into a data layer (called **M**odel), a UI layer (called **V**iew), and a glue layer (called **C**ontroller) Mithril is around 4kb gzipped thanks to its [small, focused, API](mithril.md). It provides a templating engine with a virtual DOM diff implementation for performant rendering, utilities for high-level modelling via functional composition, as well as support for routing and componentization. @@ -32,7 +32,7 @@ Yes, this is valid HTML 5! According to the specs, the ``, `` and `< ### Model -In Mithril, typically an application lives in an namespace and contains modules. Modules are merely structures that represent a viewable "page" or component. +In Mithril, an application typically lives in a namespace and contains modules. Modules are merely structures that represent a viewable "page" or component. For simplicity, our application will have only one module, and we're going to use it as the namespace for our application: @@ -108,7 +108,7 @@ list.length; //0 Our next step is to write a controller that will use our model classes. ```javascript -//the controller uses 3 model-level entities, of which one is a custom defined class: +//the controller uses three model-level entities, of which one is a custom defined class: //`Todo` is the central class in this application //`list` is merely a generic array, with standard array methods //`description` is a temporary storage box that holds a string @@ -203,7 +203,7 @@ This renders the following markup: #### Data Bindings -Let's implement a **data binding** on the text input. Data bindings connect a DOM element to a javascript variable so that updating one updates the other. +Let's implement a **data binding** on the text input. Data bindings connect a DOM element to a Javascript variable so that updating one updates the other. ```javascript m("input") @@ -224,7 +224,7 @@ m.render(todo.view(ctrl)); // input now says "Write code" Note that calling the `todo.view` method multiple times does not re-render the entire template. -Mithril internally keeps a virtual representation of the DOM in cache, scans for changes, and then only modifies the minimum required to apply the change. +Internally, Mithril keeps a virtual representation of the DOM in cache, scans for changes, and then only modifies the minimum required to apply the change. In this case, Mithril only touches the `value` attribute of the input. @@ -254,7 +254,7 @@ onchange: function(e) { } ``` -The difference, aside from the cosmetic avoidance of anonymous functions, is that the `m.withAttr` idiom also takes care of catching the correct event target and selecting the appropriate source of the data - i.e. whether it should come from a javascript property or from `DOMElement::getAttribute()` +The difference, aside from the cosmetic avoidance of anonymous functions, is that the `m.withAttr` idiom also takes care of catching the correct event target and selecting the appropriate source of the data - i.e. whether it should come from a Javascript property or from `DOMElement::getAttribute()` --- @@ -352,21 +352,21 @@ todo.view = function(ctrl) { Here are the highlights of the template above: -- The template is rendered as a child of the implicit `` element of the document -- The text input saves its value to the `ctrl.description` getter-setter we defined earlier +- The template is rendered as a child of the implicit `` element of the document. +- The text input saves its value to the `ctrl.description` getter-setter we defined earlier. - The button calls the `ctrl.add` method when clicked. The `.bind(ctrl, ctrl.description)` idiom is a [partial application](http://en.wikipedia.org/wiki/Partial_application). In this example, it's only used to maintain the scope binding for the `this` parameter in the controller method, but typically it's also used to bind parameters to the function without the need to declare a wrapper anonymous function. - The table lists all the existing to-dos, if any. -- The checkboxes save their value to the `task.done` getter setter -- The description gets crossed out via CSS if the task is marked as done -- When updates happen, the template is not wholly re-rendered - only the changes are applied +- The checkboxes save their value to the `task.done` getter setter. +- The description gets crossed out via CSS if the task is marked as done. +- When updates happen, the template is not wholly re-rendered - only the changes are applied. --- When running the classes in this application separately, you have full control and full responsibility for determining when to redraw the view. -However, Mithril does provide another utility to make this task automatic. +However, Mithril does provide another utility to make this task automatic: [the Auto-Redrawing System](http://lhorie.github.io/mithril/auto-redrawing.html). In order to enable Mithril's auto-redrawing system, we run the code as a Mithril module: @@ -374,7 +374,7 @@ In order to enable Mithril's auto-redrawing system, we run the code as a Mithril m.module(document, todo); ``` -Mithril's auto-redrawing system keeps track of controller stability, and only redraws the view once it detects that the controller has finished running all of its code, including asynchronous ajax payloads. +Mithril's auto-redrawing system keeps track of controller stability, and only redraws the view once it detects that the controller has finished running all of its code, including asynchronous AJAX payloads. Also note that this mechanism itself is not asynchronous if it doesn't need to be: Mithril does not need to wait for the next browser repaint frame to redraw - it doesn't even need to wait for the document ready event on the first redraw - it will redraw immediately upon script completion, if able to. @@ -402,7 +402,7 @@ todo.Todo = function(data) { //the TodoList class is a list of Todo's todo.TodoList = Array; -//the controller uses 3 model-level entities, of which one is a custom defined class: +//the controller uses three model-level entities, of which one is a custom defined class: //`Todo` is the central class in this application //`list` is merely a generic array, with standard array methods //`description` is a temporary storage box that holds a string @@ -457,11 +457,11 @@ Idiomatic Mithril code is meant to apply good programming conventions and be eas In the application above, notice how the Todo class can easily be moved to a different module if code re-organization is required. -Todos are self-contained and their data aren't tied to the DOM like in typical jQuery based code. The Todo class API is reusable and unit-test friendly, and in addition, it's a plain-vanilla Javascript class which requires almost no framework-specific learning curve. +Todos are self-contained and their data aren't tied to the DOM like in typical jQuery based code. The Todo class API is reusable and unit-test friendly, and in addition, it's a plain-vanilla Javascript class, and so has almost no framework-specific learning curve. [`m.prop`](mithril.prop.md) is a simple but surprisingly versatile tool: it's composable, it enables [uniform data access](http://en.wikipedia.org/wiki/Uniform_data_access) and allows a higher degree of decoupling when major refactoring is required. -When said refactoring is unavoidable, the developer can simply replace the `m.prop` call with an appropriate getter-setter implementation, instead of having to grep for API usage across the entire application. +When refactoring is unavoidable, the developer can simply replace the `m.prop` call with an appropriate getter-setter implementation, instead of having to grep for API usage across the entire application. For example, if todo descriptions needed to always be uppercased, one could simply change the `description` getter-setter: @@ -484,7 +484,7 @@ this.description = function(value) { According to Mithril's philosophy, `list` and `description` are also considered model-level entities. This is a subtle but important point: model entities don't need to be full-blown custom classes. -Native javascript classes are quite appropriate for storing primitive and structured data. Since in this case they are indeed being used to store data - even if temporarily - they are model entities! +Native Javascript classes are quite appropriate for storing primitive and structured data. Since in this case they are indeed being used to store data - even if temporarily - they are model entities! Be aware that by using the native Array class for a list, we're making an implicit statement that we are going to support all of the standard Array methods as part of our API. @@ -549,15 +549,15 @@ While superficially this may seem like an odd design, this actually has a lot of - You get the ability to automate linting, unit testing and minifying of the entire view layer - and you are even able to use Closure Compiler's Advanced Mode without needing extensive annotations. -- It provides full Turing completeness: full control over evaluation eagerness/lazyness and caching in templates. You can even build components that take other components as first-class-citizen parameters! +- It provides full Turing completeness: full control over evaluation eagerness/laziness and caching in templates. You can even build components that take other components as first-class-citizen parameters! -- Turtles all the way down: you don't need write custom data binding code in jQuery for every possible user interaction, and you don't need to support a complicated "directive" layer to be able to fit some types of components into the system. +- [Turtles all the way down](https://en.wikipedia.org/wiki/Turtles_all_the_way_down): you don't need write custom data binding code in jQuery for every possible user interaction, and you don't need to support a complicated "directive" layer to be able to fit some types of components into the system. Views in Mithril use a virtual DOM diff implementation, which sidesteps performance problems related to opaque dirty-checking and excessive browser repaint that are present in some frameworks. Another feature - the optional `m()` utility - allows writing terse templates in a declarative style using CSS shorthands, similar to popular HTML preprocessors from server-side MVC frameworks. -And because Mithril views are javascript, the developer has full freedom to abstract common patterns - from bidirectional binding helpers to full blown components - using standard javascript refactoring techniques. +And because Mithril views are Javascript, the developer has full freedom to abstract common patterns - from bidirectional binding helpers to full blown components - using standard Javascript refactoring techniques. Mithril templates are also more collision-proof than other component systems since there's no way to pollute the HTML tag namespace by defining ad-hoc tag names. @@ -583,5 +583,7 @@ Mithril provides a few more facilities that are not demonstrated in this page. T ## Misc +- [Differences from Other MVC Frameworks](comparison) +- [Benchmarks](benchmarks) - [Good Practices](practices) -- [Useful Tools](tools) \ No newline at end of file +- [Useful Tools](tools) diff --git a/docs/how-to-read-signatures.md b/docs/how-to-read-signatures.md index 2ecf89f6..785bb6c6 100644 --- a/docs/how-to-read-signatures.md +++ b/docs/how-to-read-signatures.md @@ -1,8 +1,8 @@ ## How to Read Signatures -Rather than providing concrete classes like other frameworks, Mithril provides methods that operate on plain old javascript objects (POJOs) that match given signatures. +Rather than providing concrete classes like other frameworks, Mithril provides methods that operate on plain old Javascript objects (POJOs) that match given signatures. -A signature is a description of its static type. For functions, it shows what are the parameters of the function, its return value and their expected types. For objects and arrays, it shows the expected data structure and the expected types of their members. +A signature is a description of its static type. For functions, it shows the parameters of the function, its return value and their expected types. For objects and arrays, it shows the expected data structure and the expected types of their members. Method signatures in this documentation follow a syntax similar to Java syntax, with some extra additions: @@ -133,7 +133,7 @@ typeof a == "function" // true a.label = "first" ``` -### Polimorphic Types +### Polymorphic Types When multiple (but not all) types are accepted, the pipe `|` is used to delimit the list of valid types @@ -152,7 +152,7 @@ test([1, 2, 3], "second") test([1, "test", 3], 2) ``` -Pipe syntax within Object curly brace syntax means that for a specific key name has specific type requirements. +Pipe syntax within Object curly brace syntax means that, for a specific key, name has specific type requirements. In the example below, the `value` parameter should be a key-value map. This map may contain a key called `config`, whose value should be a function. @@ -163,4 +163,4 @@ void test(Object { any | void config(DOMElement) } value) ```javascript //example of a valid function call test({ first: "first", config: function(element) { /*do stuff*/ } }) -``` \ No newline at end of file +``` diff --git a/docs/installation.md b/docs/installation.md index 83d54521..6913ff68 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -8,7 +8,7 @@ Mithril is available from a variety of sources: You can [download a zip of the latest version version here](http://lhorie.github.io/mithril/mithril.min.zip). -Links to older versions can be found in the [change log](change-log.html) +Links to older versions can be found in the [change log](change-log.html). In order to use Mithril, extract it from the zip file and point a script tag to the `.js` file: @@ -20,17 +20,17 @@ In order to use Mithril, extract it from the zip file and point a script tag to ### CDNs (Content Delivery Networks) -You can also find Mithril in [cdnjs](http://cdnjs.com/libraries/mithril/) and [jsdelivr](http://www.jsdelivr.com/#!mithril) +You can also find Mithril in [cdnjs](http://cdnjs.com/libraries/mithril/) and [jsDelivr](http://www.jsdelivr.com/#!mithril). Content delivery networks allow the library to be cached across different websites that use the same version of the framework, and help reduce latency by serving the files from a server that is physically near the user's location. -#### CdnJs +#### cdnjs ```markup ``` -#### JsDelivr +#### jsDelivr ```markup @@ -124,4 +124,4 @@ Note that Mithril uses the `next` branch as the stable branch, instead of `maste Be aware that even though Mithril has tests running in a continuous integration environment, the bleeding edge version might occasionally break. If you're interested in helping improve Mithril, you're welcome to use the bleeding edge version and report any bugs that you find. -In order to update a forked version of Mithril, [follow the instructions on this page](https://help.github.com/articles/syncing-a-fork). \ No newline at end of file +In order to update a forked version of Mithril, [follow the instructions on this page](https://help.github.com/articles/syncing-a-fork). diff --git a/docs/integration.md b/docs/integration.md index 9a1fefee..b166d35a 100644 --- a/docs/integration.md +++ b/docs/integration.md @@ -94,7 +94,7 @@ For example, if you were to call a web service using `m.request`, you would not On the other hand, if you were to call a web service using jQuery, then you would be responsible for adding a `m.startComputation` call before the jQuery ajax call, and for adding a `m.endComputation` call at the end of the completion callback, in addition to the calls within the `change` event handler. Refer to the [`auto-redrawing`](auto-redrawing.md) guide for an example. -One important note about the `config` method is that you should avoid calling `m.redraw`, `m.startComputation` and `m.endComputation` in the `config` function's execution thread. (An execution thread is basically any amount of code that runs before other asynchronous threads start to run) +One important note about the `config` method is that you should avoid calling `m.redraw`, `m.startComputation` and `m.endComputation` in the `config` function's execution thread. (An execution thread is basically any amount of code that runs before other asynchronous threads start to run.) While Mithril technically does support this use case, relying on multiple redraw passes degrades performance and makes it possible to code yourself into an infinite execution loop situation, which is extremely difficult to debug. diff --git a/docs/mithril.deferred.md b/docs/mithril.deferred.md index e4b19d9c..baed49b4 100644 --- a/docs/mithril.deferred.md +++ b/docs/mithril.deferred.md @@ -224,4 +224,4 @@ where: - \ No newline at end of file + diff --git a/docs/mithril.md b/docs/mithril.md index 398397eb..f5b68bae 100644 --- a/docs/mithril.md +++ b/docs/mithril.md @@ -38,7 +38,7 @@ m("[contenteditable]"); //yields
m("a#google.external[href='http://google.com']", "Google"); //yields Google ``` -Each `m()` call creates a virtual DOM element, that is, a javascript object that represents a DOM element, and which is eventually converted into one. +Each `m()` call creates a virtual DOM element, that is, a Javascript object that represents a DOM element, and which is eventually converted into one. You can, of course, nest virtual elements: @@ -110,7 +110,7 @@ As you can see, flow control is done with vanilla Javascript. This allows the de --- -Note that you can use both javascript property names and HTML attribute names to set values in the `attributes` argument, but you should pass a value of appropriate type. If an attribute has the same name in Javascript and in HTML, then Mithril assumes you're setting the Javascript property. +Note that you can use both Javascript property names and HTML attribute names to set values in the `attributes` argument, but you should pass a value of appropriate type. If an attribute has the same name in Javascript and in HTML, then Mithril assumes you're setting the Javascript property. ```javascript m("div", {class: "widget"}); //yields
@@ -351,5 +351,5 @@ where: - **returns** VirtualElement - The returned VirtualElement is a javascript data structure that represents the DOM element to be rendered by [`m.render`](mithril.render) + The returned VirtualElement is a Javascript data structure that represents the DOM element to be rendered by [`m.render`](mithril.render) diff --git a/docs/mithril.module.md b/docs/mithril.module.md index 64b5dec7..a703d69c 100644 --- a/docs/mithril.module.md +++ b/docs/mithril.module.md @@ -157,9 +157,9 @@ where: Note that controllers can manually instantiate child controllers (since they are simply Javascript constructors), and likewise, views can instantiate child views and manually pass the child controller instances down the the child view constructors. - This "turtles all the way down" approach is the heart of Mithril's component system. + This "[turtles all the way down](https://en.wikipedia.org/wiki/Turtles_all_the_way_down)" approach is the heart of Mithril's component system. - Components are nothing more than decoupled classes that can be dynamically brought together as required. This permits the swapping of implementations at a routing level (for example, if implementing widgetized versions of existing components) and class dependency hierarchies can be structurally organized to provide uniform interfaces (for unit tests, for example). + Components are nothing more than decoupled classes that can be dynamically brought together as required. This permits the swapping of implementations at a routing level (for example, if implementing widgetized versions of existing components), and class dependency hierarchies can be structurally organized to provide uniform interfaces (for unit tests, for example). diff --git a/docs/mithril.request.md b/docs/mithril.request.md index 1428e1c2..603e6bc8 100644 --- a/docs/mithril.request.md +++ b/docs/mithril.request.md @@ -53,7 +53,7 @@ m.request({method: "GET", url: "/user"}).then(users).then(doSomething) While both basic assignment syntax and thennable syntax can be used to the same effect, typically it's recommended that you use the assignment syntax whenever possible, as it's easier to read. -The thennable mechanism is intended to be used in 3 ways: +The thennable mechanism is intended to be used in three ways: - in the model layer: to process web service data in transformative ways (e.g. filtering a list based on a parameter that the web service doesn't support) - in the controller layer: to bind redirection code upon a condition @@ -136,7 +136,7 @@ As you saw, you can chain operations that act on the response data. Typically th - in the controller, to redirect after a model service resolves. - in the controller, to bind error messages -In the example below, we take advantage of queuing to debug the ajax response data prior to doing further processing on the user list +In the example below, we take advantage of queuing to debug the AJAX response data prior to doing further processing on the user list ```javascript var users = m.request({method: "GET", url: "/user"}) @@ -155,7 +155,7 @@ var users = m.request({method: "GET", url: "/user"}) ### Casting the Response Data to a Class -It's possible to auto-cast a JSON response to a class. This is useful when we want to control access to certain properties in an object, as opposed to exposing all the fields in POJOs (plain old javascript objects) for arbitrary processing. +It's possible to auto-cast a JSON response to a class. This is useful when we want to control access to certain properties in an object, as opposed to exposing all the fields in POJOs (plain old Javascript objects) for arbitrary processing. In the example below, `User.list` returns a list of `User` instances. diff --git a/docs/mithril.route.md b/docs/mithril.route.md index bd70dc0e..5888be53 100644 --- a/docs/mithril.route.md +++ b/docs/mithril.route.md @@ -4,7 +4,7 @@ Routing is a system that allows creating Single-Page-Applications (SPA), i.e. ap It enables seamless navigability while preserving the ability to bookmark each page individually, and the ability to navigate the application via the browser's history mechanism. -This method overloads 4 different units of functionality: +This method overloads four different units of functionality: - `m.route(rootElement, defaultRoute, routes)` - defines the available URLs in an application, and their respective modules @@ -26,7 +26,7 @@ Routing is single-page-application (SPA) friendly, and can be implemented using To define a list of routes, you need to specify a host DOM element, a default route and a key-value map of possible routes and respective [modules](mithril.module.md) to be rendered. -The example below defines 3 routes, to be rendered in ``. `home`, `login` and `dashboard` are modules. We'll see how to define a module in a bit. +The example below defines three routes, to be rendered in ``. `home`, `login` and `dashboard` are modules. We'll see how to define a module in a bit. ```javascript m.route(document.body, "/", { @@ -70,7 +70,7 @@ Above, `dashboard` is a module. It contains a `controller` and a `view` properti In this case, since there's only route, the app redirects to the default route `"/dashboard/johndoe"`. -The string `johndoe` is bound to the `:userID` parameter, which can be retrived programmatically in the controller via `m.route.param("userID")`. +The string `johndoe` is bound to the `:userID` parameter, which can be retrieved programmatically in the controller via `m.route.param("userID")`. The `m.route.mode` defines which part of the URL to use for routing. diff --git a/docs/mithril.trust.md b/docs/mithril.trust.md index 7b869298..a3e53898 100644 --- a/docs/mithril.trust.md +++ b/docs/mithril.trust.md @@ -4,7 +4,7 @@ If you're writing a template for a view, use `m()` instead. This method flags a string as trusted HTML. -Trusted HTML is allowed to render arbitrary, potentially invalid markup, as well as run arbitrary javascript, and therefore the developer is responsible for either: +Trusted HTML is allowed to render arbitrary, potentially invalid markup, as well as run arbitrary Javascript, and therefore the developer is responsible for either: - sanitizing the markup contained in the string, or @@ -16,7 +16,7 @@ For this reason, `m.trust` will not auto-run ` - \ No newline at end of file + diff --git a/docs/mithril.deferred.md b/docs/mithril.deferred.md index baed49b4..e4b19d9c 100644 --- a/docs/mithril.deferred.md +++ b/docs/mithril.deferred.md @@ -224,4 +224,4 @@ where: - + \ No newline at end of file