Skip to content

Commit

Permalink
remove references to "I" or "me" since we're now a team!
Browse files Browse the repository at this point in the history
  • Loading branch information
mbest committed Oct 20, 2012
1 parent 242d3a1 commit 3cceb3c
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 27 deletions.
2 changes: 1 addition & 1 deletion documentation/browser-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Knockout is tested on the following browsers:
* Apple Safari (tested on Windows Safari version 5, Mac OS X Safari version 3.1.2, and iPhone Safari for iOS 4; should work on newer/older versions too)
* Opera 10 for Windows

It's very likely that Knockout also works on older and newer versions of these browsers, but there's only so many combinations I can check regularly! At the time of the last check, Knockout was also found to work on the following browsers (though I don't recheck these for every release):
It's very likely that Knockout also works on older and newer versions of these browsers, but there's only so many combinations we can check regularly! At the time of the last check, Knockout was also found to work on the following browsers (though we don't recheck these for every release):

* Opera Mini
* Google Android OS browser (OS version 2.2)
Expand Down
2 changes: 1 addition & 1 deletion documentation/computedObservables.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ Now, whenever the user enters a new price, the text box immediately updates to s

Example 1 showed how a writeable computed observable can effectively *filter* its incoming data by choosing not to write certain values back to the underlying observables if they don't meet some criteria. It ignored full name values that didn't include a space.

Taking this a step further, you could also toggle an `isValid` flag depending on whether the latest input was satisfactory, and display a message in the UI accordingly. I'll explain in a moment an easier way of doing validation, but first consider the following view model, which demonstrates the mechanism:
Taking this a step further, you could also toggle an `isValid` flag depending on whether the latest input was satisfactory, and display a message in the UI accordingly. There's an easier way of doing validation (explained below), but first consider the following view model, which demonstrates the mechanism:

function MyViewModel() {
this.acceptedNumericValue = ko.observable(123);
Expand Down
6 changes: 3 additions & 3 deletions documentation/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ The quickest and most fun way to get started is by working through the [interact

## Is KO intended to compete with jQuery (or Prototype, etc.) or work with it?

Everyone loves jQuery! It's an outstanding replacement for the clunky, inconsistent DOM API we had to put up with in the past. jQuery is an excellent low-level way to manipulate elements and event handlers in a web page. I certainly still use jQuery for low-level DOM manipulation. KO solves a different problem.
Everyone loves jQuery! It's an outstanding replacement for the clunky, inconsistent DOM API we had to put up with in the past. jQuery is an excellent low-level way to manipulate elements and event handlers in a web page. KO solves a different problem.

As soon as your UI gets nontrivial and has a few overlapping behaviors, things can get tricky and expensive to maintain if you only use jQuery. Consider an example: you're displaying a list of items, stating the number of items in that list, and want to enable an 'Add' button only when there are fewer than 5 items. jQuery doesn't have a concept of an underlying data model, so to get the number of items you have to infer it from the number of TRs in a table or the number of DIVs with a certain CSS class. Maybe the number of items is displayed in some SPAN, and you have to remember to update that SPAN's text when the user adds an item. You also must remember to disable the 'Add' button when the number of TRs is 5. Later, you're asked also to implement a 'Delete' button and you have to figure out which DOM elements to change whenever it's clicked.
As soon as your UI gets nontrivial and has a few overlapping behaviors, things can get tricky and expensive to maintain if you only use jQuery. Consider an example: you're displaying a list of items, stating the number of items in that list, and want to enable an 'Add' button only when there are fewer than 5 items. jQuery doesn't have a concept of an underlying data model, so to get the number of items you have to infer it from the number of TRs in a table or the number of DIVs with a certain CSS class. Maybe the number of items is displayed in some SPAN, and you have to remember to update that SPAN's text when the user adds an item. You also must remember to disable the 'Add' button when the number of TRs is 5. Later, you're asked also to implement a 'Delete' button and you have to figure out which DOM elements to change whenever it's clicked.

### How is Knockout different?
It's much easier with KO. It lets you scale up in complexity without fear of introducing inconsistencies. Just represent your items as a JavaScript array, and then use a `foreach` binding to transform this array into a TABLE or set of DIVs. Whenever the array changes, the UI changes to match (you don't have to figure out how to inject new TRs or where to inject them). The rest of the UI stays in sync. For example, you can declaratively bind a SPAN to display the number of items as follows:
Expand All @@ -39,7 +39,7 @@ It's much easier with KO. It lets you scale up in complexity without fear of int
That's it! You don't have to write code to update it; it updates on its own when the `myItems` array changes. Similarly, to make the 'Add' button enable or disable depending on the number of items, just write:

<button data-bind="enable: myItems().count < 5">Add</button>

Later, when you're asked to implement the 'Delete' functionality, you don't have to figure out what bits of the UI it has to interact with; you just make it alter the underlying data model.

To summarise: KO doesn't compete with jQuery or similar low-level DOM APIs. KO provides a complementary, high-level way to link a data model to a UI. KO itself doesn't depend on jQuery, but you can certainly use jQuery at the same time, and indeed that's often useful if you want things like animated transitions.
20 changes: 10 additions & 10 deletions documentation/observableArrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ If you want your observable array **not** to start empty, but to contain some in

// This observable array initially contains three objects
var anotherObservableArray = ko.observableArray([
{ name: "Bungle", type: "Bear" },
{ name: "George", type: "Hippo" },
{ name: "Zippy", type: "Unknown" }
{ name: "Bungle", type: "Bear" },
{ name: "George", type: "Hippo" },
{ name: "Zippy", type: "Unknown" }
]);

## Reading information from an observableArray

Behind the scenes, an `observableArray` is actually an [observable](observables.html) whose value is an array (plus, `observableArray` adds some additional features I'll describe in a moment). So, you can get the underlying JavaScript array by invoking the `observableArray` as a function with no parameters, just like any other observable. Then you can read information from that underlying array. For example,
Behind the scenes, an `observableArray` is actually an [observable](observables.html) whose value is an array (plus, `observableArray` adds some additional features described below). So, you can get the underlying JavaScript array by invoking the `observableArray` as a function with no parameters, just like any other observable. Then you can read information from that underlying array. For example,

alert('The length of the array is ' + myObservableArray().length);
alert('The first element is ' + myObservableArray()[0]);
Expand All @@ -39,7 +39,7 @@ Technically you can use any of the native JavaScript array functions to operate
1. They work on all targeted browsers. (For example, the native JavaScript `indexOf` function doesn't work on IE 8 or earlier, but KO's `indexOf` works everywhere.)
1. For functions that modify the contents of the array, such as `push` and `splice`, KO's methods automatically trigger the dependency tracking mechanism so that all registered listeners are notified of the change, and your UI is automatically updated.
1. The syntax is more convenient. To call KO's `push` method, just write `myObservableArray.push(...)`. This is slightly nicer than calling the underlying array's `push` method by writing `myObservableArray().push(...)`.

The rest of this page describes `observableArray`'s functions for reading and writing array information.

### indexOf
Expand All @@ -52,19 +52,19 @@ The `slice` function is the `observableArray` equivalent of the native JavaScrip

## Manipulating an observableArray

`observableArray` exposes a familiar set of functions for modifying the contents of the array and notifying listeners.
`observableArray` exposes a familiar set of functions for modifying the contents of the array and notifying listeners.

### pop, push, shift, unshift, reverse, sort, splice

All of these functions are equivalent to running the native JavaScript array functions on the underlying array, and then notifying listeners about the change:

* `myObservableArray.push('Some new value')` adds a new item to the end of array
* `myObservableArray.pop()` removes the last value from the array and returns it
* `myObservableArray.pop()` removes the last value from the array and returns it
* `myObservableArray.unshift('Some new value')` inserts a new item at the beginning of the array
* `myObservableArray.shift()` removes the first value from the array and returns it
* `myObservableArray.reverse()` reverses the order of the array
* `myObservableArray.sort()` sorts the array contents.
* By default, it sorts alphabetically (for strings) or numerically (for numbers).
* By default, it sorts alphabetically (for strings) or numerically (for numbers).
* Optionally, you can pass a function to control how the array should be sorted. Your function should accept any two objects from the array and return a negative value if the first argument is smaller, a positive value is the second is smaller, or zero to treat them as equal. For example, to sort an array of 'person' objects by last name, you could write `myObservableArray.sort(function(left, right) { return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1) })`
* `myObservableArray.splice()` removes and returns a given number of elements starting from a given index. For example, `myObservableArray.splice(1, 3)` removes three elements starting from index position 1 (i.e., the 2nd, 3rd, and 4th elements) and returns them as an array.

Expand All @@ -87,7 +87,7 @@ The `destroy` and `destroyAll` functions are mainly intended as a convenience fo
* `myObservableArray.destroy(function(someItem) { return someItem.age < 18 })` finds any objects in the array whose `age` property is less than 18, and gives those objects a special property called `_destroy` with value `true`
* `myObservableArray.destroyAll(['Chad', 132, undefined])` finds any objects in the array that equal `'Chad'`, `123`, or `undefined` and gives them a special property called `_destroy` with value `true`
* `myObservableArray.destroyAll()` gives a special property called `_destroy` with value `true` to all objects in the array
So, what's this `_destroy` thing all about? As I mentioned, it's only really interesting to Rails developers. The convention in Rails is that, when you pass into an action a JSON object graph, the framework can automatically convert it to an ActiveRecord object graph and then save it to your database. It knows which of the objects are already in your database, and issues the correct INSERT or UPDATE statements. To tell the framework to DELETE a record, you just mark it with `_destroy` set to `true`.

So, what's this `_destroy` thing all about? It's only really interesting to Rails developers. The convention in Rails is that, when you pass into an action a JSON object graph, the framework can automatically convert it to an ActiveRecord object graph and then save it to your database. It knows which of the objects are already in your database, and issues the correct INSERT or UPDATE statements. To tell the framework to DELETE a record, you just mark it with `_destroy` set to `true`.

Note that when KO renders a `foreach` binding, it automatically hides any objects marked with `_destroy` equal to `true`. So, you can have some kind of "delete" button that invokes the `destroy(someItem)` method on the array, and this will immediately cause the specified item to vanish from the visible UI. Later, when you submit the JSON object graph to Rails, that item will also be deleted from the database (while the other array items will be inserted or updated as usual).
24 changes: 12 additions & 12 deletions documentation/observables.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Knockout is built around three core features:
1. Declarative bindings
1. Templating

On this page, you'll learn about the first of these three. But before that, let me explain the MVVM pattern and the concept of a *view model*.
On this page, you'll learn about the first of these three. But before that, let's examine the MVVM pattern and the concept of a *view model*.

# MVVM and View Models

Expand All @@ -21,10 +21,10 @@ On this page, you'll learn about the first of these three. But before that, let

Note that this is not the UI itself: it doesn't have any concept of buttons or display styles. It's not the persisted data model either - it holds the unsaved data the user is working with. When using KO, your view models are pure JavaScript objects that hold no knowledge of HTML. Keeping the view model abstract in this way lets it stay simple, so you can manage more sophisticated behaviors without getting lost.

* A *view*: a visible, interactive UI representing the state of the view model. It displays information from the view model, sends commands to the view model (e.g., when the user clicks buttons), and updates whenever the state of the view model changes.
* A *view*: a visible, interactive UI representing the state of the view model. It displays information from the view model, sends commands to the view model (e.g., when the user clicks buttons), and updates whenever the state of the view model changes.

When using KO, your view is simply your HTML document with declarative bindings to link it to the view model. Alternatively, you can use templates that generate HTML using data from your view model.

To create a view model with KO, just declare any JavaScript object. For example,

var myViewModel = {
Expand All @@ -41,9 +41,9 @@ You can then create a very simple *view* of this view model using a declarative
The `data-bind` attribute isn't native to HTML, though it is perfectly OK (it's strictly compliant in HTML 5, and causes no problems with HTML 4 even though a validator will point out that it's an unrecognized attribute). But since the browser doesn't know what it means, you need to activate Knockout to make it take effect.

To activate Knockout, add the following line to a `<script>` block:
ko.applyBindings(myViewModel);

ko.applyBindings(myViewModel);

You can either put the script block at the bottom of your HTML document, or you can put it at the top and wrap the contents in a DOM-ready handler such as [jQuery's `$` function](http://api.jquery.com/jQuery/#jQuery3).

That does it! Now, your view will display as if you'd written the following HTML:
Expand All @@ -68,20 +68,20 @@ For example, rewrite the preceding view model object as follows:
personName: ko.observable('Bob'),
personAge: ko.observable(123)
};

You don't have to change the view at all - the same `data-bind` syntax will keep working. The difference is that it's now capable of detecting changes, and when it does, it will update the view automatically.

## Reading and writing observables

Not all browsers support JavaScript getters and setters (\* cough \* IE \* cough \*), so for compatibility, `ko.observable` objects are actually *functions*.
Not all browsers support JavaScript getters and setters (\* cough \* IE \* cough \*), so for compatibility, `ko.observable` objects are actually *functions*.

* To **read** the observable's current value, just call the observable with no parameters. In this example, `myViewModel.personName()` will return `'Bob'`, and `myViewModel.personAge()` will return `123`.

* To **write** a new value to the observable, call the observable and pass the new value as a parameter. For example, calling `myViewModel.personName('Mary')` will change the name value to `'Mary'`.

* To write values to **multiple observable properties** on a model object, you can use *chaining syntax*. For example, `myViewModel.personName('Mary').personAge(50)` will change the name value to `'Mary'` *and* the age value to `50`.

The whole point of observables is that they can be observed, i.e., other code can say that it wants to be notified of changes. That's what many of KO's built-in bindings do internally. So, when you wrote `data-bind="text: personName"`, the `text` binding registered itself to be notified when `personName` changes (assuming it's an observable value, which it is now).
The whole point of observables is that they can be observed, i.e., other code can say that it wants to be notified of changes. That's what many of KO's built-in bindings do internally. So, when you wrote `data-bind="text: personName"`, the `text` binding registered itself to be notified when `personName` changes (assuming it's an observable value, which it is now).

When you change the name value to `'Mary'` by calling `myViewModel.personName('Mary')`, the `text` binding will automatically update the text contents of the associated DOM element. That's how changes to the view model automatically propagate to the view.

Expand All @@ -92,13 +92,13 @@ When you change the name value to `'Mary'` by calling `myViewModel.personName('M
For advanced users, if you want to register your own subscriptions to be notified of changes to observables, you can call their `subscribe` function. For example,

myViewModel.personName.subscribe(function(newValue) {
alert("The person's new name is " + newValue);
});
alert("The person's new name is " + newValue);
});

The `subscribe` function is how many parts of KO work internally. You can also terminate a subscription if you wish: first capture it as a variable, then you can call its `dispose` function, e.g.:

var subscription = myViewModel.personName.subscribe(function(newValue) { /* do stuff */ });
// ...then later...
subscription.dispose(); // I no longer want notifications

Most of the time you don't need to do this, because the built-in bindings and templating system take care of managing subscriptions.

0 comments on commit 3cceb3c

Please sign in to comment.